changeset 3:5635080385bd tip

Merge patch with 1.x-dev
author Franck Deroche <franck@defr.org>
date Fri, 07 Aug 2009 15:20:12 +0200
parents cedf71edacf5 (current diff) b0a976e17cc7 (diff)
children
files views_calc_table.inc
diffstat 6 files changed, 176 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.txt	Thu Aug 06 19:09:42 2009 +0200
+++ b/CHANGELOG.txt	Fri Aug 07 15:20:12 2009 +0200
@@ -1,4 +1,4 @@
-// $Id: CHANGELOG.txt,v 1.15 2009/05/17 11:27:42 karens Exp $
+// $Id: CHANGELOG.txt,v 1.17 2009/06/12 16:38:30 karens Exp $
 
 Version 6.1-dev
 =================
--- a/views_calc.info	Thu Aug 06 19:09:42 2009 +0200
+++ b/views_calc.info	Fri Aug 07 15:20:12 2009 +0200
@@ -5,9 +5,9 @@
 package = Views
 dependencies[] = views
 
-; Information added by drupal.org packaging script on 2009-05-17
-version = "6.x-1.3"
+; Information added by drupal.org packaging script on 2009-06-14
+version = "6.x-1.x-dev"
 core = "6.x"
 project = "views_calc"
-datestamp = "1242559869"
+datestamp = "1244939275"
 
--- a/views_calc.install	Thu Aug 06 19:09:42 2009 +0200
+++ b/views_calc.install	Fri Aug 07 15:20:12 2009 +0200
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_calc.install,v 1.3 2008/09/16 18:03:08 karens Exp $
+// $Id: views_calc.install,v 1.5 2009/06/12 16:38:30 karens Exp $
 /**
  * Implementation of hook_schema().
  */
@@ -10,6 +10,7 @@
       'label' => array('type' => 'varchar', 'length' => '255', 'not null' => TRUE, 'default' => ''),
       'format' => array('type' => 'varchar', 'length' => '255', 'not null' => TRUE, 'default' => ''),
       'custom' => array('type' => 'varchar', 'length' => '255', 'not null' => TRUE, 'default' => ''),
+      'base' => array('type' => 'varchar', 'length' => '255', 'not null' => TRUE, 'default' => ''),
       'tablelist' => array('type' => 'text', 'not null' => TRUE),
       'fieldlist' => array('type' => 'text', 'not null' => TRUE),
       'calc' => array('type' => 'text', 'not null' => TRUE),
@@ -125,20 +126,8 @@
   return $ret;
 }
 
-/**
- * TODO
- * Use these values to create new default views, then delete them.
- *
 function views_calc_update_6000() {
-  $view_calcs = (array) variable_get('views_calc_vid','');
-  foreach ($view_calcs as $view_id) {
-    variable_del('views_calc_'. $view_id .'_col');
-    variable_del('views_calc_'. $view_id .'_col_calc');
-    variable_del('views_calc_'. $view_id .'_row');
-    variable_del('views_calc_'. $view_id .'_row_calc');
-  }
-  variable_del('views_calc_vid');
-  variable_del('views_calc_operators');
-  
-}
- */
+  $ret = array();
+  db_add_field($ret, 'views_calc_fields', 'base', array('type' => 'varchar', 'length' => '255', 'not null' => TRUE, 'default' => 'node'));
+  return $ret;
+}
\ No newline at end of file
--- a/views_calc.module	Thu Aug 06 19:09:42 2009 +0200
+++ b/views_calc.module	Fri Aug 07 15:20:12 2009 +0200
@@ -1,5 +1,4 @@
 <?php
