comparison core/modules/hal/src/LinkManager/RelationLinkManager.php @ 0:c75dbcec494b

Initial commit from drush-created site
author Chris Cannam
date Thu, 05 Jul 2018 14:24:15 +0000
parents
children a9cd425dd02b
comparison
equal deleted inserted replaced
-1:000000000000 0:c75dbcec494b
1 <?php
2
3 namespace Drupal\hal\LinkManager;
4
5 use Drupal\Core\Cache\Cache;
6 use Drupal\Core\Cache\CacheBackendInterface;
7 use Drupal\Core\Config\ConfigFactoryInterface;
8 use Drupal\Core\Entity\ContentEntityTypeInterface;
9 use Drupal\Core\Entity\EntityManagerInterface;
10 use Drupal\Core\Extension\ModuleHandlerInterface;
11 use Symfony\Component\HttpFoundation\RequestStack;
12
13 class RelationLinkManager extends LinkManagerBase implements RelationLinkManagerInterface {
14
15 /**
16 * @var \Drupal\Core\Cache\CacheBackendInterface;
17 */
18 protected $cache;
19
20 /**
21 * Entity manager.
22 *
23 * @var \Drupal\Core\Entity\EntityManagerInterface
24 */
25 protected $entityManager;
26
27 /**
28 * Module handler service.
29 *
30 * @var \Drupal\Core\Extension\ModuleHandlerInterface
31 */
32 protected $moduleHandler;
33
34 /**
35 * Constructor.
36 *
37 * @param \Drupal\Core\Cache\CacheBackendInterface $cache
38 * The cache of relation URIs and their associated Typed Data IDs.
39 * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
40 * The entity manager.
41 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
42 * The module handler service.
43 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
44 * The config factory service.
45 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
46 * The request stack.
47 */
48 public function __construct(CacheBackendInterface $cache, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory, RequestStack $request_stack) {
49 $this->cache = $cache;
50 $this->entityManager = $entity_manager;
51 $this->configFactory = $config_factory;
52 $this->moduleHandler = $module_handler;
53 $this->requestStack = $request_stack;
54 }
55
56 /**
57 * {@inheritdoc}
58 */
59 public function getRelationUri($entity_type, $bundle, $field_name, $context = []) {
60 // Per the interface documentation of this method, the returned URI may
61 // optionally also serve as the URL of a documentation page about this
62 // field. However, Drupal does not currently implement such a documentation
63 // page. Therefore, we return a URI assembled relative to the site's base
64 // URL, which is sufficient to uniquely identify the site's entity type +
65 // bundle + field for use in hypermedia formats, but we do not take into
66 // account unclean URLs, language prefixing, or anything else that would be
67 // required for Drupal to be able to respond with content at this URL. If a
68 // module is installed that adds such content, but requires this URL to be
69 // different (e.g., include a language prefix), then the module must also
70 // override the RelationLinkManager class/service to return the desired URL.
71 $uri = $this->getLinkDomain($context) . "/rest/relation/$entity_type/$bundle/$field_name";
72 $this->moduleHandler->alter('hal_relation_uri', $uri, $context);
73 // @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. This
74 // hook is invoked to maintain backwards compatibility
75 // @see https://www.drupal.org/node/2830467
76 $this->moduleHandler->alter('rest_relation_uri', $uri, $context);
77 return $uri;
78 }
79
80 /**
81 * {@inheritdoc}
82 */
83 public function getRelationInternalIds($relation_uri, $context = []) {
84 $relations = $this->getRelations($context);
85 if (isset($relations[$relation_uri])) {
86 return $relations[$relation_uri];
87 }
88 return FALSE;
89 }
90
91 /**
92 * Get the array of relation links.
93 *
94 * Any field can be handled as a relation simply by changing how it is
95 * normalized. Therefore, there is no prior knowledge that can be used here
96 * to determine which fields to assign relation URIs. Instead, each field,
97 * even primitives, are given a relation URI. It is up to the caller to
98 * determine which URIs to use.
99 *
100 * @param array $context
101 * Context from the normalizer/serializer operation.
102 *
103 * @return array
104 * An array of typed data IDs keyed by corresponding relation URI. The keys
105 * are:
106 * - 'entity_type_id'
107 * - 'bundle'
108 * - 'field_name'
109 * - 'entity_type' (deprecated)
110 * The values for 'entity_type_id', 'bundle' and 'field_name' are strings.
111 * The 'entity_type' key exists for backwards compatibility and its value is
112 * the full entity type object. The 'entity_type' key will be removed before
113 * Drupal 9.0.
114 *
115 * @see https://www.drupal.org/node/2877608
116 */
117 protected function getRelations($context = []) {
118 $cid = 'hal:links:relations';
119 $cache = $this->cache->get($cid);
120 if (!$cache) {
121 $data = $this->writeCache($context);
122 }
123 else {
124 $data = $cache->data;
125 }
126
127 // @todo https://www.drupal.org/node/2716163 Remove this in Drupal 9.0.
128 foreach ($data as $relation_uri => $ids) {
129 $data[$relation_uri]['entity_type'] = $this->entityManager->getDefinition($ids['entity_type_id']);
130 }
131 return $data;
132 }
133
134 /**
135 * Writes the cache of relation links.
136 *
137 * @param array $context
138 * Context from the normalizer/serializer operation.
139 *
140 * @return array
141 * An array of typed data IDs keyed by corresponding relation URI. The keys
142 * are:
143 * - 'entity_type_id'
144 * - 'bundle'
145 * - 'field_name'
146 * The values for 'entity_type_id', 'bundle' and 'field_name' are strings.
147 */
148 protected function writeCache($context = []) {
149 $data = [];
150
151 foreach ($this->entityManager->getDefinitions() as $entity_type) {
152 if ($entity_type instanceof ContentEntityTypeInterface) {
153 foreach ($this->entityManager->getBundleInfo($entity_type->id()) as $bundle => $bundle_info) {
154 foreach ($this->entityManager->getFieldDefinitions($entity_type->id(), $bundle) as $field_definition) {
155 $relation_uri = $this->getRelationUri($entity_type->id(), $bundle, $field_definition->getName(), $context);
156 $data[$relation_uri] = [
157 'entity_type_id' => $entity_type->id(),
158 'bundle' => $bundle,
159 'field_name' => $field_definition->getName(),
160 ];
161 }
162 }
163 }
164 }
165 // These URIs only change when field info changes, so cache it permanently
166 // and only clear it when the fields cache is cleared.
167 $this->cache->set('hal:links:relations', $data, Cache::PERMANENT, ['entity_field_info']);
168 return $data;
169 }
170
171 }