node_singles-3.0.2/node_singles.module
node_singles.module
<?php
/**
* @file
* Hook implementations for the node singles module.
*/
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Url;
use Drupal\node\Entity\NodeType;
use Drupal\node_singles\Access\DecoratedNodeAccessControlHandler;
use Drupal\node_singles\Access\SingleNodeAccessControlHandler;
use Drupal\node_singles\Form\SingleNodeTypeDeleteConfirm;
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function node_singles_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the node_singles module.
case 'help.page.node_singles':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Singles are node types used for one-off pages that have unique content requirements') . '</p>';
$output .= '<h3>' . t('More Information') . '</h3>';
$output .= '<p>' . t('For more information about this module please visit the <a href="@link">module page</a>.', ['@link' => 'https://www.drupal.org/project/node_singles']) . '</p>';
return $output;
default:
}
}
/**
* Implements @see hook_entity_operation_alter().
*/
function node_singles_entity_operation_alter(array &$operations, EntityInterface $entity): void {
/** @var \Drupal\Core\Entity\EntityInterface|null $single */
$single = \Drupal::service('node_singles')->getSingleByBundle($entity->bundle());
if ($entity->getEntityTypeId() !== 'node' || !$single) {
return;
}
$operations['view'] = [
'title' => t('View'),
'weight' => 5,
'url' => Url::fromRoute('entity.node.canonical', ['node' => $entity->id()]),
];
if (!empty($operations['edit'])) {
$operations['edit']['weight'] = 4;
}
if (!empty($operations['delete'])) {
$operations['delete']['weight'] = 15;
}
$nodeType = NodeType::load($entity->bundle());
$nodeTypeOperations = \Drupal::entityTypeManager()
->getListBuilder('node_type')
->getOperations($nodeType);
if (isset($nodeTypeOperations['edit'])) {
$nodeTypeOperations['edit']['title'] = t('Edit type');
$nodeTypeOperations['edit-type'] = $nodeTypeOperations['edit'];
unset($nodeTypeOperations['edit']);
}
$operations += $nodeTypeOperations;
}
/**
* Implements @see hook_menu_links_discovered_alter().
*/
function node_singles_menu_links_discovered_alter(array &$links): void {
$singles = \Drupal::getContainer()->get('node_singles')->getAllSingles();
$settings = \Drupal::getContainer()->get('node_singles.settings');
foreach ($links as $name => $link) {
// Remove single node add menu links added by modules like
// admin_toolbar_tools. The node access handler should deal
// with this, but it doesn't for user 1.
if (
isset($link['route_name'])
&& $link['route_name'] === 'node.add'
&& isset($singles[$link['route_parameters']['node_type']])
) {
unset($links[$name]);
}
// Change the label of the menu links.
$links['node_singles.content']['title'] = $settings->getCollectionLabel();
$links['node_singles.settings']['title'] = $settings->getCollectionLabel();
}
}
/**
* Implements @see hook_local_tasks_alter().
*/
function node_singles_local_tasks_alter(array &$localTasks): void {
$localTasks['node_singles.overview']['title'] = \Drupal::getContainer()->get('node_singles.settings')->getCollectionLabel();
}
/**
* Implements @see hook_entity_insert().
*/
function node_singles_entity_insert(EntityInterface $entity): void {
\Drupal::getContainer()
->get('node_singles.node_type_update.subscriber')
->checkForSingles($entity);
}
/**
* Implements @see hook_entity_update().
*/
function node_singles_entity_update(EntityInterface $entity): void {
\Drupal::getContainer()
->get('node_singles.node_type_update.subscriber')
->checkForSingles($entity);
}
/**
* Implements @see hook_form_BASE_FORM_ID_alter().
*/
function node_singles_form_node_type_form_alter(array &$form, FormStateInterface $formState): void {
\Drupal::getContainer()
->get('node_singles.node_type_form.subscriber')
->alterNodeTypeForm($form, $formState);
}
/**
* Implements @see hook_form_BASE_FORM_ID_alter().
*/
function node_singles_form_node_form_alter(array &$form): void {
\Drupal::getContainer()
->get('node_singles.node_form.subscriber')
->formAlter($form);
}
/**
* Implements @see hook_entity_type_alter().
*/
function node_singles_entity_type_alter(array &$entityTypes): void {
$state = \Drupal::getContainer()->get('state');
$nodeHandlerClass = $entityTypes['node']->getHandlerClass('access');
$state->set(DecoratedNodeAccessControlHandler::STATE_KEY, $nodeHandlerClass);
$entityTypes['node']->setHandlerClass('access', SingleNodeAccessControlHandler::class);
$entityTypes['node_type']->setFormClass('delete', SingleNodeTypeDeleteConfirm::class);
}
/**
* Implements @see hook_form_FORM_ID_alter().
*
* Hide some single node permissions since they aren't relevant.
*/
function node_singles_form_user_admin_permissions_alter(&$form, FormStateInterface $form_state, $form_id): void {
$singles = \Drupal::getContainer()->get('node_singles')->getAllSingles();
foreach ($singles as $single) {
$permissions = [
sprintf('create %s content', $single->id()),
sprintf('delete any %s content', $single->id()),
sprintf('delete own %s content', $single->id()),
];
foreach ($permissions as $permission) {
if (isset($form['permissions'][$permission])) {
// Unsetting because #access = false doesn't work.
// @see https://www.drupal.org/project/drupal/issues/3123459
unset($form['permissions'][$permission]);
}
}
}
}
/**
* Implements @see hook_views_data_alter().
*/
function node_singles_views_data_alter(array &$data): void {
$settings = \Drupal::getContainer()->get('node_singles.settings');
$data['node']['node_singles'] = [
'title' => $settings->getCollectionLabel(),
'filter' => [
'title' => $settings->getCollectionLabel(),
'help' => t("Filter @singlesPluralLabel.", [
'@singlesPluralLabel' => $settings->getPluralLabel(),
]),
'field' => 'type',
'id' => 'node_singles',
],
];
$data['node']['node_non_singles'] = [
'title' => t("All nodes except @singlesPluralLabel", [
'@singlesPluralLabel' => Markup::create($settings->getPluralLabel()),
]),
'filter' => [
'title' => t("All nodes except @singlesPluralLabel", [
'@singlesPluralLabel' => Markup::create($settings->getPluralLabel()),
]),
'help' => t("Filter all nodes except @singlesPluralLabel.", [
'@singlesPluralLabel' => Markup::create($settings->getPluralLabel()),
]),
'field' => 'type',
'id' => 'node_non_singles',
],
];
}
/**
* Implements hook_module_implements_alter().
*/
function node_singles_module_implements_alter(array &$implementations, string|int $hook): void {
// Move our hook to be executed last, after modules like trash.
if ($hook === 'entity_type_alter') {
$value = $implementations['node_singles'];
unset($implementations['node_singles']);
$implementations['node_singles'] = $value;
}
}
