diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php index 0e2368b..f36299a 100644 --- a/core/lib/Drupal/Core/CoreBundle.php +++ b/core/lib/Drupal/Core/CoreBundle.php @@ -75,9 +75,16 @@ public function build(ContainerBuilder $container) { ->register('keyvalue.database', 'Drupal\Core\KeyValueStore\KeyValueDatabaseFactory') ->addArgument(new Reference('database')); - $container->register('path.alias_manager', 'Drupal\Core\Path\AliasManager') + $container->register('path.alias_whitelist', 'Drupal\Core\Path\AliasWhitelist') + ->addArgument('path_alias_whitelist') + ->addArgument('cache') + ->addArgument(new Reference('keyvalue')) ->addArgument(new Reference('database')); + $container->register('path.alias_manager', 'Drupal\Core\Path\AliasManager') + ->addArgument(new Reference('database')) + ->addArgument(new Reference('path.alias_whitelist')); + // Register the EntityManager. $container->register('plugin.manager.entity', 'Drupal\Core\Entity\EntityManager'); diff --git a/core/lib/Drupal/Core/Path/AliasManager.php b/core/lib/Drupal/Core/Path/AliasManager.php index 593ccfd..e998a5d 100644 --- a/core/lib/Drupal/Core/Path/AliasManager.php +++ b/core/lib/Drupal/Core/Path/AliasManager.php @@ -70,10 +70,10 @@ class AliasManager implements AliasManagerInterface { */ protected $preloadedPathLookups = array(); - public function __construct(Connection $connection) { + public function __construct(Connection $connection, AliasWhitelist $whitelist) { $this->connection = $connection; $this->langcode = language(LANGUAGE_TYPE_URL)->langcode; - $this->whitelist = new AliasWhitelist('path_alias_whitelist', 'cache'); + $this->whitelist = $whitelist; } /** diff --git a/core/lib/Drupal/Core/Path/AliasWhitelist.php b/core/lib/Drupal/Core/Path/AliasWhitelist.php index 10f1a9a..6ea0f16 100644 --- a/core/lib/Drupal/Core/Path/AliasWhitelist.php +++ b/core/lib/Drupal/Core/Path/AliasWhitelist.php @@ -2,11 +2,13 @@ /** * @file - * Definition of PathAliasWhitelist + * Contains \Drupal\Core\Path\AliasWhitelist. */ namespace Drupal\Core\Path; +use Drupal\Core\Database\Connection; +use Drupal\Core\KeyValueStore\KeyValueFactory; use Drupal\Core\Utility\CacheArray; /** @@ -15,10 +17,26 @@ class AliasWhitelist extends CacheArray { /** + * The Key/Value Store to use for state. + * + * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface + */ + protected $state; + + /** + * The database connection. + * + * @var \Drupal\Core\Database\Connection + */ + protected $connection; + + /** * Constructs an AliasWhitelist object. */ - public function __construct($cid, $bin) { + public function __construct($cid, $bin, KeyValueFactory $keyvalue, Connection $connection) { parent::__construct($cid, $bin); + $this->state = $keyvalue->get('state'); + $this->connection = $connection; // On a cold start $this->storage will be empty and the whitelist will // need to be rebuilt from scratch. The whitelist is initialized from the @@ -34,10 +52,10 @@ public function __construct($cid, $bin) { } /** - * Load menu path roots to prepopulate cache. + * Loads menu path roots to prepopulate cache. */ protected function loadMenuPathRoots() { - if ($roots = state()->get('menu_path_roots')) { + if ($roots = $this->state->get('menu_path_roots')) { foreach ($roots as $root) { $this->storage[$root] = NULL; $this->persist($root); @@ -46,7 +64,7 @@ protected function loadMenuPathRoots() { } /** - * Overrides ArrayAccess::offsetGet(). + * Overrides \ArrayAccess::offsetGet(). */ public function offsetGet($offset) { // url() may be called with paths that are not represented by menu router @@ -65,13 +83,16 @@ public function offsetGet($offset) { } /** - * Overrides CacheArray::resolveCacheMiss(). + * Overrides \Drupal\Core\Utility\CacheArray::resolveCacheMiss(). */ public function resolveCacheMiss($root) { - $query = db_select('url_alias', 'u'); + $query = $this->connection->select('url_alias', 'u'); $query->addExpression(1); - $query->condition('u.source', db_like($root) . '%', 'LIKE') ->range(0, 1); - $exists = (bool) $query->execute()->fetchField(); + $exists = (bool) $query + ->condition('u.source', $this->connection->escapeLike($root) . '%', 'LIKE') + ->range(0, 1) + ->execute() + ->fetchField(); $this->storage[$root] = $exists; $this->persist($root); if ($exists) { @@ -80,7 +101,7 @@ public function resolveCacheMiss($root) { } /** - * Overrides CacheArray::set(). + * Overrides \Drupal\Core\Utility\CacheArray::set(). */ public function set($data, $lock = TRUE) { $lock_name = $this->cid . ':' . $this->bin; @@ -98,7 +119,7 @@ public function set($data, $lock = TRUE) { } /** - * Overrides CacheArray::clear(). + * Overrides \Drupal\Core\Utility\CacheArray::clear(). */ public function clear() { parent::clear(); diff --git a/core/modules/system/lib/Drupal/system/Tests/Path/AliasTest.php b/core/modules/system/lib/Drupal/system/Tests/Path/AliasTest.php index 0325bd8..2709fd9 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Path/AliasTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Path/AliasTest.php @@ -7,10 +7,11 @@ namespace Drupal\system\Tests\Path; -use Drupal\simpletest\DrupalUnitTestBase; use Drupal\Core\Database\Database; -use Drupal\Core\Path\Path; use Drupal\Core\Path\AliasManager; +use Drupal\Core\Path\AliasWhitelist; +use Drupal\Core\Path\Path; +use Drupal\simpletest\DrupalUnitTestBase; /** * Tests path alias CRUD and lookup functionality. @@ -30,7 +31,7 @@ public function setUp() { $this->fixtures = new UrlAliasFixtures(); // The alias whitelist expects that the menu path roots are set by a // menu router rebuild. - state()->set('menu_path_roots', array('user')); + state()->set('menu_path_roots', array('user', 'admin')); } public function tearDown() { @@ -46,7 +47,8 @@ function testCRUD() { $this->fixtures->createTables($connection); //Create AliasManager and Path object. - $aliasManager = new AliasManager($connection, $this->container->get('keyvalue')); + $whitelist = new AliasWhitelist('path_alias_whitelist', 'cache', $this->container->get('keyvalue'), $connection); + $aliasManager = new AliasManager($connection, $whitelist); $path = new Path($connection, $aliasManager); $aliases = $this->fixtures->sampleUrlAliases(); @@ -99,7 +101,8 @@ function testLookupPath() { $this->fixtures->createTables($connection); //Create AliasManager and Path object. - $aliasManager = new AliasManager($connection, $this->container->get('keyvalue')); + $whitelist = new AliasWhitelist('path_alias_whitelist', 'cache', $this->container->get('keyvalue'), $connection); + $aliasManager = new AliasManager($connection, $whitelist); $pathObject = new Path($connection, $aliasManager); // Test the situation where the source is the same for multiple aliases. @@ -163,4 +166,43 @@ function testLookupPath() { $pathObject->save('user/2', 'bar'); $this->assertEqual($aliasManager->getSystemPath('bar'), 'user/2', 'Newer alias record is returned when comparing two LANGUAGE_NOT_SPECIFIED paths with the same alias.'); } + + /** + * Test the alias whitelist. + */ + function testWhitelist() { + //Prepare database table. + $connection = Database::getConnection(); + $this->fixtures->createTables($connection); + //Create AliasManager and Path object. + $whitelist = new AliasWhitelist('path_alias_whitelist', 'cache', $this->container->get('keyvalue'), $connection); + $aliasManager = new AliasManager($connection, $whitelist); + $path = new Path($connection, $aliasManager); + + // No alias for user and admin yet, so should be NULL. + $this->assertNull($whitelist['user']); + $this->assertNull($whitelist['admin']); + + // Non-existing path roots should be NULL too. + $this->assertNull($whitelist['invalid']); + + // Add an alias for user/1, user should get whitelisted now. + $path->save('user/1', 'admin'); + $this->assertTrue($whitelist['user']); + $this->assertNull($whitelist['admin']); + $this->assertNull($whitelist['invalid']); + + // Add an alias for admin, both should get whitelisted now. + $path->save('admin/something', 'admin'); + $this->assertTrue($whitelist['user']); + $this->assertTrue($whitelist['admin']); + $this->assertNull($whitelist['invalid']); + + // Remove the user alias again, whitelist entry should be removed. + $path->delete(array('source' => 'user/1')); + $this->assertNull($whitelist['user']); + $this->assertTrue($whitelist['admin']); + $this->assertNull($whitelist['invalid']); + + } }