Skip to content
Snippets Groups Projects
Commit 8d0bce68 authored by Ivan Doroshenko's avatar Ivan Doroshenko
Browse files

Issue #3341902 by Matroskeen: Add message for admins to indicate what action would happen

parent 9ffacb46
No related branches found
No related tags found
2 merge requests!68Issue #3298741: Fix the issues reported by phpcs,!56Issue #3341902: Add message for admins to indicate what action would happen.
......@@ -34,6 +34,9 @@ rabbit_hole.behavior_settings.*:
no_bypass:
type: boolean
label: 'No bypass'
bypass_message:
type: boolean
label: 'Show bypass message'
configuration:
type: rabbit_hole.behavior.[%parent.action]
......
......@@ -363,3 +363,17 @@ function rabbit_hole_update_8110() {
$config->save(TRUE);
}
}
/**
* Add "bypass_message" settings to existing configuration.
*/
function rabbit_hole_update_8111() {
$config_factory = \Drupal::configFactory();
$configs = $config_factory->listAll('rabbit_hole.behavior_settings');
foreach ($configs as $config) {
$config = $config_factory->getEditable($config);
$config->set('bypass_message', FALSE);
$config->save(TRUE);
}
}
......@@ -164,18 +164,29 @@ class BehaviorInvoker implements BehaviorInvokerInterface {
// Allow altering Rabbit Hole values.
$this->moduleHandler->alter('rabbit_hole_values', $values, $entity);
// Do nothing if action is missing or access is bypassed.
if (empty($values['action']) || $values['bypass_access']) {
return NULL;
}
try {
/** @var \Drupal\rabbit_hole\Plugin\RabbitHoleBehaviorPluginInterface $instance */
$instance = $this->rhBehaviorPluginManager->createInstance($values['action'], $values);
}
catch (PluginException $e) {
watchdog_exception('rabbit_hole', $e);
return NULL;
}
// If configured, display a message explaining the Rabbit Hole is enabled.
if ($values['bypass_access']) {
// @todo Check whether plugin instance is suitable for the message instead
// of checking particular ID. It could be some additional method in the
// plugin interface.
if ($values['bypass_message'] && $instance->getPluginId() !== 'display_page') {
$message = t('This page is configured to apply "@action" Rabbit Hole action, but you have permission to see the page.', [
'@action' => $instance->getPluginDefinition()['label'],
]);
\Drupal::messenger()->addWarning($message);
}
return NULL;
}
return $instance ?? NULL;
return $instance;
}
}
......@@ -123,6 +123,7 @@ class BehaviorSettingsManager implements BehaviorSettingsManagerInterface {
return !$default->isNew() ? $default->get() : [
'action' => 'display_page',
'no_bypass' => FALSE,
'bypass_message' => FALSE,
'configuration' => [],
];
}
......@@ -134,6 +135,7 @@ class BehaviorSettingsManager implements BehaviorSettingsManagerInterface {
$config_data = $this->getBehaviorSettings($entity->getEntityTypeId(), $entity->bundle());
$values = [
'no_bypass' => $config_data['no_bypass'],
'bypass_message' => $config_data['bypass_message'],
];
// We trigger the default bundle action under the following circumstances:
......
......@@ -26,6 +26,7 @@ use Drupal\rabbit_hole\BehaviorSettingsInterface;
* "uuid",
* "action",
* "no_bypass",
* "bypass_message",
* "configuration"
* },
* links = {}
......
......@@ -86,12 +86,6 @@ class FormManglerService {
];
// Apply form modifications from plugins.
$parents = $form['#parents'] ?? [];
$action_path = array_shift($parents);
foreach (array_merge($parents, ['action']) as $element) {
$action_path .= '[' . $element . ']';
}
foreach ($this->rhBehaviorPluginManager->getDefinitions() as $id => $definition) {
$plugin = $this->rhBehaviorPluginManager->createInstance($id, $settings['configuration']);
$plugin_form = $plugin->buildConfigurationForm([], $form_state);
......@@ -104,7 +98,7 @@ class FormManglerService {
'#tree' => TRUE,
'#states' => [
'visible' => [
':input[name="' . $action_path . '"]' => ['value' => $id],
':input[name="' . $this->getInputSelector($form, 'action') . '"]' => ['value' => $id],
],
],
] + $plugin_form;
......@@ -134,6 +128,23 @@ class FormManglerService {
'#title' => $this->t('Disable permissions-based bypassing'),
'#default_value' => $settings['no_bypass'],
'#description' => $this->t("If checked, users won't be able to bypass configured Rabbit Hole behavior. It will be applied to Administrators and other users with bypass permissions."),
'#states' => [
'invisible' => [
':input[name="' . $this->getInputSelector($form, 'bypass_message') . '"]' => ['checked' => TRUE],
],
],
];
$form['bypass_message'] = [
'#type' => 'checkbox',
'#title' => $this->t('Display a message when viewing the page'),
'#default_value' => $settings['bypass_message'],
'#description' => $this->t("If checked, users who bypassed the Rabbit Hole action, will see a warning message when viewing the page."),
'#states' => [
'invisible' => [
':input[name="' . $this->getInputSelector($form, 'no_bypass') . '"]' => ['checked' => TRUE],
],
],
];
}
......@@ -170,6 +181,7 @@ class FormManglerService {
$settings = [
'action' => $action,
'no_bypass' => $form_values['no_bypass'],
'bypass_message' => $form_values['bypass_message'],
];
// Get action settings if it exists in the form.
......@@ -241,4 +253,23 @@ class FormManglerService {
}
}
/**
* Builds the full input selector based on available parents.
*
* @param array $form
* An associative array containing the structure of the form.
* @param string $name
* Input name.
* @return string
* The full input path.
*/
protected function getInputSelector(array $form, string $name): string {
$parents = $form['#parents'] ?? [];
$selector = $root = array_shift($parents);
if ($parents) {
$selector = $root . '[' . implode('][', array_merge($parents, [$name])) . ']';
}
return $selector;
}
}
<?php
namespace Drupal\Tests\rabbit_hole\Functional;
use Drupal\node\Entity\Node;
use Drupal\Tests\BrowserTestBase;
/**
* Functional tests of Rabbit Hole generic behavior.
*
* @group rabbit_hole
*/
class RabbitHoleBehaviorFunctionalTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
protected $profile = 'standard';
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
public static $modules = ['rabbit_hole', 'node'];
/**
* The behavior settings manager.
*
* @var \Drupal\rabbit_hole\BehaviorSettingsManagerInterface
*/
protected $behaviorSettingsManager;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->setUpCurrentUser();
$this->behaviorSettingsManager = $this->container->get('rabbit_hole.behavior_settings_manager');
$this->behaviorSettingsManager->enableEntityType('node');
$this->behaviorSettingsManager->saveBehaviorSettings([
'action' => 'page_not_found',
'bypass_message' => FALSE,
], 'node_type', 'article');
\Drupal::service('rabbit_hole.entity_helper')->createRabbitHoleField('node', 'article');
}
/**
* Tests the bypass warning message.
*/
public function testBypassMessage() {
$node1 = Node::create(['title' => '#standWithUkraine', 'type' => 'article']);
$node1->save();
// Verify the "Page Not Found" is working for regular users and message is
// not displayed.
$this->drupalGet($node1->toUrl());
$this->assertSession()->statusCodeEquals(404);
$this->assertSession()->responseNotContains('This page is configured to apply "Page not found" Rabbit Hole action, but you have permission to see the page.');
// Verify the user with bypass access - the message is still disabled.
$this->drupalLogin($this->createUser(['rabbit hole bypass node']));
$this->drupalGet($node1->toUrl());
$this->assertSession()->statusCodeEquals(200);
$this->assertSession()->responseNotContains('This page is configured to apply "Page not found" Rabbit Hole action, but you have permission to see the page.');
// Now enable the bypass message and check whether it's available.
$this->behaviorSettingsManager->saveBehaviorSettings([
'bypass_message' => TRUE,
], 'node_type', 'article');
$this->drupalGet($node1->toUrl());
$this->assertSession()->statusCodeEquals(200);
$this->assertSession()->responseContains('This page is configured to apply "Page not found" Rabbit Hole action, but you have permission to see the page.');
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment