function scheduler_form_node_form_alter in Scheduler 8
Implements hook_form_FORM_ID_alter() for node_form().
File
- ./
scheduler.module, line 68 - Scheduler publishes and unpublishes nodes on dates specified by the user.
Code
function scheduler_form_node_form_alter(&$form, FormStateInterface $form_state) {
$config = \Drupal::config('scheduler.settings');
/** @var \Drupal\node\NodeTypeInterface $type */
$type = $form_state
->getFormObject()
->getEntity()->type->entity;
$publishing_enabled = $type
->getThirdPartySetting('scheduler', 'publish_enable', $config
->get('default_publish_enable'));
$unpublishing_enabled = $type
->getThirdPartySetting('scheduler', 'unpublish_enable', $config
->get('default_unpublish_enable'));
// Determine if the scheduler fields have been set to hidden (disabled).
$display = $form_state
->getFormObject()
->getFormDisplay($form_state);
$publishing_displayed = !empty($display
->getComponent('publish_on'));
$unpublishing_displayed = !empty($display
->getComponent('unpublish_on'));
/** @var \Drupal\node\NodeInterface $node */
$node = $form_state
->getFormObject()
->getEntity();
// Invoke all implementations of hook_scheduler_hide_publish_on_field() to
// allow other modules to hide the field on the node edit form.
if ($publishing_enabled && $publishing_displayed) {
$hook = 'scheduler_hide_publish_on_field';
foreach (\Drupal::moduleHandler()
->getImplementations($hook) as $module) {
$function = $module . '_' . $hook;
$publishing_displayed = $function($form, $form_state, $node) !== TRUE && $publishing_displayed;
}
}
// Invoke all implementations of hook_scheduler_hide_unpublish_on_field() to
// allow other modules to hide the field on the node edit form.
if ($unpublishing_enabled && $unpublishing_displayed) {
$hook = 'scheduler_hide_unpublish_on_field';
foreach (\Drupal::moduleHandler()
->getImplementations($hook) as $module) {
$function = $module . '_' . $hook;
$unpublishing_displayed = $function($form, $form_state, $node) !== TRUE && $unpublishing_displayed;
}
}
// If both publishing and unpublishing are either not enabled or are hidden
// for this node 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
// node is being created or it is currently not published but has a
// scheduled publishing date.
$publishing_required = $publishing_enabled && $type
->getThirdPartySetting('scheduler', 'publish_required', $config
->get('default_publish_required')) && ($node
->isNew() || !$node
->isPublished() && !empty($node->publish_on->value));
// An unpublish_on date is required if the content type option is set and the
// node is being created or the current status is published or the node is
// scheduled to be published.
$unpublishing_required = $unpublishing_enabled && $type
->getThirdPartySetting('scheduler', 'unpublish_required', $config
->get('default_unpublish_required')) && ($node
->isNew() || $node
->isPublished() || !empty($node->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($node->publish_on->value) || isset($node->unpublish_on->value);
$always_expand = $type
->getThirdPartySetting('scheduler', '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 = $type
->getThirdPartySetting('scheduler', '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.
if ($config
->get('hide_seconds')) {
// If there is a publish_on time, then use jQuery to remove the seconds.
if (isset($node->publish_on->value)) {
$form['scheduler_settings']['#attached']['library'][] = 'scheduler/default-time';
$form['scheduler_settings']['#attached']['drupalSettings']['schedulerHideSecondsPublishOn'] = date('H:i', $node->publish_on->value);
}
// Likewise for the unpublish_on time.
if (isset($node->unpublish_on->value)) {
$form['scheduler_settings']['#attached']['library'][] = 'scheduler/default-time';
$form['scheduler_settings']['#attached']['drupalSettings']['schedulerHideSecondsUnpublishOn'] = date('H:i', $node->unpublish_on->value);
}
}
if (!\Drupal::currentUser()
->hasPermission('schedule publishing of nodes')) {
// 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) {
\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 Field UI <a href="@link">content type 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' => \Drupal::moduleHandler()
->moduleExists('field_ui') ? Url::fromRoute('entity.entity_form_display.node.default', [
'node_type' => $type
->get('type'),
])
->toString() : '#',
':not_available' => \Drupal::moduleHandler()
->moduleExists('field_ui') ? '' : '(' . t('not available') . ')',
]), 'warning', FALSE);
}
}
}