toolshed-8.x-1.x-dev/modules/toolshed_search/src/Plugin/search_api/processor/ExcludeSystemUrlsProcessor.php
modules/toolshed_search/src/Plugin/search_api/processor/ExcludeSystemUrlsProcessor.php
<?php
namespace Drupal\toolshed_search\Plugin\search_api\processor;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityMalformedException;
use Drupal\Core\Entity\Exception\UndefinedLinkTemplateException;
use Drupal\Core\Path\PathValidatorInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\search_api\Processor\ProcessorPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Prevents the search indexing of the site 403 or 404 content.
*
* A content page (or other indexable entity) can be set as the response for
* these statuses, but they often get indexed and appear in search results
* unintentionally. This processor prevents them from getting added.
*
* @todo Extend this to have options for the home page or other special purpose
* pages. This could be things like a welcome page.
*
* @SearchApiProcessor(
* id = "toolshed_exclude_system_urls",
* label = @Translation("Exclude Site URLs"),
* description = @Translation("Prevent the indexing of 404 and 403 pages."),
* stages = {
* "alter_items" = 0,
* },
* locked = true,
* hidden = true,
* )
*/
class ExcludeSystemUrlsProcessor extends ProcessorPluginBase implements ContainerFactoryPluginInterface {
/**
* Build, fetch and update configurations.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected ConfigFactoryInterface $configFactory;
/**
* Service for validating and resolving URIs to Drupal routes and Url objects.
*
* @var \Drupal\Core\Path\PathValidatorInterface
*/
protected PathValidatorInterface $pathValidator;
/**
* Create a new instance of the ExcludeSystemUrlsProcessor.
*
* @param array $configuration
* Configurations to use for this processor's options.
* @param string $plugin_id
* The ID of the plugin.
* @param mixed $plugin_definition
* The definition for this plugin instances.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* Service for managing and fetching configurations.
* @param \Drupal\Core\Path\PathValidatorInterface $path_validator
* Service which is used to resolve a URI to Drupal\Core\Url objects.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory, PathValidatorInterface $path_validator) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->configFactory = $config_factory;
$this->pathValidator = $path_validator;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('config.factory'),
$container->get('path.validator')
);
}
/**
* {@inheritdoc}
*/
public function alterIndexedItems(array &$items): void {
$config = $this->configFactory
->get('system.site')
->get('page');
foreach ($config as $uri) {
$url = $this->pathValidator->getUrlIfValid($uri);
if ($url && $url->isRouted()) {
$routes[$url->getRouteName()] = $url->getRouteParameters();
}
}
if (empty($routes)) {
return;
}
foreach ($items as $item_id => $item) {
$object = $item->getOriginalObject()->getValue();
if ($object instanceof EntityInterface) {
try {
$entityUrl = $object->toUrl();
$routeName = $entityUrl->getRouteName();
// Only if the route and the parameters match do we consider these
// the same target. This avoids assuming things about the entity ID
// and route parameters for all entity types.
if (!empty($routes[$routeName]) && $routes[$routeName] == $entityUrl->getRouteParameters()) {
unset($items[$item_id]);
}
}
catch (EntityMalformedException | UndefinedLinkTemplateException) {
// Skip as this entity doesn't support regular canonical link route.
}
}
}
}
}
