You are here

public static function DurationElement::processElement in Duration Field 8.2

Same name and namespace in other branches
  1. 3.0.x src/Element/DurationElement.php \Drupal\duration_field\Element\DurationElement::processElement()

File

src/Element/DurationElement.php, line 83

Class

DurationElement
Defines the 'duration' form element.

Namespace

Drupal\duration_field\Element

Code

public static function processElement(&$element, FormStateInterface $form_state, &$complete_form) {
  $duration_service = \Drupal::service('duration_field.service');
  $granularity_service = \Drupal::service('duration_field.granularity.service');
  $value = FALSE;
  if (isset($element['#value']) && $element['#value']) {
    $value = $element['#value'];
  }
  elseif (isset($element['#default_value']) && $element['#default_value']) {
    $value = $element['#default_value'];
  }
  if (is_string($value) && !$duration_service
    ->checkDurationInvalid($value)) {
    $value = new DateInterval($value);
  }
  if (!$value) {
    $value = $duration_service
      ->createEmptyDateInterval();
  }

  // Create a wrapper for the elements. This is done in this manner
  // rather than nesting the elements in a wrapper with #prefix and #suffix
  // so as to not end up with [wrapper] as part of the name attribute
  // of the elements.
  $div = '<div';
  $classes = [
    'duration-inner-wrapper',
  ];
  if (!empty($element['#states'])) {
    self::processStates($element);
  }
  foreach ($element['#attributes'] as $attribute => $attribute_value) {
    if (is_string($attribute_value)) {
      $div .= ' ' . $attribute . "='" . $attribute_value . "'";
    }
    elseif ($attribute == 'class') {
      $classes = array_merge($classes, $attribute_value);
    }
  }
  $div .= ' class="' . implode(' ', $classes) . '"';
  $div .= '>';

  // For reasons that unfortunately I don't remember at this time, all
  // elements of $element need to be at the same level, and cannot be nested.
  // as such, the opening div wrapper is created as #markup, with the closing
  // wrapper to come after the content.
  $element['wrapper_open'] = [
    '#markup' => $div,
    '#weight' => -1,
  ];
  $time_mappings = [
    'y' => t('Years'),
    'm' => t('Months'),
    'd' => t('Days'),
    'h' => t('Hours'),
    'i' => t('Minutes'),
    's' => t('Seconds'),
  ];
  foreach ($time_mappings as $key => $label) {

    // Only include elements that are part of the given granularity.
    if ($granularity_service
      ->includeGranularityElement($key, $element['#granularity'])) {
      $element[$key] = [
        '#id' => $element['#id'] . '-' . $key,
        '#type' => 'number',
        '#title' => $label,
        // $value is a DateInterval object. This outputs the numeric value for
        // the key.
        '#default_value' => $value
          ->format('%' . $key),
        // Only require elements that are part of the given require elements
        // granularity.
        '#required' => $granularity_service
          ->includeGranularityElement($key, $element['#required_elements']),
        '#weight' => 0,
        '#min' => 0,
      ];

      // Apply the ajax of the main duration element to each granularity
      // input.
      if (!empty($element['#ajax'])) {
        $element[$info['key']]['#ajax'] = $element['#ajax'];
      }
    }
  }
  if (!empty($element['#date_increment']) && (int) $element['#date_increment'] > 0) {
    if ($element['#date_increment'] < 60) {
      if (!empty($element['s'])) {
        $element['s']['#step'] = $element['#date_increment'];
      }
    }
    elseif ($element['#date_increment'] < 3600) {
      if (!empty($element['i'])) {
        $element['i']['#step'] = (int) ($element['#date_increment'] / 60);
      }
    }
    elseif ($element['#date_increment'] < 86400) {
      if (!empty($element['h'])) {
        $element['h']['#step'] = (int) ($element['#date_increment'] / 3600);
      }
    }
    else {
      if (!empty($element['d'])) {
        $element['d']['#step'] = (int) ($element['#date_increment'] / 86400);
      }
    }
  }

  // The closing wrapper. See notes on the opening wrapper.
  $element['wrapper_close'] = [
    '#markup' => '</div>',
    '#weight' => 1,
  ];

  // Attach the CSS for the display of the output.
  $element['#attached']['library'][] = 'duration_field/element';
  return $element;
}