function _scheduler_entity_form_alter in Scheduler 2.x
Form alter handling for entity forms - add and edit.
1 call to _scheduler_entity_form_alter()
- scheduler_form_alter in ./
scheduler.module - Implements hook_form_alter().
File
- ./
scheduler.module, line 72 - Scheduler publishes and unpublishes entities on dates specified by the user.
Code
function _scheduler_entity_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Get the form display object. If this does not exist because the form is
// prevented from displaying, such as in Commerce Add Product before any store
// has been created, we can not (and do not need) to do anything, so exit.
if (!($display = $form_state
->getFormObject()
->getFormDisplay($form_state))) {
return;
}
$config = \Drupal::config('scheduler.settings');
$scheduler_manager = \Drupal::service('scheduler.manager');
/** @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $form_state
->getFormObject()
->getEntity();
$entityTypeId = $entity
->getEntityTypeId();
$publishing_enabled = $scheduler_manager
->getThirdPartySetting($entity, 'publish_enable', $config
->get('default_publish_enable'));
$unpublishing_enabled = $scheduler_manager
->getThirdPartySetting($entity, 'unpublish_enable', $config
->get('default_unpublish_enable'));
// If neither publishing nor unpublishing are enabled then there is nothing to
// do so remove the fields from the form and exit early.
if (!$publishing_enabled && !$unpublishing_enabled) {
unset($form['publish_on']);
unset($form['unpublish_on']);
return;
}
// Determine if the scheduler fields have been set to hidden (disabled).
$publishing_displayed = !empty($display
->getComponent('publish_on'));
$unpublishing_displayed = !empty($display
->getComponent('unpublish_on'));
// Invoke all implementations of hook_scheduler_hide_publish_date() and
// hook_scheduler_{type}_hide_publish_date() to allow other modules to hide
// the field on the entity edit form.
if ($publishing_enabled && $publishing_displayed) {
$hook_implementations = $scheduler_manager
->getHookImplementations('hide_publish_date', $entity);
foreach ($hook_implementations as $function) {
$publishing_displayed = $function($form, $form_state, $entity) !== TRUE && $publishing_displayed;
}
}
// Invoke all implementations of hook_scheduler_hide_unpublish_date() and
// hook_scheduler_{type}_hide_unpublish_date() to allow other modules to hide
// the field on the entity edit form.
if ($unpublishing_enabled && $unpublishing_displayed) {
$hook_implementations = $scheduler_manager
->getHookImplementations('hide_unpublish_date', $entity);
foreach ($hook_implementations as $function) {
$unpublishing_displayed = $function($form, $form_state, $entity) !== TRUE && $unpublishing_displayed;
}
}
// If both publishing and unpublishing are either not enabled or are hidden
// for this entity type then the only thing to do is remove the fields from
// the form, then exit.
if ((!$publishing_enabled || !$publishing_displayed) && (!$unpublishing_enabled || !$unpublishing_displayed)) {
unset($form['publish_on']);
unset($form['unpublish_on']);
return;
}
$allow_date_only = $config
->get('allow_date_only');
// A publish_on date is required if the content type option is set and the
// entity is being created or it is currently not published but has a
// scheduled publishing date.
$publishing_required = $publishing_enabled && $scheduler_manager
->getThirdPartySetting($entity, 'publish_required', $config
->get('default_publish_required')) && ($entity
->isNew() || !$entity
->isPublished() && !empty($entity->publish_on->value));
// An unpublish_on date is required if the content type option is set and the
// entity is being created or the current status is published or the entity is
// scheduled to be published.
$unpublishing_required = $unpublishing_enabled && $scheduler_manager
->getThirdPartySetting($entity, 'unpublish_required', $config
->get('default_unpublish_required')) && ($entity
->isNew() || $entity
->isPublished() || !empty($entity->publish_on->value));
// Create a 'details' field group to wrap the scheduling fields, and expand it
// if publishing or unpublishing is required, if a date already exists or the
// fieldset is configured to be always expanded.
$has_data = isset($entity->publish_on->value) || isset($entity->unpublish_on->value);
$always_expand = $scheduler_manager
->getThirdPartySetting($entity, 'expand_fieldset', $config
->get('default_expand_fieldset')) === 'always';
$expand_details = $publishing_required || $unpublishing_required || $has_data || $always_expand;
// Create the group for the fields.
$form['scheduler_settings'] = [
'#type' => 'details',
'#title' => t('Scheduling options'),
'#open' => $expand_details,
'#weight' => 35,
'#attributes' => [
'class' => [
'scheduler-form',
],
],
'#optional' => FALSE,
];
// Attach the fields to group.
$form['unpublish_on']['#group'] = 'scheduler_settings';
$form['publish_on']['#group'] = 'scheduler_settings';
// Show the field group as a vertical tab if this option is enabled.
$use_vertical_tabs = $scheduler_manager
->getThirdPartySetting($entity, 'fields_display_mode', $config
->get('default_fields_display_mode')) === 'vertical_tab';
if ($use_vertical_tabs) {
$form['scheduler_settings']['#group'] = 'advanced';
// Attach the javascript for the vertical tabs.
$form['scheduler_settings']['#attached']['library'][] = 'scheduler/vertical-tabs';
}
// Define the descriptions depending on whether the time can be skipped.
$descriptions = [];
if ($allow_date_only) {
$descriptions['format'] = t('Enter a date. The time part is optional.');
// Show the default time so users know what they will get if they do not
// enter a time.
$descriptions['default'] = t('The default time is @default_time.', [
'@default_time' => $config
->get('default_time'),
]);
// Use javascript to pre-fill the time parts if the dates are required.
// See js/scheduler_default_time.js for more details.
if ($publishing_required || $unpublishing_required) {
$form['scheduler_settings']['#attached']['library'][] = 'scheduler/default-time';
$form['scheduler_settings']['#attached']['drupalSettings']['schedulerDefaultTime'] = $config
->get('default_time');
}
}
else {
$descriptions['format'] = t('Enter a date and time.');
}
if (!$publishing_required) {
$descriptions['blank'] = t('Leave the date blank for no scheduled publishing.');
}
$form['publish_on']['#access'] = $publishing_enabled && $publishing_displayed;
$form['publish_on']['widget'][0]['value']['#required'] = $publishing_required;
$form['publish_on']['widget'][0]['value']['#description'] = Xss::filter(implode(' ', $descriptions));
if (!$unpublishing_required) {
$descriptions['blank'] = t('Leave the date blank for no scheduled unpublishing.');
}
else {
unset($descriptions['blank']);
}
$form['unpublish_on']['#access'] = $unpublishing_enabled && $unpublishing_displayed;
$form['unpublish_on']['widget'][0]['value']['#required'] = $unpublishing_required;
$form['unpublish_on']['widget'][0]['value']['#description'] = Xss::filter(implode(' ', $descriptions));
// When hiding the seconds on time input, we need to remove the seconds from
// the form value, as some browsers HTML5 rendering still show the seconds.
// We can use the same jQuery drupal behaviors file as for default time.
// This functionality is not covered by tests.
if ($config
->get('hide_seconds')) {
// If there is a publish_on time, then use jQuery to remove the seconds.
if (isset($entity->publish_on->value)) {
$form['scheduler_settings']['#attached']['library'][] = 'scheduler/default-time';
$form['scheduler_settings']['#attached']['drupalSettings']['schedulerHideSecondsPublishOn'] = date('H:i', $entity->publish_on->value);
}
// Likewise for the unpublish_on time.
if (isset($entity->unpublish_on->value)) {
$form['scheduler_settings']['#attached']['library'][] = 'scheduler/default-time';
$form['scheduler_settings']['#attached']['drupalSettings']['schedulerHideSecondsUnpublishOn'] = date('H:i', $entity->unpublish_on->value);
}
}
// Check the permission for entering scheduled dates.
$permission = $scheduler_manager
->permissionName($entityTypeId, 'schedule');
if (!\Drupal::currentUser()
->hasPermission($permission)) {
// Do not show the scheduler fields for users who do not have permission.
// Setting #access to FALSE for 'scheduler_settings' is enough to hide the
// fields. Setting FALSE for the individual fields is necessary to keep any
// existing scheduled dates preserved and remain unchanged on saving.
$form['scheduler_settings']['#access'] = FALSE;
$form['publish_on']['#access'] = FALSE;
$form['unpublish_on']['#access'] = FALSE;
// @todo Find a more elegant solution for bypassing the validation of
// scheduler fields when the user does not have permission.
// Note: This scenario is NOT yet covered by any tests, neither in
// SchedulerPermissionsTest.php nor SchedulerRequiredTest.php
// @see https://www.drupal.org/node/2651448
$form['publish_on']['widget'][0]['value']['#required'] = FALSE;
$form['unpublish_on']['widget'][0]['value']['#required'] = FALSE;
}
// Check which widget type is set for the scheduler fields, and give a warning
// if the wrong one has been set and provide a hint and link to fix it.
$pluginDefinitions = $display
->get('pluginManager')
->getDefinitions();
$fields_to_check = [];
if ($publishing_enabled && $publishing_displayed) {
$fields_to_check[] = 'publish_on';
}
if ($unpublishing_enabled && $unpublishing_displayed) {
$fields_to_check[] = 'unpublish_on';
}
$correct_widget_id = 'datetime_timestamp_no_default';
foreach ($fields_to_check as $field) {
$actual_widget_id = $display
->getComponent($field)['type'];
if ($actual_widget_id != $correct_widget_id) {
$link = \Drupal::moduleHandler()
->moduleExists('field_ui') ? Url::fromRoute("entity.entity_form_display.{$entityTypeId}.default", [
"{$entityTypeId}_type" => $entity
->bundle(),
])
->toString() : '#';
\Drupal::messenger()
->addMessage(t('The widget for field %field is incorrectly set to %wrong. This should be changed to %correct by an admin user via the <a href="@link">Field UI form display</a> :not_available', [
'%field' => (string) $form[$field]['widget']['#title'],
'%correct' => (string) $pluginDefinitions[$correct_widget_id]['label'],
'%wrong' => (string) $pluginDefinitions[$actual_widget_id]['label'],
'@link' => $link,
':not_available' => \Drupal::moduleHandler()
->moduleExists('field_ui') ? '' : '(' . t('not available') . ')',
]), 'warning', FALSE);
}
}
}