first commit
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
name: Path alias
|
||||
type: module
|
||||
description: 'Provides the API allowing to rename URLs.'
|
||||
package: Core
|
||||
version: VERSION
|
||||
required: true
|
||||
hidden: true
|
||||
@@ -0,0 +1,25 @@
|
||||
services:
|
||||
path_alias.subscriber:
|
||||
class: Drupal\path_alias\EventSubscriber\PathAliasSubscriber
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
arguments: ['@path_alias.manager', '@path.current']
|
||||
path_alias.path_processor:
|
||||
class: Drupal\path_alias\PathProcessor\AliasPathProcessor
|
||||
tags:
|
||||
- { name: path_processor_inbound, priority: 100 }
|
||||
- { name: path_processor_outbound, priority: 300 }
|
||||
arguments: ['@path_alias.manager']
|
||||
path_alias.manager:
|
||||
class: Drupal\path_alias\AliasManager
|
||||
arguments: ['@path_alias.repository', '@path_alias.whitelist', '@language_manager', '@cache.data']
|
||||
path_alias.repository:
|
||||
class: Drupal\path_alias\AliasRepository
|
||||
arguments: ['@database']
|
||||
tags:
|
||||
- { name: backend_overridable }
|
||||
path_alias.whitelist:
|
||||
class: Drupal\path_alias\AliasWhitelist
|
||||
tags:
|
||||
- { name: needs_destruction }
|
||||
arguments: [path_alias_whitelist, '@cache.bootstrap', '@lock', '@state', '@path_alias.repository']
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias;
|
||||
|
||||
use Drupal\Core\Path\AliasManager as CoreAliasManager;
|
||||
|
||||
/**
|
||||
* The default alias manager implementation.
|
||||
*/
|
||||
class AliasManager extends CoreAliasManager implements AliasManagerInterface {}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias;
|
||||
|
||||
use Drupal\Core\Path\AliasManagerInterface as CoreAliasManagerInterface;
|
||||
|
||||
/**
|
||||
* Find an alias for a path and vice versa.
|
||||
*
|
||||
* @see \Drupal\Core\Path\AliasStorageInterface
|
||||
*/
|
||||
interface AliasManagerInterface extends CoreAliasManagerInterface {}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias;
|
||||
|
||||
use Drupal\Core\Path\AliasRepository as CoreAliasRepository;
|
||||
|
||||
/**
|
||||
* Provides the default path alias lookup operations.
|
||||
*/
|
||||
class AliasRepository extends CoreAliasRepository implements AliasRepositoryInterface {}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias;
|
||||
|
||||
use Drupal\Core\Path\AliasRepositoryInterface as CoreAliasRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface for path alias lookup operations.
|
||||
*
|
||||
* The path alias repository service is only used internally in order to
|
||||
* optimize alias lookup queries needed in the critical path of each request.
|
||||
* However, it is not marked as an internal service because alternative storage
|
||||
* backends still need to override it if they provide a different storage class
|
||||
* for the PathAlias entity type.
|
||||
*
|
||||
* Whenever you need to determine whether an alias exists for a system path, or
|
||||
* whether a system path has an alias, the 'path_alias.manager' service should
|
||||
* be used instead.
|
||||
*/
|
||||
interface AliasRepositoryInterface extends CoreAliasRepositoryInterface {}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias;
|
||||
|
||||
use Drupal\Core\Path\AliasWhitelist as CoreAliasWhitelist;
|
||||
|
||||
/**
|
||||
* Extends CacheCollector to build the path alias whitelist over time.
|
||||
*/
|
||||
class AliasWhitelist extends CoreAliasWhitelist implements AliasWhitelistInterface {}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias;
|
||||
|
||||
use Drupal\Core\Path\AliasWhitelistInterface as CoreAliasWhitelistInterface;
|
||||
|
||||
/**
|
||||
* Cache the alias whitelist.
|
||||
*
|
||||
* The whitelist contains the first element of the router paths of all
|
||||
* aliases. For example, if /node/12345 has an alias then "node" is added to
|
||||
* the whitelist. This optimization allows skipping the lookup for every
|
||||
* /user/{user} path if "user" is not in the whitelist.
|
||||
*/
|
||||
interface AliasWhitelistInterface extends CoreAliasWhitelistInterface {}
|
||||
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityBase;
|
||||
use Drupal\Core\Entity\EntityPublishedTrait;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\path_alias\PathAliasInterface;
|
||||
|
||||
/**
|
||||
* Defines the path_alias entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "path_alias",
|
||||
* label = @Translation("URL alias"),
|
||||
* label_collection = @Translation("URL aliases"),
|
||||
* label_singular = @Translation("URL alias"),
|
||||
* label_plural = @Translation("URL aliases"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count URL alias",
|
||||
* plural = "@count URL aliases"
|
||||
* ),
|
||||
* handlers = {
|
||||
* "storage" = "Drupal\path_alias\PathAliasStorage",
|
||||
* "storage_schema" = "Drupal\path_alias\PathAliasStorageSchema",
|
||||
* },
|
||||
* base_table = "path_alias",
|
||||
* revision_table = "path_alias_revision",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "revision" = "revision_id",
|
||||
* "langcode" = "langcode",
|
||||
* "uuid" = "uuid",
|
||||
* "published" = "status",
|
||||
* },
|
||||
* admin_permission = "administer url aliases",
|
||||
* list_cache_tags = { "route_match" },
|
||||
* constraints = {
|
||||
* "UniquePathAlias" = {}
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class PathAlias extends ContentEntityBase implements PathAliasInterface {
|
||||
|
||||
use EntityPublishedTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['path'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(new TranslatableMarkup('System path'))
|
||||
->setDescription(new TranslatableMarkup('The path that this alias belongs to.'))
|
||||
->setRequired(TRUE)
|
||||
->setRevisionable(TRUE)
|
||||
->addPropertyConstraints('value', [
|
||||
'Regex' => [
|
||||
'pattern' => '/^\//i',
|
||||
'message' => new TranslatableMarkup('The source path has to start with a slash.'),
|
||||
],
|
||||
])
|
||||
->addPropertyConstraints('value', ['ValidPath' => []]);
|
||||
|
||||
$fields['alias'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(new TranslatableMarkup('URL alias'))
|
||||
->setDescription(new TranslatableMarkup('An alias used with this path.'))
|
||||
->setRequired(TRUE)
|
||||
->setRevisionable(TRUE)
|
||||
->addPropertyConstraints('value', [
|
||||
'Regex' => [
|
||||
'pattern' => '/^\//i',
|
||||
'message' => new TranslatableMarkup('The alias path has to start with a slash.'),
|
||||
],
|
||||
]);
|
||||
|
||||
$fields['langcode']->setDefaultValue(LanguageInterface::LANGCODE_NOT_SPECIFIED);
|
||||
|
||||
// Add the published field.
|
||||
$fields += static::publishedBaseFieldDefinitions($entity_type);
|
||||
$fields['status']->setTranslatable(FALSE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preSave(EntityStorageInterface $storage) {
|
||||
parent::preSave($storage);
|
||||
|
||||
// Trim the alias value of whitespace and slashes. Ensure to not trim the
|
||||
// slash on the left side.
|
||||
$alias = rtrim(trim($this->getAlias()), "\\/");
|
||||
$this->setAlias($alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
|
||||
parent::postSave($storage, $update);
|
||||
|
||||
$alias_manager = \Drupal::service('path_alias.manager');
|
||||
$alias_manager->cacheClear($this->getPath());
|
||||
if ($update) {
|
||||
$alias_manager->cacheClear($this->original->getPath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function postDelete(EntityStorageInterface $storage, array $entities) {
|
||||
parent::postDelete($storage, $entities);
|
||||
|
||||
$alias_manager = \Drupal::service('path_alias.manager');
|
||||
foreach ($entities as $entity) {
|
||||
$alias_manager->cacheClear($entity->getPath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPath() {
|
||||
return $this->get('path')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setPath($path) {
|
||||
$this->set('path', $path);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAlias() {
|
||||
return $this->get('alias')->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setAlias($alias) {
|
||||
$this->set('alias', $alias);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function label() {
|
||||
return $this->getAlias();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheTagsToInvalidate() {
|
||||
return ['route_match'];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias\EventSubscriber;
|
||||
|
||||
use Drupal\Core\EventSubscriber\PathSubscriber;
|
||||
|
||||
/**
|
||||
* Provides a path subscriber that converts path aliases.
|
||||
*/
|
||||
class PathAliasSubscriber extends PathSubscriber {}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\EntityPublishedInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface defining a path_alias entity.
|
||||
*/
|
||||
interface PathAliasInterface extends ContentEntityInterface, EntityPublishedInterface {
|
||||
|
||||
/**
|
||||
* Gets the source path of the alias.
|
||||
*
|
||||
* @return string
|
||||
* The source path.
|
||||
*/
|
||||
public function getPath();
|
||||
|
||||
/**
|
||||
* Sets the source path of the alias.
|
||||
*
|
||||
* @param string $path
|
||||
* The source path.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPath($path);
|
||||
|
||||
/**
|
||||
* Gets the alias for this path.
|
||||
*
|
||||
* @return string
|
||||
* The alias for this path.
|
||||
*/
|
||||
public function getAlias();
|
||||
|
||||
/**
|
||||
* Sets the alias for this path.
|
||||
*
|
||||
* @param string $alias
|
||||
* The path alias.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAlias($alias);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
|
||||
|
||||
/**
|
||||
* Defines the storage handler class for path_alias entities.
|
||||
*/
|
||||
class PathAliasStorage extends SqlContentEntityStorage {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function invokeHook($hook, EntityInterface $entity) {
|
||||
parent::invokeHook($hook, $entity);
|
||||
|
||||
// Invoke the deprecated hook_path_OPERATION() hooks.
|
||||
if ($hook === 'insert' || $hook === 'update' || $hook === 'delete') {
|
||||
$values = [
|
||||
'pid' => $entity->id(),
|
||||
'source' => $entity->getPath(),
|
||||
'alias' => $entity->getAlias(),
|
||||
'langcode' => $entity->language()->getId(),
|
||||
];
|
||||
|
||||
if ($hook === 'update') {
|
||||
$values['original'] = [
|
||||
'pid' => $entity->id(),
|
||||
'source' => $entity->original->getPath(),
|
||||
'alias' => $entity->original->getAlias(),
|
||||
'langcode' => $entity->original->language()->getId(),
|
||||
];
|
||||
}
|
||||
|
||||
$this->moduleHandler()->invokeAllDeprecated("It will be removed before Drupal 9.0.0. Use hook_ENTITY_TYPE_{$hook}() for the 'path_alias' entity type instead. See https://www.drupal.org/node/3013865.", 'path_' . $hook, [$values]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createWithSampleValues($bundle = FALSE, array $values = []) {
|
||||
$entity = parent::createWithSampleValues($bundle, ['path' => '/<front>'] + $values);
|
||||
// Ensure the alias is only 255 characters long.
|
||||
$entity->set('alias', substr('/' . $entity->get('alias')->value, 0, 255));
|
||||
return $entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema;
|
||||
|
||||
/**
|
||||
* Defines the path_alias schema handler.
|
||||
*/
|
||||
class PathAliasStorageSchema extends SqlContentEntityStorageSchema {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
|
||||
$schema = parent::getEntitySchema($entity_type, $reset);
|
||||
|
||||
$schema[$this->storage->getBaseTable()]['indexes'] += [
|
||||
'path_alias__alias_langcode_id_status' => ['alias', 'langcode', 'id', 'status'],
|
||||
'path_alias__path_langcode_id_status' => ['path', 'langcode', 'id', 'status'],
|
||||
];
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias\PathProcessor;
|
||||
|
||||
use Drupal\Core\PathProcessor\PathProcessorAlias;
|
||||
|
||||
/**
|
||||
* Processes the inbound path using path alias lookups.
|
||||
*/
|
||||
class AliasPathProcessor extends PathProcessorAlias {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
name: 'Path Alias deprecated test'
|
||||
type: module
|
||||
description: 'Support module for testing deprecated functionality for path aliases.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
services:
|
||||
path_alias_deprecated_test.path.alias_manager:
|
||||
class: Drupal\path_alias_deprecated_test\AliasManagerDecorator
|
||||
decorates: path.alias_manager
|
||||
arguments: ['@path_alias_deprecated_test.path.alias_manager.inner']
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias_deprecated_test;
|
||||
|
||||
use Drupal\Core\Path\AliasManagerInterface;
|
||||
|
||||
/**
|
||||
* Test alias manager decorator.
|
||||
*/
|
||||
class AliasManagerDecorator implements AliasManagerInterface {
|
||||
|
||||
/**
|
||||
* The decorated alias manager.
|
||||
*
|
||||
* @var \Drupal\Core\Path\AliasManagerInterface
|
||||
*/
|
||||
protected $aliasManager;
|
||||
|
||||
/**
|
||||
* AliasManagerDecorator constructor.
|
||||
*
|
||||
* @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
|
||||
* The decorated alias manager.
|
||||
*/
|
||||
public function __construct(AliasManagerInterface $alias_manager) {
|
||||
$this->aliasManager = $alias_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPathByAlias($alias, $langcode = NULL) {
|
||||
$this->aliasManager->getPathByAlias($alias, $langcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAliasByPath($path, $langcode = NULL) {
|
||||
return $this->aliasManager->getAliasByPath($path, $langcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function cacheClear($source = NULL) {
|
||||
$this->aliasManager->cacheClear($source);
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias_deprecated_test;
|
||||
|
||||
use Drupal\Core\Path\AliasManagerInterface;
|
||||
|
||||
/**
|
||||
* New test implementation for the alias manager.
|
||||
*/
|
||||
class NewAliasManager implements AliasManagerInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPathByAlias($alias, $langcode = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAliasByPath($path, $langcode = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function cacheClear($source = NULL) {
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias_deprecated_test;
|
||||
|
||||
use Drupal\Core\Path\AliasManager;
|
||||
|
||||
/**
|
||||
* Overridden test implementation for the alias manager.
|
||||
*/
|
||||
class OverriddenAliasManager extends AliasManager {}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\path_alias_deprecated_test;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceModifierInterface;
|
||||
|
||||
/**
|
||||
* Test service provider to test path alias deprecated services BC logic.
|
||||
*/
|
||||
class PathAliasDeprecatedTestServiceProvider implements ServiceModifierInterface {
|
||||
|
||||
/**
|
||||
* The name of the new implementation class for the alias manager.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $newClass;
|
||||
|
||||
/**
|
||||
* Whether to use a decorator to wrap the alias manager implementation.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $useDecorator = FALSE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
if (isset(static::$newClass)) {
|
||||
$definition = $container->getDefinition('path.alias_manager');
|
||||
$definition->setClass(static::$newClass);
|
||||
}
|
||||
|
||||
if (!static::$useDecorator) {
|
||||
$decorator_id = 'path_alias_deprecated_test.path.alias_manager';
|
||||
if ($container->hasDefinition($decorator_id)) {
|
||||
$container->removeDefinition($decorator_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
* @group path_alias
|
||||
*/
|
||||
class PathAliasHalJsonAnonTest extends PathAliasHalJsonTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
* @group path_alias
|
||||
*/
|
||||
class PathAliasHalJsonBasicAuthTest extends PathAliasHalJsonTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
* @group path_alias
|
||||
*/
|
||||
class PathAliasHalJsonCookieTest extends PathAliasHalJsonTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\hal\Functional\EntityResource\HalEntityNormalizationTrait;
|
||||
use Drupal\Tests\path_alias\Functional\Rest\PathAliasResourceTestBase;
|
||||
|
||||
/**
|
||||
* Base hal_json test class for the path_alias entity type.
|
||||
*/
|
||||
abstract class PathAliasHalJsonTestBase extends PathAliasResourceTestBase {
|
||||
|
||||
use HalEntityNormalizationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
$default_normalization = parent::getExpectedNormalizedEntity();
|
||||
$normalization = $this->applyHalFieldNormalization($default_normalization);
|
||||
return $normalization + [
|
||||
'_links' => [
|
||||
'self' => [
|
||||
'href' => $this->baseUrl . '/entity/path_alias/1?_format=hal_json',
|
||||
],
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/path_alias/path_alias',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return parent::getNormalizedPostEntity() + [
|
||||
'_links' => [
|
||||
'type' => [
|
||||
'href' => $this->baseUrl . '/rest/type/path_alias/path_alias',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
return [
|
||||
'url.site',
|
||||
'user.permissions',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* Test path_alias entities for unauthenticated JSON requests.
|
||||
*
|
||||
* @group path_alias
|
||||
*/
|
||||
class PathAliasJsonAnonTest extends PathAliasResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* Test path_alias entities for JSON requests via basic auth.
|
||||
*
|
||||
* @group path_alias
|
||||
*/
|
||||
class PathAliasJsonBasicAuthTest extends PathAliasResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* Test path_alias entities for JSON requests with cookie authentication.
|
||||
*
|
||||
* @group path_alias
|
||||
*/
|
||||
class PathAliasJsonCookieTest extends PathAliasResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Rest;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\path_alias\Entity\PathAlias;
|
||||
use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
/**
|
||||
* Base class for path_alias EntityResource tests.
|
||||
*/
|
||||
abstract class PathAliasResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['path_alias'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'path_alias';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $firstCreatedEntityId = 3;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $secondCreatedEntityId = 4;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer url aliases']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$path_alias = PathAlias::create([
|
||||
'path' => '/<front>',
|
||||
'alias' => '/frontpage1',
|
||||
]);
|
||||
$path_alias->save();
|
||||
return $path_alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'id' => [
|
||||
[
|
||||
'value' => 1,
|
||||
],
|
||||
],
|
||||
'revision_id' => [
|
||||
[
|
||||
'value' => 1,
|
||||
],
|
||||
],
|
||||
'langcode' => [
|
||||
[
|
||||
'value' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
],
|
||||
],
|
||||
'path' => [
|
||||
[
|
||||
'value' => '/<front>',
|
||||
],
|
||||
],
|
||||
'alias' => [
|
||||
[
|
||||
'value' => '/frontpage1',
|
||||
],
|
||||
],
|
||||
'status' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
[
|
||||
'value' => $this->entity->uuid(),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return [
|
||||
'path' => [
|
||||
[
|
||||
'value' => '/<front>',
|
||||
],
|
||||
],
|
||||
'alias' => [
|
||||
[
|
||||
'value' => '/frontpage1',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
return ['user.permissions'];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* Test path_alias entities for unauthenticated XML requests.
|
||||
*
|
||||
* @group path_alias
|
||||
*/
|
||||
class PathAliasXmlAnonTest extends PathAliasResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* Test path_alias entities for XML requests with cookie authentication.
|
||||
*
|
||||
* @group path_alias
|
||||
*/
|
||||
class PathAliasXmlBasicAuthTest extends PathAliasResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* Test path_alias entities for XML requests.
|
||||
*
|
||||
* @group path_alias
|
||||
*/
|
||||
class PathAliasXmlCookieTest extends PathAliasResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Functional;
|
||||
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
use Drupal\Tests\Traits\Core\PathAliasTestTrait;
|
||||
|
||||
/**
|
||||
* Tests altering the inbound path and the outbound path.
|
||||
*
|
||||
* @group path_alias
|
||||
*/
|
||||
class UrlAlterFunctionalTest extends BrowserTestBase {
|
||||
|
||||
use PathAliasTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['path', 'forum', 'url_alter_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Test that URL altering works and that it occurs in the correct order.
|
||||
*/
|
||||
public function testUrlAlter() {
|
||||
// Ensure that the path_alias table exists after Drupal installation.
|
||||
$this->assertTrue(Database::getConnection()->schema()->tableExists('path_alias'), 'The path_alias table exists after Drupal installation.');
|
||||
|
||||
// User names can have quotes and plus signs so we should ensure that URL
|
||||
// altering works with this.
|
||||
$account = $this->drupalCreateUser(['administer url aliases'], "a'foo+bar");
|
||||
$this->drupalLogin($account);
|
||||
|
||||
$uid = $account->id();
|
||||
$name = $account->getAccountName();
|
||||
|
||||
// Test a single altered path.
|
||||
$this->drupalGet("user/$name");
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertUrlOutboundAlter("/user/$uid", "/user/$name");
|
||||
|
||||
// Test that a path always uses its alias.
|
||||
$this->createPathAlias("/user/$uid/test1", '/alias/test1');
|
||||
$this->rebuildContainer();
|
||||
$this->assertUrlInboundAlter('/alias/test1', "/user/$uid/test1");
|
||||
$this->assertUrlOutboundAlter("/user/$uid/test1", '/alias/test1');
|
||||
|
||||
// Test adding an alias via the UI.
|
||||
$edit = ['path[0][value]' => "/user/$uid/edit", 'alias[0][value]' => '/alias/test2'];
|
||||
$this->drupalPostForm('admin/config/search/path/add', $edit, t('Save'));
|
||||
$this->assertText(t('The alias has been saved.'));
|
||||
$this->drupalGet('alias/test2');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertUrlOutboundAlter("/user/$uid/edit", '/alias/test2');
|
||||
|
||||
// Test a non-existent user is not altered.
|
||||
$uid++;
|
||||
$this->assertUrlOutboundAlter("/user/$uid", "/user/$uid");
|
||||
|
||||
// Test that 'forum' is altered to 'community' correctly, both at the root
|
||||
// level and for a specific existing forum.
|
||||
$this->drupalGet('community');
|
||||
$this->assertText('General discussion', 'The community path gets resolved correctly');
|
||||
$this->assertUrlOutboundAlter('/forum', '/community');
|
||||
$forum_vid = $this->config('forum.settings')->get('vocabulary');
|
||||
$term_name = $this->randomMachineName();
|
||||
$term = Term::create([
|
||||
'name' => $term_name,
|
||||
'vid' => $forum_vid,
|
||||
]);
|
||||
$term->save();
|
||||
$this->drupalGet("community/" . $term->id());
|
||||
$this->assertText($term_name, 'The community/{tid} path gets resolved correctly');
|
||||
$this->assertUrlOutboundAlter("/forum/" . $term->id(), "/community/" . $term->id());
|
||||
|
||||
// Test outbound query string altering.
|
||||
$url = Url::fromRoute('user.login');
|
||||
$this->assertIdentical(\Drupal::request()->getBaseUrl() . '/user/login?foo=bar', $url->toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an outbound path is altered to an expected value.
|
||||
*
|
||||
* @param $original
|
||||
* A string with the original path that is run through generateFrommPath().
|
||||
* @param $final
|
||||
* A string with the expected result after generateFrommPath().
|
||||
*
|
||||
* @return
|
||||
* TRUE if $original was correctly altered to $final, FALSE otherwise.
|
||||
*/
|
||||
protected function assertUrlOutboundAlter($original, $final) {
|
||||
// Test outbound altering.
|
||||
$result = $this->container->get('path_processor_manager')->processOutbound($original);
|
||||
return $this->assertIdentical($result, $final, new FormattableMarkup('Altered outbound URL %original, expected %final, and got %result.', ['%original' => $original, '%final' => $final, '%result' => $result]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a inbound path is altered to an expected value.
|
||||
*
|
||||
* @param $original
|
||||
* The original path before it has been altered by inbound URL processing.
|
||||
* @param $final
|
||||
* A string with the expected result.
|
||||
*
|
||||
* @return
|
||||
* TRUE if $original was correctly altered to $final, FALSE otherwise.
|
||||
*/
|
||||
protected function assertUrlInboundAlter($original, $final) {
|
||||
// Test inbound altering.
|
||||
$result = $this->container->get('path_alias.manager')->getPathByAlias($original);
|
||||
return $this->assertIdentical($result, $final, new FormattableMarkup('Altered inbound URL %original, expected %final, and got %result.', ['%original' => $original, '%final' => $final, '%result' => $result]));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Kernel;
|
||||
|
||||
use Drupal\Core\Cache\MemoryCounterBackend;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\path_alias\AliasManager;
|
||||
use Drupal\path_alias\AliasWhitelist;
|
||||
use Drupal\Tests\Traits\Core\PathAliasTestTrait;
|
||||
|
||||
/**
|
||||
* Tests path alias CRUD and lookup functionality.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\path_alias\AliasRepository
|
||||
*
|
||||
* @group path_alias
|
||||
*/
|
||||
class AliasTest extends KernelTestBase {
|
||||
|
||||
use PathAliasTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['path_alias'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// The alias whitelist expects that the menu path roots are set by a
|
||||
// menu router rebuild.
|
||||
\Drupal::state()->set('router.path_roots', ['user', 'admin']);
|
||||
|
||||
$this->installEntitySchema('path_alias');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::lookupBySystemPath
|
||||
*/
|
||||
public function testLookupBySystemPath() {
|
||||
$this->createPathAlias('/test-source-Case', '/test-alias');
|
||||
|
||||
$path_alias_repository = $this->container->get('path_alias.repository');
|
||||
$this->assertEquals('/test-alias', $path_alias_repository->lookupBySystemPath('/test-source-Case', LanguageInterface::LANGCODE_NOT_SPECIFIED)['alias']);
|
||||
$this->assertEquals('/test-alias', $path_alias_repository->lookupBySystemPath('/test-source-case', LanguageInterface::LANGCODE_NOT_SPECIFIED)['alias']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::lookupByAlias
|
||||
*/
|
||||
public function testLookupByAlias() {
|
||||
$this->createPathAlias('/test-source', '/test-alias-Case');
|
||||
|
||||
$path_alias_repository = $this->container->get('path_alias.repository');
|
||||
$this->assertEquals('/test-source', $path_alias_repository->lookupByAlias('/test-alias-Case', LanguageInterface::LANGCODE_NOT_SPECIFIED)['path']);
|
||||
$this->assertEquals('/test-source', $path_alias_repository->lookupByAlias('/test-alias-case', LanguageInterface::LANGCODE_NOT_SPECIFIED)['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\path_alias\AliasManager::getPathByAlias
|
||||
* @covers \Drupal\path_alias\AliasManager::getAliasByPath
|
||||
*/
|
||||
public function testLookupPath() {
|
||||
// Create AliasManager and Path object.
|
||||
$aliasManager = $this->container->get('path_alias.manager');
|
||||
|
||||
// Test the situation where the source is the same for multiple aliases.
|
||||
// Start with a language-neutral alias, which we will override.
|
||||
$path_alias = $this->createPathAlias('/user/1', '/foo');
|
||||
$this->assertEquals($path_alias->getAlias(), $aliasManager->getAliasByPath($path_alias->getPath()), 'Basic alias lookup works.');
|
||||
$this->assertEquals($path_alias->getPath(), $aliasManager->getPathByAlias($path_alias->getAlias()), 'Basic source lookup works.');
|
||||
|
||||
// Create a language specific alias for the default language (English).
|
||||
$path_alias = $this->createPathAlias('/user/1', '/users/Dries', 'en');
|
||||
|
||||
$this->assertEquals($path_alias->getAlias(), $aliasManager->getAliasByPath($path_alias->getPath()), 'English alias overrides language-neutral alias.');
|
||||
$this->assertEquals($path_alias->getPath(), $aliasManager->getPathByAlias($path_alias->getAlias()), 'English source overrides language-neutral source.');
|
||||
|
||||
// Create a language-neutral alias for the same path, again.
|
||||
$path_alias = $this->createPathAlias('/user/1', '/bar');
|
||||
$this->assertEquals("/users/Dries", $aliasManager->getAliasByPath($path_alias->getPath()), 'English alias still returned after entering a language-neutral alias.');
|
||||
|
||||
// Create a language-specific (xx-lolspeak) alias for the same path.
|
||||
$path_alias = $this->createPathAlias('/user/1', '/LOL', 'xx-lolspeak');
|
||||
$this->assertEquals("/users/Dries", $aliasManager->getAliasByPath($path_alias->getPath()), 'English alias still returned after entering a LOLspeak alias.');
|
||||
// The LOLspeak alias should be returned if we really want LOLspeak.
|
||||
$this->assertEquals('/LOL', $aliasManager->getAliasByPath($path_alias->getPath(), 'xx-lolspeak'), 'LOLspeak alias returned if we specify xx-lolspeak to the alias manager.');
|
||||
|
||||
// Create a new alias for this path in English, which should override the
|
||||
// previous alias for "user/1".
|
||||
$path_alias = $this->createPathAlias('/user/1', '/users/my-new-path', 'en');
|
||||
$this->assertEquals($path_alias->getAlias(), $aliasManager->getAliasByPath($path_alias->getPath()), 'Recently created English alias returned.');
|
||||
$this->assertEquals($path_alias->getPath(), $aliasManager->getPathByAlias($path_alias->getAlias()), 'Recently created English source returned.');
|
||||
|
||||
// Remove the English aliases, which should cause a fallback to the most
|
||||
// recently created language-neutral alias, 'bar'.
|
||||
$path_alias_storage = $this->container->get('entity_type.manager')->getStorage('path_alias');
|
||||
$entities = $path_alias_storage->loadByProperties(['langcode' => 'en']);
|
||||
$path_alias_storage->delete($entities);
|
||||
$this->assertEquals('/bar', $aliasManager->getAliasByPath($path_alias->getPath()), 'Path lookup falls back to recently created language-neutral alias.');
|
||||
|
||||
// Test the situation where the alias and language are the same, but
|
||||
// the source differs. The newer alias record should be returned.
|
||||
$this->createPathAlias('/user/2', '/bar');
|
||||
$aliasManager->cacheClear();
|
||||
$this->assertEquals('/user/2', $aliasManager->getPathByAlias('/bar'), 'Newer alias record is returned when comparing two LanguageInterface::LANGCODE_NOT_SPECIFIED paths with the same alias.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the alias whitelist.
|
||||
*/
|
||||
public function testWhitelist() {
|
||||
$memoryCounterBackend = new MemoryCounterBackend();
|
||||
|
||||
// Create AliasManager and Path object.
|
||||
$whitelist = new AliasWhitelist('path_alias_whitelist', $memoryCounterBackend, $this->container->get('lock'), $this->container->get('state'), $this->container->get('path_alias.repository'));
|
||||
$aliasManager = new AliasManager($this->container->get('path_alias.repository'), $whitelist, $this->container->get('language_manager'), $memoryCounterBackend);
|
||||
|
||||
// No alias for user and admin yet, so should be NULL.
|
||||
$this->assertNull($whitelist->get('user'));
|
||||
$this->assertNull($whitelist->get('admin'));
|
||||
|
||||
// Non-existing path roots should be NULL too. Use a length of 7 to avoid
|
||||
// possible conflict with random aliases below.
|
||||
$this->assertNull($whitelist->get($this->randomMachineName()));
|
||||
|
||||
// Add an alias for user/1, user should get whitelisted now.
|
||||
$this->createPathAlias('/user/1', '/' . $this->randomMachineName());
|
||||
$aliasManager->cacheClear();
|
||||
$this->assertTrue($whitelist->get('user'));
|
||||
$this->assertNull($whitelist->get('admin'));
|
||||
$this->assertNull($whitelist->get($this->randomMachineName()));
|
||||
|
||||
// Add an alias for admin, both should get whitelisted now.
|
||||
$this->createPathAlias('/admin/something', '/' . $this->randomMachineName());
|
||||
$aliasManager->cacheClear();
|
||||
$this->assertTrue($whitelist->get('user'));
|
||||
$this->assertTrue($whitelist->get('admin'));
|
||||
$this->assertNull($whitelist->get($this->randomMachineName()));
|
||||
|
||||
// Remove the user alias again, whitelist entry should be removed.
|
||||
$path_alias_storage = $this->container->get('entity_type.manager')->getStorage('path_alias');
|
||||
$entities = $path_alias_storage->loadByProperties(['path' => '/user/1']);
|
||||
$path_alias_storage->delete($entities);
|
||||
$aliasManager->cacheClear();
|
||||
$this->assertNull($whitelist->get('user'));
|
||||
$this->assertTrue($whitelist->get('admin'));
|
||||
$this->assertNull($whitelist->get($this->randomMachineName()));
|
||||
|
||||
// Destruct the whitelist so that the caches are written.
|
||||
$whitelist->destruct();
|
||||
$this->assertEqual($memoryCounterBackend->getCounter('set', 'path_alias_whitelist'), 1);
|
||||
$memoryCounterBackend->resetCounter();
|
||||
|
||||
// Re-initialize the whitelist using the same cache backend, should load
|
||||
// from cache.
|
||||
$whitelist = new AliasWhitelist('path_alias_whitelist', $memoryCounterBackend, $this->container->get('lock'), $this->container->get('state'), $this->container->get('path_alias.repository'));
|
||||
$this->assertNull($whitelist->get('user'));
|
||||
$this->assertTrue($whitelist->get('admin'));
|
||||
$this->assertNull($whitelist->get($this->randomMachineName()));
|
||||
$this->assertEqual($memoryCounterBackend->getCounter('get', 'path_alias_whitelist'), 1);
|
||||
$this->assertEqual($memoryCounterBackend->getCounter('set', 'path_alias_whitelist'), 0);
|
||||
|
||||
// Destruct the whitelist, should not attempt to write the cache again.
|
||||
$whitelist->destruct();
|
||||
$this->assertEqual($memoryCounterBackend->getCounter('get', 'path_alias_whitelist'), 1);
|
||||
$this->assertEqual($memoryCounterBackend->getCounter('set', 'path_alias_whitelist'), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests situation where the whitelist cache is deleted mid-request.
|
||||
*/
|
||||
public function testWhitelistCacheDeletionMidRequest() {
|
||||
$memoryCounterBackend = new MemoryCounterBackend();
|
||||
|
||||
// Create AliasManager and Path object.
|
||||
$whitelist = new AliasWhitelist('path_alias_whitelist', $memoryCounterBackend, $this->container->get('lock'), $this->container->get('state'), $this->container->get('path_alias.repository'));
|
||||
$aliasManager = new AliasManager($this->container->get('path_alias.repository'), $whitelist, $this->container->get('language_manager'), $memoryCounterBackend);
|
||||
|
||||
// Whitelist cache should not exist at all yet.
|
||||
$this->assertFalse($memoryCounterBackend->get('path_alias_whitelist'));
|
||||
|
||||
// Add some aliases for both menu routes we have.
|
||||
$this->createPathAlias('/admin/something', '/' . $this->randomMachineName());
|
||||
$this->createPathAlias('/user/something', '/' . $this->randomMachineName());
|
||||
|
||||
// Lookup admin path in whitelist. It will query the DB and figure out
|
||||
// that it indeed has an alias, and add it to the internal whitelist and
|
||||
// flag it to be persisted to cache.
|
||||
$this->assertTrue($whitelist->get('admin'));
|
||||
|
||||
// Destruct the whitelist so it persists its cache.
|
||||
$whitelist->destruct();
|
||||
$this->assertEquals($memoryCounterBackend->getCounter('set', 'path_alias_whitelist'), 1);
|
||||
// Cache data should have data for 'user' and 'admin', even though just
|
||||
// 'admin' was looked up. This is because the cache is primed with all
|
||||
// menu router base paths.
|
||||
$this->assertEquals(['user' => FALSE, 'admin' => TRUE], $memoryCounterBackend->get('path_alias_whitelist')->data);
|
||||
$memoryCounterBackend->resetCounter();
|
||||
|
||||
// Re-initialize the whitelist and lookup an alias for the 'user' path.
|
||||
// Whitelist should load data from its cache, see that it hasn't done a
|
||||
// check for 'user' yet, perform the check, then mark the result to be
|
||||
// persisted to cache.
|
||||
$whitelist = new AliasWhitelist('path_alias_whitelist', $memoryCounterBackend, $this->container->get('lock'), $this->container->get('state'), $this->container->get('path_alias.repository'));
|
||||
$this->assertTrue($whitelist->get('user'));
|
||||
|
||||
// Delete the whitelist cache. This could happen from an outside process,
|
||||
// like a code deployment that performs a cache rebuild.
|
||||
$memoryCounterBackend->delete('path_alias_whitelist');
|
||||
|
||||
// Destruct whitelist so it attempts to save the whitelist data to cache.
|
||||
// However it should recognize that the previous cache entry was deleted
|
||||
// from underneath it and not save anything to cache, to protect from
|
||||
// cache corruption.
|
||||
$whitelist->destruct();
|
||||
$this->assertEquals($memoryCounterBackend->getCounter('set', 'path_alias_whitelist'), 0);
|
||||
$this->assertFalse($memoryCounterBackend->get('path_alias_whitelist'));
|
||||
$memoryCounterBackend->resetCounter();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Kernel;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\Core\Path\AliasManager as CoreAliasManager;
|
||||
use Drupal\path_alias\AliasManager;
|
||||
use Drupal\path_alias\Entity\PathAlias;
|
||||
use Drupal\path_alias_deprecated_test\AliasManagerDecorator;
|
||||
use Drupal\path_alias_deprecated_test\NewAliasManager;
|
||||
use Drupal\path_alias_deprecated_test\OverriddenAliasManager;
|
||||
use Drupal\path_alias_deprecated_test\PathAliasDeprecatedTestServiceProvider;
|
||||
|
||||
/**
|
||||
* Tests deprecation of path alias core services and the related BC logic.
|
||||
*
|
||||
* @group path_alias
|
||||
* @group legacy
|
||||
*/
|
||||
class DeprecatedServicesTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['path_alias', 'path_alias_deprecated_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('path_alias');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The "path.alias_manager" service is deprecated. Use "path_alias.manager" instead. See https://drupal.org/node/3092086
|
||||
* @expectedDeprecation The "path_processor_alias" service is deprecated. Use "path_alias.path_processor" instead. See https://drupal.org/node/3092086
|
||||
* @expectedDeprecation The "path_subscriber" service is deprecated. Use "path_alias.subscriber" instead. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testAliasServicesDeprecation() {
|
||||
$this->container->get('path.alias_manager');
|
||||
$this->container->get('path_processor_alias');
|
||||
$this->container->get('path_subscriber');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The "path.alias_manager" service is deprecated. Use "path_alias.manager" instead. See https://drupal.org/node/3092086
|
||||
* @expectedDeprecation The \Drupal\Core\Path\AliasManager class is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Instead, use \Drupal\path_alias\AliasManager. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testOverriddenServiceImplementation() {
|
||||
$class = $this->setServiceClass(OverriddenAliasManager::class);
|
||||
$this->assertServiceClass('path.alias_manager', $class);
|
||||
$this->assertServiceClass('path_alias.manager', AliasManager::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The "path.alias_manager" service is deprecated. Use "path_alias.manager" instead. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testNewServiceImplementation() {
|
||||
$class = $this->setServiceClass(NewAliasManager::class);
|
||||
$this->assertServiceClass('path.alias_manager', $class);
|
||||
$this->assertServiceClass('path_alias.manager', AliasManager::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The "path_alias_deprecated_test.path.alias_manager.inner" service is deprecated. Use "path_alias.manager" instead. See https://drupal.org/node/3092086
|
||||
* @expectedDeprecation The \Drupal\Core\Path\AliasManager class is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Instead, use \Drupal\path_alias\AliasManager. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testDecoratorForOverriddenServiceImplementation() {
|
||||
$this->setServiceClass(OverriddenAliasManager::class, TRUE);
|
||||
$this->assertServiceClass('path.alias_manager', AliasManagerDecorator::class);
|
||||
$this->assertServiceClass('path_alias.manager', AliasManager::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The "path_alias_deprecated_test.path.alias_manager.inner" service is deprecated. Use "path_alias.manager" instead. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testDecoratorForNewServiceImplementation() {
|
||||
$this->setServiceClass(NewAliasManager::class, TRUE);
|
||||
$this->assertServiceClass('path.alias_manager', AliasManagerDecorator::class);
|
||||
$this->assertServiceClass('path_alias.manager', AliasManager::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The "path.alias_manager" service is deprecated. Use "path_alias.manager" instead. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testDefaultImplementations() {
|
||||
$this->assertServiceClass('path.alias_manager', CoreAliasManager::class);
|
||||
$this->assertServiceClass('path_alias.manager', AliasManager::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* No deprecation message expected.
|
||||
*/
|
||||
public function testRegularImplementation() {
|
||||
$this->assertServiceClass('path_alias.manager', AliasManager::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the new alias manager and the legacy ones share the same state.
|
||||
*
|
||||
* @expectedDeprecation The \Drupal\Core\Path\AliasManager class is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Instead, use \Drupal\path_alias\AliasManager. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testAliasManagerSharedState() {
|
||||
/** @var \Drupal\Core\Path\AliasManager $legacy_alias_manager */
|
||||
$legacy_alias_manager = $this->container->get('path.alias_manager');
|
||||
/** @var \Drupal\path_alias\AliasManager $alias_manager */
|
||||
$alias_manager = $this->container->get('path_alias.manager');
|
||||
|
||||
$cache_key = $this->randomMachineName();
|
||||
$alias_manager->setCacheKey($cache_key);
|
||||
$this->assertSharedProperty('preload-paths:' . $cache_key, $legacy_alias_manager, 'cacheKey');
|
||||
|
||||
$invalid_alias = '/' . $this->randomMachineName();
|
||||
$alias_manager->getPathByAlias($invalid_alias);
|
||||
$this->assertSharedProperty(['en' => [$invalid_alias => TRUE]], $legacy_alias_manager, 'noPath');
|
||||
|
||||
$this->assertSharedProperty(FALSE, $legacy_alias_manager, 'preloadedPathLookups');
|
||||
|
||||
/** @var \Drupal\path_alias\Entity\PathAlias $alias */
|
||||
$alias = PathAlias::create([
|
||||
'path' => '/' . $this->randomMachineName(),
|
||||
'alias' => $invalid_alias . '2',
|
||||
]);
|
||||
$alias->save();
|
||||
|
||||
$this->assertSharedProperty([], $legacy_alias_manager, 'preloadedPathLookups');
|
||||
|
||||
/** @var \Drupal\Core\State\StateInterface $state */
|
||||
$state = $this->container->get('state');
|
||||
$state->set('router.path_roots', [ltrim($alias->getPath(), '/')]);
|
||||
|
||||
$alias_manager->getAliasByPath($alias->getPath());
|
||||
$this->assertSharedProperty(['en' => [$alias->getPath() => $alias->getAlias()]], $legacy_alias_manager, 'lookupMap');
|
||||
|
||||
$invalid_path = $alias->getPath() . '/' . $this->randomMachineName();
|
||||
$alias_manager->getAliasByPath($invalid_path);
|
||||
$this->assertSharedProperty(['en' => [$invalid_path => TRUE]], $legacy_alias_manager, 'noAlias');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a shared property has the expected value.
|
||||
*
|
||||
* @param mixed $expected
|
||||
* The property expected value.
|
||||
* @param \Drupal\Core\Path\AliasManager $legacy_alias_manager
|
||||
* An instance of the legacy alias manager.
|
||||
* @param string $property
|
||||
* The property name.
|
||||
*/
|
||||
protected function assertSharedProperty($expected, CoreAliasManager $legacy_alias_manager, $property) {
|
||||
$reflector = new \ReflectionProperty(get_class($legacy_alias_manager), $property);
|
||||
$reflector->setAccessible(TRUE);
|
||||
$this->assertSame($expected, $reflector->getValue($legacy_alias_manager));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the specified service is implemented by the expected class.
|
||||
*
|
||||
* @param string $service_id
|
||||
* A service ID.
|
||||
* @param string $expected_class
|
||||
* The name of the expected class.
|
||||
*/
|
||||
protected function assertServiceClass($service_id, $expected_class) {
|
||||
$service = $this->container->get($service_id);
|
||||
$this->assertSame(get_class($service), $expected_class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified implementation for the service being tested.
|
||||
*
|
||||
* @param string $class
|
||||
* The name of the implementation class.
|
||||
* @param bool $use_decorator
|
||||
* (optional) Whether using a decorator service to wrap the specified class.
|
||||
* Defaults to no decorator.
|
||||
*
|
||||
* @return string
|
||||
* The specified class name.
|
||||
*/
|
||||
protected function setServiceClass($class, $use_decorator = FALSE) {
|
||||
PathAliasDeprecatedTestServiceProvider::$newClass = $class;
|
||||
PathAliasDeprecatedTestServiceProvider::$useDecorator = $use_decorator;
|
||||
$this->container->get('kernel')->rebuildContainer();
|
||||
return $class;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Kernel;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\path_alias\AliasManagerInterface;
|
||||
use Drupal\path_alias\Entity\PathAlias;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\path_alias\Entity\PathAlias
|
||||
*
|
||||
* @group path_alias
|
||||
*/
|
||||
class PathHooksTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['path_alias'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('path_alias');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the PathAlias entity clears caches correctly.
|
||||
*
|
||||
* @covers ::postSave
|
||||
* @covers ::postDelete
|
||||
*/
|
||||
public function testPathHooks() {
|
||||
$path_alias = PathAlias::create([
|
||||
'path' => '/' . $this->randomMachineName(),
|
||||
'alias' => '/' . $this->randomMachineName(),
|
||||
]);
|
||||
|
||||
// Check \Drupal\Core\Path\Entity\PathAlias::postSave() for new path alias
|
||||
// entities.
|
||||
$alias_manager = $this->prophesize(AliasManagerInterface::class);
|
||||
$alias_manager->cacheClear(Argument::any())->shouldBeCalledTimes(1);
|
||||
$alias_manager->cacheClear($path_alias->getPath())->shouldBeCalledTimes(1);
|
||||
\Drupal::getContainer()->set('path_alias.manager', $alias_manager->reveal());
|
||||
$path_alias->save();
|
||||
|
||||
$new_source = '/' . $this->randomMachineName();
|
||||
|
||||
// Check \Drupal\Core\Path\Entity\PathAlias::postSave() for existing path
|
||||
// alias entities.
|
||||
$alias_manager = $this->prophesize(AliasManagerInterface::class);
|
||||
$alias_manager->cacheClear(Argument::any())->shouldBeCalledTimes(2);
|
||||
$alias_manager->cacheClear($path_alias->getPath())->shouldBeCalledTimes(1);
|
||||
$alias_manager->cacheClear($new_source)->shouldBeCalledTimes(1);
|
||||
\Drupal::getContainer()->set('path_alias.manager', $alias_manager->reveal());
|
||||
$path_alias->setPath($new_source);
|
||||
$path_alias->save();
|
||||
|
||||
// Check \Drupal\Core\Path\Entity\PathAlias::postDelete().
|
||||
$alias_manager = $this->prophesize(AliasManagerInterface::class);
|
||||
$alias_manager->cacheClear(Argument::any())->shouldBeCalledTimes(1);
|
||||
$alias_manager->cacheClear($new_source)->shouldBeCalledTimes(1);
|
||||
\Drupal::getContainer()->set('path_alias.manager', $alias_manager->reveal());
|
||||
$path_alias->delete();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,554 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Unit;
|
||||
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\path_alias\AliasRepositoryInterface;
|
||||
use Drupal\path_alias\AliasManager;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\path_alias\AliasManager
|
||||
* @group path_alias
|
||||
*/
|
||||
class AliasManagerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The alias manager.
|
||||
*
|
||||
* @var \Drupal\path_alias\AliasManager
|
||||
*/
|
||||
protected $aliasManager;
|
||||
|
||||
/**
|
||||
* Alias storage.
|
||||
*
|
||||
* @var \Drupal\Core\Path\AliasStorageInterface|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
protected $aliasStorage;
|
||||
|
||||
/**
|
||||
* Alias repository.
|
||||
*
|
||||
* @var \Drupal\path_alias\AliasRepositoryInterface|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
protected $aliasRepository;
|
||||
|
||||
/**
|
||||
* Alias whitelist.
|
||||
*
|
||||
* @var \Drupal\path_alias\AliasWhitelistInterface|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
protected $aliasWhitelist;
|
||||
|
||||
/**
|
||||
* Language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* Cache backend.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* The internal cache key used by the alias manager.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $cacheKey = 'preload-paths:key';
|
||||
|
||||
/**
|
||||
* The cache key passed to the alias manager.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $path = 'key';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->aliasRepository = $this->createMock(AliasRepositoryInterface::class);
|
||||
$this->aliasWhitelist = $this->createMock('Drupal\path_alias\AliasWhitelistInterface');
|
||||
$this->languageManager = $this->createMock('Drupal\Core\Language\LanguageManagerInterface');
|
||||
$this->cache = $this->createMock('Drupal\Core\Cache\CacheBackendInterface');
|
||||
|
||||
$this->aliasManager = new AliasManager($this->aliasRepository, $this->aliasWhitelist, $this->languageManager, $this->cache);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getPathByAlias method for an alias that have no matching path.
|
||||
*
|
||||
* @covers ::getPathByAlias
|
||||
*/
|
||||
public function testGetPathByAliasNoMatch() {
|
||||
$alias = '/' . $this->randomMachineName();
|
||||
|
||||
$language = new Language(['id' => 'en']);
|
||||
|
||||
$this->languageManager->expects($this->any())
|
||||
->method('getCurrentLanguage')
|
||||
->with(LanguageInterface::TYPE_URL)
|
||||
->will($this->returnValue($language));
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('lookupByAlias')
|
||||
->with($alias, $language->getId())
|
||||
->will($this->returnValue(NULL));
|
||||
|
||||
$this->assertEquals($alias, $this->aliasManager->getPathByAlias($alias));
|
||||
// Call it twice to test the static cache.
|
||||
$this->assertEquals($alias, $this->aliasManager->getPathByAlias($alias));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getPathByAlias method for an alias that have a matching path.
|
||||
*
|
||||
* @covers ::getPathByAlias
|
||||
*/
|
||||
public function testGetPathByAliasNatch() {
|
||||
$alias = $this->randomMachineName();
|
||||
$path = $this->randomMachineName();
|
||||
|
||||
$language = $this->setUpCurrentLanguage();
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('lookupByAlias')
|
||||
->with($alias, $language->getId())
|
||||
->will($this->returnValue(['path' => $path]));
|
||||
|
||||
$this->assertEquals($path, $this->aliasManager->getPathByAlias($alias));
|
||||
// Call it twice to test the static cache.
|
||||
$this->assertEquals($path, $this->aliasManager->getPathByAlias($alias));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getPathByAlias method when a langcode is passed explicitly.
|
||||
*
|
||||
* @covers ::getPathByAlias
|
||||
*/
|
||||
public function testGetPathByAliasLangcode() {
|
||||
$alias = $this->randomMachineName();
|
||||
$path = $this->randomMachineName();
|
||||
|
||||
$this->languageManager->expects($this->never())
|
||||
->method('getCurrentLanguage');
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('lookupByAlias')
|
||||
->with($alias, 'de')
|
||||
->will($this->returnValue(['path' => $path]));
|
||||
|
||||
$this->assertEquals($path, $this->aliasManager->getPathByAlias($alias, 'de'));
|
||||
// Call it twice to test the static cache.
|
||||
$this->assertEquals($path, $this->aliasManager->getPathByAlias($alias, 'de'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAliasByPath method for a path that is not in the whitelist.
|
||||
*
|
||||
* @covers ::getAliasByPath
|
||||
*/
|
||||
public function testGetAliasByPathWhitelist() {
|
||||
$path_part1 = $this->randomMachineName();
|
||||
$path_part2 = $this->randomMachineName();
|
||||
$path = '/' . $path_part1 . '/' . $path_part2;
|
||||
|
||||
$this->setUpCurrentLanguage();
|
||||
|
||||
$this->aliasWhitelist->expects($this->any())
|
||||
->method('get')
|
||||
->with($path_part1)
|
||||
->will($this->returnValue(FALSE));
|
||||
|
||||
// The whitelist returns FALSE for that path part, so the storage should
|
||||
// never be called.
|
||||
$this->aliasRepository->expects($this->never())
|
||||
->method('lookupBySystemPath');
|
||||
|
||||
$this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAliasByPath method for a path that has no matching alias.
|
||||
*
|
||||
* @covers ::getAliasByPath
|
||||
*/
|
||||
public function testGetAliasByPathNoMatch() {
|
||||
$path_part1 = $this->randomMachineName();
|
||||
$path_part2 = $this->randomMachineName();
|
||||
$path = '/' . $path_part1 . '/' . $path_part2;
|
||||
|
||||
$language = $this->setUpCurrentLanguage();
|
||||
|
||||
$this->aliasManager->setCacheKey($this->path);
|
||||
|
||||
$this->aliasWhitelist->expects($this->any())
|
||||
->method('get')
|
||||
->with($path_part1)
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('lookupBySystemPath')
|
||||
->with($path, $language->getId())
|
||||
->will($this->returnValue(NULL));
|
||||
|
||||
$this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
|
||||
// Call it twice to test the static cache.
|
||||
$this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
|
||||
|
||||
// This needs to write out the cache.
|
||||
$this->cache->expects($this->once())
|
||||
->method('set')
|
||||
->with($this->cacheKey, [$language->getId() => [$path]], (int) $_SERVER['REQUEST_TIME'] + (60 * 60 * 24));
|
||||
|
||||
$this->aliasManager->writeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAliasByPath method for a path that has a matching alias.
|
||||
*
|
||||
* @covers ::getAliasByPath
|
||||
* @covers ::writeCache
|
||||
*/
|
||||
public function testGetAliasByPathMatch() {
|
||||
$path_part1 = $this->randomMachineName();
|
||||
$path_part2 = $this->randomMachineName();
|
||||
$path = '/' . $path_part1 . '/' . $path_part2;
|
||||
$alias = $this->randomMachineName();
|
||||
|
||||
$language = $this->setUpCurrentLanguage();
|
||||
|
||||
$this->aliasManager->setCacheKey($this->path);
|
||||
|
||||
$this->aliasWhitelist->expects($this->any())
|
||||
->method('get')
|
||||
->with($path_part1)
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('lookupBySystemPath')
|
||||
->with($path, $language->getId())
|
||||
->will($this->returnValue(['alias' => $alias]));
|
||||
|
||||
$this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
|
||||
// Call it twice to test the static cache.
|
||||
$this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
|
||||
|
||||
// This needs to write out the cache.
|
||||
$this->cache->expects($this->once())
|
||||
->method('set')
|
||||
->with($this->cacheKey, [$language->getId() => [$path]], (int) $_SERVER['REQUEST_TIME'] + (60 * 60 * 24));
|
||||
|
||||
$this->aliasManager->writeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAliasByPath method for a path that is preloaded.
|
||||
*
|
||||
* @covers ::getAliasByPath
|
||||
* @covers ::writeCache
|
||||
*/
|
||||
public function testGetAliasByPathCachedMatch() {
|
||||
$path_part1 = $this->randomMachineName();
|
||||
$path_part2 = $this->randomMachineName();
|
||||
$path = '/' . $path_part1 . '/' . $path_part2;
|
||||
$alias = $this->randomMachineName();
|
||||
|
||||
$language = $this->setUpCurrentLanguage();
|
||||
|
||||
$cached_paths = [$language->getId() => [$path]];
|
||||
$this->cache->expects($this->once())
|
||||
->method('get')
|
||||
->with($this->cacheKey)
|
||||
->will($this->returnValue((object) ['data' => $cached_paths]));
|
||||
|
||||
// Simulate a request so that the preloaded paths are fetched.
|
||||
$this->aliasManager->setCacheKey($this->path);
|
||||
|
||||
$this->aliasWhitelist->expects($this->any())
|
||||
->method('get')
|
||||
->with($path_part1)
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('preloadPathAlias')
|
||||
->with($cached_paths[$language->getId()], $language->getId())
|
||||
->will($this->returnValue([$path => $alias]));
|
||||
|
||||
// LookupPathAlias should not be called.
|
||||
$this->aliasRepository->expects($this->never())
|
||||
->method('lookupBySystemPath');
|
||||
|
||||
$this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
|
||||
// Call it twice to test the static cache.
|
||||
$this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
|
||||
|
||||
// This must not write to the cache again.
|
||||
$this->cache->expects($this->never())
|
||||
->method('set');
|
||||
$this->aliasManager->writeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAliasByPath cache when a different language is requested.
|
||||
*
|
||||
* @covers ::getAliasByPath
|
||||
* @covers ::writeCache
|
||||
*/
|
||||
public function testGetAliasByPathCachedMissLanguage() {
|
||||
$path_part1 = $this->randomMachineName();
|
||||
$path_part2 = $this->randomMachineName();
|
||||
$path = '/' . $path_part1 . '/' . $path_part2;
|
||||
$alias = $this->randomMachineName();
|
||||
|
||||
$language = $this->setUpCurrentLanguage();
|
||||
$cached_language = new Language(['id' => 'de']);
|
||||
|
||||
$cached_paths = [$cached_language->getId() => [$path]];
|
||||
$this->cache->expects($this->once())
|
||||
->method('get')
|
||||
->with($this->cacheKey)
|
||||
->will($this->returnValue((object) ['data' => $cached_paths]));
|
||||
|
||||
// Simulate a request so that the preloaded paths are fetched.
|
||||
$this->aliasManager->setCacheKey($this->path);
|
||||
|
||||
$this->aliasWhitelist->expects($this->any())
|
||||
->method('get')
|
||||
->with($path_part1)
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
// The requested language is different than the cached, so this will
|
||||
// need to load.
|
||||
$this->aliasRepository->expects($this->never())
|
||||
->method('preloadPathAlias');
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('lookupBySystemPath')
|
||||
->with($path, $language->getId())
|
||||
->will($this->returnValue(['alias' => $alias]));
|
||||
|
||||
$this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
|
||||
// Call it twice to test the static cache.
|
||||
$this->assertEquals($alias, $this->aliasManager->getAliasByPath($path));
|
||||
|
||||
// There is already a cache entry, so this should not write out to the
|
||||
// cache.
|
||||
$this->cache->expects($this->never())
|
||||
->method('set');
|
||||
$this->aliasManager->writeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAliasByPath cache with a preloaded path without alias.
|
||||
*
|
||||
* @covers ::getAliasByPath
|
||||
* @covers ::writeCache
|
||||
*/
|
||||
public function testGetAliasByPathCachedMissNoAlias() {
|
||||
$path_part1 = $this->randomMachineName();
|
||||
$path_part2 = $this->randomMachineName();
|
||||
$path = '/' . $path_part1 . '/' . $path_part2;
|
||||
$cached_path = $this->randomMachineName();
|
||||
$cached_alias = $this->randomMachineName();
|
||||
|
||||
$language = $this->setUpCurrentLanguage();
|
||||
|
||||
$cached_paths = [$language->getId() => [$cached_path, $path]];
|
||||
$this->cache->expects($this->once())
|
||||
->method('get')
|
||||
->with($this->cacheKey)
|
||||
->will($this->returnValue((object) ['data' => $cached_paths]));
|
||||
|
||||
// Simulate a request so that the preloaded paths are fetched.
|
||||
$this->aliasManager->setCacheKey($this->path);
|
||||
|
||||
$this->aliasWhitelist->expects($this->any())
|
||||
->method('get')
|
||||
->with($path_part1)
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('preloadPathAlias')
|
||||
->with($cached_paths[$language->getId()], $language->getId())
|
||||
->will($this->returnValue([$cached_path => $cached_alias]));
|
||||
|
||||
// LookupPathAlias() should not be called.
|
||||
$this->aliasRepository->expects($this->never())
|
||||
->method('lookupBySystemPath');
|
||||
|
||||
$this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
|
||||
// Call it twice to test the static cache.
|
||||
$this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
|
||||
|
||||
// This must not write to the cache again.
|
||||
$this->cache->expects($this->never())
|
||||
->method('set');
|
||||
$this->aliasManager->writeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAliasByPath cache with an unpreloaded path without alias.
|
||||
*
|
||||
* @covers ::getAliasByPath
|
||||
* @covers ::writeCache
|
||||
*/
|
||||
public function testGetAliasByPathUncachedMissNoAlias() {
|
||||
$path_part1 = $this->randomMachineName();
|
||||
$path_part2 = $this->randomMachineName();
|
||||
$path = '/' . $path_part1 . '/' . $path_part2;
|
||||
$cached_path = $this->randomMachineName();
|
||||
$cached_alias = $this->randomMachineName();
|
||||
|
||||
$language = $this->setUpCurrentLanguage();
|
||||
|
||||
$cached_paths = [$language->getId() => [$cached_path]];
|
||||
$this->cache->expects($this->once())
|
||||
->method('get')
|
||||
->with($this->cacheKey)
|
||||
->will($this->returnValue((object) ['data' => $cached_paths]));
|
||||
|
||||
// Simulate a request so that the preloaded paths are fetched.
|
||||
$this->aliasManager->setCacheKey($this->path);
|
||||
|
||||
$this->aliasWhitelist->expects($this->any())
|
||||
->method('get')
|
||||
->with($path_part1)
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('preloadPathAlias')
|
||||
->with($cached_paths[$language->getId()], $language->getId())
|
||||
->will($this->returnValue([$cached_path => $cached_alias]));
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('lookupBySystemPath')
|
||||
->with($path, $language->getId())
|
||||
->will($this->returnValue(NULL));
|
||||
|
||||
$this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
|
||||
// Call it twice to test the static cache.
|
||||
$this->assertEquals($path, $this->aliasManager->getAliasByPath($path));
|
||||
|
||||
// There is already a cache entry, so this should not write out to the
|
||||
// cache.
|
||||
$this->cache->expects($this->never())
|
||||
->method('set');
|
||||
$this->aliasManager->writeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::cacheClear
|
||||
*/
|
||||
public function testCacheClear() {
|
||||
$path = '/path';
|
||||
$alias = '/alias';
|
||||
$language = $this->setUpCurrentLanguage();
|
||||
$this->aliasRepository->expects($this->exactly(2))
|
||||
->method('lookupBySystemPath')
|
||||
->with($path, $language->getId())
|
||||
->willReturn(['alias' => $alias]);
|
||||
$this->aliasWhitelist->expects($this->any())
|
||||
->method('get')
|
||||
->willReturn(TRUE);
|
||||
|
||||
// Populate the lookup map.
|
||||
$this->assertEquals($alias, $this->aliasManager->getAliasByPath($path, $language->getId()));
|
||||
|
||||
// Check that the cache is populated.
|
||||
$this->aliasRepository->expects($this->never())
|
||||
->method('lookupByAlias');
|
||||
$this->assertEquals($path, $this->aliasManager->getPathByAlias($alias, $language->getId()));
|
||||
|
||||
// Clear specific source.
|
||||
$this->cache->expects($this->exactly(2))
|
||||
->method('delete');
|
||||
$this->aliasManager->cacheClear($path);
|
||||
|
||||
// Ensure cache has been cleared (this will be the 2nd call to
|
||||
// `lookupPathAlias` if cache is cleared).
|
||||
$this->assertEquals($alias, $this->aliasManager->getAliasByPath($path, $language->getId()));
|
||||
|
||||
// Clear non-existent source.
|
||||
$this->aliasManager->cacheClear('non-existent');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAliasByPath cache with an unpreloaded path with alias.
|
||||
*
|
||||
* @covers ::getAliasByPath
|
||||
* @covers ::writeCache
|
||||
*/
|
||||
public function testGetAliasByPathUncachedMissWithAlias() {
|
||||
$path_part1 = $this->randomMachineName();
|
||||
$path_part2 = $this->randomMachineName();
|
||||
$path = '/' . $path_part1 . '/' . $path_part2;
|
||||
$cached_path = $this->randomMachineName();
|
||||
$cached_no_alias_path = $this->randomMachineName();
|
||||
$cached_alias = $this->randomMachineName();
|
||||
$new_alias = $this->randomMachineName();
|
||||
|
||||
$language = $this->setUpCurrentLanguage();
|
||||
|
||||
$cached_paths = [$language->getId() => [$cached_path, $cached_no_alias_path]];
|
||||
$this->cache->expects($this->once())
|
||||
->method('get')
|
||||
->with($this->cacheKey)
|
||||
->will($this->returnValue((object) ['data' => $cached_paths]));
|
||||
|
||||
// Simulate a request so that the preloaded paths are fetched.
|
||||
$this->aliasManager->setCacheKey($this->path);
|
||||
|
||||
$this->aliasWhitelist->expects($this->any())
|
||||
->method('get')
|
||||
->with($path_part1)
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('preloadPathAlias')
|
||||
->with($cached_paths[$language->getId()], $language->getId())
|
||||
->will($this->returnValue([$cached_path => $cached_alias]));
|
||||
|
||||
$this->aliasRepository->expects($this->once())
|
||||
->method('lookupBySystemPath')
|
||||
->with($path, $language->getId())
|
||||
->will($this->returnValue(['alias' => $new_alias]));
|
||||
|
||||
$this->assertEquals($new_alias, $this->aliasManager->getAliasByPath($path));
|
||||
// Call it twice to test the static cache.
|
||||
$this->assertEquals($new_alias, $this->aliasManager->getAliasByPath($path));
|
||||
|
||||
// There is already a cache entry, so this should not write out to the
|
||||
// cache.
|
||||
$this->cache->expects($this->never())
|
||||
->method('set');
|
||||
$this->aliasManager->writeCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the current language.
|
||||
*
|
||||
* @return \Drupal\Core\Language\LanguageInterface
|
||||
* The current language object.
|
||||
*/
|
||||
protected function setUpCurrentLanguage() {
|
||||
$language = new Language(['id' => 'en']);
|
||||
|
||||
$this->languageManager->expects($this->any())
|
||||
->method('getCurrentLanguage')
|
||||
->with(LanguageInterface::TYPE_URL)
|
||||
->will($this->returnValue($language));
|
||||
|
||||
return $language;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Unit;
|
||||
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\EventSubscriber\PathSubscriber;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Drupal\Core\Path\AliasManager as CoreAliasManager;
|
||||
use Drupal\Core\Path\AliasManagerInterface as CoreAliasManagerInterface;
|
||||
use Drupal\Core\Path\AliasWhitelist as CoreAliasWhitelist;
|
||||
use Drupal\Core\Path\CurrentPathStack;
|
||||
use Drupal\Core\PathProcessor\PathProcessorAlias;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\path_alias\AliasManager;
|
||||
use Drupal\path_alias\AliasManagerInterface;
|
||||
use Drupal\path_alias\AliasRepositoryInterface;
|
||||
use Drupal\path_alias\AliasWhitelist;
|
||||
use Drupal\path_alias\AliasWhitelistInterface;
|
||||
use Drupal\path_alias\EventSubscriber\PathAliasSubscriber;
|
||||
use Drupal\path_alias\PathProcessor\AliasPathProcessor;
|
||||
use Drupal\system\Form\SiteInformationForm;
|
||||
use Drupal\system\Plugin\Condition\RequestPath;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\views\Plugin\views\argument_default\Raw;
|
||||
|
||||
/**
|
||||
* Tests deprecation of path alias core service classes.
|
||||
*
|
||||
* @group path_alias
|
||||
* @group legacy
|
||||
*/
|
||||
class DeprecatedClassesTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\path_alias\AliasManagerInterface
|
||||
*/
|
||||
protected $aliasManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\path_alias\AliasRepositoryInterface
|
||||
*/
|
||||
protected $aliasRepository;
|
||||
|
||||
/**
|
||||
* @var \Drupal\path_alias\AliasWhitelistInterface
|
||||
*/
|
||||
protected $aliasWhitelist;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Path\CurrentPathStack
|
||||
*/
|
||||
protected $currentPathStack;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface
|
||||
*/
|
||||
protected $lock;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->aliasManager = $this->prophesize(AliasManagerInterface::class)
|
||||
->reveal();
|
||||
$this->aliasRepository = $this->prophesize(AliasRepositoryInterface::class)
|
||||
->reveal();
|
||||
$this->aliasWhitelist = $this->prophesize(AliasWhitelistInterface::class)
|
||||
->reveal();
|
||||
$this->cache = $this->prophesize(CacheBackendInterface::class)
|
||||
->reveal();
|
||||
$this->currentPathStack = $this->prophesize(CurrentPathStack::class)
|
||||
->reveal();
|
||||
$this->languageManager = $this->prophesize(LanguageManagerInterface::class)
|
||||
->reveal();
|
||||
$this->lock = $this->prophesize(LockBackendInterface::class)
|
||||
->reveal();
|
||||
$this->state = $this->prophesize(StateInterface::class)
|
||||
->reveal();
|
||||
|
||||
/** @var \Prophecy\Prophecy\ObjectProphecy $container */
|
||||
$container = $this->prophesize(ContainerBuilder::class);
|
||||
$container->get('path_alias.manager')
|
||||
->willReturn($this->aliasManager);
|
||||
\Drupal::setContainer($container->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\EventSubscriber\PathSubscriber::__construct
|
||||
*
|
||||
* @expectedDeprecation The \Drupal\Core\EventSubscriber\PathSubscriber class is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Instead, use \Drupal\path_alias\EventSubscriber\PathAliasSubscriber. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testPathSubscriber() {
|
||||
new PathSubscriber($this->aliasManager, $this->currentPathStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\path_alias\EventSubscriber\PathAliasSubscriber::__construct
|
||||
*/
|
||||
public function testPathAliasSubscriber() {
|
||||
$object = new PathAliasSubscriber($this->aliasManager, $this->currentPathStack);
|
||||
$this->assertInstanceOf(PathSubscriber::class, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\PathProcessor\PathProcessorAlias::__construct
|
||||
*
|
||||
* @expectedDeprecation The \Drupal\Core\PathProcessor\PathProcessorAlias class is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Instead, use \Drupal\path_alias\PathProcessor\AliasPathProcessor. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testPathProcessorAlias() {
|
||||
new PathProcessorAlias($this->aliasManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\path_alias\PathProcessor\AliasPathProcessor::__construct
|
||||
*/
|
||||
public function testAliasPathProcessor() {
|
||||
$object = new AliasPathProcessor($this->aliasManager);
|
||||
$this->assertInstanceOf(PathProcessorAlias::class, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Path\AliasManager::__construct
|
||||
*
|
||||
* @expectedDeprecation The \Drupal\Core\Path\AliasManager class is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Instead, use \Drupal\path_alias\AliasManager. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testCoreAliasManager() {
|
||||
new CoreAliasManager($this->aliasRepository, $this->aliasWhitelist, $this->languageManager, $this->cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\path_alias\AliasManager::__construct
|
||||
*/
|
||||
public function testAliasManager() {
|
||||
$object = new AliasManager($this->aliasRepository, $this->aliasWhitelist, $this->languageManager, $this->cache);
|
||||
$this->assertInstanceOf(CoreAliasManager::class, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Path\AliasWhitelist::__construct
|
||||
*
|
||||
* @expectedDeprecation The \Drupal\Core\Path\AliasWhitelist class is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Instead, use \Drupal\path_alias\AliasWhitelist. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function testCoreAliasWhitelist() {
|
||||
new CoreAliasWhitelist('path_alias_whitelist', $this->cache, $this->lock, $this->state, $this->aliasRepository);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\path_alias\AliasWhitelist::__construct
|
||||
*/
|
||||
public function testAliasWhitelist() {
|
||||
$object = new AliasWhitelist('path_alias_whitelist', $this->cache, $this->lock, $this->state, $this->aliasRepository);
|
||||
$this->assertInstanceOf(CoreAliasWhitelist::class, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\system\Form\SiteInformationForm::__construct
|
||||
*
|
||||
* @expectedDeprecation Calling \Drupal\system\Form\SiteInformationForm::__construct with \Drupal\Core\Path\AliasManagerInterface instead of \Drupal\path_alias\AliasManagerInterface is deprecated in drupal:8.8.0. The new service will be required in drupal:9.0.0. See https://www.drupal.org/node/3092086
|
||||
*/
|
||||
public function testDeprecatedSystemInformationFormConstructorParameters() {
|
||||
$this->assertDeprecatedConstructorParameter(SiteInformationForm::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\system\Plugin\Condition\RequestPath::__construct
|
||||
*
|
||||
* @expectedDeprecation Calling \Drupal\system\Plugin\Condition\RequestPath::__construct with \Drupal\Core\Path\AliasManagerInterface instead of \Drupal\path_alias\AliasManagerInterface is deprecated in drupal:8.8.0. The new service will be required in drupal:9.0.0. See https://www.drupal.org/node/3092086
|
||||
*/
|
||||
public function testDeprecatedRequestPathConstructorParameters() {
|
||||
$this->assertDeprecatedConstructorParameter(RequestPath::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\views\Plugin\views\argument_default\Raw::__construct
|
||||
*
|
||||
* @expectedDeprecation Calling \Drupal\views\Plugin\views\argument_default\Raw::__construct with \Drupal\Core\Path\AliasManagerInterface instead of \Drupal\path_alias\AliasManagerInterface is deprecated in drupal:8.8.0. The new service will be required in drupal:9.0.0. See https://www.drupal.org/node/3092086
|
||||
*/
|
||||
public function testDeprecatedRawConstructorParameters() {
|
||||
$this->assertDeprecatedConstructorParameter(Raw::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that deprecation for the \Drupal\Core\Path\AliasManagerInterface.
|
||||
*
|
||||
* @param string $tested_class_name
|
||||
* The name of the tested class.
|
||||
*
|
||||
* @dataProvider deprecatedConstructorParametersProvider
|
||||
*
|
||||
* @expectedDeprecation The \Drupal\Core\Path\AliasManagerInterface interface is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Instead, use \Drupal\path_alias\AliasManagerInterface. See https://drupal.org/node/3092086
|
||||
*/
|
||||
public function assertDeprecatedConstructorParameter($tested_class_name) {
|
||||
$tested_class = new \ReflectionClass($tested_class_name);
|
||||
$parameters = $tested_class->getConstructor()
|
||||
->getParameters();
|
||||
|
||||
$args = [];
|
||||
foreach ($parameters as $parameter) {
|
||||
$name = $parameter->getName();
|
||||
if ($name === 'alias_manager') {
|
||||
$class_name = CoreAliasManagerInterface::class;
|
||||
}
|
||||
else {
|
||||
$type = $parameter->getType();
|
||||
$class_name = $type ? (string) $type : NULL;
|
||||
}
|
||||
$args[$name] = isset($class_name) && $class_name !== 'array' ? $this->prophesize($class_name)->reveal() : [];
|
||||
}
|
||||
|
||||
$instance = $tested_class->newInstanceArgs($args);
|
||||
$property = $tested_class->getProperty('aliasManager');
|
||||
$property->setAccessible(TRUE);
|
||||
$this->assertInstanceOf(AliasManagerInterface::class, $property->getValue($instance));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\path_alias\Unit\PathProcessor;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\path_alias\PathProcessor\AliasPathProcessor;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\path_alias\PathProcessor\AliasPathProcessor
|
||||
* @group PathProcessor
|
||||
* @group path_alias
|
||||
*/
|
||||
class AliasPathProcessorTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The mocked alias manager.
|
||||
*
|
||||
* @var \Drupal\path_alias\AliasManagerInterface|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
protected $aliasManager;
|
||||
|
||||
/**
|
||||
* The tested path processor.
|
||||
*
|
||||
* @var \Drupal\path_alias\PathProcessor\AliasPathProcessor
|
||||
*/
|
||||
protected $pathProcessor;
|
||||
|
||||
protected function setUp() {
|
||||
$this->aliasManager = $this->createMock('Drupal\path_alias\AliasManagerInterface');
|
||||
$this->pathProcessor = new AliasPathProcessor($this->aliasManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the processInbound method.
|
||||
*
|
||||
* @see \Drupal\path_alias\PathProcessor\AliasPathProcessor::processInbound
|
||||
*/
|
||||
public function testProcessInbound() {
|
||||
$this->aliasManager->expects($this->exactly(2))
|
||||
->method('getPathByAlias')
|
||||
->will($this->returnValueMap([
|
||||
['urlalias', NULL, 'internal-url'],
|
||||
['url', NULL, 'url'],
|
||||
]));
|
||||
|
||||
$request = Request::create('/urlalias');
|
||||
$this->assertEquals('internal-url', $this->pathProcessor->processInbound('urlalias', $request));
|
||||
$request = Request::create('/url');
|
||||
$this->assertEquals('url', $this->pathProcessor->processInbound('url', $request));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::processOutbound
|
||||
*
|
||||
* @dataProvider providerTestProcessOutbound
|
||||
*/
|
||||
public function testProcessOutbound($path, array $options, $expected_path) {
|
||||
$this->aliasManager->expects($this->any())
|
||||
->method('getAliasByPath')
|
||||
->will($this->returnValueMap([
|
||||
['internal-url', NULL, 'urlalias'],
|
||||
['url', NULL, 'url'],
|
||||
]));
|
||||
|
||||
$bubbleable_metadata = new BubbleableMetadata();
|
||||
$this->assertEquals($expected_path, $this->pathProcessor->processOutbound($path, $options, NULL, $bubbleable_metadata));
|
||||
// Cacheability of paths replaced with path aliases is permanent.
|
||||
// @todo https://www.drupal.org/node/2480077
|
||||
$this->assertEquals((new BubbleableMetadata())->setCacheMaxAge(Cache::PERMANENT), $bubbleable_metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function providerTestProcessOutbound() {
|
||||
return [
|
||||
['internal-url', [], 'urlalias'],
|
||||
['internal-url', ['alias' => TRUE], 'internal-url'],
|
||||
['url', [], 'url'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user