@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,1537 @@
1
+ <?php
2
+
3
+ namespace Drupal\Tests\silverback_gutenberg\Unit;
4
+
5
+ use Drupal\Core\DependencyInjection\ContainerBuilder;
6
+ use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergCardinalityValidatorInterface;
7
+ use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergCardinalityValidatorTrait;
8
+ use Drupal\Tests\UnitTestCase;
9
+
10
+ /**
11
+ * Block cardinality validator test.
12
+ *
13
+ * Edge cases
14
+ * - Empty validation
15
+ * - No validation: 0 as minimum, but maximum as unlimited
16
+ *
17
+ * Limit by
18
+ * - minimum and maximum
19
+ * - minimum = maximum (exact match)
20
+ * - 0 as minimum, but maximum is set
21
+ * - has minimum, but no maximum is unlimited
22
+ *
23
+ * Variations
24
+ * - with specific / any block type
25
+ * - with single and multiple children
26
+ */
27
+ class BlockValidatorCardinalityTest extends UnitTestCase {
28
+
29
+ use GutenbergCardinalityValidatorTrait;
30
+
31
+ public function setUp(): void {
32
+ parent::setUp();
33
+ $container = new ContainerBuilder();
34
+ \Drupal::setContainer($container);
35
+ $container->set('string_translation', self::getStringTranslationStub());
36
+ }
37
+
38
+ public function testEmptyCardinality() {
39
+ $expectedChildren = [];
40
+ $block = [
41
+ 'blockName' => 'core/column',
42
+ 'innerBlocks' => [
43
+ [
44
+ 'blockName' => 'core/paragraph',
45
+ ],
46
+ ],
47
+ ];
48
+ $this->assertEquals(
49
+ $this->validateCardinality($block, $expectedChildren),
50
+ [
51
+ 'is_valid' => TRUE,
52
+ 'message' => '',
53
+ ]
54
+ );
55
+ }
56
+
57
+ public function testNoLimitation() {
58
+ $expectedChildren = [
59
+ [
60
+ 'blockName' => 'core/paragraph',
61
+ 'blockLabel' => t('Paragraph'),
62
+ 'min' => 0,
63
+ 'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED,
64
+ ],
65
+ ];
66
+ $block = [
67
+ 'blockName' => 'core/column',
68
+ 'innerBlocks' => [
69
+ [
70
+ 'blockName' => 'core/paragraph',
71
+ ],
72
+ ],
73
+ ];
74
+ $this->assertEquals(
75
+ $this->validateCardinality($block, $expectedChildren),
76
+ [
77
+ 'is_valid' => TRUE,
78
+ 'message' => '',
79
+ ]
80
+ );
81
+ }
82
+
83
+ public function testSpecificBlockTypeSingleMinimumAndMaximum() {
84
+ $expectedChildren = [
85
+ [
86
+ 'blockName' => 'core/paragraph',
87
+ 'blockLabel' => t('Paragraph'),
88
+ 'min' => 1,
89
+ 'max' => 2,
90
+ ],
91
+ ];
92
+
93
+ $validBlock1 = [
94
+ 'blockName' => 'core/column',
95
+ 'innerBlocks' => [
96
+ [
97
+ 'blockName' => 'core/paragraph',
98
+ ],
99
+ ],
100
+ ];
101
+ $validBlock2 = [
102
+ 'blockName' => 'core/column',
103
+ 'innerBlocks' => [
104
+ [
105
+ 'blockName' => 'core/paragraph',
106
+ ],
107
+ [
108
+ 'blockName' => 'core/paragraph',
109
+ ],
110
+ ],
111
+ ];
112
+ $validBlock3 = [
113
+ 'blockName' => 'core/column',
114
+ 'innerBlocks' => [
115
+ [
116
+ 'blockName' => 'core/paragraph',
117
+ ],
118
+ [
119
+ 'blockName' => 'core/list',
120
+ ],
121
+ ],
122
+ ];
123
+ $invalidBlock1 = [
124
+ 'blockName' => 'core/column',
125
+ 'innerBlocks' => [
126
+ [
127
+ 'blockName' => 'core/gallery',
128
+ ],
129
+ [
130
+ 'blockName' => 'core/list',
131
+ ],
132
+ ],
133
+ ];
134
+ $invalidBlock2 = [
135
+ 'blockName' => 'core/column',
136
+ 'innerBlocks' => [
137
+ [
138
+ 'blockName' => 'core/list',
139
+ ],
140
+ ],
141
+ ];
142
+ $invalidBlock3 = [
143
+ 'blockName' => 'core/column',
144
+ 'innerBlocks' => [
145
+ [
146
+ 'blockName' => 'core/paragraph',
147
+ ],
148
+ [
149
+ 'blockName' => 'core/paragraph',
150
+ ],
151
+ [
152
+ 'blockName' => 'core/paragraph',
153
+ ],
154
+ ],
155
+ ];
156
+ $invalidBlock4 = [
157
+ 'blockName' => 'core/column',
158
+ 'innerBlocks' => [],
159
+ ];
160
+
161
+ $this->assertEquals(
162
+ $this->validateCardinality($validBlock1, $expectedChildren),
163
+ [
164
+ 'is_valid' => TRUE,
165
+ 'message' => '',
166
+ ]
167
+ );
168
+ $this->assertEquals(
169
+ $this->validateCardinality($validBlock2, $expectedChildren),
170
+ [
171
+ 'is_valid' => TRUE,
172
+ 'message' => '',
173
+ ]
174
+ );
175
+ $this->assertEquals(
176
+ $this->validateCardinality($validBlock3, $expectedChildren),
177
+ [
178
+ 'is_valid' => TRUE,
179
+ 'message' => '',
180
+ ]
181
+ );
182
+
183
+ $messageParams = [
184
+ '%label' => $expectedChildren[0]['blockLabel'],
185
+ '@min' => $expectedChildren[0]['min'],
186
+ '@max' => $expectedChildren[0]['max'],
187
+ ];
188
+ $result = t('%label: there should be between @min and @max blocks.', $messageParams);
189
+ $this->assertEquals(
190
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
191
+ [
192
+ 'is_valid' => FALSE,
193
+ 'message' => $result,
194
+ ]
195
+ );
196
+ $this->assertEquals(
197
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
198
+ [
199
+ 'is_valid' => FALSE,
200
+ 'message' => $result,
201
+ ]
202
+ );
203
+ $this->assertEquals(
204
+ $this->validateCardinality($invalidBlock3, $expectedChildren),
205
+ [
206
+ 'is_valid' => FALSE,
207
+ 'message' => '<em class="placeholder">Paragraph</em>: at most 2 blocks are allowed.',
208
+ ]
209
+ );
210
+
211
+ $this->assertEquals(
212
+ $this->validateCardinality($invalidBlock4, $expectedChildren),
213
+ [
214
+ 'is_valid' => FALSE,
215
+ 'message' => 'Required blocks are missing. <em class="placeholder">Paragraph</em>: there should be between 1 and 2 blocks.',
216
+ ]
217
+ );
218
+ }
219
+
220
+ public function testSpecificBlockTypeMultipleMinimumAndMaximum() {
221
+ $expectedChildren = [
222
+ [
223
+ 'blockName' => 'core/paragraph',
224
+ 'blockLabel' => t('Paragraph'),
225
+ 'min' => 1,
226
+ 'max' => 2,
227
+ ],
228
+ [
229
+ 'blockName' => 'core/list',
230
+ 'blockLabel' => t('List'),
231
+ 'min' => 1,
232
+ 'max' => 2,
233
+ ],
234
+ ];
235
+
236
+ $validBlock1 = [
237
+ 'blockName' => 'core/column',
238
+ 'innerBlocks' => [
239
+ [
240
+ 'blockName' => 'core/paragraph',
241
+ ],
242
+ [
243
+ 'blockName' => 'core/list',
244
+ ],
245
+ ],
246
+ ];
247
+ $validBlock2 = [
248
+ 'blockName' => 'core/column',
249
+ 'innerBlocks' => [
250
+ [
251
+ 'blockName' => 'core/paragraph',
252
+ ],
253
+ [
254
+ 'blockName' => 'core/list',
255
+ ],
256
+ [
257
+ 'blockName' => 'core/paragraph',
258
+ ],
259
+ [
260
+ 'blockName' => 'core/list',
261
+ ],
262
+ ],
263
+ ];
264
+ $invalidBlock1 = [
265
+ 'blockName' => 'core/column',
266
+ 'innerBlocks' => [
267
+ [
268
+ 'blockName' => 'core/gallery',
269
+ ],
270
+ [
271
+ 'blockName' => 'core/list',
272
+ ],
273
+ ],
274
+ ];
275
+ $invalidBlock2 = [
276
+ 'blockName' => 'core/column',
277
+ 'innerBlocks' => [
278
+ [
279
+ 'blockName' => 'core/paragraph',
280
+ ],
281
+ ],
282
+ ];
283
+ $invalidBlock3 = [
284
+ 'blockName' => 'core/column',
285
+ 'innerBlocks' => [
286
+ [
287
+ 'blockName' => 'core/paragraph',
288
+ ],
289
+ [
290
+ 'blockName' => 'core/image',
291
+ ],
292
+ ],
293
+ ];
294
+ $invalidBlock4 = [
295
+ 'blockName' => 'core/column',
296
+ 'innerBlocks' => [
297
+ [
298
+ 'blockName' => 'core/paragraph',
299
+ ],
300
+ [
301
+ 'blockName' => 'core/paragraph',
302
+ ],
303
+ [
304
+ 'blockName' => 'core/paragraph',
305
+ ],
306
+ [
307
+ 'blockName' => 'core/list',
308
+ ],
309
+ [
310
+ 'blockName' => 'core/list',
311
+ ],
312
+ [
313
+ 'blockName' => 'core/list',
314
+ ],
315
+ ],
316
+ ];
317
+ $invalidBlock5 = [
318
+ 'blockName' => 'core/column',
319
+ 'innerBlocks' => [],
320
+ ];
321
+
322
+ $this->assertEquals(
323
+ $this->validateCardinality($validBlock1, $expectedChildren),
324
+ [
325
+ 'is_valid' => TRUE,
326
+ 'message' => '',
327
+ ]
328
+ );
329
+ $this->assertEquals(
330
+ $this->validateCardinality($validBlock2, $expectedChildren),
331
+ [
332
+ 'is_valid' => TRUE,
333
+ 'message' => '',
334
+ ]
335
+ );
336
+
337
+ $messageParams = [
338
+ '%label' => $expectedChildren[0]['blockLabel'],
339
+ '@min' => $expectedChildren[0]['min'],
340
+ '@max' => $expectedChildren[0]['max'],
341
+ ];
342
+ $result = t('%label: there should be between @min and @max blocks.', $messageParams);
343
+ $this->assertEquals(
344
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
345
+ [
346
+ 'is_valid' => FALSE,
347
+ 'message' => $result,
348
+ ]
349
+ );
350
+ $messageParams = [
351
+ '%label' => $expectedChildren[1]['blockLabel'],
352
+ '@min' => $expectedChildren[1]['min'],
353
+ '@max' => $expectedChildren[1]['max'],
354
+ ];
355
+ $result = t('%label: there should be between @min and @max blocks.', $messageParams);
356
+ $this->assertEquals(
357
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
358
+ [
359
+ 'is_valid' => FALSE,
360
+ 'message' => $result,
361
+ ]
362
+ );
363
+ $this->assertEquals(
364
+ $this->validateCardinality($invalidBlock3, $expectedChildren),
365
+ [
366
+ 'is_valid' => FALSE,
367
+ 'message' => $result,
368
+ ]
369
+ );
370
+ $this->assertEquals(
371
+ $this->validateCardinality($invalidBlock4, $expectedChildren),
372
+ [
373
+ 'is_valid' => FALSE,
374
+ 'message' => '<em class="placeholder">Paragraph</em>: at most 2 blocks are allowed.',
375
+ // @todo improve: error message could mention both block types on the same validation.
376
+ //'message' => '<em class="placeholder">Paragraph</em>: at most 2 blocks are allowed. <em class="placeholder">List</em>: at most 2 blocks are allowed.',
377
+ ]
378
+ );
379
+ $this->assertEquals(
380
+ $this->validateCardinality($invalidBlock5, $expectedChildren),
381
+ [
382
+ 'is_valid' => FALSE,
383
+ 'message' => 'Required blocks are missing. <em class="placeholder">Paragraph</em>: there should be between 1 and 2 blocks. <em class="placeholder">List</em>: there should be between 1 and 2 blocks.',
384
+ ]
385
+ );
386
+ }
387
+
388
+ public function testAnyBlockTypeMinimumAndMaximum() {
389
+ $expectedChildren = [
390
+ 'validationType' => GutenbergCardinalityValidatorInterface::CARDINALITY_ANY,
391
+ 'min' => 1,
392
+ 'max' => 2,
393
+ ];
394
+
395
+ $validBlock1 = [
396
+ 'blockName' => 'core/column',
397
+ 'innerBlocks' => [
398
+ [
399
+ 'blockName' => 'core/paragraph',
400
+ ],
401
+ [
402
+ 'blockName' => 'core/list',
403
+ ],
404
+ ],
405
+ ];
406
+ $validBlock2 = [
407
+ 'blockName' => 'core/column',
408
+ 'innerBlocks' => [
409
+ [
410
+ 'blockName' => 'core/paragraph',
411
+ ],
412
+ [
413
+ 'blockName' => 'core/list',
414
+ ],
415
+ ],
416
+ ];
417
+ $invalidBlock1 = [
418
+ 'blockName' => 'core/column',
419
+ 'innerBlocks' => [
420
+ [
421
+ 'blockName' => 'core/paragraph',
422
+ ],
423
+ [
424
+ 'blockName' => 'core/list',
425
+ ],
426
+ [
427
+ 'blockName' => 'core/list',
428
+ ],
429
+ ],
430
+ ];
431
+
432
+ $this->assertEquals(
433
+ $this->validateCardinality($validBlock1, $expectedChildren),
434
+ [
435
+ 'is_valid' => TRUE,
436
+ 'message' => '',
437
+ ]
438
+ );
439
+ $this->assertEquals(
440
+ $this->validateCardinality($validBlock2, $expectedChildren),
441
+ [
442
+ 'is_valid' => TRUE,
443
+ 'message' => '',
444
+ ]
445
+ );
446
+
447
+ $this->assertEquals(
448
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
449
+ [
450
+ 'is_valid' => FALSE,
451
+ 'message' => 'At most 2 blocks are allowed.',
452
+ ]
453
+ );
454
+ }
455
+
456
+ public function testSpecificBlockTypeSingleExactMatch() {
457
+ $expectedChildren = [
458
+ [
459
+ 'blockName' => 'core/paragraph',
460
+ 'blockLabel' => t('Paragraph'),
461
+ 'min' => 2,
462
+ 'max' => 2,
463
+ ],
464
+ ];
465
+
466
+ $validBlock = [
467
+ 'blockName' => 'core/column',
468
+ 'innerBlocks' => [
469
+ [
470
+ 'blockName' => 'core/paragraph',
471
+ ],
472
+ [
473
+ 'blockName' => 'core/paragraph',
474
+ ],
475
+ ],
476
+ ];
477
+ $invalidBlock1 = [
478
+ 'blockName' => 'core/column',
479
+ 'innerBlocks' => [
480
+ [
481
+ 'blockName' => 'core/paragraph',
482
+ ],
483
+ ],
484
+ ];
485
+ $invalidBlock2 = [
486
+ 'blockName' => 'core/column',
487
+ 'innerBlocks' => [
488
+ [
489
+ 'blockName' => 'core/paragraph',
490
+ ],
491
+ [
492
+ 'blockName' => 'core/list',
493
+ ],
494
+ ],
495
+ ];
496
+ $invalidBlock3 = [
497
+ 'blockName' => 'core/column',
498
+ 'innerBlocks' => [
499
+ [
500
+ 'blockName' => 'core/gallery',
501
+ ],
502
+ [
503
+ 'blockName' => 'core/list',
504
+ ],
505
+ ],
506
+ ];
507
+ $invalidBlock4 = [
508
+ 'blockName' => 'core/column',
509
+ 'innerBlocks' => [
510
+ [
511
+ 'blockName' => 'core/paragraph',
512
+ ],
513
+ [
514
+ 'blockName' => 'core/paragraph',
515
+ ],
516
+ [
517
+ 'blockName' => 'core/paragraph',
518
+ ],
519
+ ],
520
+ ];
521
+
522
+ $this->assertEquals(
523
+ $this->validateCardinality($validBlock, $expectedChildren),
524
+ [
525
+ 'is_valid' => TRUE,
526
+ 'message' => '',
527
+ ]
528
+ );
529
+
530
+ $this->assertEquals(
531
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
532
+ [
533
+ 'is_valid' => FALSE,
534
+ 'message' => '<em class="placeholder">Paragraph</em>: at least 2 blocks are required.',
535
+ ]
536
+ );
537
+ $this->assertEquals(
538
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
539
+ [
540
+ 'is_valid' => FALSE,
541
+ 'message' => '<em class="placeholder">Paragraph</em>: at least 2 blocks are required.',
542
+ ]
543
+ );
544
+ $this->assertEquals(
545
+ $this->validateCardinality($invalidBlock3, $expectedChildren),
546
+ [
547
+ 'is_valid' => FALSE,
548
+ 'message' => '<em class="placeholder">Paragraph</em>: there should be exactly 2 blocks.',
549
+ ]
550
+ );
551
+ $this->assertEquals(
552
+ $this->validateCardinality($invalidBlock4, $expectedChildren),
553
+ [
554
+ 'is_valid' => FALSE,
555
+ 'message' => '<em class="placeholder">Paragraph</em>: at most 2 blocks are allowed.',
556
+ ]
557
+ );
558
+ }
559
+
560
+ public function testSpecificBlockTypeMultipleExactMatch() {
561
+ $expectedChildren = [
562
+ [
563
+ 'blockName' => 'core/paragraph',
564
+ 'blockLabel' => t('Paragraph'),
565
+ 'min' => 2,
566
+ 'max' => 2,
567
+ ],
568
+ [
569
+ 'blockName' => 'core/list',
570
+ 'blockLabel' => t('List'),
571
+ 'min' => 1,
572
+ 'max' => 1,
573
+ ],
574
+ ];
575
+
576
+ $validBlock = [
577
+ 'blockName' => 'core/column',
578
+ 'innerBlocks' => [
579
+ [
580
+ 'blockName' => 'core/paragraph',
581
+ ],
582
+ [
583
+ 'blockName' => 'core/paragraph',
584
+ ],
585
+ [
586
+ 'blockName' => 'core/list',
587
+ ],
588
+ ],
589
+ ];
590
+ $invalidBlock1 = [
591
+ 'blockName' => 'core/column',
592
+ 'innerBlocks' => [
593
+ [
594
+ 'blockName' => 'core/paragraph',
595
+ ],
596
+ ],
597
+ ];
598
+ $invalidBlock2 = [
599
+ 'blockName' => 'core/column',
600
+ 'innerBlocks' => [
601
+ [
602
+ 'blockName' => 'core/paragraph',
603
+ ],
604
+ [
605
+ 'blockName' => 'core/list',
606
+ ],
607
+ ],
608
+ ];
609
+ $invalidBlock3 = [
610
+ 'blockName' => 'core/column',
611
+ 'innerBlocks' => [
612
+ [
613
+ 'blockName' => 'core/gallery',
614
+ ],
615
+ [
616
+ 'blockName' => 'core/list',
617
+ ],
618
+ ],
619
+ ];
620
+ $invalidBlock4 = [
621
+ 'blockName' => 'core/column',
622
+ 'innerBlocks' => [
623
+ [
624
+ 'blockName' => 'core/paragraph',
625
+ ],
626
+ [
627
+ 'blockName' => 'core/paragraph',
628
+ ],
629
+ [
630
+ 'blockName' => 'core/paragraph',
631
+ ],
632
+ [
633
+ 'blockName' => 'core/list',
634
+ ],
635
+ ],
636
+ ];
637
+ $invalidBlock5 = [
638
+ 'blockName' => 'core/column',
639
+ 'innerBlocks' => [
640
+ [
641
+ 'blockName' => 'core/paragraph',
642
+ ],
643
+ [
644
+ 'blockName' => 'core/paragraph',
645
+ ],
646
+ ],
647
+ ];
648
+
649
+ $this->assertEquals(
650
+ $this->validateCardinality($validBlock, $expectedChildren),
651
+ [
652
+ 'is_valid' => TRUE,
653
+ 'message' => '',
654
+ ]
655
+ );
656
+
657
+ // @todo improve: error message could mention both block types on the same validation.
658
+ $this->assertEquals(
659
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
660
+ [
661
+ 'is_valid' => FALSE,
662
+ 'message' => '<em class="placeholder">Paragraph</em>: at least 2 blocks are required.',
663
+ ]
664
+ );
665
+ $this->assertEquals(
666
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
667
+ [
668
+ 'is_valid' => FALSE,
669
+ 'message' => '<em class="placeholder">Paragraph</em>: at least 2 blocks are required.',
670
+ ]
671
+ );
672
+ $this->assertEquals(
673
+ $this->validateCardinality($invalidBlock3, $expectedChildren),
674
+ [
675
+ 'is_valid' => FALSE,
676
+ 'message' => '<em class="placeholder">Paragraph</em>: there should be exactly 2 blocks.',
677
+ ]
678
+ );
679
+ $this->assertEquals(
680
+ $this->validateCardinality($invalidBlock4, $expectedChildren),
681
+ [
682
+ 'is_valid' => FALSE,
683
+ 'message' => '<em class="placeholder">Paragraph</em>: at most 2 blocks are allowed.',
684
+ ]
685
+ );
686
+ $this->assertEquals(
687
+ $this->validateCardinality($invalidBlock5, $expectedChildren),
688
+ [
689
+ 'is_valid' => FALSE,
690
+ 'message' => '<em class="placeholder">List</em>: there should be exactly 1 block.',
691
+ ]
692
+ );
693
+ }
694
+
695
+ public function testAnyBlockTypeExactMatch() {
696
+ $expectedChildren = [
697
+ 'validationType' => GutenbergCardinalityValidatorInterface::CARDINALITY_ANY,
698
+ 'min' => 2,
699
+ 'max' => 2,
700
+ ];
701
+
702
+ $validBlock1 = [
703
+ 'blockName' => 'core/column',
704
+ 'innerBlocks' => [
705
+ [
706
+ 'blockName' => 'core/paragraph',
707
+ ],
708
+ [
709
+ 'blockName' => 'core/list',
710
+ ],
711
+ ],
712
+ ];
713
+ $validBlock2 = [
714
+ 'blockName' => 'core/column',
715
+ 'innerBlocks' => [
716
+ [
717
+ 'blockName' => 'core/paragraph',
718
+ ],
719
+ [
720
+ 'blockName' => 'core/paragraph',
721
+ ],
722
+ ],
723
+ ];
724
+ $invalidBlock1 = [
725
+ 'blockName' => 'core/column',
726
+ 'innerBlocks' => [
727
+ [
728
+ 'blockName' => 'core/paragraph',
729
+ ],
730
+ ],
731
+ ];
732
+ $invalidBlock2 = [
733
+ 'blockName' => 'core/column',
734
+ 'innerBlocks' => [
735
+ [
736
+ 'blockName' => 'core/paragraph',
737
+ ],
738
+ [
739
+ 'blockName' => 'core/list',
740
+ ],
741
+ [
742
+ 'blockName' => 'core/paragraph',
743
+ ],
744
+ ],
745
+ ];
746
+ $invalidBlock3 = [
747
+ 'blockName' => 'core/column',
748
+ 'innerBlocks' => [],
749
+ ];
750
+
751
+ $this->assertEquals(
752
+ $this->validateCardinality($validBlock1, $expectedChildren),
753
+ [
754
+ 'is_valid' => TRUE,
755
+ 'message' => '',
756
+ ]
757
+ );
758
+ $this->assertEquals(
759
+ $this->validateCardinality($validBlock2, $expectedChildren),
760
+ [
761
+ 'is_valid' => TRUE,
762
+ 'message' => '',
763
+ ]
764
+ );
765
+
766
+ $this->assertEquals(
767
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
768
+ [
769
+ 'is_valid' => FALSE,
770
+ 'message' => 'At least 2 blocks are required.',
771
+ ]
772
+ );
773
+ $this->assertEquals(
774
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
775
+ [
776
+ 'is_valid' => FALSE,
777
+ 'message' => 'At most 2 blocks are allowed.',
778
+ ]
779
+ );
780
+ $this->assertEquals(
781
+ $this->validateCardinality($invalidBlock3, $expectedChildren),
782
+ [
783
+ 'is_valid' => FALSE,
784
+ 'message' => 'At least 2 blocks are required.',
785
+ ]
786
+ );
787
+ }
788
+
789
+ public function testSpecificBlockTypeSingleNoMinimumWithMaximum() {
790
+ $expectedChildren = [
791
+ [
792
+ 'blockName' => 'core/paragraph',
793
+ 'blockLabel' => t('Paragraph'),
794
+ 'min' => 0,
795
+ 'max' => 2,
796
+ ],
797
+ ];
798
+
799
+ $validBlock1 = [
800
+ 'blockName' => 'core/column',
801
+ 'innerBlocks' => [
802
+ [
803
+ 'blockName' => 'core/paragraph',
804
+ ],
805
+ ],
806
+ ];
807
+ $validBlock2 = [
808
+ 'blockName' => 'core/column',
809
+ 'innerBlocks' => [
810
+ [
811
+ 'blockName' => 'core/paragraph',
812
+ ],
813
+ [
814
+ 'blockName' => 'core/paragraph',
815
+ ],
816
+ ],
817
+ ];
818
+ $validBlock3 = [
819
+ 'blockName' => 'core/column',
820
+ 'innerBlocks' => [],
821
+ ];
822
+ $validBlock4 = [
823
+ 'blockName' => 'core/column',
824
+ 'innerBlocks' => [
825
+ [
826
+ 'blockName' => 'core/paragraph',
827
+ ],
828
+ [
829
+ 'blockName' => 'core/paragraph',
830
+ ],
831
+ [
832
+ 'blockName' => 'core/list',
833
+ ],
834
+ ],
835
+ ];
836
+ $invalidBlock1 = [
837
+ 'blockName' => 'core/column',
838
+ 'innerBlocks' => [
839
+ [
840
+ 'blockName' => 'core/paragraph',
841
+ ],
842
+ [
843
+ 'blockName' => 'core/paragraph',
844
+ ],
845
+ [
846
+ 'blockName' => 'core/paragraph',
847
+ ],
848
+ ],
849
+ ];
850
+ $invalidBlock2 = [
851
+ 'blockName' => 'core/column',
852
+ 'innerBlocks' => [
853
+ [
854
+ 'blockName' => 'core/paragraph',
855
+ ],
856
+ [
857
+ 'blockName' => 'core/paragraph',
858
+ ],
859
+ [
860
+ 'blockName' => 'core/paragraph',
861
+ ],
862
+ [
863
+ 'blockName' => 'core/list',
864
+ ],
865
+ ],
866
+ ];
867
+
868
+ $this->assertEquals(
869
+ $this->validateCardinality($validBlock1, $expectedChildren),
870
+ [
871
+ 'is_valid' => TRUE,
872
+ 'message' => '',
873
+ ]
874
+ );
875
+ $this->assertEquals(
876
+ $this->validateCardinality($validBlock2, $expectedChildren),
877
+ [
878
+ 'is_valid' => TRUE,
879
+ 'message' => '',
880
+ ]
881
+ );
882
+ $this->assertEquals(
883
+ $this->validateCardinality($validBlock3, $expectedChildren),
884
+ [
885
+ 'is_valid' => TRUE,
886
+ 'message' => '',
887
+ ]
888
+ );
889
+ $this->assertEquals(
890
+ $this->validateCardinality($validBlock4, $expectedChildren),
891
+ [
892
+ 'is_valid' => TRUE,
893
+ 'message' => '',
894
+ ]
895
+ );
896
+
897
+ $this->assertEquals(
898
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
899
+ [
900
+ 'is_valid' => FALSE,
901
+ 'message' => '<em class="placeholder">Paragraph</em>: at most 2 blocks are allowed.',
902
+ ]
903
+ );
904
+ $this->assertEquals(
905
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
906
+ [
907
+ 'is_valid' => FALSE,
908
+ 'message' => '<em class="placeholder">Paragraph</em>: at most 2 blocks are allowed.',
909
+ ]
910
+ );
911
+ }
912
+
913
+ public function testSpecificBlockTypeMultipleNoMinimumWithMaximum() {
914
+ $expectedChildren = [
915
+ [
916
+ 'blockName' => 'core/paragraph',
917
+ 'blockLabel' => t('Paragraph'),
918
+ 'min' => 0,
919
+ 'max' => 2,
920
+ ],
921
+ [
922
+ 'blockName' => 'core/list',
923
+ 'blockLabel' => t('List'),
924
+ 'min' => 0,
925
+ 'max' => 1,
926
+ ],
927
+ ];
928
+
929
+ $validBlock1 = [
930
+ 'blockName' => 'core/column',
931
+ 'innerBlocks' => [
932
+ [
933
+ 'blockName' => 'core/paragraph',
934
+ ],
935
+ ],
936
+ ];
937
+ $validBlock2 = [
938
+ 'blockName' => 'core/column',
939
+ 'innerBlocks' => [
940
+ [
941
+ 'blockName' => 'core/paragraph',
942
+ ],
943
+ [
944
+ 'blockName' => 'core/paragraph',
945
+ ],
946
+ [
947
+ 'blockName' => 'core/list',
948
+ ],
949
+ ],
950
+ ];
951
+ $validBlock3 = [
952
+ 'blockName' => 'core/column',
953
+ 'innerBlocks' => [],
954
+ ];
955
+ $validBlock4 = [
956
+ 'blockName' => 'core/column',
957
+ 'innerBlocks' => [
958
+ [
959
+ 'blockName' => 'core/paragraph',
960
+ ],
961
+ [
962
+ 'blockName' => 'core/list',
963
+ ],
964
+ ],
965
+ ];
966
+ $invalidBlock1 = [
967
+ 'blockName' => 'core/column',
968
+ 'innerBlocks' => [
969
+ [
970
+ 'blockName' => 'core/paragraph',
971
+ ],
972
+ [
973
+ 'blockName' => 'core/paragraph',
974
+ ],
975
+ [
976
+ 'blockName' => 'core/paragraph',
977
+ ],
978
+ ],
979
+ ];
980
+ $invalidBlock2 = [
981
+ 'blockName' => 'core/column',
982
+ 'innerBlocks' => [
983
+ [
984
+ 'blockName' => 'core/paragraph',
985
+ ],
986
+ [
987
+ 'blockName' => 'core/paragraph',
988
+ ],
989
+ [
990
+ 'blockName' => 'core/paragraph',
991
+ ],
992
+ [
993
+ 'blockName' => 'core/list',
994
+ ],
995
+ [
996
+ 'blockName' => 'core/list',
997
+ ],
998
+ ],
999
+ ];
1000
+
1001
+ $this->assertEquals(
1002
+ $this->validateCardinality($validBlock1, $expectedChildren),
1003
+ [
1004
+ 'is_valid' => TRUE,
1005
+ 'message' => '',
1006
+ ]
1007
+ );
1008
+ $this->assertEquals(
1009
+ $this->validateCardinality($validBlock2, $expectedChildren),
1010
+ [
1011
+ 'is_valid' => TRUE,
1012
+ 'message' => '',
1013
+ ]
1014
+ );
1015
+ $this->assertEquals(
1016
+ $this->validateCardinality($validBlock3, $expectedChildren),
1017
+ [
1018
+ 'is_valid' => TRUE,
1019
+ 'message' => '',
1020
+ ]
1021
+ );
1022
+ $this->assertEquals(
1023
+ $this->validateCardinality($validBlock4, $expectedChildren),
1024
+ [
1025
+ 'is_valid' => TRUE,
1026
+ 'message' => '',
1027
+ ]
1028
+ );
1029
+
1030
+ $this->assertEquals(
1031
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
1032
+ [
1033
+ 'is_valid' => FALSE,
1034
+ 'message' => '<em class="placeholder">Paragraph</em>: at most 2 blocks are allowed.',
1035
+ ]
1036
+ );
1037
+ $this->assertEquals(
1038
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
1039
+ [
1040
+ 'is_valid' => FALSE,
1041
+ 'message' => '<em class="placeholder">Paragraph</em>: at most 2 blocks are allowed.',
1042
+ ]
1043
+ );
1044
+ }
1045
+
1046
+ public function testAnyBlockTypeNoMinimumWithMaximum() {
1047
+ $expectedChildren = [
1048
+ 'validationType' => GutenbergCardinalityValidatorInterface::CARDINALITY_ANY,
1049
+ 'min' => 0,
1050
+ 'max' => 2,
1051
+ ];
1052
+
1053
+ $validBlock1 = [
1054
+ 'blockName' => 'core/column',
1055
+ 'innerBlocks' => [
1056
+ [
1057
+ 'blockName' => 'core/paragraph',
1058
+ ],
1059
+ [
1060
+ 'blockName' => 'core/list',
1061
+ ],
1062
+ ],
1063
+ ];
1064
+ $validBlock2 = [
1065
+ 'blockName' => 'core/column',
1066
+ 'innerBlocks' => [
1067
+ [
1068
+ 'blockName' => 'core/paragraph',
1069
+ ],
1070
+ [
1071
+ 'blockName' => 'core/paragraph',
1072
+ ],
1073
+ ],
1074
+ ];
1075
+ $validBlock3 = [
1076
+ 'blockName' => 'core/column',
1077
+ 'innerBlocks' => [
1078
+ [
1079
+ 'blockName' => 'core/paragraph',
1080
+ ],
1081
+ ],
1082
+ ];
1083
+ $validBlock4 = [
1084
+ 'blockName' => 'core/column',
1085
+ 'innerBlocks' => [],
1086
+ ];
1087
+ $invalidBlock1 = [
1088
+ 'blockName' => 'core/column',
1089
+ 'innerBlocks' => [
1090
+ [
1091
+ 'blockName' => 'core/paragraph',
1092
+ ],
1093
+ [
1094
+ 'blockName' => 'core/paragraph',
1095
+ ],
1096
+ [
1097
+ 'blockName' => 'core/paragraph',
1098
+ ],
1099
+ ],
1100
+ ];
1101
+ $invalidBlock2 = [
1102
+ 'blockName' => 'core/column',
1103
+ 'innerBlocks' => [
1104
+ [
1105
+ 'blockName' => 'core/paragraph',
1106
+ ],
1107
+ [
1108
+ 'blockName' => 'core/list',
1109
+ ],
1110
+ [
1111
+ 'blockName' => 'core/paragraph',
1112
+ ],
1113
+ ],
1114
+ ];
1115
+
1116
+ $this->assertEquals(
1117
+ $this->validateCardinality($validBlock1, $expectedChildren),
1118
+ [
1119
+ 'is_valid' => TRUE,
1120
+ 'message' => '',
1121
+ ]
1122
+ );
1123
+ $this->assertEquals(
1124
+ $this->validateCardinality($validBlock2, $expectedChildren),
1125
+ [
1126
+ 'is_valid' => TRUE,
1127
+ 'message' => '',
1128
+ ]
1129
+ );
1130
+ $this->assertEquals(
1131
+ $this->validateCardinality($validBlock3, $expectedChildren),
1132
+ [
1133
+ 'is_valid' => TRUE,
1134
+ 'message' => '',
1135
+ ]
1136
+ );
1137
+ $this->assertEquals(
1138
+ $this->validateCardinality($validBlock4, $expectedChildren),
1139
+ [
1140
+ 'is_valid' => TRUE,
1141
+ 'message' => '',
1142
+ ]
1143
+ );
1144
+
1145
+ $this->assertEquals(
1146
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
1147
+ [
1148
+ 'is_valid' => FALSE,
1149
+ 'message' => 'At most 2 blocks are allowed.',
1150
+ ]
1151
+ );
1152
+ $this->assertEquals(
1153
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
1154
+ [
1155
+ 'is_valid' => FALSE,
1156
+ 'message' => 'At most 2 blocks are allowed.',
1157
+ ]
1158
+ );
1159
+ }
1160
+
1161
+ public function testSpecificBlockTypeSingleMinimumWithNoMaximum() {
1162
+ $expectedChildren = [
1163
+ [
1164
+ 'blockName' => 'core/paragraph',
1165
+ 'blockLabel' => t('Paragraph'),
1166
+ 'min' => 2,
1167
+ 'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED,
1168
+ ],
1169
+ ];
1170
+
1171
+ $validBlock1 = [
1172
+ 'blockName' => 'core/column',
1173
+ 'innerBlocks' => [
1174
+ [
1175
+ 'blockName' => 'core/paragraph',
1176
+ ],
1177
+ [
1178
+ 'blockName' => 'core/paragraph',
1179
+ ],
1180
+ ],
1181
+ ];
1182
+ $validBlock2 = [
1183
+ 'blockName' => 'core/column',
1184
+ 'innerBlocks' => [
1185
+ [
1186
+ 'blockName' => 'core/paragraph',
1187
+ ],
1188
+ [
1189
+ 'blockName' => 'core/paragraph',
1190
+ ],
1191
+ [
1192
+ 'blockName' => 'core/paragraph',
1193
+ ],
1194
+ ],
1195
+ ];
1196
+ $validBlock3 = [
1197
+ 'blockName' => 'core/column',
1198
+ 'innerBlocks' => [
1199
+ [
1200
+ 'blockName' => 'core/paragraph',
1201
+ ],
1202
+ [
1203
+ 'blockName' => 'core/paragraph',
1204
+ ],
1205
+ [
1206
+ 'blockName' => 'core/list',
1207
+ ],
1208
+ [
1209
+ 'blockName' => 'core/list',
1210
+ ],
1211
+ ],
1212
+ ];
1213
+ $invalidBlock1 = [
1214
+ 'blockName' => 'core/column',
1215
+ 'innerBlocks' => [
1216
+ [
1217
+ 'blockName' => 'core/paragraph',
1218
+ ],
1219
+ ],
1220
+ ];
1221
+ $invalidBlock2 = [
1222
+ 'blockName' => 'core/column',
1223
+ 'innerBlocks' => [],
1224
+ ];
1225
+
1226
+ $this->assertEquals(
1227
+ $this->validateCardinality($validBlock1, $expectedChildren),
1228
+ [
1229
+ 'is_valid' => TRUE,
1230
+ 'message' => '',
1231
+ ]
1232
+ );
1233
+ $this->assertEquals(
1234
+ $this->validateCardinality($validBlock2, $expectedChildren),
1235
+ [
1236
+ 'is_valid' => TRUE,
1237
+ 'message' => '',
1238
+ ]
1239
+ );
1240
+ $this->assertEquals(
1241
+ $this->validateCardinality($validBlock3, $expectedChildren),
1242
+ [
1243
+ 'is_valid' => TRUE,
1244
+ 'message' => '',
1245
+ ]
1246
+ );
1247
+
1248
+ $this->assertEquals(
1249
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
1250
+ [
1251
+ 'is_valid' => FALSE,
1252
+ 'message' => '<em class="placeholder">Paragraph</em>: at least 2 blocks are required.',
1253
+ ]
1254
+ );
1255
+ $this->assertEquals(
1256
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
1257
+ [
1258
+ 'is_valid' => FALSE,
1259
+ 'message' => 'Required blocks are missing. <em class="placeholder">Paragraph</em>: there should be between 2 and unlimited blocks.',
1260
+ ]
1261
+ );
1262
+ }
1263
+
1264
+ public function testSpecificBlockTypeMultipleMinimumWithNoMaximum() {
1265
+ $expectedChildren = [
1266
+ [
1267
+ 'blockName' => 'core/paragraph',
1268
+ 'blockLabel' => t('Paragraph'),
1269
+ 'min' => 2,
1270
+ 'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED,
1271
+ ],
1272
+ [
1273
+ 'blockName' => 'core/list',
1274
+ 'blockLabel' => t('List'),
1275
+ 'min' => 1,
1276
+ 'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED,
1277
+ ],
1278
+ ];
1279
+
1280
+ $validBlock1 = [
1281
+ 'blockName' => 'core/column',
1282
+ 'innerBlocks' => [
1283
+ [
1284
+ 'blockName' => 'core/paragraph',
1285
+ ],
1286
+ [
1287
+ 'blockName' => 'core/paragraph',
1288
+ ],
1289
+ [
1290
+ 'blockName' => 'core/list',
1291
+ ],
1292
+ ],
1293
+ ];
1294
+ $validBlock2 = [
1295
+ 'blockName' => 'core/column',
1296
+ 'innerBlocks' => [
1297
+ [
1298
+ 'blockName' => 'core/paragraph',
1299
+ ],
1300
+ [
1301
+ 'blockName' => 'core/paragraph',
1302
+ ],
1303
+ [
1304
+ 'blockName' => 'core/paragraph',
1305
+ ],
1306
+ [
1307
+ 'blockName' => 'core/list',
1308
+ ],
1309
+ [
1310
+ 'blockName' => 'core/list',
1311
+ ],
1312
+ ],
1313
+ ];
1314
+ $validBlock3 = [
1315
+ 'blockName' => 'core/column',
1316
+ 'innerBlocks' => [
1317
+ [
1318
+ 'blockName' => 'core/paragraph',
1319
+ ],
1320
+ [
1321
+ 'blockName' => 'core/paragraph',
1322
+ ],
1323
+ [
1324
+ 'blockName' => 'core/list',
1325
+ ],
1326
+ [
1327
+ 'blockName' => 'core/list',
1328
+ ],
1329
+ ],
1330
+ ];
1331
+ $invalidBlock1 = [
1332
+ 'blockName' => 'core/column',
1333
+ 'innerBlocks' => [
1334
+ [
1335
+ 'blockName' => 'core/paragraph',
1336
+ ],
1337
+ ],
1338
+ ];
1339
+ $invalidBlock2 = [
1340
+ 'blockName' => 'core/column',
1341
+ 'innerBlocks' => [
1342
+ [
1343
+ 'blockName' => 'core/paragraph',
1344
+ ],
1345
+ [
1346
+ 'blockName' => 'core/list',
1347
+ ],
1348
+ ],
1349
+ ];
1350
+ $invalidBlock3 = [
1351
+ 'blockName' => 'core/column',
1352
+ 'innerBlocks' => [
1353
+ [
1354
+ 'blockName' => 'core/paragraph',
1355
+ ],
1356
+ [
1357
+ 'blockName' => 'core/list',
1358
+ ],
1359
+ [
1360
+ 'blockName' => 'core/list',
1361
+ ],
1362
+ ],
1363
+ ];
1364
+ $invalidBlock4 = [
1365
+ 'blockName' => 'core/column',
1366
+ 'innerBlocks' => [
1367
+ [
1368
+ 'blockName' => 'core/paragraph',
1369
+ ],
1370
+ [
1371
+ 'blockName' => 'core/paragraph',
1372
+ ],
1373
+ ],
1374
+ ];
1375
+ $invalidBlock5 = [
1376
+ 'blockName' => 'core/column',
1377
+ 'innerBlocks' => [],
1378
+ ];
1379
+
1380
+ $this->assertEquals(
1381
+ $this->validateCardinality($validBlock1, $expectedChildren),
1382
+ [
1383
+ 'is_valid' => TRUE,
1384
+ 'message' => '',
1385
+ ]
1386
+ );
1387
+ $this->assertEquals(
1388
+ $this->validateCardinality($validBlock2, $expectedChildren),
1389
+ [
1390
+ 'is_valid' => TRUE,
1391
+ 'message' => '',
1392
+ ]
1393
+ );
1394
+ $this->assertEquals(
1395
+ $this->validateCardinality($validBlock3, $expectedChildren),
1396
+ [
1397
+ 'is_valid' => TRUE,
1398
+ 'message' => '',
1399
+ ]
1400
+ );
1401
+
1402
+ $this->assertEquals(
1403
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
1404
+ [
1405
+ 'is_valid' => FALSE,
1406
+ 'message' => '<em class="placeholder">Paragraph</em>: at least 2 blocks are required.',
1407
+ ]
1408
+ );
1409
+ $this->assertEquals(
1410
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
1411
+ [
1412
+ 'is_valid' => FALSE,
1413
+ 'message' => '<em class="placeholder">Paragraph</em>: at least 2 blocks are required.',
1414
+ ]
1415
+ );
1416
+ $this->assertEquals(
1417
+ $this->validateCardinality($invalidBlock3, $expectedChildren),
1418
+ [
1419
+ 'is_valid' => FALSE,
1420
+ 'message' => '<em class="placeholder">Paragraph</em>: at least 2 blocks are required.',
1421
+ ]
1422
+ );
1423
+ $this->assertEquals(
1424
+ $this->validateCardinality($invalidBlock4, $expectedChildren),
1425
+ [
1426
+ 'is_valid' => FALSE,
1427
+ 'message' => '<em class="placeholder">List</em>: there should be between 1 and unlimited blocks.',
1428
+ ]
1429
+ );
1430
+ $this->assertEquals(
1431
+ $this->validateCardinality($invalidBlock5, $expectedChildren),
1432
+ [
1433
+ 'is_valid' => FALSE,
1434
+ 'message' => 'Required blocks are missing. <em class="placeholder">Paragraph</em>: there should be between 2 and unlimited blocks. <em class="placeholder">List</em>: there should be between 1 and unlimited blocks.',
1435
+ ]
1436
+ );
1437
+ }
1438
+
1439
+ public function testAnyBlockTypeMinimumWithNoMaximum() {
1440
+ $expectedChildren = [
1441
+ 'validationType' => GutenbergCardinalityValidatorInterface::CARDINALITY_ANY,
1442
+ 'min' => 2,
1443
+ 'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED,
1444
+ ];
1445
+
1446
+ $validBlock1 = [
1447
+ 'blockName' => 'core/column',
1448
+ 'innerBlocks' => [
1449
+ [
1450
+ 'blockName' => 'core/paragraph',
1451
+ ],
1452
+ [
1453
+ 'blockName' => 'core/list',
1454
+ ],
1455
+ ],
1456
+ ];
1457
+ $validBlock2 = [
1458
+ 'blockName' => 'core/column',
1459
+ 'innerBlocks' => [
1460
+ [
1461
+ 'blockName' => 'core/paragraph',
1462
+ ],
1463
+ [
1464
+ 'blockName' => 'core/paragraph',
1465
+ ],
1466
+ ],
1467
+ ];
1468
+ $validBlock3 = [
1469
+ 'blockName' => 'core/column',
1470
+ 'innerBlocks' => [
1471
+ [
1472
+ 'blockName' => 'core/paragraph',
1473
+ ],
1474
+ [
1475
+ 'blockName' => 'core/list',
1476
+ ],
1477
+ [
1478
+ 'blockName' => 'core/paragraph',
1479
+ ],
1480
+ [
1481
+ 'blockName' => 'core/list',
1482
+ ],
1483
+ ],
1484
+ ];
1485
+
1486
+ $invalidBlock1 = [
1487
+ 'blockName' => 'core/column',
1488
+ 'innerBlocks' => [
1489
+ [
1490
+ 'blockName' => 'core/paragraph',
1491
+ ],
1492
+ ],
1493
+ ];
1494
+ $invalidBlock2 = [
1495
+ 'blockName' => 'core/column',
1496
+ 'innerBlocks' => [],
1497
+ ];
1498
+
1499
+ $this->assertEquals(
1500
+ $this->validateCardinality($validBlock1, $expectedChildren),
1501
+ [
1502
+ 'is_valid' => TRUE,
1503
+ 'message' => '',
1504
+ ]
1505
+ );
1506
+ $this->assertEquals(
1507
+ $this->validateCardinality($validBlock2, $expectedChildren),
1508
+ [
1509
+ 'is_valid' => TRUE,
1510
+ 'message' => '',
1511
+ ]
1512
+ );
1513
+ $this->assertEquals(
1514
+ $this->validateCardinality($validBlock3, $expectedChildren),
1515
+ [
1516
+ 'is_valid' => TRUE,
1517
+ 'message' => '',
1518
+ ]
1519
+ );
1520
+
1521
+ $this->assertEquals(
1522
+ $this->validateCardinality($invalidBlock1, $expectedChildren),
1523
+ [
1524
+ 'is_valid' => FALSE,
1525
+ 'message' => 'At least 2 blocks are required.',
1526
+ ]
1527
+ );
1528
+ $this->assertEquals(
1529
+ $this->validateCardinality($invalidBlock2, $expectedChildren),
1530
+ [
1531
+ 'is_valid' => FALSE,
1532
+ 'message' => 'At least 2 blocks are required.',
1533
+ ]
1534
+ );
1535
+ }
1536
+
1537
+ }