Add Exception Day support for 'Current day' formatter

Created on 2 September 2022, about 2 years ago
Updated 6 October 2023, about 1 year ago

Problem/Motivation

Whenever the current/next day is displayed, things are not correct when Exception days are used.

Steps to reproduce

- Add an Office Hours field to a content type
- In field settings, Allow exception days (and seasonal days)
- choose the 'current day' formatter, or the select-list formatter with included open/closed status.
- create, edit a node with regular/season hours and exception day in the near feature (today+tomorrow)
- Save, display the node.
The node should display the exception day, with corresponiding open/closed status.

Proposed resolution

Below code shows the relevant formatter option. 'show next' and 'show current' are valid here

    $element['show_closed'] = [
      '#title' => $this->t('Number of days to show'),
      '#type' => 'select',
      '#options' => [
        'all' => $this->t('Show all days'),
        'open' => $this->t('Show only open days'),
        'next' => $this->t('Show next open day'),
        'none' => $this->t('Hide all days'),
        'current' => $this->t('Show only current day'),
      ],
      '#default_value' => $settings['show_closed'],
      '#description' => $this->t('The days to show in the formatter. Useful in combination with the Current Status block.'),
    ];

The code in OfficeHoursFormatterTrait~getRows() must be updated.
When looping over the data, the days for the current week must be overwritten by the data from exception days.
Upon doing so, be aware that the current season must be taken (but this can be added later)
Perhaps also changes in:
- OfficeHoursItemList~getCurrentSlot();
- $items->getCacheTime();

Note: when testing/developing, make sure that initially the formatter options 'schema.org' is disabled, and 'show open/closed status' is set properly, to not to be confused that some code is called multiple times.

Remaining tasks

...

User interface changes

The internal 'View' processing of the API is changed (in Model/View/Controller model).
The 'external' View of the data stay identical.
But perhaps it will change for all-days formatter option.

API changes

None, only the internal 'View' processing of the API is changed (in Model/View/Controller model).

Data model changes

None, only the internal 'View' processing of the API is changed. The Model is already enhanced in previous issues (in Model/View/Controller model).

๐Ÿ› Bug report
Status

Fixed

Version

1.11

Component

Code - formatter

Created by

