Skip to content
Snippets Groups Projects

Resolve #3525354 "Security advisory preparation"

Files
4
+ 221
0
<?php
namespace Drupal\partial_datelist\Hook;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\WidgetInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\datetime\Plugin\Field\FieldWidget\DateTimeDatelistWidget;
use Drupal\datetime_range\Plugin\Field\FieldWidget\DateRangeDatelistWidget;
use Drupal\partial_datelist\PartialDatelistConfig;
/**
* Hook implementations for the partial_datelist module.
*/
class PartialDatelistHooks {
use \Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* Implements hook_help().
*
* @param string $route_name
* The name of the route.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match object.
*
* @return array
* A render array for the help page.
*/
#[Hook('help')]
public function help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.partial_datelist':
return [
'#markup' =>
'<h2>' .
$this->t('About') .
'</h2><p>' .
$this->t('The <strong>Partial Datelist</strong> module allows administrators to hide specific parts of a date or datetime dropdown when using the <em>Select list</em> widget. This is useful when you only need to collect certain date or time parts (for example, just the year or month and year) from users.') .
'</p><p>' .
$this->t('This module only affects the <em>Select list</em> widget for date and datetime fields. It does <strong>not</strong> affect the calendar widget (<em>Date and time</em>).') .
'</p><h2>' .
$this->t('Uses') .
'</h2><dl><dt>' .
$this->t('Hide specific date and time parts') .
'</dt><dd>' .
$this->t('Allows administrators to hide individual date or time dropdowns (Year, Month, Day, Hour, Minute, Second) when configuring a field widget using the <em>Select list</em> option for date and datetime fields.') .
'</dd><dt>' .
$this->t('Widget configuration') .
'</dt><dd>' .
$this->t('Integrates with the field widget configuration interface. When editing a date or datetime field widget, a <em>Date list visibility settings</em> section appears, providing checkboxes to select which date or time parts to hide.') .
'</dd><dt>' .
$this->t('Entity form') .
'</dt><dd>' .
$this->t("The field selected hidden date parts, based on administrator's configuration, are not shown to users on entity add/edit forms.") .
'</dd><dt>' .
$this->t('Supported field types') .
'</dt><dd>' .
$this->t('Works with both <code>datetime</code> and <code>daterange</code> fields using the <em>Select list</em> widget. The <em>Timestamp</em> field type is not supported.') .
'</dd><dt>' .
$this->t('Persistence') .
'</dt><dd>' .
$this->t('The configuration is saved per field widget and persists across form submissions and cache clears.') .
'</dd></dl>',
];
}
return [];
}
/**
* Implements hook_help().
*
* @param Drupal\Core\Field\WidgetInterface $plugin
* The field widget plugin.
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The field definition.
* @param string $form_mode
* The form mode.
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state object.
*
* @return array
* A render array for the help page.
*/
#[Hook('field_widget_third_party_settings_form')]
public function fieldWidgetThirdPartySettingsForm(WidgetInterface $plugin, FieldDefinitionInterface $field_definition, $form_mode, array $form, FormStateInterface $form_state) {
$element = [];
$target_plugins = [
'datetime_datelist',
'daterange_datelist',
];
if (!in_array($plugin->getPluginId(), $target_plugins)) {
return $element;
}
$datetime_type = $field_definition->getSetting('datetime_type');
$datelist_parts = PartialDatelistConfig::DATELIST_PARTS;
$all_settings = $plugin->getThirdPartySettings('partial_datelist', 'hidden_datelist_parts');
$settings = $all_settings['hidden_datelist_parts'] ?? [];
$checkboxes = [];
$default_values = [];
foreach ($datelist_parts as $info) {
if (!in_array($datetime_type, $info['context'])) {
continue;
}
$checkboxes[$info['setting']] = $this->t('Hide @label', ['@label' => $info['label']]);
if (!empty($settings[$info['setting']])) {
$default_values[] = $info['setting'];
}
}
$element['hidden_datelist_parts'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Date list visibility settings'),
'#options' => $checkboxes,
'#default_value' => $default_values,
'#description' => $this->t('Select which date parts to hide in the date list.'),
'#attributes' => [
'class' => [
PartialDatelistConfig::DATELIST_SETTINGS_CLASS_NAME,
],
],
];
return $element;
}
/**
* Implements hook_field_widget_settings_summary_alter().
*
* @param array $summary
* The summary array.
* @param array $context
* The context array.
*/
#[Hook('field_widget_settings_summary_alter')]
public function fieldWidgetSettingsSummaryAlter(&$summary, $context) {
$all_settings = $context['widget']->getThirdPartySettings('partial_datelist', 'hidden_datelist_parts');
$settings = $all_settings['hidden_datelist_parts'] ?? [];
$datelist_parts = PartialDatelistConfig::DATELIST_PARTS;
$hidden_parts = array_filter($datelist_parts, function ($info) use ($settings) {
return !empty($settings[$info['setting']]);
});
if (empty($hidden_parts)) {
return;
}
$labels = array_map(function ($info) {
return $info['label'];
}, $hidden_parts);
$summary[] = $this->formatPlural(
count($labels),
'Hidden part: @items',
'Hidden parts: @items',
['@items' => implode(', ', $labels)]
);
}
/**
* Implements hook_field_widget_complete_form_alter().
*
* @param array $element
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state object.
* @param array $context
* The context array.
*/
#[Hook('field_widget_complete_form_alter')]
public function fieldWidgetCompleteFormAlter(&$element, $form_state, $context) {
if (
(!$context['widget'] instanceof DateRangeDatelistWidget || !class_exists('Drupal\datetime_range\Plugin\Field\FieldWidget\DateRangeDatelistWidget')) &&
!$context['widget'] instanceof DateTimeDatelistWidget
) {
return;
}
$all_settings = $context['widget']->getThirdPartySettings('partial_datelist', 'hidden_datelist_parts');
$settings = $all_settings['hidden_datelist_parts'] ?? [];
$datelist_parts = PartialDatelistConfig::DATELIST_PARTS;
$hidden_parts_keys = array_keys(array_filter($datelist_parts, function ($info) use ($settings) {
return !empty($settings[$info['setting']]);
}));
$widget = &$element['widget'];
$numeric_keys = array_filter(array_keys($widget), 'is_int');
foreach ($numeric_keys as $index) {
if (empty($widget[$index]['value'])) {
continue;
}
$valid_date_parts = array_diff(
$widget[$index]['value']['#date_part_order'],
$hidden_parts_keys
);
$widget[$index]['value']['#date_part_order'] = $valid_date_parts;
if (isset($widget[$index]['end_value'])) {
$widget[$index]['end_value']['#date_part_order'] = $valid_date_parts;
}
}
}
}
Loading