You are here

public function DatePopupTimepickerTimepicker::fieldSettingsFormValidate in Date Popup Timepicker 7

Field Settings Form validate callback.

Parameters

array $element: Field settings form element/part as defined in the fieldSettingsForm().

array $values: Submitted settings values for defined settings form element/part.

array $form: Whole settings form basically defined by field_ui_field_edit_form().

array $form_state: Whole form state passed to field_ui_field_edit_form_validate() and other validate callbacks of the field_ui_field_edit_form form.

Overrides DatePopupTimepicker::fieldSettingsFormValidate

See also

field_ui_field_edit_form()

field_ui_field_edit_form_validate()

File

plugins/timepicker/timepicker.inc, line 393

Class

DatePopupTimepickerTimepicker
Class DatePopupTimepickerTimepicker.

Code

public function fieldSettingsFormValidate(array &$element, array &$values, array &$form, array &$form_state) {

  // Validate int hours and minutes settings.
  foreach (array(
    'hours',
    'minutes',
    'minTime',
    'maxTime',
  ) as $key) {
    foreach ($values['timepicker_options'][$key] as $subkey => $value) {

      // Init validation limits.
      if ($key == 'minutes' && $subkey == 'interval') {
        $limits = array(
          1,
          59,
        );
      }
      elseif ($key == 'hours' || $subkey == 'hour') {
        $limits = array(
          0,
          23,
        );
      }
      else {
        $limits = array(
          0,
          59,
        );
      }

      // Validate.
      if ($value !== '') {
        if (!is_numeric($value) || intval($value) != $value || $value < $limits[0] || $value > $limits[1]) {
          $t_args = array(
            '%name' => $element['timepicker_options'][$key][$subkey]['#title'],
            '@start' => $limits[0],
            '@end' => $limits[1],
          );
          form_error($element['timepicker_options'][$key][$subkey], t('%name must be an integer between @start and @end.', $t_args));
        }
        else {
          form_set_value($element['timepicker_options'][$key][$subkey], (int) $value, $form_state);
        }
      }
      else {
        form_set_value($element['timepicker_options'][$key][$subkey], NULL, $form_state);
      }
    }
  }

  // Validate rows part.
  $value = $values['timepicker_options']['rows'];
  if ($value !== '') {
    if (!is_numeric($value) || intval($value) != $value || $value < 2) {
      $t_args = array(
        '%name' => $element['timepicker_options']['rows']['#title'],
      );
      form_error($element['timepicker_options']['rows'], t('%name must be an integer greater than 1.', $t_args));
    }
    else {
      form_set_value($element['timepicker_options']['rows'], (int) $value, $form_state);
    }
  }
  else {
    form_set_value($element['timepicker_options']['rows'], NULL, $form_state);
  }

  // Define format for Date Entry.
  $input_format = $form_state['values']['instance']['widget']['settings']['input_format'];
  $granularity = $form_state['values']['field']['settings']['granularity'];
  $date_granularity = array(
    'year',
    'month',
    'day',
  );
  foreach ($granularity as $key => $value) {
    if (!$value || in_array($key, $date_granularity)) {
      unset($granularity[$key]);
    }
  }
  $date_entry_format = date_limit_format($input_format, $granularity);

  // If date field expect seconds, we should not show timepicker,
  // as it not supports seconds entry and will lead to invalid value entry.
  // s = Seconds with leading zeros.
  if (stripos($date_entry_format, 's') === FALSE) {

    // Depending on format, apply the appropriate settings.
    // We can omit leading zeros setting for hours.
    // g = 12-hour format of an hour without leading zeros.
    // G = 24-hour format of an hour without leading zeros.
    // h = 12-hour format of an hour with leading zeros.
    // H = 24-hour format of an hour with leading zeros.
    if (strpos($date_entry_format, 'H') !== FALSE || strpos($date_entry_format, 'G') !== FALSE) {
      if (strpos($date_entry_format, 'a') === FALSE) {
        $values['timepicker_options']['showHours'] = TRUE;
        $values['timepicker_options']['showPeriod'] = FALSE;
      }
      else {
        drupal_set_message(t('Error occured. Please contact site administrator'), 'error');
        watchdog('Date popup timepicker', 'Error occured. 24-hour format should not have am/pm time period.', array(), WATCHDOG_ERROR);
        $values['timepicker_options']['showOn'] = 'none';
      }
    }
    elseif (strpos($date_entry_format, 'h') !== FALSE || strpos($date_entry_format, 'g') !== FALSE) {
      if (strpos($date_entry_format, 'a') !== FALSE) {
        $values['timepicker_options']['showHours'] = TRUE;
        $values['timepicker_options']['showPeriod'] = TRUE;
      }
      else {
        drupal_set_message(t('Error occured. Please contact site administrator'), 'error');
        watchdog('Date popup timepicker', 'Error occured. 12-hour format should have am/pm time period.', array(), WATCHDOG_ERROR);
        $values['timepicker_options']['showOn'] = 'none';
      }
    }
    else {
      $values['timepicker_options']['showHours'] = FALSE;

      // Date Field may ask to enter values like :00am,
      // it's not supported by timepicker.
      if (strpos($date_entry_format, 'a') === FALSE) {
        $values['timepicker_options']['showPeriod'] = FALSE;
      }
      else {
        drupal_set_message(t("Timepicker can't be used when hours disabled and\n          am/pm period is enabled. To enable timepicker again, go to field settings,\n          enable hours attribute or change date entry format and change 'Show on'\n          setting state."), 'warning');
        $values['timepicker_options']['showOn'] = 'none';
      }
    }

    // If date field expect minutes, show minutes selector.
    // i = Minutes with leading zeros.
    if (stripos($date_entry_format, 'i') !== FALSE) {
      $values['timepicker_options']['showMinutes'] = TRUE;
    }
    else {
      $values['timepicker_options']['showMinutes'] = FALSE;
    }

    // Options that are not supported by the Date module:
    // Date module supports only colon as time separator.
    $values['timepicker_options']['timeSeparator'] = ':';

    // Date Popup Timepicker supports minutes without leading
    // zeros, but Date module only uses standard PHP Date options.
    $values['timepicker_options']['showMinutesLeadingZero'] = FALSE;

    // Period separator is not supported in Date module.
    $values['timepicker_options']['periodSeparator'] = '';

    // Only lowercase am/pm text allowed in Date module.
    $values['timepicker_options']['amPmText'] = [
      'am',
      'pm',
    ];
  }
  else {
    drupal_set_message(t("Timepicker can't be used with seconds and was\n      disabled. To enable timepicker again, go to field settings, disable\n      seconds attribute and change 'Show on' setting state."), 'warning');
    $values['timepicker_options']['showOn'] = 'none';
  }

  // Field validation by ron_s.
  // See https://www.drupal.org/project/date_popup_timepicker/issues/2561147.
  if ($values['timepicker_options']['showOn'] != 'none') {
    $options = $values['timepicker_options'];
    $format = '';
    if ($options['showHours']) {
      $format .= $options['showPeriod'] ? 'g' : 'H';
    }
    if ($options['showHours'] && $options['showMinutes']) {
      $format .= $options['timeSeparator'] . 'i';
    }
    elseif ($options['showMinutes']) {
      $format .= 'i';
    }
    if ($options['periodSeparator']) {
      $format .= $options['periodSeparator'];
    }

    // Date Popup Timepicker supports any period label,
    // but Date module only uses standard PHP Date options.
    // a = Lowercase am/pm
    // A = Uppercase AM/PM
    // \ = Escape words added as label.
    $period_label_error = FALSE;
    if ($options['showPeriod']) {

      // Capture matches when AM and PM periods text
      // includes an "am" or "pm" (case insensitive).
      preg_match('/^(.*)(am)(.*)$/i', $options['amPmText'][0], $am_matches);
      preg_match('/^(.*)(pm)(.*)$/i', $options['amPmText'][1], $pm_matches);

      // If either AM or PM periods text do not have a match,
      // determine if there is a match in one of them.
      if (empty($am_matches) || empty($pm_matches)) {

        // If there is an AM periods text format match,
        // use it to determine am/pm case.
        if (!empty($am_matches)) {
          if (strtoupper($am_matches[2]) == $am_matches[2]) {
            $format .= $am_matches[1] . 'A' . $am_matches[3];
          }
          else {
            $format .= $am_matches[1] . 'a' . $am_matches[3];
          }
        }
        elseif (!empty($pm_matches)) {
          if (strtoupper($pm_matches[2]) == $pm_matches[2]) {
            $format .= $pm_matches[1] . 'A' . $pm_matches[3];
          }
          else {
            $format .= $pm_matches[1] . 'a' . $pm_matches[3];
          }
        }
        elseif (!empty($options['amPmText'][0])) {
          $format .= preg_replace('/([a-z0-9])/i', '\\\\$1', $options['amPmText'][0]);
        }
        elseif (!empty($options['amPmText'][1])) {
          $format .= preg_replace('/([a-z0-9])/i', '\\\\$1', $options['amPmText'][1]);
        }
      }
      elseif ($am_matches[1] != $pm_matches[1] || $am_matches[3] != $pm_matches[3]) {
        form_error($element['timepicker_options']['amPmText'], t('Format of AM and PM periods text is inconsistent. Ensure that any text preceding and following the "AM" and "PM" are the same.'));
        $period_label_error = TRUE;
      }
      else {

        // Check if both AM and PM periods text are uppercase.
        if (strtoupper($am_matches[2]) == $am_matches[2] && strtoupper($pm_matches[2]) == $pm_matches[2]) {
          $format .= $am_matches[1] . 'A' . $am_matches[3];
        }
        elseif (strtoupper($am_matches[2]) != $am_matches[2] && strtoupper($pm_matches[2]) == $pm_matches[2] || strtoupper($am_matches[2]) == $am_matches[2] && strtoupper($pm_matches[2]) != $pm_matches[2]) {
          form_error($element['timepicker_options']['amPmText'], t('Format of AM and PM periods text is inconsistent. Ensure "AM" and "PM" are either both uppercase or both lowercase.'));
          $period_label_error = TRUE;
        }
        else {
          $format .= $am_matches[1] . 'a' . $am_matches[3];
        }
      }
    }

    // Compare Date Entry and Date Popup Timepicker formats.
    if (!$period_label_error && $format != $date_entry_format) {
      form_error($element['timepicker_options'], t('Date Popup Timepicker (@format) and Date Entry (@date_entry_format) formats do not match. They must have the same format, otherwise data entry errors will occur.', array(
        '@format' => $format,
        '@date_entry_format' => $date_entry_format,
      )));
    }
  }
}