View source
<?php
namespace Drupal\smart_date\Plugin\Field\FieldType;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Form\FormStateInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeFieldItemList;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
class SmartDateFieldItemList extends DateTimeFieldItemList {
public function defaultValuesForm(array &$form, FormStateInterface $form_state) {
if (empty($this
->getFieldDefinition()
->getDefaultValueCallback())) {
if ($this
->getFieldDefinition()
->getDefaultValueLiteral()) {
$default_value = $this
->getFieldDefinition()
->getDefaultValueLiteral()[0];
}
else {
$default_value = [];
}
$element = parent::defaultValuesForm($form, $form_state);
$element['default_date_type']['#options']['next_hour'] = t('Next hour');
unset($element['default_time_type']);
$this
->addDurationConfig($element, $default_value);
return $element;
}
}
public static function addDurationConfig(array &$element, array $default_value) {
$description = '<p>' . t('The possible durations this field can contain. Enter one value per line, in the format key|label.');
$description .= '<br/>' . t('The key is the stored value, and must be numeric or "custom" to allow an arbitrary length. The label will be used in edit forms.');
$description .= '<br/>' . t('The label is optional: if a line contains a single number, it will be used as key and label.') . '</p>';
$element['default_duration_increments'] = [
'#type' => 'textarea',
'#title' => t('Allowed duration increments'),
'#description' => $description,
'#default_value' => isset($default_value['default_duration_increments']) ? $default_value['default_duration_increments'] : "30\n60|1 hour\n90\n120|2 hours\ncustom",
'#required' => TRUE,
];
$element['default_duration'] = [
'#type' => 'textfield',
'#title' => t('Default duration'),
'#description' => t('Set which of the duration increments provided above that should be selected by default.'),
'#default_value' => isset($default_value['default_duration']) ? $default_value['default_duration'] : '60',
'#required' => TRUE,
];
return $element;
}
public function defaultValuesFormValidate(array $element, array &$form, FormStateInterface $form_state) {
if ($duration = $form_state
->getValue([
'default_value_input',
'default_duration',
])) {
$increments = SmartDateListItemBase::parseValues($form_state
->getValue([
'default_value_input',
'default_duration_increments',
]));
if (!$increments) {
$increments = [];
}
$increment_min = -1;
foreach ($increments as $key => $label) {
if (intval($key) == 0 && $key !== '0' && $key !== 0 && $key !== 'custom') {
$form_state
->setErrorByName('default_value_input][default_duration_increments', $this
->t('Invalid tokens in the allowed increments specified. Please provide either integers or "custom" as the key for each value.'));
break;
}
else {
$increment_min = $increment_min < intval($key) ? intval($key) : $increment_min;
}
}
if (!in_array('custom', $increments)) {
if ($increment_min < 0) {
$form_state
->setErrorByName('default_value_input][default_duration_increments', $this
->t('Unable to parse valid durations from the allowed increments specified.'));
}
else {
$messenger = \Drupal::messenger();
$messenger
->addMessage($this
->t('No string to allow for custom values, so the provided increments will be strictly enforced.'), 'warning');
}
}
if (!isset($increments[$duration])) {
$form_state
->setErrorByName('default_value_input][default_duration', $this
->t('Please specify a default duration that is one of the provided options.'));
}
}
DateTimeFieldItemList::defaultValuesFormValidate($element, $form, $form_state);
}
public function defaultValuesFormSubmit(array $element, array &$form, FormStateInterface $form_state) {
if (strlen((string) $form_state
->getValue([
'default_value_input',
'default_duration',
])) && strlen((string) $form_state
->getValue([
'default_value_input',
'default_duration_increments',
]))) {
if ($duration = $form_state
->getValue([
'default_value_input',
'default_duration',
])) {
$form_state
->setValueForElement($element['default_duration'], $duration);
}
if ($duration_increments = $form_state
->getValue([
'default_value_input',
'default_duration_increments',
])) {
$form_state
->setValueForElement($element['default_duration_increments'], $duration_increments);
}
return [
$form_state
->getValue('default_value_input'),
];
}
DateTimeFieldItemList::defaultValuesFormSubmit($element, $form, $form_state);
return [];
}
public static function processDefaultValue($default_value, FieldableEntityInterface $entity, FieldDefinitionInterface $definition) {
$default_value = FieldItemList::processDefaultValue($default_value, $entity, $definition);
if (empty($default_value[0]['default_date_type'])) {
return $default_value;
}
$date = new DrupalDateTime($default_value[0]['default_date'], DateTimeItemInterface::STORAGE_TIMEZONE);
$format = DateTimeItemInterface::DATETIME_STORAGE_FORMAT;
if ($default_value[0]['default_date_type'] == 'next_hour') {
$date
->modify('+1 hour');
$min = (int) $date
->format('i') + 1;
$date
->modify('-' . $min . ' minutes');
}
$value = $date
->getTimestamp();
$second = $date
->format("s");
if ($second > 0) {
$value += 60 - $second;
}
$duration = (int) $default_value[0]['default_duration'];
$end_value = $value + $duration * 60;
$default_value = [
[
'value' => $value,
'end_value' => $end_value,
'date' => $date,
],
];
return $default_value;
}
}