@amazeelabs/silverback-gatsby 3.7.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/drupal/silverback_gatsby/.prettierignore +1 -0
- package/drupal/silverback_gatsby/CHANGELOG.md +1216 -0
- package/drupal/silverback_gatsby/README.md +297 -0
- package/drupal/silverback_gatsby/composer.json +15 -0
- package/drupal/silverback_gatsby/directives.gql +63 -0
- package/drupal/silverback_gatsby/directives.graphql +62 -0
- package/drupal/silverback_gatsby/drush.services.yml +9 -0
- package/drupal/silverback_gatsby/graphql/entity.directive.graphqls +2 -0
- package/drupal/silverback_gatsby/graphql/menu.directive.graphqls +17 -0
- package/drupal/silverback_gatsby/graphql/silverback_gatsby.base.graphqls +25 -0
- package/drupal/silverback_gatsby/graphql/silverback_gatsby.extension.graphqls +10 -0
- package/drupal/silverback_gatsby/graphql/stringTranslation.directive.graphqls +4 -0
- package/drupal/silverback_gatsby/graphql/translatableString.directive.graphqls +2 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/directives.gql +6 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/graphql/.graphqlrc.json +4 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/graphql/silverback_gatsby_example.graphqls +39 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/silverback_gatsby_example.info.yml +7 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/silverback_gatsby_example.module +16 -0
- package/drupal/silverback_gatsby/modules/silverback_gatsby_example/src/Directives.php +24 -0
- package/drupal/silverback_gatsby/silverback_gatsby.info.yml +8 -0
- package/drupal/silverback_gatsby/silverback_gatsby.install +180 -0
- package/drupal/silverback_gatsby/silverback_gatsby.links.task.yml +6 -0
- package/drupal/silverback_gatsby/silverback_gatsby.module +119 -0
- package/drupal/silverback_gatsby/silverback_gatsby.permissions.yml +8 -0
- package/drupal/silverback_gatsby/silverback_gatsby.post_update.php +15 -0
- package/drupal/silverback_gatsby/silverback_gatsby.routing.yml +28 -0
- package/drupal/silverback_gatsby/silverback_gatsby.services.yml +50 -0
- package/drupal/silverback_gatsby/src/Annotation/GatsbyFeed.php +41 -0
- package/drupal/silverback_gatsby/src/Commands/SilverbackGatsbyCommands.php +102 -0
- package/drupal/silverback_gatsby/src/Controller/BuildController.php +45 -0
- package/drupal/silverback_gatsby/src/Controller/PublisherController.php +34 -0
- package/drupal/silverback_gatsby/src/Directives.php +51 -0
- package/drupal/silverback_gatsby/src/GatsbyBuildTrigger.php +230 -0
- package/drupal/silverback_gatsby/src/GatsbyBuildTriggerInterface.php +52 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdate.php +38 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdateHandler.php +181 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdateTracker.php +98 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdateTrackerInterface.php +59 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdateTrigger.php +69 -0
- package/drupal/silverback_gatsby/src/GatsbyUpdateTriggerInterface.php +22 -0
- package/drupal/silverback_gatsby/src/GraphQL/Build.php +235 -0
- package/drupal/silverback_gatsby/src/GraphQL/ComposableSchema.php +73 -0
- package/drupal/silverback_gatsby/src/LocaleStorageDecorator.php +181 -0
- package/drupal/silverback_gatsby/src/MenuTreeStorageDecorator.php +139 -0
- package/drupal/silverback_gatsby/src/Plugin/FeedBase.php +121 -0
- package/drupal/silverback_gatsby/src/Plugin/FeedInterface.php +132 -0
- package/drupal/silverback_gatsby/src/Plugin/FeedPluginManager.php +39 -0
- package/drupal/silverback_gatsby/src/Plugin/Gatsby/Feed/EntityFeed.php +252 -0
- package/drupal/silverback_gatsby/src/Plugin/Gatsby/Feed/MenuFeed.php +292 -0
- package/drupal/silverback_gatsby/src/Plugin/Gatsby/Feed/StringTranslationFeed.php +171 -0
- package/drupal/silverback_gatsby/src/Plugin/Gatsby/Feed/TranslatableStringFeed.php +128 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/CurrentUserEntity.php +43 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/EntityQueryBase.php +40 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/FetchEntity.php +371 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/FetchString.php +64 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/FetchTranslatableString.php +74 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/FocalPoint.php +47 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/GatsbyBuildId.php +36 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/GatsbyExtractId.php +28 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/GatsbyExtractLangcode.php +28 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/ImageProps.php +149 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/ListEntities.php +88 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/ListStrings.php +87 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/StringId.php +37 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/DataProducer/StringTranslations.php +94 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/EntityFetch.php +51 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/EntityTranslationsWithDefault.php +30 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/FocalPoint.php +27 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/ImageProps.php +27 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/MenuLangcode.php +27 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/MenuTranslations.php +36 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/Directive/SilverbackGatsbyEntityId.php +39 -0
- package/drupal/silverback_gatsby/src/Plugin/GraphQL/SchemaExtension/SilverbackGatsbySchemaExtension.php +384 -0
- package/drupal/silverback_gatsby/src/SilverbackGatsbyServiceProvider.php +43 -0
- package/drupal/silverback_gatsby/src/SilverbackGatsbySessionConfiguration.php +30 -0
- package/drupal/silverback_gatsby/src/SilverbackReverseProxyMiddleware.php +49 -0
- package/drupal/silverback_gatsby/tests/queries/create-page-fields.gql +12 -0
- package/drupal/silverback_gatsby/tests/queries/current-user.gql +6 -0
- package/drupal/silverback_gatsby/tests/queries/feed_info.gql +12 -0
- package/drupal/silverback_gatsby/tests/queries/load-entity.gql +5 -0
- package/drupal/silverback_gatsby/tests/queries/menus.gql +31 -0
- package/drupal/silverback_gatsby/tests/queries/multilingual-menus.gql +11 -0
- package/drupal/silverback_gatsby/tests/queries/revisionable-translatable.gql +15 -0
- package/drupal/silverback_gatsby/tests/queries/revisionable.gql +8 -0
- package/drupal/silverback_gatsby/tests/queries/translatable.gql +14 -0
- package/drupal/silverback_gatsby/tests/queries/untranslatable.gql +10 -0
- package/drupal/silverback_gatsby/tests/schema/.graphqlrc.json +4 -0
- package/drupal/silverback_gatsby/tests/schema/translatable-strings.graphql +7 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/CurrentUserTest.php +37 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/EntityFeedTest.php +490 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/EntityFeedTestBase.php +178 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/GatsbyBuildTriggerTest.php +155 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/GatsbyFeedInfoTest.php +319 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/GatsbyUpdateHandlerTest.php +131 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/GatsbyUpdateTrackerTest.php +196 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/GatsbyUpdateTriggerTest.php +177 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/MenuFeedTest.php +192 -0
- package/drupal/silverback_gatsby/tests/src/Kernel/TranslatableStringFeedTest.php +210 -0
- package/drupal/silverback_gatsby/tests/src/Traits/NotificationCheckTrait.php +43 -0
- package/package.json +15 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Drupal\silverback_gatsby\Plugin\GraphQL\DataProducer;
|
|
4
|
+
|
|
5
|
+
use Drupal\Core\Entity\EntityRepositoryInterface;
|
|
6
|
+
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
|
7
|
+
use Drupal\Core\Entity\TranslatableInterface;
|
|
8
|
+
use Drupal\Core\Language\LanguageManagerInterface;
|
|
9
|
+
use Drupal\Core\Path\PathValidatorInterface;
|
|
10
|
+
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
|
11
|
+
use Drupal\Core\Session\AccountInterface;
|
|
12
|
+
use Drupal\graphql\GraphQL\Buffers\EntityBuffer;
|
|
13
|
+
use Drupal\graphql\GraphQL\Buffers\EntityRevisionBuffer;
|
|
14
|
+
use Drupal\graphql\GraphQL\Execution\FieldContext;
|
|
15
|
+
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
|
|
16
|
+
use GraphQL\Deferred;
|
|
17
|
+
use Symfony\Component\DependencyInjection\ContainerInterface;
|
|
18
|
+
use Symfony\Component\HttpFoundation\Request;
|
|
19
|
+
use Symfony\Component\HttpFoundation\RequestStack;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @todo Add an option to upstream "entity_load" to return null on missing
|
|
23
|
+
* translation and remove this plugin.
|
|
24
|
+
*
|
|
25
|
+
* Loads a single entity.
|
|
26
|
+
*
|
|
27
|
+
* @DataProducer(
|
|
28
|
+
* id = "fetch_entity",
|
|
29
|
+
* name = @Translation("Fetch entity"),
|
|
30
|
+
* description = @Translation("Loads a single entity."),
|
|
31
|
+
* produces = @ContextDefinition("entity",
|
|
32
|
+
* label = @Translation("Entity")
|
|
33
|
+
* ),
|
|
34
|
+
* consumes = {
|
|
35
|
+
* "type" = @ContextDefinition("string",
|
|
36
|
+
* label = @Translation("Entity type")
|
|
37
|
+
* ),
|
|
38
|
+
* "id" = @ContextDefinition("string",
|
|
39
|
+
* label = @Translation("Identifier"),
|
|
40
|
+
* required = FALSE
|
|
41
|
+
* ),
|
|
42
|
+
* "revision_id" = @ContextDefinition("string",
|
|
43
|
+
* label = @Translation("A specific revision id to fetch"),
|
|
44
|
+
* required = FALSE
|
|
45
|
+
* ),
|
|
46
|
+
* "language" = @ContextDefinition("string",
|
|
47
|
+
* label = @Translation("Entity language"),
|
|
48
|
+
* required = FALSE
|
|
49
|
+
* ),
|
|
50
|
+
* "bundles" = @ContextDefinition("string",
|
|
51
|
+
* label = @Translation("Entity bundle(s)"),
|
|
52
|
+
* multiple = TRUE,
|
|
53
|
+
* required = FALSE
|
|
54
|
+
* ),
|
|
55
|
+
* "access" = @ContextDefinition("boolean",
|
|
56
|
+
* label = @Translation("Check access"),
|
|
57
|
+
* required = FALSE,
|
|
58
|
+
* default_value = TRUE
|
|
59
|
+
* ),
|
|
60
|
+
* "access_user" = @ContextDefinition("entity:user",
|
|
61
|
+
* label = @Translation("User"),
|
|
62
|
+
* required = FALSE,
|
|
63
|
+
* default_value = NULL
|
|
64
|
+
* ),
|
|
65
|
+
* "access_operation" = @ContextDefinition("string",
|
|
66
|
+
* label = @Translation("Operation"),
|
|
67
|
+
* required = FALSE,
|
|
68
|
+
* default_value = "view"
|
|
69
|
+
* ),
|
|
70
|
+
* "load_latest_revision" = @ContextDefinition("boolean",
|
|
71
|
+
* label = @Translation("Load latest revision"),
|
|
72
|
+
* required = FALSE,
|
|
73
|
+
* default_value = FALSE
|
|
74
|
+
* ),
|
|
75
|
+
* }
|
|
76
|
+
* )
|
|
77
|
+
*/
|
|
78
|
+
class FetchEntity extends DataProducerPluginBase implements ContainerFactoryPluginInterface {
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The entity type manager service.
|
|
82
|
+
*
|
|
83
|
+
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
|
84
|
+
*/
|
|
85
|
+
protected $entityTypeManager;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The entity repository service.
|
|
89
|
+
*
|
|
90
|
+
* @var \Drupal\Core\Entity\EntityRepositoryInterface
|
|
91
|
+
*/
|
|
92
|
+
protected $entityRepository;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The entity buffer service.
|
|
96
|
+
*
|
|
97
|
+
* @var \Drupal\graphql\GraphQL\Buffers\EntityBuffer
|
|
98
|
+
*/
|
|
99
|
+
protected $entityBuffer;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @var \Drupal\graphql\GraphQL\Buffers\EntityRevisionBuffer
|
|
103
|
+
*/
|
|
104
|
+
protected $entityRevisionBuffer;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @var \Drupal\Core\Path\PathValidatorInterface
|
|
108
|
+
*/
|
|
109
|
+
protected $pathValidator;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @var \Symfony\Component\HttpFoundation\RequestStack
|
|
113
|
+
*/
|
|
114
|
+
protected $requestStack;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @var \Drupal\Core\Language\LanguageManagerInterface
|
|
118
|
+
*/
|
|
119
|
+
protected $languageManager;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* {@inheritdoc}
|
|
123
|
+
*
|
|
124
|
+
* @codeCoverageIgnore
|
|
125
|
+
*/
|
|
126
|
+
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
|
127
|
+
return new static(
|
|
128
|
+
$configuration,
|
|
129
|
+
$plugin_id,
|
|
130
|
+
$plugin_definition,
|
|
131
|
+
$container->get('entity_type.manager'),
|
|
132
|
+
$container->get('entity.repository'),
|
|
133
|
+
$container->get('graphql.buffer.entity'),
|
|
134
|
+
$container->get('graphql.buffer.entity_revision'),
|
|
135
|
+
$container->get('path.validator'),
|
|
136
|
+
$container->get('request_stack'),
|
|
137
|
+
$container->get('language_manager')
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* EntityLoad constructor.
|
|
143
|
+
*
|
|
144
|
+
* @param array $configuration
|
|
145
|
+
* The plugin configuration array.
|
|
146
|
+
* @param string $pluginId
|
|
147
|
+
* The plugin id.
|
|
148
|
+
* @param array $pluginDefinition
|
|
149
|
+
* The plugin definition array.
|
|
150
|
+
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
|
|
151
|
+
* The entity type manager service.
|
|
152
|
+
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entityRepository
|
|
153
|
+
* The entity repository service.
|
|
154
|
+
* @param \Drupal\graphql\GraphQL\Buffers\EntityBuffer $entityBuffer
|
|
155
|
+
* The entity buffer service.
|
|
156
|
+
* @param \Drupal\graphql\GraphQL\Buffers\EntityRevisionBuffer $entityRevisionBuffer
|
|
157
|
+
* The entity revision buffer service.
|
|
158
|
+
*
|
|
159
|
+
* @codeCoverageIgnore
|
|
160
|
+
*/
|
|
161
|
+
public function __construct(
|
|
162
|
+
array $configuration,
|
|
163
|
+
string $pluginId,
|
|
164
|
+
array $pluginDefinition,
|
|
165
|
+
EntityTypeManagerInterface $entityTypeManager,
|
|
166
|
+
EntityRepositoryInterface $entityRepository,
|
|
167
|
+
EntityBuffer $entityBuffer,
|
|
168
|
+
EntityRevisionBuffer $entityRevisionBuffer,
|
|
169
|
+
PathValidatorInterface $pathValidator,
|
|
170
|
+
RequestStack $request_stack,
|
|
171
|
+
LanguageManagerInterface $language_manager
|
|
172
|
+
) {
|
|
173
|
+
parent::__construct($configuration, $pluginId, $pluginDefinition);
|
|
174
|
+
$this->entityTypeManager = $entityTypeManager;
|
|
175
|
+
$this->entityRepository = $entityRepository;
|
|
176
|
+
$this->entityBuffer = $entityBuffer;
|
|
177
|
+
$this->entityRevisionBuffer = $entityRevisionBuffer;
|
|
178
|
+
$this->pathValidator = $pathValidator;
|
|
179
|
+
$this->requestStack = $request_stack;
|
|
180
|
+
$this->languageManager = $language_manager;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Resolver.
|
|
185
|
+
*
|
|
186
|
+
* @param string $type
|
|
187
|
+
* @param string $id
|
|
188
|
+
* @param string|null $revisionId
|
|
189
|
+
* @param string|null $language
|
|
190
|
+
* @param array|null $bundles
|
|
191
|
+
* @param bool|null $access
|
|
192
|
+
* @param \Drupal\Core\Session\AccountInterface|null $accessUser
|
|
193
|
+
* @param string|null $accessOperation
|
|
194
|
+
* @param bool|null $loadLatestRevision
|
|
195
|
+
* @param \Drupal\graphql\GraphQL\Execution\FieldContext $context
|
|
196
|
+
*
|
|
197
|
+
* @return \GraphQL\Deferred
|
|
198
|
+
*/
|
|
199
|
+
public function resolve(
|
|
200
|
+
string $type,
|
|
201
|
+
string $id,
|
|
202
|
+
?string $revisionId,
|
|
203
|
+
?string $language,
|
|
204
|
+
?array $bundles,
|
|
205
|
+
?bool $access,
|
|
206
|
+
?AccountInterface $accessUser,
|
|
207
|
+
?string $accessOperation,
|
|
208
|
+
?bool $loadLatestRevision,
|
|
209
|
+
FieldContext $context
|
|
210
|
+
) {
|
|
211
|
+
if ($id[0] === '/') {
|
|
212
|
+
// We are dealing with a path. Attempt to resolve it to an entity. And if
|
|
213
|
+
// the language is not defined, then we try to extract it from the path.
|
|
214
|
+
if (empty($language)) {
|
|
215
|
+
// In order to extract the language we basically just push a temporary
|
|
216
|
+
// request to the stack, reset the language negotiation and get the
|
|
217
|
+
// current language again, which will use the request at the top of the
|
|
218
|
+
// stack. At the end, we pop the temporary request from the stack and
|
|
219
|
+
// reste the language negotiation again.ss
|
|
220
|
+
$tmpRequest = Request::create($id);
|
|
221
|
+
$this->requestStack->push($tmpRequest);
|
|
222
|
+
$this->languageManager->reset();
|
|
223
|
+
$language = $this->languageManager->getCurrentLanguage()->getId();
|
|
224
|
+
$this->requestStack->pop();
|
|
225
|
+
$this->languageManager->reset();
|
|
226
|
+
}
|
|
227
|
+
$url = $this->pathValidator->getUrlIfValidWithoutAccessCheck($id);
|
|
228
|
+
if (!($url && $url->isRouted() && $url->access())) {
|
|
229
|
+
$context->addCacheTags(['4xx-response']);
|
|
230
|
+
return NULL;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
$parameters = $url->getRouteParameters();
|
|
234
|
+
$id = $parameters[$type];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (!preg_match('/^[0-9]+$/', $id)) {
|
|
238
|
+
// Looks like we got a UUID. Transform it to a regular ID.
|
|
239
|
+
$result = $this->entityTypeManager
|
|
240
|
+
->getStorage($type)
|
|
241
|
+
->getQuery()
|
|
242
|
+
->condition('uuid', $id)
|
|
243
|
+
->accessCheck(FALSE)
|
|
244
|
+
->execute();
|
|
245
|
+
if ($result) {
|
|
246
|
+
$id = reset($result);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
$resolver = $revisionId
|
|
251
|
+
? $this->entityRevisionBuffer->add($type, $revisionId)
|
|
252
|
+
: $this->entityBuffer->add($type, $id);
|
|
253
|
+
|
|
254
|
+
return new Deferred(function () use ($type, $id, $revisionId, $language, $bundles, $resolver, $context, $access, $accessUser, $accessOperation, $loadLatestRevision) {
|
|
255
|
+
/** @var $entity \Drupal\Core\Entity\EntityInterface */
|
|
256
|
+
if (!$entity = $resolver()) {
|
|
257
|
+
// If there is no entity with this id, add the list cache tags so that
|
|
258
|
+
// the cache entry is purged whenever a new entity of this type is
|
|
259
|
+
// saved.
|
|
260
|
+
$type = $this->entityTypeManager->getDefinition($type);
|
|
261
|
+
/** @var \Drupal\Core\Entity\EntityTypeInterface $type */
|
|
262
|
+
$tags = $type->getListCacheTags();
|
|
263
|
+
$context->addCacheTags($tags);
|
|
264
|
+
return NULL;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
$context->addCacheableDependency($entity);
|
|
268
|
+
|
|
269
|
+
// Make sure that the loaded entity has the exact same id as the one which
|
|
270
|
+
// was computed from the route. It maybe be that a wrong revision was sent
|
|
271
|
+
// as parameter. In that case, return NULL.
|
|
272
|
+
if ($entity->id() !== $id) {
|
|
273
|
+
return NULL;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (isset($bundles) && !in_array($entity->bundle(), $bundles)) {
|
|
277
|
+
// If the entity is not among the allowed bundles, don't return it.
|
|
278
|
+
return NULL;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
// If we did not request a specific revision, then we just load the most
|
|
283
|
+
// up to date one (the latest/active revision), but only if the flag is
|
|
284
|
+
// set.
|
|
285
|
+
if (empty($revisionId) && $loadLatestRevision) {
|
|
286
|
+
$activeEntityContext = [];
|
|
287
|
+
$additionalCacheContexts = [];
|
|
288
|
+
if (isset($language)) {
|
|
289
|
+
$activeEntityContext['langcode'] = $language;
|
|
290
|
+
$additionalCacheContexts[] = "static:language:{$language}";
|
|
291
|
+
}
|
|
292
|
+
$entity = $this->entityRepository->getActive($type, $entity->id(), $activeEntityContext);
|
|
293
|
+
if (!empty($additionalCacheContexts)) {
|
|
294
|
+
$entity->addCacheContexts($additionalCacheContexts);
|
|
295
|
+
}
|
|
296
|
+
// If the language of the found revision does not match the requested
|
|
297
|
+
// language, then we just return NULL.
|
|
298
|
+
if (isset($language) && $language !== $entity->language()->getId()) {
|
|
299
|
+
return NULL;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
// If we are not interested in the latest revision, then we try to get the
|
|
303
|
+
// correct translation of the entity. When the latest revision is fetched,
|
|
304
|
+
// the proper language is already set into the context, so we do not need
|
|
305
|
+
// to request the translation separately.
|
|
306
|
+
elseif (isset($language) && $language !== $entity->language()->getId() && $entity instanceof TranslatableInterface) {
|
|
307
|
+
if (!$entity->hasTranslation($language)) {
|
|
308
|
+
return NULL;
|
|
309
|
+
}
|
|
310
|
+
$entity = $entity->getTranslation($language);
|
|
311
|
+
$entity->addCacheContexts(["static:language:{$language}"]);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Check if the passed user (or current user if none is passed) has access
|
|
315
|
+
// to the entity, if not return NULL.
|
|
316
|
+
if ($access) {
|
|
317
|
+
/** @var \Drupal\Core\Access\AccessResultInterface $accessResult */
|
|
318
|
+
$accessResult = $entity->access($accessOperation, $accessUser, TRUE);
|
|
319
|
+
$context->addCacheableDependency($accessResult);
|
|
320
|
+
if (!$accessResult->isAllowed()) {
|
|
321
|
+
return NULL;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// If a specific revision was requested, we show that one and do not check
|
|
326
|
+
// further for autosaved values.
|
|
327
|
+
if (!empty($revisionId)) {
|
|
328
|
+
return $entity;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Autosave: get autosaved values.
|
|
332
|
+
if (\Drupal::service('module_handler')->moduleExists('silverback_autosave')) {
|
|
333
|
+
$context->mergeCacheMaxAge(0);
|
|
334
|
+
// @todo Add DI to both.
|
|
335
|
+
/** @var \Drupal\silverback_autosave\Storage\AutosaveEntityFormStorageInterface $autoSaveFormStorage */
|
|
336
|
+
$autoSaveFormStorage = \Drupal::service('silverback_autosave.entity_form_storage');
|
|
337
|
+
$currentUser = \Drupal::currentUser();
|
|
338
|
+
$autosaveUserId = $currentUser->hasPermission('fetch any autosaved entity') ? NULL : $currentUser->id();
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* This causes leaked metadata error.
|
|
342
|
+
* $entityForm = \Drupal::service('entity.form_builder')->getForm($entity, 'edit');
|
|
343
|
+
* $form_id = $entityForm['form_id']['#value'];
|
|
344
|
+
*/
|
|
345
|
+
$form_id = "{$entity->getEntityTypeId()}_{$entity->bundle()}_edit_form";
|
|
346
|
+
$autosaved_state = $autoSaveFormStorage->getEntityAndFormState($form_id, $entity->getEntityTypeId(), $entity->id(), $entity->language()->getId(), $autosaveUserId);
|
|
347
|
+
/** @var \Drupal\Core\Entity\EntityInterface $autosaved_entity */
|
|
348
|
+
$autosaved_entity = $autosaved_state['entity'] ?? NULL;
|
|
349
|
+
/** @var \Drupal\Core\Form\FormStateInterface $autosaved_form_state */
|
|
350
|
+
$autosaved_form_state = $autosaved_state['form_state'] ?? [];
|
|
351
|
+
if ($autosaved_entity && !empty($autosaved_form_state)) {
|
|
352
|
+
$current_user_input = $autosaved_form_state->getUserInput();
|
|
353
|
+
foreach ($autosaved_entity->getFields() as $name => $field) {
|
|
354
|
+
if (in_array($name, [
|
|
355
|
+
'title',
|
|
356
|
+
'body',
|
|
357
|
+
]) || str_starts_with($name, 'field_')) {
|
|
358
|
+
if (isset($current_user_input[$name])) {
|
|
359
|
+
$field->setValue($current_user_input[$name]);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return $autosaved_entity;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return $entity;
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Drupal\silverback_gatsby\Plugin\GraphQL\DataProducer;
|
|
4
|
+
|
|
5
|
+
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
|
6
|
+
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
|
|
7
|
+
use Drupal\locale\StringStorageInterface;
|
|
8
|
+
use Symfony\Component\DependencyInjection\ContainerInterface;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* Loads a single string or translated string.
|
|
13
|
+
*
|
|
14
|
+
* @DataProducer(
|
|
15
|
+
* id = "fetch_string",
|
|
16
|
+
* name = @Translation("Fetch string"),
|
|
17
|
+
* description = @Translation("Loads a single string."),
|
|
18
|
+
* produces = @ContextDefinition("any",
|
|
19
|
+
* label = @Translation("String")
|
|
20
|
+
* ),
|
|
21
|
+
* consumes = {
|
|
22
|
+
* "id" = @ContextDefinition("string",
|
|
23
|
+
* label = @Translation("Identifier"),
|
|
24
|
+
* required = FALSE
|
|
25
|
+
* )
|
|
26
|
+
* }
|
|
27
|
+
* )
|
|
28
|
+
*/
|
|
29
|
+
class FetchString extends DataProducerPluginBase implements ContainerFactoryPluginInterface {
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The locale storage service.
|
|
33
|
+
*
|
|
34
|
+
* @var \Drupal\locale\StringStorageInterface
|
|
35
|
+
*/
|
|
36
|
+
protected $localeStorage;
|
|
37
|
+
|
|
38
|
+
public function __construct(
|
|
39
|
+
array $configuration,
|
|
40
|
+
$plugin_id,
|
|
41
|
+
$plugin_definition,
|
|
42
|
+
StringStorageInterface $locale_storage
|
|
43
|
+
) {
|
|
44
|
+
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
|
45
|
+
$this->localeStorage = $locale_storage;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
|
49
|
+
return new static(
|
|
50
|
+
$configuration,
|
|
51
|
+
$plugin_id,
|
|
52
|
+
$plugin_definition,
|
|
53
|
+
$container->get('locale.storage')
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public function resolve($id) {
|
|
58
|
+
$strings = $this->localeStorage->getStrings(['lid' => $id]);
|
|
59
|
+
if (!empty($strings)) {
|
|
60
|
+
return reset($strings);
|
|
61
|
+
}
|
|
62
|
+
return NULL;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Drupal\silverback_gatsby\Plugin\GraphQL\DataProducer;
|
|
4
|
+
|
|
5
|
+
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
|
6
|
+
use Drupal\graphql\GraphQL\Execution\FieldContext;
|
|
7
|
+
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
|
|
8
|
+
use Drupal\locale\StringStorageInterface;
|
|
9
|
+
use Symfony\Component\DependencyInjection\ContainerInterface;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* Loads a single string or translated string.
|
|
14
|
+
*
|
|
15
|
+
* @DataProducer(
|
|
16
|
+
* id = "fetch_translatable_string",
|
|
17
|
+
* name = @Translation("Fetch translatable string"),
|
|
18
|
+
* description = @Translation("Loads a single translatable string."),
|
|
19
|
+
* produces = @ContextDefinition("any",
|
|
20
|
+
* label = @Translation("String")
|
|
21
|
+
* ),
|
|
22
|
+
* consumes = {
|
|
23
|
+
* "id" = @ContextDefinition("string",
|
|
24
|
+
* label = @Translation("Identifier"),
|
|
25
|
+
* required = FALSE
|
|
26
|
+
* ),
|
|
27
|
+
* "language" = @ContextDefinition("string",
|
|
28
|
+
* label = @Translation("Language"),
|
|
29
|
+
* required = FALSE
|
|
30
|
+
* )
|
|
31
|
+
* }
|
|
32
|
+
* )
|
|
33
|
+
*/
|
|
34
|
+
class FetchTranslatableString extends DataProducerPluginBase implements ContainerFactoryPluginInterface {
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The locale storage service.
|
|
38
|
+
*
|
|
39
|
+
* @var \Drupal\locale\StringStorageInterface
|
|
40
|
+
*/
|
|
41
|
+
protected $localeStorage;
|
|
42
|
+
|
|
43
|
+
public function __construct(
|
|
44
|
+
array $configuration,
|
|
45
|
+
$plugin_id,
|
|
46
|
+
$plugin_definition,
|
|
47
|
+
StringStorageInterface $locale_storage
|
|
48
|
+
) {
|
|
49
|
+
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
|
50
|
+
$this->localeStorage = $locale_storage;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
|
54
|
+
return new static(
|
|
55
|
+
$configuration,
|
|
56
|
+
$plugin_id,
|
|
57
|
+
$plugin_definition,
|
|
58
|
+
$container->get('locale.storage')
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public function resolve($id, $language, FieldContext $context) {
|
|
63
|
+
$strings = $this->localeStorage->getTranslations([
|
|
64
|
+
'lid' => $id,
|
|
65
|
+
'language' => $language,
|
|
66
|
+
]);
|
|
67
|
+
// Make sure the result clears when new translations are added.
|
|
68
|
+
$context->addCacheTags(['locale']);
|
|
69
|
+
if (!empty($strings)) {
|
|
70
|
+
return reset($strings);
|
|
71
|
+
}
|
|
72
|
+
return NULL;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Drupal\silverback_gatsby\Plugin\GraphQL\DataProducer;
|
|
4
|
+
|
|
5
|
+
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
|
|
6
|
+
use Drupal\crop\Entity\Crop;
|
|
7
|
+
use Drupal\Core\StreamWrapper\PublicStream;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @DataProducer(
|
|
11
|
+
* id = "focal_point",
|
|
12
|
+
* name = @Translation("Focal Point"),
|
|
13
|
+
* description = @Translation("Retrieve focal point coordinates for an image source."),
|
|
14
|
+
* produces = @ContextDefinition("any",
|
|
15
|
+
* label = @Translation("Image properties")
|
|
16
|
+
* ),
|
|
17
|
+
* consumes = {
|
|
18
|
+
* "image_props" = @ContextDefinition("any",
|
|
19
|
+
* label = @Translation("Image Props"),
|
|
20
|
+
* required = FALSE
|
|
21
|
+
* )
|
|
22
|
+
* }
|
|
23
|
+
* )
|
|
24
|
+
*/
|
|
25
|
+
class FocalPoint extends DataProducerPluginBase {
|
|
26
|
+
/**
|
|
27
|
+
* Resolver to return the focal point coordinates.
|
|
28
|
+
*
|
|
29
|
+
* @param array $image_props
|
|
30
|
+
*
|
|
31
|
+
* @return array|null
|
|
32
|
+
*/
|
|
33
|
+
public function resolve(?array $image_props = NULL) {
|
|
34
|
+
$path = parse_url($image_props['src']);
|
|
35
|
+
$publicFilesDirectory = '/' . PublicStream::basePath();
|
|
36
|
+
// Reverse-engineer the public path to find the crop.
|
|
37
|
+
$public = 'public:/' . substr($path['path'], strlen($publicFilesDirectory));
|
|
38
|
+
$crop = Crop::findCrop($public, 'focal_point');
|
|
39
|
+
$x = $crop?->x->value;
|
|
40
|
+
$y = $crop?->y->value;
|
|
41
|
+
$image_props['focalPoint'] = $x && $y ? [
|
|
42
|
+
'x' => $x,
|
|
43
|
+
'y' => $y,
|
|
44
|
+
] : NULL;
|
|
45
|
+
return $image_props;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Drupal\silverback_gatsby\Plugin\GraphQL\DataProducer;
|
|
4
|
+
|
|
5
|
+
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @DataProducer(
|
|
9
|
+
* id = "gatsby_build_id",
|
|
10
|
+
* name = @Translation("Build the Gatsby ID "),
|
|
11
|
+
* produces = @ContextDefinition("string",
|
|
12
|
+
* label = @Translation("Gatsby ID"),
|
|
13
|
+
* multiple = TRUE,
|
|
14
|
+
* ),
|
|
15
|
+
* consumes = {
|
|
16
|
+
* "id" = @ContextDefinition("string",
|
|
17
|
+
* label = @Translation("ID"),
|
|
18
|
+
* required = TRUE,
|
|
19
|
+
* ),
|
|
20
|
+
* "langcode" = @ContextDefinition("string",
|
|
21
|
+
* label = @Translation("Langcode"),
|
|
22
|
+
* required = TRUE,
|
|
23
|
+
* )
|
|
24
|
+
* },
|
|
25
|
+
* )
|
|
26
|
+
*/
|
|
27
|
+
class GatsbyBuildId extends DataProducerPluginBase {
|
|
28
|
+
|
|
29
|
+
public static function build(string $id, string $langcode) {
|
|
30
|
+
return $id . ':' . $langcode;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public function resolve(string $id, string $langcode) {
|
|
34
|
+
return static::build($id, $langcode);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Drupal\silverback_gatsby\Plugin\GraphQL\DataProducer;
|
|
4
|
+
|
|
5
|
+
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @DataProducer(
|
|
9
|
+
* id = "gatsby_extract_id",
|
|
10
|
+
* name = @Translation("Extract ID from a Gatsby ID "),
|
|
11
|
+
* produces = @ContextDefinition("string",
|
|
12
|
+
* label = @Translation("ID"),
|
|
13
|
+
* multiple = TRUE,
|
|
14
|
+
* ),
|
|
15
|
+
* consumes = {
|
|
16
|
+
* "id" = @ContextDefinition("string",
|
|
17
|
+
* label = @Translation("Gatsby ID"),
|
|
18
|
+
* required = TRUE,
|
|
19
|
+
* )
|
|
20
|
+
* },
|
|
21
|
+
* )
|
|
22
|
+
*/
|
|
23
|
+
class GatsbyExtractId extends DataProducerPluginBase {
|
|
24
|
+
|
|
25
|
+
public function resolve(string $id) {
|
|
26
|
+
return explode(':', $id)[0];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Drupal\silverback_gatsby\Plugin\GraphQL\DataProducer;
|
|
4
|
+
|
|
5
|
+
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @DataProducer(
|
|
9
|
+
* id = "gatsby_extract_langcode",
|
|
10
|
+
* name = @Translation("Extract langcode from a Gatsby ID "),
|
|
11
|
+
* produces = @ContextDefinition("string",
|
|
12
|
+
* label = @Translation("Langcode"),
|
|
13
|
+
* multiple = TRUE,
|
|
14
|
+
* ),
|
|
15
|
+
* consumes = {
|
|
16
|
+
* "id" = @ContextDefinition("string",
|
|
17
|
+
* label = @Translation("Gatsby ID"),
|
|
18
|
+
* required = TRUE,
|
|
19
|
+
* )
|
|
20
|
+
* },
|
|
21
|
+
* )
|
|
22
|
+
*/
|
|
23
|
+
class GatsbyExtractLangcode extends DataProducerPluginBase {
|
|
24
|
+
|
|
25
|
+
public function resolve(string $id) {
|
|
26
|
+
return explode(':', $id)[1] ?? NULL;
|
|
27
|
+
}
|
|
28
|
+
}
|