Mercurial > defr > drupal > views_calc
comparison views_calc.module @ 2:b0a976e17cc7
Views Calc: Version de dev du 14/06/2009
author | Franck Deroche <franck@defr.org> |
---|---|
date | Fri, 07 Aug 2009 15:17:08 +0200 |
parents | 0651c02e6ed7 |
children |
comparison
equal
deleted
inserted
replaced
0:0651c02e6ed7 | 2:b0a976e17cc7 |
---|---|
1 <?php | 1 <?php |
2 | |
3 /** | 2 /** |
4 * @file | 3 * @file |
5 * This module will allow you to add calculated fields to views tables | 4 * This module will allow you to add calculated fields to views tables |
6 * and compute (SUM, COUNT, AVG, etc) columns of numeric data in a views table. | 5 * and compute (SUM, COUNT, AVG, etc) columns of numeric data in a views table. |
7 */ | 6 */ |
112 'access arguments' => array('create views calc'), | 111 'access arguments' => array('create views calc'), |
113 ); | 112 ); |
114 $items['admin/settings/views_calc/settings'] = array( | 113 $items['admin/settings/views_calc/settings'] = array( |
115 'title' => t('Settings'), | 114 'title' => t('Settings'), |
116 'type' => MENU_LOCAL_TASK, | 115 'type' => MENU_LOCAL_TASK, |
117 'weight' => 10, | 116 'weight' => 6, |
118 'priority' => 1, | 117 'priority' => 1, |
119 'page callback' => 'drupal_get_form', | 118 'page callback' => 'drupal_get_form', |
120 'page arguments' => array('views_calc_settings_form'), | 119 'page arguments' => array('views_calc_settings_form'), |
121 'access arguments' => array('administer views calc'), | 120 'access arguments' => array('administer views calc'), |
122 ); | 121 ); |
122 $items['admin/settings/views_calc/export'] = array( | |
123 'title' => 'Export fields', | |
124 'page callback' => 'drupal_get_form', | |
125 'page arguments' => array('views_calc_export_form'), | |
126 'access arguments' => array('create views calc'), | |
127 'type' => MENU_LOCAL_TASK, | |
128 'weight' => 7, | |
129 ); | |
130 $items['admin/settings/views_calc/import'] = array( | |
131 'title' => 'Import fields', | |
132 'page callback' => 'drupal_get_form', | |
133 'page arguments' => array('views_calc_import_form'), | |
134 'access arguments' => array('create views calc'), | |
135 'type' => MENU_LOCAL_TASK, | |
136 'weight' => 8, | |
137 ); | |
138 | |
123 return $items; | 139 return $items; |
124 } | 140 } |
125 | 141 |
126 /** | 142 /** |
127 * Implementation of hook_settings() | 143 * Implementation of hook_settings() |
150 /** | 166 /** |
151 * Views Calc Fields tab on views list. | 167 * Views Calc Fields tab on views list. |
152 */ | 168 */ |
153 function views_calc_fields_form() { | 169 function views_calc_fields_form() { |
154 $i = 0; | 170 $i = 0; |
155 $substitutions = _views_calc_substitutions(); | 171 $substitutions = array(); |
156 $reverse = array_flip($substitutions); | 172 $help = t('<p>The specific fields that are available in any view depend on the base table used for that view.</p>'); |
173 require_once(drupal_get_path('module', 'views') .'/includes/admin.inc'); | |
174 $base_tables = views_fetch_base_tables(); | |
175 foreach ($base_tables as $base => $data) { | |
176 $base_subs = _views_calc_substitutions($base); | |
177 $substitutions += $base_subs; | |
178 $fieldset = array( | |
179 '#title' => t('Base table: !name', array('!name' => t($data['title']))), | |
180 '#value' => theme('item_list', $base_subs), | |
181 '#collapsible' => TRUE, | |
182 '#collapsed' => TRUE, | |
183 ); | |
184 $help .= theme('fieldset', $fieldset); | |
185 } | |
157 | 186 |
158 // display current views calcs fields | 187 // display current views calcs fields |
159 $fields = _views_calc_fields(); | 188 $fields = _views_calc_fields(); |
160 while ($field = db_fetch_array($fields)) { | 189 while ($field = db_fetch_array($fields)) { |
161 $form[] = views_calc_field_form_item($i, $field, $substitutions); | 190 $form[] = views_calc_field_form_item($i, $field, $substitutions); |
165 for ($x = $i + 1; $x < $i + 2; $x++) { | 194 for ($x = $i + 1; $x < $i + 2; $x++) { |
166 $field = array(); | 195 $field = array(); |
167 $form[] = views_calc_field_form_item($i, $field, $substitutions); | 196 $form[] = views_calc_field_form_item($i, $field, $substitutions); |
168 } | 197 } |
169 $form['#prefix'] = '<div class="views-calc-field-settings">'; | 198 $form['#prefix'] = '<div class="views-calc-field-settings">'; |
170 $form['#suffix'] = '</div><div class="views-calc-field-names"><strong>Field Substitutions</strong><div class="form-item">'. theme('item_list', _views_calc_substitutions()) .'</div></div>'; | 199 $form['#suffix'] = '</div><div class="views-calc-field-names"><strong>Field Substitutions</strong><div class="form-item">'. $help .'</div></div>'; |
171 $form['submit'] = array( | 200 $form['submit'] = array( |
172 '#type' => 'submit', | 201 '#type' => 'submit', |
173 '#value' => t('Save'), | 202 '#value' => t('Save'), |
174 ); | 203 ); |
175 return $form; | 204 return $form; |
179 * A form element for an individual calculated field. | 208 * A form element for an individual calculated field. |
180 */ | 209 */ |
181 function views_calc_field_form_item($i, $field, $substitutions) { | 210 function views_calc_field_form_item($i, $field, $substitutions) { |
182 if (empty($field)) { | 211 if (empty($field)) { |
183 $field = array('cid' => 0, 'label' => '', 'tablelist' => '', 'calc' => '', 'format' => '', 'custom' => ''); | 212 $field = array('cid' => 0, 'label' => '', 'tablelist' => '', 'calc' => '', 'format' => '', 'custom' => ''); |
213 } | |
214 require_once(drupal_get_path('module', 'views') .'/includes/admin.inc'); | |
215 $options = array(); | |
216 $base_tables = views_fetch_base_tables(); | |
217 foreach ($base_tables as $base => $data) { | |
218 $options[$base] = t($data['title']); | |
184 } | 219 } |
185 $form['group'][$i] = array( | 220 $form['group'][$i] = array( |
186 '#type' => 'fieldset', | 221 '#type' => 'fieldset', |
187 '#tree' => TRUE, | 222 '#tree' => TRUE, |
188 '#title' => t('Field: ') . !empty($field['label']) ? $field['label'] : t('New'), | 223 '#title' => t('Field: ') . !empty($field['label']) ? $field['label'] : t('New'), |
195 ); | 230 ); |
196 $form['group'][$i]['tablelist'] = array( | 231 $form['group'][$i]['tablelist'] = array( |
197 '#type' => 'hidden', | 232 '#type' => 'hidden', |
198 '#value' => $field['tablelist'], | 233 '#value' => $field['tablelist'], |
199 ); | 234 ); |
235 $form['group'][$i]['base'] = array( | |
236 '#type' => 'select', | |
237 '#title' => t('Base table'), | |
238 '#options' => $options, | |
239 '#default_value' => !empty($field['base']) && array_key_exists($field['base'], $options) ? $field['base'] : 'node', | |
240 '#description' => t('The base table for this field.'), | |
241 ); | |
200 $form['group'][$i]['label'] = array( | 242 $form['group'][$i]['label'] = array( |
201 '#type' => 'textfield', | 243 '#type' => 'textfield', |
202 '#title' => t('Label'), | 244 '#title' => t('Label'), |
203 '#field_prefix' => 'ViewsCalc: ', | 245 '#field_prefix' => 'ViewsCalc: ', |
204 '#default_value' => str_replace('ViewsCalc: ', '', $field['label']), | 246 '#default_value' => str_replace('ViewsCalc: ', '', $field['label']), |
206 ); | 248 ); |
207 $form['group'][$i]['calc'] = array( | 249 $form['group'][$i]['calc'] = array( |
208 '#type' => 'textarea', | 250 '#type' => 'textarea', |
209 '#title' => t('Calculation'), | 251 '#title' => t('Calculation'), |
210 '#default_value' => strtr($field['calc'], $substitutions), | 252 '#default_value' => strtr($field['calc'], $substitutions), |
211 '#description' => t('<p>The query operation to be performed, using numbers, field substitutions, and '. implode(' ', _views_calc_operators()) .'.</p>'), | 253 '#description' => t("<p>The query operation to be performed, using numbers, field substitutions, and ". implode(' ', _views_calc_operators()) .". Leave spaces between parentheses and field names, i.e. 'CONCAT( %field1, ' ', %field2 )'. <strong>". t('Note that all fields must be from the base table selected above! You cannot combine fields from different base tables.') ."</strong></p>"), |
212 ); | 254 ); |
213 $form['group'][$i]['format'] = array( | 255 $form['group'][$i]['format'] = array( |
214 '#type' => 'select', | 256 '#type' => 'select', |
215 '#title' => t('Format'), | 257 '#title' => t('Format'), |
216 '#default_value' => $field['format'], | 258 '#default_value' => $field['format'], |
233 $form_values = $form_state['values']; | 275 $form_values = $form_state['values']; |
234 $edit = $form_values; | 276 $edit = $form_values; |
235 foreach ($edit as $delta => $item) { | 277 foreach ($edit as $delta => $item) { |
236 if ($item['calc'] == '' || !is_numeric($delta)) { | 278 if ($item['calc'] == '' || !is_numeric($delta)) { |
237 // remove blank fields, don't save them | 279 // remove blank fields, don't save them |
238 unset($form_values[$delta]); | 280 continue; |
239 } else { | 281 } |
282 else { | |
240 // Remove all valid values from calc, if anything is left over, it is invalid. | 283 // Remove all valid values from calc, if anything is left over, it is invalid. |
241 | 284 |
242 // First, remove all field names. | 285 // First, remove all field names. |
243 $repl = array(); | 286 $repl = array(); |
244 $patterns = array(); | 287 $patterns = array(); |
245 foreach (_views_calc_substitutions() as $key => $value) { | 288 $base = $item['base']; |
289 foreach (_views_calc_substitutions($base) as $key => $value) { | |
246 $key = trim($value); | 290 $key = trim($value); |
247 $count = strlen($value); | 291 $count = strlen($value); |
248 $replace = preg_quote($value); | 292 $replace = preg_quote($value); |
249 $patterns[] = "`(^|[^\\\\\\\\])". $replace ."`"; | 293 $patterns[] = "`(^|[^\\\\\\\\])". $replace ."`"; |
250 $repl[] = '${1}'; | 294 $repl[] = '${1}'; |
251 } | 295 } |
252 $remaining = trim(preg_replace($patterns, $repl, $item['calc'])); | 296 $remaining = trim(preg_replace($patterns, $repl, $item['calc'])); |
297 | |
253 // Next, remove functions and numbers. | 298 // Next, remove functions and numbers. |
254 $repl = array(); | 299 $repl = array(); |
255 $patterns = array(); | 300 $patterns = array(); |
256 foreach (_views_calc_replacements() as $value) { | 301 foreach (_views_calc_replacements() as $value) { |
257 $patterns[] = "`(^|[^\\\\\\\\])". preg_quote(trim($value)) ."`"; | 302 $patterns[] = "`(^|[^\\\\\\\\])". preg_quote(trim($value)) ."`"; |
267 | 312 |
268 /** | 313 /** |
269 * Save the views calc field settings | 314 * Save the views calc field settings |
270 */ | 315 */ |
271 function views_calc_fields_form_submit($form, &$form_state) { | 316 function views_calc_fields_form_submit($form, &$form_state) { |
272 $form_values = $form_state['values']; | 317 $edit = $form_state['values']; |
273 $edit = $form_values; | 318 $form_values = array(); |
274 foreach ($edit as $delta => $value) { | 319 foreach ($edit as $delta => $value) { |
275 if ($value['calc'] == '' || !is_numeric($delta)) { | 320 // If this is some form item we don't care about, skip it. |
321 if (!is_array($value) || !is_numeric($delta)) { | |
322 continue; | |
323 } | |
324 $value['calc'] = trim($value['calc']); | |
325 if (empty($value['calc'])) { | |
276 // remove blank fields, don't save them | 326 // remove blank fields, don't save them |
277 unset($form_values[$delta]); | 327 if (!empty($value['cid'])) { |
328 db_query("DELETE FROM {views_calc_fields} WHERE cid=%d", $value['cid']); | |
329 } | |
278 | 330 |
279 } | 331 } |
280 else { | 332 else { |
281 $tables = array(); | 333 $tables = array(); |
282 $form_values[$delta]['label'] = $value['label']; | 334 $form_values[$delta]['label'] = $value['label']; |
283 $form_values[$delta]['format'] = $value['format']; | 335 $form_values[$delta]['format'] = $value['format']; |
284 $form_values[$delta]['custom'] = $value['custom']; | 336 $form_values[$delta]['custom'] = $value['custom']; |
285 $form_values[$delta]['calc'] = $value['calc']; | 337 $form_values[$delta]['calc'] = $value['calc']; |
338 $form_values[$delta]['base'] = $value['base']; | |
286 | 339 |
287 // Substitute field names back into the calculation. | 340 // Substitute field names back into the calculation. |
288 $matches = array(); | 341 $matches = array(); |
289 foreach (_views_calc_substitutions() as $key => $value) { | 342 $base = $value['base']; |
343 foreach (_views_calc_substitutions($base) as $key => $value) { | |
290 $label_patterns[] = "`(^|[^\\\\\\\\])". preg_quote($value) ."`"; | 344 $label_patterns[] = "`(^|[^\\\\\\\\])". preg_quote($value) ."`"; |
291 $value_patterns[] = "`(^|[^\\\\\\\\])". preg_quote($key) ."`"; | 345 $value_patterns[] = "`(^|[^\\\\\\\\])". preg_quote($key) ."`"; |
292 $repl[] = '${1}'. $key; | 346 $repl[] = '${1}'. $key; |
293 } | 347 } |
294 $form_values[$delta]['calc'] = preg_replace($label_patterns, $repl, $form_values[$delta]['calc']); | 348 $form_values[$delta]['calc'] = preg_replace($label_patterns, $repl, $form_values[$delta]['calc']); |
296 // Extract the fields and table names from the calculation. | 350 // Extract the fields and table names from the calculation. |
297 $tables = array(); | 351 $tables = array(); |
298 $fields = array(); | 352 $fields = array(); |
299 foreach ($value_patterns as $pattern) { | 353 foreach ($value_patterns as $pattern) { |
300 if (preg_match($pattern, $form_values[$delta]['calc'], $results)) { | 354 if (preg_match($pattern, $form_values[$delta]['calc'], $results)) { |
301 $fields[] = trim($results[0]); | 355 $fields[trim($results[0])] = trim($results[0]); |
302 $tmp = explode('.', trim($results[0])); | 356 $tmp = explode('.', trim($results[0])); |
303 if (trim($tmp[0])) { | 357 if (trim($tmp[0])) { |
304 $tables[trim($tmp[0])] = trim($tmp[0]); | 358 $tables[trim($tmp[0])] = trim($tmp[0]); |
305 } | 359 } |
306 } | 360 } |
307 } | 361 } |
308 $form_values[$delta]['tablelist'] = implode(',', $tables); | 362 $form_values[$delta]['tablelist'] = implode(',', $tables); |
309 $form_values[$delta]['fieldlist'] = implode(',', $fields); | 363 $form_values[$delta]['fieldlist'] = implode(',', $fields); |
310 } | 364 } |
311 } | 365 } |
312 foreach ($form_values as $delta => $value) { | 366 |
313 if ($value['cid'] == 0) { | 367 foreach ((array) $form_values as $delta => $value) { |
368 if (empty($value['cid'])) { | |
314 drupal_write_record('views_calc_fields', $value); | 369 drupal_write_record('views_calc_fields', $value); |
315 } | 370 } |
316 else { | 371 else { |
317 drupal_write_record('views_calc_fields', $value, array('cid')); | 372 drupal_write_record('views_calc_fields', $value, array('cid')); |
318 } | 373 } |
364 function _views_calc_replacements() { | 419 function _views_calc_replacements() { |
365 $operators = array_filter(_views_calc_operators(), 'trim'); | 420 $operators = array_filter(_views_calc_operators(), 'trim'); |
366 $numbers = range(0, 9); | 421 $numbers = range(0, 9); |
367 return array_merge($operators, $numbers); | 422 return array_merge($operators, $numbers); |
368 } | 423 } |
424 | |
425 | |
426 /** | |
427 * Field export form. | |
428 */ | |
429 function views_calc_export_form() { | |
430 | |
431 $fields = _views_calc_fields(); | |
432 $string = ''; | |
433 while ($field = db_fetch_array($fields)) { | |
434 $base = $field['base']; | |
435 $substitutions = _views_calc_substitutions($base); | |
436 $field['calc'] = strtr($field['calc'], $substitutions); | |
437 $string .= "\$fields[] = ". var_export((array) $field, TRUE) .";\n"; | |
438 } | |
439 | |
440 $form['#prefix'] = t('This form will export Views Calc custom fields.'); | |
441 $form['macro'] = array( | |
442 '#type' => 'textarea', | |
443 '#rows' => 20, | |
444 '#title' => t('Export data'), | |
445 '#default_value' => $string, | |
446 '#description' => t('This is an export of the custom Views Calc fields. Paste this text into a Views Calc import box to import these fields into another installation. This will only work if the other installation uses the same base tables required by these fields.'), | |
447 ); | |
448 return $form; | |
449 } | |
450 | |
451 /** | |
452 * Field import form. | |
453 */ | |
454 function views_calc_import_form(&$form_state, $type_name = '') { | |
455 $form['#prefix'] = t('This form will import Views Calc custom fields.'); | |
456 $form['macro'] = array( | |
457 '#type' => 'textarea', | |
458 '#rows' => 20, | |
459 '#title' => t('Import data'), | |
460 '#required' => TRUE, | |
461 '#description' => t('Paste the text created by a Views Calc export into this field.'), | |
462 ); | |
463 $form['submit'] = array( | |
464 '#type' => 'submit', | |
465 '#value' => t('Import'), | |
466 ); | |
467 // Read in a file if there is one and set it as the default macro value. | |
468 if (isset($_REQUEST['macro_file']) && $file = file_get_contents($_REQUEST['macro_file'])) { | |
469 $form['macro']['#default_value'] = $file; | |
470 if (isset($_REQUEST['type_name'])) { | |
471 $form['type_name']['#default_value'] = $_REQUEST['type_name']; | |
472 } | |
473 $form['#prefix'] .= '<p class="error">'. t('A file has been pre-loaded for import.') .'</p>'; | |
474 } | |
475 $form['#redirect'] = 'admin/settings/views_calc'; | |
476 return $form; | |
477 } | |
478 | |
479 /** | |
480 * Submit handler for import form. | |
481 */ | |
482 function views_calc_import_form_submit($form, &$form_state) { | |
483 $form_values = $form_state['values']; | |
484 $fields = NULL; | |
485 | |
486 // Use '@' to suppress errors about undefined constants in the macro. | |
487 @eval($form_values['macro']); | |
488 | |
489 if (empty($fields) || !is_array($fields)) { | |
490 return; | |
491 } | |
492 | |
493 foreach ($fields as $delta => $field) { | |
494 // Don't over-write existing fields, create new ones. | |
495 $fields[$delta]['cid'] = NULL; | |
496 } | |
497 | |
498 // Run the values thru drupal_execute() so they are properly validated. | |
499 $form_state = array('values' => $fields); | |
500 drupal_execute('views_calc_fields_form', $form_state); | |
501 | |
502 } |