redirect-8.x-1.x-dev/src/RedirectPrefixList.php
src/RedirectPrefixList.php
<?php
namespace Drupal\redirect;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheCollector;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Lock\LockBackendInterface;
use Drupal\Core\Site\Settings;
/**
* Cache a list of prefixes and whether they have redirects.
*/
class RedirectPrefixList extends CacheCollector {
public function __construct($cid, CacheBackendInterface $cache, LockBackendInterface $lock, protected EntityTypeManagerInterface $entityTypeManager) {
parent::__construct($cid, $cache, $lock);
}
/**
* {@inheritdoc}
*/
public function resolveCacheMiss($key) {
// Only persist a fixed amount of prefixes to avoid the cache getting too
// large, return TRUE to pass through to the regular redirect check.
if (count($this->storage) > Settings::get('redirect_prefix_list_max', 100)) {
return TRUE;
}
// Check if there are any redirects starting with this part.
$ids = $this->entityTypeManager->getStorage('redirect')->getQuery()
->accessCheck(FALSE)
->condition('redirect_source.path', $key . '/', 'STARTS_WITH')
->condition('enabled', 1)
->range(0, 1)
->count()
->execute();
$this->storage[$key] = (bool) $ids;
$this->persist($key);
return $this->storage[$key];
}
/**
* Returns whether there may be redirects for the given prefix.
*
* @param string $source_path
* The complete source path being checked.
*
* @return bool
* FALSE if there are no redirects, TRUE if there may be.
*/
public function hasRedirectsWithPrefix(string $source_path): bool {
if (str_contains($source_path, '/') && Settings::get('redirect_use_prefix_list', TRUE)) {
return $this->get(substr($source_path, 0, strpos($source_path, '/')));
}
return TRUE;
}
/**
* Updates the cache if it became stale by the addition of a new redirect.
*
* @param string $source_path
* The redirect source that now exists in the storage.
*/
public function registerNewSource(string $source_path): void {
if (str_contains($source_path, '/') && Settings::get('redirect_use_prefix_list', TRUE)) {
$prefix = substr($source_path, 0, strpos($source_path, '/'));
// The cache only needs to be updated if the prefix is already in the
// cache as not having redirects.
$this->lazyLoadCache();
if (isset($this->storage[$prefix]) && $this->storage[$prefix] === FALSE) {
$this->storage[$prefix] = TRUE;
$this->persist($prefix);
}
}
}
}
