Created
April 22, 2022 15:38
-
-
Save jhedstrom/1bfce59799afde80bf3efaae3be7a068 to your computer and use it in GitHub Desktop.
Redirect canonical node page
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\mymodule\EventSubscriber; | |
use Drupal\mymodule\ExternalRedirectHelper; | |
use Drupal\Core\Routing\TrustedRedirectResponse; | |
use Drupal\node\NodeInterface; | |
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Component\HttpKernel\Event\RequestEvent; | |
use Symfony\Component\HttpKernel\KernelEvents; | |
/** | |
* Event subscriber to redirect canonical pages to external links. | |
*/ | |
class ExternalRedirect implements EventSubscriberInterface { | |
/** | |
* The external redirect helper service. | |
* | |
* @var \Drupal\mymodule\ExternalRedirectHelper | |
*/ | |
protected $redirectHelper; | |
/** | |
* Construct the event subscriber. | |
* | |
* @param \Drupal\mymodule\ExternalRedirectHelper $helper | |
* The external redirect helper service. | |
*/ | |
public function __construct(ExternalRedirectHelper $helper) { | |
$this->redirectHelper = $helper; | |
} | |
/** | |
* Redirect canonical pages if the node has an external URL set. | |
* | |
* @param \Symfony\Component\HttpKernel\Event\RequestEvent $event | |
* The request event. | |
*/ | |
public function redirectExternalLinks(RequestEvent $event) { | |
$request = $event->getRequest(); | |
// Don't redirect on node edit pages and such. | |
if ($request->attributes->get('_route') !== 'entity.node.canonical') { | |
return; | |
} | |
// Get node object. | |
$node = $request->attributes->get('node'); | |
if ($node instanceof NodeInterface && $this->redirectHelper->shouldRedirect($node)) { | |
$uri = $this->redirectHelper->getRedirectUrl($node); | |
$response = new TrustedRedirectResponse($uri, Response::HTTP_MOVED_PERMANENTLY); | |
$event->setResponse($response); | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function getSubscribedEvents() { | |
return [ | |
KernelEvents::REQUEST => ['redirectExternalLinks', 10], | |
]; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\mymodule; | |
use Drupal\Core\Session\AccountProxyInterface; | |
use Drupal\node\NodeInterface; | |
/** | |
* Utility methods for handling external content redirects. | |
*/ | |
class ExternalRedirectHelper { | |
/** | |
* Node types that can have external URLs defined. | |
* | |
* @var string[] | |
*/ | |
const EXTERNAL_NODE_TYPES = [ | |
'external_link', | |
]; | |
/** | |
* The name of the field defining the external URL. | |
* | |
* @var string | |
*/ | |
const EXTERNAL_URL_FIELD_NAME = 'field_external_link'; | |
/** | |
* The current user. | |
* | |
* @var \Drupal\Core\Session\AccountProxyInterface | |
* The current user. | |
*/ | |
protected $currentUser; | |
/** | |
* Construct the utility service. | |
* | |
* @param \Drupal\Core\Session\AccountProxyInterface $account | |
* The current user. | |
*/ | |
public function __construct(AccountProxyInterface $account) { | |
$this->currentUser = $account; | |
} | |
/** | |
* Determine if the given node contains external content to redirect to. | |
* | |
* Will not redirect if the current user has access to edit the node. | |
* | |
* @param \Drupal\node\NodeInterface $node | |
* The content node. | |
* | |
* @return bool | |
* Returns TRUE if the given content should be redirected. | |
*/ | |
public function shouldRedirect(NodeInterface $node):bool { | |
return !$node->access('update', $this->currentUser) | |
&& $this->isExternalContent($node); | |
} | |
/** | |
* Determine if the given content is external. | |
* | |
* @param \Drupal\node\NodeInterface $node | |
* The content node. | |
* | |
* @return bool | |
* Returns TRUE if the content is external. | |
*/ | |
public function isExternalContent(NodeInterface $node):bool { | |
return in_array($node->getType(), static::EXTERNAL_NODE_TYPES) | |
&& $node->hasField(static::EXTERNAL_URL_FIELD_NAME) | |
&& !$node->get(static::EXTERNAL_URL_FIELD_NAME)->isEmpty() | |
&& !empty($node->get(static::EXTERNAL_URL_FIELD_NAME)->uri); | |
} | |
/** | |
* Get the redirect URL. | |
* | |
* @param \Drupal\node\NodeInterface $node | |
* | |
* @return string | |
* The external URI. | |
*/ | |
public function getRedirectUrl(NodeInterface $node):string { | |
return $node->get(static::EXTERNAL_URL_FIELD_NAME)->uri; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Implements hook_ENTITY_TYPE_view_alter(). | |
*/ | |
function mymodule_node_view_alter(array &$build, NodeInterface $node, EntityViewDisplayInterface $display) { | |
$helper = \Drupal::service('mymodule.redirect_helper'); | |
if ($build['#view_mode'] === 'full' && $helper->isExternalContent($node)) { | |
$url = $helper->getRedirectUrl($node); | |
\Drupal::messenger()->addWarning(t('This content will redirect to <a href="@url">@url</a> for anonymous users.', ['@url' => $url])); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
services: | |
mymodule.redirect_helper: | |
class: Drupal\mymodule\ExternalRedirectHelper | |
arguments: ['@current_user'] | |
mymodule.event_subscriber: | |
class: Drupal\mymodule\EventSubscriber\ExternalRedirect | |
arguments: ['@mymodule.redirect_helper'] | |
tags: | |
- { name: event_subscriber } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment