You are here

public function SmartDateRecurrenceFormatter::viewElements in Smart Date 3.3.x

Same name and namespace in other branches
  1. 8.2 modules/smart_date_recur/src/Plugin/Field/FieldFormatter/SmartDateRecurrenceFormatter.php \Drupal\smart_date_recur\Plugin\Field\FieldFormatter\SmartDateRecurrenceFormatter::viewElements()
  2. 3.x modules/smart_date_recur/src/Plugin/Field/FieldFormatter/SmartDateRecurrenceFormatter.php \Drupal\smart_date_recur\Plugin\Field\FieldFormatter\SmartDateRecurrenceFormatter::viewElements()
  3. 3.0.x modules/smart_date_recur/src/Plugin/Field/FieldFormatter/SmartDateRecurrenceFormatter.php \Drupal\smart_date_recur\Plugin\Field\FieldFormatter\SmartDateRecurrenceFormatter::viewElements()
  4. 3.1.x modules/smart_date_recur/src/Plugin/Field/FieldFormatter/SmartDateRecurrenceFormatter.php \Drupal\smart_date_recur\Plugin\Field\FieldFormatter\SmartDateRecurrenceFormatter::viewElements()
  5. 3.2.x modules/smart_date_recur/src/Plugin/Field/FieldFormatter/SmartDateRecurrenceFormatter.php \Drupal\smart_date_recur\Plugin\Field\FieldFormatter\SmartDateRecurrenceFormatter::viewElements()
  6. 3.4.x modules/smart_date_recur/src/Plugin/Field/FieldFormatter/SmartDateRecurrenceFormatter.php \Drupal\smart_date_recur\Plugin\Field\FieldFormatter\SmartDateRecurrenceFormatter::viewElements()

Overrides SmartDateTrait::viewElements

File

modules/smart_date_recur/src/Plugin/Field/FieldFormatter/SmartDateRecurrenceFormatter.php, line 103

Class

SmartDateRecurrenceFormatter
Plugin for a recurrence-optimized formatter for 'smartdate' fields.

Namespace

Drupal\smart_date_recur\Plugin\Field\FieldFormatter

Code

