localgov_step_by_step-2.1.10/localgov_step_by_step.module
localgov_step_by_step.module
<?php
/**
* @file
* Module file.
*
* Implements hooks.
*/
declare(strict_types=1);
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\localgov_roles\RolesHelper;
/**
* Implements hook_theme().
*
* Provides the following themes:
* - Step by step navigation view's Prev/Next block.
*/
function localgov_step_by_step_theme() {
return [
'step_by_step_part_of_block' => [
'variables' => [
'label' => NULL,
'url' => NULL,
],
'render element' => 'children',
],
'views_view_list__localgov_step_by_step_navigation__prev_next' => [
'base hook' => 'views_view_list',
],
];
}
/**
* Implements hook_localgov_role_default().
*/
function localgov_step_by_step_localgov_roles_default() {
// Content editing permissions.
$perms = [
RolesHelper::EDITOR_ROLE => [
'create localgov_step_by_step_overview content',
'create localgov_step_by_step_page content',
'delete any localgov_step_by_step_overview content',
'delete any localgov_step_by_step_page content',
'delete localgov_step_by_step_overview revisions',
'delete localgov_step_by_step_page revisions',
'delete own localgov_step_by_step_overview content',
'delete own localgov_step_by_step_page content',
'edit any localgov_step_by_step_overview content',
'edit any localgov_step_by_step_page content',
'edit own localgov_step_by_step_overview content',
'edit own localgov_step_by_step_page content',
'revert localgov_step_by_step_overview revisions',
'revert localgov_step_by_step_page revisions',
'view localgov_step_by_step_overview revisions',
'view localgov_step_by_step_page revisions',
],
RolesHelper::AUTHOR_ROLE => [
'create localgov_step_by_step_overview content',
'create localgov_step_by_step_page content',
'delete own localgov_step_by_step_overview content',
'delete own localgov_step_by_step_page content',
'edit own localgov_step_by_step_overview content',
'edit own localgov_step_by_step_page content',
'revert localgov_step_by_step_overview revisions',
'revert localgov_step_by_step_page revisions',
'view localgov_step_by_step_overview revisions',
'view localgov_step_by_step_page revisions',
],
RolesHelper::CONTRIBUTOR_ROLE => [
'create localgov_step_by_step_overview content',
'create localgov_step_by_step_page content',
'delete own localgov_step_by_step_overview content',
'delete own localgov_step_by_step_page content',
'edit own localgov_step_by_step_overview content',
'edit own localgov_step_by_step_page content',
'view localgov_step_by_step_overview revisions',
'view localgov_step_by_step_page revisions',
],
];
// Content scheduling permissions required by localgov_workflows.
if (\Drupal::moduleHandler()->moduleExists('localgov_workflows')) {
$perms[RolesHelper::EDITOR_ROLE] = array_merge($perms[RolesHelper::EDITOR_ROLE], [
'add scheduled transitions node localgov_step_by_step_overview',
'add scheduled transitions node localgov_step_by_step_page',
'reschedule scheduled transitions node localgov_step_by_step_overview',
'reschedule scheduled transitions node localgov_step_by_step_page',
'view scheduled transitions node localgov_step_by_step_overview',
'view scheduled transitions node localgov_step_by_step_page',
]);
$perms[RolesHelper::AUTHOR_ROLE] = array_merge($perms[RolesHelper::AUTHOR_ROLE], [
'add scheduled transitions node localgov_step_by_step_overview',
'add scheduled transitions node localgov_step_by_step_page',
'reschedule scheduled transitions node localgov_step_by_step_overview',
'reschedule scheduled transitions node localgov_step_by_step_page',
'view scheduled transitions node localgov_step_by_step_overview',
'view scheduled transitions node localgov_step_by_step_page',
]);
$perms[RolesHelper::CONTRIBUTOR_ROLE] = array_merge($perms[RolesHelper::CONTRIBUTOR_ROLE], [
'add scheduled transitions node localgov_step_by_step_overview',
'add scheduled transitions node localgov_step_by_step_page',
'reschedule scheduled transitions node localgov_step_by_step_overview',
'reschedule scheduled transitions node localgov_step_by_step_page',
'view scheduled transitions node localgov_step_by_step_overview',
'view scheduled transitions node localgov_step_by_step_page',
]);
}
return $perms;
}
/**
* Implements hook_ENTITY_TYPE_insert().
*/
function localgov_step_by_step_node_insert(EntityInterface $entity) {
localgov_step_by_step_node_update($entity);
}
/**
* Implements hook_ENTITY_TYPE_update().
*
* The step_by_step_overview and step_by_step_page content types reference each
* other. When a step_by_step_page type node is updated, find its
* step_by_step_overview node. Then make sure this step_by_step_overview node
* refers back to the step_by_step_page node.
*/
function localgov_step_by_step_node_update(EntityInterface $entity) {
$is_not_step_by_step_page_node = ($entity->bundle() !== 'localgov_step_by_step_page');
if ($is_not_step_by_step_page_node) {
return;
}
$step_by_step_page_node = $entity;
$step_by_step_page_nid = $step_by_step_page_node->id();
$step_by_step_overview_node = $step_by_step_page_node->localgov_step_parent->entity ?? FALSE;
if (empty($step_by_step_overview_node)) {
return;
}
try {
$has_ref_to_this_step_by_step_page = array_filter($step_by_step_overview_node->localgov_step_by_step_pages->referencedEntities(), function (EntityInterface $page_node) use ($step_by_step_page_nid): bool {
return $page_node->id() === $step_by_step_page_nid;
});
if ($has_ref_to_this_step_by_step_page) {
return;
}
$step_by_step_overview_node->localgov_step_by_step_pages->appendItem($step_by_step_page_nid);
$step_by_step_overview_node->save();
}
catch (Exception $e) {
Drupal::service('logger.factory')->get('localgov-step-by-step')->error($e->getMessage());
}
}
/**
* Implements hook_preprocess_views_view_list().
*
* Marks the rows corresponding to the current, previous, and next nodes.
*/
function localgov_step_by_step_preprocess_views_view_list(array &$variables) {
$view = $variables['view'];
$view_id = $view->id();
$view_display_id = $view->current_display;
$is_step_by_step_nav = ($view_id === 'localgov_step_by_step_navigation');
$is_step_by_step_nav_block = ($view_display_id === 'steps');
$is_step_by_step_prev_next_block = ($view_display_id === 'prev_next');
$current_nid = $is_step_by_step_nav ? $view->args[0] : '';
if ($is_step_by_step_nav && $is_step_by_step_prev_next_block) {
_localgov_step_by_step_find_prev_next_steps($current_nid, $variables);
}
elseif ($is_step_by_step_nav && $is_step_by_step_nav_block) {
_localgov_step_by_step_mark_current_step($current_nid, $variables);
}
if ($is_step_by_step_nav) {
$variables['view']->element['#attached']['library'][] = 'localgov_step_by_step/step-by-step-nav';
}
}
/**
* Find previous and next steps.
*
* Find the previous and next Step by step page nodes relative to the current
* node. The current node is the one where we are displaying this block. Its
* node ID is treated as the first contextual argument of our View.
*/
function _localgov_step_by_step_find_prev_next_steps(string $current_nid, array &$variables): void {
$prev_step_index = -1;
$next_step_index = -1;
foreach ($variables['rows'] as $key => $row) {
$row_nid = $row['content']['#row']->node_field_data_node__localgov_step_by_step_pages_1_nid ?? '-1';
$is_current_step = ($row_nid === $current_nid);
if ($is_current_step) {
$prev_step_index = $key - 1;
$next_step_index = $key + 1;
break;
}
}
$variables['has_prev_step'] = array_key_exists($prev_step_index, $variables['rows']);
$variables['has_next_step'] = array_key_exists($next_step_index, $variables['rows']);
$variables['prev_step_nid'] = $variables['rows'][$prev_step_index]['content']['#row']->node_field_data_node__localgov_step_by_step_pages_1_nid ?? -1;
$variables['next_step_nid'] = $variables['rows'][$next_step_index]['content']['#row']->node_field_data_node__localgov_step_by_step_pages_1_nid ?? -1;
$variables['prev_step_link_text'] = t('Previous Step');
$variables['prev_step_index'] = $prev_step_index;
$variables['next_step_index'] = $next_step_index;
$is_first_step = ($next_step_index === 1);
$variables['next_step_link_text'] = $is_first_step ? t('Next Step') : t('Next Step');
$node_storage = \Drupal::entityTypeManager()->getStorage('node');
if ($variables['has_next_step']) {
$variables['next_step_title'] = $node_storage->load($variables['next_step_nid'])->title->value;
}
if ($variables['has_prev_step']) {
$variables['prev_step_title'] = $node_storage->load($variables['prev_step_nid'])->title->value;
}
}
/**
* Mark the row corresponding to the current Step by step page node.
*/
function _localgov_step_by_step_mark_current_step(string $current_nid, array &$variables): void {
foreach ($variables['rows'] as &$row) {
$row_nid = $row['content']['#row']->node_field_data_node__localgov_step_by_step_pages_1_nid ?? '-1';
$is_current_step = ($row_nid === $current_nid);
if ($is_current_step) {
$row['attributes']['class'][] = 'step--active';
$row['attributes']['aria-current'] = 'step';
break;
}
}
}
/**
* Implements hook_modules_installed().
*/
function localgov_step_by_step_modules_installed($modules) {
$services = in_array('localgov_services_navigation', $modules, TRUE);
$topics = in_array('localgov_topics', $modules, TRUE);
if ($services) {
\Drupal::service('config.installer')->installOptionalConfig(NULL, [
'config' => 'field.storage.node.localgov_services_parent',
]);
}
if ($topics) {
\Drupal::service('config.installer')->installOptionalConfig(NULL, [
'config' => 'field.storage.node.localgov_topic_classified',
]);
}
if ($services || $topics) {
localgov_step_by_step_optional_fields_settings($services, $topics);
}
}
/**
* Set form settings for optional services and topic fields on installation.
*
* @param bool $services
* If localgov_services is (being) installed.
* @param bool $topics
* If localgov_topics is (being) installed.
*/
function localgov_step_by_step_optional_fields_settings($services, $topics) {
$properties = [
'targetEntityType' => 'node',
'bundle' => 'localgov_step_by_step_overview',
];
if ($form_displays = \Drupal::entityTypeManager()->getStorage('entity_form_display')->loadByProperties($properties)) {
foreach ($form_displays as $form_display) {
assert($form_display instanceof EntityFormDisplayInterface);
if ($services && !$form_display->getComponent('localgov_services_parent')) {
$form_display->setComponent('localgov_services_parent', [
'type' => 'entity_reference_autocomplete',
'region' => 'content',
'settings' => [
'match_operator' => 'CONTAINS',
'size' => '60',
'placeholder' => '',
'match_limit' => 10,
],
'weight' => -1,
])->save();
}
if ($topics && !$form_display->getComponent('localgov_topic_classified')) {
$form_display->setComponent('localgov_topic_classified', [
'type' => 'entity_reference_autocomplete',
'region' => 'content',
'settings' => [
'match_operator' => 'CONTAINS',
'size' => '60',
'placeholder' => '',
'match_limit' => 10,
],
'weight' => 50,
])->save();
}
}
}
}
