class PageRedirect in Rabbit Hole 8
Same name and namespace in other branches
- 2.x src/Plugin/RabbitHoleBehaviorPlugin/PageRedirect.php \Drupal\rabbit_hole\Plugin\RabbitHoleBehaviorPlugin\PageRedirect
Redirects to another page.
Plugin annotation
@RabbitHoleBehaviorPlugin(
id = "page_redirect",
label = @Translation("Page redirect")
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\rabbit_hole\Plugin\RabbitHoleBehaviorPluginBase implements RabbitHoleBehaviorPluginInterface
- class \Drupal\rabbit_hole\Plugin\RabbitHoleBehaviorPlugin\PageRedirect implements ContainerFactoryPluginInterface uses StringTranslationTrait
- class \Drupal\rabbit_hole\Plugin\RabbitHoleBehaviorPluginBase implements RabbitHoleBehaviorPluginInterface
Expanded class hierarchy of PageRedirect
1 file declares its use of PageRedirect
- RabbitHoleBehaviorPluginTest.php in tests/
src/ Functional/ RabbitHoleBehaviorPluginTest.php
File
- src/
Plugin/ RabbitHoleBehaviorPlugin/ PageRedirect.php, line 34
Namespace
Drupal\rabbit_hole\Plugin\RabbitHoleBehaviorPluginView source
class PageRedirect extends RabbitHoleBehaviorPluginBase implements ContainerFactoryPluginInterface {
use StringTranslationTrait;
const RABBIT_HOLE_PAGE_REDIRECT_DEFAULT = '';
const RABBIT_HOLE_PAGE_REDIRECT_RESPONSE_DEFAULT = 301;
const REDIRECT_MOVED_PERMANENTLY = 301;
const REDIRECT_FOUND = 302;
const REDIRECT_SEE_OTHER = 303;
const REDIRECT_NOT_MODIFIED = 304;
const REDIRECT_USE_PROXY = 305;
const REDIRECT_TEMPORARY_REDIRECT = 307;
/**
* The redirect path.
*
* @var string
*/
private $path;
/**
* The HTTP response code.
*
* @var string
*/
private $code;
/**
* The entity plugin manager.
*
* @var \Drupal\rabbit_hole\Plugin\RabbitHoleEntityPluginManager
*/
protected $rhEntityPluginManager;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The token service.
*
* @var \Drupal\Core\Utility\Token
*/
protected $token;
/**
* Cache metadata for the redirect response.
*
* @var \Drupal\Core\Render\BubbleableMetadata
*/
protected $cacheMetadata;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, RabbitHoleEntityPluginManager $rhepm, ModuleHandlerInterface $mhi, Token $token) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->rhEntityPluginManager = $rhepm;
$this->moduleHandler = $mhi;
$this->token = $token;
$this->cacheMetadata = new BubbleableMetadata();
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('plugin.manager.rabbit_hole_entity_plugin'), $container
->get('module_handler'), $container
->get('token'));
}
/**
* {@inheritdoc}
*/
public function performAction(EntityInterface $entity, Response $current_response = NULL) {
$target = $this
->getActionTarget($entity);
$response_code = $this
->getActionResponseCode($entity);
// The fallback action is executed if redirect target is either empty or
// has invalid value.
if (empty($target)) {
return $this
->getFallbackAction($entity);
}
switch ($response_code) {
case self::REDIRECT_MOVED_PERMANENTLY:
case self::REDIRECT_FOUND:
case self::REDIRECT_SEE_OTHER:
case self::REDIRECT_TEMPORARY_REDIRECT:
if ($current_response === NULL) {
$redirect_response = new TrustedRedirectResponse($target, $response_code);
$redirect_response
->addCacheableDependency($this->cacheMetadata);
return $redirect_response;
}
else {
// If a response already exists we don't need to do anything with it.
return $current_response;
}
// TODO: I don't think this is the correct way to handle a 304 response.
case self::REDIRECT_NOT_MODIFIED:
if ($current_response === NULL) {
$not_modified_response = new Response();
$not_modified_response
->setStatusCode(self::REDIRECT_NOT_MODIFIED);
$not_modified_response->headers
->set('Location', $target);
return $not_modified_response;
}
else {
// If a response already exists we don't need to do anything with it.
return $current_response;
}
// TODO: I have no idea if this is actually the correct way to handle a
// 305 response in Symfony/D8. Documentation on it seems a bit sparse.
case self::REDIRECT_USE_PROXY:
if ($current_response === NULL) {
$use_proxy_response = new Response();
$use_proxy_response
->setStatusCode(self::REDIRECT_USE_PROXY);
$use_proxy_response->headers
->set('Location', $target);
return $use_proxy_response;
}
else {
// If a response already exists we don't need to do anything with it.
return $current_response;
}
default:
throw new InvalidRedirectResponseException();
}
}
/**
* Returns the action target URL object.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity the action is being performed on.
*
* @return string|null
* Absolute destination URL or NULL if proper URL wasn't found.
*/
public function getActionTarget(EntityInterface $entity) {
$target = $entity
->get('rh_redirect')->value;
if (empty($target)) {
$bundle_settings = $this
->getBundleSettings($entity);
$target = $bundle_settings
->get('redirect');
$this->cacheMetadata
->addCacheableDependency($bundle_settings);
}
// Replace any tokens if applicable.
$langcode = $entity
->language()
->getId();
if ($langcode == LanguageInterface::LANGCODE_NOT_APPLICABLE) {
$langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED;
}
// Convert <front> into valid URI.
$target = $target === '<front>' ? 'base:/' : $target;
$target = $this->token
->replace($target, [
$entity
->getEntityTypeId() => $entity,
], [
'clear' => TRUE,
'langcode' => $langcode,
], $this->cacheMetadata);
$target = PlainTextOutput::renderFromHtml($target);
if (empty($target)) {
return NULL;
}
// If non-absolute URI, pass URL through Drupal's URL generator to
// handle languages etc.
if (!UrlHelper::isExternal($target)) {
$scheme = parse_url($target, PHP_URL_SCHEME);
if ($scheme === NULL) {
$target = 'internal:' . $target;
}
try {
$target = Url::fromUri($target)
->toString();
} catch (\InvalidArgumentException $exception) {
return NULL;
}
}
return $target;
}
/**
* Returns the action response code.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity the action is being performed on.
*
* @return int
* Redirect code.
*/
public function getActionResponseCode(EntityInterface $entity) {
$target = $entity
->get('rh_redirect')->value;
if (empty($target)) {
$bundle_settings = $this
->getBundleSettings($entity);
$response_code = $bundle_settings
->get('redirect_code');
$this->cacheMetadata
->addCacheableDependency($bundle_settings);
}
else {
$response_code = $entity
->get('rh_redirect_response')->value;
}
return $response_code;
}
/**
* {@inheritdoc}
*/
public function settingsForm(array &$form, FormStateInterface $form_state, $form_id, EntityInterface $entity = NULL, $entity_is_bundle = FALSE, ImmutableConfig $bundle_settings = NULL) {
$redirect = NULL;
$redirect_code = NULL;
$redirect_fallback_action = NULL;
if ($entity_is_bundle) {
$redirect = $bundle_settings
->get('redirect');
$redirect_code = $bundle_settings
->get('redirect_code');
$redirect_fallback_action = $bundle_settings
->get('redirect_fallback_action');
}
elseif (isset($entity)) {
$redirect = isset($entity->rh_redirect->value) ? $entity->rh_redirect->value : self::RABBIT_HOLE_PAGE_REDIRECT_DEFAULT;
$redirect_code = isset($entity->rh_redirect_response->value) ? $entity->rh_redirect_response->value : self::RABBIT_HOLE_PAGE_REDIRECT_RESPONSE_DEFAULT;
$redirect_fallback_action = isset($entity->rh_redirect_fallback_action->value) ? $entity->rh_redirect_fallback_action->value : 'bundle_default';
}
else {
$redirect = NULL;
$redirect_code = NULL;
}
$form['rabbit_hole']['redirect'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Redirect settings'),
'#attributes' => [
'class' => [
'rabbit-hole-redirect-options',
],
],
'#states' => [
'visible' => [
':input[name="rh_action"]' => [
'value' => $this
->getPluginId(),
],
],
],
];
// Get the default value for the redirect path.
// Build the descriptive text.
$description = [];
$description[] = $this
->t('Enter the %front tag, relative path or the full URL that the user should get redirected to. Query strings and fragments are supported, such as %example.', [
'%front' => '<front>',
'%example' => 'http://www.example.com/?query=value#fragment',
]);
$description[] = $this
->t('You may enter tokens in this field, such as %example1 or %example2.', [
'%example1' => '[node:field_link]',
'%example2' => '/my/view?page=[node:field_page_number]',
]);
$form['rabbit_hole']['redirect']['rh_redirect'] = [
'#type' => 'textfield',
'#title' => $this
->t('Redirect path'),
'#default_value' => $redirect,
'#description' => '<p>' . implode('</p><p>', $description) . '</p>',
'#attributes' => [
'class' => [
'rabbit-hole-redirect-setting',
],
],
'#rows' => substr_count($redirect, "\r\n") + 2,
'#element_validate' => [],
'#after_build' => [],
'#states' => [
'required' => [
':input[name="rh_action"]' => [
'value' => $this
->getPluginId(),
],
],
],
'#maxlength' => 2000,
];
$entity_type_id = NULL;
if (isset($entity)) {
$entity_type_id = $entity_is_bundle ? $entity
->getEntityType()
->getBundleOf() : $entity
->getEntityTypeId();
}
else {
$entity_type_id = $this->rhEntityPluginManager
->loadSupportedGlobalForms()[$form_id];
}
$entity_type_for_tokens = NULL;
if ($this->moduleHandler
->moduleExists('token')) {
$token_map = $this->rhEntityPluginManager
->loadEntityTokenMap();
$entity_type_for_tokens = $token_map[$entity_type_id];
$form['rabbit_hole']['redirect']['rh_redirect']['#element_validate'][] = 'token_element_validate';
$form['rabbit_hole']['redirect']['rh_redirect']['#after_build'][] = 'token_element_validate';
$form['rabbit_hole']['redirect']['rh_redirect']['#token_types'] = [
$entity_type_for_tokens,
];
}
// Add the redirect response setting.
$form['rabbit_hole']['redirect']['rh_redirect_response'] = [
'#type' => 'select',
'#title' => $this
->t('Response code'),
'#options' => [
301 => $this
->t('301 (Moved Permanently)'),
302 => $this
->t('302 (Found)'),
303 => $this
->t('303 (See other)'),
304 => $this
->t('304 (Not modified)'),
305 => $this
->t('305 (Use proxy)'),
307 => $this
->t('307 (Temporary redirect)'),
],
'#default_value' => $redirect_code,
'#description' => $this
->t('The response code that should be sent to the users browser. Follow @link for more information on response codes.', [
'@link' => Link::fromTextAndUrl($this
->t('this link'), Url::fromUri('http://api.drupal.org/api/drupal/includes--common.inc/function/drupal_goto/7'))
->toString(),
]),
'#attributes' => [
'class' => [
'rabbit-hole-redirect-response-setting',
],
],
];
// Add fallback action setting with all available options except page
// redirect.
$fallback_options = $form['rh_action']['#options'];
unset($fallback_options['page_redirect']);
if (isset($fallback_options['bundle_default'])) {
$args = $fallback_options['bundle_default']
->getArguments();
$bundle_settings = $this
->getBundleSettings($entity);
$bundle_fallback = $bundle_settings
->get('redirect_fallback_action');
$fallback_options['bundle_default'] = $this
->t('Global @bundle fallback (@setting)', [
'@bundle' => $args['@bundle'],
'@setting' => $bundle_fallback,
]);
}
$form['rabbit_hole']['redirect']['rh_redirect_fallback_action'] = [
'#type' => 'radios',
'#title' => $this
->t('Fallback behavior'),
'#options' => $fallback_options,
'#default_value' => $redirect_fallback_action,
'#description' => $this
->t('What should happen when the redirect is invalid/empty?'),
'#attributes' => [
'class' => [
'rabbit-hole-redirect-fallback-action-setting',
],
],
];
// Display a list of tokens if the Token module is enabled.
if ($this->moduleHandler
->moduleExists('token')) {
$form['rabbit_hole']['redirect']['token_help'] = [
'#theme' => 'token_tree_link',
'#token_types' => [
$entity_type_for_tokens,
],
];
}
}
/**
* {@inheritdoc}
*/
public function alterExtraFields(array &$fields) {
$fields['rh_redirect'] = BaseFieldDefinition::create('string')
->setName('rh_redirect')
->setLabel($this
->t('Rabbit Hole redirect path.'))
->setDescription($this
->t('The path to where the user should get redirected to.'));
$fields['rh_redirect_response'] = BaseFieldDefinition::create('integer')
->setName('rh_redirect_response')
->setLabel($this
->t('Rabbit Hole redirect response code'))
->setDescription($this
->t('Specifies the HTTP response code that should be used when perform a redirect.'));
$fields['rh_redirect_fallback_action'] = BaseFieldDefinition::create('string')
->setName('rh_redirect_fallback_action')
->setLabel($this
->t('Rabbit Hole redirect fallback action'))
->setDescription($this
->t('Specifies the action that should be used when the redirect path is invalid or empty.'));
}
/**
* {@inheritdoc}
*/
protected function getFallbackAction(EntityInterface $entity) {
$fallback_action = $entity
->get('rh_redirect_fallback_action')->value;
if (empty($fallback_action) || $fallback_action === 'bundle_default') {
$bundle_settings = $this
->getBundleSettings($entity);
$fallback_action = $bundle_settings
->get('redirect_fallback_action');
$this->cacheMetadata
->addCacheableDependency($bundle_settings);
}
return !empty($fallback_action) ? $fallback_action : parent::getFallbackAction($entity);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
PageRedirect:: |
protected | property | Cache metadata for the redirect response. | |
PageRedirect:: |
private | property | The HTTP response code. | |
PageRedirect:: |
protected | property | The module handler. | |
PageRedirect:: |
private | property | The redirect path. | |
PageRedirect:: |
protected | property | The entity plugin manager. | |
PageRedirect:: |
protected | property | The token service. | |
PageRedirect:: |
public | function |
Add to or adjust the fields added by rabbit hole. Overrides RabbitHoleBehaviorPluginBase:: |
|
PageRedirect:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
|
PageRedirect:: |
public | function | Returns the action response code. | |
PageRedirect:: |
public | function | Returns the action target URL object. | |
PageRedirect:: |
protected | function |
Returns the fallback action in case if action cannot be performed. Overrides RabbitHoleBehaviorPluginBase:: |
|
PageRedirect:: |
public | function |
Perform the rabbit hole action. Overrides RabbitHoleBehaviorPluginBase:: |
|
PageRedirect:: |
constant | |||
PageRedirect:: |
constant | |||
PageRedirect:: |
constant | |||
PageRedirect:: |
constant | |||
PageRedirect:: |
constant | |||
PageRedirect:: |
constant | |||
PageRedirect:: |
constant | |||
PageRedirect:: |
constant | |||
PageRedirect:: |
public | function |
Return a settings form for the rabbit hole action. Overrides RabbitHoleBehaviorPluginBase:: |
|
PageRedirect:: |
public | function |
Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides PluginBase:: |
|
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
RabbitHoleBehaviorPluginBase:: |
protected | function | Returns configuration object with "Rabbit Hole" bundle settings. | |
RabbitHoleBehaviorPluginBase:: |
public | function |
Handle submission of the settings form for this plugin. Overrides RabbitHoleBehaviorPluginInterface:: |
|
RabbitHoleBehaviorPluginBase:: |
public | function |
Get whether this plugin uses a response to perform its action. Overrides RabbitHoleBehaviorPluginInterface:: |
|
RabbitHoleBehaviorPluginInterface:: |
constant | |||
RabbitHoleBehaviorPluginInterface:: |
constant | |||
RabbitHoleBehaviorPluginInterface:: |
constant | |||
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |