<?php

/**
 * @file
 * Provides workflow enhancements for Drupal.
 */

use Drupal\Core\Form\FormStateInterface;
use Drupal\lightning_workflow\Plugin\views\field\NodeBulkForm;
use Drupal\node\NodeTypeInterface;
use Drupal\views\ViewExecutable;
use Drupal\workbench_moderation\Entity\ModerationState;

/**
 * Alters a moderation_state form element.
 *
 * Workbench Moderation's out-of-the-box UX is kind of awful, so this restores
 * a measure of sanity by making the moderation_state widget into a select list
 * and preventing it from messing around with the form's submit buttons.
 *
 * @param array $element
 *   The element to modify.
 */
function lightning_workflow_alter_moderation_state(array &$element) {
  // Allow the user to choose the moderation state.
  $element['#access'] = TRUE;

  // Show the original labels of the destination states.
  foreach (array_keys($element['#options']) as $id) {
    $element['#options'][$id] = ModerationState::load($id)->label();
  }

  // Do NOT rejigger the form's buttons.
  unset($element['#process'][0]);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function lightning_workflow_form_node_form_alter(array &$form, FormStateInterface $form_state) {
  $form_object = $form_state->getFormObject();
  /** @var \Drupal\workbench_moderation\ModerationInformation $mod_info */
  $mod_info = \Drupal::service('workbench_moderation.moderation_information');

  if (isset($form['moderation_state']) && $mod_info->isModeratedEntityForm($form_object)) {
    lightning_workflow_alter_moderation_state($form['moderation_state']['widget'][0]);

    // Show the basic 'Save' button, but hide the confusing
    // 'Save as unpublished' and 'Save and publish' buttons.
    $form['actions']['submit']['#access'] = TRUE;
    $form['actions']['publish']['#access'] = $form['actions']['unpublish']['#access'] = FALSE;
    unset($form['actions']['publish']['#dropbutton'], $form['actions']['unpublish']['#dropbutton']);

    // Workbench Moderation enforces revisions by checking and disabling the
    // revision checkbox. We don't need to display that.
    $form['revision']['#type'] = 'hidden';
    unset($form['revision_log']['#states']['visible'][':input[name="revision"]']);
  }
}

/**
 * Implements hook_ENTITY_TYPE_insert().
 */
function lightning_workflow_node_type_insert(NodeTypeInterface $node_type) {
  /** @var \Drupal\user\RoleInterface $role */
  user_role_grant_permissions($node_type->id() . '_creator', [
    'view any unpublished content',
    'use draft_draft transition',
    'use draft_needs_review transition',
    'use needs_review_needs_review transition',
    'view latest version',
  ]);

  user_role_grant_permissions($node_type->id() . '_reviewer', [
    'use draft_published transition',
    'use needs_review_draft transition',
    'use needs_review_published transition',
    'use published_published transition',
  ]);
}

/**
 * Implements hook_views_plugins_field_alter().
 */
function lightning_workflow_views_plugins_field_alter(array &$plugins) {
  if (isset($plugins['node_bulk_form'])) {
    $plugins['node_bulk_form']['class'] = NodeBulkForm::class;
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Transform the WBM status filter field on /admin/content from a text field to
 * a select list.
 */
function lightning_workflow_form_views_exposed_form_alter(array &$form, FormStateInterface $form_state) {
  if ($form_state->getStorage()['view']->storage->id() == 'content') {
    if (isset($form['moderation_state'])) {
      $form['moderation_state'] = [
        '#type' => 'select',
        '#options' => [
          '' => \Drupal::translation()->translate('- any -'),
        ],
      ];
      /** @var \Drupal\workbench_moderation\ModerationStateInterface $state */
      foreach (ModerationState::loadMultiple() as $state) {
        $form['moderation_state']['#options'][$state->id()] = $state->label();
      }
    }
  }
}

/**
 * Implements hook_views_pre_render().
 */
function lightning_workflow_views_pre_render(ViewExecutable $view) {
  if ($view->storage->id() == 'moderation_history') {
    foreach ($view->result as $index => $row) {
      $entity = $row->_entity;

      if (empty($previous) || $previous->moderation_state->target_id != $entity->moderation_state->target_id) {
        $previous = $entity;
      }
      else {
        unset($view->result[$index]);
        $view->total_rows--;
      }
    }
  }
}
