You are here

public function Calendar::render in Calendar 8

Same name in this branch
  1. 8 src/Plugin/views/style/Calendar.php \Drupal\calendar\Plugin\views\style\Calendar::render()
  2. 8 src/Plugin/views/row/Calendar.php \Drupal\calendar\Plugin\views\row\Calendar::render()
Same name and namespace in other branches
  1. 8.2 src/Plugin/views/style/Calendar.php \Drupal\calendar\Plugin\views\style\Calendar::render()

Render the display in this style.

Overrides StylePluginBase::render

File

src/Plugin/views/style/Calendar.php, line 521

Class

Calendar
Views style plugin for the Calendar module.

Namespace

Drupal\calendar\Plugin\views\style

Code

public function render() {

  // @todo Move to $this->validate()
  if (empty($this->view->rowPlugin) || !$this
    ->hasCalendarRowPlugin()) {
    debug('\\Drupal\\calendar\\Plugin\\views\\style\\CalendarStyle: The calendar row plugin is required when using the calendar style, but it is missing.');
    return;
  }
  if (!($argument = CalendarHelper::getDateArgumentHandler($this->view))) {
    debug('\\Drupal\\calendar\\Plugin\\views\\style\\CalendarStyle: A calendar date argument is required when using the calendar style, to add a date argument in a view, please go to Advanced > Contextual Filters on the views configuration panel.');
    return;
  }
  if (!$argument
    ->validateValue()) {
    if (!$argument
      ->getDateArg()
      ->getValue()) {
      $msg = 'No calendar date argument value was provided.';
    }
    else {
      $msg = $this
        ->t('The value <strong>@value</strong> is not a valid date argument for @granularity', [
        '@value' => $argument
          ->getDateArg()
          ->getValue(),
        '@granularity' => $argument
          ->getGranularity(),
      ]);
    }
    $this->messenger
      ->addError($msg);
    return;
  }

  // Add information from the date argument to the view.
  $this->dateInfo
    ->setGranularity($argument
    ->getGranularity());
  $this->dateInfo
    ->setCalendarType($this->options['calendar_type']);
  $this->dateInfo
    ->setDateArgument($argument
    ->getDateArg());
  $this->dateInfo
    ->setMinYear($argument
    ->getMinDate()
    ->format('Y'));
  $this->dateInfo
    ->setMinMonth($argument
    ->getMinDate()
    ->format('n'));
  $this->dateInfo
    ->setMinDay($argument
    ->getMinDate()
    ->format('j'));

  // @todo We shouldn't use DATETIME_DATE_STORAGE_FORMAT.
  $this->dateInfo
    ->setMinWeek(CalendarHelper::dateWeek(date_format($argument
    ->getMinDate(), DateTimeItemInterface::DATE_STORAGE_FORMAT)));

  // $this->dateInfo->setRange($argument->options['calendar']['date_range']);
  $this->dateInfo
    ->setMinDate($argument
    ->getMinDate());
  $this->dateInfo
    ->setMaxDate($argument
    ->getMaxDate());

  // @todo implement limit
  //   $this->dateInfo->limit = $argument->limit;
  // @todo What if the display doesn't have a route?
  // $this->dateInfo->url = $this->view->getUrl();
  $this->dateInfo
    ->setForbid(isset($argument
    ->getDateArg()->forbid) ? $argument
    ->getDateArg()->forbid : FALSE);

  // Add calendar style information to the view.
  $this->styleInfo
    ->setCalendarPopup($this->displayHandler
    ->getOption('calendar_popup'));
  $this->styleInfo
    ->setMonthNameSize($this->options['month_name_size']);
  $this->styleInfo
    ->setNameSize($this->options['name_size']);
  $this->styleInfo
    ->setMini($this->options['mini']);
  $this->styleInfo
    ->setShowWeekNumbers($this->options['with_weekno']);
  $this->styleInfo
    ->setMultiDayTheme($this->options['multiday_theme']);
  $this->styleInfo
    ->setThemeStyle($this->options['theme_style']);
  $this->styleInfo
    ->setMaxItems($this->options['max_items']);
  $this->styleInfo
    ->setMaxItemsStyle($this->options['max_items_behavior']);
  if (!empty($this->options['groupby_times_custom'])) {
    $this->styleInfo
      ->setGroupByTimes(explode(',', $this->options['groupby_times_custom']));
  }
  else {
    $this->styleInfo
      ->setGroupByTimes(calendar_groupby_times($this->options['groupby_times']));
  }
  $this->styleInfo
    ->setCustomGroupByField($this->options['groupby_field']);

  // @todo make this an option setting.
  $this->styleInfo
    ->setShowEmptyTimes(!empty($this->options['groupby_times_custom']) ? TRUE : FALSE);

  // Set up parameters for the current view that can be used by row plugin.
  $display_timezone = date_timezone_get($this->dateInfo
    ->getMinDate());
  $this->dateInfo
    ->setTimezone($display_timezone);

  // @todo min and max date timezone info shouldn't be stored separately.
  $date = clone $this->dateInfo
    ->getMinDate();
  date_timezone_set($date, $display_timezone);

  // $this->dateInfo->min_zone_string = date_format($date, DATETIME_DATE_STORAGE_FORMAT);
  $date = clone $this->dateInfo
    ->getMaxDate();
  date_timezone_set($date, $display_timezone);

  // $this->dateInfo->max_zone_string = date_format($date, DATETIME_DATE_STORAGE_FORMAT);
  // Let views render fields the way it thinks they should look before we
  // start massaging them.
  $this
    ->renderFields($this->view->result);

  // Invoke the row plugin to massage each result row into calendar items.
  // Gather the row items into an array grouped by date and time.
  $items = [];
  foreach ($this->view->result as $row_index => $row) {
    $this->view->row_index = $row_index;
    $events = $this->view->rowPlugin
      ->render($row);

    // @todo Check what comes out here.

    /** @var \Drupal\calendar\CalendarEvent $event_info */
    foreach ($events as $event_info) {
      $item_start = $event_info->calendar_start_date
        ->format('Y-m-d');
      $item_end = $event_info->calendar_end_date
        ->format('Y-m-d');
      $time_start = $event_info->calendar_start_date
        ->format('H:i:s');
      $event_info
        ->setRenderedFields($this->rendered_fields[$row_index]);
      $items[$item_start][$time_start][] = $event_info;
    }
  }
  ksort($items);
  $rows = [];
  $this->currentDay = clone $this->dateInfo
    ->getMinDate();
  $this->items = $items;

  // Retrieve results array using method for the granularity of the display.
  switch ($this->options['calendar_type']) {
    case 'year':
      $rows = [];
      $this->styleInfo
        ->setMini(TRUE);
      for ($i = 1; $i <= 12; $i++) {
        $rows[$i] = $this
          ->calendarBuildMiniMonth();
      }
      $this->styleInfo
        ->setMini(FALSE);
      break;
    case 'month':
      $rows = !empty($this->styleInfo
        ->isMini()) ? $this
        ->calendarBuildMiniMonth() : $this
        ->calendarBuildMonth();
      break;
    case 'day':
      $rows = $this
        ->calendarBuildDay();
      break;
    case 'week':
      $rows = $this
        ->calendarBuildWeek();

      // Merge the day names in as the first row.
      $rows = array_merge([
        CalendarHelper::weekHeader($this->view),
      ], $rows);
      break;
  }

  // Send the sorted rows to the right theme for this type of calendar.
  $this->definition['theme'] = 'calendar_' . $this->options['calendar_type'];

  // Adjust the theme to match the currently selected default.
  // Only the month view needs the special 'mini' class,
  // which is used to retrieve a different, more compact, theme.
  if ($this->options['calendar_type'] == 'month' && !empty($this->styleInfo
    ->isMini())) {
    $this->definition['theme'] = 'calendar_mini';
  }
  elseif (in_array($this->options['calendar_type'], [
    'week',
    'day',
  ]) && !empty($this->options['multiday_theme']) && !empty($this->options['theme_style'])) {
    $this->definition['theme'] .= '_overlap';
  }
  $output = [
    '#theme' => $this
      ->themeFunctions(),
    '#view' => $this->view,
    '#options' => $this->options,
    '#rows' => $rows,
  ];
  unset($this->view->row_index);
  return $output;
}