/[drupal]/contributions/modules/unitsapi/unitsapi.module
ViewVC logotype

Contents of /contributions/modules/unitsapi/unitsapi.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.7 - (show annotations) (download) (as text)
Fri Feb 27 23:02:28 2009 UTC (8 months, 4 weeks ago) by raspberryman
Branch: MAIN
CVS Tags: DRUPAL-6--1-0-ALPHA1, HEAD
Changes since 1.6: +2 -2 lines
File MIME type: text/x-php
Added new unitsapi_get_units() to the convert function
1 <?php // $Id: unitsapi.module,v 1.6 2009/02/27 22:54:29 raspberryman Exp $
2
3 /**
4 * @file
5 * Provides a variety of measurement unit conversions.
6 */
7
8 /**
9 * Implementation of hook_help().
10 */
11 function unitsapi_help($path, $arg) {
12 switch ($path) {
13 case 'admin/help#unitsapi':
14 $output = '<p>'. t('To use the unitsapi_convert() function, you need the key of the to and from unit. These keys are below.') .'</p>';
15 $output .= _unitsapi_key_table();
16 return $output;
17 }
18 }
19
20 /**
21 * The API call for all unit conversions.
22 *
23 * @param $value
24 * A number containing the value of the measurement.
25 * @param $from
26 * A string containing the name of the measurement to convert from.
27 * @param $to
28 * A string containing the name of the measurement to convert to.
29 * @param $details
30 * A boolean value. TRUE returns an array with details about the conversion. FALSE returns
31 * simply the converted value. Default is FALSE.
32 * @return
33 * A float containing the result of the conversion. FALSE if an error occured.
34 */
35 function unitsapi_convert($value, $from, $to, $details = FALSE) {
36
37 $units = unitsapi_get_units();
38
39 // Only accept numeric values.
40 if (!is_numeric($value)) {
41 drupal_set_message(t('Unit conversion value must be numeric.'), 'error');
42 return FALSE;
43 }
44
45 // Check to see if the unit key was found in the array.
46 if (!isset($units[$from]) || !isset($units[$to])) {
47 drupal_set_message(t('Units API cannot find the specified measurement units.'), 'error');
48 return FALSE;
49 }
50
51 // Only convert with like kinds
52 if ($units[$from]['kind'] != $units[$to]['kind']) {
53 drupal_set_message(t('Units API cannot convert between different kinds of measurement units.'), 'error');
54 return FALSE;
55 }
56
57 // Execute the conversion factors differently based on the kind. For example, temperature needs to be executed differently.
58 switch ($units[$from]['kind']) {
59 case 'temperature':
60 $result = _unitsapi_convert_temperature($value, $units[$to]['factor'][$from]);
61 break;
62 default:
63 $from_si = $units[$from]['factor'];
64 $to_si = $units[$to]['factor'];
65 $from_convert = $value * $from_si;
66 $result = $from_convert / $to_si;
67 }
68
69 // Round to the 6 spaces after the decimal.
70 $result = round($result, 6);
71
72 $return = array();
73 if ($details) {
74 $return['result'] = $result;
75 $return['from'] = $value == 1 ? t($units[$from]['singular']) : t($units[$from]['plural']);
76 $return['to'] = $result == 1 ? t($units[$to]['singular']) : t($units[$to]['plural']);
77 }
78 else {
79 $return = $result;
80 }
81
82 return $return;
83 }
84
85 /**
86 * Fetches the units array, and saved to cache if needed.
87 *
88 * @return
89 * An array of unit data, including conversion factors and labels.
90 */
91 function unitsapi_get_units() {
92 $cache = cache_get('unitsapi_data');
93 if (empty($cache->data) || !is_array($cache->data)) {
94 unitsapi_xml_cache();
95 $cache = cache_get('unitsapi_data');
96 }
97
98 return $cache->data;
99
100 }
101
102 /**
103 * Loads units.xml and saves it in the cache as a serialized array.
104 *
105 * @return
106 * TRUE if the cache was successful. FALSE if an error occured.
107 */
108 function unitsapi_xml_cache() {
109
110 $file = url(drupal_get_path('module', 'unitsapi'), array('absolute' => TRUE)) .'/units.xml';
111
112 // Load the XML file
113 if (!function_exists('simplexml_load_file')) {
114 drupal_set_message(t('SimpleXML not found. PHP 5 is required for Units API.'), 'error');
115 return FALSE;
116 }
117 elseif (empty($file)) {
118 drupal_set_message(t('The specified Units XML file is empty.'), 'error');
119 return FALSE;
120 }
121 elseif (!$xml = simplexml_load_file($file)) {
122 drupal_set_message(t('The Units API XML file could not be loaded by SimpleXML.'), 'error');
123 return FALSE;
124 }
125
126
127 // Loop the XML file. It is often easier to force the type of the SimpleXML object to an array.
128 foreach ((array) $xml as $kind => $units) {
129
130 foreach ($units->unit as $unit) {
131
132 $unitarray = (array) $unit;
133
134 // If this unit has multiple factors, set them in $unitsarray according to their kind
135 if (isset($unit->factors)) {
136 unset($unitarray['factors']);
137 foreach ($unit->factors->factor as $factor) {
138 $factor = (array) $factor;
139
140 switch ($kind) {
141 case 'temperature':
142 $unitarray['factor'][$factor['@attributes']['from']] = $factor[0];
143 break;
144 }
145 }
146 }
147
148 $units_cache[$unitarray['key']] = array(
149 'singular' => $unitarray['singular'],
150 'plural' => $unitarray['plural'],
151 'symbol' => $unitarray['symbol'],
152 'factor' => _unitsapi_factor_set($unitarray['factor']),
153 'kind' => $kind,
154 'source' => $unitarray['source'],
155 );
156
157 }
158 }
159
160 $data = module_invoke_all('unitsapi');
161
162 // Loop through the $data array and make changes to the $units collection
163 if (!empty($data) && is_array($data)) {
164 foreach ($data as $key => $unit) {
165 if (!empty($unit) && is_array($unit) && isset($units_cache[$key])) {
166 foreach ($unit as $parameter => $value) {
167 if (isset($units_cache[$key][$parameter])) {
168 $units_cache[check_plain($key)][check_plain($parameter)] = check_plain($value);
169 }
170 }
171 }
172 }
173 }
174
175 cache_set('unitsapi_data', $units_cache);
176 return TRUE;
177 }
178
179
180 /**
181 * Helper function to format the conversion factor.
182 *
183 * @param $si
184 * A string or array containing the conversion factor equation.
185 * @return
186 * A string or array that contains equations that are formatted for execution.
187 */
188 function _unitsapi_factor_set($si) {
189
190 $si = str_replace(' ', '', $si);
191 $si = str_replace(array('—', '−', '–'), '-', $si);
192
193 return $si;
194 }
195
196 /**
197 * Executes the temperature conversion equation.
198 *
199 * @param $value
200 * A number containing the value of the temperature.
201 * @param $factor
202 * A string containing the conversion equation.
203 * @return
204 * A float containing the result of the conversion. FALSE if an error occured.
205 */
206 function _unitsapi_convert_temperature($value, $factor) {
207
208 // Security note: Execute a variety of checks to make sure the equation is not something mischievous
209 $equation = str_replace(array('t/°C', 't/°F', 'T/K'), $value, $factor);
210 $equation = preg_replace("/[^0-9+\-.*\/()%]/", "", $equation);
211 $equation = preg_replace("/([+-])([0-9]+)(%)/", "*(1\$1.\$2)", $equation);
212 $equation = preg_replace("/([0-9]+)(%)/", ".\$1", $equation);
213
214 if ($equation == "") {
215 $return = FALSE;
216 }
217 else {
218 eval("\$return=". $equation .";");
219 }
220 return $return;
221 }
222
223 /**
224 * Helper function to generate a table of unit keys, symbols, and conversion factors. Used in hook_help()
225 *
226 * @return
227 * A themed table of unit keys, symbols, and conversion factors.
228 */
229 function _unitsapi_key_table() {
230
231 $units = unitsapi_get_units();
232
233 $header = array(
234 t('KEY'),
235 t('UNIT NAME'),
236 t('CONVERSION FACTOR'),
237 );
238
239 if (!empty($units) && is_array($units)) {
240 foreach ($units as $key => $unit) {
241 if ($curr_kind != $unit['kind']) {
242 $curr_kind = $unit['kind'];
243 $row = array(
244 'data' => array(array('data' => '<strong>'. drupal_ucfirst(t($curr_kind)) .'</strong>', 'colspan' => 4)),
245 );
246 $rows[] = $row;
247 }
248
249 if ($curr_kind == 'temperature') {
250 $output_factor = '';
251
252 foreach ($unit['factor'] as $factor_key => $factor) {
253 $output_factor .= t('from @factor-key: <a href="@source-url">@factor</a>', array('@factor-key' => $factor_key, '@source-url' => url($unit['source']), '@factor' => $factor)) .'<br />';
254 }
255
256 $row = array(
257 check_plain($key),
258 t('@singular (@symbol)', array('@singular' => $unit['singular'], '@symbol' => $unit['symbol'])),
259 $output_factor,
260 );
261 }
262 else {
263 $row = array(
264 check_plain($key),
265 t('@singular (@symbol)', array('@singular' => $unit['singular'], '@symbol' => $unit['symbol'])),
266 t('<a href="@source-url">@factor</a>', array('@source-url' => url($unit['source']), '@factor' => $unit['factor'])),
267 );
268 }
269
270 $rows[] = $row;
271
272 }
273 }
274 return theme('table', $header, $rows);
275 }

  ViewVC Help
Powered by ViewVC 1.1.2