[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

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

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


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7