62be23d2bca04b1b644579b29da207b5362a3ef1
[yaffs-website] / web / core / modules / hal / src / LinkManager / TypeLinkManager.php
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\EntityTypeBundleInfoInterface;
9 use Drupal\Core\Extension\ModuleHandlerInterface;
10 use Symfony\Component\HttpFoundation\RequestStack;
11
12 class TypeLinkManager extends LinkManagerBase implements TypeLinkManagerInterface {
13
14   /**
15    * Injected cache backend.
16    *
17    * @var \Drupal\Core\Cache\CacheBackendInterface
18    */
19   protected $cache;
20
21   /**
22    * Module handler service.
23    *
24    * @var \Drupal\Core\Extension\ModuleHandlerInterface
25    */
26   protected $moduleHandler;
27
28   /**
29    * The bundle info service.
30    *
31    * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
32    */
33   protected $bundleInfoService;
34
35   /**
36    * Constructor.
37    *
38    * @param \Drupal\Core\Cache\CacheBackendInterface $cache
39    *   The injected cache backend for caching type URIs.
40    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
41    *   The module handler service.
42    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
43    *   The config factory service.
44    * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
45    *   The request stack.
46    * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info_service
47    *   The bundle info service.
48    */
49   public function __construct(CacheBackendInterface $cache, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory, RequestStack $request_stack, EntityTypeBundleInfoInterface $bundle_info_service) {
50     $this->cache = $cache;
51     $this->configFactory = $config_factory;
52     $this->moduleHandler = $module_handler;
53     $this->requestStack = $request_stack;
54     $this->bundleInfoService = $bundle_info_service;
55   }
56
57   /**
58    * {@inheritdoc}
59    */
60   public function getTypeUri($entity_type, $bundle, $context = []) {
61     // Per the interface documentation of this method, the returned URI may
62     // optionally also serve as the URL of a documentation page about this
63     // bundle. However, Drupal does not currently implement such a documentation
64     // page. Therefore, we return a URI assembled relative to the site's base
65     // URL, which is sufficient to uniquely identify the site's entity type and
66     // bundle for use in hypermedia formats, but we do not take into account
67     // unclean URLs, language prefixing, or anything else that would be required
68     // for Drupal to be able to respond with content at this URL. If a module is
69     // installed that adds such content, but requires this URL to be different
70     // (e.g., include a language prefix), then the module must also override the
71     // TypeLinkManager class/service to return the desired URL.
72     $uri = $this->getLinkDomain($context) . "/rest/type/$entity_type/$bundle";
73     $this->moduleHandler->alter('hal_type_uri', $uri, $context);
74     $this->moduleHandler->alterDeprecated('This hook is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0. Implement hook_hal_type_uri_alter() instead.', 'rest_type_uri', $uri, $context);
75     return $uri;
76   }
77
78   /**
79    * {@inheritdoc}
80    */
81   public function getTypeInternalIds($type_uri, $context = []) {
82     $types = $this->getTypes($context);
83     if (isset($types[$type_uri])) {
84       return $types[$type_uri];
85     }
86     return FALSE;
87   }
88
89   /**
90    * Get the array of type links.
91    *
92    * @param array $context
93    *   Context from the normalizer/serializer operation.
94    *
95    * @return array
96    *   An array of typed data ids (entity_type and bundle) keyed by
97    *   corresponding type URI.
98    */
99   protected function getTypes($context = []) {
100     $cid = 'hal:links:types';
101     $cache = $this->cache->get($cid);
102     if (!$cache) {
103       $data = $this->writeCache($context);
104     }
105     else {
106       $data = $cache->data;
107     }
108     return $data;
109   }
110
111   /**
112    * Writes the cache of type links.
113    *
114    * @param array $context
115    *   Context from the normalizer/serializer operation.
116    *
117    * @return array
118    *   An array of typed data ids (entity_type and bundle) keyed by
119    *   corresponding type URI.
120    */
121   protected function writeCache($context = []) {
122     $data = [];
123
124     // Type URIs correspond to bundles. Iterate through the bundles to get the
125     // URI and data for them.
126     $entity_types = \Drupal::entityManager()->getDefinitions();
127     foreach ($this->bundleInfoService->getAllBundleInfo() as $entity_type_id => $bundles) {
128       // Only content entities are supported currently.
129       // @todo Consider supporting config entities.
130       if ($entity_types[$entity_type_id]->entityClassImplements(ConfigEntityInterface::class)) {
131         continue;
132       }
133       foreach ($bundles as $bundle => $bundle_info) {
134         // Get a type URI for the bundle.
135         $bundle_uri = $this->getTypeUri($entity_type_id, $bundle, $context);
136         $data[$bundle_uri] = [
137           'entity_type' => $entity_type_id,
138           'bundle' => $bundle,
139         ];
140       }
141     }
142     // These URIs only change when entity info changes, so cache it permanently
143     // and only clear it when entity_info is cleared.
144     $this->cache->set('hal:links:types', $data, Cache::PERMANENT, ['entity_types']);
145     return $data;
146   }
147
148 }