[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/date/includes/ -> date_api_argument_handler.inc (source)

   1  <?php
   2  // $Id: date_api_argument_handler.inc,v 1.1.2.48 2011/01/03 02:39:15 karens Exp $
   3  /**
   4   * Date API argument handler.
   5   */
   6  class date_api_argument_handler extends views_handler_argument_date {
   7    function construct() {
   8      parent::construct();
   9      require_once('./'. drupal_get_path('module', 'date_api') .'/date_api_sql.inc');
  10      $this->date_handler = new date_sql_handler();
  11      $this->date_handler->construct();
  12    }
  13  
  14    /**
  15     * Get granularity and use it to create the formula and a format
  16     * for the results.
  17     */
  18    function init(&$view, $options) {
  19      parent::init($view, $options);
  20      
  21      // Identify the type of display we're using.
  22      $this->display_handler = $view->display_handler->definition['handler'];
  23      
  24      // Add a date handler to the display.
  25      $date_handler = $this->date_handler;
  26      $date_handler->granularity = $this->options['granularity'];
  27      $this->format = $date_handler->views_formats($date_handler->granularity, 'display');
  28      $this->sql_format = $date_handler->views_formats($date_handler->granularity, 'sql');
  29      
  30      if (empty($this->view->date_info)) $this->view->date_info = new stdClass();
  31  
  32      // Set the view range, do this only if not already set in case there are multiple date arguments.
  33      if (empty($this->view->date_info->min_allowed_year)) {
  34        $range = date_range_years($this->options['year_range']);
  35        $this->view->date_info->min_allowed_year = !empty($range) && is_array($range) ? $range[0] : variable_get('min_allowed_year', 100);
  36        $this->view->date_info->max_allowed_year = !empty($range) && is_array($range) ? $range[1] : variable_get('max_allowed_year', 4000);
  37      }
  38      if (empty($this->view->date_info->date_fields)) {
  39        $this->view->date_info->date_fields = array();
  40      }
  41      $this->view->date_info->date_fields = array_merge($this->view->date_info->date_fields, $this->options['date_fields']);
  42    }
  43  
  44    /**
  45     * Default value for the date_fields option.
  46     */
  47    function option_definition() {
  48      $options = parent::option_definition();
  49      $options['date_fields'] = array('default' => array());
  50      $options['year_range'] = array('default' => '-3:+3');
  51      $options['date_method'] = array('default' => 'OR');
  52      $options['granularity'] = array('default' => 'month');
  53  
  54      return $options;
  55    }
  56  
  57    /**
  58     * Add a form element to select date_fields for this argument.
  59     */
  60    function options_form(&$form, &$form_state) {
  61      parent::options_form($form, $form_state);
  62      $options = $this->date_handler->date_parts();
  63      unset($options['second'], $options['minute']);
  64      $options += array('week' => date_t('Week', 'datetime'));
  65      $form['granularity'] = array(
  66        '#title' => t('Granularity'),
  67        '#type' => 'radios',
  68        '#options' => $options,
  69        '#default_value' => $this->options['granularity'],
  70        '#multiple' => TRUE,
  71        '#description' => t("Select the type of date value to be used in defaults, summaries, and navigation. For example, a granularity of 'month' will set the default date to the current month, summarize by month in summary views, and link to the next and previous month when using date navigation."),
  72      );
  73  
  74      $form['year_range'] = array(
  75        '#title' => t('Date year range'),
  76        '#type' => 'textfield',
  77        '#default_value' => $this->options['year_range'],
  78        '#description' => t("Set the allowable minimum and maximum year range for this argument, either a -X:+X offset from the current year, like '-3:+3' or an absolute minimum and maximum year, like '2005:2010'. When the argument is set to a date outside the range, the page will be returned as 'Page not found (404)'."),
  79      );
  80      
  81      $fields = date_api_fields($this->definition['base']);
  82      $options = array();
  83      foreach ($fields['name'] as $name => $field) {
  84        $options[$name] = $field['label'];
  85      }
  86      
  87      // If this argument was added as a CCK field argument and no other date field
  88      // has been chosen, update the default with the right date.
  89      if (empty($this->options['date_fields']) && $this->field != 'date_argument') {
  90        $this->options['date_fields'] = array($this->table .'.'. $this->field);
  91      }
  92      
  93      $form['date_fields'] = array(
  94        '#title' => t('Date field(s)'),
  95        '#type' => 'checkboxes',
  96        '#options' => $options,
  97        '#default_value' => $this->options['date_fields'],
  98        '#multiple' => TRUE,
  99        '#description' => t("Select one or more date fields to filter with this argument. Do not select both the 'From date' and 'To date' for CCK date fields, only one of them is needed."),
 100      );
 101      $form['date_method'] = array(
 102        '#title' => t('Method'),
 103        '#type' => 'radios',
 104        '#options' => array('OR' => t('OR'), 'AND' => t('AND')),
 105        '#default_value' => $this->options['date_method'],
 106        '#description' => t('Method of handling multiple date fields in the same query. Return items that have any matching date field (date = field_1 OR field_2), or only those with matches in all selected date fields (date = field_1 AND field_2).'),
 107        );
 108      
 109    }
 110      
 111    function options_validate($form, &$form_state) {
 112      // It is very important to call the parent function here:
 113      parent::options_validate($form, $form_state);
 114      
 115      if ($form_state['values']['form_id'] == 'views_ui_config_item_form') {
 116        $check_fields = array_filter($form_state['values']['options']['date_fields']);
 117        if (empty($check_fields)) {
 118          form_error($form['date_fields'], t('You must select at least one date field for this argument.'));
 119        }
 120        if (!preg_match('/^(?:\-[0-9]{1,4}|[0-9]{4}):(?:[\+|\-][0-9]{1,4}|[0-9]{4})$/', $form_state['values']['options']['year_range'])) {
 121          form_error($form['year_range'], t('Date year range must be in the format -9:+9, 2005:2010, -9:2010, or 2005:+9'));
 122        }
 123      }
 124    }
 125    
 126    function options_submit($form, &$form_state) {
 127      // It is very important to call the parent function here:
 128      parent::options_submit($form, $form_state);
 129      
 130      if ($form_state['values']['form_id'] == 'views_ui_config_item_form') {
 131        $form_state['values']['options']['date_fields'] = array_filter($form_state['values']['options']['date_fields']);
 132      }
 133    }
 134    
 135    // Update the summary values to show selected granularity.
 136    function admin_summary() {
 137      $fields = date_api_fields($this->definition['base']);
 138      if (!empty($this->options['date_fields'])) {
 139        $output = array();
 140        foreach ($this->options['date_fields'] as $field) {
 141          $output[] = $fields['name'][$field]['label'];
 142        }
 143        return implode('<br />'. $this->options['date_method'] .' ', $output);
 144      }
 145      else {
 146        return parent::admin_summary();
 147      }
 148    }
 149  
 150    /**
 151     * Set the empty argument value to the current date, 
 152     * formatted appropriately for this argument.
 153     */
 154    function get_default_argument($raw = FALSE) {
 155      if (!$raw && $this->options['default_argument_type'] == 'date') {
 156        return date($this->format(), time());
 157      }
 158      else {
 159        return parent::get_default_argument($raw);
 160      }
 161    }
 162      
 163    function format() {
 164      if (!empty($this->options['granularity'])) {
 165        $date_handler = new date_sql_handler();
 166        return $date_handler->views_formats($this->options['granularity']);
 167      }
 168      else {
 169        return !empty($this->options[$this->option_name]) ? $this->options[$this->option_name] : 'Y-m';
 170      }
 171    }
 172      
 173    /**
 174     * Provide a link to the next level of the view from the summary.
 175     */
 176    function summary_name($data) {
 177      $format = $this->date_handler->views_formats($this->options['granularity'], 'display');
 178      $value = $data->{$this->name_alias};
 179      $range = $this->date_handler->arg_range($value);
 180      return date_format_date($range[0], 'custom', $format);
 181    }
 182  
 183    /**
 184     * Provide the argument to use to link from the summary to the next level;
 185     * this will be called once per row of a summary, and used as part of
 186     * $view->get_url().
 187     *
 188     * @param $data
 189     *   The query results for the row.
 190     */
 191    function summary_argument($data) {
 192      $format = $this->date_handler->views_formats($this->options['granularity'], 'sql');
 193      $value = $data->{$this->name_alias};
 194      $range = $this->date_handler->arg_range($value);
 195      return date_format_date($range[0], 'custom', $format);
 196    }
 197    
 198    /**
 199     * Provide a link to the next level of the view from the argument.
 200     */
 201    function title() {
 202      $format = $this->date_handler->views_formats($this->options['granularity'], 'display');
 203      $range = $this->date_handler->arg_range($this->argument);
 204      return date_format_date($range[0], 'custom', $format);
 205    }
 206  
 207    /**
 208     * Create a summary query that matches the granularity.
 209     *
 210     * Needed or Views will do a groupby on the complete date instead
 211     * of only the part of the date actually used in the argument.
 212     */
 213    function summary_query() {
 214      $this->get_query_fields();
 215      
 216      // No way to do summaries on more than one field at a time.
 217      if (count($this->query_fields) > 1) {
 218        return;
 219      }
 220      
 221      $field = $this->query_fields[0]['field'];
 222      $date_handler = $this->query_fields[0]['date_handler'];
 223        
 224      // Get the SQL format for this granularity, like Y-m,
 225      // and use that as the grouping value.
 226      $format = $date_handler->views_formats($this->options['granularity'], 'sql');
 227      $this->formula = $date_handler->sql_format($format, $date_handler->sql_field($field['fullname']));
 228      
 229      // Add the computed field.
 230      $this->base_alias = $this->name_alias = $this->query->add_field(NULL, $this->formula, $field['query_name']);
 231         
 232      return $this->summary_basics(FALSE);
 233    }
 234  
 235    function get_query_fields() {
 236      $fields = date_api_fields($this->definition['base']);
 237      $fields = $fields['name'];
 238      $min_date = isset($this->min_date) ? $this->min_date : NULL;
 239      $min_utc = isset($this->min_utc) ? $this->min_utc : NULL;
 240      $max_date = isset($this->max_date) ? $this->max_date : NULL;
 241      $max_utc = isset($this->max_utc) ? $this->max_utc : NULL;
 242      $this->query_fields = array();
 243      foreach ($this->options['date_fields'] as $delta => $name) {
 244        if (array_key_exists($name, $fields) && $field = $fields[$name]) {
 245          $date_handler = new date_sql_handler();
 246          $date_handler->construct($field['sql_type'], date_default_timezone_name());
 247          $date_handler->granularity = $this->options['granularity'];
 248          date_views_set_timezone($date_handler, $this, $field);
 249          $this->query_fields[] = array('field' => $field, 'date_handler' => $date_handler);
 250        }
 251      }
 252    }
 253   
 254    /**
 255     * Make sure the date field is added to the query.
 256     * 
 257     * Do this in pre_query() so it will get done even if the argument 
 258     * is the wildcard, since query() is skipped when the wildcard is used.
 259     */
 260    function pre_query() { 
 261      // Unset invalid date values before the query runs.
 262      if (!empty($this->view->args) && count($this->view->args) > $this->position) {
 263        $argument = $this->view->args[$this->position];
 264        $parts = $this->date_handler->arg_parts($argument);
 265        if (empty($parts[0]['date']) && empty($parts[0]['period'])) {
 266          unset($this->view->args[$this->position]); 
 267        }
 268      }
 269    }
 270    
 271    /**
 272     * Called just prior to query(), this lets us set up table aliases for
 273     * relationships. This can't be done in pre_query(), because the relationship
 274     * isn't defined yet.
 275     */
 276    function set_relationship() {
 277      parent::set_relationship();
 278      $this->get_query_fields();
 279      if (!empty($this->relationship)) {
 280        if (!empty($this->query_fields)) {
 281          foreach ($this->query_fields as $query_field) {
 282            $field = $query_field['field'];
 283            $this->related_table_alias = $this->query->queue_table($field['table_name'], $this->relationship);
 284          }
 285        }
 286      }
 287    }
 288    
 289    /**
 290     * Set up the query for this argument.
 291     *
 292     * The argument sent may be found at $this->argument.
 293     */
 294    function query() {
 295      $block_identifier = date_block_identifier($this->view);
 296      if (!empty($this->view->block_identifier) || isset($_GET[$block_identifier])) {
 297        // Retrieve the block arguments in a way that will work for
 298        // urls like user/%/calendar/2009-04.
 299        if (!empty($_GET[$block_identifier])) {
 300          $path_args = explode('/', $this->view->get_path());
 301          $mini_args = explode('/', $_GET[$block_identifier]);
 302          foreach ($path_args as $pos => $key) {
 303            if ($path_args[$pos] != '%') {
 304              unset($mini_args[$pos]);
 305            }
 306          }
 307          // Get rid of gaps in the array caused by embedded args.
 308          $mini_args = array_values($mini_args);
 309          $this->view->args = $mini_args;
 310        }
 311        $i = 0;
 312        foreach ($this->view->argument as $argument) {
 313          if ($argument->field == 'date_argument') {
 314            $this->argument = $this->view->args[$argument->position];
 315            break;
 316          }
 317          $i++;
 318        }
 319      }
 320      $parts = $this->date_handler->arg_parts($this->argument);
 321      
 322      foreach ($parts as $type) {
 323        foreach ($type as $part) {
 324          foreach ($part as $key => $value) {
 325            if (!empty($value)) {
 326              // The last part evaluated is the one that will 'stick'
 327              // as the date type.
 328              $this->granularity = $key;
 329              $this->$key = $value;
 330            }
 331          }
 332        }
 333      }
 334      
 335      $range = $this->date_handler->arg_range($this->argument);
 336      $min_date = $range[0];
 337      $max_date = $range[1];
 338      $this->min_date = $min_date;
 339      $this->max_date = $max_date;
 340      
 341      // See if we're outside the allowed date range for our argument.
 342      if (date_format($min_date, 'Y') < $this->view->date_info->min_allowed_year || date_format($max_date, 'Y') > $this->view->date_info->max_allowed_year) {
 343        $this->forbid = TRUE;
 344        $this->query->add_where('date', "0=1");
 345        return;
 346      }
 347      
 348      // The second option seems to work better in the block view if 
 349      // set to something other than the original value. 
 350      // Need to keep an eye on this to be sure nothing else breaks.
 351      //$format = $this->date_handler->views_formats($this->options['granularity'], 'sql');
 352      $format = $this->date_handler->views_formats($this->granularity, 'sql');
 353      $this->get_query_fields();
 354      if (!empty($this->query_fields)) {
 355        // Use set_where_group() with the selected date_method 
 356        // of 'AND' or 'OR' to create the where clause.
 357        $this->query->set_where_group($this->options['date_method'], 'date');
 358        foreach ($this->query_fields as $query_field) {
 359          $field = $query_field['field'];
 360          $date_handler = $query_field['date_handler'];
 361          $table_alias = !empty($this->related_table_alias) ? $this->related_table_alias : $field['table_name'];
 362          $from_field = str_replace($field['table_name'] .'_', $table_alias .'.', $field['fromto'][0]);
 363          $to_field = str_replace($field['table_name'] .'_', $table_alias .'.', $field['fromto'][1]);
 364          
 365          if ($this->granularity != 'week') {
 366            $from = $date_handler->sql_where_format($format, $from_field, '<=', date_format($max_date, $format));
 367            $to   = $date_handler->sql_where_format($format, $to_field, '>=', date_format($min_date, $format));
 368          }
 369          else {
 370            $format = DATE_FORMAT_DATETIME;
 371            $from = $date_handler->sql_where_date('DATE', $from_field, '<=', date_format($max_date, $format));
 372            $to   = $date_handler->sql_where_date('DATE', $to_field, '>=', date_format($min_date, $format));          
 373          }
 374          $sql = str_replace('***table***', $field['table_name'], "($from AND $to)");
 375          if ($sql) {
 376            $this->query->add_where('date', $sql);
 377          }
 378        }
 379      }
 380    }
 381  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7