lightning_workflow.module in Lightning Workflow 8
Same filename and directory in other branches
Provides workflow enhancements for Drupal.
File
lightning_workflow.moduleView source
<?php
/**
* @file
* Provides workflow enhancements for Drupal.
*/
use Drupal\content_moderation\Plugin\WorkflowType\ContentModerationInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\lightning_core\Element;
use Drupal\lightning_core\Routing\RouteSubscriber;
use Drupal\lightning_workflow\Plugin\views\field\NodeBulkForm;
use Drupal\node\NodeTypeInterface;
use Drupal\views\ViewEntityInterface;
use Drupal\views\ViewExecutable;
use Drupal\workflows\Entity\Workflow;
/**
* Implements hook_ENTITY_TYPE_insert().
*/
function lightning_workflow_node_type_insert(NodeTypeInterface $node_type) {
// Don't do anything during a config sync.
if (\Drupal::isConfigSyncing()) {
return;
}
$workflow = $node_type
->getThirdPartySetting('lightning_workflow', 'workflow');
if (empty($workflow)) {
return;
}
$workflow = Workflow::load($workflow);
if (empty($workflow)) {
return;
}
$plugin = $workflow
->getTypePlugin();
if ($plugin instanceof ContentModerationInterface) {
$rebuild = !in_array('node', $plugin
->getEntityTypes(), TRUE);
$plugin
->addEntityTypeAndBundle('node', $node_type
->id());
$workflow
->save();
// We need to rebuild all routes because Content Moderation needs to ensure
// that edit forms load the latest revision.
if ($rebuild) {
Drupal::service('router.builder')
->rebuild();
}
}
}
/**
* Implements hook_theme_registry_alter().
*/
function lightning_workflow_theme_registry_alter(array &$theme_registry) {
foreach ($theme_registry as $hook => &$info) {
if ($hook == 'field' || isset($info['base hook']) && $info['base hook'] == 'field') {
// We wrap around Quick Edit's preprocess function, so it should not be
// run directly.
$info['preprocess functions'] = array_diff($info['preprocess functions'], [
'quickedit_preprocess_field',
]);
}
}
}
/**
* Implements template_preprocess_field().
*/
function lightning_workflow_preprocess_field(array &$variables) {
if (\Drupal::moduleHandler()
->moduleExists('quickedit')) {
quickedit_preprocess_field($variables);
/** @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $variables['element']['#object'];
if ($entity instanceof EntityPublishedInterface && $entity
->isPublished() && RouteSubscriber::isViewing($entity)) {
unset($variables['attributes']['data-quickedit-field-id']);
}
}
}
/**
* Implements hook_module_implements_alter().
*/
function lightning_workflow_module_implements_alter(array &$implementations, $hook) {
// We have to check for hook_node_view_alter() because of absolute insanity
// in ModuleHandler::alter() and the way it determines the implementations of
// 'secondary' alter hooks. It's weird logic that is pretty close to
// inexplicable...but trust me, to wrap around quickedit_entity_view_alter(),
// we need to alter the implementations of hook_node_view_alter(). Granted,
// this will only work for nodes. If we want to do this for another entity
// type, we'll have to check for its entity type-specific view_alter hook as
// well.
if ($hook == 'node_view_alter') {
unset($implementations['quickedit']);
}
}
/**
* Implements hook_entity_view_alter().
*/
function lightning_workflow_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
if (\Drupal::moduleHandler()
->moduleExists('quickedit')) {
quickedit_entity_view_alter($build, $entity, $display);
if ($entity instanceof EntityPublishedInterface && $entity
->isPublished() && RouteSubscriber::isViewing($entity)) {
unset($build['#attributes']['data-quickedit-entity-id']);
}
}
}
/**
* Implements hook_ENTITY_TYPE_presave().
*
* TODO: Re-implement a relationship to the latest revision, and add a field
* indicating if forward revisions exist. This is a known regression due to
* incomplete functionality in Content Moderation.
*/
function lightning_workflow_view_presave(ViewEntityInterface $view) {
// Don't do anything during config sync.
if (\Drupal::isConfigSyncing()) {
return;
}
elseif ($view
->id() == 'content' && $view
->isNew()) {
$display =& $view
->getDisplay('default');
$display_options =& $display['display_options'];
// Allow users to filter by moderation state.
$display_options['filters']['moderation_state'] = unserialize('a:15:{s:2:"id";s:16:"moderation_state";s:5:"table";s:15:"node_field_data";s:5:"field";s:16:"moderation_state";s:12:"relationship";s:4:"none";s:10:"group_type";s:5:"group";s:11:"admin_label";s:0:"";s:8:"operator";s:2:"in";s:5:"value";a:5:{s:3:"all";s:3:"all";s:15:"editorial-draft";s:15:"editorial-draft";s:16:"editorial-review";s:16:"editorial-review";s:19:"editorial-published";s:19:"editorial-published";s:18:"editorial-archived";s:18:"editorial-archived";}s:5:"group";i:1;s:7:"exposed";b:1;s:6:"expose";a:11:{s:11:"operator_id";s:19:"moderation_state_op";s:5:"label";s:16:"Moderation state";s:11:"description";s:0:"";s:12:"use_operator";b:0;s:8:"operator";s:19:"moderation_state_op";s:10:"identifier";s:16:"moderation_state";s:8:"required";b:0;s:8:"remember";b:0;s:8:"multiple";b:0;s:14:"remember_roles";a:10:{s:13:"authenticated";s:13:"authenticated";s:9:"anonymous";s:1:"0";s:13:"administrator";s:1:"0";s:12:"page_creator";s:1:"0";s:14:"layout_manager";s:1:"0";s:13:"page_reviewer";s:1:"0";s:20:"landing_page_creator";s:1:"0";s:21:"landing_page_reviewer";s:1:"0";s:13:"media_creator";s:1:"0";s:13:"media_manager";s:1:"0";}s:6:"reduce";b:0;}s:10:"is_grouped";b:0;s:10:"group_info";a:10:{s:5:"label";s:0:"";s:11:"description";s:0:"";s:10:"identifier";s:0:"";s:8:"optional";b:1;s:6:"widget";s:6:"select";s:8:"multiple";b:0;s:8:"remember";b:0;s:13:"default_group";s:3:"All";s:22:"default_group_multiple";a:0:{}s:11:"group_items";a:0:{}}s:11:"entity_type";s:4:"node";s:9:"plugin_id";s:23:"moderation_state_filter";}');
// Ditch status field and the "published"/"published or admin" filters.
unset($display_options['filters']['status'], $display_options['filters']['status_extra'], $display_options['fields']['status']);
// Add a field to display the moderation state.
$display_options['fields']['moderation_state'] = unserialize('a:37:{s:2:"id";s:16:"moderation_state";s:5:"table";s:35:"content_moderation_state_field_data";s:5:"field";s:16:"moderation_state";s:12:"relationship";s:4:"none";s:10:"group_type";s:5:"group";s:11:"admin_label";s:16:"Moderation state";s:5:"label";s:16:"Moderation state";s:7:"exclude";b:0;s:5:"alter";a:26:{s:10:"alter_text";b:0;s:4:"text";s:0:"";s:9:"make_link";b:0;s:4:"path";s:0:"";s:8:"absolute";b:0;s:8:"external";b:0;s:14:"replace_spaces";b:0;s:9:"path_case";s:4:"none";s:15:"trim_whitespace";b:0;s:3:"alt";s:0:"";s:3:"rel";s:0:"";s:10:"link_class";s:0:"";s:6:"prefix";s:0:"";s:6:"suffix";s:0:"";s:6:"target";s:0:"";s:5:"nl2br";b:0;s:10:"max_length";i:0;s:13:"word_boundary";b:1;s:8:"ellipsis";b:1;s:9:"more_link";b:0;s:14:"more_link_text";s:0:"";s:14:"more_link_path";s:0:"";s:10:"strip_tags";b:0;s:4:"trim";b:0;s:13:"preserve_tags";s:0:"";s:4:"html";b:0;}s:12:"element_type";s:0:"";s:13:"element_class";s:0:"";s:18:"element_label_type";s:0:"";s:19:"element_label_class";s:0:"";s:19:"element_label_colon";b:1;s:20:"element_wrapper_type";s:0:"";s:21:"element_wrapper_class";s:0:"";s:23:"element_default_classes";b:1;s:5:"empty";s:3:"N/A";s:10:"hide_empty";b:0;s:10:"empty_zero";b:0;s:16:"hide_alter_empty";b:1;s:17:"click_sort_column";s:5:"value";s:4:"type";s:6:"string";s:8:"settings";a:1:{s:14:"link_to_entity";b:0;}s:12:"group_column";s:5:"value";s:13:"group_columns";a:0:{}s:10:"group_rows";b:1;s:11:"delta_limit";i:0;s:12:"delta_offset";i:0;s:14:"delta_reversed";b:0;s:16:"delta_first_last";b:0;s:10:"multi_type";s:9:"separator";s:9:"separator";s:2:", ";s:17:"field_api_classes";b:0;s:11:"entity_type";s:24:"content_moderation_state";s:12:"entity_field";s:16:"moderation_state";s:9:"plugin_id";s:5:"field";}');
Element::toTail($display_options['fields'], 'operations');
}
}
/**
* Implements hook_modules_installed().
*/
function lightning_workflow_modules_installed(array $modules) {
// Don't do anything during config sync.
if (\Drupal::isConfigSyncing()) {
return;
}
if (in_array('lightning_roles', $modules, TRUE)) {
\Drupal::service('lightning.content_roles')
->grantPermissions('creator', [
'use editorial transition create_new_draft',
'use editorial transition review',
'view any unpublished content',
'view latest version',
])
->grantPermissions('reviewer', [
'use editorial transition publish',
'use editorial transition review',
'use editorial transition archive',
'view any unpublished content',
'view latest version',
]);
}
if (in_array('lightning_dev', $modules, TRUE)) {
/** @var \Drupal\Core\Extension\ModuleInstallerInterface $module_installer */
$module_installer = \Drupal::service('module_installer');
// Lightning Workflow optionally integrates with Diff, and for testing
// purposes we'd like to enable that integration. In order to test with
// meaningful responsibility-based roles, we also enable Lightning Roles.
$module_installer
->install([
'diff',
'lightning_roles',
]);
// BigPipe breaks a couple of non-JS tests which expect to find local task
// links, but receive BigPipe placeholders instead. This is a bit of a
// sledgehammer approach, but until it's possible to disable a module during
// a single test, it's the best we can do.
$module_installer
->uninstall([
'big_pipe',
]);
// Add moderation to the page content type.
/** @var NodeTypeInterface $node_type */
$node_type = entity_load('node_type', 'page');
$node_type
->setThirdPartySetting('lightning_workflow', 'workflow', 'editorial');
lightning_workflow_node_type_insert($node_type);
// Allow the content view to filter by moderation state.
$view = entity_load('view', 'content')
->enforceIsNew();
lightning_workflow_view_presave($view);
$view
->enforceIsNew(FALSE)
->save();
}
}
/**
* Implements hook_views_data_alter().
*/
function lightning_workflow_views_data_alter(array &$data) {
foreach ($data as $table => $table_data) {
if (isset($table_data['moderation_state']['field'])) {
$data[$table]['moderation_state']['field'] += [
'id' => 'null',
];
}
}
}
/**
* 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_views_pre_render().
*/
function lightning_workflow_views_pre_render(ViewExecutable $view) {
if ($view
->id() == 'moderation_history') {
foreach ($view->result as $index => $row) {
$entity = $row->_entity;
if (empty($previous) || $previous->moderation_state->value != $entity->moderation_state->value) {
$previous = $entity;
}
else {
unset($view->result[$index]);
$view->total_rows--;
}
}
}
}
Functions
Name | Description |
---|---|
lightning_workflow_entity_view_alter | Implements hook_entity_view_alter(). |
lightning_workflow_modules_installed | Implements hook_modules_installed(). |
lightning_workflow_module_implements_alter | Implements hook_module_implements_alter(). |
lightning_workflow_node_type_insert | Implements hook_ENTITY_TYPE_insert(). |
lightning_workflow_preprocess_field | Implements template_preprocess_field(). |
lightning_workflow_theme_registry_alter | Implements hook_theme_registry_alter(). |
lightning_workflow_views_data_alter | Implements hook_views_data_alter(). |
lightning_workflow_views_plugins_field_alter | Implements hook_views_plugins_field_alter(). |
lightning_workflow_views_pre_render | Implements hook_views_pre_render(). |
lightning_workflow_view_presave | Implements hook_ENTITY_TYPE_presave(). |