public function viewElements(FieldItemListInterface $items, $langcode) {
  $elements = [];

  // TODO: intellident switching between retrieval methods
  // Look for a defined format and use it if specified.
  $timezone_override = $this
    ->getSetting('timezone_override') ?: NULL;
  $format_label = $this
    ->getSetting('format');
  $add_classes = $this
    ->getSetting('add_classes');
  $time_wrapper = $this
    ->getSetting('time_wrapper');
  if ($format_label) {
    $format = SmartDateFormat::load($format_label);
    $settings = $format
      ->getOptions();
  }
  else {
    $settings = [
      'separator' => $this
        ->getSetting('separator'),
      'join' => $this
        ->getSetting('join'),
      'time_format' => $this
        ->getSetting('time_format'),
      'time_hour_format' => $this
        ->getSetting('time_hour_format'),
      'date_format' => $this
        ->getSetting('date_format'),
      'date_first' => $this
        ->getSetting('date_first'),
      'ampm_reduce' => $this
        ->getSetting('ampm_reduce'),
      'allday_label' => $this
        ->getSetting('allday_label'),
    ];
  }
  $rrules = [];
  foreach ($items as $delta => $item) {
    $timezone = $item->timezone ? $item->timezone : $timezone_override;
    if (empty($item->value) || empty($item->end_value)) {
      continue;
    }
    if (empty($item->rrule)) {

      // No rule so include the item directly.
      $elements[$delta] = static::formatSmartDate($item->value, $item->end_value, $settings, $timezone);
      if ($add_classes) {
        $this
          ->addRangeClasses($elements[$delta]);
      }
      if ($time_wrapper) {
        $this
          ->addTimeWrapper($elements[$delta], $item->value, $item->end_value, $timezone);
      }
    }
    else {

      // Uses a rule, so use a placeholder instead.
      if (!isset($rrules[$item->rrule])) {
        $elements[$delta] = $item->rrule;
        $rrules[$item->rrule]['delta'] = $delta;
      }

      // Add this instance to our array of instances for the rule.
      $rrules[$item->rrule]['instances'][] = $item;
    }
  }
  foreach ($rrules as $rrid => $rrule_collected) {
    $rrule_output = [
      '#theme' => 'smart_date_recurring_formatter',
    ];
    $instances = $rrule_collected['instances'];
    if (empty($instances)) {
      continue;
    }
    $delta = $rrule_collected['delta'];

    // Retrieve the text of the rrule.
    $rrule = SmartDateRule::load($rrid);
    if (empty($rrule)) {
      continue;
    }
    $rrule_output['#rule_text'] = $rrule
      ->getTextRule();

    // Get the specified number of past instances.
    $past_display = $this
      ->getSetting('past_display');
    if (in_array($rrule
      ->get('freq')
      ->getString(), [
      'MINUTELY',
      'HOURLY',
    ])) {
      $within_day = TRUE;
    }
    else {
      $within_day = FALSE;
    }
    if ($within_day) {

      // Output for dates recurring within a day.
      // Group the instances into days first.
      $instance_dates = [];
      $instances_nested = [];
      $comparison_date = 'Ymd';
      $comparison_format = $this
        ->settingsFormatNoTime($settings);
      $comparison_format['date_format'] = $comparison_date;

      // Group instances into days, make array of dates.
      foreach ($instances as $instance) {
        $this_comparison_date = static::formatSmartDate($instance->value, $instance->end_value, $comparison_format, $timezone, 'string');
        $instance_dates[$this_comparison_date] = (int) $this_comparison_date;
        $instances_nested[$this_comparison_date][] = $instance;
      }
      $instances = array_values($instances_nested);
      $next_index = $this
        ->findNextInstanceByDay(array_values($instance_dates), (int) date($comparison_date));
    }
    else {

      // Output for other recurrences frequencies.
      // Find the 'next' instance after now.
      $next_index = $this
        ->findNextInstance($instances);
    }

    // Display past instances if set and at least one instances in the past.
    if ($past_display && $next_index) {
      if ($next_index == -1) {
        $begin = count($instances) - $past_display;
      }
      else {
        $begin = $next_index - $past_display;
      }
      if ($begin < 0) {
        $begin = 0;
      }
      $past_instances = array_slice($instances, $begin, $past_display);
      $rrule_output['#past_display'] = [
        '#theme' => 'item_list',
        '#list_type' => 'ul',
      ];
      if ($within_day) {
        $items = $this
          ->formatWithinDay($past_instances, $settings);
      }
      else {
        $items = [];
        foreach ($past_instances as $key => $item) {
          $items[$key] = static::formatSmartDate($item->value, $item->end_value, $settings, $item->timezone);
          if ($add_classes) {
            $this
              ->addRangeClasses($items[$key]);
          }
          if ($time_wrapper) {
            $this
              ->addTimeWrapper($items[$key], $item->value, $item->end_value, $item->timezone);
          }
        }
      }
      foreach ($items as $item) {
        $rrule_output['#past_display']['#items'][] = [
          '#children' => $item,
          '#theme' => 'container',
        ];
      }
    }
    $upcoming_display = $this
      ->getSetting('upcoming_display');

    // Display upcoming instances if set and at least one instance upcoming.
    if ($upcoming_display && $next_index < count($instances) && $next_index != -1) {
      $upcoming_instances = array_slice($instances, $next_index, $upcoming_display);
      $rrule_output['#upcoming_display'] = [
        '#theme' => 'item_list',
        '#list_type' => 'ul',
      ];
      if ($within_day) {
        $items = $this
          ->formatWithinDay($upcoming_instances, $settings);
      }
      else {
        $items = [];
        foreach ($upcoming_instances as $key => $item) {
          $items[$key] = static::formatSmartDate($item->value, $item->end_value, $settings, $item->timezone);
          if ($add_classes) {
            $this
              ->addRangeClasses($items[$key]);
          }
          if ($time_wrapper) {
            $this
              ->addTimeWrapper($items[$key], $item->value, $item->end_value, $item->timezone);
          }
        }
      }
      foreach ($items as $item) {
        $rrule_output['#upcoming_display']['#items'][] = [
          '#children' => $item,
          '#theme' => 'container',
        ];
      }
      if ($this
        ->getSetting('show_next')) {
        $rrule_output['#next_display'] = array_shift($rrule_output['#upcoming_display']['#items']);
      }
    }
    $elements[$delta] = $rrule_output;
  }
  return $elements;
}