You are here

public function Calendar::calendarBuildMonth in Calendar 8

Build one month.

1 call to Calendar::calendarBuildMonth()
Calendar::render in src/Plugin/views/style/Calendar.php
Render the display in this style.

File

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

Class

Calendar
Views style plugin for the Calendar module.

Namespace

Drupal\calendar\Plugin\views\style

Code

public function calendarBuildMonth() {
  $week_days = CalendarHelper::weekDays(TRUE);
  $week_days = CalendarHelper::weekDaysOrdered($week_days);

  // $month = date_format($this->curday, 'n');
  $current_day_date = $this->currentDay
    ->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);
  $today = new \DateTime();
  $today = $today
    ->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);
  $day = $this->currentDay
    ->format('j');
  $this->currentDay
    ->modify('-' . strval($day - 1) . ' days');
  $rows = [];
  do {
    $init_day = clone $this->currentDay;
    $month = $this->currentDay
      ->format('n');
    $week = CalendarHelper::dateWeek($current_day_date);
    $first_day = \Drupal::config('system.date')
      ->get('first_day');
    list($multiday_buckets, $singleday_buckets, $total_rows) = array_values($this
      ->calendarBuildWeek(TRUE));
    $output = [];
    $final_day = clone $this->currentDay;
    $iehint = 0;
    $max_multirow_count = 0;
    $max_singlerow_count = 0;
    for ($i = 0; $i < intval($total_rows + 1); $i++) {
      $inner = [];

      // If we're displaying the week number, add it as the first cell in the
      // week.
      if ($i == 0 && !empty($this->styleInfo
        ->isShowWeekNumbers()) && !in_array($this->dateInfo
        ->getGranularity(), [
        'day',
        'week',
      ])) {
        $url = CalendarHelper::getURLForGranularity($this->view, 'week', [
          $this->dateInfo
            ->getMinYear() . $week,
        ]);
        if (!empty($url)) {
          $week_number = [
            '#type' => 'link',
            '#url' => $url,
            '#title' => $week,
          ];
        }
        else {

          // Do not link week numbers, if week views are disabled.
          $week_number = $week;
        }
        $item = [
          'entry' => $week_number,
          'colspan' => 1,
          'rowspan' => $total_rows + 1,
          'id' => $this->view
            ->id() . '-weekno-' . $current_day_date,
          'class' => 'week',
        ];
        $inner[] = [
          '#theme' => 'calendar_month_col',
          '#item' => $item,
        ];
      }
      $this->currentDay = clone $init_day;

      // Move backwards to the first day of the week.
      $day_week_day = $this->currentDay
        ->format('w');
      $this->currentDay
        ->modify('-' . (7 + $day_week_day - $first_day) % 7 . ' days');
      foreach ($week_days as $week_day => $day_object) {
        $current_day_date = $this->currentDay
          ->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);
        $item = NULL;
        $in_month = !($current_day_date < $this->dateInfo
          ->getMinDate()
          ->format(DateTimeItemInterface::DATE_STORAGE_FORMAT) || $current_day_date > $this->dateInfo
          ->getMaxDate()
          ->format(DateTimeItemInterface::DATE_STORAGE_FORMAT) || $this->currentDay
          ->format('n') != $month);

        // Add the datebox.
        if ($i == 0) {
          $item = [
            'entry' => [
              '#theme' => 'calendar_datebox',
              '#date' => $current_day_date,
              '#view' => $this->view,
              '#items' => $this->items,
              '#selected' => $in_month ? (bool) (count($multiday_buckets[$week_day]) + count($singleday_buckets[$week_day])) : FALSE,
            ],
            'colspan' => 1,
            'rowspan' => 1,
            'class' => 'date-box',
            'date' => $current_day_date,
            'id' => $this->view
              ->id() . '-' . $current_day_date . '-date-box',
            'header_id' => $day_object
              ->render(),
            'day_of_month' => $this->currentDay
              ->format('j'),
          ];
          $item['class'] .= ($current_day_date == $today && $in_month ? ' today' : '') . ($current_day_date < $today ? ' past' : '') . ($current_day_date > $today ? ' future' : '') . ($this
            ->isPastMonth($this->currentDay
            ->format('n'), $month) ? ' past-month' : '') . ($this
            ->isFutureMonth($this->currentDay
            ->format('n'), $month) ? ' future-month' : '');
          if (count($singleday_buckets[$week_day]) == 0) {
            if ($max_multirow_count == 0) {
              $item['class'] .= ' no-entry';
            }
          }
        }
        else {
          $index = $i - 1;
          $multi_count = count($multiday_buckets[$week_day]);

          // Process multiday buckets first.
          if ($index < $multi_count) {

            // If this item is filled with either a blank or an entry.
            if ($multiday_buckets[$week_day][$index]['filled']) {

              // Add item and add class.
              $item = $multiday_buckets[$week_day][$index];
              $item['class'] = 'multi-day';
              $item['date'] = $current_day_date;

              // Check wheter this is an entry.
              if (!$multiday_buckets[$week_day][$index]['avail']) {

                // If the item either starts or ends on today,then add tags so
                // we can style the borders.
                if ($current_day_date == $today && $in_month) {
                  $item['class'] .= ' starts-today';
                }

                // Calculate on which day of this week this item ends on.
                $end_day = clone $this->currentDay;
                $span = $item['colspan'] - 1;
                $end_day
                  ->modify('+' . $span . ' day');
                $end_day_date = $end_day
                  ->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);

                // If it ends today, add class.
                if ($end_day_date == $today && $in_month) {
                  $item['class'] .= ' ends-today';
                }
              }
            }

            // If this is an actual entry, add classes regarding the state of
            // the item.
            if ($multiday_buckets[$week_day][$index]['avail']) {
              $item['class'] .= ' ' . $week_day . ' ' . $index . ' no-entry ';
              $item['class'] .= ($current_day_date == $today && $in_month ? ' today' : '') . ($current_day_date < $today ? ' past' : '') . ($current_day_date > $today ? ' future' : '') . ($this
                ->isPastMonth($this->currentDay
                ->format('n'), $month) ? ' past-month' : '') . ($this
                ->isFutureMonth($this->currentDay
                ->format('n'), $month) ? ' future-month' : '');
            }
          }
          elseif ($index == $multi_count) {
            $single_day_count = 0;
            $single_days = '';

            // If it's empty, add class.
            if (count($singleday_buckets[$week_day]) == 0) {
              if ($max_multirow_count == 0) {
                $class = $multi_count > 0 ? 'single-day no-entry noentry-multi-day' : 'single-day no-entry';
              }
              else {
                $class = 'single-day';
              }
            }
            else {
              $single_days = [];
              foreach ($singleday_buckets[$week_day] as $day) {
                foreach ($day as $event) {
                  $single_day_count++;
                  if (isset($event['more_link'])) {

                    // @todo more logic
                  }
                  else {
                    $single_days[] = $event['entry'];
                  }

                  // $single_days .= (isset($event['more_link'])) ? '<div class="calendar-more">' . $event['entry'] . '</div>' : $event['entry'];
                }
              }
              $class = 'single-day';
            }
            $rowspan = $total_rows - $index;
            $item = [
              'entry' => $single_days,
              'colspan' => 1,
              'rowspan' => $rowspan,
              'class' => $class,
              'date' => $current_day_date,
              'id' => $this->view
                ->id() . '-' . $current_day_date . '-' . $index,
              'header_id' => $week_days[$week_day],
              'day_of_month' => $this->currentDay
                ->format('j'),
            ];

            // Hack for ie to help it properly space single day rows.
            // @todo do we still need this?
            if ($rowspan > 1 && $in_month && $single_day_count > 0) {
              $max_multirow_count = max($max_multirow_count, $single_day_count);
            }
            else {
              $max_singlerow_count = max($max_singlerow_count, $single_day_count);
            }

            // If the single row is bigger than the multi-row, then null out
            // ieheight - I'm estimating that a single row is twice the size
            // of multi-row. This is really the best that can be done with ie.
            if ($max_singlerow_count >= $max_multirow_count || $max_multirow_count <= $multi_count / 2) {
              $iehint = 0;
            }
            elseif ($rowspan > 1 && $in_month && $single_day_count > 0) {

              // Calculate how many rows we need to adjust.
              $iehint = max($iehint, $rowspan - 1);
            }

            // Set the class.
            $item['class'] .= ($current_day_date == $today && $in_month ? ' today' : '') . ($current_day_date < $today ? ' past' : '') . ($current_day_date > $today ? ' future' : '') . ($this
              ->isPastMonth($this->currentDay
              ->format('n'), $month) ? ' past-month' : '') . ($this
              ->isFutureMonth($this->currentDay
              ->format('n'), $month) ? ' future-month' : '');
          }
        }

        // If there isn't an item, then add empty class.
        if ($item != NULL) {
          if (!$in_month) {
            $item['class'] .= ' empty';
          }

          // Style this entry - it will be a <td>.
          $inner[] = [
            '#theme' => 'calendar_month_col',
            '#item' => $item,
          ];
        }
        $this->currentDay
          ->modify('+1 day');
      }
      if ($i == 0) {
        $output[] = [
          '#theme' => 'calendar_month_row',
          '#inner' => $inner,
          '#class' => 'date-box',
          '#iehint' => $iehint,
        ];
      }
      elseif ($i == $total_rows) {
        $output[] = [
          '#theme' => 'calendar_month_row',
          '#inner' => $inner,
          '#class' => 'single-day',
          '#iehint' => $iehint,
        ];
        $iehint = 0;
        $max_singlerow_count = 0;
        $max_multirow_count = 0;
      }
      else {

        // Style all the columns into a row.
        $output[] = [
          '#theme' => 'calendar_month_row',
          '#inner' => $inner,
          '#class' => 'multi-day',
          '#iehint' => 0,
        ];
      }
    }
    $this->currentDay = $final_day;

    // Add the row into the row array.
    $rows[] = [
      'data' => $output,
    ];
    $current_day_date = $this->currentDay
      ->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);
    $current_day_month = $this->currentDay
      ->format('n');
  } while ($current_day_month == $month && $current_day_date <= $this->dateInfo
    ->getMaxDate()
    ->format(DateTimeItemInterface::DATE_STORAGE_FORMAT));

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