View source
<?php
namespace Drupal\office_hours\Plugin\Field\FieldFormatter;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\office_hours\OfficeHoursDateHelper;
use Drupal\office_hours\OfficeHoursFormatterTrait;
use Drupal\office_hours\Plugin\Field\FieldType\OfficeHoursItemListInterface;
abstract class OfficeHoursFormatterBase extends FormatterBase {
use OfficeHoursFormatterTrait;
public static function defaultSettings() {
return [
'day_format' => 'long',
'time_format' => 'G',
'compress' => FALSE,
'grouped' => FALSE,
'show_closed' => 'all',
'closed_format' => 'Closed',
'separator' => [
'days' => '<br />',
'grouped_days' => ' - ',
'day_hours' => ': ',
'hours_hours' => '-',
'more_hours' => ', ',
],
'current_status' => [
'position' => '',
'open_text' => 'Currently open!',
'closed_text' => 'Currently closed',
],
'schema' => [
'enabled' => FALSE,
],
'timezone_field' => '',
'office_hours_first_day' => '',
] + parent::defaultSettings();
}
public function settingsForm(array $form, FormStateInterface $form_state) {
$element = parent::settingsForm($form, $form_state);
$settings = $this
->getSettings();
$day_names = OfficeHoursDateHelper::weekDays(FALSE);
$day_names[''] = $this
->t("- system's Regional settings -");
$element['show_closed'] = [
'#type' => 'select',
'#title' => $this
->t('Number of days to show'),
'#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.'),
];
$element['office_hours_first_day'] = [
'#type' => 'select',
'#options' => $day_names,
'#title' => $this
->t('First day of week'),
'#default_value' => $this
->getSetting('office_hours_first_day'),
];
$element['day_format'] = [
'#type' => 'select',
'#title' => $this
->t('Day notation'),
'#options' => [
'long' => $this
->t('long'),
'short' => $this
->t('3-letter weekday abbreviation'),
'two_letter' => $this
->t('2-letter weekday abbreviation'),
'number' => $this
->t('number'),
'none' => $this
->t('none'),
],
'#default_value' => $settings['day_format'],
];
$element['time_format'] = [
'#type' => 'select',
'#title' => $this
->t('Time notation'),
'#options' => [
'G' => $this
->t('24 hour time') . ' (9:00)',
'H' => $this
->t('24 hour time') . ' (09:00)',
'g' => $this
->t('12 hour time') . ' (9:00 am)',
'h' => $this
->t('12 hour time') . ' (09:00 am)',
],
'#default_value' => $settings['time_format'],
'#required' => FALSE,
'#description' => $this
->t('Format of the clock in the formatter.'),
];
$element['compress'] = [
'#title' => $this
->t('Compress all hours of a day into one set'),
'#type' => 'checkbox',
'#default_value' => $settings['compress'],
'#description' => $this
->t('Even if more hours is allowed, you might want to show a compressed form. E.g., 7:00-12:00, 13:30-19:00 becomes 7:00-19:00.'),
'#required' => FALSE,
];
$element['grouped'] = [
'#title' => $this
->t('Group consecutive days with same hours into one set'),
'#type' => 'checkbox',
'#default_value' => $settings['grouped'],
'#description' => $this
->t('E.g., Mon: 7:00-19:00; Tue: 7:00-19:00 becomes Mon-Tue: 7:00-19:00.'),
'#required' => FALSE,
];
$element['closed_format'] = [
'#type' => 'textfield',
'#size' => 30,
'#title' => $this
->t('Empty days notation'),
'#default_value' => $settings['closed_format'],
'#required' => FALSE,
'#description' => $this
->t('Format of empty (closed) days. String
<a>can be translated</a> when the
<a href=":install">Interface Translation module</a> is installed.', [
':install' => Url::fromRoute('system.modules_list')
->toString(),
]),
];
$element['separator'] = [
'#title' => $this
->t('Separators'),
'#type' => 'details',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
];
$element['separator']['days'] = [
'#type' => 'textfield',
'#size' => 10,
'#default_value' => $settings['separator']['days'],
'#description' => $this
->t('This separator will be placed between the days. Use '<br>' to show each day on a new line.'),
];
$element['separator']['grouped_days'] = [
'#type' => 'textfield',
'#size' => 10,
'#default_value' => $settings['separator']['grouped_days'],
'#description' => $this
->t('This separator will be placed between the labels of grouped days.'),
];
$element['separator']['day_hours'] = [
'#type' => 'textfield',
'#size' => 10,
'#default_value' => $settings['separator']['day_hours'],
'#description' => $this
->t('This separator will be placed between the day and the hours.'),
];
$element['separator']['hours_hours'] = [
'#type' => 'textfield',
'#size' => 10,
'#default_value' => $settings['separator']['hours_hours'],
'#description' => $this
->t('This separator will be placed between the hours of a day.'),
];
$element['separator']['more_hours'] = [
'#type' => 'textfield',
'#size' => 10,
'#default_value' => $settings['separator']['more_hours'],
'#description' => $this
->t('This separator will be placed between the hours and more_hours of a day.'),
];
$element['current_status'] = [
'#title' => $this
->t('Current status'),
'#type' => 'details',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#description' => $this
->t('Below strings <a>can be translated</a> when the
<a href=":install">Interface Translation module</a> is installed.', [
':install' => Url::fromRoute('system.modules_list')
->toString(),
]),
];
$element['current_status']['position'] = [
'#type' => 'select',
'#title' => $this
->t('Current status position'),
'#options' => [
'' => $this
->t('Hidden'),
'before' => $this
->t('Before hours'),
'after' => $this
->t('After hours'),
],
'#default_value' => $settings['current_status']['position'],
'#description' => $this
->t('Where should the current status be located?'),
];
$element['current_status']['open_text'] = [
'#title' => $this
->t('Status strings'),
'#type' => 'textfield',
'#size' => 40,
'#default_value' => $settings['current_status']['open_text'],
'#description' => $this
->t('Format of the message displayed when currently open.'),
];
$element['current_status']['closed_text'] = [
'#type' => 'textfield',
'#size' => 40,
'#default_value' => $settings['current_status']['closed_text'],
'#description' => $this
->t('Format of message displayed when currently closed.'),
];
$element['schema'] = [
'#title' => $this
->t('Schema.org openingHours support'),
'#type' => 'details',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
];
$element['schema']['enabled'] = [
'#title' => $this
->t('Enable Schema.org openingHours support'),
'#type' => 'checkbox',
'#default_value' => $settings['schema']['enabled'],
'#description' => $this
->t('Enable meta tags with property for Schema.org openingHours.'),
'#required' => FALSE,
];
return $element;
}
public function settingsSummary() {
$summary = parent::settingsSummary();
$summary[] = $this
->t('Display Office hours in different formats.');
return $summary;
}
protected function addSchemaFormatter(OfficeHoursItemListInterface $items, $langcode, array $elements) {
$formatter = new OfficeHoursFormatterSchema($this->pluginId, $this->pluginDefinition, $this->fieldDefinition, $this->settings, $this->viewMode, $this->label, $this->thirdPartySettings);
$new_element = $formatter
->viewElements($items, $langcode);
$schema_items = [];
foreach ($new_element[0]['#office_hours'] as $schema) {
$schema_items[] = [
'label' => $schema['label'],
'formatted_slots' => $schema['formatted_slots'],
];
}
$elements['#schema'] = [
'#theme' => 'office_hours',
'#office_hours' => [
'schema' => $schema_items,
],
'#cache' => [
'max-age' => $this
->getStatusTimeLeft($items, $langcode),
'tags' => [
'office_hours:field.default',
],
],
];
return $elements;
}
protected function addStatusFormatter(OfficeHoursItemListInterface $items, $langcode, array $elements) {
if (!empty($this->settings['current_status']['position'])) {
$formatter = new OfficeHoursFormatterStatus($this->pluginId, $this->pluginDefinition, $this->fieldDefinition, $this->settings, $this->viewMode, $this->label, $this->thirdPartySettings);
$new_element = $formatter
->viewElements($items, $langcode);
switch ($new_element['#position']) {
case 'before':
array_unshift($elements, $new_element);
break;
case 'after':
array_push($elements, $new_element);
break;
default:
break;
}
}
return $elements;
}
public function getStatusTimeLeft(OfficeHoursItemListInterface $items, $langcode) {
if (empty($items
->getValue())) {
return Cache::PERMANENT;
}
$date = new DrupalDateTime('now');
$today = $date
->format('w');
$now = $date
->format('Hi');
$seconds = $date
->format('s');
$next_time = '0000';
$add_days = 0;
$settings = $this
->getSettings();
switch ($settings['show_closed']) {
case 'all':
case 'open':
case 'none':
return Cache::PERMANENT;
case 'current':
$next_time = '0000';
$add_days = 1;
break;
case 'next':
$office_hours = $this
->getRows($items
->getValue(), $this
->getSettings(), $this
->getFieldSettings());
$next = array_shift($office_hours);
$first_time = NULL;
foreach ($next['slots'] as $slot) {
$start = $slot['start'];
$end = $slot['end'];
if ($next['startday'] != $today) {
$next_time = $start;
$add_days = ($next['startday'] - $today + 7) % 7;
break;
}
elseif ($start > $now) {
$next_time = $start;
$add_days = 0;
break;
}
elseif ($start > $end || $start == $end || $start < $end && $end > $now) {
$next_time = $end;
$add_days = $start < $end ? 0 : 1;
break;
}
else {
if (!isset($first_time_slot_found)) {
$first_time_slot_found = TRUE;
$next_time = $start;
$add_days = 7;
}
continue;
}
}
break;
default:
return Cache::PERMANENT;
}
$next_time = is_numeric($next_time) ? $next_time : '0000';
$time_left = (int) $add_days * 24 * 3600;
$time_left += (int) (substr($next_time, 0, 2) - substr($now, 0, 2)) * 3600;
$time_left += (int) (substr($next_time, 2, 2) - substr($now, 2, 2)) * 60;
$time_left -= $seconds;
return $time_left;
}
}