diff --git a/core/modules/hal/hal.info.yml b/core/modules/hal/hal.info.yml index 4cf0c7ead66c99ed65cc4dceabd17f3ad74b356c..2d87eff9d290ee87742dec422e244c523c501ccc 100644 --- a/core/modules/hal/hal.info.yml +++ b/core/modules/hal/hal.info.yml @@ -5,5 +5,4 @@ package: Web services version: VERSION core: 8.x dependencies: - - rest - serialization diff --git a/core/modules/hal/hal.services.yml b/core/modules/hal/hal.services.yml index 7e40df0d5b8c56ccff4f14eb61f7ed312c5f641d..c8c9a2cd47f447d00dc5128bb8dc4accc86c4cd1 100644 --- a/core/modules/hal/hal.services.yml +++ b/core/modules/hal/hal.services.yml @@ -1,7 +1,7 @@ services: serializer.normalizer.entity_reference_item.hal: class: Drupal\hal\Normalizer\EntityReferenceItemNormalizer - arguments: ['@rest.link_manager', '@serializer.entity_resolver'] + arguments: ['@serialization.link_manager', '@serializer.entity_resolver'] tags: - { name: normalizer, priority: 10 } serializer.normalizer.field_item.hal: @@ -16,10 +16,10 @@ services: class: Drupal\hal\Normalizer\FileEntityNormalizer tags: - { name: normalizer, priority: 20 } - arguments: ['@entity.manager', '@http_client', '@rest.link_manager', '@module_handler'] + arguments: ['@entity.manager', '@http_client', '@serialization.link_manager', '@module_handler'] serializer.normalizer.entity.hal: class: Drupal\hal\Normalizer\ContentEntityNormalizer - arguments: ['@rest.link_manager', '@entity.manager', '@module_handler'] + arguments: ['@serialization.link_manager', '@entity.manager', '@module_handler'] tags: - { name: normalizer, priority: 10 } serializer.encoder.hal: diff --git a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php index fce3ddca401743b11d32f933efc1de9f608f9395..88eb36cdcd303be8585f7fd0b78969821b9b7f8a 100644 --- a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php +++ b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php @@ -6,7 +6,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\rest\LinkManager\LinkManagerInterface; +use Drupal\serialization\LinkManager\LinkManagerInterface; use Drupal\serialization\Normalizer\FieldableEntityNormalizerTrait; use Symfony\Component\Serializer\Exception\UnexpectedValueException; @@ -27,7 +27,7 @@ class ContentEntityNormalizer extends NormalizerBase { /** * The hypermedia link manager. * - * @var \Drupal\rest\LinkManager\LinkManagerInterface + * @var \Drupal\serialization\LinkManager\LinkManagerInterface */ protected $linkManager; @@ -41,7 +41,7 @@ class ContentEntityNormalizer extends NormalizerBase { /** * Constructs an ContentEntityNormalizer object. * - * @param \Drupal\rest\LinkManager\LinkManagerInterface $link_manager + * @param \Drupal\serialization\LinkManager\LinkManagerInterface $link_manager * The hypermedia link manager. */ public function __construct(LinkManagerInterface $link_manager, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler) { diff --git a/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php b/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php index 6c73256e1470cb1964acef8c52f21a6452987d41..4dea76c917952108a5050d13bb414d1349a3dbf9 100644 --- a/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php +++ b/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php @@ -3,7 +3,7 @@ namespace Drupal\hal\Normalizer; use Drupal\Core\Entity\FieldableEntityInterface; -use Drupal\rest\LinkManager\LinkManagerInterface; +use Drupal\serialization\LinkManager\LinkManagerInterface; use Drupal\serialization\EntityResolver\EntityResolverInterface; use Drupal\serialization\EntityResolver\UuidReferenceInterface; @@ -22,7 +22,7 @@ class EntityReferenceItemNormalizer extends FieldItemNormalizer implements UuidR /** * The hypermedia link manager. * - * @var \Drupal\rest\LinkManager\LinkManagerInterface + * @var \Drupal\serialization\LinkManager\LinkManagerInterface */ protected $linkManager; @@ -36,7 +36,7 @@ class EntityReferenceItemNormalizer extends FieldItemNormalizer implements UuidR /** * Constructs an EntityReferenceItemNormalizer object. * - * @param \Drupal\rest\LinkManager\LinkManagerInterface $link_manager + * @param \Drupal\serialization\LinkManager\LinkManagerInterface $link_manager * The hypermedia link manager. * @param \Drupal\serialization\EntityResolver\EntityResolverInterface $entity_Resolver * The entity resolver. diff --git a/core/modules/hal/src/Normalizer/FileEntityNormalizer.php b/core/modules/hal/src/Normalizer/FileEntityNormalizer.php index 46c609451dfb2d70162b755aa5de7762fceb4780..c7c686fde8313354ebc20d8c2cc5b8367ec66206 100644 --- a/core/modules/hal/src/Normalizer/FileEntityNormalizer.php +++ b/core/modules/hal/src/Normalizer/FileEntityNormalizer.php @@ -4,7 +4,7 @@ use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\rest\LinkManager\LinkManagerInterface; +use Drupal\serialization\LinkManager\LinkManagerInterface; use GuzzleHttp\ClientInterface; /** @@ -33,7 +33,7 @@ class FileEntityNormalizer extends ContentEntityNormalizer { * The entity manager. * @param \GuzzleHttp\ClientInterface $http_client * The HTTP Client. - * @param \Drupal\rest\LinkManager\LinkManagerInterface $link_manager + * @param \Drupal\serialization\LinkManager\LinkManagerInterface $link_manager * The hypermedia link manager. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. diff --git a/core/modules/hal/tests/src/Kernel/FileNormalizeTest.php b/core/modules/hal/tests/src/Kernel/FileNormalizeTest.php index 42d7a36a6f54c31edc5d068eb02137759a8be062..cacef30fff6624675b3204e6a9df5e0cebcdd557 100644 --- a/core/modules/hal/tests/src/Kernel/FileNormalizeTest.php +++ b/core/modules/hal/tests/src/Kernel/FileNormalizeTest.php @@ -7,9 +7,9 @@ use Drupal\hal\Encoder\JsonEncoder; use Drupal\hal\Normalizer\FieldItemNormalizer; use Drupal\hal\Normalizer\FileEntityNormalizer; -use Drupal\rest\LinkManager\LinkManager; -use Drupal\rest\LinkManager\RelationLinkManager; -use Drupal\rest\LinkManager\TypeLinkManager; +use Drupal\serialization\LinkManager\LinkManager; +use Drupal\serialization\LinkManager\RelationLinkManager; +use Drupal\serialization\LinkManager\TypeLinkManager; use Symfony\Component\Serializer\Serializer; diff --git a/core/modules/hal/tests/src/Kernel/NormalizerTestBase.php b/core/modules/hal/tests/src/Kernel/NormalizerTestBase.php index 58674763c2ca2ccecead3453063c69fe65d4c220..1fc5e4c0c69c9c19fd6ce97066ce46bea8b10ff5 100644 --- a/core/modules/hal/tests/src/Kernel/NormalizerTestBase.php +++ b/core/modules/hal/tests/src/Kernel/NormalizerTestBase.php @@ -10,9 +10,9 @@ use Drupal\hal\Normalizer\FieldItemNormalizer; use Drupal\hal\Normalizer\FieldNormalizer; use Drupal\language\Entity\ConfigurableLanguage; -use Drupal\rest\LinkManager\LinkManager; -use Drupal\rest\LinkManager\RelationLinkManager; -use Drupal\rest\LinkManager\TypeLinkManager; +use Drupal\serialization\LinkManager\LinkManager; +use Drupal\serialization\LinkManager\RelationLinkManager; +use Drupal\serialization\LinkManager\TypeLinkManager; use Drupal\serialization\EntityResolver\ChainEntityResolver; use Drupal\serialization\EntityResolver\TargetIdResolver; use Drupal\serialization\EntityResolver\UuidResolver; @@ -30,7 +30,7 @@ abstract class NormalizerTestBase extends KernelTestBase { * * @var array */ - public static $modules = ['entity_test', 'field', 'hal', 'language', 'rest', 'serialization', 'system', 'text', 'user', 'filter']; + public static $modules = ['entity_test', 'field', 'hal', 'language', 'serialization', 'system', 'text', 'user', 'filter']; /** * The mock serializer. diff --git a/core/modules/rest/config/install/rest.settings.yml b/core/modules/rest/config/install/rest.settings.yml index eb3da2df4ca6d77149ab67513f4e7e7de6b7e9d1..8f70c6997d154aa81e92d2b692b24a63dcd07146 100644 --- a/core/modules/rest/config/install/rest.settings.yml +++ b/core/modules/rest/config/install/rest.settings.yml @@ -1,7 +1,3 @@ -# Set the domain for REST type and relation links. -# If left blank, the site's domain will be used. -link_domain: ~ - # Before Drupal 8.2, EntityResource used permissions as well as the entity # access system for access checking. This was confusing, and it only did this # for historical reasons. New Drupal installations opt out from this by default diff --git a/core/modules/rest/config/schema/rest.schema.yml b/core/modules/rest/config/schema/rest.schema.yml index 2c255ab88cd4f810fc973995a11a439f01088622..49b4b2d942630c98fd3aa5dda4e41b843f0c7b55 100644 --- a/core/modules/rest/config/schema/rest.schema.yml +++ b/core/modules/rest/config/schema/rest.schema.yml @@ -3,6 +3,7 @@ rest.settings: type: config_object label: 'REST settings' mapping: + # @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. link_domain: type: string label: 'Domain of the relation' diff --git a/core/modules/rest/rest.api.php b/core/modules/rest/rest.api.php index fb8993d26808f1bc03daaa68e60f2ae47de16283..9bf6921c09bf93ed78edce5513179a5a9a54eab2 100644 --- a/core/modules/rest/rest.api.php +++ b/core/modules/rest/rest.api.php @@ -31,6 +31,9 @@ function hook_rest_resource_alter(&$definitions) { /** * Alter the REST type URI. * + * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. Use + * hook_serialization_type_uri_alter() instead. This exists solely for BC. + * * Modules may wish to alter the type URI generated for a resource based on the * context of the serializer/normalizer operation. * @@ -46,7 +49,7 @@ function hook_rest_resource_alter(&$definitions) { */ function hook_rest_type_uri_alter(&$uri, $context = array()) { if ($context['mymodule'] == TRUE) { - $base = \Drupal::config('rest.settings')->get('link_domain'); + $base = \Drupal::config('serialization.settings')->get('link_domain'); $uri = str_replace($base, 'http://mymodule.domain', $uri); } } @@ -55,6 +58,9 @@ function hook_rest_type_uri_alter(&$uri, $context = array()) { /** * Alter the REST relation URI. * + * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. Use + * hook_serialization_relation_uri_alter() instead. This exists solely for BC. + * * Modules may wish to alter the relation URI generated for a resource based on * the context of the serializer/normalizer operation. * @@ -70,7 +76,7 @@ function hook_rest_type_uri_alter(&$uri, $context = array()) { */ function hook_rest_relation_uri_alter(&$uri, $context = array()) { if ($context['mymodule'] == TRUE) { - $base = \Drupal::config('rest.settings')->get('link_domain'); + $base = \Drupal::config('serialization.settings')->get('link_domain'); $uri = str_replace($base, 'http://mymodule.domain', $uri); } } diff --git a/core/modules/rest/rest.services.yml b/core/modules/rest/rest.services.yml index 81eb45108944d19eae544ef8b76a2d98d4e3bd09..2def91e992d17f5c962d854682a39bd2c30d406c 100644 --- a/core/modules/rest/rest.services.yml +++ b/core/modules/rest/rest.services.yml @@ -11,15 +11,22 @@ services: # @todo Remove this service in Drupal 9.0.0. access_check.rest.csrf: alias: access_check.header.csrf + # Link managers. + # @deprecated in Drupal 8.3.x and will be removed before 9.0.0. Use + # serialization.link_manager instead. rest.link_manager: + parent: serialization.link_manager class: Drupal\rest\LinkManager\LinkManager - arguments: ['@rest.link_manager.type', '@rest.link_manager.relation'] + # @deprecated in Drupal 8.3.x and will be removed before 9.0.0. Use + # serialization.link_manager.type instead. rest.link_manager.type: + parent: serialization.link_manager.type class: Drupal\rest\LinkManager\TypeLinkManager - arguments: ['@cache.default', '@module_handler', '@config.factory', '@request_stack', '@entity_type.bundle.info'] + # @deprecated in Drupal 8.3.x and will be removed before 9.0.0. Use + # serialization.link_manager.relation instead. rest.link_manager.relation: + parent: serialization.link_manager.relation class: Drupal\rest\LinkManager\RelationLinkManager - arguments: ['@cache.default', '@entity.manager', '@module_handler', '@config.factory', '@request_stack'] rest.resource_routes: class: Drupal\rest\Routing\ResourceRoutes arguments: ['@plugin.manager.rest', '@entity_type.manager', '@logger.channel.rest'] diff --git a/core/modules/rest/src/LinkManager/ConfigurableLinkManagerInterface.php b/core/modules/rest/src/LinkManager/ConfigurableLinkManagerInterface.php index c2eb1f136b12592ab9c040d838aa3029f8882532..c73f5f0aef2b6b8f74bab23be7a3924b8d64c012 100644 --- a/core/modules/rest/src/LinkManager/ConfigurableLinkManagerInterface.php +++ b/core/modules/rest/src/LinkManager/ConfigurableLinkManagerInterface.php @@ -2,19 +2,10 @@ namespace Drupal\rest\LinkManager; +use Drupal\serialization\LinkManager\ConfigurableLinkManagerInterface as MovedConfigurableLinkManagerInterface; + /** - * Defines an interface for a link manager with a configurable domain. + * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has + * been moved to the serialization module. This exists solely for BC. */ -interface ConfigurableLinkManagerInterface { - - /** - * Sets the link domain used in constructing link URIs. - * - * @param string $domain - * The link domain to use for constructing link URIs. - * - * @return $this - */ - public function setLinkDomain($domain); - -} +interface ConfigurableLinkManagerInterface extends MovedConfigurableLinkManagerInterface {} diff --git a/core/modules/rest/src/LinkManager/LinkManager.php b/core/modules/rest/src/LinkManager/LinkManager.php index bd94a6580eed06217b757d2ddf8fbdca618ebde7..1b450c50a6c06c60c1184a9716fafc86bf805b26 100644 --- a/core/modules/rest/src/LinkManager/LinkManager.php +++ b/core/modules/rest/src/LinkManager/LinkManager.php @@ -2,70 +2,10 @@ namespace Drupal\rest\LinkManager; -class LinkManager implements LinkManagerInterface { +use Drupal\serialization\LinkManager\LinkManager as MovedLinkManager; - /** - * The type link manager. - * - * @var \Drupal\rest\LinkManager\TypeLinkManagerInterface - */ - protected $typeLinkManager; - - /** - * The relation link manager. - * - * @var \Drupal\rest\LinkManager\RelationLinkManagerInterface - */ - protected $relationLinkManager; - - /** - * Constructor. - * - * @param \Drupal\rest\LinkManager\TypeLinkManagerInterface $type_link_manager - * Manager for handling bundle URIs. - * @param \Drupal\rest\LinkManager\RelationLinkManagerInterface $relation_link_manager - * Manager for handling bundle URIs. - */ - public function __construct(TypeLinkManagerInterface $type_link_manager, RelationLinkManagerInterface $relation_link_manager) { - $this->typeLinkManager = $type_link_manager; - $this->relationLinkManager = $relation_link_manager; - } - - /** - * {@inheritdoc} - */ - public function getTypeUri($entity_type, $bundle, $context = array()) { - return $this->typeLinkManager->getTypeUri($entity_type, $bundle, $context); - } - - /** - * {@inheritdoc} - */ - public function getTypeInternalIds($type_uri, $context = array()) { - return $this->typeLinkManager->getTypeInternalIds($type_uri, $context); - } - - /** - * {@inheritdoc} - */ - public function getRelationUri($entity_type, $bundle, $field_name, $context = array()) { - return $this->relationLinkManager->getRelationUri($entity_type, $bundle, $field_name, $context); - } - - /** - * {@inheritdoc} - */ - public function getRelationInternalIds($relation_uri) { - return $this->relationLinkManager->getRelationInternalIds($relation_uri); - } - - /** - * {@inheritdoc} - */ - public function setLinkDomain($domain) { - $this->relationLinkManager->setLinkDomain($domain); - $this->typeLinkManager->setLinkDomain($domain); - return $this; - } - -} +/** + * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has + * been moved to the serialization module. This exists solely for BC. + */ +class LinkManager extends MovedLinkManager implements LinkManagerInterface {} diff --git a/core/modules/rest/src/LinkManager/LinkManagerBase.php b/core/modules/rest/src/LinkManager/LinkManagerBase.php index 0896a80f73da4d2b34ff445356aad711330e5bfd..13f8b53ae3f819c086dd9f31319ac2a575ec15b1 100644 --- a/core/modules/rest/src/LinkManager/LinkManagerBase.php +++ b/core/modules/rest/src/LinkManager/LinkManagerBase.php @@ -2,57 +2,10 @@ namespace Drupal\rest\LinkManager; +use Drupal\serialization\LinkManager\LinkManagerBase as MovedLinkManagerBase; + /** - * Defines an abstract base-class for REST link manager objects. + * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has + * been moved to the serialization module. This exists solely for BC. */ -abstract class LinkManagerBase { - - /** - * Link domain used for type links URIs. - * - * @var string - */ - protected $linkDomain; - - /** - * Config factory service. - * - * @var \Drupal\Core\Config\ConfigFactoryInterface - */ - protected $configFactory; - - /** - * The request stack. - * - * @var \Symfony\Component\HttpFoundation\RequestStack - */ - protected $requestStack; - - /** - * {@inheritdoc} - */ - public function setLinkDomain($domain) { - $this->linkDomain = rtrim($domain, '/'); - return $this; - } - - /** - * Gets the link domain. - * - * @return string - * The link domain. - */ - protected function getLinkDomain() { - if (empty($this->linkDomain)) { - if ($domain = $this->configFactory->get('rest.settings')->get('link_domain')) { - $this->linkDomain = rtrim($domain, '/'); - } - else { - $request = $this->requestStack->getCurrentRequest(); - $this->linkDomain = $request->getSchemeAndHttpHost() . $request->getBasePath(); - } - } - return $this->linkDomain; - } - -} +abstract class LinkManagerBase extends MovedLinkManagerBase {} diff --git a/core/modules/rest/src/LinkManager/LinkManagerInterface.php b/core/modules/rest/src/LinkManager/LinkManagerInterface.php index 1bd04ff50b9043d34d5290124e301fa975db6cff..26f5dc473ddb19748dc97c89a8004fcd4e2495c1 100644 --- a/core/modules/rest/src/LinkManager/LinkManagerInterface.php +++ b/core/modules/rest/src/LinkManager/LinkManagerInterface.php @@ -2,17 +2,10 @@ namespace Drupal\rest\LinkManager; +use Drupal\serialization\LinkManager\LinkManagerInterface as MovedLinkManagerInterface; + /** - * Interface implemented by link managers. - * - * There are no explicit methods on the manager interface. Instead link managers - * broker the interactions of the different components, and therefore must - * implement each component interface, which is enforced by this interface - * extending all of the component ones. - * - * While a link manager may directly implement these interface methods with - * custom logic, it is expected to be more common for plugin managers to proxy - * the method invocations to the respective components. + * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has + * been moved to the serialization module. This exists solely for BC. */ -interface LinkManagerInterface extends TypeLinkManagerInterface, RelationLinkManagerInterface { -} +interface LinkManagerInterface extends MovedLinkManagerInterface {} diff --git a/core/modules/rest/src/LinkManager/RelationLinkManager.php b/core/modules/rest/src/LinkManager/RelationLinkManager.php index 297ffd9a0c2823a879dda432fd95ec9e1f8dc20b..a29eb9a89270a08ee6c1a3f3d39e6b1d63cad96d 100644 --- a/core/modules/rest/src/LinkManager/RelationLinkManager.php +++ b/core/modules/rest/src/LinkManager/RelationLinkManager.php @@ -2,141 +2,10 @@ namespace Drupal\rest\LinkManager; -use Drupal\Core\Cache\Cache; -use Drupal\Core\Cache\CacheBackendInterface; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Entity\ContentEntityTypeInterface; -use Drupal\Core\Entity\EntityManagerInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Symfony\Component\HttpFoundation\RequestStack; +use Drupal\serialization\LinkManager\RelationLinkManager as MovedLinkRelationManager; -class RelationLinkManager extends LinkManagerBase implements RelationLinkManagerInterface { - - /** - * @var \Drupal\Core\Cache\CacheBackendInterface; - */ - protected $cache; - - /** - * Entity manager. - * - * @var \Drupal\Core\Entity\EntityManagerInterface - */ - protected $entityManager; - - /** - * Module handler service. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * Constructor. - * - * @param \Drupal\Core\Cache\CacheBackendInterface $cache - * The cache of relation URIs and their associated Typed Data IDs. - * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager - * The entity manager. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory - * The config factory service. - * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack - * The request stack. - */ - public function __construct(CacheBackendInterface $cache, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory, RequestStack $request_stack) { - $this->cache = $cache; - $this->entityManager = $entity_manager; - $this->configFactory = $config_factory; - $this->moduleHandler = $module_handler; - $this->requestStack = $request_stack; - } - - /** - * {@inheritdoc} - */ - public function getRelationUri($entity_type, $bundle, $field_name, $context = array()) { - // Per the interface documention of this method, the returned URI may - // optionally also serve as the URL of a documentation page about this - // field. However, the REST module does not currently implement such - // a documentation page. Therefore, we return a URI assembled relative to - // the site's base URL, which is sufficient to uniquely identify the site's - // entity type + bundle + field for use in hypermedia formats, but we do - // not take into account unclean URLs, language prefixing, or anything else - // that would be required for Drupal to be able to respond with content - // at this URL. If a module is installed that adds such content, but - // requires this URL to be different (e.g., include a language prefix), - // then the module must also override the RelationLinkManager class/service - // to return the desired URL. - $uri = $this->getLinkDomain() . "/rest/relation/$entity_type/$bundle/$field_name"; - $this->moduleHandler->alter('rest_relation_uri', $uri, $context); - return $uri; - } - - /** - * {@inheritdoc} - */ - public function getRelationInternalIds($relation_uri, $context = array()) { - $relations = $this->getRelations($context); - if (isset($relations[$relation_uri])) { - return $relations[$relation_uri]; - } - return FALSE; - } - - /** - * Get the array of relation links. - * - * Any field can be handled as a relation simply by changing how it is - * normalized. Therefore, there is no prior knowledge that can be used here - * to determine which fields to assign relation URIs. Instead, each field, - * even primitives, are given a relation URI. It is up to the caller to - * determine which URIs to use. - * - * @param array $context - * Context from the normalizer/serializer operation. - * - * @return array - * An array of typed data ids (entity_type, bundle, and field name) keyed - * by corresponding relation URI. - */ - protected function getRelations($context = array()) { - $cid = 'rest:links:relations'; - $cache = $this->cache->get($cid); - if (!$cache) { - $this->writeCache($context); - $cache = $this->cache->get($cid); - } - return $cache->data; - } - - /** - * Writes the cache of relation links. - * - * @param array $context - * Context from the normalizer/serializer operation. - */ - protected function writeCache($context = array()) { - $data = array(); - - foreach ($this->entityManager->getDefinitions() as $entity_type) { - if ($entity_type instanceof ContentEntityTypeInterface) { - foreach ($this->entityManager->getBundleInfo($entity_type->id()) as $bundle => $bundle_info) { - foreach ($this->entityManager->getFieldDefinitions($entity_type->id(), $bundle) as $field_definition) { - $relation_uri = $this->getRelationUri($entity_type->id(), $bundle, $field_definition->getName(), $context); - $data[$relation_uri] = array( - 'entity_type' => $entity_type, - 'bundle' => $bundle, - 'field_name' => $field_definition->getName(), - ); - } - } - } - } - // These URIs only change when field info changes, so cache it permanently - // and only clear it when the fields cache is cleared. - $this->cache->set('rest:links:relations', $data, Cache::PERMANENT, array('entity_field_info')); - } - -} +/** + * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has + * been moved to the serialization module. This exists solely for BC. + */ +class RelationLinkManager extends MovedLinkRelationManager implements RelationLinkManagerInterface {} diff --git a/core/modules/rest/src/LinkManager/RelationLinkManagerInterface.php b/core/modules/rest/src/LinkManager/RelationLinkManagerInterface.php index 53cd03991fb576ae64e0aafa12104dadeec84e73..c171b764eeb0bffeca0dee997ffd74ae4f888ae4 100644 --- a/core/modules/rest/src/LinkManager/RelationLinkManagerInterface.php +++ b/core/modules/rest/src/LinkManager/RelationLinkManagerInterface.php @@ -2,38 +2,10 @@ namespace Drupal\rest\LinkManager; -interface RelationLinkManagerInterface extends ConfigurableLinkManagerInterface { +use Drupal\serialization\LinkManager\RelationLinkManagerInterface as MovedRelationLinkManagerInterface; - /** - * Gets the URI that corresponds to a field. - * - * When using hypermedia formats, this URI can be used to indicate which - * field the data represents. Documentation about this field can also be - * provided at this URI. - * - * @param string $entity_type - * The bundle's entity type. - * @param string $bundle - * The bundle name. - * @param string $field_name - * The field name. - * @param array $context - * (optional) Optional serializer/normalizer context. - * - * @return string - * The corresponding URI for the field. - */ - public function getRelationUri($entity_type, $bundle, $field_name, $context = array()); - - /** - * Translates a REST URI into internal IDs. - * - * @param string $relation_uri - * Relation URI to transform into internal IDs - * - * @return array - * Array with keys 'entity_type', 'bundle' and 'field_name'. - */ - public function getRelationInternalIds($relation_uri); - -} +/** + * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has + * been moved to the serialization module. This exists solely for BC. + */ +interface RelationLinkManagerInterface extends MovedRelationLinkManagerInterface {} diff --git a/core/modules/rest/src/LinkManager/TypeLinkManager.php b/core/modules/rest/src/LinkManager/TypeLinkManager.php index 3b0c8a23a8f216e0d117f668aea532ed7d3ec120..ac514eb0b0aa32ff96e1fb215828a30792b3c45c 100644 --- a/core/modules/rest/src/LinkManager/TypeLinkManager.php +++ b/core/modules/rest/src/LinkManager/TypeLinkManager.php @@ -2,148 +2,10 @@ namespace Drupal\rest\LinkManager; -use Drupal\Core\Cache\Cache; -use Drupal\Core\Cache\CacheBackendInterface; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Config\Entity\ConfigEntityInterface; -use Drupal\Core\Entity\EntityTypeBundleInfoInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Symfony\Component\HttpFoundation\RequestStack; +use Drupal\serialization\LinkManager\TypeLinkManager as MovedTypeLinkManager; -class TypeLinkManager extends LinkManagerBase implements TypeLinkManagerInterface { - - /** - * Injected cache backend. - * - * @var \Drupal\Core\Cache\CacheBackendInterface; - */ - protected $cache; - - /** - * Module handler service. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * The bundle info service. - * - * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface - */ - protected $bundleInfoService; - - /** - * Constructor. - * - * @param \Drupal\Core\Cache\CacheBackendInterface $cache - * The injected cache backend for caching type URIs. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler service. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory - * The config factory service. - * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack - * The request stack. - * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info_service - * The bundle info service. - */ - public function __construct(CacheBackendInterface $cache, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory, RequestStack $request_stack, EntityTypeBundleInfoInterface $bundle_info_service) { - $this->cache = $cache; - $this->configFactory = $config_factory; - $this->moduleHandler = $module_handler; - $this->requestStack = $request_stack; - $this->bundleInfoService = $bundle_info_service; - } - - /** - * {@inheritdoc} - */ - public function getTypeUri($entity_type, $bundle, $context = array()) { - // Per the interface documention of this method, the returned URI may - // optionally also serve as the URL of a documentation page about this - // bundle. However, the REST module does not currently implement such - // a documentation page. Therefore, we return a URI assembled relative to - // the site's base URL, which is sufficient to uniquely identify the site's - // entity type and bundle for use in hypermedia formats, but we do not - // take into account unclean URLs, language prefixing, or anything else - // that would be required for Drupal to be able to respond with content - // at this URL. If a module is installed that adds such content, but - // requires this URL to be different (e.g., include a language prefix), - // then the module must also override the TypeLinkManager class/service to - // return the desired URL. - $uri = $this->getLinkDomain() . "/rest/type/$entity_type/$bundle"; - $this->moduleHandler->alter('rest_type_uri', $uri, $context); - return $uri; - } - - /** - * {@inheritdoc} - */ - public function getTypeInternalIds($type_uri, $context = array()) { - $types = $this->getTypes($context); - if (isset($types[$type_uri])) { - return $types[$type_uri]; - } - return FALSE; - } - - /** - * Get the array of type links. - * - * @param array $context - * Context from the normalizer/serializer operation. - * - * @return array - * An array of typed data ids (entity_type and bundle) keyed by - * corresponding type URI. - */ - protected function getTypes($context = array()) { - $cid = 'rest:links:types'; - $cache = $this->cache->get($cid); - if (!$cache) { - $data = $this->writeCache($context); - } - else { - $data = $cache->data; - } - return $data; - } - - /** - * Writes the cache of type links. - * - * @param array $context - * Context from the normalizer/serializer operation. - * - * @return array - * An array of typed data ids (entity_type and bundle) keyed by - * corresponding type URI. - */ - protected function writeCache($context = array()) { - $data = array(); - - // Type URIs correspond to bundles. Iterate through the bundles to get the - // URI and data for them. - $entity_types = \Drupal::entityManager()->getDefinitions(); - foreach ($this->bundleInfoService->getAllBundleInfo() as $entity_type_id => $bundles) { - // Only content entities are supported currently. - // @todo Consider supporting config entities. - if ($entity_types[$entity_type_id]->entityClassImplements(ConfigEntityInterface::class)) { - continue; - } - foreach ($bundles as $bundle => $bundle_info) { - // Get a type URI for the bundle. - $bundle_uri = $this->getTypeUri($entity_type_id, $bundle, $context); - $data[$bundle_uri] = array( - 'entity_type' => $entity_type_id, - 'bundle' => $bundle, - ); - } - } - // These URIs only change when entity info changes, so cache it permanently - // and only clear it when entity_info is cleared. - $this->cache->set('rest:links:types', $data, Cache::PERMANENT, array('entity_types')); - return $data; - } - -} +/** + * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has + * been moved to the serialization module. This exists solely for BC. + */ +class TypeLinkManager extends MovedTypeLinkManager implements TypeLinkManagerInterface {} diff --git a/core/modules/rest/src/LinkManager/TypeLinkManagerInterface.php b/core/modules/rest/src/LinkManager/TypeLinkManagerInterface.php index 484ca76f15693ab560faae98a87dd7807a780dac..e4abf1d2e9361387695d198507f4a115dadf8055 100644 --- a/core/modules/rest/src/LinkManager/TypeLinkManagerInterface.php +++ b/core/modules/rest/src/LinkManager/TypeLinkManagerInterface.php @@ -2,39 +2,10 @@ namespace Drupal\rest\LinkManager; -interface TypeLinkManagerInterface extends ConfigurableLinkManagerInterface { +use Drupal\serialization\LinkManager\TypeLinkManagerInterface as MovedTypeLinkManagerInterface; - /** - * Gets the URI that corresponds to a bundle. - * - * When using hypermedia formats, this URI can be used to indicate which - * bundle the data represents. Documentation about required and optional - * fields can also be provided at this URI. - * - * @param $entity_type - * The bundle's entity type. - * @param $bundle - * The bundle name. - * @param array $context - * (optional) Optional serializer/normalizer context. - * - * @return string - * The corresponding URI for the bundle. - */ - public function getTypeUri($entity_type, $bundle, $context = array()); - - /** - * Get a bundle's Typed Data IDs based on a URI. - * - * @param string $type_uri - * The type URI. - * @param array $context - * Context from the normalizer/serializer operation. - * - * @return array | boolean - * If the URI matches a bundle, returns an array containing entity_type and - * bundle. Otherwise, returns false. - */ - public function getTypeInternalIds($type_uri, $context = array()); - -} +/** + * @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This has + * been moved to the serialization module. This exists solely for BC. + */ +interface TypeLinkManagerInterface extends MovedTypeLinkManagerInterface {} diff --git a/core/modules/rest/tests/modules/rest_test/rest_test.module b/core/modules/rest/tests/modules/rest_test/rest_test.module index 01511ea1e0ba74ff458459104aae9f07fd9ee372..98f9b5a129d4b3eaeb8c1fd28108147bd16a6d99 100644 --- a/core/modules/rest/tests/modules/rest_test/rest_test.module +++ b/core/modules/rest/tests/modules/rest_test/rest_test.module @@ -12,6 +12,8 @@ /** * Implements hook_rest_type_uri_alter(). + * + * @deprecated Kept only for BC test coverage, see \Drupal\Tests\serialization\Kernel\SerializationLinkManagerTest::testGetTypeUri(). */ function rest_test_rest_type_uri_alter(&$uri, $context = array()) { if (!empty($context['rest_test'])) { @@ -21,6 +23,8 @@ function rest_test_rest_type_uri_alter(&$uri, $context = array()) { /** * Implements hook_rest_relation_uri_alter(). + * + * @deprecated Kept only for BC test coverage, see \Drupal\Tests\serialization\Kernel\SerializationLinkManagerTest::testGetRelationUri(). */ function rest_test_rest_relation_uri_alter(&$uri, $context = array()) { if (!empty($context['rest_test'])) { diff --git a/core/modules/rest/tests/src/Kernel/RestLinkManagerTest.php b/core/modules/rest/tests/src/Kernel/RestLinkManagerTest.php deleted file mode 100644 index ab558e5761c816be7047d46d1e5287885101e7a1..0000000000000000000000000000000000000000 --- a/core/modules/rest/tests/src/Kernel/RestLinkManagerTest.php +++ /dev/null @@ -1,85 +0,0 @@ -rebuild(); - } - - /** - * Tests that type hooks work as expected. - */ - public function testRestLinkManagers() { - \Drupal::moduleHandler()->invoke('rest', 'install'); - /* @var \Drupal\rest\LinkManager\TypeLinkManagerInterface $type_manager */ - $type_manager = \Drupal::service('rest.link_manager.type'); - $base = Url::fromRoute('', [], ['absolute' => TRUE])->toString(); - $link = $type_manager->getTypeUri('node', 'page'); - $this->assertEqual($link, $base . 'rest/type/node/page'); - // Now with optional context. - $link = $type_manager->getTypeUri('node', 'page', ['rest_test' => TRUE]); - $this->assertEqual($link, 'rest_test_type'); - - /* @var \Drupal\rest\LinkManager\RelationLinkManagerInterface $relation_manager */ - $relation_manager = \Drupal::service('rest.link_manager.relation'); - $link = $relation_manager->getRelationUri('node', 'page', 'field_ref'); - $this->assertEqual($link, $base . 'rest/relation/node/page/field_ref'); - // Now with optional context. - $link = $relation_manager->getRelationUri('node', 'page', 'foobar', ['rest_test' => TRUE]); - $this->assertEqual($link, 'rest_test_relation'); - } - - /** - * Tests that type hooks work as expected even without install hook. - */ - public function testRestLinkManagersNoInstallHook() { - /* @var \Drupal\rest\LinkManager\TypeLinkManagerInterface $type_manager */ - $type_manager = \Drupal::service('rest.link_manager.type'); - $base = Url::fromRoute('', [], ['absolute' => TRUE])->toString(); - $link = $type_manager->getTypeUri('node', 'page'); - $this->assertEqual($link, $base . 'rest/type/node/page'); - // Now with optional context. - $link = $type_manager->getTypeUri('node', 'page', ['rest_test' => TRUE]); - $this->assertEqual($link, 'rest_test_type'); - - /* @var \Drupal\rest\LinkManager\RelationLinkManagerInterface $relation_manager */ - $relation_manager = \Drupal::service('rest.link_manager.relation'); - $link = $relation_manager->getRelationUri('node', 'page', 'field_ref'); - $this->assertEqual($link, $base . 'rest/relation/node/page/field_ref'); - // Now with optional context. - $link = $relation_manager->getRelationUri('node', 'page', 'foobar', ['rest_test' => TRUE]); - $this->assertEqual($link, 'rest_test_relation'); - } - - /** - * Tests \Drupal\rest\LinkManager\LinkManager::setLinkDomain(). - */ - public function testRestLinkManagersSetLinkDomain() { - /* @var \Drupal\rest\LinkManager\LinkManager $link_manager */ - $link_manager = \Drupal::service('rest.link_manager'); - $link_manager->setLinkDomain('http://example.com/'); - $link = $link_manager->getTypeUri('node', 'page'); - $this->assertEqual($link, 'http://example.com/rest/type/node/page'); - $link = $link_manager->getRelationUri('node', 'page', 'field_ref'); - $this->assertEqual($link, 'http://example.com/rest/relation/node/page/field_ref'); - } - -} diff --git a/core/modules/serialization/config/install/serialization.settings.yml b/core/modules/serialization/config/install/serialization.settings.yml new file mode 100644 index 0000000000000000000000000000000000000000..efe9deb9dda50016cd7e9572a4bc0ff521b29635 --- /dev/null +++ b/core/modules/serialization/config/install/serialization.settings.yml @@ -0,0 +1,3 @@ +# Set the domain for Serialization type and relation links. +# If left blank, the site's domain will be used. +link_domain: ~ diff --git a/core/modules/serialization/config/schema/serialization.schema.yml b/core/modules/serialization/config/schema/serialization.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..349499aa21f0f68f174b25e7d819052cae5103f3 --- /dev/null +++ b/core/modules/serialization/config/schema/serialization.schema.yml @@ -0,0 +1,8 @@ +# Schema for the configuration files of the Serialization module. +serialization.settings: + type: config_object + label: 'Serialization settings' + mapping: + link_domain: + type: string + label: 'Domain of the relation' diff --git a/core/modules/serialization/serialization.api.php b/core/modules/serialization/serialization.api.php new file mode 100644 index 0000000000000000000000000000000000000000..a9ced7243628821f7f09ab5d228731c39f45d166 --- /dev/null +++ b/core/modules/serialization/serialization.api.php @@ -0,0 +1,62 @@ +get('link_domain'); + $uri = str_replace($base, 'http://mymodule.domain', $uri); + } +} + + +/** + * Alter the serialization relation URI. + * + * Modules may wish to alter the relation URI generated for a resource based on + * the context of the serializer/normalizer operation. + * + * @param string $uri + * The URI to alter. + * @param array $context + * The context from the serializer/normalizer operation. + * + * @see \Symfony\Component\Serializer\SerializerInterface::serialize() + * @see \Symfony\Component\Serializer\SerializerInterface::deserialize() + * @see \Symfony\Component\Serializer\NormalizerInterface::normalize() + * @see \Symfony\Component\Serializer\DenormalizerInterface::denormalize() + */ +function hook_serialization_relation_uri_alter(&$uri, $context = array()) { + if ($context['mymodule'] == TRUE) { + $base = \Drupal::config('serialization.settings')->get('link_domain'); + $uri = str_replace($base, 'http://mymodule.domain', $uri); + } +} + +/** + * @} End of "addtogroup hooks". + */ diff --git a/core/modules/serialization/serialization.install b/core/modules/serialization/serialization.install new file mode 100644 index 0000000000000000000000000000000000000000..de3004945e40b80a3c14c949fc5a4bc37cd59a12 --- /dev/null +++ b/core/modules/serialization/serialization.install @@ -0,0 +1,43 @@ +getEditable('rest.settings'); + if ($rest_settings->getRawData() !== []) { + $link_domain = $rest_settings->get('link_domain'); + // Remove the 'link_domain' setting from 'rest.settings'. + $rest_settings->clear('link_domain') + ->save(); + } + + $serialization_settings = $config_factory->getEditable('serialization.settings'); + $serialization_settings->set('link_domain', $link_domain); + $serialization_settings->save(TRUE); +} + +/** + * @} End of "defgroup updates-8.2.x-to-8.3.x". + */ diff --git a/core/modules/serialization/serialization.services.yml b/core/modules/serialization/serialization.services.yml index c8fb3767f7e2ae54f1b13ca8ff2b0c9ddb8a9386..98a190bb264507c4dea5575ae29ae82afaa10130 100644 --- a/core/modules/serialization/serialization.services.yml +++ b/core/modules/serialization/serialization.services.yml @@ -89,3 +89,13 @@ services: tags: - { name: event_subscriber } arguments: ['%serializer.formats%'] + # Link managers. + serialization.link_manager: + class: Drupal\serialization\LinkManager\LinkManager + arguments: ['@serialization.link_manager.type', '@serialization.link_manager.relation'] + serialization.link_manager.type: + class: Drupal\serialization\LinkManager\TypeLinkManager + arguments: ['@cache.default', '@module_handler', '@config.factory', '@request_stack', '@entity_type.bundle.info'] + serialization.link_manager.relation: + class: Drupal\serialization\LinkManager\RelationLinkManager + arguments: ['@cache.default', '@entity.manager', '@module_handler', '@config.factory', '@request_stack'] diff --git a/core/modules/serialization/src/LinkManager/ConfigurableLinkManagerInterface.php b/core/modules/serialization/src/LinkManager/ConfigurableLinkManagerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..2e866025e02c1e399baa9c0d92e23d8eac1e391b --- /dev/null +++ b/core/modules/serialization/src/LinkManager/ConfigurableLinkManagerInterface.php @@ -0,0 +1,20 @@ +typeLinkManager = $type_link_manager; + $this->relationLinkManager = $relation_link_manager; + } + + /** + * {@inheritdoc} + */ + public function getTypeUri($entity_type, $bundle, $context = array()) { + return $this->typeLinkManager->getTypeUri($entity_type, $bundle, $context); + } + + /** + * {@inheritdoc} + */ + public function getTypeInternalIds($type_uri, $context = array()) { + return $this->typeLinkManager->getTypeInternalIds($type_uri, $context); + } + + /** + * {@inheritdoc} + */ + public function getRelationUri($entity_type, $bundle, $field_name, $context = array()) { + return $this->relationLinkManager->getRelationUri($entity_type, $bundle, $field_name, $context); + } + + /** + * {@inheritdoc} + */ + public function getRelationInternalIds($relation_uri) { + return $this->relationLinkManager->getRelationInternalIds($relation_uri); + } + + /** + * {@inheritdoc} + */ + public function setLinkDomain($domain) { + $this->relationLinkManager->setLinkDomain($domain); + $this->typeLinkManager->setLinkDomain($domain); + return $this; + } + +} diff --git a/core/modules/serialization/src/LinkManager/LinkManagerBase.php b/core/modules/serialization/src/LinkManager/LinkManagerBase.php new file mode 100644 index 0000000000000000000000000000000000000000..0cf7e69221d193447772e494278ba9ac876c995c --- /dev/null +++ b/core/modules/serialization/src/LinkManager/LinkManagerBase.php @@ -0,0 +1,58 @@ +linkDomain = rtrim($domain, '/'); + return $this; + } + + /** + * Gets the link domain. + * + * @return string + * The link domain. + */ + protected function getLinkDomain() { + if (empty($this->linkDomain)) { + if ($domain = $this->configFactory->get('serialization.settings')->get('link_domain')) { + $this->linkDomain = rtrim($domain, '/'); + } + else { + $request = $this->requestStack->getCurrentRequest(); + $this->linkDomain = $request->getSchemeAndHttpHost() . $request->getBasePath(); + } + } + return $this->linkDomain; + } + +} diff --git a/core/modules/serialization/src/LinkManager/LinkManagerInterface.php b/core/modules/serialization/src/LinkManager/LinkManagerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..8986d0faacd5ad8fecaaf795e4a93c302444a1f6 --- /dev/null +++ b/core/modules/serialization/src/LinkManager/LinkManagerInterface.php @@ -0,0 +1,18 @@ +cache = $cache; + $this->entityManager = $entity_manager; + $this->configFactory = $config_factory; + $this->moduleHandler = $module_handler; + $this->requestStack = $request_stack; + } + + /** + * {@inheritdoc} + */ + public function getRelationUri($entity_type, $bundle, $field_name, $context = array()) { + // Per the interface documentation of this method, the returned URI may + // optionally also serve as the URL of a documentation page about this + // field. However, Drupal does not currently implement such a documentation + // page. Therefore, we return a URI assembled relative to the site's base + // URL, which is sufficient to uniquely identify the site's entity type + + // bundle + field for use in hypermedia formats, but we do not take into + // account unclean URLs, language prefixing, or anything else that would be + // required for Drupal to be able to respond with content at this URL. If a + // module is installed that adds such content, but requires this URL to be + // different (e.g., include a language prefix), then the module must also + // override the RelationLinkManager class/service to return the desired URL. + $uri = $this->getLinkDomain() . "/rest/relation/$entity_type/$bundle/$field_name"; + $this->moduleHandler->alter('serialization_relation_uri', $uri, $context); + // @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This + // hook is invoked to maintain backwards compatibility + $this->moduleHandler->alter('rest_relation_uri', $uri, $context); + return $uri; + } + + /** + * {@inheritdoc} + */ + public function getRelationInternalIds($relation_uri, $context = array()) { + $relations = $this->getRelations($context); + if (isset($relations[$relation_uri])) { + return $relations[$relation_uri]; + } + return FALSE; + } + + /** + * Get the array of relation links. + * + * Any field can be handled as a relation simply by changing how it is + * normalized. Therefore, there is no prior knowledge that can be used here + * to determine which fields to assign relation URIs. Instead, each field, + * even primitives, are given a relation URI. It is up to the caller to + * determine which URIs to use. + * + * @param array $context + * Context from the normalizer/serializer operation. + * + * @return array + * An array of typed data ids (entity_type, bundle, and field name) keyed + * by corresponding relation URI. + */ + protected function getRelations($context = array()) { + $cid = 'serialization:links:relations'; + $cache = $this->cache->get($cid); + if (!$cache) { + $this->writeCache($context); + $cache = $this->cache->get($cid); + } + return $cache->data; + } + + /** + * Writes the cache of relation links. + * + * @param array $context + * Context from the normalizer/serializer operation. + */ + protected function writeCache($context = array()) { + $data = array(); + + foreach ($this->entityManager->getDefinitions() as $entity_type) { + if ($entity_type instanceof ContentEntityTypeInterface) { + foreach ($this->entityManager->getBundleInfo($entity_type->id()) as $bundle => $bundle_info) { + foreach ($this->entityManager->getFieldDefinitions($entity_type->id(), $bundle) as $field_definition) { + $relation_uri = $this->getRelationUri($entity_type->id(), $bundle, $field_definition->getName(), $context); + $data[$relation_uri] = array( + 'entity_type' => $entity_type, + 'bundle' => $bundle, + 'field_name' => $field_definition->getName(), + ); + } + } + } + } + // These URIs only change when field info changes, so cache it permanently + // and only clear it when the fields cache is cleared. + $this->cache->set('serialization:links:relations', $data, Cache::PERMANENT, array('entity_field_info')); + } + +} diff --git a/core/modules/serialization/src/LinkManager/RelationLinkManagerInterface.php b/core/modules/serialization/src/LinkManager/RelationLinkManagerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..fb0aac8f8f219b04433b24aa6e190eb06476e760 --- /dev/null +++ b/core/modules/serialization/src/LinkManager/RelationLinkManagerInterface.php @@ -0,0 +1,39 @@ +cache = $cache; + $this->configFactory = $config_factory; + $this->moduleHandler = $module_handler; + $this->requestStack = $request_stack; + $this->bundleInfoService = $bundle_info_service; + } + + /** + * {@inheritdoc} + */ + public function getTypeUri($entity_type, $bundle, $context = array()) { + // Per the interface documentation of this method, the returned URI may + // optionally also serve as the URL of a documentation page about this + // bundle. However, Drupal does not currently implement such a documentation + // page. Therefore, we return a URI assembled relative to the site's base + // URL, which is sufficient to uniquely identify the site's entity type and + // bundle for use in hypermedia formats, but we do not take into account + // unclean URLs, language prefixing, or anything else that would be required + // for Drupal to be able to respond with content at this URL. If a module is + // installed that adds such content, but requires this URL to be different + // (e.g., include a language prefix), then the module must also override the + // TypeLinkManager class/service to return the desired URL. + $uri = $this->getLinkDomain() . "/rest/type/$entity_type/$bundle"; + $this->moduleHandler->alter('serialization_type_uri', $uri, $context); + // @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This + // hook is invoked to maintain backwards compatibility + $this->moduleHandler->alter('rest_type_uri', $uri, $context); + return $uri; + } + + /** + * {@inheritdoc} + */ + public function getTypeInternalIds($type_uri, $context = array()) { + $types = $this->getTypes($context); + if (isset($types[$type_uri])) { + return $types[$type_uri]; + } + return FALSE; + } + + /** + * Get the array of type links. + * + * @param array $context + * Context from the normalizer/serializer operation. + * + * @return array + * An array of typed data ids (entity_type and bundle) keyed by + * corresponding type URI. + */ + protected function getTypes($context = array()) { + $cid = 'serialization:links:types'; + $cache = $this->cache->get($cid); + if (!$cache) { + $data = $this->writeCache($context); + } + else { + $data = $cache->data; + } + return $data; + } + + /** + * Writes the cache of type links. + * + * @param array $context + * Context from the normalizer/serializer operation. + * + * @return array + * An array of typed data ids (entity_type and bundle) keyed by + * corresponding type URI. + */ + protected function writeCache($context = array()) { + $data = array(); + + // Type URIs correspond to bundles. Iterate through the bundles to get the + // URI and data for them. + $entity_types = \Drupal::entityManager()->getDefinitions(); + foreach ($this->bundleInfoService->getAllBundleInfo() as $entity_type_id => $bundles) { + // Only content entities are supported currently. + // @todo Consider supporting config entities. + if ($entity_types[$entity_type_id]->entityClassImplements(ConfigEntityInterface::class)) { + continue; + } + foreach ($bundles as $bundle => $bundle_info) { + // Get a type URI for the bundle. + $bundle_uri = $this->getTypeUri($entity_type_id, $bundle, $context); + $data[$bundle_uri] = array( + 'entity_type' => $entity_type_id, + 'bundle' => $bundle, + ); + } + } + // These URIs only change when entity info changes, so cache it permanently + // and only clear it when entity_info is cleared. + $this->cache->set('serialization:links:types', $data, Cache::PERMANENT, array('entity_types')); + return $data; + } + +} diff --git a/core/modules/serialization/src/LinkManager/TypeLinkManagerInterface.php b/core/modules/serialization/src/LinkManager/TypeLinkManagerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..fed9119cf4b3a5b0c7a8d2a4ed6f5e8e117cc051 --- /dev/null +++ b/core/modules/serialization/src/LinkManager/TypeLinkManagerInterface.php @@ -0,0 +1,40 @@ +insert('key_value') + ->fields([ + 'collection' => 'system.schema', + 'name' => 'serialization', + 'value' => 'i:8000;', + ]) + ->execute(); + +// Update core.extension. +$extensions = $connection->select('config') + ->fields('config', ['data']) + ->condition('collection', '') + ->condition('name', 'core.extension') + ->execute() + ->fetchField(); +$extensions = unserialize($extensions); +$extensions['module']['serialization'] = 0; +$connection->update('config') + ->fields([ + 'data' => serialize($extensions), + ]) + ->condition('collection', '') + ->condition('name', 'core.extension') + ->execute(); diff --git a/core/modules/serialization/tests/serialization_test/serialization_test.module b/core/modules/serialization/tests/serialization_test/serialization_test.module new file mode 100644 index 0000000000000000000000000000000000000000..c47ca2fe87fe6defe310ec304461247cc5f697cb --- /dev/null +++ b/core/modules/serialization/tests/serialization_test/serialization_test.module @@ -0,0 +1,24 @@ +databaseDumpFiles = [ + __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz', + __DIR__ . '/../../../fixtures/update/drupal-8.serialization-serialization_update_8301.php', + ]; + } + + /** + * Tests serialization_update_8301(). + */ + public function testSerializationSettingsCreated() { + // Make sure we have the expected values before the update. + $serialization_settings = $this->config('serialization.settings'); + $this->assertIdentical([], $serialization_settings->getRawData()); + + $this->runUpdates(); + + // Make sure we have the expected values after the update. + $serialization_settings = \Drupal::configFactory()->get('serialization.settings'); + $this->assertTrue(array_key_exists('link_domain', $serialization_settings->getRawData())); + $this->assertIdentical(NULL, $serialization_settings->getRawData()['link_domain']); + } + +} diff --git a/core/modules/serialization/tests/src/Functional/Update/MigrateLinkDomainSettingFromRestToSerializationUpdateTest.php b/core/modules/serialization/tests/src/Functional/Update/MigrateLinkDomainSettingFromRestToSerializationUpdateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5e490577db858e1c68c7c849cd8e1027f4fbc8aa --- /dev/null +++ b/core/modules/serialization/tests/src/Functional/Update/MigrateLinkDomainSettingFromRestToSerializationUpdateTest.php @@ -0,0 +1,53 @@ +databaseDumpFiles = [ + __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz', + __DIR__ . '/../../../fixtures/update/drupal-8.serialization-serialization_update_8301.php', + __DIR__ . '/../../../fixtures/update/drupal-8.rest-serialization_update_8301.php', + ]; + } + + /** + * Tests serialization_update_8301(). + */ + public function testLinkDomainMigratedFromRestSettingsToSerializationSettings() { + // Make sure we have the expected values before the update. + $serialization_settings = $this->config('serialization.settings'); + $this->assertIdentical([], $serialization_settings->getRawData()); + $rest_settings = $this->config('rest.settings'); + $this->assertTrue(array_key_exists('link_domain', $rest_settings->getRawData())); + $this->assertIdentical('http://example.com', $rest_settings->getRawData()['link_domain']); + + $this->runUpdates(); + + // Make sure we have the expected values after the update. + $serialization_settings = \Drupal::configFactory()->get('serialization.settings'); + $this->assertTrue(array_key_exists('link_domain', $serialization_settings->getRawData())); + $this->assertIdentical('http://example.com', $serialization_settings->getRawData()['link_domain']); + $rest_settings = $this->config('rest.settings'); + $this->assertFalse(array_key_exists('link_domain', $rest_settings->getRawData())); + } + +} diff --git a/core/modules/serialization/tests/src/Kernel/SerializationLinkManagerTest.php b/core/modules/serialization/tests/src/Kernel/SerializationLinkManagerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e88ef0ab492919d8edb386f323168cfc2f091ba1 --- /dev/null +++ b/core/modules/serialization/tests/src/Kernel/SerializationLinkManagerTest.php @@ -0,0 +1,74 @@ +rebuild(); + } + + /** + * @covers ::getTypeUri + */ + public function testGetTypeUri() { + /* @var \Drupal\rest\LinkManager\TypeLinkManagerInterface $type_manager */ + $type_manager = \Drupal::service('serialization.link_manager.type'); + $base = Url::fromRoute('', [], ['absolute' => TRUE])->toString(); + $link = $type_manager->getTypeUri('node', 'page'); + $this->assertSame($link, $base . 'rest/type/node/page'); + // Now with optional context. + $link = $type_manager->getTypeUri('node', 'page', ['serialization_test' => TRUE]); + $this->assertSame($link, 'serialization_test_type'); + // Test BC: hook_rest_type_uri_alter(). + $link = $type_manager->getTypeUri('node', 'page', ['rest_test' => TRUE]); + $this->assertSame($link, 'rest_test_type'); + } + + /** + * @covers ::getRelationUri + */ + public function testGetRelationUri() { + /* @var \Drupal\rest\LinkManager\RelationLinkManagerInterface $relation_manager */ + $relation_manager = \Drupal::service('serialization.link_manager.relation'); + $base = Url::fromRoute('', [], ['absolute' => TRUE])->toString(); + $link = $relation_manager->getRelationUri('node', 'page', 'field_ref'); + $this->assertSame($link, $base . 'rest/relation/node/page/field_ref'); + // Now with optional context. + $link = $relation_manager->getRelationUri('node', 'page', 'foobar', ['serialization_test' => TRUE]); + $this->assertSame($link, 'serialization_test_relation'); + // Test BC: hook_rest_relation_uri_alter(). + $link = $relation_manager->getRelationUri('node', 'page', 'foobar', ['rest_test' => TRUE]); + $this->assertSame($link, 'rest_test_relation'); + } + + /** + * @covers ::setLinkDomain + */ + public function testSerializationLinkManagersSetLinkDomain() { + /* @var \Drupal\rest\LinkManager\LinkManager $link_manager */ + $link_manager = \Drupal::service('serialization.link_manager'); + $link_manager->setLinkDomain('http://example.com/'); + $link = $link_manager->getTypeUri('node', 'page'); + $this->assertEqual($link, 'http://example.com/rest/type/node/page'); + $link = $link_manager->getRelationUri('node', 'page', 'field_ref'); + $this->assertEqual($link, 'http://example.com/rest/relation/node/page/field_ref'); + } + +}