access_policy-1.0.x-dev/src/Plugin/access_policy/AccessRule/WeekdayRange.php
src/Plugin/access_policy/AccessRule/WeekdayRange.php
<?php namespace Drupal\access_policy\Plugin\access_policy\AccessRule; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Datetime\TimeZoneFormHelper; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Week day range access rule. * * @AccessRule( * id = "weekday_range", * ) */ class WeekdayRange extends AccessRuleBase { use StringTranslationTrait; /** * The config object. * * @var \Drupal\Core\Config\ConfigFactoryInterface */ protected $configFactory; /** * Constructs a new WeekdayRange access rule. * * @param array $configuration * A configuration array containing information about the plugin instance. * @param string $plugin_id * The plugin_id for the plugin instance. * @param mixed $plugin_definition * The plugin implementation definition. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The config object. */ public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->configFactory = $config_factory; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('config.factory') ); } /** * {@inheritdoc} */ public function defaultSettings() { return [ 'weekday' => [], 'start_time' => '', 'end_time' => '', 'all_day' => FALSE, 'timezone_select' => 'default', ] + parent::defaultSettings(); } /** * {@inheritdoc} */ public function isApplicable(EntityInterface $entity) { return TRUE; } /** * {@inheritdoc} */ public function accessRuleForm(array $form, FormStateInterface $form_state) { $form['weekday'] = [ '#title' => $this->t('Weekday'), '#type' => 'checkboxes', '#options' => $this->getWeekdays(), '#description' => $this->t('Choose the days of the week you want to grant access to this content.'), '#default_value' => $this->settings['weekday'], '#required' => TRUE, ]; $form['time_range'] = [ '#type' => 'container', '#states' => [ 'visible' => [':input[name="all_day"]' => ['checked' => FALSE]], ], ]; $form['time_range']['start_time'] = [ '#type' => 'datetime', '#title' => $this->t('Start time'), '#date_date_element' => 'none', '#default_value' => $this->getDateTimeObj($this->settings['start_time']), ]; $form['time_range']['end_time'] = [ '#type' => 'datetime', '#title' => $this->t('End time'), '#date_date_element' => 'none', '#default_value' => $this->getDateTimeObj($this->settings['end_time']), ]; $form['all_day'] = [ '#type' => 'checkbox', '#title' => $this->t('All day'), '#default_value' => $this->settings['all_day'], ]; $form['timezone_select'] = [ '#type' => 'select', '#title' => $this->t('Time zone'), '#default_value' => $this->settings['timezone_select'], '#options' => [ // Default will do either site or current user. 'default' => $this->t('Default'), 'other' => $this->t('Other'), ], ]; $system_date_config = $this->configFactory->get('system.date'); $form['timezone'] = [ '#type' => 'select', '#title' => $this->t('Select time zone'), '#default_value' => $this->settings['timezone'] ?? $system_date_config->get('timezone.default'), '#options' => TimeZoneFormHelper::getOptionsListByRegion(NULL), '#description' => $this->t('Select the desired time zone.'), '#states' => [ 'visible' => [':input[name="timezone_select"]' => ['value' => 'other']], ], ]; return $form; } /** * Get the date time object. * * This is necessary in order to properly render the value in the form. * * @param string $time * The current saved time in a specific format (e.g 9:00:00 AM). * * @return \Drupal\Core\Datetime\DrupalDateTime|string * The drupal date time object. */ protected function getDateTimeObj($time) { if (empty($time)) { return ''; } return DrupalDateTime::createFromFormat('H:i:s', $time); } /** * Get the days of the week. * * @return array * Array of the days of the week. */ protected function getWeekdays() { return [ 'sun' => $this->t('Sunday'), 'mon' => $this->t('Monday'), 'tue' => $this->t('Tuesday'), 'wed' => $this->t('Wednesday'), 'thu' => $this->t('Thursday'), 'fri' => $this->t('Friday'), 'sat' => $this->t('Saturday'), ]; } /** * {@inheritdoc} */ public function accessRuleFormSubmit(array &$form, FormStateInterface $form_state) { parent::accessRuleFormSubmit($form, $form_state); $values = $form_state->getValues(); $this->settings['weekday'] = array_filter($values['weekday']); $this->settings['all_day'] = boolval($values['all_day']); if (!$values['all_day']) { $this->settings['start_time'] = $values['start_time'] ? $values['start_time']->format('H:i:s') : ''; $this->settings['end_time'] = $values['end_time'] ? $values['end_time']->format('H:i:s') : ''; } else { unset($this->settings['start_time']); unset($this->settings['end_time']); } $this->settings['timezone_select'] = $values['timezone_select']; if ($this->settings['timezone_select'] == 'other') { $this->settings['timezone'] = $values['timezone']; } else { unset($this->settings['timezone']); } } /** * {@inheritdoc} */ public function accessRuleFormValidate(array &$form, FormStateInterface $form_state) { $all_day = $form_state->getValue('all_day'); if (empty($all_day)) { if (empty($form_state->getValue('start_time'))) { $form_state->setErrorByName('start_time', "Start time is required."); } if (empty($form_state->getValue('end_time'))) { $form_state->setErrorByName('end_time', "End time is required."); } } } /** * {@inheritdoc} */ public function validate(EntityInterface $entity, AccountInterface $account) { // Get the current day. $date = $this->getValue(); $day = strtolower($date->format('D')); // If the day is not supported then return false. if (!in_array($day, $this->settings['weekday'])) { return FALSE; } if (!$this->settings['all_day']) { $timestamp = $date->getTimestamp(); if ($timestamp < $this->getTimestampFromTime($this->settings['start_time']) || $timestamp > $this->getTimestampFromTime($this->settings['end_time'])) { return FALSE; } } return TRUE; } /** * {@inheritdoc} */ public function getValue() { if (!$this->value) { $time_zone = $this->settings['timezone'] ?? NULL; $this->value = new DrupalDateTime('now', $time_zone); } return $this->value; } /** * Get the DrupalDateTime object for a specific daily time. * * This is the date in the format ready to be validated against. * * @param string $time * The current time (e.g 9:00:00). * * @return int * The DrupalDateTime object. */ protected function getTimestampFromTime($time) { $time_zone = $this->settings['timezone'] ?? NULL; $datetime = new DrupalDateTime($time, $time_zone); return $datetime->getTimestamp(); } }