๐Ÿ‡ณ๐Ÿ‡ฑNetherlands johnv

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • ๐Ÿ‡จ๐Ÿ‡ญSwitzerland Lukas von Blarer

    I'm interested in fixing this. What needs to happen here? I have trouble to wrap my head around this...

  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands johnv

    Hi Lukas,
    glad you step in.
    In fact, this is a special case of the (newer) issue โœจ Season Formatter: update weekly timetable depending on the season Closed: duplicate .
    Since the latest versions, we now have 3 different sets of office hours:
    - regular hours
    - seasonal hours
    - exceptions

    There are other requests:
    - โœจ Season Formatter: Each season week as individual table Needs review
    - do not show all seasons, only current season
    But they can be dealt with later.

    I updated the issue description. I hope it will help you.

  • Issue was unassigned.
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands johnv
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia Raveen Kumar

    Raveen Thakur โ†’ made their first commit to this issueโ€™s fork.

  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Waiting for branch to pass
  • @raveen-thakur opened merge request.
  • ๐Ÿ‡จ๐Ÿ‡ญSwitzerland Lukas von Blarer

    Ok, that is a bit confusing to be tbh. AFAIK that's a different case than I have. I only have exceptions, not seasons. Or is seasons going to replace exceptions alltogether?

    I have been using an old path from โœจ Add "Exception day" feature Fixed . In that patch we maintained a separate list of exception days and compare those to the days of the current and next week. This was woughly what we did back then:

      /**
        * @param array $office_hours
        * @return array
        */
       protected function handleClosedDates($office_hours) {
         $time = \Drupal::time()->getRequestTime();
         $today = (int) idate('w', $time);
         $special_opening_hours = $this->getSpecialOpeningHours();
         foreach ($office_hours as $key => $item) {
           $day = (int) $item['startday'];
           if($day == 0) {
             $day = 7;
           }
           if($day >= $today) {
             $week = 'this';
           }
           else {
             $week = 'next';
           }
           $datetime = new DrupalDateTime($day - 1 . ' day ' . $week . ' week');
           $date = $datetime->format('Y-m-d');
           if (isset($special_opening_hours[$date])) {
             if ($special_opening_hours[$date]['closed'] === '1') {
               $office_hours[$key]['closed'] = TRUE;
               $office_hours[$key]['slots'] = [];
             }
             else if (isset($special_opening_hours[$date]['from']) && isset($special_opening_hours[$date]['to'])) {
               $office_hours[$key]['slots'][0] = [
                 'start' => $special_opening_hours[$date]['from'],
                 'end' => $special_opening_hours[$date]['to'],
               ];
             }
           }
         }
         return $office_hours;
       }
    
       /**
        * @return array
        */
       protected function getSpecialOpeningHours() {
         $special_opening_hours = [];
         $field_list = $this->parent->get('field_special_opening_hours');
         foreach ($field_list as $item) {
           $entity = $item->entity;
           $special_opening_hours[$entity->get('field_date')->value] = [
             'closed' => $entity->get('field_closed')->value,
             'from' => $entity->get('field_time_from')->value,
             'to' => $entity->get('field_time_to')->value,
           ];
         }
         return $special_opening_hours;
       }
    

    I'd take a similar approach except you know a better one.

    @Raveen Thakur sorry, I don't get your MR. The commit is unrelated to this issue.

  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Waiting for branch to pass
  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Waiting for branch to pass
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands johnv

    Hi Lukas,
    No, seasons is not going to replace exceptions. You can forget seasons for your use case. I will adapt later on.

  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Waiting for branch to pass
  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Waiting for branch to pass
  • Status changed to Needs review over 1 year ago
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands johnv

    When testing with multiple slots per day, this part $exception_days[$date] = $item;overwrites the first slot:

      public function getExceptionDays() {
        $exception_days = [];
        $date_formatter = \Drupal::service('date.formatter');
    
        foreach ($this->list as $item) {
          if ($item->isException()) {
            $slot = $item->getValue();
            $date = $date_formatter->format($slot['day'], 'custom', OfficeHoursItem::EXCEPTION_DAY_LOOKUP_DATE_FORMAT);
            $exception_days[$date] = $item;
          }
        }
    
        return $exception_days;
      }
    
    
  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Waiting for branch to pass
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands johnv

    The attached patch:
    - overrides all values of a day, by adding $day_delta. Still a problem when weekday has less slots then exception day.
    - getExceptiondays is now static. Still to test with multiple nodes on a page.
    - has no problem with labels, due to not copying objects, but only object values.

    I renamed $slot to $value, for better code comparison.
    There is still duplicate code.
    Docu is not updated.

  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Waiting for branch to pass
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands johnv

    Removed the static variable. Must be tested.

  • ๐Ÿ‡จ๐Ÿ‡ญSwitzerland Lukas von Blarer

    @johnv Thank you for your feedback and your patch! Here is a quick first review;

    Your approach makes sense. I have only tested my particular use case.
    There is a lot of calls to dpm()
    There is uncommented code in the patch.
    Is there a reason for not using the issue fork? I find it a had to review your changes without having a diff.

    Also this probably needs tests.

  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands johnv

    Hi Lukas, truth is i have't been able to include MR 's in my workflow, (bluntly: i did not succeed in using them until know) hence, the patch.
    indeed, a diff would make things easier. Sorry for that.
    I meant to remove the dpms but i needed to wrap things up before Day end.

    About your use case: What Will you so with the remai ing exceptional days? Will you not show them at all? Or Just show this weeks exception in the weedkays AND in the exception?

  • ๐Ÿ‡จ๐Ÿ‡ญSwitzerland Lukas von Blarer

    Using MRs is actually a lot easier than using patches. I highly recommend you to try them. You can get started using the instructions right below th IS of this issue by clicking on "Show commands".

    I am actually only showing the next or current open day. So yes, I don't need them and that's why I didn't experience the issues you are trying to fix with your patch.

  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Waiting for branch to pass
  • @johnv opened merge request.
  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Waiting for branch to pass
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands johnv

    OK, I am trying to work with MR's.
    I tried to rebase the MR23, since there are some other commits in main branch. Did not succeed , yet.
    MR24 can be discarded.

    At least, please see attached patch, with less impact, doing exactly the same as the previous one.

    • johnv โ†’ committed 1ce41635 on 8.x-1.x
      Issue #3307517 by johnv, Lukas von Blarer, Raveen Thakur: Add Exception...
  • Status changed to Fixed about 1 year ago
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands johnv

    Wow,
    a presumably small request with a big patch!

    Somewhere in this issue, I decided that the complete formatter should replace the exceptions. But that would require some additional settings.
    For the CURRENT formatter, it is always OK to replace with the exception (or with the actual seasonal hours).

    For housekeeping, the following have been changed in the interfaces:

    $item->IsInRange() --> new
    $item->IsOpen() --> new
    $item->IsSeasonDay() --> new
    $item->isException() --> $item->isExceptionDay()

    $itemlist->getNextDay() --> new
    $itemlist->getCurrent() --> $itemlist->getCurrentSlot()

    OfficeHoursItem::isExceptionDay() --> OfficeHoursDateHelper::isExceptionDay()
    OfficeHoursItem::isSeasonDay() --> OfficeHoursDateHelper::isSeasonDay()

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024