onlyone.module in Allow a content type only once (Only One) 8
Same filename and directory in other branches
Contains onlyone.module.
File
onlyone.moduleView source
<?php
/**
* @file
* Contains onlyone.module.
*/
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\Core\Link;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Render\Markup;
/**
* Implements hook_help().
*/
function onlyone_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help.
case 'help.page.onlyone':
// The route onlyone.add_page exists or not?
if (\Drupal::service('config.factory')
->get('onlyone.settings')
->get('onlyone_new_menu_entry')) {
// Creating the link.
$onlyone_add_page_link = Link::fromTextAndUrl(t('Add content (Only One)'), Url::fromRoute('onlyone.add_page'))
->toString();
$onlyone_add_page = t('@link page', [
'@link' => $onlyone_add_page_link,
]);
}
else {
// As the route doesn't exists we use a string.
$onlyone_add_page = t('<em>Add content (Only One)</em> page (onlyone/add)');
}
// Array with routes to replace.
$routes = [
':settings-page' => Url::fromRoute('onlyone.admin_settings')
->toString(),
':content' => Url::fromRoute('system.admin_content')
->toString(),
'@onlyone_add_page' => $onlyone_add_page,
':add-content' => Url::fromRoute('node.add_page')
->toString(),
];
// Getting the help link for the admin_toolbar module.
$admin_toolbar_page = \Drupal::service('onlyone.module_handler')
->getModuleHelpPageLink('admin_toolbar', 'Admin Toolbar', TRUE);
// Getting the help link for the admin_toolbar_tools module.
$admin_toolbar_tools_page = \Drupal::service('onlyone.module_handler')
->getModuleHelpPageLink('admin_toolbar_tools', 'Admin Toolbar Extra Tools', TRUE);
// Getting the help link for the onlyone_admin_toolbar module.
$onlyone_admin_toolbar = \Drupal::service('onlyone.module_handler')
->getModuleHelpPageLink('onlyone_admin_toolbar', 'Allow a content type only once (Only One) for Admin Toolbar');
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Allow a content type only once (Only One) module allows the creation of Only One content per language in the selected content types for this configuration.') . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Configuring content types') . '</dt>';
$output .= '<dd>' . t('To configure the content types to allow for Only One content per language, visit the <a href=":config-page">Only One</a> page, in the <em>Available content types for Only One</em> section and <em>check</em> the content types that should have Only One content per language. For this you need the <em>Administer Only One</em> permission.', [
':config-page' => Url::fromRoute('onlyone.config_content_types')
->toString(),
]) . '</dd>';
$output .= '<dt>' . t('Configuring module settings') . '</dt>';
$output .= '<dd>' . t('To configure the module settings visit the <a href=":settings-page">Settings</a> page, if you want to have the configured content types in a new menu entry named <em>Add content (Only One)</em> you must check the option <em>Show configured content types in a new menu entry</em>, the new menu link will be available in the <a href=":content">Content</a> page as an action link to the @onlyone_add_page, then the <a href=":add-content">Add content</a> page will show the not configured content types. For this you need the <em>Administer Only One</em> permission.', $routes) . '</dd>';
$output .= '<dt>' . t('Creating content') . '</dt>';
$output .= '<dd>' . t('Once you try to <a href=":add-content">Add content</a>, if the chosen content type is configured to have Only One content and it already has one content created in the actual language, you will be redirected to <em>edit</em> the content, otherwise, you will go to create a new one.', [
':add-content' => Url::fromRoute('node.add_page')
->toString(),
]) . '</dd>';
$output .= '</dl>';
$output .= '<h3>' . t('Aditionals modules') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . $onlyone_admin_toolbar . '</dt>';
$output .= '<dd>' . t('Very useful if you use the @admin_toolbar_page module as it handles modifications to the @admin_toolbar_tools_page module menu entries related to the configured content types.', [
'@admin_toolbar_page' => $admin_toolbar_page,
'@admin_toolbar_tools_page' => $admin_toolbar_tools_page,
]) . '</dd>';
$output .= '</dl>';
return $output;
}
}
/**
* Implements hook_menu_local_actions_alter().
*/
function onlyone_menu_local_actions_alter(&$local_actions) {
// Adding the local actions if the new menu entry option is active.
if (\Drupal::config('onlyone.settings')
->get('onlyone_new_menu_entry')) {
$local_actions['onlyone.add_page'] = [
'title' => t('Add content (Only One)'),
'weight' => -1,
'route_name' => 'onlyone.add_page',
'options' => [],
'appears_on' => [
'system.admin_content',
],
'class' => 'Drupal\\Core\\Menu\\LocalActionDefault',
];
}
}
/**
* Implements hook_menu_links_discovered_alter().
*/
function onlyone_menu_links_discovered_alter(&$links) {
// Adding the menu link if the new menu entry option is active.
if (\Drupal::config('onlyone.settings')
->get('onlyone_new_menu_entry')) {
$links['onlyone.add_page'] = [
'title' => t('Add content (Only One)'),
'route_name' => 'onlyone.add_page',
'menu_name' => 'admin',
'parent' => 'system.admin_content',
'description' => t('Add content page for content types configured to have Only One node per language.'),
];
}
}
/**
* Implements hook_preprocess_HOOK() for block content add list templates.
*/
function onlyone_preprocess_node_add_list(&$variables) {
// Getting the route.
$route = \Drupal::request()->attributes
->get('_route');
// Getting variable to know if we should show the configured content type
// in a new page.
$onlyone_new_menu_entry = \Drupal::config('onlyone.settings')
->get('onlyone_new_menu_entry');
// Leaving this code here until this issue will be resolved:
// https://www.drupal.org/project/drupal/issues/2965718
// @see https://www.drupal.org/project/onlyone/issues/3029598
// Creating the message variable.
if ($route == 'onlyone.add_page') {
$variables['message'] = t('You have not configured any content type yet, go to the <a href=":config-content-types">Only One page</a> to configure the content types.', [
':config-content-types' => Url::fromRoute('onlyone.config_content_types')
->toString(),
]);
}
else {
if ($onlyone_new_menu_entry) {
$variables['message'] = t('All the content types are configured to have Only One node. Go to the <a href=":add-onlyone-content-type">Add content (Only One)</a> page to create or edit content.', [
':add-onlyone-content-type' => Url::fromRoute('onlyone.add_page')
->toString(),
]);
}
else {
$variables['message'] = t('You have not created any content types yet. Go to the <a href=":add-content-type">Add content type</a> page to create content types.', [
':add-content-type' => Url::fromRoute('node.type_add')
->toString(),
]);
}
}
// Getting the configured content types.
$onlyone_content_types = \Drupal::config('onlyone.settings')
->get('onlyone_node_types');
// Modifying the contet types information if needed.
foreach ($onlyone_content_types as $content_type_machine_name) {
// If the user don't have permission to create the content type even if it
// is configured to have only one node the content type will not exists
// in the render array.
// See: https://www.drupal.org/project/onlyone/issues/3028525 .
if (empty($variables['content'][$content_type_machine_name])) {
continue;
}
// Getting help from the community to solve this part, see:
// https://drupal.stackexchange.com/q/244030/28275 .
// We need to modify the links?
if (!($onlyone_new_menu_entry xor $route == 'onlyone.add_page')) {
// Getting the content type.
$content_type = $variables['content'][$content_type_machine_name];
// Checking if exists nodes created for the content type.
if (\Drupal::service('onlyone')
->existsNodesContentType($content_type_machine_name)) {
// Assigning the new name.
$new_name = t('@content_type_name (Edit)', [
'@content_type_name' => $content_type
->get('name'),
]);
$variables['content'][$content_type_machine_name]
->set('name', $new_name);
// Changing the value in the original template, because all the themes
// dont' use the same variables, see the seven theme as example.
// @see template_preprocess_block_content_add_list().
$variables['types'][$content_type_machine_name]['title'] = $new_name;
}
$original_description = empty($content_type
->getDescription()) ? '' : rtrim($content_type
->getDescription(), '.') . '.';
$original_description_markup = Markup::create($original_description);
$description = t('@description <strong>Only a single node can be created and edited</strong>.', [
'@description' => $original_description_markup,
]);
// Changing the value in the content type.
$variables['content'][$content_type_machine_name]
->set('description', $description);
// Changing the value in the original template, because all the themes
// dont' use the same variables, see the seven theme as example.
// @see template_preprocess_block_content_add_list().
$variables['types'][$content_type_machine_name]['description'] = $description;
}
else {
// We need to delete the links.
unset($variables['content'][$content_type_machine_name]);
unset($variables['types'][$content_type_machine_name]);
}
}
}
/**
* Implements hook_form_BASE_FORM_ID_alter() for node_form.
*/
function onlyone_form_node_form_alter(&$form, FormStateInterface &$form_state, $form_id) {
// Getting the configured content types.
$onlyone_content_types = \Drupal::config('onlyone.settings')
->get('onlyone_node_types');
$onlyone_redirect = \Drupal::config('onlyone.settings')
->get('onlyone_redirect');
// Getting the node.
$node = $form_state
->getFormObject()
->getEntity();
// Verifying if the new node should by onlyone and if we are trying to create
// a new node.
if (isset($onlyone_content_types) && in_array($node
->getType(), $onlyone_content_types) && $node
->isNew()) {
// If we have one node, then redirect to the edit page.
$nid = \Drupal::service('onlyone')
->existsNodesContentType($node
->getType());
if ($nid) {
// Creating the url.
if ($onlyone_redirect) {
$route = 'entity.node.edit_form';
}
else {
$route = 'entity.node.canonical';
}
$url = Url::fromRoute($route, [
'node' => $nid,
])
->toString();
// Redirecting to edit the only one node for this content type.
$response = new RedirectResponse($url);
$response
->send();
}
}
}
/**
* Implements hook_node_type_delete().
*/
function onlyone_node_type_delete(EntityInterface $node) {
// Getting the content type machine name.
$content_type = $node
->id();
// Deleting the value from the config.
\Drupal::service('onlyone')
->deleteContentTypeConfig($content_type);
}
/**
* Implements hook_entity_type_alter().
*/
function onlyone_entity_type_alter(array &$entity_types) {
// Adding the constraint. Here is not possible to check specific content type.
// @see https://drupal.stackexchange.com/q/208283/28275
if (isset($entity_types['node'])) {
$entity_types['node']
->addConstraint('OnlyOne');
}
}
Functions
Name | Description |
---|---|
onlyone_entity_type_alter | Implements hook_entity_type_alter(). |
onlyone_form_node_form_alter | Implements hook_form_BASE_FORM_ID_alter() for node_form. |
onlyone_help | Implements hook_help(). |
onlyone_menu_links_discovered_alter | Implements hook_menu_links_discovered_alter(). |
onlyone_menu_local_actions_alter | Implements hook_menu_local_actions_alter(). |
onlyone_node_type_delete | Implements hook_node_type_delete(). |
onlyone_preprocess_node_add_list | Implements hook_preprocess_HOOK() for block content add list templates. |