You are here

require_on_publish.module in Require on Publish 8

Module file for the Require on Publish module.

File

require_on_publish.module
View source
<?php

/**
 * @file
 * Module file for the Require on Publish module.
 */
use Drupal\Core\Entity\EntityFormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Template\Attribute;
use Drupal\field\FieldConfigInterface;

/**
 * Implements hook_help().
 */
function require_on_publish_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.require_on_publish':
      $output = '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Require on Publish module provides a mechanism for requiring a field to be filled out <em>only when publishing an entity</em>.') . '</p>';
      $output .= '<h3>' . t('Configuration') . '</h3>';
      $output .= '<p>' . t('Tick off the "Require on Publish" checkbox when managing a field. That\'s it!') . '</p>';
      return $output;
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function require_on_publish_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  /** @var \Drupal\field\FieldConfigInterface $field_config */
  $field_config = $form_state
    ->getFormObject()
    ->getEntity();

  /** @var \Drupal\Core\Entity\ContentEntityType $entity_type */
  $entity_type = \Drupal::entityTypeManager()
    ->getDefinition($field_config
    ->getTargetEntityTypeId());
  if (!_require_on_publish_entity_is_publishable($entity_type
    ->getClass())) {
    return;
  }
  $form['#attached']['library'][] = 'require_on_publish/config-form';
  $form['#attached']['library'][] = 'require_on_publish/require_on_publish';
  $form['require_on_publish'] = [
    '#type' => 'checkbox',
    '#title' => t('Required on Publish'),
    '#default_value' => $field_config
      ->getThirdPartySetting('require_on_publish', 'require_on_publish', FALSE),
    '#weight' => -4,
  ];
  $form['warn_on_empty'] = [
    '#type' => 'checkbox',
    '#title' => t('Warning on Empty'),
    '#default_value' => $field_config
      ->getThirdPartySetting('require_on_publish', 'warn_on_empty', FALSE),
    '#weight' => -3,
    '#states' => [
      'visible' => [
        ':input[name="require_on_publish"]' => [
          'checked' => TRUE,
        ],
      ],
      'invisible' => [
        ':input[name="require_on_publish"]' => [
          'checked' => FALSE,
        ],
      ],
    ],
  ];
  $form['actions']['submit']['#submit'][] = 'require_on_publish_field_config_submit';
}

/**
 * Submit handler for the form_field_config_edit form.
 */
function require_on_publish_field_config_submit($form, FormStateInterface $form_state) {

  /** @var \Drupal\field\FieldConfigInterface $entity */
  $entity = $form_state
    ->getFormObject()
    ->getEntity();

  /** @var int $require_on_publish */
  $require_on_publish = $form_state
    ->getValue('require_on_publish');

  /** @var int $warn_on_empty */
  $warn_on_empty = $form_state
    ->getValue('warn_on_empty');
  if ($require_on_publish) {
    $entity
      ->setThirdPartySetting('require_on_publish', 'require_on_publish', $require_on_publish);
    if ($warn_on_empty) {
      $entity
        ->setThirdPartySetting('require_on_publish', 'warn_on_empty', $warn_on_empty);
    }
    else {
      $entity
        ->unsetThirdPartySetting('require_on_publish', 'warn_on_empty');
    }
  }
  else {
    $entity
      ->unsetThirdPartySetting('require_on_publish', 'require_on_publish');
    $entity
      ->unsetThirdPartySetting('require_on_publish', 'warn_on_empty');
  }
  $entity
    ->save();
}

/**
 * Implements hook_entity_type_alter().
 */
