@amazeelabs/silverback-gutenberg 2.6.2

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.
Files changed (94) hide show
  1. package/CHANGELOG.md +983 -0
  2. package/drupal/silverback_gutenberg/README.md +439 -0
  3. package/drupal/silverback_gutenberg/composer.json +20 -0
  4. package/drupal/silverback_gutenberg/config/install/silverback_gutenberg.settings.yml +1 -0
  5. package/drupal/silverback_gutenberg/config/schema/silverback_gutenberg.schema.yml +13 -0
  6. package/drupal/silverback_gutenberg/css/gutenberg-tweaks.css +46 -0
  7. package/drupal/silverback_gutenberg/directives.gql +40 -0
  8. package/drupal/silverback_gutenberg/directives.graphql +46 -0
  9. package/drupal/silverback_gutenberg/js/base.js +24 -0
  10. package/drupal/silverback_gutenberg/js/gutenberg-tweaks.js +154 -0
  11. package/drupal/silverback_gutenberg/silverback_gutenberg.api.php +76 -0
  12. package/drupal/silverback_gutenberg/silverback_gutenberg.info.yml +8 -0
  13. package/drupal/silverback_gutenberg/silverback_gutenberg.libraries.yml +14 -0
  14. package/drupal/silverback_gutenberg/silverback_gutenberg.module +97 -0
  15. package/drupal/silverback_gutenberg/silverback_gutenberg.services.yml +29 -0
  16. package/drupal/silverback_gutenberg/src/Annotation/GutenbergBlockMutator.php +39 -0
  17. package/drupal/silverback_gutenberg/src/Annotation/GutenbergValidator.php +37 -0
  18. package/drupal/silverback_gutenberg/src/Annotation/GutenbergValidatorRule.php +37 -0
  19. package/drupal/silverback_gutenberg/src/Attribute/GutenbergBlockMutator.php +29 -0
  20. package/drupal/silverback_gutenberg/src/BlockMutator/BlockMutatorBase.php +24 -0
  21. package/drupal/silverback_gutenberg/src/BlockMutator/BlockMutatorInterface.php +41 -0
  22. package/drupal/silverback_gutenberg/src/BlockMutator/BlockMutatorManager.php +114 -0
  23. package/drupal/silverback_gutenberg/src/BlockMutator/BlockMutatorManagerInterface.php +30 -0
  24. package/drupal/silverback_gutenberg/src/BlockMutator/EntityBlockMutatorBase.php +189 -0
  25. package/drupal/silverback_gutenberg/src/BlockSerializer.php +84 -0
  26. package/drupal/silverback_gutenberg/src/Controller/LinkitAutocomplete.php +84 -0
  27. package/drupal/silverback_gutenberg/src/Directives.php +74 -0
  28. package/drupal/silverback_gutenberg/src/EditorBlocksProcessor.php +53 -0
  29. package/drupal/silverback_gutenberg/src/GutenbergValidation/GutenbergCardinalityValidatorInterface.php +19 -0
  30. package/drupal/silverback_gutenberg/src/GutenbergValidation/GutenbergCardinalityValidatorTrait.php +221 -0
  31. package/drupal/silverback_gutenberg/src/GutenbergValidation/GutenbergValidatorBase.php +24 -0
  32. package/drupal/silverback_gutenberg/src/GutenbergValidation/GutenbergValidatorInterface.php +65 -0
  33. package/drupal/silverback_gutenberg/src/GutenbergValidation/GutenbergValidatorManager.php +37 -0
  34. package/drupal/silverback_gutenberg/src/GutenbergValidation/GutenbergValidatorRuleInterface.php +20 -0
  35. package/drupal/silverback_gutenberg/src/GutenbergValidation/GutenbergValidatorRuleManager.php +37 -0
  36. package/drupal/silverback_gutenberg/src/LinkProcessor.php +405 -0
  37. package/drupal/silverback_gutenberg/src/LinkedContentExtractor.php +35 -0
  38. package/drupal/silverback_gutenberg/src/Normalizer/GutenbergContentEntityNormalizer.php +123 -0
  39. package/drupal/silverback_gutenberg/src/Plugin/EntityUsage/Track/GutenbergContentTrackTrait.php +51 -0
  40. package/drupal/silverback_gutenberg/src/Plugin/EntityUsage/Track/GutenbergLinkedContent.php +96 -0
  41. package/drupal/silverback_gutenberg/src/Plugin/EntityUsage/Track/GutenbergMediaEmbed.php +63 -0
  42. package/drupal/silverback_gutenberg/src/Plugin/EntityUsage/Track/GutenbergReferencedContent.php +101 -0
  43. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/DataProducer/EditorBlockAttribute.php +42 -0
  44. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/DataProducer/EditorBlockChildren.php +32 -0
  45. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/DataProducer/EditorBlockHtml.php +30 -0
  46. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/DataProducer/EditorBlockMedia.php +159 -0
  47. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/DataProducer/EditorBlockType.php +29 -0
  48. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/DataProducer/EditorBlocks.php +127 -0
  49. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/Directive/EditorBlockAttribute.php +29 -0
  50. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/Directive/EditorBlockChildren.php +21 -0
  51. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/Directive/EditorBlockMarkup.php +21 -0
  52. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/Directive/EditorBlockMedia.php +21 -0
  53. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/Directive/EditorBlockType.php +21 -0
  54. package/drupal/silverback_gutenberg/src/Plugin/GraphQL/Directive/EditorBlocks.php +36 -0
  55. package/drupal/silverback_gutenberg/src/Plugin/GutenbergBlockMutator/MediaBlockMutator.php +30 -0
  56. package/drupal/silverback_gutenberg/src/Plugin/GutenbergBlockMutator/NodeBlockMutator.php +25 -0
  57. package/drupal/silverback_gutenberg/src/Plugin/GutenbergBlockMutator/TermReferenceBlockMutator.php +104 -0
  58. package/drupal/silverback_gutenberg/src/Plugin/Linkit/Matcher/SilverbackMatcherTrait.php +69 -0
  59. package/drupal/silverback_gutenberg/src/Plugin/Linkit/Matcher/SilverbackMediaMatcher.php +53 -0
  60. package/drupal/silverback_gutenberg/src/Plugin/Linkit/Matcher/SilverbackNodeMatcher.php +19 -0
  61. package/drupal/silverback_gutenberg/src/Plugin/Validation/Constraint/Gutenberg.php +15 -0
  62. package/drupal/silverback_gutenberg/src/Plugin/Validation/Constraint/GutenbergValidator.php +210 -0
  63. package/drupal/silverback_gutenberg/src/Plugin/Validation/GutenbergValidatorRule/Email.php +28 -0
  64. package/drupal/silverback_gutenberg/src/Plugin/Validation/GutenbergValidatorRule/Required.php +29 -0
  65. package/drupal/silverback_gutenberg/src/ReferencedContentExtractor.php +67 -0
  66. package/drupal/silverback_gutenberg/src/Routing/RouteSubscriber.php +17 -0
  67. package/drupal/silverback_gutenberg/src/Service/MediaService.php +27 -0
  68. package/drupal/silverback_gutenberg/src/SilverbackGutenbergServiceProvider.php +28 -0
  69. package/drupal/silverback_gutenberg/src/Utils.php +30 -0
  70. package/drupal/silverback_gutenberg/src/WebformMessageManager.php +29 -0
  71. package/drupal/silverback_gutenberg/tests/graphql/.graphqlrc.json +5 -0
  72. package/drupal/silverback_gutenberg/tests/graphql/queries/editor.gql +30 -0
  73. package/drupal/silverback_gutenberg/tests/graphql/schema.graphqls +37 -0
  74. package/drupal/silverback_gutenberg/tests/modules/silverback_gutenberg_test_validator/silverback_gutenberg_test_validator.info.yml +9 -0
  75. package/drupal/silverback_gutenberg/tests/modules/silverback_gutenberg_test_validator/src/Plugin/Validation/GutenbergValidator/ColumnValidator.php +42 -0
  76. package/drupal/silverback_gutenberg/tests/modules/silverback_gutenberg_test_validator/src/Plugin/Validation/GutenbergValidator/GroupValidator.php +50 -0
  77. package/drupal/silverback_gutenberg/tests/modules/silverback_gutenberg_test_validator/src/Plugin/Validation/GutenbergValidator/LinkValidator.php +43 -0
  78. package/drupal/silverback_gutenberg/tests/src/Kernel/BlockValidationRuleTest.php +194 -0
  79. package/drupal/silverback_gutenberg/tests/src/Kernel/EditorDirectivesTest.php +255 -0
  80. package/drupal/silverback_gutenberg/tests/src/Kernel/GutenbergLinkedContentEUTrackTest.php +133 -0
  81. package/drupal/silverback_gutenberg/tests/src/Kernel/GutenbergReferencedContentEUTrackTest.php +225 -0
  82. package/drupal/silverback_gutenberg/tests/src/Kernel/LinkProcessorTest.php +284 -0
  83. package/drupal/silverback_gutenberg/tests/src/Kernel/MediaNormalizerTest.php +174 -0
  84. package/drupal/silverback_gutenberg/tests/src/Traits/SampleAssetTrait.php +15 -0
  85. package/drupal/silverback_gutenberg/tests/src/Unit/BlockSerializerTest.php +27 -0
  86. package/drupal/silverback_gutenberg/tests/src/Unit/BlockValidatorCardinalityTest.php +1537 -0
  87. package/drupal/silverback_gutenberg/tests/src/Unit/EditorBlocksProcessorTest.php +159 -0
  88. package/drupal/silverback_gutenberg/tests/src/Unit/LinkedContentExtractorTest.php +65 -0
  89. package/drupal/silverback_gutenberg/tests/src/Unit/ReferencedContentExtractorTest.php +248 -0
  90. package/drupal/silverback_gutenberg/tests/src/assets/media/data.json +4 -0
  91. package/drupal/silverback_gutenberg/tests/src/assets/media/source.html +71 -0
  92. package/drupal/silverback_gutenberg/tests/src/assets/media/target.html +71 -0
  93. package/package.json +16 -0
  94. package/turbo.json +15 -0