-
 /**
  * @file
  * This module will allow you to add calculated fields to views tables
@@ -114,12 +113,29 @@
   $items['admin/settings/views_calc/settings'] = array(
     'title' => t('Settings'),
     'type' => MENU_LOCAL_TASK,
-    'weight' => 10,
+    'weight' => 6,
     'priority' => 1,
     'page callback' => 'drupal_get_form',
     'page arguments' => array('views_calc_settings_form'),
     'access arguments' => array('administer views calc'),
     );
+  $items['admin/settings/views_calc/export'] = array(
+    'title' => 'Export fields',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('views_calc_export_form'),
+    'access arguments' => array('create views calc'),
+    'type' => MENU_LOCAL_TASK,
+    'weight' => 7,
+  );
+  $items['admin/settings/views_calc/import'] = array(
+    'title' => 'Import fields',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('views_calc_import_form'),
+    'access arguments' => array('create views calc'),
+    'type' => MENU_LOCAL_TASK,
+    'weight' => 8,
+  );
+    
   return $items;
 }
 
@@ -152,8 +168,21 @@
  */
 function views_calc_fields_form() {
   $i = 0;
-  $substitutions = _views_calc_substitutions();
-  $reverse       = array_flip($substitutions);
+  $substitutions = array();
+  $help = t('<p>The specific fields that are available in any view depend on the base table used for that view.</p>');
+  require_once(drupal_get_path('module', 'views') .'/includes/admin.inc');
+  $base_tables = views_fetch_base_tables();
+  foreach ($base_tables as $base => $data) {
+    $base_subs = _views_calc_substitutions($base);
+    $substitutions += $base_subs;
+    $fieldset = array(
+      '#title' => t('Base table: !name', array('!name' => t($data['title']))),
+      '#value' => theme('item_list', $base_subs),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      );
+    $help .= theme('fieldset', $fieldset);
+  }
 
   // display current views calcs fields
   $fields = _views_calc_fields();
@@ -167,7 +196,7 @@
     $form[] = views_calc_field_form_item($i, $field, $substitutions);
   }
   $form['#prefix'] = '<div class="views-calc-field-settings">';
-  $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>';
+  $form['#suffix'] = '</div><div class="views-calc-field-names"><strong>Field Substitutions</strong><div class="form-item">'. $help .'</div></div>';
   $form['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Save'),
@@ -182,6 +211,12 @@
   if (empty($field)) {
     $field = array('cid' => 0, 'label' => '', 'tablelist' => '', 'calc' => '', 'format' => '', 'custom' => '');
   }
+  require_once(drupal_get_path('module', 'views') .'/includes/admin.inc');
+  $options = array();
+  $base_tables = views_fetch_base_tables();
+  foreach ($base_tables as $base => $data) {
+    $options[$base] = t($data['title']);
+  }
   $form['group'][$i] = array(
     '#type' => 'fieldset',
     '#tree' => TRUE,
@@ -197,6 +232,13 @@
     '#type' => 'hidden',
     '#value' => $field['tablelist'],
     );
