You are here

function webform_expand_date in Webform 7.4

Same name and namespace in other branches
  1. 5.2 components/date.inc \webform_expand_date()
  2. 6.3 components/date.inc \webform_expand_date()
  3. 6.2 components/date.inc \webform_expand_date()
  4. 7.3 components/date.inc \webform_expand_date()

Form API #process function for Webform date fields.

1 string reference to 'webform_expand_date'
_webform_render_date in components/date.inc
Implements _webform_render_component().

File

components/date.inc, line 214
Webform module date component.

Code

function webform_expand_date($element) {
  $timezone = $element['#timezone'] != 'user' ? NULL : 'user';

  // Accept a string or array value for #default_value.
  if (!empty($element['#default_value']) && is_string($element['#default_value'])) {
    $timestring = webform_strtodate('c', $element['#default_value'], $timezone);
    $element['#default_value'] = webform_date_array($timestring, 'date');
  }

  // Prevent an error in PHP 5.4 caused by core's treatment of the #value.
  if (isset($element['#value'])) {
    unset($element['#value']);
  }

  // Set defaults according to existing #default_value (set by Form API).
  if (isset($element['#default_value']['month']) || isset($element['#default_value']['day']) || isset($element['#default_value']['year'])) {
    $default_values = array(
      'month' => $element['#default_value']['month'],
      'day' => $element['#default_value']['day'],
      'year' => $element['#default_value']['year'],
    );
  }
  else {
    $default_values = array(
      'day' => NULL,
      'month' => NULL,
      'year' => NULL,
    );
  }

  // Let Drupal do it's normal expansion.
  $element = form_process_date($element);

  // Convert relative dates to absolute and calculate the year, month and day.
  $timezone = $element['#timezone'] != 'user' ? NULL : 'user';
  foreach (array(
    'start',
    'end',
  ) as $start_end) {
    $element_field =& $element["#{$start_end}_date"];
    $element_field = $element_field ? webform_strtodate('Y-m-d', $element_field, $timezone, $element['#reference_timestamp']) : '';
    if ($element_field) {
      $parts = explode('-', $element_field);
    }
    else {
      $parts = $start_end == 'start' ? array(
        webform_strtodate('Y', '-2 years'),
        1,
        1,
      ) : array(
        webform_strtodate('Y', '+2 years'),
        12,
        31,
      );
      $element_field = '';
    }

    // Drop PHP reference.
    unset($element_field);
    $parts[3] = $parts[0] . '-' . $parts[1] . '-' . $parts[2];
    $range[$start_end] = array_combine(array(
      'year',
      'month',
      'day',
      'date',
    ), $parts);
  }

  // The start date is not guaranteed to be early than the end date for
  // historical reasons.
  if ($range['start']['date'] > $range['end']['date']) {
    $temp = $range['start'];
    $range['start'] = $range['end'];
    $range['end'] = $temp;
  }

  // Restrict the months and days when not all options are valid choices.
  if ($element['#start_date'] && $element['#end_date']) {
    $delta_months = $range['end']['year'] * 12 + $range['end']['month'] - ($range['start']['year'] * 12 + $range['start']['month']);
    if ($delta_months < 11) {

      // There are 10 or fewer months between the start and end date. If there
      // were 11, then every month would be possible, and the menu select
      // should not be pruned.
      $month_options =& $element['month']['#options'];
      if ($range['start']['month'] <= $range['end']['month']) {
        $month_options = array_intersect_key($month_options, array_flip(range($range['start']['month'], $range['end']['month'])));
      }
      else {
        $month_options = array_intersect_key($month_options, array_flip(range($range['start']['month'], 12))) + array_intersect_key($month_options, array_flip(range(1, $range['end']['month'])));
      }

      // Drop PHP reference.
      unset($month_options);
      if ($delta_months <= 1) {

        // The start and end date are either on the same month or consecutive
        // months. See if the days should be pruned.
        $day_options =& $element['day']['#options'];
        if ($range['start']['month'] == $range['end']['month']) {

          // Range is within the same month. The days are a simple range from
          // start day to end day.
          $day_options = array_intersect_key($day_options, array_flip(range($range['start']['day'], $range['end']['day'])));
        }
        elseif ($range['start']['day'] > $range['end']['day'] + 1) {

          // Range spans two months and at least one day would be omitted.
          $days_in_month = date('t', mktime(0, 0, 0, $range['start']['month'], 1, $range['start']['year']));
          $day_options = array_intersect_key($day_options, array_flip(range($range['start']['day'], $days_in_month))) + array_intersect_key($day_options, array_flip(range(1, $range['end']['day'])));
        }

        // Drop PHP reference.
        unset($day_options);
      }
    }
  }

  // Set default values.
  foreach ($default_values as $type => $value) {
    switch ($type) {
      case 'month':
        $none = t('Month');
        $hidden_default = 1;
        break;
      case 'day':
        $none = t('Day');
        $hidden_default = 1;
        break;
      case 'year':
        $none = t('Year');
        $hidden_default = !empty($element['#default_value']['year']) ? $element['#default_value']['year'] : webform_strtodate('Y', 'today', $timezone);
        break;
    }
    unset($element[$type]['#value']);
    $element[$type]['#title'] = $none;
    $element[$type]['#title_display'] = 'invisible';
    $element[$type]['#default_value'] = $default_values[$type];
    $element[$type]['#options'] = array(
      '' => $none,
    ) + $element[$type]['#options'];
    if (in_array($type, $element['#exclude'])) {
      $element[$type] += array(
        '#prefix' => '<div class="webform-date-field-wrapper element-invisible">',
        '#suffix' => '</div>',
      );
      $element[$type]['#default_value'] = $hidden_default;
    }
  }

  // Tweak the year field.
  if ($element['#year_textfield']) {
    $element['year']['#type'] = 'textfield';
    $element['year']['#size'] = 5;
    $element['year']['#maxlength'] = 4;
    unset($element['year']['#options']);
  }
  elseif ($element['#start_date'] || $element['#end_date']) {
    $element['year']['#options'] = array(
      '' => t('Year'),
    ) + drupal_map_assoc(range($range['start']['year'], $range['end']['year']));
  }
  return $element;
}