@@ -0,0 +1,255 @@
1
+ <?php
2
+
3
+ namespace Drupal\Tests\silverback_gutenberg\Kernel;
4
+
5
+ use Drupal\field\Entity\FieldConfig;
6
+ use Drupal\field\Entity\FieldStorageConfig;
7
+ use Drupal\file\Entity\File;
8
+ use Drupal\media\Entity\Media;
9
+ use Drupal\node\Entity\Node;
10
+ use Drupal\node\Entity\NodeType;
11
+ use Drupal\silverback_gutenberg\BlockSerializer;
12
+ use Drupal\Tests\graphql\Kernel\GraphQLTestBase;
13
+ use Drupal\Tests\graphql_directives\Traits\GraphQLDirectivesTestTrait;
14
+ use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
15
+ use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
16
+ use Drupal\Tests\node\Traits\NodeCreationTrait;
17
+ use Drupal\Tests\TestFileCreationTrait;
18
+
19
+ class EditorDirectivesTest extends GraphQLTestBase {
20
+ use GraphQLDirectivesTestTrait;
21
+ protected static $modules = [
22
+ 'graphql_directives',
23
+ 'text',
24
+ 'file',
25
+ 'media',
26
+ 'image',
27
+ 'path_alias',
28
+ 'silverback_gutenberg'
29
+ ];
30
+
31
+ use ContentTypeCreationTrait;
32
+ use NodeCreationTrait;
33
+ use MediaTypeCreationTrait;
34
+ use TestFileCreationTrait;
35
+
36
+ protected function setUp(): void {
37
+ parent::setUp();
38
+ $this->installEntitySchema('media');
39
+ $this->installEntitySchema('file');
40
+ $this->installSchema('file', ['file_usage']);
41
+ $this->installConfig('media');
42
+
43
+ $this->createMediaType('image', ['id' => 'image']);
44
+ $this->container->get('content_translation.manager')->setEnabled(
45
+ 'media',
46
+ 'image',
47
+ TRUE
48
+ );
49
+
50
+ $pageType = NodeType::create(
51
+ [
52
+ 'type' => 'page',
53
+ 'name' => 'Page',
54
+ 'translatable' => TRUE,
55
+ ]
56
+ );
57
+ $pageType->save();
58
+
59
+ $this->container->get('content_translation.manager')->setEnabled(
60
+ 'node',
61
+ 'page',
62
+ TRUE
63
+ );
64
+
65
+ FieldStorageConfig::create([
66
+ 'field_name' => 'body',
67
+ 'entity_type' => 'node',
68
+ 'type' => 'text_long',
69
+ 'cardinality' => 1,
70
+ ])->save();
71
+
72
+ FieldConfig::create([
73
+ 'field_name' => 'body',
74
+ 'entity_type' => 'node',
75
+ 'bundle' => 'page',
76
+ 'label' => 'Body',
77
+ ])->save();
78
+
79
+ $this->setupDirectableSchema('../../../packages/@amazeelabs/silverback-gutenberg/drupal/silverback_gutenberg/tests/graphql');
80
+ }
81
+
82
+ function testEditorBlockResolution() {
83
+
84
+ File::create([
85
+ 'uri' => $this->getTestFiles('image')[0]->uri,
86
+ ])->save();
87
+ $media = Media::create([
88
+ 'bundle' => 'image',
89
+ 'name' => 'Screaming hairy armadillo',
90
+ 'field_media_image' => [
91
+ [
92
+ 'target_id' => 1,
93
+ 'alt' => 'Screaming hairy armadillo',
94
+ 'title' => 'Screaming hairy armadillo',
95
+ ],
96
+ ],
97
+ ]);
98
+ $media->addTranslation('de', [
99
+ 'bundle' => 'image',
100
+ 'name' => 'Screaming hairy armadillo',
101
+ 'field_media_image' => [
102
+ [
103
+ 'target_id' => 1,
104
+ 'alt' => 'Screaming hairy armadillo DE',
105
+ 'title' => 'Screaming hairy armadillo DE',
106
+ ],
107
+ ],
108
+ ])->save();
109
+ $media->save();
110
+
111
+ $serializer = new BlockSerializer();
112
+ $blocks = [
113
+ [
114
+ 'blockName' => 'core/paragraph',
115
+ 'innerContent' => ['<p>A test paragraph</p>'],
116
+ 'attrs' => [],
117
+ 'innerBlocks' => [],
118
+ ], [
119
+ 'blockName' => 'core/list',
120
+ 'innerContent' => ['<p>Another test paragraph</p>'],
121
+ 'attrs' => [],
122
+ 'innerBlocks' => [],
123
+ ],
124
+ [
125
+ 'blockName' => 'core/group',
126
+ 'attrs' => [],
127
+ 'innerContent' => [null, null, null],
128
+ 'innerBlocks' => [
129
+ [
130
+ 'blockName' => 'custom/figure',
131
+ 'innerContent' => [],
132
+ 'attrs' => [
133
+ 'caption' => 'This is the caption',
134
+ 'mediaEntityIds' => [$media->id()],
135
+ ],
136
+ 'innerBlocks' => [],
137
+ ],
138
+ [
139
+ 'blockName' => 'custom/figure',
140
+ 'innerContent' => [],
141
+ 'attrs' => [
142
+ 'caption' => 'This image does not exist',
143
+ 'mediaEntityIds' => ['666'],
144
+ ],
145
+ 'innerBlocks' => [],
146
+ ],
147
+ [
148
+ 'blockName' => 'custom/columns',
149
+ 'innerContent' => [null, null],
150
+ 'attrs' => [],
151
+ 'innerBlocks' => [
152
+ [
153
+ 'blockName' => 'core/paragraph',
154
+ 'innerContent' => ['<p>First column</p>'],
155
+ 'attrs' => [],
156
+ 'innerBlocks' => [],
157
+ ],
158
+ [
159
+ 'blockName' => 'core/paragraph',
160
+ 'innerContent' => ['<p>Second column</p>'],
161
+ 'attrs' => [],
162
+ 'innerBlocks' => [],
163
+ ],
164
+ ],
165
+ ]
166
+ ],
167
+ ]];
168
+
169
+ $html = $serializer->serialize_blocks($blocks);
170
+
171
+ $node = Node::create([
172
+ 'type' => 'page',
173
+ 'title' => 'Editor test',
174
+ 'body' => $html,
175
+ ]);
176
+ $node->addTranslation('de',
177
+ [
178
+ 'type' => 'page',
179
+ 'title' => 'Editor test DE',
180
+ 'body' => $html,
181
+ ]
182
+ )->save();
183
+ $node->save();
184
+
185
+ $query = $this->getQueryFromFile('editor.gql');
186
+ $metadata = $this->defaultCacheMetaData();
187
+ $metadata->addCacheContexts(['static:language:de']);
188
+ $metadata->addCacheTags(['node:1', 'media:1', 'media_list']);
189
+ $this->assertResults($query, ['id' => '1:en'], [
190
+ 'en' => [
191
+ 'title' => 'Editor test',
192
+ 'content' => [
193
+ [
194
+ '__typename' => 'Text',
195
+ 'content' => '<p>A test paragraph</p><p>Another test paragraph</p>',
196
+ ],
197
+ [
198
+ '__typename' => 'Figure',
199
+ 'caption' => 'This is the caption',
200
+ 'image' => [
201
+ 'alt' => 'Screaming hairy armadillo'
202
+ ],
203
+ 'imageAlt' => 'Screaming hairy armadillo'
204
+ ],
205
+ [
206
+ '__typename' => 'Figure',
207
+ 'caption' => 'This image does not exist',
208
+ 'image' => NULL,
209
+ 'imageAlt' => NULL,
210
+ ],
211
+ [
212
+ '__typename' => 'Columns',
213
+ 'columns' => [
214
+ [
215
+ '__typename' => 'Text',
216
+ ],
217
+ ],
218
+ ],
219
+ ],
220
+ ],
221
+ 'de' => [
222
+ 'title' => 'Editor test DE',
223
+ 'content' => [
224
+ [
225
+ '__typename' => 'Text',
226
+ 'content' => '<p>A test paragraph</p><p>Another test paragraph</p>',
227
+ ],
228
+ [
229
+ '__typename' => 'Figure',
230
+ 'caption' => 'This is the caption',
231
+ 'image' => [
232
+ 'alt' => 'Screaming hairy armadillo DE'
233
+ ],
234
+ 'imageAlt' => 'Screaming hairy armadillo DE'
235
+ ],
236
+ [
237
+ '__typename' => 'Figure',
238
+ 'caption' => 'This image does not exist',
239
+ 'image' => NULL,
240
+ 'imageAlt' => NULL,
241
+ ],
242
+ [
243
+ '__typename' => 'Columns',
244
+ 'columns' => [
245
+ [
246
+ '__typename' => 'Text',
247
+ ],
248
+ ],
249
+ ],
250
+ ],
251
+ ],
252
+ ], $metadata);
253
+ }
254
+
255
+ }
@@ -0,0 +1,133 @@
1
+ <?php
2
+
3
+ namespace Drupal\Tests\silverback_gutenberg\Kernel;
4
+
5
+ use Drupal\KernelTests\KernelTestBase;
6
+ use Drupal\node\Entity\Node;
7
+ use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
8
+ use Drupal\user\Entity\User;
9
+
10
+ /**
11
+ * @requires module entity_usage
12
+ */
13
+ class GutenbergLinkedContentEUTrackTest extends KernelTestBase {
14
+ use ContentTypeCreationTrait;
15
+
16
+ protected static $modules = [
17
+ 'node',
18
+ 'path_alias',
19
+ 'system',
20
+ 'user',
21
+ 'field',
22
+ 'text',
23
+ 'silverback_gutenberg',
24
+ 'entity_usage'
25
+ ];
26
+
27
+ /* @var \Drupal\entity_usage\EntityUsageTrackInterface */
28
+ protected $linkedContentPlugin;
29
+
30
+ /* @var \Drupal\node\NodeInterface[] */
31
+ protected $targetNodes = [];
32
+
33
+ /* @var \Drupal\node\NodeInterface[]*/
34
+ protected $targetUsers = [];
35
+
36
+ /**
37
+ * {@inheritDoc}
38
+ */
39
+ protected function setUp(): void {
40
+ parent::setUp();
41
+
42
+ $this->installEntitySchema('node');
43
+ $this->installEntitySchema('user');
44
+ $this->installEntitySchema('path_alias');
45
+ $this->installConfig('node');
46
+
47
+ $this->createContentType([
48
+ 'type' => 'page',
49
+ 'name' => 'Basic page'
50
+ ]);
51
+
52
+ $this->targetNodes[0] = Node::create([
53
+ 'title' => 'EU Test node1',
54
+ 'type' => 'page',
55
+ ]);
56
+ $this->targetNodes[0]->save();
57
+ $this->targetNodes[1] = Node::create([
58
+ 'title' => 'EU Test node2',
59
+ 'type' => 'page',
60
+ ]);
61
+ $this->targetNodes[1]->save();
62
+
63
+ $this->targetUsers[0] = User::create([
64
+ 'name' => 'user1',
65
+ ]);
66
+ $this->targetUsers[0]->save();
67
+
68
+ $this->linkedContentPlugin = \Drupal::service('plugin.manager.entity_usage.track')->createInstance('gutenberg_linked_content');
69
+ }
70
+
71
+ /**
72
+ * @covers \Drupal\silverback_gutenberg\Plugin\EntityUsage\Track\GutenbergLinkedContent::getTargetEntities
73
+ */
74
+ public function testGetTargetEntities() {
75
+ $fieldItem = Node::create([
76
+ 'title' => 'Source node',
77
+ 'type' => 'page',
78
+ 'body' => '<div>This is a text with <span>no internally referenced</span> <a href="https://www.example.com">content</a>.</div>',
79
+ ])->get('body')[0];
80
+ $targetEntities = $this->linkedContentPlugin->getTargetEntities($fieldItem);
81
+ $expected = [];
82
+ $this->assertEquals($expected, $targetEntities);
83
+
84
+ $fieldItem = Node::create([
85
+ 'title' => 'Source node',
86
+ 'type' => 'page',
87
+ 'body' => '<div>This is a simple <a href="/" data-id="' . $this->targetNodes[0]->uuid() .'" data-entity-type="node">link</a></div>',
88
+ ])->get('body')[0];
89
+ $targetEntities = $this->linkedContentPlugin->getTargetEntities($fieldItem);
90
+ $expected = ['node|' . $this->targetNodes[0]->id()];
91
+ $this->assertEquals($expected, $targetEntities);
92
+
93
+ $fieldItem = Node::create([
94
+ 'title' => 'Source node',
95
+ 'type' => 'page',
96
+ 'body' => '<div>This is a <p>node <a href="/" data-id="' . $this->targetNodes[0]->uuid() . '" data-entity-type="node">reference</a>, another node <a href="/" data-id="' . $this->targetNodes[1]->uuid() . '" data-entity-type="node">reference</a></p>,<p>then another duplicated node <a href="/" data-id="' . $this->targetNodes[0]->uuid() . '" data-entity-type="node">reference</a></p> and one user <a href="/" data-id="' . $this->targetUsers[0]->uuid() . '" data-entity-type="user">reference</a></div>',
97
+ ])->get('body')[0];
98
+ $targetEntities = $this->linkedContentPlugin->getTargetEntities($fieldItem);
99
+ $expected = [
100
+ 'node|' . $this->targetNodes[0]->id(),
101
+ 'node|' . $this->targetNodes[1]->id(),
102
+ 'user|' . $this->targetNodes[0]->id()
103
+ ];
104
+ $this->assertEquals($expected, $targetEntities);
105
+
106
+ $fieldItem = Node::create([
107
+ 'title' => 'Source node',
108
+ 'type' => 'page',
109
+ 'body' => '<div>This is a node <a href="/" data-id="' . $this->targetNodes[0]->uuid() . '">reference</a> without the data-entity-type attribute</div>',
110
+ ])->get('body')[0];
111
+ $targetEntities = $this->linkedContentPlugin->getTargetEntities($fieldItem);
112
+ $expected = ['node|' . $this->targetNodes[0]->id()];
113
+ $this->assertEquals($expected, $targetEntities);
114
+
115
+ $fieldItem = Node::create([
116
+ 'title' => 'Source node',
117
+ 'type' => 'page',
118
+ 'body' => '<div>This is a node <a href="/" data-entity-type="node">reference</a> without the data-id attribute</div>',
119
+ ])->get('body')[0];
120
+ $targetEntities = $this->linkedContentPlugin->getTargetEntities($fieldItem);
121
+ $expected = [];
122
+ $this->assertEquals($expected, $targetEntities);
123
+
124
+ $fieldItem = Node::create([
125
+ 'title' => 'Source node',
126
+ 'type' => 'page',
127
+ 'body' => '<div>This is an invalid node <a href="/" data-id="invalid-uuid" data-entity-type="node">reference</a></div>',
128
+ ])->get('body')[0];
129
+ $targetEntities = $this->linkedContentPlugin->getTargetEntities($fieldItem);
130
+ $expected = [];
131
+ $this->assertEquals($expected, $targetEntities);
132
+ }
133
+ }
@@ -0,0 +1,225 @@
1
+ <?php
2
+
3
+ namespace Drupal\Tests\silverback_gutenberg\Kernel;
4
+
5
+ use Drupal\KernelTests\KernelTestBase;
6
+ use Drupal\node\Entity\Node;
7
+ use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
8
+ use Drupal\user\Entity\User;
9
+
10
+ /**
11
+ * @requires module entity_usage
12
+ */
13
+ class GutenbergReferencedContentEUTrackTest extends KernelTestBase {
14
+ use ContentTypeCreationTrait;
15
+
16
+ protected static $modules = [
17
+ 'node',
18
+ 'path_alias',
19
+ 'system',
20
+ 'user',
21
+ 'field',
22
+ 'text',
23
+ 'silverback_gutenberg',
24
+ 'entity_usage'
25
+ ];
26
+
27
+ /* @var \Drupal\entity_usage\EntityUsageTrackInterface */
28
+ protected $referencedContentPlugin;
29
+
30
+ /* @var \Drupal\node\NodeInterface[] */
31
+ protected $targetNodes = [];
32
+
33
+ /* @var \Drupal\node\NodeInterface[]*/
34
+ protected $targetUsers = [];
35
+
36
+ /**
37
+ * {@inheritDoc}
38
+ */
39
+ protected function setUp(): void {
40
+ parent::setUp();
41
+
42
+ $this->installEntitySchema('node');
43
+ $this->installEntitySchema('user');
44
+ $this->installEntitySchema('path_alias');
45
+ $this->installConfig('node');
46
+
47
+ $this->createContentType([
48
+ 'type' => 'page',
49
+ 'name' => 'Basic page'
50
+ ]);
51
+
52
+ $this->targetNodes[0] = Node::create([
53
+ 'title' => 'EU Test node1',
54
+ 'type' => 'page',
55
+ ]);
56
+ $this->targetNodes[0]->save();
57
+ $this->targetNodes[1] = Node::create([
58
+ 'title' => 'EU Test node2',
59
+ 'type' => 'page',
60
+ ]);
61
+ $this->targetNodes[1]->save();
62
+ $this->targetNodes[2] = Node::create([
63
+ 'title' => 'EU Test node3',
64
+ 'type' => 'page',
65
+ ]);
66
+ $this->targetNodes[2]->save();
67
+
68
+ $this->targetUsers[0] = User::create([
69
+ 'name' => 'user1',
70
+ ]);
71
+ $this->targetUsers[0]->save();
72
+
73
+ $this->referencedContentPlugin = \Drupal::service('plugin.manager.entity_usage.track')->createInstance('gutenberg_referenced_content');
74
+ }
75
+
76
+ /**
77
+ * @covers \Drupal\silverback_gutenberg\Plugin\EntityUsage\Track\GutenbergReferencedContent::getTargetEntities
78
+ */
79
+ public function testGetTargetEntities() {
80
+ // Content with no references.
81
+ $fieldItem = Node::create([
82
+ 'title' => 'Source node',
83
+ 'type' => 'page',
84
+ 'body' => '<!-- wp:custom/root --><main class="wp-block-custom-root"><!-- wp:paragraph --><p>Content with no internal references</p><!-- /wp:paragraph --></main><!-- /wp:custom/root -->',
85
+ ])->get('body')[0];
86
+ $targetEntities = $this->referencedContentPlugin->getTargetEntities($fieldItem);
87
+ $expected = [];
88
+ $this->assertEquals($expected, $targetEntities);
89
+
90
+ // One single root block, with a node reference.
91
+ $fieldItem = Node::create([
92
+ 'title' => 'Source node',
93
+ 'type' => 'page',
94
+ 'body' => '<!-- wp:custom/root --><main class="wp-block-custom-root"><!-- wp:custom/link-item {"title":"test","uuid":"' . $this->targetNodes[0]->uuid() . '","entityType":"node"} -->
95
+ <!-- /wp:custom/link-item --></main><!-- /wp:custom/root -->',
96
+ ])->get('body')[0];
97
+ $targetEntities = $this->referencedContentPlugin->getTargetEntities($fieldItem);
98
+ $expected = ['node|' . $this->targetNodes[0]->id()];
99
+ $this->assertEquals($expected, $targetEntities);
100
+
101
+ // One single root block with an array of node uuids.
102
+ $fieldItem = Node::create([
103
+ 'title' => 'Source node',
104
+ 'type' => 'page',
105
+ 'body' => '<!-- wp:custom/root --><main class="wp-block-custom-root"><!-- wp:custom/link-item {"title":"test","uuid":["' . $this->targetNodes[0]->uuid() . '","' . $this->targetNodes[1]->uuid() . '"],"entityType":"node"} -->
106
+ <!-- /wp:custom/link-item --></main><!-- /wp:custom/root -->',
107
+ ])->get('body')[0];
108
+ $targetEntities = $this->referencedContentPlugin->getTargetEntities($fieldItem);
109
+ $expected = [
110
+ 'node|' . $this->targetNodes[0]->id(),
111
+ 'node|' . $this->targetNodes[1]->id()
112
+ ];
113
+ $this->assertEquals($expected, $targetEntities);
114
+
115
+ // More root blocks with the same entity type.
116
+ $fieldItem = Node::create([
117
+ 'title' => 'Source node',
118
+ 'type' => 'page',
119
+ 'body' => '<!-- wp:custom/root --><main class="wp-block-custom-root">
120
+ <!-- wp:custom/link-item {"title":"test","uuid":"' . $this->targetNodes[0]->uuid() . '","entityType":"node"} --><!-- /wp:custom/link-item -->
121
+ <!-- wp:custom/link-item {"title":"one more test","uuid":"' . $this->targetNodes[1]->uuid() . '","entityType":"node"} --><!-- /wp:custom/link-item -->
122
+ </main><!-- /wp:custom/root -->',
123
+ ])->get('body')[0];
124
+ $targetEntities = $this->referencedContentPlugin->getTargetEntities($fieldItem);
125
+ $expected = [
126
+ 'node|' . $this->targetNodes[0]->id(),
127
+ 'node|' . $this->targetNodes[1]->id()
128
+ ];
129
+ $this->assertEquals($expected, $targetEntities);
130
+
131
+ // Multiple root block with inner blocks, referencing one entity type.
132
+ $fieldItem = Node::create([
133
+ 'title' => 'Source node',
134
+ 'type' => 'page',
135
+ 'body' => '<!-- wp:custom/root --><main class="wp-block-custom-root">
136
+ <!-- wp:custom/link-item {"title":"test","uuid":"' . $this->targetNodes[0]->uuid() . '","entityType":"node"} -->
137
+ <!-- wp:custom/link-item-inner {"title":"inner","uuid":"' . $this->targetNodes[1]->uuid() . '","entityType":"node"} --><!-- /wp:custom/link-item-inner -->
138
+ <!-- wp:custom/link-item-inner {"title":"inner","uuid":"' . $this->targetNodes[0]->uuid() . '","entityType":"node"} --><!-- /wp:custom/link-item-inner -->
139
+ <!-- /wp:custom/link-item -->
140
+ <!-- wp:custom/link-item {"title":"last","uuid":"' . $this->targetNodes[2]->uuid() . '","entityType":"node"} --><!-- /wp:custom/link-item -->
141
+ </main><!-- /wp:custom/root -->',
142
+ ])->get('body')[0];
143
+ $targetEntities = $this->referencedContentPlugin->getTargetEntities($fieldItem);
144
+ $expected = [
145
+ 'node|' . $this->targetNodes[0]->id(),
146
+ 'node|' . $this->targetNodes[1]->id(),
147
+ 'node|' . $this->targetNodes[2]->id()
148
+ ];
149
+ $this->assertEquals($expected, $targetEntities);
150
+
151
+ // Multiple blocks referencing different entity types.
152
+ $fieldItem = Node::create([
153
+ 'title' => 'Source node',
154
+ 'type' => 'page',
155
+ 'body' => '<!-- wp:custom/root --><main class="wp-block-custom-root">
156
+ <!-- wp:custom/link-item {"title":"test","uuid":"' . $this->targetUsers[0]->uuid() . '","entityType":"user"} -->
157
+ <!-- wp:custom/link-item-inner {"title":"inner","uuid":"' . $this->targetNodes[0]->uuid() . '","entityType":"node"} --><!-- /wp:custom/link-item-inner -->
158
+ <!-- wp:custom/link-item-inner {"title":"inner","uuid":"' . $this->targetNodes[1]->uuid() . '","entityType":"node"} --><!-- /wp:custom/link-item-inner -->
159
+ <!-- /wp:custom/link-item -->
160
+ </main><!-- /wp:custom/root -->',
161
+ ])->get('body')[0];
162
+ $targetEntities = $this->referencedContentPlugin->getTargetEntities($fieldItem);
163
+ $expected = [
164
+ 'user|' . $this->targetUsers[0]->id(),
165
+ 'node|' . $this->targetNodes[0]->id(),
166
+ 'node|' . $this->targetNodes[1]->id()
167
+ ];
168
+ $this->assertEquals($expected, $targetEntities);
169
+
170
+ // Multiple blocks, one of them not having the entityType attribute set.
171
+ $fieldItem = Node::create([
172
+ 'title' => 'Source node',
173
+ 'type' => 'page',
174
+ 'body' => '<!-- wp:custom/root --><main class="wp-block-custom-root">
175
+ <!-- wp:custom/link-item {"title":"test","uuid":"' . $this->targetNodes[0]->uuid() . '"} -->
176
+ <!-- wp:custom/link-item-inner {"title":"inner","uuid":"' . $this->targetNodes[1]->uuid() . '","entityType":"node"} --><!-- /wp:custom/link-item-inner -->
177
+ <!-- wp:custom/link-item-inner {"title":"inner","uuid":"' . $this->targetNodes[2]->uuid() . '","entityType":"node"} --><!-- /wp:custom/link-item-inner -->
178
+ <!-- /wp:custom/link-item -->
179
+ </main><!-- /wp:custom/root -->',
180
+ ])->get('body')[0];
181
+ $targetEntities = $this->referencedContentPlugin->getTargetEntities($fieldItem);
182
+ $expected = [
183
+ 'node|' . $this->targetUsers[0]->id(),
184
+ 'node|' . $this->targetNodes[1]->id(),
185
+ 'node|' . $this->targetNodes[2]->id()
186
+ ];
187
+ $this->assertEquals($expected, $targetEntities);
188
+
189
+ // Multiple blocks, one of them not having the uuid attribute set.
190
+ $fieldItem = Node::create([
191
+ 'title' => 'Source node',
192
+ 'type' => 'page',
193
+ 'body' => '<!-- wp:custom/root --><main class="wp-block-custom-root">
194
+ <!-- wp:custom/link-item {"title":"test","entityType":"node"} -->
195
+ <!-- wp:custom/link-item-inner {"title":"inner","uuid":"' . $this->targetNodes[0]->uuid() . '","entityType":"node"} --><!-- /wp:custom/link-item-inner -->
196
+ <!-- wp:custom/link-item-inner {"title":"inner","uuid":"' . $this->targetUsers[0]->uuid() . '","entityType":"user"} --><!-- /wp:custom/link-item-inner -->
197
+ <!-- /wp:custom/link-item -->
198
+ </main><!-- /wp:custom/root -->',
199
+ ])->get('body')[0];
200
+ $targetEntities = $this->referencedContentPlugin->getTargetEntities($fieldItem);
201
+ $expected = [
202
+ 'node|' . $this->targetNodes[0]->id(),
203
+ 'user|' . $this->targetUsers[0]->id(),
204
+ ];
205
+ $this->assertEquals($expected, $targetEntities);
206
+
207
+ // Invalid uuids.
208
+ $fieldItem = Node::create([
209
+ 'title' => 'Source node',
210
+ 'type' => 'page',
211
+ 'body' => '<!-- wp:custom/root --><main class="wp-block-custom-root">
212
+ <!-- wp:custom/link-item {"title":"test","uuid":"' . $this->targetNodes[0]->uuid() . '","entityType":"node"} -->
213
+ <!-- wp:custom/link-item-inner {"title":"inner","uuid":"invalid","entityType":"node"} --><!-- /wp:custom/link-item-inner -->
214
+ <!-- wp:custom/link-item-inner {"title":"inner","uuid":"' . $this->targetUsers[0]->uuid() . '","entityType":"user"} --><!-- /wp:custom/link-item-inner -->
215
+ <!-- /wp:custom/link-item -->
216
+ </main><!-- /wp:custom/root -->',
217
+ ])->get('body')[0];
218
+ $targetEntities = $this->referencedContentPlugin->getTargetEntities($fieldItem);
219
+ $expected = [
220
+ 'node|' . $this->targetNodes[0]->id(),
221
+ 'user|' . $this->targetUsers[0]->id(),
222
+ ];
223
+ $this->assertEquals($expected, $targetEntities);
224
+ }
225
+ }