Commit f6bde547 authored by catch's avatar catch
Browse files

Issue #3155568 by claudiu.cristea, jonathanshaw, idimopoulos, catch: Filter by...

Issue #3155568 by claudiu.cristea, jonathanshaw, idimopoulos, catch: Filter by bundle in EntityConverter route param converter
parent 1cb136a1
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1162,6 +1162,9 @@ services:
    tags:
      - { name: access_check, applies_to: _entity_access }
  access_check.entity_bundles:
    # Deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Specify the
    # list of bundles in the entity parameter, under "bundle" key as a sequence,
    # instead. See https://www.drupal.org/node/3155569.
    class: Drupal\Core\Entity\EntityBundleAccessCheck
    tags:
      - { name: access_check, applies_to: _entity_bundles }
+7 −0
Original line number Diff line number Diff line
@@ -10,6 +10,12 @@

/**
 * Provides an entity bundle checker for the _entity_bundles route requirement.
 *
 * @todo Deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Specify
 *   the list of bundles in the entity parameter, under "bundle" key, as a
 *   sequence, instead.
 *
 * @see https://www.drupal.org/node/3155569
 */
class EntityBundleAccessCheck implements AccessInterface {

@@ -34,6 +40,7 @@ class EntityBundleAccessCheck implements AccessInterface {
   *   The access result.
   */
  public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) {
    @trigger_error('The ' . __NAMESPACE__ . '\EntityBundleAccessCheck is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Specify the list of bundles in the entity parameter, under "bundle" key, as a sequence, instead. See https://www.drupal.org/node/3155569', E_USER_DEPRECATED);
    if ($route->hasRequirement('_entity_bundles')) {
      list($entity_type, $bundle_definition) = explode(':', $route->getRequirement('_entity_bundles'));
      $bundles = explode('|', $bundle_definition);
+21 −0
Original line number Diff line number Diff line
@@ -37,6 +37,23 @@
 *         type: entity:{entity_type}
 * @endcode
 *
 * The conversion can be limited to certain entity bundles by specifying a
 * parameter 'bundle' definition property as an array:
 * @code
 * example.route:
 *   path: foo/{example}
 *   options:
 *     parameters:
 *       example:
 *         type: entity:node
 *         bundle:
 *           - article
 *           - news
 * @endcode
 * In the above example, only node entities of types 'article' and 'news' are
 * converted. For a node of a different type, such as 'page', the route will
 * return 404 'Not found'.
 *
 * If your route needs to support pending revisions, you can specify the
 * "load_latest_revision" parameter. This will ensure that the latest revision
 * is returned, even if it is not the default one:
@@ -125,6 +142,10 @@ public function convert($value, $definition, $name, array $defaults) {
    }
    $entity = $this->entityRepository->getCanonical($entity_type_id, $value, $contexts);

    if (!empty($definition['bundle']) && !in_array($entity->bundle(), $definition['bundle'], TRUE)) {
      return NULL;
    }

    return $entity;
  }

+101 −0
Original line number Diff line number Diff line
<?php

declare(strict_types = 1);

namespace Drupal\KernelTests\Core\ParamConverter;

use Drupal\entity_test\Entity\EntityTest;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\user\Traits\UserCreationTrait;

/**
 * Tests the entity param converter.
 *
 * @group ParamConverter
 * @coversDefaultClass \Drupal\Core\ParamConverter\EntityConverter
 */
class EntityConverterTest extends KernelTestBase {

  use UserCreationTrait;

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'entity_test',
    'user',
  ];

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $this->setUpCurrentUser();
    $this->installEntitySchema('entity_test');

    // Create some testing bundles for 'entity_test' entity type.
    entity_test_create_bundle('foo', 'Foo');
    entity_test_create_bundle('bar', 'Bar');
    entity_test_create_bundle('baz', 'Baz');
  }

  /**
   * Tests an entity route parameter having 'bundle' definition property.
   *
   * @covers ::convert
   */
  public function testRouteParamWithBundleDefinition(): void {
    $converter = $this->container->get('paramconverter.entity');

    $entity1 = EntityTest::create([
      'name' => $this->randomString(),
      'type' => 'foo',
    ]);
    $entity1->save();
    $entity2 = EntityTest::create([
      'name' => $this->randomString(),
      'type' => 'bar',
    ]);
    $entity2->save();
    $entity3 = EntityTest::create([
      'name' => $this->randomString(),
      'type' => 'baz',
    ]);
    $entity3->save();

    $definition = [
      'type' => 'entity:entity_test',
      'bundle' => [
        'foo',
        'bar',
      ],
    ];

    // An entity whose bundle is in the definition list is converted.
    $converted = $converter->convert($entity1->id(), $definition, 'qux', []);
    $this->assertSame($entity1->id(), $converted->id());

    // An entity whose bundle is in the definition list is converted.
    $converted = $converter->convert($entity2->id(), $definition, 'qux', []);
    $this->assertSame($entity2->id(), $converted->id());

    // An entity whose bundle is missed from definition is not converted.
    $converted = $converter->convert($entity3->id(), $definition, 'qux', []);
    $this->assertNull($converted);

    $definition = [
      'type' => 'entity:entity_test',
    ];

    // Check that all entities are returned when 'bundle' is not defined.
    $converted = $converter->convert($entity1->id(), $definition, 'qux', []);
    $this->assertSame($entity1->id(), $converted->id());
    $converted = $converter->convert($entity2->id(), $definition, 'qux', []);
    $this->assertSame($entity2->id(), $converted->id());
    $converted = $converter->convert($entity3->id(), $definition, 'qux', []);
    $this->assertSame($entity3->id(), $converted->id());
  }

}
+2 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
 *
 * @group Access
 * @group Entity
 * @group legacy
 */
class EntityBundleAccessCheckTest extends UnitTestCase {

@@ -91,6 +92,7 @@ public function testRouteAccess($bundle, $access_requirement, $access_result) {
    $route_match = $route_match->reveal();

    $access_check = new EntityBundleAccessCheck();
    $this->expectDeprecation('The Drupal\Core\Entity\EntityBundleAccessCheck is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Specify the list of bundles in the entity parameter, under "bundle" key, as a sequence, instead. See https://www.drupal.org/node/3155569');
    $this->assertEquals($access_result, $access_check->access($route, $route_match, $account));
  }