bbeb049a6172f08b668752fd449f18f681b9cd97
[yaffs-website] / web / core / modules / layout_builder / tests / src / Unit / OverridesSectionStorageTest.php
1 <?php
2
3 namespace Drupal\Tests\layout_builder\Unit;
4
5 use Drupal\Core\Entity\EntityFieldManagerInterface;
6 use Drupal\Core\Entity\EntityStorageInterface;
7 use Drupal\Core\Entity\EntityTypeInterface;
8 use Drupal\Core\Entity\EntityTypeManagerInterface;
9 use Drupal\Core\Entity\FieldableEntityInterface;
10 use Drupal\Core\Field\FieldStorageDefinitionInterface;
11 use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage;
12 use Drupal\layout_builder\SectionStorage\SectionStorageDefinition;
13 use Drupal\Tests\UnitTestCase;
14 use Prophecy\Argument;
15 use Symfony\Component\Routing\Route;
16 use Symfony\Component\Routing\RouteCollection;
17
18 /**
19  * @coversDefaultClass \Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage
20  *
21  * @group layout_builder
22  */
23 class OverridesSectionStorageTest extends UnitTestCase {
24
25   /**
26    * The plugin.
27    *
28    * @var \Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage
29    */
30   protected $plugin;
31
32   /**
33    * The entity type manager.
34    *
35    * @var \Drupal\Core\Entity\EntityTypeManagerInterface
36    */
37   protected $entityTypeManager;
38
39   /**
40    * The entity field manager.
41    *
42    * @var \Drupal\Core\Entity\EntityFieldManagerInterface
43    */
44   protected $entityFieldManager;
45
46   /**
47    * {@inheritdoc}
48    */
49   protected function setUp() {
50     parent::setUp();
51
52     $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
53     $this->entityFieldManager = $this->prophesize(EntityFieldManagerInterface::class);
54
55     $definition = new SectionStorageDefinition([
56       'id' => 'overrides',
57       'class' => OverridesSectionStorage::class,
58     ]);
59     $this->plugin = new OverridesSectionStorage([], 'overrides', $definition, $this->entityTypeManager->reveal(), $this->entityFieldManager->reveal());
60   }
61
62   /**
63    * @covers ::extractIdFromRoute
64    *
65    * @dataProvider providerTestExtractIdFromRoute
66    */
67   public function testExtractIdFromRoute($expected, $value, array $defaults) {
68     $result = $this->plugin->extractIdFromRoute($value, [], 'the_parameter_name', $defaults);
69     $this->assertSame($expected, $result);
70   }
71
72   /**
73    * Provides data for ::testExtractIdFromRoute().
74    */
75   public function providerTestExtractIdFromRoute() {
76     $data = [];
77     $data['with value, with layout'] = [
78       'my_entity_type.entity_with_layout',
79       'my_entity_type.entity_with_layout',
80       [],
81     ];
82     $data['with value, without layout'] = [
83       NULL,
84       'my_entity_type',
85       [],
86     ];
87     $data['empty value, populated defaults'] = [
88       'my_entity_type.entity_with_layout',
89       '',
90       [
91         'entity_type_id' => 'my_entity_type',
92         'my_entity_type' => 'entity_with_layout',
93       ],
94     ];
95     $data['empty value, empty defaults'] = [
96       NULL,
97       '',
98       [],
99     ];
100     return $data;
101   }
102
103   /**
104    * @covers ::getSectionListFromId
105    *
106    * @dataProvider providerTestGetSectionListFromId
107    */
108   public function testGetSectionListFromId($success, $expected_entity_type_id, $id) {
109     $defaults['the_parameter_name'] = $id;
110
111     if ($expected_entity_type_id) {
112       $entity_storage = $this->prophesize(EntityStorageInterface::class);
113
114       $entity_without_layout = $this->prophesize(FieldableEntityInterface::class);
115       $entity_without_layout->hasField('layout_builder__layout')->willReturn(FALSE);
116       $entity_without_layout->get('layout_builder__layout')->shouldNotBeCalled();
117       $entity_storage->load('entity_without_layout')->willReturn($entity_without_layout->reveal());
118
119       $entity_with_layout = $this->prophesize(FieldableEntityInterface::class);
120       $entity_with_layout->hasField('layout_builder__layout')->willReturn(TRUE);
121       $entity_with_layout->get('layout_builder__layout')->willReturn('the_return_value');
122       $entity_storage->load('entity_with_layout')->willReturn($entity_with_layout->reveal());
123
124       $this->entityTypeManager->getStorage($expected_entity_type_id)->willReturn($entity_storage->reveal());
125     }
126     else {
127       $this->entityTypeManager->getStorage(Argument::any())->shouldNotBeCalled();
128     }
129
130     if (!$success) {
131       $this->setExpectedException(\InvalidArgumentException::class);
132     }
133
134     $result = $this->plugin->getSectionListFromId($id);
135     if ($success) {
136       $this->assertEquals('the_return_value', $result);
137     }
138   }
139
140   /**
141    * Provides data for ::testGetSectionListFromId().
142    */
143   public function providerTestGetSectionListFromId() {
144     $data = [];
145     $data['with value, with layout'] = [
146       TRUE,
147       'my_entity_type',
148       'my_entity_type.entity_with_layout',
149     ];
150     $data['with value, without layout'] = [
151       FALSE,
152       'my_entity_type',
153       'my_entity_type.entity_without_layout',
154     ];
155     $data['empty value, empty defaults'] = [
156       FALSE,
157       NULL,
158       '',
159     ];
160     return $data;
161   }
162
163   /**
164    * @covers ::buildRoutes
165    * @covers ::hasIntegerId
166    * @covers ::getEntityTypes
167    */
168   public function testBuildRoutes() {
169     $entity_types = [];
170
171     $not_fieldable = $this->prophesize(EntityTypeInterface::class);
172     $not_fieldable->entityClassImplements(FieldableEntityInterface::class)->willReturn(FALSE);
173     $entity_types['not_fieldable'] = $not_fieldable->reveal();
174
175     $no_view_builder = $this->prophesize(EntityTypeInterface::class);
176     $no_view_builder->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
177     $no_view_builder->hasViewBuilderClass()->willReturn(FALSE);
178     $entity_types['no_view_builder'] = $no_view_builder->reveal();
179
180     $no_canonical_link = $this->prophesize(EntityTypeInterface::class);
181     $no_canonical_link->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
182     $no_canonical_link->hasViewBuilderClass()->willReturn(TRUE);
183     $no_canonical_link->hasLinkTemplate('canonical')->willReturn(FALSE);
184     $entity_types['no_canonical_link'] = $no_canonical_link->reveal();
185     $this->entityFieldManager->getFieldStorageDefinitions('no_canonical_link')->shouldNotBeCalled();
186
187     $with_string_id = $this->prophesize(EntityTypeInterface::class);
188     $with_string_id->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
189     $with_string_id->hasViewBuilderClass()->willReturn(TRUE);
190     $with_string_id->hasLinkTemplate('canonical')->willReturn(TRUE);
191     $with_string_id->getLinkTemplate('canonical')->willReturn('/entity/{entity}');
192     $with_string_id->id()->willReturn('with_string_id');
193     $with_string_id->getKey('id')->willReturn('id');
194     $entity_types['with_string_id'] = $with_string_id->reveal();
195     $string_id = $this->prophesize(FieldStorageDefinitionInterface::class);
196     $string_id->getType()->willReturn('string');
197     $this->entityFieldManager->getFieldStorageDefinitions('with_string_id')->willReturn(['id' => $string_id->reveal()]);
198
199     $with_integer_id = $this->prophesize(EntityTypeInterface::class);
200     $with_integer_id->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
201     $with_integer_id->hasViewBuilderClass()->willReturn(TRUE);
202     $with_integer_id->hasLinkTemplate('canonical')->willReturn(TRUE);
203     $with_integer_id->getLinkTemplate('canonical')->willReturn('/entity/{entity}');
204     $with_integer_id->id()->willReturn('with_integer_id');
205     $with_integer_id->getKey('id')->willReturn('id');
206     $entity_types['with_integer_id'] = $with_integer_id->reveal();
207     $integer_id = $this->prophesize(FieldStorageDefinitionInterface::class);
208     $integer_id->getType()->willReturn('integer');
209     $this->entityFieldManager->getFieldStorageDefinitions('with_integer_id')->willReturn(['id' => $integer_id->reveal()]);
210
211     $this->entityTypeManager->getDefinitions()->willReturn($entity_types);
212
213     $expected = [
214       'layout_builder.overrides.with_string_id.view' => new Route(
215         '/entity/{entity}/layout',
216         [
217           'entity_type_id' => 'with_string_id',
218           'section_storage_type' => 'overrides',
219           'section_storage' => '',
220           'is_rebuilding' => FALSE,
221           '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::layout',
222           '_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
223         ],
224         [
225           '_has_layout_section' => 'true',
226         ],
227         [
228           'parameters' => [
229             'section_storage' => ['layout_builder_tempstore' => TRUE],
230             'with_string_id' => ['type' => 'entity:with_string_id'],
231           ],
232           '_layout_builder' => TRUE,
233         ]
234       ),
235       'layout_builder.overrides.with_string_id.save' => new Route(
236         '/entity/{entity}/layout/save',
237         [
238           'entity_type_id' => 'with_string_id',
239           'section_storage_type' => 'overrides',
240           'section_storage' => '',
241           '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout',
242         ],
243         [
244           '_has_layout_section' => 'true',
245         ],
246         [
247           'parameters' => [
248             'section_storage' => ['layout_builder_tempstore' => TRUE],
249             'with_string_id' => ['type' => 'entity:with_string_id'],
250           ],
251           '_layout_builder' => TRUE,
252         ]
253       ),
254       'layout_builder.overrides.with_string_id.cancel' => new Route(
255         '/entity/{entity}/layout/cancel',
256         [
257           'entity_type_id' => 'with_string_id',
258           'section_storage_type' => 'overrides',
259           'section_storage' => '',
260           '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout',
261         ],
262         [
263           '_has_layout_section' => 'true',
264         ],
265         [
266           'parameters' => [
267             'section_storage' => ['layout_builder_tempstore' => TRUE],
268             'with_string_id' => ['type' => 'entity:with_string_id'],
269           ],
270           '_layout_builder' => TRUE,
271         ]
272       ),
273       'layout_builder.overrides.with_string_id.revert' => new Route(
274         '/entity/{entity}/layout/revert',
275         [
276           'entity_type_id' => 'with_string_id',
277           'section_storage_type' => 'overrides',
278           'section_storage' => '',
279           '_form' => '\Drupal\layout_builder\Form\RevertOverridesForm',
280         ],
281         [
282           '_has_layout_section' => 'true',
283         ],
284         [
285           'parameters' => [
286             'section_storage' => ['layout_builder_tempstore' => TRUE],
287             'with_string_id' => ['type' => 'entity:with_string_id'],
288           ],
289           '_layout_builder' => TRUE,
290         ]
291       ),
292       'layout_builder.overrides.with_integer_id.view' => new Route(
293         '/entity/{entity}/layout',
294         [
295           'entity_type_id' => 'with_integer_id',
296           'section_storage_type' => 'overrides',
297           'section_storage' => '',
298           'is_rebuilding' => FALSE,
299           '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::layout',
300           '_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
301         ],
302         [
303           '_has_layout_section' => 'true',
304           'with_integer_id' => '\d+',
305         ],
306         [
307           'parameters' => [
308             'section_storage' => ['layout_builder_tempstore' => TRUE],
309             'with_integer_id' => ['type' => 'entity:with_integer_id'],
310           ],
311           '_layout_builder' => TRUE,
312         ]
313       ),
314       'layout_builder.overrides.with_integer_id.save' => new Route(
315         '/entity/{entity}/layout/save',
316         [
317           'entity_type_id' => 'with_integer_id',
318           'section_storage_type' => 'overrides',
319           'section_storage' => '',
320           '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout',
321         ],
322         [
323           '_has_layout_section' => 'true',
324           'with_integer_id' => '\d+',
325         ],
326         [
327           'parameters' => [
328             'section_storage' => ['layout_builder_tempstore' => TRUE],
329             'with_integer_id' => ['type' => 'entity:with_integer_id'],
330           ],
331           '_layout_builder' => TRUE,
332         ]
333       ),
334       'layout_builder.overrides.with_integer_id.cancel' => new Route(
335         '/entity/{entity}/layout/cancel',
336         [
337           'entity_type_id' => 'with_integer_id',
338           'section_storage_type' => 'overrides',
339           'section_storage' => '',
340           '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout',
341         ],
342         [
343           '_has_layout_section' => 'true',
344           'with_integer_id' => '\d+',
345         ],
346         [
347           'parameters' => [
348             'section_storage' => ['layout_builder_tempstore' => TRUE],
349             'with_integer_id' => ['type' => 'entity:with_integer_id'],
350           ],
351           '_layout_builder' => TRUE,
352         ]
353       ),
354       'layout_builder.overrides.with_integer_id.revert' => new Route(
355         '/entity/{entity}/layout/revert',
356         [
357           'entity_type_id' => 'with_integer_id',
358           'section_storage_type' => 'overrides',
359           'section_storage' => '',
360           '_form' => '\Drupal\layout_builder\Form\RevertOverridesForm',
361         ],
362         [
363           '_has_layout_section' => 'true',
364           'with_integer_id' => '\d+',
365         ],
366         [
367           'parameters' => [
368             'section_storage' => ['layout_builder_tempstore' => TRUE],
369             'with_integer_id' => ['type' => 'entity:with_integer_id'],
370           ],
371           '_layout_builder' => TRUE,
372         ]
373       ),
374     ];
375
376     $collection = new RouteCollection();
377     $this->plugin->buildRoutes($collection);
378     $this->assertEquals($expected, $collection->all());
379     $this->assertSame(array_keys($expected), array_keys($collection->all()));
380   }
381
382 }