diff --git a/UPGRADE-3.x.md b/UPGRADE-3.x.md index a3aa35ae11..3708b1b702 100644 --- a/UPGRADE-3.x.md +++ b/UPGRADE-3.x.md @@ -4,6 +4,14 @@ UPGRADE 3.x UPGRADE FROM 3.xx to 3.xx ========================= +### Deprecated `Sonata\AdminBundle\Guesser\TypeGuesserInterface::guessType()` method. + +Deprecated `guessType()` method in favor of `guessTypeForFieldDescription()`. + +### Deprecated `Sonata\AdminBundle\Guesser\TypeGuesserChain::guessType()` method. + +Deprecated `guessType()` method in favor of `guessTypeForFieldDescription()`. + ### Deprecated `Sonata\AdminBundle\Admin\AbstractAdmin::formOptions` property. This property has been replaced by the new method `Sonata\AdminBundle\Admin\AbstractAdmin::configureFormOptions()` diff --git a/src/Guesser/TypeGuesserChain.php b/src/Guesser/TypeGuesserChain.php index fa6de1f9c0..afa5f8428d 100644 --- a/src/Guesser/TypeGuesserChain.php +++ b/src/Guesser/TypeGuesserChain.php @@ -13,6 +13,7 @@ namespace Sonata\AdminBundle\Guesser; +use Sonata\AdminBundle\Admin\FieldDescriptionInterface; use Sonata\AdminBundle\Model\ModelManagerInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Guess\TypeGuess; @@ -47,8 +48,18 @@ public function __construct(array $guessers) } } + /** + * @deprecated since sonata-project/admin-bundle 3.x. Use guessTypeForFieldDescription instead. + */ public function guessType($class, $property, ModelManagerInterface $modelManager) { + @trigger_error(sprintf( + 'Method "%s()" is deprecated since sonata-project/admin-bundle 3.x and will be removed in version 4.0.' + .' Use "%s::guessTypeForFieldDescription()" instead.', + __METHOD__, + self::class + ), \E_USER_DEPRECATED); + $guesses = []; foreach ($this->guessers as $guesser) { @@ -61,4 +72,19 @@ public function guessType($class, $property, ModelManagerInterface $modelManager return TypeGuess::getBestGuess($guesses); } + + public function guessTypeForFieldDescription(FieldDescriptionInterface $fieldDescription): ?TypeGuess + { + $guesses = []; + + foreach ($this->guessers as $guesser) { + $guess = $guesser->guessTypeForFieldDescription($fieldDescription); + + if (null !== $guess) { + $guesses[] = $guess; + } + } + + return TypeGuess::getBestGuess($guesses); + } } diff --git a/src/Guesser/TypeGuesserInterface.php b/src/Guesser/TypeGuesserInterface.php index 8edd1be7c5..06b3bf6499 100644 --- a/src/Guesser/TypeGuesserInterface.php +++ b/src/Guesser/TypeGuesserInterface.php @@ -13,15 +13,20 @@ namespace Sonata\AdminBundle\Guesser; +use Sonata\AdminBundle\Admin\FieldDescriptionInterface; use Sonata\AdminBundle\Model\ModelManagerInterface; use Symfony\Component\Form\Guess\TypeGuess; /** * @author Thomas Rabaix + * + * @method TypeGuess|null guessTypeForFieldDescription(FieldDescriptionInterface $fieldDescription) */ interface TypeGuesserInterface { /** + * @deprecated since sonata-project/admin-bundle 3.x. Use guessTypeForFieldDescription instead. + * * @param string $class * @param string $property * @@ -30,4 +35,7 @@ interface TypeGuesserInterface * @phpstan-param class-string $class */ public function guessType($class, $property, ModelManagerInterface $modelManager); + + // NEXT_MAJOR: Uncomment next line. + // public function guessTypeForFieldDescription(FieldDescriptionInterface $fieldDescription): ?TypeGuess; } diff --git a/tests/Guesser/TypeGuesserChainTest.php b/tests/Guesser/TypeGuesserChainTest.php index 40a820c6e3..e0d0c9bb1f 100644 --- a/tests/Guesser/TypeGuesserChainTest.php +++ b/tests/Guesser/TypeGuesserChainTest.php @@ -14,20 +14,22 @@ namespace Sonata\AdminBundle\Tests\Guesser; use PHPUnit\Framework\TestCase; +use Sonata\AdminBundle\Admin\FieldDescriptionInterface; use Sonata\AdminBundle\Guesser\TypeGuesserChain; use Sonata\AdminBundle\Guesser\TypeGuesserInterface; use Sonata\AdminBundle\Model\ModelManagerInterface; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\TypeGuess; /** - * TypeGuesserChain Test. - * * @author Andrej Hudec */ -class TypeGuesserChainTest extends TestCase +final class TypeGuesserChainTest extends TestCase { + use ExpectDeprecationTrait; + public function testConstructorWithException(): void { $this->expectException(UnexpectedTypeException::class); @@ -35,6 +37,11 @@ public function testConstructorWithException(): void new TypeGuesserChain([new \stdClass()]); } + /** + * NEXT_MAJOR: Remove this test. + * + * @group legacy + */ public function testGuessType(): void { $typeGuess1 = new TypeGuess('foo1', [], Guess::MEDIUM_CONFIDENCE); @@ -61,6 +68,9 @@ public function testGuessType(): void $property = 'firstName'; $typeGuesserChain = new TypeGuesserChain([$guesser1, $guesser2, $guesser3]); + + $this->expectDeprecation('Method "Sonata\AdminBundle\Guesser\TypeGuesserChain::guessType()" is deprecated since sonata-project/admin-bundle 3.x and will be removed in version 4.0. Use "Sonata\AdminBundle\Guesser\TypeGuesserChain::guessTypeForFieldDescription()" instead.'); + $this->assertSame($typeGuess2, $typeGuesserChain->guessType($class, $property, $modelManager)); $typeGuess4 = new TypeGuess('foo4', [], Guess::LOW_CONFIDENCE); @@ -72,4 +82,51 @@ public function testGuessType(): void $typeGuesserChain = new TypeGuesserChain([$guesser4, $typeGuesserChain]); $this->assertSame($typeGuess2, $typeGuesserChain->guessType($class, $property, $modelManager)); } + + public function testGuessTypeForFieldDescription(): void + { + $typeGuess1 = new TypeGuess('foo1', [], Guess::MEDIUM_CONFIDENCE); + // NEXT_MAJOR: Change this mock with a stub. + $guesser1 = $this->getMockBuilder(TypeGuesserInterface::class) + ->addMethods(['guessTypeForFieldDescription']) + ->getMockForAbstractClass(); + $guesser1 + ->method('guessTypeForFieldDescription') + ->willReturn($typeGuess1); + + $typeGuess2 = new TypeGuess('foo2', [], Guess::HIGH_CONFIDENCE); + // NEXT_MAJOR: Change this mock with a stub. + $guesser2 = $this->getMockBuilder(TypeGuesserInterface::class) + ->addMethods(['guessTypeForFieldDescription']) + ->getMockForAbstractClass(); + $guesser2 + ->method('guessTypeForFieldDescription') + ->willReturn($typeGuess2); + + $typeGuess3 = new TypeGuess('foo3', [], Guess::LOW_CONFIDENCE); + // NEXT_MAJOR: Change this mock with a stub. + $guesser3 = $this->getMockBuilder(TypeGuesserInterface::class) + ->addMethods(['guessTypeForFieldDescription']) + ->getMockForAbstractClass(); + $guesser3 + ->method('guessTypeForFieldDescription') + ->willReturn($typeGuess3); + + $fieldDescription = $this->createStub(FieldDescriptionInterface::class); + + $typeGuesserChain = new TypeGuesserChain([$guesser1, $guesser2, $guesser3]); + $this->assertSame($typeGuess2, $typeGuesserChain->guessTypeForFieldDescription($fieldDescription)); + + $typeGuess4 = new TypeGuess('foo4', [], Guess::LOW_CONFIDENCE); + // NEXT_MAJOR: Change this mock with a stub. + $guesser4 = $this->getMockBuilder(TypeGuesserInterface::class) + ->addMethods(['guessTypeForFieldDescription']) + ->getMockForAbstractClass(); + $guesser4 + ->method('guessTypeForFieldDescription') + ->willReturn($typeGuess4); + + $typeGuesserChain = new TypeGuesserChain([$guesser4, $typeGuesserChain]); + $this->assertSame($typeGuess2, $typeGuesserChain->guessTypeForFieldDescription($fieldDescription)); + } }