datetime_extras-8.x-1.x-dev/src/Plugin/Field/FieldWidget/DateTimeConfigurableWidget.php
src/Plugin/Field/FieldWidget/DateTimeConfigurableWidget.php
<?php
namespace Drupal\datetime_extras\Plugin\Field\FieldWidget;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Datetime\Entity\DateFormat;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\datetime\Plugin\Field\FieldWidget\DateTimeDefaultWidget;
/**
* Plugin implementation of the 'datatime_configurable' widget.
*
* @FieldWidget(
* id = "datatime_configurable",
* label = @Translation("Configurable Date and time"),
* field_types = {
* "datetime"
* }
* )
*/
class DateTimeConfigurableWidget extends DateTimeDefaultWidget {
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
$settings = parent::defaultSettings();
$settings['year_range'] = '-50:+50';
$settings['increment'] = '1';
return $settings;
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$elements['year_range'] = [
'#title' => t('Year Range'),
'#description' => t('The range of years to display in the date/time picker.'),
'#type' => 'textfield',
'#required' => TRUE,
'#default_value' => $this->getSetting('year_range'),
];
$elements['increment'] = [
'#title' => t('Increment'),
'#description' => t('The amount of seconds to increment the date/time picker by.'),
'#type' => 'textfield',
'#required' => TRUE,
'#default_value' => $this->getSetting('increment'),
];
return $elements;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = [];
$summary[] = t('Year Range: @range', ['@range' => $this->getSetting('year_range')]);
$summary[] = t('Increment: @i', ['@i' => $this->getSetting('increment')]);
return $summary;
}
/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element = parent::formElement($items, $delta, $element, $form, $form_state);
$date = $element['value']['#default_value'] ?? NULL;
// Calculate the min and max properties for the HTML5 date element.
$date_format = $element['value']['#date_date_element'] != 'none' ? static::getHtml5DateFormat($element['value']) : '';
$range = static::datetimeRangeYears($this->getSetting('year_range'), $date);
$html5_min = new DrupalDateTime();
$html5_min->setDate($range[0], 1, 1)->setTime(0, 0, 0);
$html5_max = new DrupalDateTime();
$html5_max->setDate($range[1], 12, 31)->setTime(23, 59, 59);
$element['value']['#attributes']['min'] = $html5_min->format($date_format);
$element['value']['#attributes']['max'] = $html5_max->format($date_format);
// Set the increment property.
$element['value']['#date_increment'] = $this->getSetting('increment');
return $element;
}
/**
* Copy of protected function we need to reuse.
*
* @see \Drupal\Core\Datetime\Element\DateElementBase::datetimeRangeYears()
*/
protected static function datetimeRangeYears($string, $date = NULL) {
$datetime = new DrupalDateTime();
$this_year = $datetime->format('Y');
[$min_year, $max_year] = explode(':', $string);
// Valid patterns would be -5:+5, 0:+1, 2008:2010.
$plus_pattern = '@[\+|\-][0-9]{1,4}@';
$year_pattern = '@^[0-9]{4}@';
if (!preg_match($year_pattern, $min_year, $matches)) {
if (preg_match($plus_pattern, $min_year, $matches)) {
$min_year = $this_year + $matches[0];
}
else {
$min_year = $this_year;
}
}
if (!preg_match($year_pattern, $max_year, $matches)) {
if (preg_match($plus_pattern, $max_year, $matches)) {
$max_year = $this_year + $matches[0];
}
else {
$max_year = $this_year;
}
}
// We expect the $min year to be less than the $max year. Some custom values
// for -99:+99 might not obey that.
if ($min_year > $max_year) {
$temp = $max_year;
$max_year = $min_year;
$min_year = $temp;
}
// If there is a current value, stretch the range to include it.
$value_year = $date instanceof DrupalDateTime ? $date->format('Y') : '';
if (!empty($value_year)) {
$min_year = min($value_year, $min_year);
$max_year = max($value_year, $max_year);
}
return [$min_year, $max_year];
}
/**
* Copy of protected function we need to reuse.
*
* @see \Drupal\Core\Datetime\Element\Datetime::getHtml5DateFormat()
*/
protected static function getHtml5DateFormat($element) {
switch ($element['#date_date_element']) {
case 'date':
return DateFormat::load('html_date')->getPattern();
case 'datetime':
case 'datetime-local':
return DateFormat::load('html_datetime')->getPattern();
default:
return $element['#date_date_format'];
}
}
}
