View source
<?php
namespace Drupal\calendar\Plugin\views\style;
use Drupal\calendar\CalendarStyleInfo;
use Drupal\calendar\CalendarEvent;
use Drupal\Core\Form\FormStateInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\node\Plugin\views\row\NodeRow;
use Drupal\views\Plugin\views\row\Fields;
use Drupal\views\Plugin\views\style\StylePluginBase;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Link;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
class Calendar extends StylePluginBase implements ContainerFactoryPluginInterface {
protected $usesRowPlugin = TRUE;
protected $styleInfo;
protected $calendarHelper;
protected $usesRowClass = TRUE;
protected $defaultFieldLabels = FALSE;
protected $account;
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options);
if (empty($view->styleInfo)) {
$this->view->styleInfo = new CalendarStyleInfo();
}
$this->styleInfo =& $this->view->styleInfo;
}
public function __construct(array $configuration, $plugin_id, $plugin_definition, $account, $styleInfo, $calendarHelper) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->account = $account;
$this->styleInfo = $styleInfo;
$this->calendarHelper = $calendarHelper;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('current_user'), $container
->get('calendar.style_info'), $container
->get('calendar.helper'));
}
protected function getBaseEntityType() {
return $this->view
->getBaseEntityType()
->Id();
}
public function evenEmpty() {
return empty($this->definition['even empty']);
}
protected function renderLabel($rowentity) {
$entity_type = $this
->getBaseEntityType();
$entity_id = $rowentity
->Id();
if ($this->options['multi_allday_style'] === "1") {
$view_mode = $this->options['multi_allday_viewmode'];
$entity = \Drupal::entityTypeManager()
->getStorage($entity_type)
->load($entity_id);
$view_builder = \Drupal::entityTypeManager()
->getViewBuilder($entity_type);
$pre_render = $view_builder
->view($entity, $view_mode);
return render($pre_render);
}
else {
if ($this->options['multi_allday_title'] === "1") {
switch ($entity_type) {
case 'user':
$link = Link::createFromRoute($rowentity
->getTitle(), 'entity.user.canonical', [
'user' => $entity_id,
]);
break;
default:
$link = Link::createFromRoute($rowentity
->getTitle(), 'entity.node.canonical', [
'node' => $entity_id,
]);
}
return $link;
}
else {
return $rowentity
->getTitle();
}
}
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['granularity'] = [
'default' => 'month',
];
$options['day_name_size'] = [
'default' => 99,
];
$options['with_weekno'] = [
'default' => 0,
];
$options['mini'] = [
'default' => 0,
];
$options['multi_allday_style'] = [
'default' => 0,
];
$options['multi_allday_title'] = [
'default' => 0,
];
$options['granularity_links'] = [
'default' => [
'day' => '',
'week' => '',
],
];
$options['colors'] = [
'default' => '',
];
return $options;
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$form['granularity'] = [
'#title' => $this
->t('Calendar granularity'),
'#type' => 'select',
'#description' => $this
->t('Select the time period for this display.'),
'#default_value' => $this->options['granularity'],
'#options' => [
'day' => $this
->t('Day'),
'week' => $this
->t('Week'),
'month' => $this
->t('Month'),
'year' => $this
->t('Year'),
],
];
$form['day_name_size'] = [
'#title' => $this
->t('Calendar day of week names'),
'#default_value' => $this->options['day_name_size'],
'#type' => 'radios',
'#options' => [
1 => $this
->t('First letter of name'),
2 => $this
->t('First two letters of name'),
3 => $this
->t('Abbreviated name'),
99 => $this
->t('Full name'),
],
'#description' => $this
->t('The way day of week names should be displayed in a calendar.'),
'#states' => [
'visible' => [
':input[name="style_options[granularity]"]' => [
[
'value' => 'year',
],
[
'value' => 'month',
],
[
'value' => 'week',
],
],
],
],
];
$form['mini'] = [
'#title' => $this
->t('Display as mini calendar'),
'#default_value' => $this->options['mini'],
'#type' => 'radios',
'#options' => [
0 => $this
->t('No'),
1 => $this
->t('Yes'),
],
'#description' => $this
->t('Display the mini style calendar, with no item details. Suitable for a calendar displayed in a block.'),
'#dependency' => [
'edit-style-options-granularity' => [
'month',
],
],
'#states' => [
'visible' => [
':input[name="style_options[granularity]"]' => [
'value' => 'month',
],
],
],
];
$form['with_weekno'] = [
'#title' => $this
->t('Show week numbers'),
'#default_value' => $this->options['with_weekno'],
'#type' => 'radios',
'#options' => [
0 => $this
->t('No'),
1 => $this
->t('Yes'),
],
'#description' => $this
->t('Whether or not to show week numbers in the calendar.'),
];
$calendar_displays = $this->calendarHelper
->getCalendarDisplays();
$form['granularity_links'] = [
'#tree' => TRUE,
];
$options_week = [
$calendar_displays['week']['route'] => $calendar_displays['week']['title'],
];
$options_day = [
$calendar_displays['day']['route'] => $calendar_displays['day']['title'],
];
$form['granularity_links']['week'] = [
'#title' => $this
->t('Week link displays'),
'#type' => 'select',
'#default_value' => $this->options['granularity_links']['week'],
'#description' => $this
->t("Optionally select a View display to use for Week links."),
'#options' => [
'' => $this
->t('Select...'),
] + $options_week,
];
$form['granularity_links']['day'] = [
'#title' => $this
->t('Day link displays'),
'#type' => 'select',
'#default_value' => $this->options['granularity_links']['day'],
'#description' => $this
->t("Optionally select a View display to use for Day links."),
'#options' => [
'' => $this
->t('Select...'),
] + $options_day,
];
$form['multi_allday_style'] = [
'#title' => $this
->t('Multi- & allday style'),
'#default_value' => $this->options['multi_allday_style'],
'#type' => 'select',
'#options' => [
0 => $this
->t('Display multi- & allday item as title'),
1 => $this
->t('Display multi- & allday item as view mode'),
],
'#description' => $this
->t('Select how to show multi- & allday items.'),
'#states' => [
'visible' => [
':input[name="style_options[granularity]"]' => [
[
'value' => 'month',
],
[
'value' => 'week',
],
[
'value' => 'day',
],
],
],
],
];
$form['multi_allday_title'] = [
'#title' => $this
->t('Multi- & allday title style'),
'#default_value' => $this->options['multi_allday_title'],
'#type' => 'select',
'#options' => [
0 => $this
->t('Display title as plain text'),
1 => $this
->t('Display title as link to entity'),
],
'#description' => $this
->t('Select how titles are shown.'),
'#states' => [
'visible' => [
':input[name="style_options[multi_allday_style]"]' => [
[
'value' => 0,
],
],
],
],
];
$view_modes = \Drupal::service('entity_display.repository')
->getViewModes($this
->getBaseEntityType());
foreach ($view_modes as $mode => $settings) {
$options[$mode] = $settings['label'];
}
$form['multi_allday_viewmode'] = [
'#title' => $this
->t('Multi- & allday viewmode'),
'#default_value' => $this->options['multi_allday_title'],
'#type' => 'select',
'#options' => $options,
'#description' => $this
->t('Select viewmode for multi- & allday.'),
'#states' => [
'visible' => [
':input[name="style_options[multi_allday_style]"]' => [
[
'value' => 1,
],
],
],
],
];
$moduleHandler = \Drupal::service('module_handler');
if ($moduleHandler
->moduleExists('color_field')) {
$options = [];
$dependencies = $this->view->storage
->getDependencies();
$config = $dependencies['config'];
foreach ($config as $detail) {
if (substr($detail, 0, strlen('field_storage')) === 'field.storage') {
$field = \Drupal::entityTypeManager()
->getStorage('field_storage_config')
->load(substr($detail, 14));
if ($field
->getType() === 'color_field_type') {
$options[$field
->id()] = $field
->getName() . ' (' . $field
->id() . ')';
}
}
}
array_unshift($options, 'None.');
$form['colors'] = [
'#title' => $this
->t('Use a field for event colors'),
'#default_value' => $this->options['colors'],
'#type' => 'select',
'#options' => $options,
];
}
}
protected function renderTitle($rowentity) {
$entity_type = $this
->getBaseEntityType();
$entity_id = $rowentity
->Id();
if ($this->options['multi_allday_style'] === "1") {
$view_mode = $this->options['multi_allday_viewmode'];
$entity = \Drupal::entityTypeManager()
->getStorage($entity_type)
->load($entity_id);
$view_builder = \Drupal::entityTypeManager()
->getViewBuilder($entity_type);
$pre_render = $view_builder
->view($entity, $view_mode);
return render($pre_render);
}
else {
if ($this->options['multi_allday_title'] === "1") {
switch ($entity_type) {
case 'user':
$link = Link::createFromRoute($rowentity
->get('title')->value, 'entity.user.canonical', [
'user' => $entity_id,
]);
break;
default:
$link = Link::createFromRoute($rowentity
->get('title')->value, 'entity.node.canonical', [
'node' => $entity_id,
]);
}
return $link;
}
else {
return $rowentity
->get('title')->value;
}
}
}
public function render() {
$field_argument = NULL;
if (empty($this->view->argument)) {
return [];
}
$this->styleInfo
->setGranularity($this->options['granularity']);
$this->styleInfo
->setCalendarPopup($this->displayHandler
->getOption('calendar_popup'));
$this->styleInfo
->setDayNameSize($this->options['day_name_size']);
$this->styleInfo
->setMini($this->options['mini']);
$this->styleInfo
->setShowWeekNumbers($this->options['with_weekno']);
$this->styleInfo
->setColorField($this->options['colors']);
$this->styleInfo
->setWeekLink($this->options['granularity_links']['week']);
$this->styleInfo
->setDayLink($this->options['granularity_links']['day']);
$this->styleInfo
->setMultiAllDayStyle($this->options['multi_allday_style']);
$this->styleInfo
->setMultiAllDayTitle($this->options['multi_allday_title']);
$this->styleInfo
->setmultiAllDayViewMode($this->options['multi_allday_viewmode']);
$calendar_arguments = $this->calendarHelper
->getCalendarArguments($this->view);
$field_argument = $calendar_arguments[0]['field'];
$current_user = \Drupal::entityTypeManager()
->getStorage('user')
->load($this->account
->id());
if (!empty($current_user->timezone->value)) {
$tz_user = new \DateTimeZone($current_user->timezone->value);
$storagetime = new \DateTime('now', new \DateTimeZone(DateTimeItemInterface::STORAGE_TIMEZONE));
$tz_interval = \DateInterval::createFromDateString($tz_user
->getOffset($storagetime) . 'seconds');
}
else {
$tz_interval = \DateInterval::createFromDateString('0 seconds');
}
$granularity = $this->styleInfo
->getGranularity();
$color_field = $ref = NULL;
$color_info = explode('.', $this->styleInfo
->getColorField());
if (count($color_info) > 1) {
$entity_type = $color_info[0];
$color_field = $color_info[1];
if (isset($this->view->result[0]->_entity) && $this->view->result[0]->_entity
->getEntityTypeId() !== $entity_type) {
foreach ($this->view->relationship as $field_name => $field) {
if (isset($field->definition['entity type']) && $field->definition['entity type'] === $entity_type) {
$ref = $field_name;
}
elseif ($entity_type === 'group' && isset($color_field)) {
$ref = 'gid';
}
}
}
}
$caldays = $this->calendarHelper
->{$granularity}($this->view);
if (in_array($granularity, [
'week',
'day',
])) {
foreach ($caldays as $weekno => $data) {
foreach ($data['weekdays'] as $date => $day) {
if (is_numeric($date)) {
$caldays[$weekno]['weekdays'][(string) $date]['other'] = $this->calendarHelper
->buildDayHours();
}
}
}
}
foreach ($caldays as $weekno => $weekday) {
$year = $month = $week = $day_route = $week_route = NULL;
$year = $caldays[$weekno]['startweekdate']
->format('Y');
$month = $caldays[$weekno]['startweekdate']
->format('m');
$week = $weekno;
if (isset($this->options['granularity_links']['week'])) {
$week_route = $this->options['granularity_links']['week'];
}
if (isset($this->options['granularity_links']['day'])) {
$day_route = $this->options['granularity_links']['day'];
}
if ($this->styleInfo
->getShowWeekNumbers() === '1') {
$show_week = true;
}
else {
$show_week = NULL;
}
$caldays[$weekno]['linkdata'] = [
'year' => $year,
'month' => $month,
'week' => $week,
'show_week' => $show_week,
'week_route' => $week_route,
'day_route' => $day_route,
];
}
$events = [];
foreach ($this->view->result as $row) {
foreach ($row->_entity
->get($field_argument) as $delta => $item) {
$event = NULL;
if (isset($item->end_value) && isset($item->value)) {
$enddate = new DrupalDateTime($item->end_value);
$startdate = new DrupalDateTime($item->value);
$event = new CalendarEvent();
$event
->setId($row->_entity
->id());
$event
->setWeekno($this->calendarHelper::weekInfoDate($startdate)['weekno']);
$event
->setEndDate($enddate
->add($tz_interval));
$event
->setStartDate($startdate
->add($tz_interval));
$event
->setWeekno($this->calendarHelper::weekInfoDate($startdate)['weekno']);
if ($color_field) {
if ($ref && isset($row->_relationship_entities[$ref]->{$color_field}->color)) {
$event
->setColor($row->_relationship_entities[$ref]->{$color_field}->color);
}
elseif (isset($row->_entity->{$color_field}->color)) {
$event
->setColor($row->_entity->{$color_field}->color);
}
}
$event
->setRow($this->view->rowPlugin
->render($row));
if ($event
->getStartDate()
->format('Ymd') === $event
->getEndDate()
->format('Ymd')) {
$event
->setMultiDay(FALSE);
if ($event
->getStartDate()
->format('Hi') === '0000' && $event
->getEndDate()
->format('Hi') === '2359') {
$event
->setAllDay(TRUE);
$event
->setLabel(self::renderTitle($row->_entity));
}
else {
$event
->setAllDay(FALSE);
$event
->setLength($enddate
->diff($startdate));
}
}
else {
$event
->setMultiDay(TRUE);
$event
->setLabel(self::renderTitle($row->_entity));
$event
->setAllDay(FALSE);
}
}
elseif ($item->value) {
$event = new CalendarEvent();
$event
->setId($row->_entity
->id());
$startdate = new DrupalDateTime($item->value);
$event
->setStartDate($startdate
->add($tz_interval));
$event
->setWeekno($this->calendarHelper::weekInfoDate($startdate)['weekno']);
$event
->setMultiDay(FALSE);
$event
->setAllDay(FALSE);
$event
->setLabel($row->_entity
->get('title')->value);
$event
->setRow($this->view->rowPlugin
->render($row));
}
}
$events[] = $event;
if ($event
->getMultiDay()) {
$offset = $this->calendarHelper::weekInfoDate($event
->getStartDate())['startweekdate']
->diff($event
->getStartDate());
$event
->setOffSet($offset);
$diff = $event
->getStartDate()
->diff($event
->getEndDate());
if ($diff->d < 7 - $offset->d) {
$length = $event
->getStartDate()
->diff($event
->getEndDate());
}
elseif ($event
->getOffSet()->d > 0 || $event
->getOffSet()->h > 0) {
$days = 'P' . (7 - $event
->getOffSet()->d) . 'D';
$length = new \DateInterval($days);
}
else {
$length = new \DateInterval('P7D');
}
$event
->setLength($length);
if ($diff->d > $length->d) {
$year = $event
->getStartDate()
->format('Y');
$weekno = $event
->getWeekno();
$max = $weekno + (int) floor($diff->d / 7);
do {
$weekno++;
$week_start = $this->calendarHelper::weekInfo($year . $weekno)['startweekdate'];
$c_event = clone $event;
$c_event
->setStartDate($week_start);
$c_event
->setWeekno($weekno);
$c_event
->setOffset(new \DateInterval('P0D'));
$c_diff = $week_start
->diff($event
->getEndDate());
if ($c_diff->d > 7) {
$c_event
->setLength(new \DateInterval('P7D'));
}
else {
$c_event
->setLength($c_diff);
}
$events[] = $c_event;
} while ($weekno < $max);
}
}
}
foreach ($events as $event) {
if (isset($caldays[$event
->getWeekno()])) {
if ($event
->getMultiDay()) {
$caldays[$event
->getWeekno()]['weekdays'][$event
->getStartDate()
->format('Ymd')]['multiday'][$event
->getId()] = $event;
}
elseif ($event
->getAllDay()) {
$caldays[$event
->getWeekno()]['weekdays'][$event
->getStartDate()
->format('Ymd')]['allday'][$event
->getId()] = $event;
}
else {
if (in_array($granularity, [
'week',
'day',
])) {
if (array_key_exists($event
->getStartDate()
->format('H.i'), array_keys($caldays[$event
->getWeekno()]['weekdays'][$event
->getStartDate()
->format('Ymd')]['other']))) {
$caldays[$event
->getWeekno()]['weekdays'][$event
->getStartDate()
->format('Ymd')]['other'][$event
->getStartDate()
->format('H.i')][$event
->getId()] = $event;
}
else {
$nearest = $event
->getStartDate()
->format('H') . '.00';
$caldays[$event
->getWeekno()]['weekdays'][$event
->getStartDate()
->format('Ymd')]['other'][$nearest][$event
->getId()] = $event;
}
}
else {
$caldays[$event
->getWeekno()]['weekdays'][$event
->getStartDate()
->format('Ymd')]['other'][$event
->getId()] = $event;
}
}
}
}
$template = 'calendar_' . $this->styleInfo
->getGranularity();
if ($this->view->styleInfo
->getMini()) {
$template = 'calendar_mini_' . $this->styleInfo
->getGranularity();
}
$build = [
'#theme' => $template,
'#view' => $this->view,
'#options' => $this->options,
'#rows' => $caldays,
];
return $build;
}
}