Commit 7d22f44a authored by John Voskuilen's avatar John Voskuilen
Browse files

Issue #3583782: Add better inheritance handling in ComplexWidget

parent 743add24
Loading
Loading
Loading
Loading
Loading
+11 −11
Original line number Diff line number Diff line
@@ -40,17 +40,6 @@ class OfficeHoursItemList extends FieldItemList implements OfficeHoursItemListIn
   */
  protected $season_max = 0;

  /**
   * Returns the formatter, creating it lazily.
   *
   * @return \Drupal\office_hours\OfficeHoursItemListFormatter
   *   The formatter object for this ItemList.
   */
  private function getOfficeHoursItemListFormatter(): OfficeHoursItemListFormatter {
    // Create the formatter AFTER setting the initial value in constructor.
    return $this->formatter ??= new OfficeHoursItemListFormatter($this, \Drupal::service('office_hours.event_dispatcher'));
  }

  /**
   * {@inheritdoc}
   *
@@ -282,6 +271,17 @@ class OfficeHoursItemList extends FieldItemList implements OfficeHoursItemListIn
    return (bool) $current_item;
  }

  /**
   * Returns the formatter, creating it lazily.
   *
   * @return \Drupal\office_hours\OfficeHoursItemListFormatter
   *   The formatter object for this ItemList.
   */
  private function getOfficeHoursItemListFormatter(): OfficeHoursItemListFormatter {
    // Create the formatter AFTER setting the initial value in constructor.
    return $this->formatter ??= new OfficeHoursItemListFormatter($this, \Drupal::service('office_hours.event_dispatcher'));
  }

  /**
   * Instantiate the widget/formatter object from the stored properties.
   *
+25 −5
Original line number Diff line number Diff line
@@ -94,15 +94,22 @@ class OfficeHoursComplexWeekWidget extends OfficeHoursSeasonWidget {
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state): array {
    $massaged_values = [];

    // NOTE: We are manipulating plugin_id in ComplexWidget, to get children working properly.
    $original_plugin_id = $this->getPluginId();

    // @todo Correct $element['#parents'], since FormBuilder's
    // $form_state->setValueForElement() and  $form_state->setUserInput($input)
    // set too much/wrong data, complicating massageFormValues().
    foreach ($values as $plugin_id => $widgets) {
      foreach ($widgets as $widget_values) {
        $widget_values = isset($widget_values['_actions'])
          // Use widget for exceptions.

      // NOTE: We are manipulating plugin_id in ComplexWidget, to get children working properly.
      $this->setPluginId($plugin_id);

      foreach ($widgets as $widget_id => $widget_values) {
        $widget_values = $this->isExceptionsWidget()
          // Call OfficeHoursWidgetBase for exceptions.
          ? OfficeHoursWidgetBase::massageFormValues($widget_values, $form, $form_state)
          // Use widget for weekdays/seasons.
          // Call OfficeHoursSeasonWidget for weekdays/seasons.
          : OfficeHoursSeasonWidget::massageFormValues($widget_values, $form, $form_state);
        // @todo Use proper level, alt.1:
        // $widget_values = parent::massageFormValues($widget_values, $form, $form_state);
@@ -113,7 +120,20 @@ class OfficeHoursComplexWeekWidget extends OfficeHoursSeasonWidget {
      }
    }

    // NOTE: We are manipulating plugin_id in ComplexWidget, to get children working properly.
    $this->setPluginId($original_plugin_id);

    return $massaged_values;
  }

  /**
   * {@inheritdoc}
   *
   * Do a dangerous override of Plugin Id.
   */
  public function setPluginId(string $plugin_id) {
    $this->pluginId = $plugin_id;
    return $this;
  }

}
+3 −2
Original line number Diff line number Diff line
@@ -154,8 +154,9 @@ class OfficeHoursSeasonWidget extends OfficeHoursWeekWidget {

    // If season exists, attach it to weekday rows.
    if ($season_id) {
      // Add season header row, to make sure it is saved to the datase.
      $values[] = $season->getValues();
      // Add season header row at start,
      // to make sure it is saved and can be used by following season items.
      array_unshift($values, $season->getValues());
    }

    return $values;
+18 −9
Original line number Diff line number Diff line
@@ -140,8 +140,10 @@ abstract class OfficeHoursWidgetBase extends WidgetBase {
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state): array {
    $values = parent::massageFormValues($values, $form, $form_state);

    $is_exceptions_widget = isset($values['_actions']);
    $is_list_widget = !isset($values['value']);
    // NOTE: We are manipulating plugin_id in ComplexWidget, to get children working properly.
    $plugin_id = $this->pluginId;

    $is_list_widget = $plugin_id == "office_hours_list";
    if ($is_list_widget) {
      // Nothing to do.
      return $values;
@@ -156,39 +158,41 @@ abstract class OfficeHoursWidgetBase extends WidgetBase {
      // Below lines should work fine with Annotation: multiple_values = FALSE.
      : $values = reset($values)['value'] ?? $values;

    if (empty($values)) {
      return [];
    }

    // Remove excessive data.
    // @todo Correct $element['#parents'], since FormBuilder's
    // $form_state->setValueForElement() and $form_state->setUserInput($input)
    // set too much/wrong data, complicating massageFormValues().
    if ($is_exceptions_widget) {
    if ($this->isExceptionsWidget()) {
      // Remove excessive data, leaving only the exception days.
      foreach ($values as $day => $value) {
        if ($day < OfficeHoursDateHelper::EXCEPTION_DAY_MIN) {
         if (\is_string($day) || $day < OfficeHoursDateHelper::EXCEPTION_DAY_MIN) {
          unset($values[$day]);
        }
      }
      // Remove 'value' of the 'Add exception' button.
      // unset($values['add_more']);
      // unset($values['_weight']);
      // unset($values['_actions']);
    }
    else {
      // Remove excessive data, leaving only the 7 weekdays.
      $values = \array_slice($values, 0, 7);
    }

    // Transform multi-level array: from [$day][$delta][...] to flat array.
    // Set the correct day number for regular/seasonal/exception days.
    $new_values = [];
    $settings = $this->getSettings();
    $cardinality = $settings['cardinality_per_day'];
    $season_id = $this->getSeason()?->id();

    foreach ($values as $value) {
      for ($day_delta = 0; $day_delta < $cardinality; $day_delta++) {
        $date = ($day_delta === 0) ? $value[$day_delta]['day'] : $date;
        // Copy $date from $value[0] to subsequent time slots.
        // Convert weekday numbers to seasonal day numbers.
        // Add safe-guard for exceptions (empty 'day' ).
        $value[$day_delta]['day'] = $is_exceptions_widget
        $value[$day_delta]['day'] = $this->isExceptionsWidget()
          ? $date
          : $date + $season_id;
        // Remove the double 'day' layer.
@@ -236,6 +240,11 @@ abstract class OfficeHoursWidgetBase extends WidgetBase {
    return $this;
  }

  protected function isExceptionsWidget(): bool {
    $is_exceptions_widget = ($this->pluginId == "office_hours_exceptions_only");
    return $is_exceptions_widget;
  }

  /**
   * Adds a message to the user, when widget does not support items.
   *