@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,284 @@
1
+ <?php
2
+
3
+ namespace Drupal\Tests\silverback_gutenberg\Kernel;
4
+
5
+ use Drupal\Core\DependencyInjection\ContainerBuilder;
6
+ use Drupal\Core\StreamWrapper\PublicStream;
7
+ use Drupal\language\Entity\ConfigurableLanguage;
8
+ use Drupal\media\Entity\Media;
9
+ use Drupal\node\Entity\Node;
10
+ use Drupal\node\Entity\NodeType;
11
+ use Drupal\silverback_gutenberg\LinkProcessor;
12
+ use Drupal\Tests\media\Kernel\MediaKernelTestBase;
13
+ use Drupal\user\Entity\User;
14
+
15
+ class LinkProcessorTest extends MediaKernelTestBase {
16
+
17
+ protected static $modules = [
18
+ 'path',
19
+ 'path_alias',
20
+ 'node',
21
+ 'user',
22
+ 'system',
23
+ 'language',
24
+ 'content_translation',
25
+ 'silverback_gutenberg',
26
+ ];
27
+
28
+ protected function setUp(): void {
29
+ parent::setUp();
30
+
31
+ $this->installEntitySchema('node');
32
+ $this->installEntitySchema('user');
33
+ $this->installEntitySchema('path_alias');
34
+
35
+ // Workaround for https://www.drupal.org/project/drupal/issues/3056234
36
+ User::create([
37
+ 'name' => '',
38
+ 'uid' => 0,
39
+ ])->save();
40
+
41
+ $this->installSchema('node', ['node_access']);
42
+
43
+ $node_type = NodeType::create(['type' => 'page']);
44
+ $node_type->save();
45
+
46
+ $this->installConfig(['language']);
47
+ ConfigurableLanguage::createFromLangcode('de')->save();
48
+
49
+ $this->config('silverback_gutenberg.settings')
50
+ ->set('local_hosts', [
51
+ 'this.site',
52
+ 'www.this.site',
53
+ ])
54
+ ->save();
55
+
56
+ // Let LanguageServiceProvider register its path processors.
57
+ drupal_flush_all_caches();
58
+ }
59
+
60
+ public function register(ContainerBuilder $container) {
61
+ parent::register($container);
62
+
63
+ // Restore AliasPathProcessor tags which are removed in the parent method.
64
+ $container->getDefinition('path_alias.path_processor')
65
+ ->addTag('path_processor_inbound', ['priority' => 100])
66
+ ->addTag('path_processor_outbound', ['priority' => 300]);
67
+ }
68
+
69
+ public function testProcessUrl() {
70
+ $languages = \Drupal::languageManager()->getLanguages();
71
+
72
+ $withoutAlias = Node::create([
73
+ 'title' => 'English without alias',
74
+ 'type' => 'page',
75
+ ]);
76
+ $withoutAlias->save();
77
+ $translation = $withoutAlias->addTranslation('de', $withoutAlias->toArray());
78
+ $translation->save();
79
+
80
+ $withAlias = Node::create([
81
+ 'title' => 'English with alias',
82
+ 'type' => 'page',
83
+ 'path' => ['alias' => '/english'],
84
+ ]);
85
+ $withAlias->save();
86
+ $translation = $withAlias->addTranslation('de', $withAlias->toArray());
87
+ $translation->get('path')->alias = '/german';
88
+ $translation->save();
89
+
90
+ $media = Media::create([
91
+ 'bundle' => $this->testMediaType->id(),
92
+ 'name' => 'Unnamed',
93
+ 'field_media_test' => 'Whatever.',
94
+ ]);
95
+ $media->save();
96
+
97
+ /** @var \Drupal\silverback_gutenberg\LinkProcessor $linkProcessor */
98
+ $linkProcessor = \Drupal::service(LinkProcessor::class);
99
+
100
+ $currentHost = \Drupal::request()->getHttpHost();
101
+ $currentPort = \Drupal::request()->getPort();
102
+ $standaloneMediaUrl = $this->config('media.settings')->get('standalone_url');
103
+ $mediaCanonicalSuffix = $standaloneMediaUrl ? '' : '/edit';
104
+ $cases = [
105
+ 'absolute' => [
106
+ 'inbound' => [
107
+ 'https://example.com/foo' => 'https://example.com/foo',
108
+ 'https://example.com/de/foo' => 'https://example.com/de/foo',
109
+ ],
110
+ 'outbound' => [
111
+ 'https://example.com/foo' => [
112
+ 'en' => 'https://example.com/foo',
113
+ 'de' => 'https://example.com/foo',
114
+ ],
115
+ 'https://example.com/de/foo' => [
116
+ 'en' => 'https://example.com/de/foo',
117
+ 'de' => 'https://example.com/de/foo',
118
+ ],
119
+ ],
120
+ ],
121
+ 'without alias' => [
122
+ 'inbound' => [
123
+ '/node/' . $withoutAlias->id() => '/node/' . $withoutAlias->uuid(),
124
+ '/de/node/' . $withoutAlias->id() => '/node/' . $withoutAlias->uuid(),
125
+ ],
126
+ 'outbound' => [
127
+ '/node/' . $withoutAlias->id() => [
128
+ 'en' => '/node/' . $withoutAlias->id(),
129
+ 'de' => '/de/node/' . $withoutAlias->id(),
130
+ ],
131
+ '/node/' . $withoutAlias->uuid() => [
132
+ 'en' => '/node/' . $withoutAlias->id(),
133
+ 'de' => '/de/node/' . $withoutAlias->id(),
134
+ ],
135
+ ],
136
+ ],
137
+ 'with alias' => [
138
+ 'inbound' => [
139
+ '/node/' . $withAlias->id() => '/node/' . $withAlias->uuid(),
140
+ '/de/node/' . $withAlias->id() => '/node/' . $withAlias->uuid(),
141
+ '/english' => '/node/' . $withAlias->uuid(),
142
+ '/de/german' => '/node/' . $withAlias->uuid(),
143
+ "https://{$currentHost}:{$currentPort}/node/{$withAlias->id()}" => '/node/' . $withAlias->uuid(),
144
+ 'http://this.site/english' => '/node/' . $withAlias->uuid(),
145
+ "https://www.this.site/de/german" => '/node/' . $withAlias->uuid(),
146
+ ],
147
+ 'outbound' => [
148
+ '/node/' . $withAlias->id() => [
149
+ 'en' => '/english',
150
+ 'de' => '/de/german',
151
+ ],
152
+ '/node/' . $withAlias->uuid() => [
153
+ 'en' => '/english',
154
+ 'de' => '/de/german',
155
+ ],
156
+ "https://{$currentHost}:{$currentPort}/node/{$withAlias->id()}" => [
157
+ 'en' => '/english',
158
+ 'de' => '/de/german',
159
+ ],
160
+ "http://this.site/de/node/{$withAlias->id()}" => [
161
+ 'en' => '/english',
162
+ 'de' => '/de/german',
163
+ ],
164
+ // In case if we somehow got an absolute URL in database, we just turn
165
+ // it to relative.
166
+ "https://www.this.site/de/german" => [
167
+ 'en' => '/english',
168
+ 'de' => '/de/german',
169
+ ],
170
+ ],
171
+ ],
172
+ 'media' => [
173
+ 'inbound' => [
174
+ '/media/' . $media->id() . $mediaCanonicalSuffix => '/media/' . $media->uuid() . $mediaCanonicalSuffix,
175
+ '/de/media/' . $media->id() . $mediaCanonicalSuffix => '/media/' . $media->uuid() . $mediaCanonicalSuffix,
176
+ ],
177
+ 'outbound' => [
178
+ '/media/' . $media->id() . $mediaCanonicalSuffix => [
179
+ 'en' => '/media/' . $media->id() . $mediaCanonicalSuffix,
180
+ 'de' => '/de/media/' . $media->id() . $mediaCanonicalSuffix,
181
+ ],
182
+ '/media/' . $media->uuid() . $mediaCanonicalSuffix => [
183
+ 'en' => '/media/' . $media->id() . $mediaCanonicalSuffix,
184
+ 'de' => '/de/media/' . $media->id() . $mediaCanonicalSuffix,
185
+ ],
186
+ ],
187
+ ],
188
+ 'unrouted' => [
189
+ 'inbound' => [
190
+ '/unrouted-path' => '/unrouted-path',
191
+ '/de/unrouted-path' => '/de/unrouted-path',
192
+ '/unrouted-path with spaces' => '/unrouted-path with spaces',
193
+ ],
194
+ 'outbound' => [
195
+ '/unrouted-path' => [
196
+ 'en' => '/unrouted-path',
197
+ 'de' => '/unrouted-path',
198
+ ],
199
+ '/de/unrouted-path' => [
200
+ 'en' => '/de/unrouted-path',
201
+ 'de' => '/de/unrouted-path',
202
+ ],
203
+ '/unrouted-path with spaces' => [
204
+ 'en' => '/unrouted-path with spaces',
205
+ 'de' => '/unrouted-path with spaces',
206
+ ],
207
+ ],
208
+ ],
209
+ 'mailto' => [
210
+ 'inbound' => [
211
+ 'mailto:someone@example.site' => 'mailto:someone@example.site',
212
+ ],
213
+ 'outbound' => [
214
+ 'mailto:someone@example.site' => [
215
+ 'en' => 'mailto:someone@example.site',
216
+ 'de' => 'mailto:someone@example.site',
217
+ ],
218
+ ],
219
+ ],
220
+ 'corrupted' => [
221
+ 'inbound' => [
222
+ '///C:/en/surfaceinfrastructure' => '///C:/en/surfaceinfrastructure',
223
+ ],
224
+ 'outbound' => [
225
+ '///C:/en/surfaceinfrastructure' => [
226
+ 'en' => '///C:/en/surfaceinfrastructure',
227
+ ],
228
+ ],
229
+ ],
230
+ ];
231
+
232
+ foreach ($cases as $name => $directions) {
233
+ foreach ($directions as $direction => $samples) {
234
+ foreach ($samples as $original => $target) {
235
+ if ($direction === 'inbound') {
236
+ $url = $linkProcessor->processUrl($original, 'inbound');
237
+ $this->assertEquals($target, $url, "Case name: {$name}, direction: {$direction}, original: {$original}");
238
+ }
239
+ else {
240
+ foreach ($target as $langcode => $processed) {
241
+ $url = $linkProcessor->processUrl($original, 'outbound', $languages[$langcode]);
242
+ $this->assertEquals($processed, $url, "Case name: {$name}, direction: {$direction}, langcode: {$langcode}, original: {$original}");
243
+ }
244
+ }
245
+ }
246
+ }
247
+ }
248
+ }
249
+
250
+ /**
251
+ * @dataProvider urlFlagsProvider
252
+ */
253
+ public function testUrlFlags(string $url, bool $hasSchemeOrHost, bool $linksToCurrentHost, bool $isAsset) {
254
+ /** @var \Drupal\silverback_gutenberg\LinkProcessor $linkProcessor */
255
+ $linkProcessor = \Drupal::service(LinkProcessor::class);
256
+ $url = str_replace('**BASE**', \Drupal::request()->getSchemeAndHttpHost(), $url);
257
+ $url = str_replace('**HOST**', \Drupal::request()->getHttpHost(), $url);
258
+ $url = str_replace('**FILES**', PublicStream::basePath(), $url);
259
+
260
+ $this->assertEquals($hasSchemeOrHost, $linkProcessor->hasSchemeOrHost($url), "$url hasSchemeOrHost");
261
+ $this->assertEquals($linksToCurrentHost, $linkProcessor->linksToCurrentHost($url), "$url linksToCurrentHost");
262
+ $this->assertEquals($isAsset, $linkProcessor->isAsset($url), "$url isAsset");
263
+ }
264
+
265
+ public function urlFlagsProvider(): array {
266
+ return [
267
+ ['/foo', false, true, false],
268
+ ['https://foo.bar/baz', true, false, false],
269
+ ['http://this.site/foo', true, true, false],
270
+ ['https://www.this.site/foo', true, true, false],
271
+ ['//foo/bar', true, false, false],
272
+ ['//**HOST**/bar', true, true, false],
273
+ ['**BASE**', true, true, false],
274
+ ['**BASE**/foo', true, true, false],
275
+ ['**BASE**/**FILES**/foo.bar', true, true, true],
276
+ ['/**FILES**/foo.bar', false, true, true],
277
+ ['/system/files/foo.bar', false, true, true],
278
+ ['**BASE**/system/files/foo.bar', true, true, true],
279
+ ['**BASE**/fr/system/files/foo.bar', true, true, true],
280
+ ['//**HOST**/system/files/foo.bar', true, true, true],
281
+ ];
282
+ }
283
+
284
+ }
@@ -0,0 +1,174 @@
1
+ <?php
2
+
3
+ namespace Drupal\Tests\silverback_gutenberg\Kernel;
4
+
5
+ use Drupal\KernelTests\KernelTestBase;
6
+ use Drupal\language\Entity\ConfigurableLanguage;
7
+ use Drupal\media\Entity\Media;
8
+ use Drupal\node\Entity\Node;
9
+ use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
10
+ use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
11
+ use Drupal\Tests\silverback_gutenberg\Traits\SampleAssetTrait;
12
+
13
+ class MediaNormalizerTest extends KernelTestBase {
14
+ use ContentTypeCreationTrait;
15
+ use MediaTypeCreationTrait;
16
+ use SampleAssetTrait;
17
+ protected $strictConfigSchema = FALSE;
18
+
19
+ protected static $modules = [
20
+ 'file',
21
+ 'image',
22
+ 'media',
23
+ 'media_test_source',
24
+ 'field',
25
+ 'block_content',
26
+ 'path',
27
+ 'filter',
28
+ 'path_alias',
29
+ 'node',
30
+ 'user',
31
+ 'system',
32
+ 'language',
33
+ 'editor',
34
+ 'content_translation',
35
+ 'gutenberg',
36
+ 'views',
37
+ 'text',
38
+ 'silverback_gutenberg',
39
+ 'language',
40
+ 'content_translation',
41
+ 'default_content',
42
+ 'serialization',
43
+ 'hal',
44
+ ];
45
+
46
+ protected function setUp(): void {
47
+ parent::setUp();
48
+ $this->installSchema('system', 'sequences');
49
+ $this->installSchema('node', 'node_access');
50
+ $this->installSchema('file', 'file_usage');
51
+ $this->installEntitySchema('node');
52
+ $this->installEntitySchema('file');
53
+ $this->installEntitySchema('user');
54
+ $this->installEntitySchema('block_content');
55
+ $this->installEntitySchema('path_alias');
56
+ $this->installEntitySchema('media');
57
+ $this->installConfig('block_content');
58
+ $this->installConfig('filter');
59
+ $this->installConfig('node');
60
+ $this->installConfig('file');
61
+ $this->installConfig('image');
62
+ $this->installConfig('media');
63
+ $this->installConfig(['gutenberg']);
64
+ $this->createContentType([
65
+ 'type' => 'page',
66
+ 'name' => 'Basic page'
67
+ ]);
68
+ $this->createMediaType('test', ['id' => 'test']);
69
+
70
+ $config = \Drupal::service('config.factory')->getEditable('gutenberg.settings');
71
+ $config->set('page_enable_full', true);
72
+ $config->save();
73
+
74
+ $this->installConfig(['language']);
75
+ ConfigurableLanguage::createFromLangcode('de')->save();
76
+
77
+ // Let LanguageServiceProvider register its path processors.
78
+ drupal_flush_all_caches();
79
+ }
80
+
81
+ public function testNormalization() {
82
+ [$source, $target] = $this->loadSample('media');
83
+ $image1 = Media::create(['bundle' => 'test']);
84
+ $image1->save();
85
+
86
+ $image2 = Media::create(['bundle' => 'test']);
87
+ $image2->save();
88
+
89
+ $target = str_replace(
90
+ ['["abc"]', '["def"]'],
91
+ ['["'. $image1->uuid().'"]', '["'.$image2->uuid().'"]'],
92
+ $target
93
+ );
94
+
95
+ $node = Node::create([
96
+ 'type' => 'page',
97
+ 'title' => 'Test',
98
+ 'body' => $source,
99
+ ]);
100
+ $node->save();
101
+ $node->addTranslation('de', [
102
+ 'body' => $source,
103
+ ]);
104
+
105
+ /** @var \Drupal\default_content\Normalizer\ContentEntityNormalizer $normalizer */
106
+ $normalizer = $this->container->get('default_content.content_entity_normalizer');
107
+ $this->assertTrue(_gutenberg_is_gutenberg_enabled($node));
108
+ $result = $normalizer->normalize($node);
109
+ $this->assertSameHtml($target, $result['default']['body'][0]['value']);
110
+ $this->assertSameHtml($target, $result['translations']['de']['body'][0]['value']);
111
+ }
112
+
113
+ public function testDependencies() {
114
+ [$source] = $this->loadSample('media');
115
+ $image1 = Media::create(['bundle' => 'test']);
116
+ $image1->save();
117
+
118
+ $image2 = Media::create(['bundle' => 'test']);
119
+ $image2->save();
120
+
121
+ $node = Node::create([
122
+ 'type' => 'page',
123
+ 'title' => 'Test',
124
+ 'body' => $source,
125
+ ]);
126
+ $node->save();
127
+
128
+ /** @var \Drupal\default_content\Normalizer\ContentEntityNormalizer $normalizer */
129
+ $normalizer = $this->container->get('default_content.content_entity_normalizer');
130
+ $this->assertTrue(_gutenberg_is_gutenberg_enabled($node));
131
+ $result = $normalizer->normalize($node);
132
+
133
+ $depends = [];
134
+ $depends[$image1->uuid()] = 'media';
135
+ $depends[$image2->uuid()] = 'media';
136
+ $this->assertArrayHasKey('depends', $result['_meta']);
137
+ $this->assertEquals($depends, $result['_meta']['depends']);
138
+ }
139
+
140
+ public function testDenormalization() {
141
+ [$source] = $this->loadSample('media');
142
+ $image1 = Media::create(['bundle' => 'test']);
143
+ $image1->save();
144
+
145
+ $image2 = Media::create(['bundle' => 'test']);
146
+ $image2->save();
147
+
148
+ $node = Node::create([
149
+ 'type' => 'page',
150
+ 'title' => 'Test',
151
+ 'body' => $source,
152
+ ]);
153
+ $node->save();
154
+ $node->addTranslation('de', [
155
+ 'title' => 'Test DE',
156
+ 'body' => $source,
157
+ ]);
158
+ $node->save();
159
+
160
+ /** @var \Drupal\default_content\Normalizer\ContentEntityNormalizer $normalizer */
161
+ $normalizer = $this->container->get('default_content.content_entity_normalizer');
162
+ $this->assertTrue(_gutenberg_is_gutenberg_enabled($node));
163
+ $result = $normalizer->normalize($node);
164
+ /** @var \Drupal\node\NodeInterface $denormalized */
165
+ $denormalized = $normalizer->denormalize($result);
166
+ $this->assertSameHtml($source, $denormalized->body->value);
167
+ $this->assertSameHtml($source, $denormalized->getTranslation('de')->body->value);
168
+ }
169
+
170
+ protected function assertSameHtml(string $expected, string $actual) {
171
+ $normalize = fn (string $html) => trim(preg_replace('/>\s+</', '><', $html));
172
+ $this->assertEquals($normalize($expected), $normalize($actual));
173
+ }
174
+ }
@@ -0,0 +1,15 @@
1
+ <?php
2
+
3
+ namespace Drupal\Tests\silverback_gutenberg\Traits;
4
+
5
+ trait SampleAssetTrait {
6
+
7
+ protected function loadSample(string $name) {
8
+ $path = __DIR__ . '/../assets/' . $name;
9
+ $source = file_get_contents($path . '/source.html');
10
+ $target = file_get_contents($path . '/target.html');
11
+ $data = json_decode(file_get_contents($path . '/data.json'), TRUE);
12
+ return [$source, $target, $data];
13
+ }
14
+
15
+ }
@@ -0,0 +1,27 @@
1
+ <?php
2
+
3
+ namespace Drupal\Tests\silverback_gutenberg\Unit;
4
+
5
+ use Drupal\gutenberg\Parser\BlockParser;
6
+ use Drupal\silverback_gutenberg\BlockSerializer;
7
+ use Drupal\Tests\silverback_gutenberg\Traits\SampleAssetTrait;
8
+ use Drupal\Tests\UnitTestCase;
9
+
10
+ class BlockSerializerTest extends UnitTestCase {
11
+
12
+ use SampleAssetTrait;
13
+
14
+ public function testSerialization() {
15
+ [$source] = $this->loadSample('media');
16
+
17
+ $serializer = (new BlockSerializer());
18
+ $blocks = (new BlockParser())->parse($source);
19
+
20
+ $expected = (simplexml_load_string('<div>' .$source . '</div>'));
21
+
22
+ $actual = (simplexml_load_string('<div>' . $serializer->serialize_blocks($blocks) . '</div>'));
23
+
24
+ $this->assertEquals($expected->saveXML(), $actual->saveXML());
25
+ }
26
+
27
+ }