3 namespace Drupal\Core\Path;
5 use Drupal\Core\Cache\CacheBackendInterface;
6 use Drupal\Core\Cache\CacheCollector;
7 use Drupal\Core\State\StateInterface;
8 use Drupal\Core\Lock\LockBackendInterface;
11 * Extends CacheCollector to build the path alias whitelist over time.
13 class AliasWhitelist extends CacheCollector implements AliasWhitelistInterface {
16 * The Key/Value Store to use for state.
18 * @var \Drupal\Core\State\StateInterface
23 * The Path CRUD service.
25 * @var \Drupal\Core\Path\AliasStorageInterface
27 protected $aliasStorage;
30 * Constructs an AliasWhitelist object.
33 * The cache id to use.
34 * @param \Drupal\Core\Cache\CacheBackendInterface $cache
36 * @param \Drupal\Core\Lock\LockBackendInterface $lock
38 * @param \Drupal\Core\State\StateInterface $state
39 * The state keyvalue store.
40 * @param \Drupal\Core\Path\AliasStorageInterface $alias_storage
41 * The alias storage service.
43 public function __construct($cid, CacheBackendInterface $cache, LockBackendInterface $lock, StateInterface $state, AliasStorageInterface $alias_storage) {
44 parent::__construct($cid, $cache, $lock);
45 $this->state = $state;
46 $this->aliasStorage = $alias_storage;
52 protected function lazyLoadCache() {
53 parent::lazyLoadCache();
55 // On a cold start $this->storage will be empty and the whitelist will
56 // need to be rebuilt from scratch. The whitelist is initialized from the
57 // list of all valid path roots stored in the 'router.path_roots' state,
58 // with values initialized to NULL. During the request, each path requested
59 // that matches one of these keys will be looked up and the array value set
60 // to either TRUE or FALSE. This ensures that paths which do not exist in
61 // the router are not looked up, and that paths that do exist in the router
62 // are only looked up once.
63 if (empty($this->storage)) {
64 $this->loadMenuPathRoots();
69 * Loads menu path roots to prepopulate cache.
71 protected function loadMenuPathRoots() {
72 if ($roots = $this->state->get('router.path_roots')) {
73 foreach ($roots as $root) {
74 $this->storage[$root] = NULL;
75 $this->persist($root);
83 public function get($offset) {
84 $this->lazyLoadCache();
85 // this may be called with paths that are not represented by menu router
86 // items such as paths that will be rewritten by hook_url_outbound_alter().
87 // Therefore internally TRUE is used to indicate whitelisted paths. FALSE is
88 // used to indicate paths that have already been checked but are not
89 // whitelisted, and NULL indicates paths that have not been checked yet.
90 if (isset($this->storage[$offset])) {
91 if ($this->storage[$offset]) {
95 elseif (array_key_exists($offset, $this->storage)) {
96 return $this->resolveCacheMiss($offset);
103 public function resolveCacheMiss($root) {
104 $exists = $this->aliasStorage->pathHasMatchingAlias('/' . $root);
105 $this->storage[$root] = $exists;
106 $this->persist($root);
115 public function clear() {
117 $this->loadMenuPathRoots();