function require_on_publish_entity_type_alter(array &$entity_types) {
  foreach ($entity_types as $type => $entity_type) {
    if (_require_on_publish_entity_is_publishable($entity_type
      ->getClass())) {
      $entity_types[$type]
        ->addConstraint('require_on_publish');
    }
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function require_on_publish_preprocess_datetime_wrapper(&$variables) {
  $element = $variables['element'];
  if (isset($element['#required_on_publish']) && $element['#required_on_publish']) {
    $variables['title_attributes']['class'][] = 'form-required-on-publish';
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function require_on_publish_preprocess_field_multiple_value_form(&$variables) {
  $element = $variables['element'];
  $variables['multiple'] = $element['#cardinality_multiple'];
  if ($variables['multiple']) {
    $header_attributes = new Attribute([
      'class' => [
        'label',
      ],
    ]);
    if (!empty($element['#required'])) {
      $header_attributes['class'][] = 'js-form-required';
      $header_attributes['class'][] = 'form-required';
    }
    if (isset($element['#required_on_publish']) && $element['#required_on_publish']) {
      $header_attributes['class'][] = 'form-required-on-publish';
    }
    $header = [
      [
        'data' => [
          '#prefix' => '<h4' . $header_attributes . '>',
          '#markup' => $element['#title'],
          '#suffix' => '</h4>',
        ],
        'colspan' => 2,
        'class' => [
          'field-label',
        ],
      ],
      t('Order', [], [
        'context' => 'Sort order',
      ]),
    ];
    $variables['table']['#header'] = $header;
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function require_on_publish_preprocess_fieldset(&$variables) {
  $element = $variables['element'];
  if (isset($element['#required_on_publish']) && $element['#required_on_publish']) {
    $variables['legend_span']['attributes'] = new Attribute([
      'class' => [
        'form-required-on-publish',
      ],
    ]);
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function require_on_publish_preprocess_form_element(&$variables) {
  $element = $variables['element'];
  if (isset($element['#required_on_publish']) && $element['#required_on_publish']) {
    $variables['label']['#attributes']['class'][] = 'form-required-on-publish';
  }
}

/**
 * Implements hook_field_widget_entity_reference_paragraphs_form_alter().
 */
function require_on_publish_field_widget_entity_reference_paragraphs_form_alter(&$element, &$form_state, $context) {
  _require_on_publish_add_indicator_to_paragraph($element, $form_state, $context);
}

/**
 * Implements hook_field_widget_WIDGET_TYPE_form_alter().
 */
function require_on_publish_field_widget_paragraphs_form_alter(&$element, FormStateInterface $form_state, $context) {
  _require_on_publish_add_indicator_to_paragraph($element, $form_state, $context);
}

/**
 * Helper function that adds an indicator to paragraph elements.
 */
function _require_on_publish_add_indicator_to_paragraph(&$element, FormStateInterface $form_state, $context) {
  $paragraph_type = $element['#paragraph_type'];
  $fields = \Drupal::service('entity_field.manager')
    ->getFieldDefinitions('paragraph', $paragraph_type);
  foreach ($fields as $field_config) {
    if (!$field_config instanceof FieldConfigInterface) {
      continue;
    }
    if ($field_config
      ->getThirdPartySetting('require_on_publish', 'require_on_publish', FALSE)) {
      $field_name = $field_config
        ->getName();
      $element['#attached']['library'][] = 'require_on_publish/require_on_publish';
      if (isset($element['subform'][$field_name]['widget'])) {
        require_on_publish_add_indicator($element['subform'][$field_name]['widget']);
      }
    }
  }
}

/**
 * Implements hook_form_alter().
 */
function require_on_publish_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  /** @var \Drupal\Core\Entity\EntityFormInterface $form_object */
  $form_object = $form_state
    ->getFormObject();
  if (!$form_object instanceof EntityFormInterface) {
    return;
  }
  $entity = $form_object
    ->getEntity();
  if (!_require_on_publish_entity_is_publishable(get_class($entity))) {
    return;
  }
  foreach ($entity
    ->getFields() as $field) {
    $field_config = $field
      ->getFieldDefinition();
    if (!$field_config instanceof FieldConfigInterface) {
      continue;
    }
    if ($field_config
      ->getThirdPartySetting('require_on_publish', 'require_on_publish', FALSE)) {
      $field_name = $field_config
        ->getName();
      if (!isset($form[$field_name])) {
        continue;
      }
      $form['#attached']['library'][] = 'require_on_publish/require_on_publish';
      require_on_publish_add_indicator($form[$field_name]['widget']);
    }
  }
}

/**
 * Adds an indicator to fields that are required on publish.
 *
 * @param array $widget
 *   The widget array.
 */
function require_on_publish_add_indicator(array &$widget) {
  $widget['#required_on_publish'] = TRUE;
  if (array_key_exists('target_id', $widget)) {
    $widget['target_id']['#required_on_publish'] = TRUE;
  }
  elseif (array_key_exists('value', $widget)) {
    $widget['value']['#required_on_publish'] = TRUE;
    if (array_key_exists('title', $widget['value']) && is_array($widget['value']['title'])) {
      $widget['value']['title']['#required_on_publish'] = TRUE;
    }
  }
  elseif (array_key_exists(0, $widget)) {
    $widget[0]['#required_on_publish'] = TRUE;
    if (array_key_exists('value', $widget[0])) {
      $widget[0]['value']['#required_on_publish'] = TRUE;
    }
  }
}

/**
 * Checks whether an entity type is publishable or not.
 *
 * @param string $entity_class
 *   The class name.
 *
 * @return bool
 *   Whether the entity can be published or not.
 */
function _require_on_publish_entity_is_publishable($entity_class) {
  if (!(new ReflectionClass($entity_class))
    ->implementsInterface('\\Drupal\\Core\\Entity\\EntityPublishedInterface')) {
    return FALSE;
  }
  return TRUE;
}