
| Current Path : /var/www/html/strat/web/core/modules/layout_builder/tests/src/Unit/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : /var/www/html/strat/web/core/modules/layout_builder/tests/src/Unit/OverridesSectionStorageTest.php |
<?php
declare(strict_types=1);
namespace Drupal\Tests\layout_builder\Unit;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityType;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage;
use Drupal\layout_builder\SectionStorage\SectionStorageDefinition;
use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface;
use Drupal\Tests\UnitTestCase;
use Prophecy\Argument;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
/**
* @coversDefaultClass \Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage
*
* @group layout_builder
* @group #slow
*/
class OverridesSectionStorageTest extends UnitTestCase {
/**
* The plugin.
*
* @var \Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage
*/
protected $plugin;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The entity field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager;
/**
* The entity repository.
*
* @var \Drupal\Core\Entity\EntityRepositoryInterface
*/
protected $entityRepository;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
$this->entityFieldManager = $this->prophesize(EntityFieldManagerInterface::class);
$section_storage_manager = $this->prophesize(SectionStorageManagerInterface::class);
$this->entityRepository = $this->prophesize(EntityRepositoryInterface::class);
$account = $this->prophesize(AccountInterface::class);
$definition = new SectionStorageDefinition([
'id' => 'overrides',
'class' => OverridesSectionStorage::class,
]);
$this->plugin = new OverridesSectionStorage([], 'overrides', $definition, $this->entityTypeManager->reveal(), $this->entityFieldManager->reveal(), $section_storage_manager->reveal(), $this->entityRepository->reveal(), $account->reveal());
}
/**
* @covers ::extractEntityFromRoute
*
* @dataProvider providerTestExtractEntityFromRoute
*
* @param bool $success
* Whether a successful result is expected.
* @param string|null $expected_entity_type_id
* The expected entity type ID.
* @param string $value
* The value to pass to ::extractEntityFromRoute().
* @param array $defaults
* The defaults to pass to ::extractEntityFromRoute().
*/
public function testExtractEntityFromRoute($success, $expected_entity_type_id, $value, array $defaults): void {
if ($expected_entity_type_id) {
$entity_without_layout = $this->prophesize(FieldableEntityInterface::class);
$entity_without_layout->hasField(OverridesSectionStorage::FIELD_NAME)->willReturn(FALSE);
$this->entityRepository->getActive($expected_entity_type_id, 'entity_without_layout')->willReturn($entity_without_layout->reveal());
$entity_with_layout = $this->prophesize(FieldableEntityInterface::class);
$entity_with_layout->hasField(OverridesSectionStorage::FIELD_NAME)->willReturn(TRUE);
$this->entityRepository->getActive($expected_entity_type_id, 'entity_with_layout')->willReturn($entity_with_layout->reveal());
$entity_type = new EntityType([
'id' => $expected_entity_type_id,
]);
$this->entityTypeManager->getDefinition($expected_entity_type_id)->willReturn($entity_type);
}
else {
$this->entityRepository->getActive(Argument::any())->shouldNotBeCalled();
}
$method = new \ReflectionMethod($this->plugin, 'extractEntityFromRoute');
$result = $method->invoke($this->plugin, $value, $defaults);
if ($success) {
$this->assertInstanceOf(FieldableEntityInterface::class, $result);
}
else {
$this->assertNull($result);
}
}
/**
* Provides data for ::testExtractEntityFromRoute().
*/
public static function providerTestExtractEntityFromRoute() {
// Data provider values are:
// - whether a successful result is expected
// - the expected entity ID
// - the value to pass to ::extractEntityFromRoute()
// - the defaults to pass to ::extractEntityFromRoute().
$data = [];
$data['with value, with layout'] = [
TRUE,
'my_entity_type',
'my_entity_type.entity_with_layout',
[],
];
$data['with value, without layout'] = [
TRUE,
'my_entity_type',
'my_entity_type.entity_without_layout',
[],
];
$data['empty value, populated defaults'] = [
TRUE,
'my_entity_type',
'',
[
'entity_type_id' => 'my_entity_type',
'my_entity_type' => 'entity_with_layout',
],
];
$data['empty value, empty defaults'] = [
FALSE,
NULL,
'',
[],
];
return $data;
}
/**
* @covers ::buildRoutes
* @covers ::hasIntegerId
* @covers ::getEntityTypes
* @covers \Drupal\layout_builder\Routing\LayoutBuilderRoutesTrait::buildLayoutRoutes
*/
public function testBuildRoutes(): void {
$entity_types = [];
$not_fieldable = $this->prophesize(EntityTypeInterface::class);
$not_fieldable->entityClassImplements(FieldableEntityInterface::class)->willReturn(FALSE);
$entity_types['not_fieldable'] = $not_fieldable->reveal();
$no_layout_builder_form = $this->prophesize(EntityTypeInterface::class);
$no_layout_builder_form->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
$no_layout_builder_form->hasHandlerClass('form', 'layout_builder')->willReturn(FALSE);
$entity_types['no_layout_builder_form'] = $no_layout_builder_form->reveal();
$this->entityFieldManager->getFieldStorageDefinitions('no_layout_builder_form')->shouldNotBeCalled();
$no_view_builder = $this->prophesize(EntityTypeInterface::class);
$no_view_builder->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
$no_view_builder->hasViewBuilderClass()->willReturn(FALSE);
$no_view_builder->hasHandlerClass('form', 'layout_builder')->willReturn(TRUE);
$entity_types['no_view_builder'] = $no_view_builder->reveal();
$no_canonical_link = $this->prophesize(EntityTypeInterface::class);
$no_canonical_link->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
$no_canonical_link->hasViewBuilderClass()->willReturn(TRUE);
$no_canonical_link->hasLinkTemplate('canonical')->willReturn(FALSE);
$no_canonical_link->hasHandlerClass('form', 'layout_builder')->willReturn(TRUE);
$entity_types['no_canonical_link'] = $no_canonical_link->reveal();
$this->entityFieldManager->getFieldStorageDefinitions('no_canonical_link')->shouldNotBeCalled();
$canonical_link_no_route = $this->prophesize(EntityTypeInterface::class);
$canonical_link_no_route->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
$canonical_link_no_route->hasViewBuilderClass()->willReturn(TRUE);
$canonical_link_no_route->hasLinkTemplate('canonical')->willReturn(TRUE);
$canonical_link_no_route->getLinkTemplate('canonical')->willReturn('/entity/{entity}');
$canonical_link_no_route->hasHandlerClass('form', 'layout_builder')->willReturn(TRUE);
$entity_types['canonical_link_no_route'] = $canonical_link_no_route->reveal();
$this->entityFieldManager->getFieldStorageDefinitions('canonical_link_no_route')->shouldNotBeCalled();
$from_canonical = $this->prophesize(EntityTypeInterface::class);
$from_canonical->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
$from_canonical->hasViewBuilderClass()->willReturn(TRUE);
$from_canonical->hasLinkTemplate('canonical')->willReturn(TRUE);
$from_canonical->getLinkTemplate('canonical')->willReturn('/entity/{entity}');
$from_canonical->hasHandlerClass('form', 'layout_builder')->willReturn(TRUE);
$entity_types['from_canonical'] = $from_canonical->reveal();
$with_string_id = $this->prophesize(EntityTypeInterface::class);
$with_string_id->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
$with_string_id->hasViewBuilderClass()->willReturn(TRUE);
$with_string_id->hasLinkTemplate('canonical')->willReturn(TRUE);
$with_string_id->getLinkTemplate('canonical')->willReturn('/entity/{entity}');
$with_string_id->hasHandlerClass('form', 'layout_builder')->willReturn(TRUE);
$with_string_id->id()->willReturn('with_string_id');
$with_string_id->getKey('id')->willReturn('id');
$entity_types['with_string_id'] = $with_string_id->reveal();
$string_id = $this->prophesize(FieldStorageDefinitionInterface::class);
$string_id->getType()->willReturn('string');
$this->entityFieldManager->getFieldStorageDefinitions('with_string_id')->willReturn(['id' => $string_id->reveal()]);
$with_integer_id = $this->prophesize(EntityTypeInterface::class);
$with_integer_id->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
$with_integer_id->hasViewBuilderClass()->willReturn(TRUE);
$with_integer_id->hasLinkTemplate('canonical')->willReturn(TRUE);
$with_integer_id->getLinkTemplate('canonical')->willReturn('/entity/{entity}');
$with_integer_id->hasHandlerClass('form', 'layout_builder')->willReturn(TRUE);
$with_integer_id->id()->willReturn('with_integer_id');
$with_integer_id->getKey('id')->willReturn('id');
$entity_types['with_integer_id'] = $with_integer_id->reveal();
$integer_id = $this->prophesize(FieldStorageDefinitionInterface::class);
$integer_id->getType()->willReturn('integer');
$this->entityFieldManager->getFieldStorageDefinitions('with_integer_id')->willReturn(['id' => $integer_id->reveal()]);
$this->entityTypeManager->getDefinitions()->willReturn($entity_types);
$expected = [
'entity.from_canonical.canonical' => new Route(
'/entity/{entity}',
[],
[
'custom requirement' => 'from_canonical_route',
]
),
'entity.with_string_id.canonical' => new Route(
'/entity/{entity}'
),
'entity.with_integer_id.canonical' => new Route(
'/entity/{entity}',
[],
[
'with_integer_id' => '\d+',
]
),
'layout_builder.overrides.from_canonical.view' => new Route(
'/entity/{entity}/layout',
[
'entity_type_id' => 'from_canonical',
'section_storage_type' => 'overrides',
'section_storage' => '',
'_entity_form' => 'from_canonical.layout_builder',
'_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
],
[
'_layout_builder_access' => 'view',
'custom requirement' => 'from_canonical_route',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
'from_canonical' => ['type' => 'entity:from_canonical'],
],
'_layout_builder' => TRUE,
'_admin_route' => FALSE,
]
),
'layout_builder.overrides.from_canonical.discard_changes' => new Route(
'/entity/{entity}/layout/discard-changes',
[
'entity_type_id' => 'from_canonical',
'section_storage_type' => 'overrides',
'section_storage' => '',
'_form' => '\Drupal\layout_builder\Form\DiscardLayoutChangesForm',
],
[
'_layout_builder_access' => 'view',
'custom requirement' => 'from_canonical_route',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
'from_canonical' => ['type' => 'entity:from_canonical'],
],
'_layout_builder' => TRUE,
'_admin_route' => FALSE,
]
),
'layout_builder.overrides.from_canonical.revert' => new Route(
'/entity/{entity}/layout/revert',
[
'entity_type_id' => 'from_canonical',
'section_storage_type' => 'overrides',
'section_storage' => '',
'_form' => '\Drupal\layout_builder\Form\RevertOverridesForm',
],
[
'_layout_builder_access' => 'view',
'custom requirement' => 'from_canonical_route',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
'from_canonical' => ['type' => 'entity:from_canonical'],
],
'_layout_builder' => TRUE,
'_admin_route' => FALSE,
]
),
'layout_builder.overrides.with_string_id.view' => new Route(
'/entity/{entity}/layout',
[
'entity_type_id' => 'with_string_id',
'section_storage_type' => 'overrides',
'section_storage' => '',
'_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
'_entity_form' => 'with_string_id.layout_builder',
],
[
'_layout_builder_access' => 'view',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
'with_string_id' => ['type' => 'entity:with_string_id'],
],
'_layout_builder' => TRUE,
'_admin_route' => FALSE,
]
),
'layout_builder.overrides.with_string_id.discard_changes' => new Route(
'/entity/{entity}/layout/discard-changes',
[
'entity_type_id' => 'with_string_id',
'section_storage_type' => 'overrides',
'section_storage' => '',
'_form' => '\Drupal\layout_builder\Form\DiscardLayoutChangesForm',
],
[
'_layout_builder_access' => 'view',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
'with_string_id' => ['type' => 'entity:with_string_id'],
],
'_layout_builder' => TRUE,
'_admin_route' => FALSE,
]
),
'layout_builder.overrides.with_string_id.revert' => new Route(
'/entity/{entity}/layout/revert',
[
'entity_type_id' => 'with_string_id',
'section_storage_type' => 'overrides',
'section_storage' => '',
'_form' => '\Drupal\layout_builder\Form\RevertOverridesForm',
],
[
'_layout_builder_access' => 'view',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
'with_string_id' => ['type' => 'entity:with_string_id'],
],
'_layout_builder' => TRUE,
'_admin_route' => FALSE,
]
),
'layout_builder.overrides.with_integer_id.view' => new Route(
'/entity/{entity}/layout',
[
'entity_type_id' => 'with_integer_id',
'section_storage_type' => 'overrides',
'section_storage' => '',
'_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
'_entity_form' => 'with_integer_id.layout_builder',
],
[
'_layout_builder_access' => 'view',
'with_integer_id' => '\d+',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
'with_integer_id' => ['type' => 'entity:with_integer_id'],
],
'_layout_builder' => TRUE,
'_admin_route' => FALSE,
]
),
'layout_builder.overrides.with_integer_id.discard_changes' => new Route(
'/entity/{entity}/layout/discard-changes',
[
'entity_type_id' => 'with_integer_id',
'section_storage_type' => 'overrides',
'section_storage' => '',
'_form' => '\Drupal\layout_builder\Form\DiscardLayoutChangesForm',
],
[
'_layout_builder_access' => 'view',
'with_integer_id' => '\d+',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
'with_integer_id' => ['type' => 'entity:with_integer_id'],
],
'_layout_builder' => TRUE,
'_admin_route' => FALSE,
]
),
'layout_builder.overrides.with_integer_id.revert' => new Route(
'/entity/{entity}/layout/revert',
[
'entity_type_id' => 'with_integer_id',
'section_storage_type' => 'overrides',
'section_storage' => '',
'_form' => '\Drupal\layout_builder\Form\RevertOverridesForm',
],
[
'_layout_builder_access' => 'view',
'with_integer_id' => '\d+',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
'with_integer_id' => ['type' => 'entity:with_integer_id'],
],
'_layout_builder' => TRUE,
'_admin_route' => FALSE,
]
),
];
$collection = new RouteCollection();
// Entity types that declare a link template for canonical must have a
// canonical route present in the route collection.
$collection->add('entity.from_canonical.canonical', $expected['entity.from_canonical.canonical']);
$collection->add('entity.with_string_id.canonical', $expected['entity.with_string_id.canonical']);
$collection->add('entity.with_integer_id.canonical', $expected['entity.with_integer_id.canonical']);
$this->plugin->buildRoutes($collection);
$this->assertEquals($expected, $collection->all());
$this->assertSame(array_keys($expected), array_keys($collection->all()));
}
}