View source
<?php
namespace Drupal\fullcalendar\Plugin\fullcalendar\type;
use Drupal\Core\Datetime\DateHelper;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Url;
use Drupal\fullcalendar\Plugin\FullcalendarBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
class FullCalendar extends FullcalendarBase implements ContainerFactoryPluginInterface {
use OptionsFormHelperTrait;
const FC_DOCS_URL = 'http://fullcalendar.io/docs';
const COMMA_REPLACEMENT = '_COMMA_';
protected $moduleHandler;
protected $languageManager;
public function __construct(array $configuration, $plugin_id, $plugin_definition, ModuleHandlerInterface $module_handler, LanguageManagerInterface $language_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->moduleHandler = $module_handler;
$this->languageManager = $language_manager;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('module_handler'), $container
->get('language_manager'));
}
public function defineOptions() {
return $this
->getDefaultOptions();
}
public function process(&$settings) {
static $fc_dom_id = 1;
if (empty($this->style->view->dom_id)) {
$this->style->view->dom_id = 'fc-' . $fc_dom_id++;
}
$options = $this->style->options;
unset($options['fields']);
$settings += $options + [
'view_name' => $this->style->view->storage
->id(),
'view_display' => $this->style->view->current_display,
];
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$style_plugin = $this->style;
$form['intro'] = [
'#markup' => $this
->t('Fullcalendar defaults have been provided where appropriate. See the "more info" links for the documentation of settings.'),
];
$form['google'] = $this
->getFieldsetElement($this
->t('Google Calendar Settings'), $this
->t('Display events from a public Google Calendar you have configured. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/google-calendar', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]));
$form['google']['googleCalendarApiKey'] = [
'#type' => 'textfield',
'#title' => $this
->t('Google Calendar API key'),
'#default_value' => $style_plugin->options['google']['googleCalendarApiKey'],
'#size' => '60',
'#fieldset' => 'google',
];
$form['google']['googleCalendarId'] = [
'#type' => 'textfield',
'#title' => $this
->t('Google Calendar ID(s)'),
'#description' => $this
->t('You can specify multiple, comma-separated Google Calendar IDs'),
'#default_value' => $style_plugin->options['google']['googleCalendarId'],
'#size' => '60',
'#fieldset' => 'google',
];
$form['toolbar'] = $this
->getFieldsetElement($this
->t('Toolbar'));
$form['header'] = [
'#type' => 'textfield',
'#title' => $this
->t('Header'),
'#description' => $this
->t("Defines the buttons and title at the top of the calendar. Enter comma-separated key:value pairs for object properties e.g. left: 'title', center: '', right: 'today prev,next' @more-info", [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/header', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['header'],
'#size' => '40',
'#fieldset' => 'toolbar',
];
$form['footer'] = [
'#type' => 'textfield',
'#title' => $this
->t('Footer'),
'#description' => $this
->t('Defines the controls at the bottom of the calendar. These settings accept the same exact values as the header option. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/footer', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['footer'],
'#size' => '40',
'#fieldset' => 'toolbar',
];
$form['titleFormat'] = $this
->getTitleFormatElement($style_plugin->options['titleFormat'], 'toolbar');
$form['titleRangeSeparator'] = [
'#type' => 'textfield',
'#title' => $this
->t('Title range separator'),
'#description' => $this
->t('Determines the separator text when formatting the date range in the toolbar title. Default: \\u2013 (en dash)'),
'#default_value' => $style_plugin->options['titleRangeSeparator'],
'#prefix' => '<div class="views-left-50">',
'#suffix' => '</div>',
'#size' => '40',
'#fieldset' => 'toolbar',
];
$form['buttonText'] = $this
->getButtonTextElement($style_plugin->options['buttonText'], 'toolbar');
$form['buttonIcons'] = [
'#type' => 'textfield',
'#title' => $this
->t('Button icons'),
'#description' => $this
->t("Icons that will be displayed in buttons of the header/footer. Enter comma-separated key:value pairs for object properties e.g. prev:'left-single-arrow', next:'right-single-arrow', prevYear:'left-double-arrow', nextYear:'right-double-arrow' @more-info", [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/buttonIcons', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['buttonIcons'],
'#prefix' => '<div class="views-left-50">',
'#suffix' => '</div>',
'#size' => '40',
'#fieldset' => 'toolbar',
];
$form['views'] = $this
->getFieldsetElement($this
->t('Views'), $this
->t('Select the Fullcalendar views to enable on this calendar.'));
$form['month_view'] = [
'#type' => 'checkbox',
'#title' => t('Month View'),
'#default_value' => $style_plugin->options['month_view'],
'#data_type' => 'bool',
'#fieldset' => 'views',
'#prefix' => '<div class="views-left-25">',
'#suffix' => '</div>',
];
$form['timegrid_view'] = [
'#type' => 'checkbox',
'#title' => t('TimeGrid View'),
'#default_value' => $style_plugin->options['timegrid_view'],
'#data_type' => 'bool',
'#fieldset' => 'views',
'#prefix' => '<div class="views-left-25">',
'#suffix' => '</div>',
];
$form['list_view'] = [
'#type' => 'checkbox',
'#title' => t('List View'),
'#default_value' => $style_plugin->options['list_view'],
'#data_type' => 'bool',
'#fieldset' => 'views',
'#prefix' => '<div class="views-left-25">',
'#suffix' => '</div>',
];
$form['daygrid_view'] = [
'#type' => 'checkbox',
'#title' => t('DayGrid View'),
'#default_value' => $style_plugin->options['daygrid_view'],
'#data_type' => 'bool',
'#fieldset' => 'views',
'#prefix' => '<div class="views-left-25">',
'#suffix' => '</div>',
];
$form['view_settings'] = $this
->getFieldsetElement($this
->t('View settings'), '', FALSE, '', [
'visible' => [
':input[name="style_options[month_view]"]' => [
'checked' => TRUE,
],
],
]);
$form['month_view_settings'] = $this
->getFieldsetElement($this
->t('Month View settings'), '', FALSE, 'view_settings', [
'visible' => [
':input[name="style_options[month_view]"]' => [
'checked' => TRUE,
],
],
]);
$form['month_view_settings']['fixedWeekCount'] = [
'#type' => 'checkbox',
'#title' => t('Number of weeks'),
'#description' => $this
->t('Determines the number of weeks displayed in a month view (true). If true, the calendar will always be 6 weeks tall. If false, the calendar will have either 4, 5, or 6 weeks, depending on the month.'),
'#default_value' => $style_plugin->options['month_view_settings']['fixedWeekCount'],
'#data_type' => 'bool',
'#fieldset' => 'month_view_settings',
'#prefix' => '<div class="views-left-50">',
'#suffix' => '</div>',
];
$form['month_view_settings']['showNonCurrentDates'] = [
'#type' => 'checkbox',
'#title' => t('Number of weeks'),
'#description' => $this
->t('In month view, whether dates in the previous or next month should be rendered at all. (true). Days that are disabled will not render events.'),
'#default_value' => $style_plugin->options['month_view_settings']['showNonCurrentDates'],
'#data_type' => 'bool',
'#fieldset' => 'month_view_settings',
'#prefix' => '<div class="views-left-50">',
'#suffix' => '</div>',
];
$form['timegrid_view_settings'] = $this
->getFieldsetElement($this
->t('TimeGrid View settings'), '', FALSE, 'view_settings', [
'visible' => [
':input[name="style_options[timegrid_view]"]' => [
'checked' => TRUE,
],
],
]);
$form['timegrid_view_settings']['allDaySlot'] = [
'#type' => 'checkbox',
'#title' => t('Display "all-day" slot'),
'#description' => $this
->t('Determines the number of weeks displayed in a month view (true). When hidden with false, all-day events will not be displayed in TimeGrid views.'),
'#default_value' => $style_plugin->options['timegrid_view_settings']['allDaySlot'],
'#data_type' => 'bool',
'#fieldset' => 'timegrid_view_settings',
];
$form['timegrid_view_settings']['allDayText'] = [
'#type' => 'textfield',
'#title' => $this
->t('"All-day" text'),
'#description' => $this
->t('The text titling the “all-day” slot at the top of the calendar (default: all-day).'),
'#default_value' => $style_plugin->options['timegrid_view_settings']['allDayText'],
'#size' => '40',
'#fieldset' => 'timegrid_view_settings',
];
$form['timegrid_view_settings']['slotEventOverlap'] = [
'#type' => 'checkbox',
'#title' => t('Determines if timed events in TimeGrid view should visually overlap.'),
'#description' => $this
->t('When set to true (the default), events will overlap each other.'),
'#default_value' => $style_plugin->options['timegrid_view_settings']['slotEventOverlap'],
'#data_type' => 'bool',
'#fieldset' => 'timegrid_view_settings',
];
$form['timegrid_view_settings']['timeGridEventMinHeight'] = [
'#type' => 'textfield',
'#title' => t('Guaranteed minimum height.'),
'#description' => $this
->t('Guarantees that events within the TimeGrid views will be a minimum height. An integer pixel value can be specified to force all TimeGrid view events to be at least the given pixel height. (default: null). If not specified (the default), all events will have a height determined by their start and end times.'),
'#default_value' => $style_plugin->options['timegrid_view_settings']['timeGridEventMinHeight'],
'#size' => '40',
'#fieldset' => 'timegrid_view_settings',
];
$form['list_view_settings'] = $this
->getFieldsetElement($this
->t('List View settings'), '', FALSE, 'view_settings', [
'visible' => [
':input[name="style_options[list_view]"]' => [
'checked' => TRUE,
],
],
]);
$form['list_view_settings']['listDayFormat'] = [
'#type' => 'textfield',
'#title' => t('Day format (left)'),
'#description' => $this
->t('A @more-info that affects the text on the left side of the day headings in list view. If false is specified, no text is displayed.', [
'@more-info' => Link::fromTextAndUrl($this
->t('Date Formatter'), Url::fromUri(self::FC_DOCS_URL . '/listDayFormat', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['list_view_settings']['listDayFormat'],
'#size' => '40',
'#fieldset' => 'list_view_settings',
];
$form['list_view_settings']['listDayAltFormat'] = [
'#type' => 'textfield',
'#title' => t('Day format (right)'),
'#description' => $this
->t('A @more-info that affects the text on the right side of the day headings in list view. If false is specified, no text is displayed.', [
'@more-info' => Link::fromTextAndUrl($this
->t('Date Formatter'), Url::fromUri(self::FC_DOCS_URL . '/listDayFormat', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['list_view_settings']['listDayAltFormat'],
'#size' => '40',
'#fieldset' => 'list_view_settings',
];
$form['list_view_settings']['noEventsMessage'] = [
'#type' => 'textfield',
'#title' => t('No events message'),
'#description' => $this
->t('The text that is displayed in the middle of list view, alerting the user that there are no events within the given range.'),
'#default_value' => $style_plugin->options['list_view_settings']['noEventsMessage'],
'#size' => '40',
'#fieldset' => 'list_view_settings',
];
$form['views_options'] = $this
->getFieldsetElement($this
->t('View-Specific Options'), $this
->t('Options that apply only to specific calendar views, provided as options objects in the views option, keyed by the name of the view. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/view-specific-options', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]));
$form['views_year'] = $this
->getFieldsetElement($this
->t('Year'), $this
->t('Options that apply only to Year views'), FALSE, 'views_options');
$form['views_year']['listYear_buttonText'] = $this
->getButtonTextElement($style_plugin->options['views_year']['listYear_buttonText'], 'views_year', $this
->t('Button text (Year - List)'));
$form['views_year']['listYear_titleFormat'] = $this
->getTitleFormatElement($style_plugin->options['views_year']['listYear_titleFormat'], 'views_year', $this
->t('Title format (Year - List)'));
$form['views_month'] = $this
->getFieldsetElement($this
->t('Month'), $this
->t('Options that apply only to Month views'), FALSE, 'views_options');
$form['views_month']['listMonth_buttonText'] = $this
->getButtonTextElement($style_plugin->options['views_month']['listMonth_buttonText'], 'views_month', $this
->t('Button text (Month - List)'));
$form['views_month']['listMonth_titleFormat'] = $this
->getTitleFormatElement($style_plugin->options['views_month']['listMonth_titleFormat'], 'views_month', $this
->t('Title format (Month - List)'));
$form['views_month']['dayGridMonth_buttonText'] = $this
->getButtonTextElement($style_plugin->options['views_month']['dayGridMonth_buttonText'], 'views_month', $this
->t('Button text (Month - Day Grid)'));
$form['views_month']['dayGridMonth_titleFormat'] = $this
->getTitleFormatElement($style_plugin->options['views_month']['dayGridMonth_titleFormat'], 'views_month', $this
->t('Title format (Month - Day Grid)'));
$form['views_month']['dayGridMonth_columnHeaderFormat'] = $this
->getColumnHeaderFormatElement($style_plugin->options['views_month']['dayGridMonth_columnHeaderFormat'], 'views_month', $this
->t('Column header format (Month - Day Grid)'));
$form['views_week'] = $this
->getFieldsetElement($this
->t('Week'), $this
->t('Options that apply only to Week views'), FALSE, 'views_options');
$form['views_week']['listWeek_buttonText'] = $this
->getButtonTextElement($style_plugin->options['views_week']['listWeek_buttonText'], 'views_week', $this
->t('Button text (Week - List)'));
$form['views_week']['listWeek_titleFormat'] = $this
->getTitleFormatElement($style_plugin->options['views_week']['listWeek_titleFormat'], 'views_week', $this
->t('Title format (Week - List)'));
$form['views_week']['dayGridWeek_buttonText'] = $this
->getButtonTextElement($style_plugin->options['views_week']['dayGridWeek_buttonText'], 'views_week', $this
->t('Button text (Week - Day Grid)'));
$form['views_week']['dayGridWeek_titleFormat'] = $this
->getTitleFormatElement($style_plugin->options['views_week']['dayGridWeek_titleFormat'], 'views_week', $this
->t('Title format (Week - Day Grid)'));
$form['views_week']['dayGridWeek_columnHeaderFormat'] = $this
->getColumnHeaderFormatElement($style_plugin->options['views_week']['dayGridWeek_columnHeaderFormat'], 'views_week', $this
->t('Column header format (Week - Day Grid)'));
$form['views_week']['timeGridWeek_buttonText'] = $this
->getButtonTextElement($style_plugin->options['views_week']['timeGridWeek_buttonText'], 'views_week', $this
->t('Button text (Week - Time Grid)'));
$form['views_week']['timeGridWeek_titleFormat'] = $this
->getTitleFormatElement($style_plugin->options['views_week']['timeGridWeek_titleFormat'], 'views_week', $this
->t('Title format (Week - Time Grid)'));
$form['views_week']['timeGridWeek_columnHeaderFormat'] = $this
->getColumnHeaderFormatElement($style_plugin->options['views_week']['timeGridWeek_columnHeaderFormat'], 'views_week', $this
->t('Column header format (Week - Time Grid)'));
$form['views_day'] = $this
->getFieldsetElement($this
->t('Day'), $this
->t('Options that apply only to Day views'), FALSE, 'views_options');
$form['views_day']['listDay_buttonText'] = $this
->getButtonTextElement($style_plugin->options['views_day']['listDay_buttonText'], 'views_day', $this
->t('Button text (Day - List)'));
$form['views_day']['listDay_titleFormat'] = $this
->getTitleFormatElement($style_plugin->options['views_day']['listDay_titleFormat'], 'views_day', $this
->t('Title format (Day - List)'));
$form['views_day']['dayGridDay_buttonText'] = $this
->getButtonTextElement($style_plugin->options['views_day']['dayGridDay_buttonText'], 'views_day', $this
->t('Button text (Day - Day Grid)'));
$form['views_day']['dayGridDay_titleFormat'] = $this
->getTitleFormatElement($style_plugin->options['views_day']['dayGridDay_titleFormat'], 'views_day', $this
->t('Title format (Day - Day Grid)'));
$form['views_day']['dayGridDay_columnHeaderFormat'] = $this
->getColumnHeaderFormatElement($style_plugin->options['views_day']['dayGridDay_columnHeaderFormat'], 'views_day', $this
->t('Column header format (Day - Day Grid)'));
$form['views_day']['timeGridDay_buttonText'] = $this
->getButtonTextElement($style_plugin->options['views_day']['timeGridDay_buttonText'], 'views_day', $this
->t('Button text (Day - Time Grid)'));
$form['views_day']['timeGridDay_titleFormat'] = $this
->getTitleFormatElement($style_plugin->options['views_day']['timeGridDay_titleFormat'], 'views_day', $this
->t('Title format (Day - Time Grid)'));
$form['views_day']['timeGridDay_columnHeaderFormat'] = $this
->getColumnHeaderFormatElement($style_plugin->options['views_day']['timeGridDay_columnHeaderFormat'], 'views_day', $this
->t('Column header format (Day - Time Grid)'));
$form['display'] = $this
->getFieldsetElement($this
->t('Display settings'));
$form['display']['defaultView'] = [
'#type' => 'select',
'#title' => $this
->t('Initial display'),
'#options' => [
'dayGridMonth' => $this
->t('Month'),
'timeGridWeek' => $this
->t('Week (Agenda)'),
'dayGridWeek' => $this
->t('Week (Basic)'),
'timeGridDay' => $this
->t('Day (Agenda)'),
'dayGridDay' => $this
->t('Day (Basic)'),
'listYear' => $this
->t('Year (List)'),
'listMonth' => $this
->t('Month (List)'),
'listWeek' => $this
->t('Week (List)'),
'listDay' => $this
->t('Day (List)'),
],
'#empty_option' => $this
->t('- Select -'),
'#description' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/intro', [
'attributes' => [
'target' => '_blank',
],
])),
'#default_value' => $style_plugin->options['display']['defaultView'],
'#prefix' => '<div class="views-left-30">',
'#suffix' => '</div>',
'#fieldset' => 'display',
];
$form['display']['firstDay'] = [
'#type' => 'select',
'#title' => $this
->t('Week starts on'),
'#options' => DateHelper::weekDays(TRUE),
'#default_value' => $style_plugin->options['display']['firstDay'],
'#prefix' => '<div class="views-left-30">',
'#suffix' => '</div>',
'#fieldset' => 'display',
];
$form['times'] = $this
->getFieldsetElement($this
->t('Date & Time Display'), $this
->t('Settings that control presence/absence of dates as well as their styling and text. These settings work across a variety of different views. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/date-display', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]));
$form['times']['weekends'] = [
'#type' => 'checkbox',
'#title' => t('Weekends'),
'#description' => $this
->t('Whether to include Saturday/Sunday columns in any of the calendar views (true).'),
'#default_value' => $style_plugin->options['times']['weekends'],
'#data_type' => 'bool',
'#fieldset' => 'times',
];
$form['times']['hiddenDays'] = [
'#type' => 'textfield',
'#title' => t('Exclude days'),
'#description' => $this
->t('Exclude certain days-of-the-week from being displayed. By default, no days are hidden, unless weekends is set to false. Enter comma-separated numbers e.g. 2, 4 @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/hiddenDays', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['times']['hiddenDays'],
'#size' => '40',
'#fieldset' => 'times',
];
$form['times']['columnHeader'] = [
'#type' => 'checkbox',
'#title' => t('Column header'),
'#description' => $this
->t('Whether the day headers should appear. For the Month, TimeGrid, and DayGrid views (true).'),
'#default_value' => $style_plugin->options['times']['columnHeader'],
'#data_type' => 'bool',
'#fieldset' => 'times',
];
$form['axis'] = $this
->getFieldsetElement($this
->t('Time-axis settings'), $this
->t('Settings that control display of times along the side of the calendar. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/date-display', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]));
$form['axis']['slotDuration'] = [
'#type' => 'textfield',
'#title' => t('Duration of slots'),
'#description' => $this
->t('The frequency for displaying time slots. (default: 00:30:00) @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/slotDuration', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['axis']['slotDuration'],
'#size' => '40',
'#fieldset' => 'axis',
];
$form['axis']['slotLabelInterval'] = [
'#type' => 'textfield',
'#title' => t('Interval of slot labels'),
'#description' => $this
->t('The frequency that the time slots should be labelled with text. If not specified, a reasonable value will be automatically computed based on slotDuration. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/slotLabelInterval', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['axis']['slotLabelInterval'],
'#size' => '40',
'#fieldset' => 'axis',
];
$form['axis']['slotLabelFormat'] = [
'#type' => 'textfield',
'#title' => t('Format of slot labels'),
'#description' => $this
->t('Determines the text that will be displayed within a time slot. Enter comma-separated, object properties e.g. hour:numeric, minute:2-digit, omitZeroMinute:true, meridiem:short @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/slotLabelFormat', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['axis']['slotLabelFormat'],
'#size' => '40',
'#fieldset' => 'axis',
];
$form['axis']['minTime'] = [
'#type' => 'textfield',
'#title' => t('First time slot'),
'#description' => $this
->t('Determines the first time slot that will be displayed for each day. (default: 00:00:00) @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/minTime', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['axis']['minTime'],
'#size' => '40',
'#fieldset' => 'axis',
];
$form['axis']['maxTime'] = [
'#type' => 'textfield',
'#title' => t('Last time slot'),
'#description' => $this
->t('Determines the last time slot that will be displayed for each day. This MUST be specified as an exclusive end time. (default: 24:00:00) @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/maxTime', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['axis']['maxTime'],
'#size' => '40',
'#fieldset' => 'axis',
];
$form['axis']['scrollTime'] = [
'#type' => 'textfield',
'#title' => t('Scroll time'),
'#description' => $this
->t('Determines how far forward the scroll pane is initially scrolled. The user will be able to scroll back to see events before this time. (default: 06:00:00) @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/scrollTime', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['axis']['scrollTime'],
'#size' => '40',
'#fieldset' => 'axis',
];
$form['nav'] = $this
->getFieldsetElement($this
->t('Date navigation'));
$form['nav']['defaultDate'] = [
'#type' => 'textfield',
'#title' => $this
->t('Default date'),
'#description' => $this
->t('The initial date displayed when the calendar first loads. When not specified, this value defaults to the current date. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/defaultDate', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['nav']['defaultDate'],
'#size' => '40',
'#fieldset' => 'nav',
];
$form['nav']['validRange'] = [
'#type' => 'textfield',
'#title' => $this
->t('Valid date range'),
'#description' => $this
->t('Limits which dates the user can navigate to and where events can go. Dates outside of the valid range will be grayed-out. Enter comma-separated key:value properties e.g. start:2017-05-01, end:2017-06-01 @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/validRange', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['nav']['validRange'],
'#size' => '40',
'#fieldset' => 'nav',
];
$form['links'] = $this
->getFieldsetElement($this
->t('Date Nav Links'));
$form['links']['navLinks'] = [
'#type' => 'checkbox',
'#title' => t('Enable nav links'),
'#description' => $this
->t('Determines if day names and week names are clickable. When true, day headings and weekNumbers will become clickable. Default: false. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/navLinks', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['links']['navLinks'],
'#data_type' => 'bool',
'#fieldset' => 'links',
];
$form['links']['navLinkDayClick'] = [
'#type' => 'textfield',
'#title' => $this
->t('Day click function'),
'#description' => $this
->t('Determines what happens upon a day heading nav-link click. By default, the user is taken to the first day-view that appears in the header. Enter the name of a function you have written for this feature. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/navLinkDayClick', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['links']['navLinkDayClick'],
'#size' => '40',
'#fieldset' => 'links',
'#states' => [
'visible' => [
':input[name="style_options[links][navLinks]"]' => [
'checked' => TRUE,
],
],
],
];
$form['links']['navLinkWeekClick'] = [
'#type' => 'textfield',
'#title' => $this
->t('Week click function'),
'#description' => $this
->t('Determines what happens upon a week-number nav-link click. By default, the user is taken to the a the first week-view that appears in the header. Enter the name of a function you have written for this feature. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/navLinkWeekClick', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['links']['navLinkWeekClick'],
'#size' => '40',
'#fieldset' => 'links',
'#states' => [
'visible' => [
':input[name="style_options[links][navLinks]"]' => [
'checked' => TRUE,
],
],
],
];
$form['week'] = $this
->getFieldsetElement($this
->t('Week Numbers'));
$form['week']['weekNumbers'] = [
'#type' => 'checkbox',
'#title' => t('Display week numbers'),
'#description' => $this
->t('Determines if week numbers should be displayed on the calendar. If set to true, week numbers will be displayed in a separate left column in the Month/DayGrid views as well as at the top-left corner of the TimeGrid views. Default: false. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/weekNumbers', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['week']['weekNumbers'],
'#data_type' => 'bool',
'#fieldset' => 'week',
];
$form['week']['weekNumbersWithinDays'] = [
'#type' => 'checkbox',
'#title' => t('Display week numbers in Month and DayGrid views'),
'#description' => $this
->t('Determines the styling for week numbers in Month and DayGrid views. Default: false. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/weekNumbersWithinDays', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['week']['weekNumbersWithinDays'],
'#data_type' => 'bool',
'#fieldset' => 'week',
];
$form['week']['weekNumberCalculation'] = [
'#type' => 'textfield',
'#title' => $this
->t('Week label'),
'#description' => $this
->t('The method for calculating week numbers that are displayed with the weekNumbers setting e.g. local, ISO, or name of function you have written for this feature. Default: "local" @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/weekNumberCalculation', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['week']['weekNumberCalculation'],
'#size' => '40',
'#fieldset' => 'week',
];
$form['week']['weekLabel'] = [
'#type' => 'textfield',
'#title' => $this
->t('Week label'),
'#description' => $this
->t('The heading text for week numbers. Also affects weeks in date formatting. Default: "W" @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/weekLabel', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['week']['weekLabel'],
'#size' => '40',
'#fieldset' => 'week',
];
$form['now'] = $this
->getFieldsetElement($this
->t('Now Indicator'));
$form['now']['nowIndicator'] = [
'#type' => 'checkbox',
'#title' => t('Now indicator'),
'#description' => $this
->t('Whether or not to display a marker indicating the current time. Default: false. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/nowIndicator', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['now']['nowIndicator'],
'#data_type' => 'bool',
'#fieldset' => 'now',
];
$form['now']['now'] = [
'#type' => 'checkbox',
'#title' => t('Now'),
'#description' => $this
->t('Explicitly sets the "today" date of the calendar - the day that is normally highlighted in yellow. Enter a @parsable-date or name of function you have written for this feature. @more-info', [
'@parsable-date' => Link::fromTextAndUrl($this
->t('parsable date'), Url::fromUri(self::FC_DOCS_URL . '/date-parsing', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/now', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['now']['now'],
'#data_type' => 'bool',
'#fieldset' => 'now',
];
$form['business'] = $this
->getFieldsetElement($this
->t('Business Hours'));
$form['business']['businessHours'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Business Hours'),
'#description' => $this
->t('Emphasizes certain time slots on the calendar. By default, Monday-Friday, 9am-5pm. For better control, see below. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/businessHours', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['business']['businessHours'],
'#data_type' => 'bool',
'#fieldset' => 'business',
];
$form['business']['businessHours2'] = [
'#type' => 'textfield',
'#title' => t('Business hours format'),
'#description' => $this
->t('For fine-grain control over business hours enter key:value pairs for object properties. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/businessHours', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['business']['businessHours2'],
'#size' => '40',
'#fieldset' => 'business',
'#states' => [
'visible' => [
':input[name="style_options[business][businessHours]"]' => [
'checked' => TRUE,
],
],
],
];
$form['style'] = $this
->getFieldsetElement($this
->t('Appearance/Sizing'));
$form['style']['themeSystem'] = [
'#type' => 'select',
'#title' => $this
->t('Theme'),
'#options' => [
'standard' => $this
->t('Standard'),
'bootstrap' => $this
->t('Bootstrap 4'),
],
'#default_value' => $style_plugin->options['style']['themeSystem'],
'#fieldset' => 'style',
];
$form['style']['height'] = [
'#type' => 'textfield',
'#title' => t('Height'),
'#description' => $this
->t('Sets the height of the entire calendar, including header and footer. Enter a number, "parent", "auto" or name of function you have written for this feature. Default: This option is unset and the calendar\'s height is calculated by aspectRatio. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/sizing', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['style']['height'],
'#size' => '40',
'#fieldset' => 'style',
];
$form['style']['contentHeight'] = [
'#type' => 'textfield',
'#title' => t('View area height'),
'#description' => $this
->t('Sets the height of the view area of the calendar. Enter a number, "auto" or name of function you have written for this feature. Default: This option is unset and the calendar\'s height is calculated by aspectRatio. @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/sizing', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['style']['contentHeight'],
'#size' => '40',
'#fieldset' => 'style',
];
$form['style']['aspectRatio'] = [
'#type' => 'textfield',
'#title' => t('Width-height ratio'),
'#description' => $this
->t('Sets the width-to-height aspect ratio of the calendar. Enter a float. Default: 1.35 @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/sizing', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['style']['aspectRatio'],
'#size' => '40',
'#fieldset' => 'style',
];
$form['style']['handleWindowResize'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Resize calendar'),
'#description' => $this
->t('Automatically resize the calendar when the browser window resizes. Default: true @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/sizing', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['style']['handleWindowResize'],
'#data_type' => 'bool',
'#fieldset' => 'style',
];
$form['style']['windowResizeDelay'] = [
'#type' => 'textfield',
'#title' => $this
->t('Resize delay'),
'#description' => $this
->t('The time the calendar will wait to adjust its size after a window resize occurs, in milliseconds. Default: 100 @more-info', [
'@more-info' => Link::fromTextAndUrl($this
->t('More info'), Url::fromUri(self::FC_DOCS_URL . '/sizing', [
'attributes' => [
'target' => '_blank',
],
]))
->toString(),
]),
'#default_value' => $style_plugin->options['style']['windowResizeDelay'],
'#size' => '40',
'#fieldset' => 'style',
];
$field_options = $style_plugin->displayHandler
->getFieldLabels();
$date_fields = $style_plugin
->parseFields();
$form['fields'] = $this
->getFieldsetElement($this
->t('Customise fields'), $this
->t('Customise the Drupal fields to use in the Calendar view.'));
$form['fields']['title'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Use a custom title'),
'#default_value' => $style_plugin->options['fields']['title'],
'#data_type' => 'bool',
'#fieldset' => 'fields',
];
$form['fields']['title_field'] = [
'#type' => 'select',
'#title' => $this
->t('Title field'),
'#options' => $field_options,
'#default_value' => $style_plugin->options['fields']['title_field'],
'#empty_option' => $this
->t('- Select -'),
'#description' => $this
->t('Choose the field with the custom title.'),
'#process' => [
'\\Drupal\\Core\\Render\\Element\\Select::processSelect',
],
'#states' => [
'visible' => [
':input[name="style_options[fields][title]"]' => [
'checked' => TRUE,
],
],
],
'#fieldset' => 'fields',
];
$form['fields']['url'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Use a custom URL'),
'#default_value' => $style_plugin->options['fields']['url'],
'#data_type' => 'bool',
'#fieldset' => 'fields',
];
$form['fields']['url_field'] = [
'#type' => 'select',
'#title' => $this
->t('URL field'),
'#options' => $field_options,
'#default_value' => $style_plugin->options['fields']['url_field'],
'#empty_option' => $this
->t('- Select -'),
'#description' => $this
->t('Choose the field with the custom link.'),
'#process' => [
'\\Drupal\\Core\\Render\\Element\\Select::processSelect',
],
'#states' => [
'visible' => [
':input[name="style_options[fields][url]"]' => [
'checked' => TRUE,
],
],
],
'#fieldset' => 'fields',
];
$form['fields']['date'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Use a custom date field'),
'#default_value' => $style_plugin->options['fields']['date'],
'#data_type' => 'bool',
'#fieldset' => 'fields',
];
$form['fields']['date_field'] = [
'#type' => 'select',
'#title' => $this
->t('Date fields'),
'#options' => $date_fields,
'#default_value' => $style_plugin->options['fields']['date_field'],
'#description' => $this
->t('Select one or more date fields.'),
'#multiple' => TRUE,
'#size' => count($date_fields),
'#process' => [
'\\Drupal\\Core\\Render\\Element\\Select::processSelect',
],
'#states' => [
'visible' => [
':input[name="style_options[fields][date]"]' => [
'checked' => TRUE,
],
],
],
'#fieldset' => 'fields',
];
if (empty($field_options)) {
$form['fields']['#description'] = $this
->t('All the options are hidden, you need to add fields first.');
$form['fields']['title']['#type'] = 'hidden';
$form['fields']['url']['#type'] = 'hidden';
$form['fields']['date']['#type'] = 'hidden';
$form['fields']['title_field']['#disabled'] = TRUE;
$form['fields']['url_field']['#disabled'] = TRUE;
$form['fields']['date_field']['#disabled'] = TRUE;
}
elseif (empty($date_fields)) {
$form['fields']['date']['#type'] = 'hidden';
$form['fields']['date_field']['#disabled'] = TRUE;
}
$form['#attached']['library'][] = 'fullcalendar/drupal.fullcalendar.admin';
}
public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = []) {
$options = $form_state
->getValue('style_options');
foreach ([
'title',
'url',
'date',
] as $field) {
if (empty($options['fields'][$field]) && isset($options['fields'][$field . '_field'])) {
unset($options['fields'][$field . '_field']);
}
}
}
public function preView(&$settings) {
$options = [];
if ($plugins = $this
->getEnabledFullcalendarPlugins($settings)) {
$options['plugins'] = $plugins;
}
$settings = $this
->filterSettings($settings);
$defaultKeys = $this
->getCalendarProperties();
if (isset($settings['buttonIcons'])) {
$_type = in_array($settings['buttonIcons'], [
'true',
'false',
]) ? 'scalar' : 'object';
$defaultKeys[$_type][] = 'buttonIcons';
unset($_type);
}
$views = [];
foreach ([
'views_year',
'views_month',
'views_week',
'views_day',
] as $_views) {
if (!empty($settings[$_views])) {
foreach ($settings[$_views] as $key => $value) {
list($_view, $_option) = explode('_', $key);
$array = $this
->convertKeyValuePairsToArray($value);
if ($_option === 'buttonText') {
$views[$_view][$array['key']] = $array['value'];
}
else {
$views[$_view][$_option][$array['key']] = $array['value'];
}
}
}
unset($settings[$_views]);
}
if ($views) {
$options['views'] = $views;
}
$settings = $this
->flattenMultidimensionalArray($settings);
$keys = array_keys($settings);
foreach ($defaultKeys as $type => $properties) {
foreach ($properties as $property) {
if (in_array($property, $keys)) {
switch ($type) {
case 'scalar':
switch ($settings[$property]) {
case 'true':
$value = TRUE;
break;
case 'false':
$value = FALSE;
break;
default:
$value = $settings[$property];
break;
}
$options[$property] = $value;
unset($value);
break;
case 'array':
$items = explode(',', $settings[$property]);
$options[$property] = array_map('trim', $items);
break;
case 'object':
$string = $this
->fixCommaSeparatedValues($settings[$property]);
$values = explode(',', $string);
foreach ($values as $value) {
$value = str_replace('_COMMA_', ',', $value);
$array = $this
->convertKeyValuePairsToArray($value);
$options[$property][$array['key']] = $array['value'];
}
break;
}
}
unset($settings[$property]);
}
}
$settings['options'] = $options;
}
public function filterSettings(array $settings) {
$defaults = [];
$_defaults = $this
->defineOptions();
foreach ($_defaults as $key => $value) {
if (isset($value['default'])) {
$defaults[$key] = $value['default'];
}
elseif (isset($value['contains'])) {
foreach ($value['contains'] as $key1 => $value1) {
$defaults[$key][$key1] = $value1['default'];
}
}
}
return $this
->arrayRecursiveDiff($settings, $defaults);
}
public function arrayRecursiveDiff($array1, $array2) {
$aReturn = [];
foreach ($array1 as $mKey => $mValue) {
if (array_key_exists($mKey, $array2)) {
if (is_array($mValue)) {
$aRecursiveDiff = $this
->arrayRecursiveDiff($mValue, $array2[$mKey]);
if (count($aRecursiveDiff)) {
$aReturn[$mKey] = $aRecursiveDiff;
}
}
else {
if ($mValue != $array2[$mKey]) {
$aReturn[$mKey] = $mValue;
}
}
}
else {
$aReturn[$mKey] = $mValue;
}
}
return $aReturn;
}
public function filterEmptyValue(&$array, $value, $depth1, $depth2 = '') {
if (!is_bool($value)) {
if (!strlen($value)) {
return;
}
}
if (!strlen($depth2)) {
$array[$depth1] = $value;
}
else {
$array[$depth1][$depth2] = $value;
}
}
public function convertKeyValuePairsToArray($value) {
if (strpos($value, self::COMMA_REPLACEMENT) === FALSE) {
$value = $this
->fixCommaSeparatedValues($value);
}
$items = explode(',', $value);
$items = array_map('trim', $items);
$array = [];
foreach ($items as $item) {
list($key, $value) = explode(':', $item);
$array['key'] = $key;
$array['value'] = str_replace("'", '', str_replace(self::COMMA_REPLACEMENT, ',', $value));
}
return $array;
}
public function fixCommaSeparatedValues($value) {
preg_match_all("/('[^',]+),([^']+')/", $value, $matches);
if ($matches) {
foreach ($matches[0] as $match) {
$_match = str_replace(',', self::COMMA_REPLACEMENT, $match);
$value = str_replace($match, $_match, $value);
}
}
return $value;
}
public function getEnabledFullcalendarPlugins($settings) {
$plugins = [];
$form_fields = [
'month_view' => 'dayGrid',
'timegrid_view' => 'timeGrid',
'list_view' => 'list',
'daygrid_view' => 'dayGrid',
];
foreach ($form_fields as $field => $fcPlugin) {
if (isset($settings[$field]) && (bool) $settings[$field] === TRUE) {
$plugins[] = $fcPlugin;
}
}
if (!empty($settings['google']['googleCalendarApiKey'])) {
$plugins[] = 'googleCalendar';
}
return $plugins;
}
}