Loading office_hours.module +3 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,9 @@ use Drupal\Core\Form\FormStateInterface; // Add theme.api.php hooks. \Drupal::moduleHandler()->loadInclude('office_hours', 'inc', 'office_hours.theme'); // Add ExceptionItem third party settings. \Drupal::moduleHandler()->loadInclude('office_hours', 'inc', 'office_hours.exceptions.third_party'); /** * Implements hook_form_FORM_ID_alter(). * Loading src/Element/OfficeHoursExceptionsSlot.php 0 → 100644 +65 −0 Original line number Diff line number Diff line <?php namespace Drupal\office_hours\Element; use Drupal\Core\Form\FormStateInterface; use Drupal\office_hours\OfficeHoursDateHelper; /** * Provides a one-line text field form element for Exception days. * * @FormElement("office_hours_exceptions_slot") */ class OfficeHoursExceptionsSlot extends OfficeHoursWeekSlot { /** * {@inheritdoc} */ public static function processOfficeHoursSlot(&$element, FormStateInterface $form_state, &$complete_form) { // Update $element['#value'] with default data and prepare $element widget. parent::processOfficeHoursSlot($element, $form_state, $complete_form); // Facilitate Exception day specific things, such as changing date. $value = $element['#value']; $day = $value['day']; $day_delta = $element['#daydelta']; $default_day = (is_numeric($day)) ? date('Y-m-d', $day) : ''; $label = OfficeHoursDateHelper::getLabel('l', $value, $day_delta); if ($day_delta == 0) { // For first time slot of a day, set a 'date' select element + day name, // overriding the hidden (Week widget) or select (List widget) 'day'. // Override (hide) the 'day' select-field. $element['day'] = [ '#type' => 'date', '#prefix' => $day_delta ? "<div class='office-hours-more-label'>$label</div>" : "<div class='office-hours-label'>$label</div>", '#default_value' => $default_day, ]; } else { // Leave 'more slots' as-is, but overriding the value, // so all slots have same day number. $element['day'] = [ '#type' => 'hidden', '#prefix' => $day_delta ? "<div class='office-hours-more-label'>$label</div>" : "<div class='office-hours-label'>$label</div>", '#default_value' => $default_day, '#value' => $default_day, ]; } // Add 'day_delta' to facilitate ExceptionsSlot. // @todo This adds a loose column to the widget. Fix it, avoiding colspan. $element['day_delta'] = [ '#type' => 'value', // 'hidden', '#value' => $day_delta, ]; return $element; } } src/OfficeHoursExceptionsThirdPartySettings.php 0 → 100644 +335 −0 Original line number Diff line number Diff line <?php namespace Drupal\office_hours; use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\PluginSettingsBase; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; /** * A unit-testable wrapper class around third party settings hook logic. */ class OfficeHoursExceptionsThirdPartySettings { use StringTranslationTrait; /** * The plugin_id. * * @var string */ protected $pluginId; /** * The plugin (formatter, widget). * * @var \Drupal\office_hours\Plugin\Field\FieldFormatter\OfficeHoursFormatterBase */ protected $plugin; /** * The plugin implementation definition. * * @var array */ protected $pluginDefinition; /** * Configuration information passed into the plugin. * * When using an interface like * \Drupal\Component\Plugin\ConfigurableInterface, this is where the * configuration should be stored. * * Plugin configuration is optional, so plugin implementations must provide * their own setters and getters. * * @var array */ protected $configuration; /** * The field definition. * * @var \Drupal\Core\Field\FieldDefinitionInterface */ protected $fieldDefinition; /** * The viewMode. */ protected $viewMode; /** * The plugin (formatter/widget) settings. * * @var array */ protected $settings; /** * The third party settings. * * @var array */ protected $thirdPartySettings; /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * Office hours exceptions table constructor. * * @param $plugin string|\Drupal\office_hours\Plugin\Field\FieldFormatter\OfficeHoursFormatterBase * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * @param array $settings * @param $view_mode * @param array $third_party_settings * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager */ public function __construct($plugin, // $plugin_definition, $field_definition, array $settings, // $label, $view_mode, array $third_party_settings, EntityTypeManager $entity_type_manager) { // parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); // The following from pluginBase. // $this->configuration = $configuration; // Sometimes the plugin/formatter is not provided, and not needed. Use ID. $this->pluginId = is_string($plugin) ? $plugin : $plugin->getPluginId(); $this->plugin = is_string($plugin) ? NULL : $plugin; // $this->pluginDefinition = $plugin_definition; // // The following from FormatterBase. $this->fieldDefinition = $field_definition; $this->settings = $settings; // $this->label = $label; $this->viewMode = $view_mode; $this->thirdPartySettings = $third_party_settings; $this->entityTypeManager = $entity_type_manager; } /** * {@inheritdoc} */ public static function create(array $configuration, $plugin_id, $plugin_definition) { //public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $plugin_id, $configuration['field_definition'] ?? NULL, $configuration['settings'] ?? [], //$configuration['label'], $configuration['view_mode'] ?? [], $configuration['third_party_settings'] ?? [], \Drupal::service('entity_type.manager') // @todo Use $container->get('entity_type.manager'). ); } /** * {@inheritdoc} */ public static function defaultSettings() { return [ 'exceptions' => [ 'restrict_exceptions_to_num_days' => 7, 'date_format' => 'long', 'title' => 'Exception hours', ], ]; // + parent::defaultSettings(); } /** * {@inheritdoc} */ public function getThirdPartySettings($module = 'office_hours_exceptions') { $settings = $this->plugin->getThirdPartySettings($module); $settings += $this->defaultSettings()['exceptions']; return $settings; } /** * {@inheritdoc} */ public function formatterSettingsForm(PluginSettingsBase $plugin) { // public function settingsForm(FormatterInterface $plugin) {. // public function settingsForm(array $form, FormStateInterface $form_state) {. $settings = $this->getThirdPartySettings(); // Get the date formats. $formats = $this->entityTypeManager->getStorage('date_format')->loadMultiple(); // Set select list options for the date format. @todo OptionsProviderInterface. $options = []; foreach ($formats as $format) { $options[$format->id()] = $format->get('label'); } $element['exceptions'] = [ '#title' => $this->t('Exception day handling'), '#type' => 'details', '#open' => TRUE, ]; $element['exceptions']['restrict_exceptions_to_num_days'] = [ '#title' => $this->t('Restrict exceptions display to x days in future'), '#type' => 'number', // '#default_value' => $settings['exceptions']['restrict_exceptions_to_num_days'], '#default_value' => $settings['restrict_exceptions_to_num_days'], '#min' => 0, '#max' => 99, '#step' => 1, '#description' => $this->t("To enable Exception days, set a non-zero number (to be used in the formatter) and select an 'Exceptions' widget."), '#required' => TRUE, ]; // @todo Add link to admin/config/regional/date-time. $element['exceptions']['date_format'] = [ '#title' => $this->t('Date format for exception day'), '#type' => 'select', '#options' => $options, '#default_value' => $settings['date_format'], '#description' => $this->t("Maintain additional date formats <a href=':url'>here</a>.", [ ':url' => Url::fromRoute('entity.date_format.collection')->toString(), ]), '#required' => TRUE, ]; // @todo Move to field settings, since used in both Formatter and Widget. $element['exceptions']['title'] = [ '#title' => $this->t('Title for exceptions'), '#type' => 'textfield', '#default_value' => $settings['title'], '#description' => $this->t('Leave empty to display no title between weekdays and exception days.'), '#required' => FALSE, ]; return $element; } /** * {@inheritdoc} */ public function formatterSettingsSummary(&$summary) { // $summary = parent::settingsSummary(); $settings = $this->getThirdPartySettings(); $label = OfficeHoursDateHelper::getLabel($settings['date_format'], ['day' => strtotime('today midnight')]); $summary[] = $this->t("Show '@title' until @time days in the future.", [ '@time' => $settings['restrict_exceptions_to_num_days'], '@date' => $settings['date_format'], '@title' => $settings['title'] == '' ? $this->t('Exception days') : $this->t($settings['title']), ]) . ' ' . $this->t("Example: $label"); return $summary; } /** * {@inheritdoc} */ public function widgetSettingsForm(PluginSettingsBase $plugin) { $element['exceptions'] = []; return $element; } /** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items, $langcode, array &$elements) { if ($items->isEmpty()) { return $elements; } $settings = $this->settings; $third_party_settings = $this->thirdPartySettings; // Loop over formatters: $elements contains table/status/schema formatter. foreach ($elements as $key => &$element) if (is_numeric($key)) { switch ($element['content']['#theme']) { case 'office_hours_table': $formatter_rows = &$element['content']['#table']['#rows']; if ($formatter_rows) { $exception_exists = FALSE; // Check if an exception day exists in the table. foreach ($formatter_rows as $day => $item) { $is_exception_day = OfficeHoursDateHelper::isExceptionDay(['day' => $day]); $exception_exists |= $is_exception_day; } // If there is an exception, add a title for exceptions. // Add an extra row to label the exceptions. // Note: may be changed in template_preprocess_office_hours_table(). $label = $third_party_settings['title']; if ($exception_exists && $label) { $exception_header['data']['label']['data']['#markup'] = $label; $exception_header['class'] = [ 'office-hours__exceptions-label', ]; $exception_header['id'] = ['office-hours-exception__title']; // Keys 0-7 are for sorted weekdays, so adding our 8. $formatter_rows[8] = $exception_header; // Sort, to ensure that the header is before the exceptions. $formatter_rows = OfficeHoursDateHelper::weekDaysOrdered($formatter_rows, $settings['office_hours_first_day']); } } break; case 'office_hours': // Get Plain text formatter in Formatter::viewElements(). // $formatter_rows = &$element['#office_hours'] ?? NULL; // Get Plain text formatter in ThirdPartySettings::viewElements(). // @todo Perhaps better use new ['#office_hours_field']. $formatter_rows = &$element['content']['#office_hours']; if ($formatter_rows) { $exception_exists = FALSE; foreach ($formatter_rows as $day => $item) { // @todo rows vs. office_hours. $is_exception_day = OfficeHoursDateHelper::isExceptionDay(['day' => $day]); $exception_exists |= $is_exception_day; } // If there is an exception, add an extra row to label the exceptions. // Note: may be changed in template_preprocess_office_hours_table(). $label = $third_party_settings['title']; if ($exception_exists && $label) { // Set the title for the exceptions. $exception_header['title'] = $label; $exception_header['label'] = $label; // Set everything else to NULL. $exception_header['slots'] = NULL; $exception_header['formatted_slots'] = NULL; $exception_header['index'] = NULL; $exception_header['comments'] = NULL; // Keys 0-7 are for sorted weekdays, so adding our 8. $formatter_rows[8] = $exception_header; // Sort, to ensure that the header is before the exceptions. $formatter_rows = OfficeHoursDateHelper::weekDaysOrdered($formatter_rows, $settings['office_hours_first_day']); } } break; case 'office_hours_schema': // @todo Test/Enhance this formatter. case 'office_hours_status': // @todo Test/Enhance this formatter. default: break; } } return $elements; } } src/Plugin/Field/FieldType/OfficeHoursExceptionsItem.php 0 → 100644 +82 −0 Original line number Diff line number Diff line <?php namespace Drupal\office_hours\Plugin\Field\FieldType; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\office_hours\Plugin\Field\FieldType\OfficeHoursItem; /** * Plugin implementation of the 'office_hours' field type. * * @FieldType( * id = "office_hours_exceptions", * label = @Translation("Office hours exception day"), * list_class = "\Drupal\office_hours\Plugin\Field\FieldType\OfficeHoursItemList", * ) */ class OfficeHoursExceptionsItem extends OfficeHoursItem { /** * {@inheritdoc} */ public static function generateSampleValue(FieldDefinitionInterface $field_definition) { // @todo Add random Exception day value in past and in near future. $value = [ 'day' => mt_rand(0, 6), 'starthours' => mt_rand(00, 23) * 100, 'endhours' => mt_rand(00, 23) * 100, 'comment' => mt_rand(0, 1) ? 'additional exception text' : '', ]; return $value; } /** * {@inheritdoc} */ public function isExceptionDay() { return TRUE; } /** * Returns if a timestamp is in the past. * * @return bool * TRUE if the timestamp is in the past. */ public function isExceptionDayInPast() { $day = $this->getValue()['day']; if ($day < strtotime('today midnight')) { return TRUE; } return FALSE; } /** * Returns if a timestamp is in date range of x days to the future. * * Prerequisite: $item->isExceptionDay() must be TRUE. * * @param int $rangeInDays * The days into the future we want to check the timestamp against. * * @return bool * TRUE if the timestamp is in range. * TRUE if $rangeInDays has a negative value. */ public function isExceptionDayInRange($rangeInDays) { if ($rangeInDays <= 0) { return TRUE; } if ($this->isExceptionDayInPast()) { return FALSE; } $day = $this->getValue()['day']; $maxTime = time() + $rangeInDays * 24 * 60 * 60; if ($day > $maxTime) { return FALSE; } return TRUE; } } src/Plugin/Field/FieldType/OfficeHoursItemList.php +3 −3 Original line number Diff line number Diff line Loading @@ -49,10 +49,10 @@ class OfficeHoursItemList extends FieldItemList implements OfficeHoursItemListIn if (!$exceptions_list) { $pluginManager = \Drupal::service('plugin.manager.field.field_type'); // Get field definition of ExceptionsItem. $plugin_id = 'office_hours_exception'; $plugin_id = 'office_hours_exceptions'; $field_definition = BaseFieldDefinition::create($plugin_id); // Create an ItemList with ExceptionsItems. $exceptions_list = new OfficeHoursItemList($field_definition); // Create an ItemList with OfficeHoursExceptionsItem items. $exceptions_list = OfficeHoursItemList::createInstance($field_definition, $this->name, NULL); } // Then, add an item to the list with Exception day field definition. $item = $pluginManager->createFieldItem($exceptions_list, $offset, $value); Loading Loading
office_hours.module +3 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,9 @@ use Drupal\Core\Form\FormStateInterface; // Add theme.api.php hooks. \Drupal::moduleHandler()->loadInclude('office_hours', 'inc', 'office_hours.theme'); // Add ExceptionItem third party settings. \Drupal::moduleHandler()->loadInclude('office_hours', 'inc', 'office_hours.exceptions.third_party'); /** * Implements hook_form_FORM_ID_alter(). * Loading
src/Element/OfficeHoursExceptionsSlot.php 0 → 100644 +65 −0 Original line number Diff line number Diff line <?php namespace Drupal\office_hours\Element; use Drupal\Core\Form\FormStateInterface; use Drupal\office_hours\OfficeHoursDateHelper; /** * Provides a one-line text field form element for Exception days. * * @FormElement("office_hours_exceptions_slot") */ class OfficeHoursExceptionsSlot extends OfficeHoursWeekSlot { /** * {@inheritdoc} */ public static function processOfficeHoursSlot(&$element, FormStateInterface $form_state, &$complete_form) { // Update $element['#value'] with default data and prepare $element widget. parent::processOfficeHoursSlot($element, $form_state, $complete_form); // Facilitate Exception day specific things, such as changing date. $value = $element['#value']; $day = $value['day']; $day_delta = $element['#daydelta']; $default_day = (is_numeric($day)) ? date('Y-m-d', $day) : ''; $label = OfficeHoursDateHelper::getLabel('l', $value, $day_delta); if ($day_delta == 0) { // For first time slot of a day, set a 'date' select element + day name, // overriding the hidden (Week widget) or select (List widget) 'day'. // Override (hide) the 'day' select-field. $element['day'] = [ '#type' => 'date', '#prefix' => $day_delta ? "<div class='office-hours-more-label'>$label</div>" : "<div class='office-hours-label'>$label</div>", '#default_value' => $default_day, ]; } else { // Leave 'more slots' as-is, but overriding the value, // so all slots have same day number. $element['day'] = [ '#type' => 'hidden', '#prefix' => $day_delta ? "<div class='office-hours-more-label'>$label</div>" : "<div class='office-hours-label'>$label</div>", '#default_value' => $default_day, '#value' => $default_day, ]; } // Add 'day_delta' to facilitate ExceptionsSlot. // @todo This adds a loose column to the widget. Fix it, avoiding colspan. $element['day_delta'] = [ '#type' => 'value', // 'hidden', '#value' => $day_delta, ]; return $element; } }
src/OfficeHoursExceptionsThirdPartySettings.php 0 → 100644 +335 −0 Original line number Diff line number Diff line <?php namespace Drupal\office_hours; use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\PluginSettingsBase; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; /** * A unit-testable wrapper class around third party settings hook logic. */ class OfficeHoursExceptionsThirdPartySettings { use StringTranslationTrait; /** * The plugin_id. * * @var string */ protected $pluginId; /** * The plugin (formatter, widget). * * @var \Drupal\office_hours\Plugin\Field\FieldFormatter\OfficeHoursFormatterBase */ protected $plugin; /** * The plugin implementation definition. * * @var array */ protected $pluginDefinition; /** * Configuration information passed into the plugin. * * When using an interface like * \Drupal\Component\Plugin\ConfigurableInterface, this is where the * configuration should be stored. * * Plugin configuration is optional, so plugin implementations must provide * their own setters and getters. * * @var array */ protected $configuration; /** * The field definition. * * @var \Drupal\Core\Field\FieldDefinitionInterface */ protected $fieldDefinition; /** * The viewMode. */ protected $viewMode; /** * The plugin (formatter/widget) settings. * * @var array */ protected $settings; /** * The third party settings. * * @var array */ protected $thirdPartySettings; /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * Office hours exceptions table constructor. * * @param $plugin string|\Drupal\office_hours\Plugin\Field\FieldFormatter\OfficeHoursFormatterBase * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * @param array $settings * @param $view_mode * @param array $third_party_settings * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager */ public function __construct($plugin, // $plugin_definition, $field_definition, array $settings, // $label, $view_mode, array $third_party_settings, EntityTypeManager $entity_type_manager) { // parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); // The following from pluginBase. // $this->configuration = $configuration; // Sometimes the plugin/formatter is not provided, and not needed. Use ID. $this->pluginId = is_string($plugin) ? $plugin : $plugin->getPluginId(); $this->plugin = is_string($plugin) ? NULL : $plugin; // $this->pluginDefinition = $plugin_definition; // // The following from FormatterBase. $this->fieldDefinition = $field_definition; $this->settings = $settings; // $this->label = $label; $this->viewMode = $view_mode; $this->thirdPartySettings = $third_party_settings; $this->entityTypeManager = $entity_type_manager; } /** * {@inheritdoc} */ public static function create(array $configuration, $plugin_id, $plugin_definition) { //public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $plugin_id, $configuration['field_definition'] ?? NULL, $configuration['settings'] ?? [], //$configuration['label'], $configuration['view_mode'] ?? [], $configuration['third_party_settings'] ?? [], \Drupal::service('entity_type.manager') // @todo Use $container->get('entity_type.manager'). ); } /** * {@inheritdoc} */ public static function defaultSettings() { return [ 'exceptions' => [ 'restrict_exceptions_to_num_days' => 7, 'date_format' => 'long', 'title' => 'Exception hours', ], ]; // + parent::defaultSettings(); } /** * {@inheritdoc} */ public function getThirdPartySettings($module = 'office_hours_exceptions') { $settings = $this->plugin->getThirdPartySettings($module); $settings += $this->defaultSettings()['exceptions']; return $settings; } /** * {@inheritdoc} */ public function formatterSettingsForm(PluginSettingsBase $plugin) { // public function settingsForm(FormatterInterface $plugin) {. // public function settingsForm(array $form, FormStateInterface $form_state) {. $settings = $this->getThirdPartySettings(); // Get the date formats. $formats = $this->entityTypeManager->getStorage('date_format')->loadMultiple(); // Set select list options for the date format. @todo OptionsProviderInterface. $options = []; foreach ($formats as $format) { $options[$format->id()] = $format->get('label'); } $element['exceptions'] = [ '#title' => $this->t('Exception day handling'), '#type' => 'details', '#open' => TRUE, ]; $element['exceptions']['restrict_exceptions_to_num_days'] = [ '#title' => $this->t('Restrict exceptions display to x days in future'), '#type' => 'number', // '#default_value' => $settings['exceptions']['restrict_exceptions_to_num_days'], '#default_value' => $settings['restrict_exceptions_to_num_days'], '#min' => 0, '#max' => 99, '#step' => 1, '#description' => $this->t("To enable Exception days, set a non-zero number (to be used in the formatter) and select an 'Exceptions' widget."), '#required' => TRUE, ]; // @todo Add link to admin/config/regional/date-time. $element['exceptions']['date_format'] = [ '#title' => $this->t('Date format for exception day'), '#type' => 'select', '#options' => $options, '#default_value' => $settings['date_format'], '#description' => $this->t("Maintain additional date formats <a href=':url'>here</a>.", [ ':url' => Url::fromRoute('entity.date_format.collection')->toString(), ]), '#required' => TRUE, ]; // @todo Move to field settings, since used in both Formatter and Widget. $element['exceptions']['title'] = [ '#title' => $this->t('Title for exceptions'), '#type' => 'textfield', '#default_value' => $settings['title'], '#description' => $this->t('Leave empty to display no title between weekdays and exception days.'), '#required' => FALSE, ]; return $element; } /** * {@inheritdoc} */ public function formatterSettingsSummary(&$summary) { // $summary = parent::settingsSummary(); $settings = $this->getThirdPartySettings(); $label = OfficeHoursDateHelper::getLabel($settings['date_format'], ['day' => strtotime('today midnight')]); $summary[] = $this->t("Show '@title' until @time days in the future.", [ '@time' => $settings['restrict_exceptions_to_num_days'], '@date' => $settings['date_format'], '@title' => $settings['title'] == '' ? $this->t('Exception days') : $this->t($settings['title']), ]) . ' ' . $this->t("Example: $label"); return $summary; } /** * {@inheritdoc} */ public function widgetSettingsForm(PluginSettingsBase $plugin) { $element['exceptions'] = []; return $element; } /** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items, $langcode, array &$elements) { if ($items->isEmpty()) { return $elements; } $settings = $this->settings; $third_party_settings = $this->thirdPartySettings; // Loop over formatters: $elements contains table/status/schema formatter. foreach ($elements as $key => &$element) if (is_numeric($key)) { switch ($element['content']['#theme']) { case 'office_hours_table': $formatter_rows = &$element['content']['#table']['#rows']; if ($formatter_rows) { $exception_exists = FALSE; // Check if an exception day exists in the table. foreach ($formatter_rows as $day => $item) { $is_exception_day = OfficeHoursDateHelper::isExceptionDay(['day' => $day]); $exception_exists |= $is_exception_day; } // If there is an exception, add a title for exceptions. // Add an extra row to label the exceptions. // Note: may be changed in template_preprocess_office_hours_table(). $label = $third_party_settings['title']; if ($exception_exists && $label) { $exception_header['data']['label']['data']['#markup'] = $label; $exception_header['class'] = [ 'office-hours__exceptions-label', ]; $exception_header['id'] = ['office-hours-exception__title']; // Keys 0-7 are for sorted weekdays, so adding our 8. $formatter_rows[8] = $exception_header; // Sort, to ensure that the header is before the exceptions. $formatter_rows = OfficeHoursDateHelper::weekDaysOrdered($formatter_rows, $settings['office_hours_first_day']); } } break; case 'office_hours': // Get Plain text formatter in Formatter::viewElements(). // $formatter_rows = &$element['#office_hours'] ?? NULL; // Get Plain text formatter in ThirdPartySettings::viewElements(). // @todo Perhaps better use new ['#office_hours_field']. $formatter_rows = &$element['content']['#office_hours']; if ($formatter_rows) { $exception_exists = FALSE; foreach ($formatter_rows as $day => $item) { // @todo rows vs. office_hours. $is_exception_day = OfficeHoursDateHelper::isExceptionDay(['day' => $day]); $exception_exists |= $is_exception_day; } // If there is an exception, add an extra row to label the exceptions. // Note: may be changed in template_preprocess_office_hours_table(). $label = $third_party_settings['title']; if ($exception_exists && $label) { // Set the title for the exceptions. $exception_header['title'] = $label; $exception_header['label'] = $label; // Set everything else to NULL. $exception_header['slots'] = NULL; $exception_header['formatted_slots'] = NULL; $exception_header['index'] = NULL; $exception_header['comments'] = NULL; // Keys 0-7 are for sorted weekdays, so adding our 8. $formatter_rows[8] = $exception_header; // Sort, to ensure that the header is before the exceptions. $formatter_rows = OfficeHoursDateHelper::weekDaysOrdered($formatter_rows, $settings['office_hours_first_day']); } } break; case 'office_hours_schema': // @todo Test/Enhance this formatter. case 'office_hours_status': // @todo Test/Enhance this formatter. default: break; } } return $elements; } }
src/Plugin/Field/FieldType/OfficeHoursExceptionsItem.php 0 → 100644 +82 −0 Original line number Diff line number Diff line <?php namespace Drupal\office_hours\Plugin\Field\FieldType; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\office_hours\Plugin\Field\FieldType\OfficeHoursItem; /** * Plugin implementation of the 'office_hours' field type. * * @FieldType( * id = "office_hours_exceptions", * label = @Translation("Office hours exception day"), * list_class = "\Drupal\office_hours\Plugin\Field\FieldType\OfficeHoursItemList", * ) */ class OfficeHoursExceptionsItem extends OfficeHoursItem { /** * {@inheritdoc} */ public static function generateSampleValue(FieldDefinitionInterface $field_definition) { // @todo Add random Exception day value in past and in near future. $value = [ 'day' => mt_rand(0, 6), 'starthours' => mt_rand(00, 23) * 100, 'endhours' => mt_rand(00, 23) * 100, 'comment' => mt_rand(0, 1) ? 'additional exception text' : '', ]; return $value; } /** * {@inheritdoc} */ public function isExceptionDay() { return TRUE; } /** * Returns if a timestamp is in the past. * * @return bool * TRUE if the timestamp is in the past. */ public function isExceptionDayInPast() { $day = $this->getValue()['day']; if ($day < strtotime('today midnight')) { return TRUE; } return FALSE; } /** * Returns if a timestamp is in date range of x days to the future. * * Prerequisite: $item->isExceptionDay() must be TRUE. * * @param int $rangeInDays * The days into the future we want to check the timestamp against. * * @return bool * TRUE if the timestamp is in range. * TRUE if $rangeInDays has a negative value. */ public function isExceptionDayInRange($rangeInDays) { if ($rangeInDays <= 0) { return TRUE; } if ($this->isExceptionDayInPast()) { return FALSE; } $day = $this->getValue()['day']; $maxTime = time() + $rangeInDays * 24 * 60 * 60; if ($day > $maxTime) { return FALSE; } return TRUE; } }
src/Plugin/Field/FieldType/OfficeHoursItemList.php +3 −3 Original line number Diff line number Diff line Loading @@ -49,10 +49,10 @@ class OfficeHoursItemList extends FieldItemList implements OfficeHoursItemListIn if (!$exceptions_list) { $pluginManager = \Drupal::service('plugin.manager.field.field_type'); // Get field definition of ExceptionsItem. $plugin_id = 'office_hours_exception'; $plugin_id = 'office_hours_exceptions'; $field_definition = BaseFieldDefinition::create($plugin_id); // Create an ItemList with ExceptionsItems. $exceptions_list = new OfficeHoursItemList($field_definition); // Create an ItemList with OfficeHoursExceptionsItem items. $exceptions_list = OfficeHoursItemList::createInstance($field_definition, $this->name, NULL); } // Then, add an item to the list with Exception day field definition. $item = $pluginManager->createFieldItem($exceptions_list, $offset, $value); Loading