+  $form['group'][$i]['base'] = array(
+    '#type' => 'select',
+    '#title' => t('Base table'),
+    '#options' => $options,
+    '#default_value' => !empty($field['base']) && array_key_exists($field['base'], $options) ? $field['base'] : 'node',
+    '#description' => t('The base table for this field.'),
+    );    
   $form['group'][$i]['label'] = array(
     '#type' => 'textfield',
     '#title' => t('Label'),
@@ -208,7 +250,7 @@
     '#type' => 'textarea',
     '#title' => t('Calculation'),
     '#default_value' => strtr($field['calc'], $substitutions),
-    '#description' => t('<p>The query operation to be performed, using numbers, field substitutions, and '. implode(' ', _views_calc_operators()) .'.</p>'),
+    '#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>"),
     );
   $form['group'][$i]['format'] = array(
     '#type' => 'select',
@@ -235,14 +277,16 @@
   foreach ($edit as $delta => $item) {
     if ($item['calc'] == '' || !is_numeric($delta)) {
       // remove blank fields, don't save them
-      unset($form_values[$delta]);
-    } else {
+      continue;
+    } 
+    else {
       // Remove all valid values from calc, if anything is left over, it is invalid.
 
       // First, remove all field names.
       $repl = array();
       $patterns = array();
-      foreach (_views_calc_substitutions() as $key => $value) {
+      $base = $item['base'];
+      foreach (_views_calc_substitutions($base) as $key => $value) {
         $key = trim($value);
         $count = strlen($value);
         $replace = preg_quote($value);
@@ -250,6 +294,7 @@
         $repl[] = '${1}';
       }
       $remaining = trim(preg_replace($patterns, $repl, $item['calc']));
+      
       // Next, remove functions and numbers.
       $repl = array();
       $patterns = array();
@@ -269,12 +314,19 @@
  *  Save the views calc field settings
  */
 function views_calc_fields_form_submit($form, &$form_state) {
-  $form_values = $form_state['values'];
-  $edit = $form_values;
+  $edit = $form_state['values'];
+  $form_values = array();
   foreach ($edit as $delta => $value) {
-    if ($value['calc'] == '' || !is_numeric($delta)) {
+    // If this is some form item we don't care about, skip it.
+    if (!is_array($value) || !is_numeric($delta)) {
+      continue;
+    }
+    $value['calc'] = trim($value['calc']);
+    if (empty($value['calc'])) {
       // remove blank fields, don't save them
-      unset($form_values[$delta]);
+      if (!empty($value['cid'])) {
+        db_query("DELETE FROM {views_calc_fields} WHERE cid=%d", $value['cid']);
+      }
 
     } 
     else {
@@ -283,10 +335,12 @@
       $form_values[$delta]['format'] = $value['format'];
       $form_values[$delta]['custom'] = $value['custom'];
       $form_values[$delta]['calc']   = $value['calc'];
+      $form_values[$delta]['base']   = $value['base'];
 
       // Substitute field names back into the calculation.
       $matches = array();
-      foreach (_views_calc_substitutions() as $key => $value) {
+      $base = $value['base'];
+      foreach (_views_calc_substitutions($base) as $key => $value) {
         $label_patterns[] = "`(^|[^\\\\\\\\])". preg_quote($value) ."`";
         $value_patterns[] = "`(^|[^\\\\\\\\])". preg_quote($key) ."`";
         $repl[] = '${1}'. $key;
@@ -298,7 +352,7 @@
       $fields = array();
       foreach ($value_patterns as $pattern) {
         if (preg_match($pattern, $form_values[$delta]['calc'], $results)) {
-          $fields[] = trim($results[0]);
+          $fields[trim($results[0])] = trim($results[0]);
           $tmp = explode('.', trim($results[0]));
           if (trim($tmp[0])) {
             $tables[trim($tmp[0])] = trim($tmp[0]);
@@ -309,8 +363,9 @@
       $form_values[$delta]['fieldlist'] = implode(',', $fields);
     }
   }
-  foreach ($form_values as $delta => $value) {
-    if ($value['cid'] == 0) {
+  
+  foreach ((array) $form_values as $delta => $value) {
+    if (empty($value['cid'])) {
       drupal_write_record('views_calc_fields', $value);
     } 
     else {
@@ -365,4 +420,83 @@
   $operators     = array_filter(_views_calc_operators(), 'trim');
   $numbers       = range(0, 9);
   return array_merge($operators, $numbers);
+}
+
+
+/**
+ * Field export form.
+ */
+function views_calc_export_form() {
+  
+  $fields = _views_calc_fields();
+  $string = '';
+  while ($field = db_fetch_array($fields)) {
+    $base = $field['base'];
+    $substitutions = _views_calc_substitutions($base);
+    $field['calc'] = strtr($field['calc'], $substitutions);
+    $string .= "\$fields[] = ". var_export((array) $field, TRUE) .";\n";
+  }
+    
+  $form['#prefix'] = t('This form will export Views Calc custom fields.');
+  $form['macro'] = array(
+    '#type' => 'textarea',
+    '#rows' => 20,
+    '#title' => t('Export data'),
+    '#default_value' => $string,
+    '#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.'),
+  );
+  return $form;
+}
+
+/**
+ * Field import form.
+ */
+function views_calc_import_form(&$form_state, $type_name = '') {
+  $form['#prefix'] = t('This form will import Views Calc custom fields.');
+  $form['macro'] = array(
+    '#type' => 'textarea',
+    '#rows' => 20,
+    '#title' => t('Import data'),
+    '#required' => TRUE,
+    '#description' => t('Paste the text created by a Views Calc export into this field.'),
+  );
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Import'),
+  );
+  // Read in a file if there is one and set it as the default macro value.
+  if (isset($_REQUEST['macro_file']) && $file = file_get_contents($_REQUEST['macro_file'])) {
+    $form['macro']['#default_value'] = $file;
+    if (isset($_REQUEST['type_name'])) {
+      $form['type_name']['#default_value'] = $_REQUEST['type_name'];
+    }
+    $form['#prefix'] .= '<p class="error">'. t('A file has been pre-loaded for import.') .'</p>';
+  }
+  $form['#redirect'] = 'admin/settings/views_calc';
+  return $form;
+}
+
+/**
+ *  Submit handler for import form.
+ */
+function views_calc_import_form_submit($form, &$form_state) {
+  $form_values = $form_state['values'];
+  $fields = NULL;
+  
+  // Use '@' to suppress errors about undefined constants in the macro.
+  @eval($form_values['macro']);
+  
+  if (empty($fields) || !is_array($fields)) {
+    return;
+  }
+  
+  foreach ($fields as $delta => $field) {
+    // Don't over-write existing fields, create new ones.
+    $fields[$delta]['cid'] = NULL;
+  }
+  
+  // Run the values thru drupal_execute() so they are properly validated.
+  $form_state = array('values' => $fields);
+  drupal_execute('views_calc_fields_form', $form_state);
+
 }
\ No newline at end of file
--- a/views_calc.views.inc	Thu Aug 06 19:09:42 2009 +0200
+++ b/views_calc.views.inc	Fri Aug 07 15:20:12 2009 +0200
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_calc.views.inc,v 1.7 2009/05/17 11:11:17 karens Exp $
+// $Id: views_calc.views.inc,v 1.9 2009/06/12 16:38:30 karens Exp $
 /**
  * Implementation of hook_views_handlers().
  */
@@ -25,7 +25,7 @@
   $data = array();
   $results = _views_calc_fields();
   while($field = db_fetch_array($results)) {
-    $data['node']['cid'. $field['cid']] = array(
+    $data[$field['base']]['cid'. $field['cid']] = array(
       'group' => t('Views Calc'),
       'title' => t($field['label']),
       'help' =>  $field['calc'],
--- a/views_calc_table.inc	Thu Aug 06 19:09:42 2009 +0200
+++ b/views_calc_table.inc	Fri Aug 07 15:20:12 2009 +0200
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_calc_table.inc,v 1.15 2009/04/22 02:21:41 karens Exp $
+// $Id: views_calc_table.inc,v 1.17 2009/06/13 17:05:38 karens Exp $
 /**
  * @file
  * Copied from the table style plugin.
@@ -78,7 +78,7 @@
    */
   function pre_render($results) {
     parent::pre_render($results);
-       
+    
     // If there are no calc fields, do nothing.
     if (!$calc_fields = $this->get_calc_fields()) {
       return;
@@ -87,7 +87,6 @@
     if (!empty($this->view->views_calc_calculation)) {
       return;
     }
-   
     $this->view->totals = array();
     $this->view->sub_totals = array();
       
@@ -114,6 +113,8 @@
   }
 
   function do_calculation($calc, $sub_total, $nids = array()) {
+    // TODO Looks like we have problems unless we
+    // force a non-page display, need to keep an eye on this.
     if ($summary_view = views_get_view($this->view->name)) {
       $summary_view->set_display($this->view->current_display);
       $summary_view->set_arguments($this->view->args);
@@ -122,7 +123,7 @@
       $summary_view->views_calc_nids = $nids;
       $summary_view->views_calc_sub_total = $sub_total;
       $summary_view->is_cacheable = FALSE;
-      $summary_view->execute();
+      $summary_view->preview();
       return array_shift($summary_view->result);
     }
     return '';
@@ -168,6 +169,10 @@
     foreach ($this->view->field as $field) {
       $query_field = substr($field->field, 0, 3) == 'cid' ? $field->definition['calc'] : $field->table .'.'. $field->field;
       $query_alias = $field->field_alias;
+      // Bail if we have a broken handler.
+      if ($query_alias == 'unknown') {
+        continue;
+      }
       if (in_array($field->field, $fields)) {
         // Calculated fields.
         $this->view->query->add_field(NULL, "$calc($query_field)", $query_alias);
@@ -207,6 +212,10 @@
     foreach ($this->view->field as $field) {
       $query_field = substr($field->field, 0, 3) == 'cid' ? $field->definition['calc'] : $field->table .'.'. $field->field;
       $query_alias = $field->field_alias;
+      // Bail if we have a broken handler.
+      if ($query_alias == 'unknown') {
+        continue;
+      }
       $this->view->query->add_table($field->table, NULL, NULL, $field->table);
       if (!empty($fields) && in_array($field->field, $fields)) {
         // Calculated fields.