[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

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

   1  <?php
   2  //$Id: date_api_elements.inc,v 1.49.2.1.2.59 2010/12/29 14:11:50 karens Exp $
   3  /**
   4   * @file
   5   * Date API elements themes and validation.
   6   * This file is only included during the edit process to reduce memory usage.
   7   */
   8  
   9  /**
  10   * Implementation of hook_elements().
  11   *
  12   * Parameters for date form elements, designed to have sane defaults so any
  13   * or all can be omitted.
  14   *
  15   * Fill the element #default_value with a date in datetime format,
  16   * (YYYY-MM-DD HH:MM:SS), adjusted to the proper local timezone.
  17   *
  18   * NOTE - Converting a date stored in the database from UTC to the local zone
  19   * and converting it back to UTC before storing it is not handled by this
  20   * element and must be done in pre-form and post-form processing!!
  21   *
  22   * The date_select element will create a collection of form elements, with a
  23   * separate select or textfield for each date part. The whole collection will
  24   * get re-formatted back into a date value of the requested type during validation.
  25   *
  26   * The date_text element will create a textfield that can contain a whole
  27   * date or any part of a date as text. The user input value will be re-formatted
  28   * back into a date value of the requested type during validation.
  29   *
  30   * The date_timezone element will create a drop-down selector to pick a
  31   * timezone name.
  32   *
  33   * #date_timezone
  34   *   The local timezone to be used to create this date.
  35   *
  36   * #date_format
  37   *   A format string that describes the format and order of date parts to
  38   *   display in the edit form for this element. This makes it possible
  39   *   to show date parts in a custom order, or to leave some of them out.
  40   *   Be sure to add 'A' or 'a' to get an am/pm selector. Defaults to the
  41   *   short site default format.
  42   *
  43   * #date_label_position
  44   *   Handling option for date part labels, like 'Year', 'Month', and 'Day',
  45   *   can be 'above' the date part, 'within' it, or 'none', default is 'above'.
  46   *   The 'within' option shows the label as the first option in a select list
  47   *   or the default value for an empty textfield, taking up less screen space.
  48   *
  49   * #date_increment
  50   *   Increment minutes and seconds by this amount, default is 1.
  51   *
  52   * #date_year_range
  53   *   The number of years to go back and forward in a year selector,
  54   *   default is -3:+3 (3 back and 3 forward).
  55   *
  56   * #date_text_parts
  57   *   Array of date parts that should use textfields instead of selects
  58   *   i.e. array('year') will format the year as a textfield and other
  59   *   date parts as drop-down selects.
  60   */
  61  function _date_api_elements() {
  62    $date_base = array(
  63      '#input' => TRUE, '#tree' => TRUE,
  64      '#date_timezone' => date_default_timezone_name(),
  65      '#date_format' => variable_get('date_format_short', 'm/d/Y - H:i'),
  66      '#date_text_parts' => array(),
  67      '#date_increment' => 1,
  68      '#date_year_range' => '-3:+3',
  69      '#date_label_position' => 'above',
  70      );
  71    $type['date_select'] = array_merge($date_base, array(
  72      '#process' => array('date_select_process'),
  73      ));
  74    $type['date_text'] = array_merge($date_base, array(
  75      '#process' => array('date_text_process'),
  76      ));
  77    $type['date_timezone'] = array(
  78      '#input' => TRUE, '#tree' => TRUE,
  79      '#process' => array('date_timezone_process'),
  80      );
  81    return $type;
  82  }
  83  
  84  /**
  85   * Create a timezone form element.
  86   *
  87   * @param array $element
  88   * @return array
  89   *   the timezone form element
  90   */
  91  function date_timezone_process($element, $edit, $form_state, $form) {
  92    $element['#tree'] = TRUE;
  93    $element['timezone'] = array(
  94      '#type' => 'select',
  95      '#title' => theme('date_part_label_timezone', 'select', $element),
  96      '#default_value' => $element['#value'],
  97      '#options' => date_timezone_names($element['#required']),
  98      '#weight' => $element['#weight'],
  99      '#required' => $element['#required'],
 100      '#theme' => 'date_select_element',
 101    );
 102    if (isset($element['#element_validate'])) {
 103      array_push($element['#element_validate'], 'date_timezone_validate');
 104    }
 105    else {
 106      $element['#element_validate'] = array('date_timezone_validate');
 107    }
 108    // TODO This sometimes causes problems, do we need it?
 109    //$element['#attributes'] = array('class' => 'date-timezone clear-block');
 110    return $element;
 111  }
 112  
 113  /**
 114   * Text date input form.
 115   *
 116   * Display all or part of a date in a single textfield.
 117   *
 118   * The exact parts displayed in the field are those in #date_granularity.
 119   * The display of each part comes from #date_format.
 120   * 
 121   * In regular FAPI processing $element['#value'] will contain a string
 122   * value before the form is submitted, and an array during submission.
 123   * 
 124   * In regular FAPI processing $edit is empty until the form is submitted
 125   * when it will contain an array.
 126   * 
 127   * Views widget processing now receives the same values as normal FAPI
 128   * processing (that was not true in Views 1).
 129   * 
 130   */
 131  function date_text_process($element, $edit, $form_state, $form) {
 132    $date = NULL;
 133    $granularity = date_format_order($element['#date_format']);
 134    
 135    // We sometimes get $edit without $edit['date'] from
 136    // Views exposed filters.
 137    if (!empty($edit) && is_array($edit) && !empty($edit['date'])) {
 138      $datetime = date_convert_from_custom($edit['date'], $element['#date_format']);
 139      $date = date_make_date($datetime, $element['#date_timezone'], DATE_DATETIME, $granularity);
 140    }
 141    elseif (!empty($element['#value'])) {
 142      $date = date_make_date($element['#value'], $element['#date_timezone'], DATE_DATETIME, $granularity);
 143    }
 144    $element['#tree'] = TRUE;
 145  
 146    $element['date']['#type'] = 'textfield';
 147    $element['date']['#weight'] = !empty($element['date']['#weight']) ? $element['date']['#weight'] : $element['#weight'];
 148    $element['date']['#default_value'] = is_object($date) ? date_format_date($date , 'custom', $element['#date_format']) : '';
 149    $element['date']['#attributes'] = array('class' => (isset($element['#attributes']['class']) ? $element['#attributes']['class'] : '') .' date-date');
 150    $element['date']['#description'] = ' '. t('Format: @date', array('@date' => date_format_date(date_now(), 'custom', $element['#date_format'])));
 151    
 152    // Keep the system from creating an error message for the sub-element.
 153    // We'll set our own message on the parent element.
 154    //$element['date']['#required'] = $element['#required'];
 155    $element['date']['#theme'] = 'date_textfield_element';
 156    if (isset($element['#element_validate'])) {
 157      array_push($element['#element_validate'], 'date_text_validate');
 158    }
 159    else {
 160      $element['#element_validate'] = array('date_text_validate');
 161    }
 162    if (!empty($element['#force_value'])) {
 163      $element['date']['#value'] = $element['date']['#default_value'];
 164    }
 165    return $element;
 166  }
 167  
 168  /**
 169   * Flexible date/time drop-down selector.
 170   *
 171   * Splits date into a collection of date and time sub-elements, one
 172   * for each date part. Each sub-element can be either a textfield or a
 173   * select, based on the value of ['#date_settings']['text_fields'].
 174   *
 175   * The exact parts displayed in the field are those in #date_granularity.
 176   * The display of each part comes from ['#date_settings']['format'].
 177   * 
 178   * In regular FAPI processing $element['#value'] will contain a string
 179   * value before the form is submitted, and an array during submission.
 180   * 
 181   * In regular FAPI processing $edit is empty until the form is submitted
 182   * when it will contain an array.
 183   * 
 184   * Views widget processing now receives the same values as normal FAPI
 185   * processing (that was not true in Views 1).
 186   * 
 187   */
 188  function date_select_process($element, $edit, $form_state, $form) {
 189    $date = NULL;
 190    $granularity = date_format_order($element['#date_format']);
 191    if (!empty($edit)) {
 192      $date = date_make_date($edit, $element['#date_timezone'], DATE_ARRAY, $granularity);
 193    }
 194    elseif (!empty($element['#value'])) {
 195      $date = date_make_date($element['#value'], $element['#date_timezone'], DATE_DATETIME, $granularity);
 196    }
 197    
 198    $element['#tree'] = TRUE;
 199    date_increment_round($date, $element['#date_increment']);
 200    $element += (array) date_parts_element($element, $date, $element['#date_format']);
 201    
 202    // Store a hidden value for all date parts not in the current display.
 203    $granularity = date_format_order($element['#date_format']);
 204    $formats = array('year' => 'Y', 'month' => 'n', 'day' => 'j', 'hour' => 'H', 'minute' => 'i', 'second' => 's');
 205    foreach (date_nongranularity($granularity) as $field) {
 206      if ($field != 'timezone') {
 207        $element[$field] = array(
 208          '#type' => 'value',
 209          '#value' => 0,
 210          );
 211      }
 212    }
 213    if (isset($element['#element_validate'])) {
 214      array_push($element['#element_validate'], 'date_select_validate');
 215    }
 216    else {
 217      $element['#element_validate'] = array('date_select_validate');
 218    }
 219  
 220    return $element;
 221  }
 222  
 223  /**
 224   * Create form elements for one or more date parts.
 225   *
 226   * Get the order of date elements from the provided format.
 227   * If the format order omits any date parts in the granularity, alter the
 228   * granularity array to match the format, then flip the $order array
 229   * to get the position for each element. Then iterate through the
 230   * elements and create a sub-form for each part.
 231   *
 232   * @param array $element
 233   * @param object $date
 234   * @param array $granularity
 235   * @param string $format
 236   * @return array
 237   *   the form array for the submitted date parts
 238   */
 239  function date_parts_element($element, $date, $format) {
 240    $granularity = date_format_order($format);
 241    $sub_element = array('#granularity' => $granularity);
 242    $order = array_flip($granularity);
 243  
 244    $hours_format  = strpos(strtolower($element['#date_format']), 'a') ? 'g': 'G';
 245    $month_function  = strpos($element['#date_format'], 'F') !== FALSE ? 'date_month_names' : 'date_month_names_abbr';
 246    $count = 0;
 247    $increment = min(intval($element['#date_increment']), 1);
 248    foreach ($granularity as $field) {
 249      // Allow empty value as option if date is not required 
 250      // or if empty value was provided as a starting point.
 251      $part_required = ($element['#required'] && is_object($date)) ? TRUE : FALSE;
 252      $part_type = in_array($field, $element['#date_text_parts']) ? 'textfield' : 'select';
 253      $sub_element[$field] = array(
 254        '#weight' => $order[$field],
 255        '#required' => $element['#required'],
 256        '#attributes' => array('class' => (isset($element['#attributes']['class']) ? $element['#attributes']['class'] : '') .' date-'. $field),
 257        );
 258      switch ($field) {
 259        case 'year':
 260          $range = date_range_years($element['#date_year_range'], $date);
 261          $min_year = $range[0];
 262          $max_year = $range[1];
 263          
 264          $sub_element[$field]['#default_value'] = is_object($date) ? date_format($date, 'Y') : '';
 265          if ($part_type == 'select') {
 266            $sub_element[$field]['#options'] = drupal_map_assoc(date_years($min_year, $max_year, $part_required));
 267          }
 268          break;
 269        case 'month':
 270          $sub_element[$field]['#default_value'] = is_object($date) ? date_format($date, 'n') : '';
 271          if ($part_type == 'select') {
 272            $sub_element[$field]['#options'] = $month_function($part_required);
 273          }
 274          break;
 275        case 'day':
 276          $sub_element[$field]['#default_value'] = is_object($date) ? date_format($date, 'j') : '';
 277          if ($part_type == 'select') {
 278            $sub_element[$field]['#options'] = drupal_map_assoc(date_days($part_required));
 279          }
 280          break;
 281        case 'hour':
 282          $sub_element[$field]['#default_value'] = is_object($date) ? date_format($date, $hours_format) : '';
 283          if ($part_type == 'select') {
 284            $sub_element[$field]['#options'] = drupal_map_assoc(date_hours($hours_format, $part_required));
 285          }
 286          $sub_element[$field]['#prefix'] = theme('date_part_hour_prefix', $element);
 287          break;
 288        case 'minute':
 289          $sub_element[$field]['#default_value'] = is_object($date) ? date_format($date, 'i') : '';
 290          if ($part_type == 'select') {
 291            $sub_element[$field]['#options'] = drupal_map_assoc(date_minutes('i', $part_required, $element['#date_increment']));
 292          }
 293          $sub_element[$field]['#prefix'] = theme('date_part_minsec_prefix', $element);
 294          break;
 295        case 'second':
 296          $sub_element[$field]['#default_value'] = is_object($date) ? date_format($date, 's') : '';
 297          if ($part_type == 'select') {
 298            $sub_element[$field]['#options'] = drupal_map_assoc(date_seconds('s', $part_required, $element['#date_increment']));
 299          }
 300          $sub_element[$field]['#prefix'] = theme('date_part_minsec_prefix', $element);
 301          break;
 302      }
 303  
 304      // Add handling for the date part label.
 305      $label = theme('date_part_label_'. $field, $part_type, $element);
 306      if (in_array($field, $element['#date_text_parts'])) {
 307        $sub_element[$field]['#type'] = 'textfield';
 308        $sub_element[$field]['#theme'] = 'date_textfield_element';
 309        $sub_element[$field]['#size'] = 7;
 310        if ($element['#date_label_position'] == 'within') {
 311          if (is_array($sub_element[$field]['#options'])) {
 312            $sub_element[$field]['#options'] = array(
 313              '-'. $label => '-'. $label) + $sub_element[$field]['#options'];
 314          }
 315          if (empty($sub_element[$field]['#default_value'])) {
 316            $sub_element[$field]['#default_value'] = '-'. $label;
 317          }
 318        }
 319        elseif ($element['#date_label_position'] != 'none') {
 320          $sub_element[$field]['#title'] = $label;
 321        }
 322      }
 323      else {
 324        $sub_element[$field]['#type'] = 'select';
 325        $sub_element[$field]['#theme'] = 'date_select_element';
 326        if ($element['#date_label_position'] == 'within') {
 327          $sub_element[$field]['#options'] = array(
 328            '' => '-'. $label) + $sub_element[$field]['#options'];
 329        }
 330        elseif ($element['#date_label_position'] != 'none') {
 331          $sub_element[$field]['#title'] = $label;
 332        }
 333      }
 334   
 335      // Views exposed filters are treated as submitted even if not,
 336      // so force the #default value in that case. Make sure we set
 337      // a default that is in the option list.
 338      if (!empty($element['#force_value'])) {
 339        $options = $sub_element[$field]['#options'];
 340        $default = !empty($sub_element[$field]['#default_value']) ? $sub_element[$field]['#default_value'] : array_shift($options);
 341        $sub_element[$field]['#value'] = $default;
 342      }
 343    }
 344    
 345    if (($hours_format == 'g' || $hours_format == 'h') && date_has_time($granularity)) {
 346      $sub_element['ampm'] = array(
 347        '#type' => 'select',
 348        '#default_value' => is_object($date) ? (date_format($date, 'G') >= 12 ? 'pm' : 'am') : '',
 349        '#options' => drupal_map_assoc(date_ampm()),
 350        '#weight' => 8,
 351        '#attributes' => array('class' => 'date-ampm'),
 352      );
 353      if ($element['#date_label_position'] == 'within') {
 354        $sub_element['ampm']['#options'] = array('' => '-'. theme('date_part_label_ampm', 'ampm', $element)) + $sub_element['ampm']['#options'];
 355      }
 356      elseif ($element['#date_label_position'] != 'none') {
 357        $sub_element['ampm']['#title'] = theme('date_part_label_ampm', 'ampm', $element);
 358      }
 359    }
 360  
 361    return $sub_element;
 362  }
 363  
 364  /**
 365   * Helper function to round minutes and seconds to requested value.
 366   */
 367  function date_increment_round(&$date, $increment) {
 368    // Round minutes and seconds, if necessary.
 369    if (is_object($date) && $increment > 1) {
 370      $day = intval(date_format($date, 'j'));
 371      $hour = intval(date_format($date, 'H'));
 372      $second = intval(round(intval(date_format($date, 's')) / $increment) * $increment);
 373      $minute = intval(date_format($date, 'i'));
 374      if ($second == 60) {
 375        $minute += 1;
 376        $second = 0;
 377      }
 378      $minute = intval(round($minute / $increment) * $increment);
 379      if ($minute == 60) {
 380        $hour += 1;
 381        $minute = 0;
 382      }
 383      date_time_set($date, $hour, $minute, $second);
 384      if ($hour == 24) {
 385        $day += 1;
 386        $hour = 0;
 387        $year = date_format($date, 'Y');
 388        $month = date_format($date, 'n');
 389        date_date_set($date, $year, $month, $day);
 390      }
 391    }
 392    return $date;
 393  }
 394  
 395  /**
 396   *  Validation function for date selector.
 397   * 
 398   * When used as a Views widget, the validation step always gets triggered,
 399   * even with no form submission. Before form submission $element['#value']
 400   * contains a string, after submission it contains an array.
 401   * 
 402   */
 403  function date_select_validate($element, &$form_state) {
 404    if (is_string($element['#value'])) {
 405      return;
 406    }
 407    // Strip field labels out of the results.
 408    foreach ($element['#value'] as $field => $field_value) {
 409      if (substr($field_value, 0, 1) == '-') {
 410        $element['#value'][$field] = '';
 411      }
 412    }
 413   
 414    $error_field = implode('][', $element['#parents']);
 415    $errors = array();
 416    $label = !empty($element['#date_title']) ? $element['#date_title'] : (!empty($element['#title']) ? $element['#title'] : '');
 417    
 418    if (in_array('year', $element['#granularity']) && ($element['#required'] || !empty($element['#value']['year']))) {
 419      if ($element['#value']['year'] < variable_get('date_min_year', 1) || $element['#value']['year'] > variable_get('date_max_year', 4000)) {
 420        $errors[] = t('The year must be a number between %min and %max.', array(
 421          '%min' => variable_get('date_min_year', 1), '%max' => variable_get('date_max_year', 4000)));  
 422      }
 423      else {
 424        $year = $element['#value']['year'];
 425      }
 426    }
 427    if (in_array('month', $element['#granularity']) && ($element['#required'] || !empty($element['#value']['month']))) {
 428      if ($element['#value']['month'] < 1 || $element['#value']['month'] > 12) {
 429        $errors[] = t('The month must be a number between 1 and 12.');
 430      }
 431      else {
 432        $month = $element['#value']['month'];
 433      }
 434    }
 435    if (in_array('day', $element['#granularity']) && ($element['#required'] || !empty($element['#value']['day']))) {
 436      $min = 1;
 437      $max = isset($year) && isset($month) ? date_days_in_month($year, $month) : 31;
 438      if ($element['#value']['day'] < $min || $element['#value']['day'] > $max) {
 439        $errors[] = t('The day must be a number between !min and !max.', array('!min' => $min, '!max' => $max));
 440      }
 441    }
 442    if (in_array('hour', $element['#granularity']) && ($element['#required'] || !empty($element['#value']['hour']))) {
 443      $min = isset($element['#value']['ampm']) ? 1 : 0;
 444      $max = isset($element['#value']['ampm']) ? 12 : 23;
 445      if ($element['#value']['hour'] < $min || $element['#value']['hour'] > $max) {
 446        $errors[] = t('The hour must be a number between !min and !max.', array('!min' => $min, '!max' => $max));
 447      }
 448    }
 449    if (in_array('minute', $element['#granularity']) && ($element['#required'] || !empty($element['#value']['minute']))) {
 450      $min = 0;
 451      $max = 59;
 452      if ($element['#value']['minute'] < $min || $element['#value']['minute'] > $max) {
 453        $errors[] = t('The minute must be a number between !min and !max.', array('!min' => $min, '!max' => $max));
 454      }
 455    }
 456    if (in_array('second', $element['#granularity']) && ($element['#required'] || !empty($element['#value']['second']))) {
 457      $min = 0;
 458      $max = 59;
 459      if ($element['#value']['second'] < $min || $element['#value']['second'] > $max) {
 460        $errors[] = t('The second must be a number between !min and !max.', array('!min' => $min, '!max' => $max));
 461      }
 462    }
 463    if (isset($element['#value']['ampm'])) {
 464      if ($element['#value']['ampm'] == 'pm' && $element['#value']['hour'] < 12) {
 465        $element['#value']['hour'] += 12;
 466      }
 467      elseif ($element['#value']['ampm'] == 'am' && $element['#value']['hour'] == 12) {
 468        $element['#value']['hour'] -= 12;
 469      }
 470    }
 471    $value = date_select_input_value($element);
 472    if (empty($value) && empty($errors) && $element['#required']) {
 473      $errors[] = t('A valid value is required.');
 474    }
 475    if (!empty($errors)) {
 476      array_unshift($errors, t('Field %field has errors.', array('%field' => $label)));
 477      form_set_error($error_field, implode(' ', $errors));
 478    }
 479    // If there are no errors and the value is valid, set it.
 480    if (empty($errors) && !empty($value)) {
 481      form_set_value($element, $value, $form_state);
 482    }
 483    else {
 484      form_set_value($element, NULL, $form_state);
 485    }
 486  }
 487  
 488  /**
 489   * Helper function for extracting a date value out of user input.
 490   */
 491  function date_select_input_value($element) {
 492    $granularity = date_format_order($element['#date_format']);
 493    if (date_is_valid($element['#value'], DATE_ARRAY, $granularity)) {
 494      // Use fuzzy_datetime here to be sure year-only dates
 495      // aren't inadvertantly shifted to the wrong year by trying
 496      // to save '2009-00-00 00:00:00'.
 497      return date_fuzzy_datetime(date_convert($element['#value'], DATE_ARRAY, DATE_DATETIME));
 498    }
 499    return NULL;
 500  }
 501  
 502  /**
 503   *  Validation for text input.
 504   * 
 505   * When used as a Views widget, the validation step always gets triggered,
 506   * even with no form submission. Before form submission $element['#value']
 507   * contains a string, after submission it contains an array.
 508   * 
 509   */
 510  function date_text_validate($element, &$form_state) {
 511    if (is_string($element['#value'])) {
 512      return;
 513    }
 514    $parents = $element['#parents'];
 515    $label = !empty($element['#date_title']) ? $element['#date_title'] : (!empty($element['#title']) ? $element['#title'] : '');
 516    $value = date_text_input_value($element);
 517    
 518    if (empty($value) && !empty($element['#required'])) {
 519      form_error($element, t('A valid date is required for %title.', array('%title' => $label))); 
 520    }
 521    elseif (empty($value) && !empty($element['#value']['date'])) {
 522      form_error($element, t('%title is invalid.', array('%title' => $label))); 
 523    }
 524    elseif (!empty($value)) {
 525      form_set_value($element, $value, $form_state);
 526    }
 527  }
 528  
 529  /**
 530   * Helper function for extracting a date value out of user input.
 531   */
 532  function date_text_input_value($element) {
 533    $form_values = $element['#value'];
 534    $granularity = date_format_order($element['#date_format']);
 535    $input = $form_values['date'];
 536    if (!$element['#required'] && trim($input) == '') return NULL;
 537  
 538    $value = date_limit_value(date_convert_from_custom($input, $element['#date_format']), $granularity);
 539  
 540    // If it creates a valid date, use it.
 541    if (date_is_valid($value, DATE_DATETIME, $granularity)) {
 542      return $value;
 543    }
 544    // TODO come back and try to find a way to use strtotime to guess
 545    // a valid value. Previous attempts to do it were too forgiving and
 546    // invalid input was just silently converted to 'now'.
 547    // See http://drupal.org/node/265076.
 548  
 549    return NULL;
 550  }
 551  
 552  /**
 553   *  Validation for timezone input
 554   *
 555   *  Move the timezone value from the nested field back to the original field.
 556   */
 557  function date_timezone_validate($element, &$form_state) {
 558    form_set_value($element, $element['#value']['timezone'], $form_state);
 559  }
 560  
 561  
 562  /**
 563   * Convert a date input in a custom format to a standard date type
 564   *
 565   * Handles conversion of translated month names (i.e. turns t('Mar') or
 566   * t('March') into 3). Also properly handles dates input in European style
 567   * short formats, like DD/MM/YYYY. Works by parsing the format string
 568   * to create a regex that can be used on the input value.
 569   *
 570   * The original code to do this was created by Yves Chedemois (yched).
 571   *
 572   * @param string $date
 573   *   a date value
 574   * @param string $format
 575   *   a date format string that describes the format of the input value
 576   * @return mixed
 577   *   input value converted to a DATE_DATETIME value
 578   */
 579  function date_convert_from_custom($date, $format) {
 580    $array = date_format_patterns();
 581    foreach ($array as $key => $value) {
 582      $patterns[] = "`(^|[^\\\\\\\\])". $key ."`"; // the letter with no preceding '\'
 583      $repl1[] = '$1}(.)';                  // a single character
 584      $repl2[] = '$1}('. $value .')';       // the
 585    }
 586    $patterns[] = "`\\\\\\\\([". implode(array_keys($array)) ."])`";
 587    $repl1[] = '$1}';
 588    $repl2[] = '$1}';
 589  
 590    $format_regexp = preg_quote($format);
 591  
 592    // extract letters
 593    $regex1 = preg_replace($patterns, $repl1, $format_regexp, 1);
 594    $regex1 = str_replace('A', '(.)', $regex1);
 595    $regex1 = str_replace('a', '(.)', $regex1);
 596    preg_match('`^'. $regex1 .'$`', stripslashes($format), $letters);
 597    array_shift($letters);
 598  
 599    // extract values
 600    $regex2 = preg_replace($patterns, $repl2, $format_regexp, 1);
 601    $regex2 = str_replace('A', '(AM|PM)', $regex2);
 602    $regex2 = str_replace('a', '(am|pm)', $regex2);
 603    preg_match('`^'. $regex2 .'$`', $date, $values);
 604    array_shift($values);
 605    
 606    // if we did not find all the values for the patterns in the format, abort
 607    if (count($letters) != count($values)) {
 608      return  NULL;
 609    }
 610    $final_date = array('hour' => 0, 'minute' => 0, 'second' => 0,
 611      'month' => 0, 'day' => 0, 'year' => 0);
 612    foreach ($letters as $i => $letter) {
 613      $value = $values[$i];
 614      switch ($letter) {
 615        case 'd':
 616        case 'j':
 617          $final_date['day'] = intval($value);
 618          break;
 619        case 'n':
 620        case 'm':
 621          $final_date['month'] = intval($value);
 622          break;
 623        case 'F':
 624          $array_month_long = array_flip(date_month_names());
 625          $final_date['month'] = $array_month_long[$value];
 626          break;
 627        case 'M':
 628          $array_month = array_flip(date_month_names_abbr());
 629          $final_date['month'] = $array_month[$value];
 630          break;
 631        case 'Y':
 632        case 'y':
 633          $year = $value;
 634          // if no century, we add the current one ("06" => "2006")
 635          $final_date['year'] = str_pad($year, 4, substr(date("Y"), 0, 2), STR_PAD_LEFT);
 636          break;
 637        case 'a':
 638        case 'A':
 639          $ampm = strtolower($value);
 640          break;
 641        case 'g':
 642        case 'h':
 643        case 'G':
 644        case 'H':
 645          $final_date['hour'] = intval($value);
 646          break;
 647        case 'i':
 648          $final_date['minute'] = intval($value);
 649          break;
 650        case 's':
 651          $final_date['second'] = intval($value);
 652          break;
 653        case 'U':
 654          return date_convert($value, DATE_UNIX, DATE_DATETIME);
 655          break;
 656      }
 657    }
 658    if (isset($ampm) && $ampm == 'pm' && $final_date['hour'] < 12) {
 659      $final_date['hour'] += 12;
 660    }
 661    elseif (isset($ampm) && $ampm == 'am' && $final_date['hour'] == 12) {
 662      $final_date['hour'] -= 12;
 663    }
 664    // Don't test for valid date, we might use this to extract
 665    // incomplete date part info from user input.
 666    return date_convert($final_date, DATE_ARRAY, DATE_DATETIME);
 667  }


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