Commit 964bfbb2 authored by catch's avatar catch
Browse files

fix: #3315276 Fatal error when using a union type on a controller's callback

By: acbramley
By: donquixote
By: spadxiii
By: voleger
(cherry picked from commit 1ba26c89)
parent ea8f200f
Loading
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -18,8 +18,9 @@ final class Reflection {
   */
  public static function getParameterClassName(\ReflectionParameter $parameter) : ?string {
    $name = NULL;
    if ($parameter->hasType() && !$parameter->getType()->isBuiltin()) {
      $name = $parameter->getType()->getName();
    $parameterType = $parameter->getType();
    if ($parameterType instanceof \ReflectionNamedType && !$parameterType->isBuiltin()) {
      $name = $parameterType->getName();
      $lc_name = strtolower($name);
      switch ($lc_name) {
        case 'self':
+42 −0
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\entity_test\Entity\EntityTestRev;
use Drupal\Tests\UnitTestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
@@ -219,6 +221,40 @@ public static function providerTestSetRouteOptionsWithEntityTypeUpcasting() {
    ];
  }

  /**
   * Tests setRouteOptions() with an entity union type.
   *
   * @legacy-covers ::setRouteOptions
   * @legacy-covers ::getControllerClass
   * @legacy-covers ::getEntityTypes
   * @legacy-covers ::setParametersFromReflection
   */
  #[DataProvider('providerTestSetRouteOptionsWithUnionEntityType')]
  public function testSetRouteOptionsWithUnionEntityType($controller): void {
    $this->setupEntityTypes();

    $route = new Route('/example/{entity_test}', [
      '_controller' => $controller,
    ]);

    $defaults = $route->getDefaults();
    $this->entityResolverManager->setRouteOptions($route);
    $this->assertEquals($defaults, $route->getDefaults());
    $parameters = $route->getOption('parameters');
    // Entity route parameters can't be set for union types.
    $this->assertEquals(NULL, $parameters);
  }

  /**
   * Data provider for testSetRouteOptionsWithUnionEntityType.
   */
  public static function providerTestSetRouteOptionsWithUnionEntityType(): array {
    return [
      ['Drupal\Tests\Core\Entity\BasicControllerClass::exampleControllerWithEntityUnionType'],
      ['Drupal\Tests\Core\Entity\test_function_controller_entity_union_type'],
    ];
  }

  /**
   * Tests setRouteOptions() with an entity type parameter form.
   *
@@ -493,6 +529,9 @@ public function exampleControllerWithEntityNoUpcasting($entity_test) {
  public function exampleControllerWithEntityUpcasting(EntityInterface $entity_test) {
  }

  public function exampleControllerWithEntityUnionType(EntityTest|EntityTestRev $entity_test): void {
  }

}

/**
@@ -602,3 +641,6 @@ function test_function_controller_no_upcasting($entity_test) {

function test_function_controller_entity_upcasting(EntityInterface $entity_test) {
}

function test_function_controller_entity_union_type(EntityTest|EntityTestRev $entity_test): void {
}