Commit a90bc959 authored by John Voskuilen's avatar John Voskuilen
Browse files

Issue #1998266: Add 'Exception day' feature - remove ThirdPartySettings

parent 7db58395
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -10,9 +10,8 @@ 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');
// Add ExceptionItem field formatter theming/preprocessing.
\Drupal::moduleHandler()->loadInclude('office_hours', 'inc', 'office_hours.theme.exceptions');

/**
 * Implements hook_form_FORM_ID_alter().
+103 −0
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Implements third_party_settings hooks provided by the Field UI module.
 */

use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\office_hours\OfficeHoursDateHelper;

/* @see File core/modules/field_ui/field_ui.api.php
 *
 * hook_field_formatter_settings_summary_alter
 * 	 Alters the field formatter settings summary.
 * hook_field_formatter_third_party_settings_form
 * 	 Allow modules to add settings to field formatters provided by other modules.
 * hook_field_widget_settings_summary_alter
 *   Alters the field widget settings summary.
 * hook_field_widget_third_party_settings_form
 *   Allow modules to add settings to field widgets provided by other modules.
 */

/**
 * Implements hook_preprocess_field().
 */
function office_hours_exceptions_preprocess_field(array &$variables) {
  if (substr($variables['field_type'], 0, 12) !== 'office_hours') {
    return;
  }

  $entity = $variables['element']['#object'];
  $view_mode = $variables['element']['#view_mode'];
  $field_name = $variables['element']['#field_name'];

  // Get the field formatter settings.
  $entity_display = EntityViewDisplay::collectRenderDisplay($entity, $view_mode);
  $settings = $entity_display->getComponent($field_name)['settings'];

  /** @var \Drupal\office_hours\Plugin\Field\FieldType\OfficeHoursItemList $items */
  $items = &$variables['element']['#items'];
  $langcode = $variables['element']['#language'];
  $elements = &$variables['items'];

  if ($items->isEmpty()) {
    return $elements;
  }
  // Check if an exception day exists in the table.
  if (!$items->hasExceptionDays()) {
    return $elements;
  }

  // Loop over formatters: $elements contains table/status/schema formatter.
  foreach ($elements as $key => &$element) if (is_numeric($key)) {
    // If there is an exception, add an extra row to label the exceptions.
    // Note: may be changed in template_preprocess_office_hours_table().
    $label = $settings['exceptions']['title'];
    $exception_header = [];
    switch ($element['content']['#theme']) {

      case 'office_hours_table':
        $formatter_rows = &$element['content']['#table']['#rows'];
        if ($label && $formatter_rows) {
          // Set the title for the exceptions.
          $exception_header['data']['label']['data']['#markup'] = $label;
          $exception_header['class'] = [
            'office-hours__exceptions-label',
          ];
          $exception_header['id'] = ['office-hours-exception__title'];
        }
        break;

      case 'office_hours':
        $formatter_rows = &$element['content']['#office_hours'];
        if ($label && $formatter_rows) {
          // 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;
        }
        break;

      case 'office_hours_schema':
        // @todo Test/Enhance this formatter.
      case 'office_hours_status':
        // @todo Test/Enhance this formatter.
      default:
        break;
    }
    if ($exception_header) {
      // 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']);
    }

  }

  return $elements;
}
+2 −0
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ function office_hours_preprocess_field(&$variables, $hook) {
      $delta++;
    }
  }
  // Add exception hours.
  office_hours_exceptions_preprocess_field($variables, $hook);
}

/**
+0 −335
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;
  }

}
+1 −1
Original line number Diff line number Diff line
@@ -352,7 +352,7 @@ trait OfficeHoursFormatterTrait {
   */
  protected function formatLabels(array $office_hours, array $settings, array $third_party_settings) {
    $day_format = $settings['day_format'];
    $exceptions_day_format = $third_party_settings['office_hours_exceptions']['date_format'] ?? NULL;
    $exceptions_day_format = $settings['exceptions']['date_format'] ?? NULL;
    $group_separator = $settings['separator']['grouped_days'];
    $days_suffix = $settings['separator']['day_hours'];
    foreach ($office_hours as $key => &$info) {
Loading