Issue #3007669 by amateescu, Berdir, catch: Add publishing status to path aliases
parent
791a988503
commit
e0c5f41ff4
|
@ -171,17 +171,30 @@ class AliasStorage implements AliasStorageInterface {
|
|||
$storage->delete($storage->loadMultiple($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a SELECT query for the path_alias base table.
|
||||
*
|
||||
* @return \Drupal\Core\Database\Query\SelectInterface
|
||||
* A Select query object.
|
||||
*/
|
||||
protected function getBaseQuery() {
|
||||
$query = $this->connection->select(static::TABLE, 'base_table');
|
||||
$query->condition('base_table.status', 1);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preloadPathAlias($preloaded, $langcode) {
|
||||
$select = $this->connection->select(static::TABLE)
|
||||
->fields(static::TABLE, ['path', 'alias']);
|
||||
$select = $this->getBaseQuery()
|
||||
->fields('base_table', ['path', 'alias']);
|
||||
|
||||
if (!empty($preloaded)) {
|
||||
$conditions = new Condition('OR');
|
||||
foreach ($preloaded as $preloaded_item) {
|
||||
$conditions->condition('path', $this->connection->escapeLike($preloaded_item), 'LIKE');
|
||||
$conditions->condition('base_table.path', $this->connection->escapeLike($preloaded_item), 'LIKE');
|
||||
}
|
||||
$select->condition($conditions);
|
||||
}
|
||||
|
@ -191,7 +204,7 @@ class AliasStorage implements AliasStorageInterface {
|
|||
// We order by ID ASC so that fetchAllKeyed() returns the most recently
|
||||
// created alias for each source. Subsequent queries using fetchField() must
|
||||
// use ID DESC to have the same effect.
|
||||
$select->orderBy('id', 'ASC');
|
||||
$select->orderBy('base_table.id', 'ASC');
|
||||
|
||||
return $select->execute()->fetchAllKeyed();
|
||||
}
|
||||
|
@ -201,13 +214,13 @@ class AliasStorage implements AliasStorageInterface {
|
|||
*/
|
||||
public function lookupPathAlias($path, $langcode) {
|
||||
// See the queries above. Use LIKE for case-insensitive matching.
|
||||
$select = $this->connection->select(static::TABLE)
|
||||
->fields(static::TABLE, ['alias'])
|
||||
->condition('path', $this->connection->escapeLike($path), 'LIKE');
|
||||
$select = $this->getBaseQuery()
|
||||
->fields('base_table', ['alias'])
|
||||
->condition('base_table.path', $this->connection->escapeLike($path), 'LIKE');
|
||||
|
||||
$this->addLanguageFallback($select, $langcode);
|
||||
|
||||
$select->orderBy('id', 'DESC');
|
||||
$select->orderBy('base_table.id', 'DESC');
|
||||
|
||||
return $select->execute()->fetchField();
|
||||
}
|
||||
|
@ -217,13 +230,13 @@ class AliasStorage implements AliasStorageInterface {
|
|||
*/
|
||||
public function lookupPathSource($alias, $langcode) {
|
||||
// See the queries above. Use LIKE for case-insensitive matching.
|
||||
$select = $this->connection->select(static::TABLE)
|
||||
->fields(static::TABLE, ['path'])
|
||||
->condition('alias', $this->connection->escapeLike($alias), 'LIKE');
|
||||
$select = $this->getBaseQuery()
|
||||
->fields('base_table', ['path'])
|
||||
->condition('base_table.alias', $this->connection->escapeLike($alias), 'LIKE');
|
||||
|
||||
$this->addLanguageFallback($select, $langcode);
|
||||
|
||||
$select->orderBy('id', 'DESC');
|
||||
$select->orderBy('base_table.id', 'DESC');
|
||||
|
||||
return $select->execute()->fetchField();
|
||||
}
|
||||
|
@ -246,12 +259,12 @@ class AliasStorage implements AliasStorageInterface {
|
|||
array_pop($langcode_list);
|
||||
}
|
||||
elseif ($langcode > LanguageInterface::LANGCODE_NOT_SPECIFIED) {
|
||||
$query->orderBy('langcode', 'DESC');
|
||||
$query->orderBy('base_table.langcode', 'DESC');
|
||||
}
|
||||
else {
|
||||
$query->orderBy('langcode', 'ASC');
|
||||
$query->orderBy('base_table.langcode', 'ASC');
|
||||
}
|
||||
$query->condition('langcode', $langcode_list, 'IN');
|
||||
$query->condition('base_table.langcode', $langcode_list, 'IN');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -304,11 +317,11 @@ class AliasStorage implements AliasStorageInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function pathHasMatchingAlias($initial_substring) {
|
||||
$query = $this->connection->select(static::TABLE);
|
||||
$query = $this->getBaseQuery();
|
||||
$query->addExpression(1);
|
||||
|
||||
return (bool) $query
|
||||
->condition('path', $this->connection->escapeLike($initial_substring) . '%', 'LIKE')
|
||||
->condition('base_table.path', $this->connection->escapeLike($initial_substring) . '%', 'LIKE')
|
||||
->range(0, 1)
|
||||
->execute()
|
||||
->fetchField();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\Core\Path\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;
|
||||
|
@ -34,6 +35,7 @@ use Drupal\Core\Path\PathAliasInterface;
|
|||
* "revision" = "revision_id",
|
||||
* "langcode" = "langcode",
|
||||
* "uuid" = "uuid",
|
||||
* "published" = "status",
|
||||
* },
|
||||
* admin_permission = "administer url aliases",
|
||||
* list_cache_tags = { "route_match" },
|
||||
|
@ -41,6 +43,8 @@ use Drupal\Core\Path\PathAliasInterface;
|
|||
*/
|
||||
class PathAlias extends ContentEntityBase implements PathAliasInterface {
|
||||
|
||||
use EntityPublishedTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -61,6 +65,10 @@ class PathAlias extends ContentEntityBase implements PathAliasInterface {
|
|||
|
||||
$fields['langcode']->setDefaultValue(LanguageInterface::LANGCODE_NOT_SPECIFIED);
|
||||
|
||||
// Add the published field.
|
||||
$fields += static::publishedBaseFieldDefinitions($entity_type);
|
||||
$fields['status']->setTranslatable(FALSE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
namespace Drupal\Core\Path;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\EntityPublishedInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface defining a path_alias entity.
|
||||
*/
|
||||
interface PathAliasInterface extends ContentEntityInterface {
|
||||
interface PathAliasInterface extends ContentEntityInterface, EntityPublishedInterface {
|
||||
|
||||
/**
|
||||
* Gets the source path of the alias.
|
||||
|
|
|
@ -17,8 +17,8 @@ class PathAliasStorageSchema extends SqlContentEntityStorageSchema {
|
|||
$schema = parent::getEntitySchema($entity_type, $reset);
|
||||
|
||||
$schema[$this->storage->getBaseTable()]['indexes'] += [
|
||||
'path_alias__alias_langcode_id' => ['alias', 'langcode', 'id'],
|
||||
'path_alias__path_langcode_id' => ['path', 'langcode', 'id'],
|
||||
'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,20 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\Routing;
|
||||
|
||||
/**
|
||||
* Extends the router provider interface to provide caching support.
|
||||
*/
|
||||
interface CacheableRouteProviderInterface extends RouteProviderInterface {
|
||||
|
||||
/**
|
||||
* Adds a cache key part to be used in the cache ID of the route collection.
|
||||
*
|
||||
* @param string $cache_key_provider
|
||||
* The provider of the cache key part.
|
||||
* @param string $cache_key_part
|
||||
* A string to be used as a cache key part.
|
||||
*/
|
||||
public function addExtraCacheKeyPart($cache_key_provider, $cache_key_part);
|
||||
|
||||
}
|
|
@ -21,7 +21,7 @@ use Drupal\Core\Database\Connection;
|
|||
/**
|
||||
* A Route Provider front-end for all Drupal-stored routes.
|
||||
*/
|
||||
class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProviderInterface, EventSubscriberInterface {
|
||||
class RouteProvider implements CacheableRouteProviderInterface, PreloadableRouteProviderInterface, PagedRouteProviderInterface, EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The database connection from which to read route information.
|
||||
|
@ -98,6 +98,13 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
|
|||
*/
|
||||
const ROUTE_LOAD_CID_PREFIX = 'route_provider.route_load:';
|
||||
|
||||
/**
|
||||
* An array of cache key parts to be used for the route match cache.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $extraCacheKeyParts = [];
|
||||
|
||||
/**
|
||||
* Constructs a new PathMatcher.
|
||||
*
|
||||
|
@ -442,6 +449,13 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
|
|||
return $this->connection->query("SELECT COUNT(*) FROM {" . $this->connection->escapeTable($this->tableName) . "}")->fetchField();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addExtraCacheKeyPart($cache_key_provider, $cache_key_part) {
|
||||
$this->extraCacheKeyParts[$cache_key_provider] = $cache_key_part;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache ID for the route collection cache.
|
||||
*
|
||||
|
@ -455,8 +469,17 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
|
|||
// Include the current language code in the cache identifier as
|
||||
// the language information can be elsewhere than in the path, for example
|
||||
// based on the domain.
|
||||
$language_part = $this->getCurrentLanguageCacheIdPart();
|
||||
return 'route:' . $language_part . ':' . $request->getPathInfo() . ':' . $request->getQueryString();
|
||||
$this->addExtraCacheKeyPart('language', $this->getCurrentLanguageCacheIdPart());
|
||||
|
||||
// Sort the cache key parts by their provider in order to have predictable
|
||||
// cache keys.
|
||||
ksort($this->extraCacheKeyParts);
|
||||
$key_parts = [];
|
||||
foreach ($this->extraCacheKeyParts as $provider => $key_part) {
|
||||
$key_parts[] = '[' . $provider . ']=' . $key_part;
|
||||
}
|
||||
|
||||
return 'route:' . implode(':', $key_parts) . ':' . $request->getPathInfo() . ':' . $request->getQueryString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,7 @@ use Drupal\Core\Url;
|
|||
* JSON:API integration test for the "PathAlias" content entity type.
|
||||
*
|
||||
* @group jsonapi
|
||||
* @group path
|
||||
*/
|
||||
class PathAliasTest extends ResourceTestBase {
|
||||
|
||||
|
@ -86,6 +87,7 @@ class PathAliasTest extends ResourceTestBase {
|
|||
'alias' => '/frontpage1',
|
||||
'path' => '/<front>',
|
||||
'langcode' => 'en',
|
||||
'status' => TRUE,
|
||||
'drupal_internal__id' => 1,
|
||||
'drupal_internal__revision_id' => 1,
|
||||
],
|
||||
|
|
|
@ -63,28 +63,42 @@ class PathItem extends FieldItemBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function postSave($update) {
|
||||
$path_alias_storage = \Drupal::entityTypeManager()->getStorage('path_alias');
|
||||
$entity = $this->getEntity();
|
||||
|
||||
// If specified, rely on the langcode property for the language, so that the
|
||||
// existing language of an alias can be kept. That could for example be
|
||||
// unspecified even if the field/entity has a specific langcode.
|
||||
$alias_langcode = ($this->langcode && $this->pid) ? $this->langcode : $this->getLangcode();
|
||||
|
||||
if (!$update) {
|
||||
if ($this->alias) {
|
||||
$entity = $this->getEntity();
|
||||
if ($path = \Drupal::service('path.alias_storage')->save('/' . $entity->toUrl()->getInternalPath(), $this->alias, $alias_langcode)) {
|
||||
$this->pid = $path['pid'];
|
||||
// If we have an alias, we need to create or update a path alias entity.
|
||||
if ($this->alias) {
|
||||
if (!$update || !$this->pid) {
|
||||
$path_alias = $path_alias_storage->create([
|
||||
'path' => '/' . $entity->toUrl()->getInternalPath(),
|
||||
'alias' => $this->alias,
|
||||
'langcode' => $alias_langcode,
|
||||
]);
|
||||
$path_alias->save();
|
||||
$this->pid = $path_alias->id();
|
||||
}
|
||||
elseif ($this->pid) {
|
||||
$path_alias = $path_alias_storage->load($this->pid);
|
||||
|
||||
if ($this->alias != $path_alias->getAlias()) {
|
||||
$path_alias->setAlias($this->alias);
|
||||
$path_alias->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Delete old alias if user erased it.
|
||||
if ($this->pid && !$this->alias) {
|
||||
\Drupal::service('path.alias_storage')->delete(['pid' => $this->pid]);
|
||||
elseif ($this->pid && !$this->alias) {
|
||||
// Otherwise, delete the old alias if the user erased it.
|
||||
$path_alias = $path_alias_storage->load($this->pid);
|
||||
if ($entity->isDefaultRevision()) {
|
||||
$path_alias_storage->delete([$path_alias]);
|
||||
}
|
||||
// Only save a non-empty alias.
|
||||
elseif ($this->alias) {
|
||||
$entity = $this->getEntity();
|
||||
\Drupal::service('path.alias_storage')->save('/' . $entity->toUrl()->getInternalPath(), $this->alias, $alias_langcode, $this->pid);
|
||||
else {
|
||||
$path_alias_storage->deleteRevision($path_alias->getRevisionID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2395,6 +2395,7 @@ function system_update_8803() {
|
|||
'revision' => 'revision_id',
|
||||
'langcode' => 'langcode',
|
||||
'uuid' => 'uuid',
|
||||
'published' => 'status',
|
||||
],
|
||||
]);
|
||||
|
||||
|
@ -2423,6 +2424,11 @@ function system_update_8803() {
|
|||
->setInternal(TRUE)
|
||||
->setRevisionable(TRUE);
|
||||
|
||||
$field_storage_definitions['status'] = BaseFieldDefinition::create('boolean')
|
||||
->setLabel(new TranslatableMarkup('Published'))
|
||||
->setRevisionable(TRUE)
|
||||
->setDefaultValue(TRUE);
|
||||
|
||||
$field_storage_definitions['path'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(new TranslatableMarkup('System path'))
|
||||
->setDescription(new TranslatableMarkup('The path that this alias belongs to.'))
|
||||
|
@ -2472,9 +2478,9 @@ function system_update_8804(&$sandbox = NULL) {
|
|||
$uuid = \Drupal::service('uuid');
|
||||
|
||||
$base_table_insert = $database->insert('path_alias');
|
||||
$base_table_insert->fields(['id', 'revision_id', 'uuid', 'path', 'alias', 'langcode']);
|
||||
$base_table_insert->fields(['id', 'revision_id', 'uuid', 'path', 'alias', 'langcode', 'status']);
|
||||
$revision_table_insert = $database->insert('path_alias_revision');
|
||||
$revision_table_insert->fields(['id', 'revision_id', 'path', 'alias', 'langcode', 'revision_default']);
|
||||
$revision_table_insert->fields(['id', 'revision_id', 'path', 'alias', 'langcode', 'status', 'revision_default']);
|
||||
foreach ($url_aliases as $url_alias) {
|
||||
$values = [
|
||||
'id' => $url_alias->pid,
|
||||
|
@ -2483,6 +2489,7 @@ function system_update_8804(&$sandbox = NULL) {
|
|||
'path' => $url_alias->source,
|
||||
'alias' => $url_alias->alias,
|
||||
'langcode' => $url_alias->langcode,
|
||||
'status' => 1,
|
||||
];
|
||||
$base_table_insert->values($values);
|
||||
|
||||
|
|
|
@ -38,6 +38,11 @@ class PathAliasToEntityUpdateTest extends UpdatePathTestBase {
|
|||
$query->addField('url_alias', 'source', 'path');
|
||||
$query->addField('url_alias', 'alias');
|
||||
$query->addField('url_alias', 'langcode');
|
||||
|
||||
// Path aliases did not have a 'status' value before the conversion to
|
||||
// entities, but we're adding it here to ensure that the field was installed
|
||||
// and populated correctly.
|
||||
$query->addExpression('1', 'status');
|
||||
$original_records = $query->execute()->fetchAllAssoc('id');
|
||||
|
||||
// drupal-8.filled.standard.php.gz contains one URL alias and
|
||||
|
@ -90,12 +95,12 @@ class PathAliasToEntityUpdateTest extends UpdatePathTestBase {
|
|||
// Check that correct data was written in both the base and the revision
|
||||
// tables.
|
||||
$base_table_records = $database->select('path_alias')
|
||||
->fields('path_alias', ['id', 'path', 'alias', 'langcode'])
|
||||
->fields('path_alias', ['id', 'path', 'alias', 'langcode', 'status'])
|
||||
->execute()->fetchAllAssoc('id');
|
||||
$this->assertEquals($original_records, $base_table_records);
|
||||
|
||||
$revision_table_records = $database->select('path_alias_revision')
|
||||
->fields('path_alias_revision', ['id', 'path', 'alias', 'langcode'])
|
||||
->fields('path_alias_revision', ['id', 'path', 'alias', 'langcode', 'status'])
|
||||
->execute()->fetchAllAssoc('id');
|
||||
$this->assertEquals($original_records, $revision_table_records);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workspaces;
|
||||
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Path\AliasStorage as CoreAliasStorage;
|
||||
|
||||
/**
|
||||
* Provides workspace-specific path alias lookup queries.
|
||||
*/
|
||||
class AliasStorage extends CoreAliasStorage {
|
||||
|
||||
/**
|
||||
* The workspace manager.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceManagerInterface
|
||||
*/
|
||||
protected $workspaceManager;
|
||||
|
||||
/**
|
||||
* AliasStorage constructor.
|
||||
*
|
||||
* @param \Drupal\Core\Database\Connection $connection
|
||||
* A database connection for reading and writing path aliases.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
* @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
|
||||
* The workspace manager service.
|
||||
*/
|
||||
public function __construct(Connection $connection, ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager, WorkspaceManagerInterface $workspace_manager) {
|
||||
parent::__construct($connection, $module_handler, $entity_type_manager);
|
||||
$this->workspaceManager = $workspace_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getBaseQuery() {
|
||||
// Don't alter any queries if we're not in a workspace context.
|
||||
if (!$this->workspaceManager->hasActiveWorkspace()) {
|
||||
return parent::getBaseQuery();
|
||||
}
|
||||
|
||||
$active_workspace = $this->workspaceManager->getActiveWorkspace();
|
||||
|
||||
$query = $this->connection->select('path_alias', 'base_table_2');
|
||||
$wa_join = $query->leftJoin('workspace_association', NULL, "%alias.target_entity_type_id = 'path_alias' AND %alias.target_entity_id = base_table_2.id AND %alias.workspace = :active_workspace_id", [
|
||||
':active_workspace_id' => $active_workspace->id(),
|
||||
]);
|
||||
$query->innerJoin('path_alias_revision', 'base_table', "%alias.revision_id = COALESCE($wa_join.target_entity_revision_id, base_table_2.revision_id)");
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
}
|
|
@ -107,6 +107,11 @@ class EntityTypeInfo implements ContainerInjectionInterface {
|
|||
if (isset($definitions['entity_reference'])) {
|
||||
$definitions['entity_reference']['constraints']['EntityReferenceSupportedNewEntities'] = [];
|
||||
}
|
||||
|
||||
// Allow path aliases to be changed in workspace-specific pending revisions.
|
||||
if (isset($definitions['path'])) {
|
||||
unset($definitions['path']['constraints']['PathAlias']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workspaces\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Path\AliasManagerInterface;
|
||||
use Drupal\Core\Path\CurrentPathStack;
|
||||
use Drupal\Core\Routing\CacheableRouteProviderInterface;
|
||||
use Drupal\Core\Routing\RouteProviderInterface;
|
||||
use Drupal\workspaces\WorkspaceManagerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
* Provides a event subscriber for setting workspace-specific cache keys.
|
||||
*/
|
||||
class WorkspaceRequestSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The alias manager that caches alias lookups based on the request.
|
||||
*
|
||||
* @var \Drupal\Core\Path\AliasManagerInterface
|
||||
*/
|
||||
protected $aliasManager;
|
||||
|
||||
/**
|
||||
* The current path.
|
||||
*
|
||||
* @var \Drupal\Core\Path\CurrentPathStack
|
||||
*/
|
||||
protected $currentPath;
|
||||
|
||||
/**
|
||||
* The route provider to load routes by name.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteProviderInterface
|
||||
*/
|
||||
protected $routeProvider;
|
||||
|
||||
/**
|
||||
* The workspace manager.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceManagerInterface
|
||||
*/
|
||||
protected $workspaceManager;
|
||||
|
||||
/**
|
||||
* Constructs a new WorkspaceRequestSubscriber instance.
|
||||
*
|
||||
* @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
|
||||
* The alias manager.
|
||||
* @param \Drupal\Core\Path\CurrentPathStack $current_path
|
||||
* The current path.
|
||||
* @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
|
||||
* The route provider.
|
||||
* @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
|
||||
* The workspace manager.
|
||||
*/
|
||||
public function __construct(AliasManagerInterface $alias_manager, CurrentPathStack $current_path, RouteProviderInterface $route_provider, WorkspaceManagerInterface $workspace_manager) {
|
||||
$this->aliasManager = $alias_manager;
|
||||
$this->currentPath = $current_path;
|
||||
$this->routeProvider = $route_provider;
|
||||
$this->workspaceManager = $workspace_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache key on the alias manager cache decorator.
|
||||
*
|
||||
* KernelEvents::CONTROLLER is used in order to be executed after routing.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\Event\FilterControllerEvent $event
|
||||
* The Event to process.
|
||||
*/
|
||||
public function onKernelController(FilterControllerEvent $event) {
|
||||
// Set the cache key on the alias manager cache decorator.
|
||||
if ($event->isMasterRequest() && $this->workspaceManager->hasActiveWorkspace()) {
|
||||
$cache_key = $this->workspaceManager->getActiveWorkspace()->id() . ':' . rtrim($this->currentPath->getPath($event->getRequest()), '/');
|
||||
$this->aliasManager->setCacheKey($cache_key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the active workspace as a cache key part to the route provider.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
|
||||
* An event object.
|
||||
*/
|
||||
public function onKernelRequest(GetResponseEvent $event) {
|
||||
if ($this->workspaceManager->hasActiveWorkspace() && $this->routeProvider instanceof CacheableRouteProviderInterface) {
|
||||
$this->routeProvider->addExtraCacheKeyPart('workspace', $this->workspaceManager->getActiveWorkspace()->id());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
// Use a priority of 190 in order to run after the generic core subscriber.
|
||||
// @see \Drupal\Core\EventSubscriber\PathSubscriber::getSubscribedEvents()
|
||||
$events[KernelEvents::CONTROLLER][] = ['onKernelController', 190];
|
||||
|
||||
// Use a priority of 33 in order to run before Symfony's router listener.
|
||||
// @see \Symfony\Component\HttpKernel\EventListener\RouterListener::getSubscribedEvents()
|
||||
$events[KernelEvents::REQUEST][] = ['onKernelRequest', 33];
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -262,6 +262,10 @@ class WorkspaceManager implements WorkspaceManagerInterface {
|
|||
return 'entity.memory_cache:' . $entity_type_id;
|
||||
}, array_keys($this->getSupportedEntityTypes()));
|
||||
$this->entityMemoryCache->invalidateTags($cache_tags_to_invalidate);
|
||||
|
||||
// Clear the static cache for path aliases. We can't inject the path alias
|
||||
// manager service because it would create a circular dependency.
|
||||
\Drupal::service('path.alias_manager')->cacheClear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Drupal\workspaces;
|
|||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceProviderBase;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Defines a service provider for the Workspaces module.
|
||||
|
@ -18,6 +19,11 @@ class WorkspacesServiceProvider extends ServiceProviderBase {
|
|||
$renderer_config = $container->getParameter('renderer.config');
|
||||
$renderer_config['required_cache_contexts'][] = 'workspace';
|
||||
$container->setParameter('renderer.config', $renderer_config);
|
||||
|
||||
// Replace the class of the 'path.alias_storage' service.
|
||||
$container->getDefinition('path.alias_storage')
|
||||
->setClass(AliasStorage::class)
|
||||
->addArgument(new Reference('workspaces.manager'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,309 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workspaces\Functional;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\workspaces\Entity\Workspace;
|
||||
|
||||
/**
|
||||
* Tests path aliases with workspaces.
|
||||
*
|
||||
* @group path
|
||||
* @group workspaces
|
||||
*/
|
||||
class PathWorkspacesTest extends BrowserTestBase {
|
||||
|
||||
use WorkspaceTestUtilities;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'content_translation', 'node', 'path', 'workspaces'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
ConfigurableLanguage::createFromLangcode('ro')->save();
|
||||
$this->rebuildContainer();
|
||||
|
||||
// Create a content type.
|
||||
$this->drupalCreateContentType([
|
||||
'name' => 'article',
|
||||
'type' => 'article',
|
||||
]);
|
||||
|
||||
$this->drupalLogin($this->rootUser);
|
||||
|
||||
// Enable URL language detection and selection.
|
||||
$edit = ['language_interface[enabled][language-url]' => 1];
|
||||
$this->drupalPostForm('admin/config/regional/language/detection', $edit, 'Save settings');
|
||||
|
||||
// Enable translation for article node.
|
||||
$edit = [
|
||||
'entity_types[node]' => 1,
|
||||
'settings[node][article][translatable]' => 1,
|
||||
'settings[node][article][fields][path]' => 1,
|
||||
'settings[node][article][fields][body]' => 1,
|
||||
'settings[node][article][settings][language][language_alterable]' => 1,
|
||||
];
|
||||
$this->drupalPostForm('admin/config/regional/content-language', $edit, 'Save configuration');
|
||||
\Drupal::entityTypeManager()->clearCachedDefinitions();
|
||||
|
||||
$this->setupWorkspaceSwitcherBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests path aliases with workspaces.
|
||||
*/
|
||||
public function testPathAliases() {
|
||||
// Create a published node in Live, without an alias.
|
||||
$node = $this->drupalCreateNode([
|
||||
'type' => 'article',
|
||||
'status' => TRUE,
|
||||
]);
|
||||
|
||||
// Switch to Stage and create an alias for the node.
|
||||
$stage = Workspace::load('stage');
|
||||
$this->switchToWorkspace($stage);
|
||||
|
||||
$edit = [
|
||||
'path[0][alias]' => '/' . $this->randomMachineName(),
|
||||
];
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, 'Save');
|
||||
|
||||
// Check that the node can be accessed in Stage with the given alias.
|
||||
$path = $edit['path[0][alias]'];
|
||||
$this->assertAccessiblePaths([$path]);
|
||||
|
||||
// Check that the 'preload-paths' cache includes the active workspace ID in
|
||||
// the cache key.
|
||||
$this->assertNotEmpty(\Drupal::cache('data')->get('preload-paths:stage:/node/1'));
|
||||
$this->assertFalse(\Drupal::cache('data')->get('preload-paths:/node/1'));
|
||||
|
||||
// Check that the alias can not be accessed in Live.
|
||||
$this->switchToLive();
|
||||
$this->assertNotAccessiblePaths([$path]);
|
||||
$this->assertFalse(\Drupal::cache('data')->get('preload-paths:/node/1'));
|
||||
|
||||
// Publish the workspace and check that the alias can be accessed in Live.
|
||||
$stage->publish();
|
||||
$this->assertAccessiblePaths([$path]);
|
||||
$this->assertNotEmpty(\Drupal::cache('data')->get('preload-paths:/node/1'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests path aliases with workspaces and user switching.
|
||||
*/
|
||||
public function testPathAliasesUserSwitch() {
|
||||
// Create a published node in Live, without an alias.
|
||||
$node = $this->drupalCreateNode([
|
||||
'type' => 'article',
|
||||
'status' => TRUE,
|
||||
]);
|
||||
|
||||
// Switch to Stage and create an alias for the node.
|
||||
$stage = Workspace::load('stage');
|
||||
$this->switchToWorkspace($stage);
|
||||
|
||||
$edit = [
|
||||
'path[0][alias]' => '/' . $this->randomMachineName(),
|
||||
];
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, 'Save');
|
||||
|
||||
// Check that the node can be accessed in Stage with the given alias.
|
||||
$path = $edit['path[0][alias]'];
|
||||
$this->assertAccessiblePaths([$path]);
|
||||
|
||||
// Check that the 'preload-paths' cache includes the active workspace ID in
|
||||
// the cache key.
|
||||
$this->assertNotEmpty(\Drupal::cache('data')->get('preload-paths:stage:/node/1'));
|
||||
$this->assertFalse(\Drupal::cache('data')->get('preload-paths:/node/1'));
|
||||
|
||||
// Check that the alias can not be accessed in Live, by logging out without
|
||||
// an explicit switch.
|
||||
$this->drupalLogout();
|
||||
$this->assertNotAccessiblePaths([$path]);
|
||||
$this->assertFalse(\Drupal::cache('data')->get('preload-paths:/node/1'));
|
||||
|
||||
// Publish the workspace and check that the alias can be accessed in Live.
|
||||
$this->drupalLogin($this->rootUser);
|
||||
$stage->publish();
|
||||
$this->drupalLogout();
|
||||
$this->assertAccessiblePaths([$path]);
|
||||
$this->assertNotEmpty(\Drupal::cache('data')->get('preload-paths:/node/1'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests path aliases with workspaces for translatable nodes.
|
||||
*/
|
||||
public function testPathAliasesWithTranslation() {
|
||||
$stage = Workspace::load('stage');
|
||||
|
||||
// Create one node with a random alias.
|
||||
$default_node = $this->drupalCreateNode([
|
||||
'type' => 'article',
|
||||
'langcode' => 'en',
|
||||
'status' => TRUE,
|
||||
'path' => '/' . $this->randomMachineName(),
|
||||
]);
|
||||
|
||||
// Add published translation with another alias.
|
||||
$this->drupalGet('node/' . $default_node->id());
|
||||
$this->drupalGet('node/' . $default_node->id() . '/translations');
|
||||
$this->clickLink('Add');
|
||||
$edit_translation = [
|
||||
'body[0][value]' => $this->randomMachineName(),
|
||||
'status[value]' => TRUE,
|
||||
'path[0][alias]' => '/' . $this->randomMachineName(),
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit_translation, 'Save (this translation)');
|
||||
// Confirm that the alias works.
|
||||
$this->drupalGet('ro' . $edit_translation['path[0][alias]']);
|
||||
$this->assertSession()->pageTextContains($edit_translation['body[0][value]']);
|
||||
|
||||
$default_path = $default_node->path->alias;
|
||||
$translation_path = 'ro' . $edit_translation['path[0][alias]'];
|
||||
|
||||
$this->assertAccessiblePaths([$default_path, $translation_path]);
|
||||
|
||||
$this->switchToWorkspace($stage);
|
||||
|
||||
$this->assertAccessiblePaths([$default_path, $translation_path]);
|
||||
|
||||
// Create a workspace-specific revision for the translation with a new path
|
||||
// alias.
|
||||
$edit_new_translation_draft_with_alias = [
|
||||
'path[0][alias]' => '/' . $this->randomMachineName(),
|
||||
];
|
||||
$this->drupalPostForm('ro/node/' . $default_node->id() . '/edit', $edit_new_translation_draft_with_alias, 'Save (this translation)');
|
||||
$stage_translation_path = 'ro' . $edit_new_translation_draft_with_alias['path[0][alias]'];
|
||||
|
||||
// The new alias of the translation should be available in Stage, but not
|
||||
// available in Live.
|
||||
$this->assertAccessiblePaths([$default_path, $stage_translation_path]);
|
||||
|
||||
// Check that the previous (Live) path alias no longer works.
|
||||
$this->assertNotAccessiblePaths([$translation_path]);
|
||||
|
||||
// Switch out of Stage and check that the initial path aliases still work.
|
||||
$this->switchToLive();
|
||||
$this->assertAccessiblePaths([$default_path, $translation_path]);
|
||||
$this->assertNotAccessiblePaths([$stage_translation_path]);
|
||||
|
||||
// Switch back to Stage.
|
||||
$this->switchToWorkspace($stage);
|
||||
|
||||
// Create new workspace-specific revision for translation without changing
|
||||
// the path alias.
|
||||
$edit_new_translation_draft = [
|
||||
'body[0][value]' => $this->randomMachineName(),
|
||||
];
|
||||
$this->drupalPostForm('ro/node/' . $default_node->id() . '/edit', $edit_new_translation_draft, t('Save (this translation)'));
|
||||
// Confirm that the new draft revision was created.
|
||||
$this->assertSession()->pageTextContains($edit_new_translation_draft['body[0][value]']);
|
||||
|
||||
// Switch out of Stage and check that the initial path aliases still work.
|
||||
$this->switchToLive();
|
||||
$this->assertAccessiblePaths([$default_path, $translation_path]);
|
||||
$this->assertNotAccessiblePaths([$stage_translation_path]);
|
||||
|
||||
// Switch back to Stage.
|
||||
$this->switchToWorkspace($stage);
|
||||
$this->assertAccessiblePaths([$default_path, $stage_translation_path]);
|
||||
$this->assertNotAccessiblePaths([$translation_path]);
|
||||
|
||||
// Create a new workspace-specific revision for translation with path alias
|
||||
// from the original language's default revision.
|
||||
$edit_new_translation_draft_with_defaults_alias = [
|
||||
'path[0][alias]' => $default_node->path->alias,
|
||||
];
|
||||
$this->drupalPostForm('ro/node/' . $default_node->id() . '/edit', $edit_new_translation_draft_with_defaults_alias, 'Save (this translation)');
|
||||
|
||||
// Switch out of Stage and check that the initial path aliases still work.
|
||||
$this->switchToLive();
|
||||
$this->assertAccessiblePaths([$default_path, $translation_path]);
|
||||
$this->assertNotAccessiblePaths([$stage_translation_path]);
|
||||
|
||||
// Check that only one path alias (the original one) is available in Stage.
|
||||
$this->switchToWorkspace($stage);
|
||||
$this->assertAccessiblePaths([$default_path]);
|
||||
$this->assertNotAccessiblePaths([$translation_path, $stage_translation_path]);
|
||||
|
||||
// Create new workspace-specific revision for translation with a deleted
|
||||
// (empty) path alias.
|
||||
$edit_new_translation_draft_empty_alias = [
|
||||
'body[0][value]' => $this->randomMachineName(),
|
||||
'path[0][alias]' => '',
|
||||
];
|
||||
$this->drupalPostForm('ro/node/' . $default_node->id() . '/edit', $edit_new_translation_draft_empty_alias, 'Save (this translation)');
|
||||
|
||||
// Check that only one path alias (the original one) is available now.
|
||||
$this->switchToLive();
|
||||
$this->assertAccessiblePaths([$default_path, $translation_path]);
|
||||
$this->assertNotAccessiblePaths([$stage_translation_path]);
|
||||
|
||||
$this->switchToWorkspace($stage);
|
||||
$this->assertAccessiblePaths([$default_path]);
|
||||
$this->assertNotAccessiblePaths([$translation_path, $stage_translation_path]);
|
||||
|
||||
// Create a new workspace-specific revision for the translation with a new
|
||||
// path alias.
|
||||
$edit_new_translation = [
|
||||
'body[0][value]' => $this->randomMachineName(),
|
||||
'path[0][alias]' => '/' . $this->randomMachineName(),
|
||||
];
|
||||
$this->drupalPostForm('ro/node/' . $default_node->id() . '/edit', $edit_new_translation, 'Save (this translation)');
|
||||
|
||||
// Confirm that the new revision was created.
|
||||
$this->assertSession()->pageTextContains($edit_new_translation['body[0][value]']);
|
||||
$this->assertSession()->addressEquals('ro' . $edit_new_translation['path[0][alias]']);
|
||||
|
||||
// Check that only the new path alias of the translation can be accessed.
|
||||
$new_stage_translation_path = 'ro' . $edit_new_translation['path[0][alias]'];
|
||||
$this->assertAccessiblePaths([$default_path, $new_stage_translation_path]);
|
||||
$this->assertNotAccessiblePaths([$stage_translation_path]);
|
||||
|
||||
// Switch out of Stage and check that none of the workspace-specific path
|
||||
// aliases can be accessed.
|
||||
$this->switchToLive();
|
||||
$this->assertAccessiblePaths([$default_path, $translation_path]);
|
||||
$this->assertNotAccessiblePaths([$stage_translation_path, $new_stage_translation_path]);
|
||||
|
||||
// Publish Stage and check that its path alias for the translation can be
|
||||
// accessed.
|
||||
$stage->publish();
|
||||
$this->assertAccessiblePaths([$default_path, $new_stage_translation_path]);
|
||||
$this->assertNotAccessiblePaths([$stage_translation_path]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper callback to verify paths are responding with status 200.
|
||||
*
|
||||
* @param string[] $paths
|
||||
* An array of paths to check for.
|
||||
*/
|
||||
protected function assertAccessiblePaths(array $paths) {
|
||||
foreach ($paths as $path) {
|
||||
$this->drupalGet($path);
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper callback to verify paths are responding with status 404.
|
||||
*
|
||||
* @param string[] $paths
|
||||
* An array of paths to check for.
|
||||
*/
|
||||
protected function assertNotAccessiblePaths(array $paths) {
|
||||
foreach ($paths as $path) {
|
||||
$this->drupalGet($path);
|
||||
$this->assertSession()->statusCodeEquals(404);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workspaces\Unit;
|
||||
|
||||
use Drupal\Core\Path\AliasManagerInterface;
|
||||
use Drupal\Core\Path\CurrentPathStack;
|
||||
use Drupal\Core\Routing\CacheableRouteProviderInterface;
|
||||
use Drupal\Core\Routing\RouteProviderInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\workspaces\EventSubscriber\WorkspaceRequestSubscriber;
|
||||
use Drupal\workspaces\WorkspaceInterface;
|
||||
use Drupal\workspaces\WorkspaceManagerInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\workspaces\EventSubscriber\WorkspaceRequestSubscriber
|
||||
*
|
||||
* @group workspace
|
||||
*/
|
||||
class WorkspaceRequestSubscriberTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Path\AliasManagerInterface
|
||||
*/
|
||||
protected $aliasManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Path\CurrentPathStack
|
||||
*/
|
||||
protected $currentPath;
|
||||
|
||||
/**
|
||||
* @var \Drupal\workspaces\WorkspaceManagerInterface
|
||||
*/
|
||||
protected $workspaceManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->aliasManager = $this->prophesize(AliasManagerInterface::class)->reveal();
|
||||
$this->currentPath = $this->prophesize(CurrentPathStack::class)->reveal();
|
||||
$this->workspaceManager = $this->prophesize(WorkspaceManagerInterface::class);
|
||||
|
||||
$active_workspace = $this->prophesize(WorkspaceInterface::class);
|
||||
$active_workspace->id()->willReturn('test');
|
||||
$this->workspaceManager->getActiveWorkspace()->willReturn($active_workspace->reveal());
|
||||
$this->workspaceManager->hasActiveWorkspace()->willReturn(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::onKernelRequest
|
||||
*/
|
||||
public function testOnKernelRequestWithCacheableRouteProvider() {
|
||||
$route_provider = $this->prophesize(CacheableRouteProviderInterface::class);
|
||||
$route_provider->addExtraCacheKeyPart('workspace', 'test')->shouldBeCalled();
|
||||
|
||||
// Check that WorkspaceRequestSubscriber::onKernelRequest() calls
|
||||
// addExtraCacheKeyPart() on a route provider that implements
|
||||
// CacheableRouteProviderInterface.
|
||||
$workspace_request_subscriber = new WorkspaceRequestSubscriber($this->aliasManager, $this->currentPath, $route_provider->reveal(), $this->workspaceManager->reveal());
|
||||
$event = $this->prophesize(GetResponseEvent::class)->reveal();
|
||||
$this->assertNull($workspace_request_subscriber->onKernelRequest($event));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::onKernelRequest
|
||||
*/
|
||||
public function testOnKernelRequestWithoutCacheableRouteProvider() {
|
||||
$route_provider = $this->prophesize(RouteProviderInterface::class);
|
||||
|
||||
// Check that WorkspaceRequestSubscriber::onKernelRequest() doesn't call
|
||||
// addExtraCacheKeyPart() on a route provider that does not implement
|
||||
// CacheableRouteProviderInterface.
|
||||
$workspace_request_subscriber = new WorkspaceRequestSubscriber($this->aliasManager, $this->currentPath, $route_provider->reveal(), $this->workspaceManager->reveal());
|
||||
$event = $this->prophesize(GetResponseEvent::class)->reveal();
|
||||
$this->assertNull($workspace_request_subscriber->onKernelRequest($event));
|
||||
}
|
||||
|
||||
}
|
|
@ -35,6 +35,11 @@ services:
|
|||
arguments: ['@entity.definition_update_manager', '@entity.last_installed_schema.repository', '@workspaces.manager']
|
||||
tags:
|
||||
- { name: 'event_subscriber' }
|
||||
workspaces.workspace_subscriber:
|
||||
class: Drupal\workspaces\EventSubscriber\WorkspaceRequestSubscriber
|
||||
arguments: ['@path.alias_manager', '@path.current', '@router.route_provider', '@workspaces.manager']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
|
||||
cache_context.workspace:
|
||||
class: Drupal\workspaces\WorkspaceCacheContext
|
||||
|
|
|
@ -83,6 +83,11 @@ abstract class PathAliasResourceTestBase extends EntityResourceTestBase {
|
|||
'value' => '/frontpage1',
|
||||
],
|
||||
],
|
||||
'status' => [
|
||||
[
|
||||
'value' => TRUE,
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
[
|
||||
'value' => $this->entity->uuid(),
|
||||
|
|
|
@ -546,7 +546,7 @@ class RouteProviderTest extends KernelTestBase {
|
|||
$request = Request::create($path, 'GET');
|
||||
$provider->getRouteCollectionForRequest($request);
|
||||
|
||||
$cache = $this->cache->get('route:en:/path/add/one:');
|
||||
$cache = $this->cache->get('route:[language]=en:/path/add/one:');
|
||||
$this->assertEqual('/path/add/one', $cache->data['path']);
|
||||
$this->assertEqual([], $cache->data['query']);
|
||||
$this->assertEqual(3, count($cache->data['routes']));
|
||||
|
@ -556,7 +556,7 @@ class RouteProviderTest extends KernelTestBase {
|
|||
$request = Request::create($path, 'GET');
|
||||
$provider->getRouteCollectionForRequest($request);
|
||||
|
||||
$cache = $this->cache->get('route:en:/path/add/one:foo=bar');
|
||||
$cache = $this->cache->get('route:[language]=en:/path/add/one:foo=bar');
|
||||
$this->assertEqual('/path/add/one', $cache->data['path']);
|
||||
$this->assertEqual(['foo' => 'bar'], $cache->data['query']);
|
||||
$this->assertEqual(3, count($cache->data['routes']));
|
||||
|
@ -566,7 +566,7 @@ class RouteProviderTest extends KernelTestBase {
|
|||
$request = Request::create($path, 'GET');
|
||||
$provider->getRouteCollectionForRequest($request);
|
||||
|
||||
$cache = $this->cache->get('route:en:/path/1/one:');
|
||||
$cache = $this->cache->get('route:[language]=en:/path/1/one:');
|
||||
$this->assertEqual('/path/1/one', $cache->data['path']);
|
||||
$this->assertEqual([], $cache->data['query']);
|
||||
$this->assertEqual(2, count($cache->data['routes']));
|
||||
|
@ -583,7 +583,7 @@ class RouteProviderTest extends KernelTestBase {
|
|||
$request = Request::create($path, 'GET');
|
||||
$provider->getRouteCollectionForRequest($request);
|
||||
|
||||
$cache = $this->cache->get('route:en:/path/add-one:');
|
||||
$cache = $this->cache->get('route:[language]=en:/path/add-one:');
|
||||
$this->assertEqual('/path/add/one', $cache->data['path']);
|
||||
$this->assertEqual([], $cache->data['query']);
|
||||
$this->assertEqual(3, count($cache->data['routes']));
|
||||
|
@ -598,7 +598,7 @@ class RouteProviderTest extends KernelTestBase {
|
|||
$request = Request::create($path, 'GET');
|
||||
$provider->getRouteCollectionForRequest($request);
|
||||
|
||||
$cache = $this->cache->get('route:gsw-berne:/path/add-one:');
|
||||
$cache = $this->cache->get('route:[language]=gsw-berne:/path/add-one:');
|
||||
$this->assertEquals('/path/add/one', $cache->data['path']);
|
||||
$this->assertEquals([], $cache->data['query']);
|
||||
$this->assertEquals(3, count($cache->data['routes']));
|
||||
|
|
Loading…
Reference in New Issue