Chris@18
|
1 <?php
|
Chris@18
|
2
|
Chris@18
|
3 namespace Drupal\jsonapi\Controller;
|
Chris@18
|
4
|
Chris@18
|
5 use Drupal\Core\Cache\CacheableMetadata;
|
Chris@18
|
6 use Drupal\Core\Controller\ControllerBase;
|
Chris@18
|
7 use Drupal\Core\Session\AccountInterface;
|
Chris@18
|
8 use Drupal\Core\Url;
|
Chris@18
|
9 use Drupal\jsonapi\JsonApiResource\JsonApiDocumentTopLevel;
|
Chris@18
|
10 use Drupal\jsonapi\JsonApiResource\LinkCollection;
|
Chris@18
|
11 use Drupal\jsonapi\JsonApiResource\NullIncludedData;
|
Chris@18
|
12 use Drupal\jsonapi\JsonApiResource\Link;
|
Chris@18
|
13 use Drupal\jsonapi\JsonApiResource\ResourceObjectData;
|
Chris@18
|
14 use Drupal\jsonapi\ResourceResponse;
|
Chris@18
|
15 use Drupal\jsonapi\ResourceType\ResourceType;
|
Chris@18
|
16 use Drupal\jsonapi\ResourceType\ResourceTypeRepositoryInterface;
|
Chris@18
|
17 use Drupal\user\Entity\User;
|
Chris@18
|
18 use Symfony\Component\DependencyInjection\ContainerInterface;
|
Chris@18
|
19 use Symfony\Component\Routing\Exception\RouteNotFoundException;
|
Chris@18
|
20
|
Chris@18
|
21 /**
|
Chris@18
|
22 * Controller for the API entry point.
|
Chris@18
|
23 *
|
Chris@18
|
24 * @internal JSON:API maintains no PHP API. The API is the HTTP API. This class
|
Chris@18
|
25 * may change at any time and could break any dependencies on it.
|
Chris@18
|
26 *
|
Chris@18
|
27 * @see https://www.drupal.org/project/jsonapi/issues/3032787
|
Chris@18
|
28 * @see jsonapi.api.php
|
Chris@18
|
29 */
|
Chris@18
|
30 class EntryPoint extends ControllerBase {
|
Chris@18
|
31
|
Chris@18
|
32 /**
|
Chris@18
|
33 * The JSON:API resource type repository.
|
Chris@18
|
34 *
|
Chris@18
|
35 * @var \Drupal\jsonapi\ResourceType\ResourceTypeRepositoryInterface
|
Chris@18
|
36 */
|
Chris@18
|
37 protected $resourceTypeRepository;
|
Chris@18
|
38
|
Chris@18
|
39 /**
|
Chris@18
|
40 * The account object.
|
Chris@18
|
41 *
|
Chris@18
|
42 * @var \Drupal\Core\Session\AccountInterface
|
Chris@18
|
43 */
|
Chris@18
|
44 protected $user;
|
Chris@18
|
45
|
Chris@18
|
46 /**
|
Chris@18
|
47 * EntryPoint constructor.
|
Chris@18
|
48 *
|
Chris@18
|
49 * @param \Drupal\jsonapi\ResourceType\ResourceTypeRepositoryInterface $resource_type_repository
|
Chris@18
|
50 * The resource type repository.
|
Chris@18
|
51 * @param \Drupal\Core\Session\AccountInterface $user
|
Chris@18
|
52 * The current user.
|
Chris@18
|
53 */
|
Chris@18
|
54 public function __construct(ResourceTypeRepositoryInterface $resource_type_repository, AccountInterface $user) {
|
Chris@18
|
55 $this->resourceTypeRepository = $resource_type_repository;
|
Chris@18
|
56 $this->user = $user;
|
Chris@18
|
57 }
|
Chris@18
|
58
|
Chris@18
|
59 /**
|
Chris@18
|
60 * {@inheritdoc}
|
Chris@18
|
61 */
|
Chris@18
|
62 public static function create(ContainerInterface $container) {
|
Chris@18
|
63 return new static(
|
Chris@18
|
64 $container->get('jsonapi.resource_type.repository'),
|
Chris@18
|
65 $container->get('current_user')
|
Chris@18
|
66 );
|
Chris@18
|
67 }
|
Chris@18
|
68
|
Chris@18
|
69 /**
|
Chris@18
|
70 * Controller to list all the resources.
|
Chris@18
|
71 *
|
Chris@18
|
72 * @return \Drupal\jsonapi\ResourceResponse
|
Chris@18
|
73 * The response object.
|
Chris@18
|
74 */
|
Chris@18
|
75 public function index() {
|
Chris@18
|
76 $cacheability = (new CacheableMetadata())
|
Chris@18
|
77 ->addCacheContexts(['user.roles:authenticated'])
|
Chris@18
|
78 ->addCacheTags(['jsonapi_resource_types']);
|
Chris@18
|
79
|
Chris@18
|
80 // Only build URLs for exposed resources.
|
Chris@18
|
81 $resources = array_filter($this->resourceTypeRepository->all(), function ($resource) {
|
Chris@18
|
82 return !$resource->isInternal();
|
Chris@18
|
83 });
|
Chris@18
|
84
|
Chris@18
|
85 $self_link = new Link(new CacheableMetadata(), Url::fromRoute('jsonapi.resource_list'), ['self']);
|
Chris@18
|
86 $urls = array_reduce($resources, function (LinkCollection $carry, ResourceType $resource_type) {
|
Chris@18
|
87 if ($resource_type->isLocatable() || $resource_type->isMutable()) {
|
Chris@18
|
88 $route_suffix = $resource_type->isLocatable() ? 'collection' : 'collection.post';
|
Chris@18
|
89 $url = Url::fromRoute(sprintf('jsonapi.%s.%s', $resource_type->getTypeName(), $route_suffix))->setAbsolute();
|
Chris@18
|
90 // @todo: implement an extension relation type to signal that this is a primary collection resource.
|
Chris@18
|
91 $link_relation_types = [];
|
Chris@18
|
92 return $carry->withLink($resource_type->getTypeName(), new Link(new CacheableMetadata(), $url, $link_relation_types));
|
Chris@18
|
93 }
|
Chris@18
|
94 return $carry;
|
Chris@18
|
95 }, new LinkCollection(['self' => $self_link]));
|
Chris@18
|
96
|
Chris@18
|
97 $meta = [];
|
Chris@18
|
98 if ($this->user->isAuthenticated()) {
|
Chris@18
|
99 $current_user_uuid = User::load($this->user->id())->uuid();
|
Chris@18
|
100 $meta['links']['me'] = ['meta' => ['id' => $current_user_uuid]];
|
Chris@18
|
101 $cacheability->addCacheContexts(['user']);
|
Chris@18
|
102 try {
|
Chris@18
|
103 $me_url = Url::fromRoute(
|
Chris@18
|
104 'jsonapi.user--user.individual',
|
Chris@18
|
105 ['entity' => $current_user_uuid]
|
Chris@18
|
106 )
|
Chris@18
|
107 ->setAbsolute()
|
Chris@18
|
108 ->toString(TRUE);
|
Chris@18
|
109 $meta['links']['me']['href'] = $me_url->getGeneratedUrl();
|
Chris@18
|
110 // The cacheability of the `me` URL is the cacheability of that URL
|
Chris@18
|
111 // itself and the currently authenticated user.
|
Chris@18
|
112 $cacheability = $cacheability->merge($me_url);
|
Chris@18
|
113 }
|
Chris@18
|
114 catch (RouteNotFoundException $e) {
|
Chris@18
|
115 // Do not add the link if the route is disabled or marked as internal.
|
Chris@18
|
116 }
|
Chris@18
|
117 }
|
Chris@18
|
118
|
Chris@18
|
119 $response = new ResourceResponse(new JsonApiDocumentTopLevel(new ResourceObjectData([]), new NullIncludedData(), $urls, $meta));
|
Chris@18
|
120 return $response->addCacheableDependency($cacheability);
|
Chris@18
|
121 }
|
Chris@18
|
122
|
Chris@18
|
123 }
|