Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC] Add guessTypeForFieldDescription to TypeGuesserInterface #6839

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions UPGRADE-3.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -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()`
Expand Down
26 changes: 26 additions & 0 deletions src/Guesser/TypeGuesserChain.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
}
}
8 changes: 8 additions & 0 deletions src/Guesser/TypeGuesserInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
*
* @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
*
Expand All @@ -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;
}
63 changes: 60 additions & 3 deletions tests/Guesser/TypeGuesserChainTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,34 @@
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 <[email protected]>
*/
class TypeGuesserChainTest extends TestCase
final class TypeGuesserChainTest extends TestCase
{
use ExpectDeprecationTrait;

public function testConstructorWithException(): void
{
$this->expectException(UnexpectedTypeException::class);

new TypeGuesserChain([new \stdClass()]);
}

/**
* NEXT_MAJOR: Remove this test.
*
* @group legacy
*/
public function testGuessType(): void
{
$typeGuess1 = new TypeGuess('foo1', [], Guess::MEDIUM_CONFIDENCE);
Expand All @@ -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);
Expand All @@ -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));
}
}