Skip to content

Commit

Permalink
bug #35851 [4.4][DoctrineBridge] Use new Types::* constants and suppo…
Browse files Browse the repository at this point in the history
…rt new json types (fancyweb)

This PR was merged into the 4.4 branch.

Discussion
----------

[4.4][DoctrineBridge] Use new Types::* constants and support new json types

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | #35817 (comment)
| License       | MIT
| Doc PR        | -

Commits
-------

ddf3353 [4.4][DoctrineBridge] Use new Types::* constants and support new json type
  • Loading branch information
fabpot committed Feb 25, 2020
2 parents 1024f5f + ddf3353 commit 88b96ab
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 71 deletions.
41 changes: 24 additions & 17 deletions src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Bridge\Doctrine\Form;

use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\MappingException as LegacyMappingException;
use Doctrine\Persistence\ManagerRegistry;
Expand All @@ -28,9 +29,15 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface

private $cache = [];

private static $useDeprecatedConstants;

public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;

if (null === self::$useDeprecatedConstants) {
self::$useDeprecatedConstants = !class_exists(Types::class);
}
}

/**
Expand All @@ -52,39 +59,39 @@ public function guessType($class, $property)
}

switch ($metadata->getTypeOfField($property)) {
case Type::TARRAY:
case Type::SIMPLE_ARRAY:
case self::$useDeprecatedConstants ? Type::TARRAY : Types::ARRAY:
case self::$useDeprecatedConstants ? Type::SIMPLE_ARRAY : Types::SIMPLE_ARRAY:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', [], Guess::MEDIUM_CONFIDENCE);
case Type::BOOLEAN:
case self::$useDeprecatedConstants ? Type::BOOLEAN : Types::BOOLEAN:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', [], Guess::HIGH_CONFIDENCE);
case Type::DATETIME:
case Type::DATETIMETZ:
case self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE:
case self::$useDeprecatedConstants ? Type::DATETIMETZ : Types::DATETIMETZ_MUTABLE:
case 'vardatetime':
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', [], Guess::HIGH_CONFIDENCE);
case 'datetime_immutable':
case 'datetimetz_immutable':
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE);
case 'dateinterval':
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateIntervalType', [], Guess::HIGH_CONFIDENCE);
case Type::DATE:
case self::$useDeprecatedConstants ? Type::DATE : Types::DATE_MUTABLE:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', [], Guess::HIGH_CONFIDENCE);
case 'date_immutable':
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE);
case Type::TIME:
case self::$useDeprecatedConstants ? Type::TIME : Types::TIME_MUTABLE:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', [], Guess::HIGH_CONFIDENCE);
case 'time_immutable':
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE);
case Type::DECIMAL:
case self::$useDeprecatedConstants ? Type::DECIMAL : Types::DECIMAL:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', ['input' => 'string'], Guess::MEDIUM_CONFIDENCE);
case Type::FLOAT:
case self::$useDeprecatedConstants ? Type::FLOAT : Types::FLOAT:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', [], Guess::MEDIUM_CONFIDENCE);
case Type::INTEGER:
case Type::BIGINT:
case Type::SMALLINT:
case self::$useDeprecatedConstants ? Type::INTEGER : Types::INTEGER:
case self::$useDeprecatedConstants ? Type::BIGINT : Types::BIGINT:
case self::$useDeprecatedConstants ? Type::SMALLINT : Types::SMALLINT:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\IntegerType', [], Guess::MEDIUM_CONFIDENCE);
case Type::STRING:
case self::$useDeprecatedConstants ? Type::STRING : Types::STRING:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::MEDIUM_CONFIDENCE);
case Type::TEXT:
case self::$useDeprecatedConstants ? Type::TEXT : Types::TEXT:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextareaType', [], Guess::MEDIUM_CONFIDENCE);
default:
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE);
Expand All @@ -107,7 +114,7 @@ public function guessRequired($class, $property)

// Check whether the field exists and is nullable or not
if (isset($classMetadata->fieldMappings[$property])) {
if (!$classMetadata->isNullable($property) && Type::BOOLEAN !== $classMetadata->getTypeOfField($property)) {
if (!$classMetadata->isNullable($property) && (self::$useDeprecatedConstants ? Type::BOOLEAN : Types::BOOLEAN) !== $classMetadata->getTypeOfField($property)) {
return new ValueGuess(true, Guess::HIGH_CONFIDENCE);
}

Expand Down Expand Up @@ -144,7 +151,7 @@ public function guessMaxLength($class, $property)
return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE);
}

if (\in_array($ret[0]->getTypeOfField($property), [Type::DECIMAL, Type::FLOAT])) {
if (\in_array($ret[0]->getTypeOfField($property), self::$useDeprecatedConstants ? [Type::DECIMAL, Type::FLOAT] : [Types::DECIMAL, Types::FLOAT])) {
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
}
}
Expand All @@ -159,7 +166,7 @@ public function guessPattern($class, $property)
{
$ret = $this->getMetadata($class);
if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) {
if (\in_array($ret[0]->getTypeOfField($property), [Type::DECIMAL, Type::FLOAT])) {
if (\in_array($ret[0]->getTypeOfField($property), self::$useDeprecatedConstants ? [Type::DECIMAL, Type::FLOAT] : [Types::DECIMAL, Types::FLOAT])) {
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
}
}
Expand Down
59 changes: 34 additions & 25 deletions src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Bridge\Doctrine\PropertyInfo;

use Doctrine\DBAL\Types\Type as DBALType;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
Expand All @@ -33,6 +34,8 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE
private $entityManager;
private $classMetadataFactory;

private static $useDeprecatedConstants;

/**
* @param EntityManagerInterface $entityManager
*/
Expand All @@ -46,6 +49,10 @@ public function __construct($entityManager)
} else {
throw new \TypeError(sprintf('$entityManager must be an instance of "%s", "%s" given.', EntityManagerInterface::class, \is_object($entityManager) ? \get_class($entityManager) : \gettype($entityManager)));
}

if (null === self::$useDeprecatedConstants) {
self::$useDeprecatedConstants = !class_exists(Types::class);
}
}

/**
Expand Down Expand Up @@ -146,11 +153,11 @@ public function getTypes($class, $property, array $context = [])
switch ($builtinType) {
case Type::BUILTIN_TYPE_OBJECT:
switch ($typeOfField) {
case DBALType::DATE:
case DBALType::DATETIME:
case DBALType::DATETIMETZ:
case self::$useDeprecatedConstants ? DBALType::DATE : Types::DATE_MUTABLE:
case self::$useDeprecatedConstants ? DBALType::DATETIME : Types::DATETIME_MUTABLE:
case self::$useDeprecatedConstants ? DBALType::DATETIMETZ : Types::DATETIMETZ_MUTABLE:
case 'vardatetime':
case DBALType::TIME:
case self::$useDeprecatedConstants ? DBALType::TIME : Types::TIME_MUTABLE:
return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')];

case 'date_immutable':
Expand All @@ -166,11 +173,12 @@ public function getTypes($class, $property, array $context = [])
break;
case Type::BUILTIN_TYPE_ARRAY:
switch ($typeOfField) {
case DBALType::TARRAY:
case DBALType::JSON_ARRAY:
case self::$useDeprecatedConstants ? DBALType::TARRAY : Types::ARRAY:
case 'json_array':
case self::$useDeprecatedConstants ? false : Types::JSON:
return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)];

case DBALType::SIMPLE_ARRAY:
case self::$useDeprecatedConstants ? DBALType::SIMPLE_ARRAY : Types::SIMPLE_ARRAY:
return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))];
}
}
Expand Down Expand Up @@ -245,43 +253,44 @@ private function isAssociationNullable(array $associationMapping): bool
private function getPhpType(string $doctrineType): ?string
{
switch ($doctrineType) {
case DBALType::SMALLINT:
case DBALType::INTEGER:
case self::$useDeprecatedConstants ? DBALType::SMALLINT : Types::SMALLINT:
case self::$useDeprecatedConstants ? DBALType::INTEGER : Types::INTEGER:
return Type::BUILTIN_TYPE_INT;

case DBALType::FLOAT:
case self::$useDeprecatedConstants ? DBALType::FLOAT : Types::FLOAT:
return Type::BUILTIN_TYPE_FLOAT;

case DBALType::BIGINT:
case DBALType::STRING:
case DBALType::TEXT:
case DBALType::GUID:
case DBALType::DECIMAL:
case self::$useDeprecatedConstants ? DBALType::BIGINT : Types::BIGINT:
case self::$useDeprecatedConstants ? DBALType::STRING : Types::STRING:
case self::$useDeprecatedConstants ? DBALType::TEXT : Types::TEXT:
case self::$useDeprecatedConstants ? DBALType::GUID : Types::GUID:
case self::$useDeprecatedConstants ? DBALType::DECIMAL : Types::DECIMAL:
return Type::BUILTIN_TYPE_STRING;

case DBALType::BOOLEAN:
case self::$useDeprecatedConstants ? DBALType::BOOLEAN : Types::BOOLEAN:
return Type::BUILTIN_TYPE_BOOL;

case DBALType::BLOB:
case self::$useDeprecatedConstants ? DBALType::BLOB : Types::BLOB:
case 'binary':
return Type::BUILTIN_TYPE_RESOURCE;

case DBALType::OBJECT:
case DBALType::DATE:
case DBALType::DATETIME:
case DBALType::DATETIMETZ:
case self::$useDeprecatedConstants ? DBALType::OBJECT : Types::OBJECT:
case self::$useDeprecatedConstants ? DBALType::DATE : Types::DATE_MUTABLE:
case self::$useDeprecatedConstants ? DBALType::DATETIME : Types::DATETIME_MUTABLE:
case self::$useDeprecatedConstants ? DBALType::DATETIMETZ : Types::DATETIMETZ_MUTABLE:
case 'vardatetime':
case DBALType::TIME:
case self::$useDeprecatedConstants ? DBALType::TIME : Types::TIME_MUTABLE:
case 'date_immutable':
case 'datetime_immutable':
case 'datetimetz_immutable':
case 'time_immutable':
case 'dateinterval':
return Type::BUILTIN_TYPE_OBJECT;

case DBALType::TARRAY:
case DBALType::SIMPLE_ARRAY:
case DBALType::JSON_ARRAY:
case self::$useDeprecatedConstants ? DBALType::TARRAY : Types::ARRAY:
case self::$useDeprecatedConstants ? DBALType::SIMPLE_ARRAY : Types::SIMPLE_ARRAY:
case 'json_array':
case self::$useDeprecatedConstants ? false : Types::JSON:
return Type::BUILTIN_TYPE_ARRAY;
}

Expand Down
Expand Up @@ -12,7 +12,8 @@
namespace Symfony\Bridge\Doctrine\Security\RememberMe;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Types\Type as DoctrineType;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface;
use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface;
Expand Down Expand Up @@ -40,9 +41,15 @@ class DoctrineTokenProvider implements TokenProviderInterface
{
private $conn;

private static $useDeprecatedConstants;

public function __construct(Connection $conn)
{
$this->conn = $conn;

if (null === self::$useDeprecatedConstants) {
self::$useDeprecatedConstants = !class_exists(Types::class);
}
}

/**
Expand Down Expand Up @@ -90,7 +97,7 @@ public function updateToken($series, $tokenValue, \DateTime $lastUsed)
];
$paramTypes = [
'value' => \PDO::PARAM_STR,
'lastUsed' => DoctrineType::DATETIME,
'lastUsed' => self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE,
'series' => \PDO::PARAM_STR,
];
$updated = $this->conn->executeUpdate($sql, $paramValues, $paramTypes);
Expand Down Expand Up @@ -119,7 +126,7 @@ public function createNewToken(PersistentTokenInterface $token)
'username' => \PDO::PARAM_STR,
'series' => \PDO::PARAM_STR,
'value' => \PDO::PARAM_STR,
'lastUsed' => DoctrineType::DATETIME,
'lastUsed' => self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE,
];
$this->conn->executeUpdate($sql, $paramValues, $paramTypes);
}
Expand Down
Expand Up @@ -13,10 +13,12 @@

use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Type as DBALType;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\Setup;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor;
use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy210;
use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineGeneratedValue;
use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation;
use Symfony\Component\PropertyInfo\Type;
Expand Down Expand Up @@ -51,29 +53,40 @@ public function testLegacyGetProperties()

private function doTestGetProperties(bool $legacy)
{
// Fields
$expected = [
'id',
'guid',
'time',
'timeImmutable',
'dateInterval',
'jsonArray',
'simpleArray',
'float',
'decimal',
'bool',
'binary',
'customFoo',
'bigint',
];

if (class_exists(Types::class)) {
$expected[] = 'json';
}

// Associations
$expected = array_merge($expected, [
'foo',
'bar',
'indexedBar',
'indexedFoo',
'indexedByDt',
'indexedByCustomType',
]);

$this->assertEquals(
[
'id',
'guid',
'time',
'timeImmutable',
'dateInterval',
'json',
'simpleArray',
'float',
'decimal',
'bool',
'binary',
'customFoo',
'bigint',
'foo',
'bar',
'indexedBar',
'indexedFoo',
'indexedByDt',
'indexedByCustomType',
],
$this->createExtractor($legacy)->getProperties('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy')
$expected,
$this->createExtractor($legacy)->getProperties(!class_exists(Types::class) ? 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy' : DoctrineDummy210::class)
);
}

Expand Down Expand Up @@ -120,7 +133,7 @@ public function testLegacyExtract($property, array $type = null)

private function doTestExtract(bool $legacy, $property, array $type = null)
{
$this->assertEquals($type, $this->createExtractor($legacy)->getTypes('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy', $property, []));
$this->assertEquals($type, $this->createExtractor($legacy)->getTypes(!class_exists(Types::class) ? 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy' : DoctrineDummy210::class, $property, []));
}

public function testExtractWithEmbedded()
Expand Down Expand Up @@ -156,7 +169,7 @@ private function doTestExtractWithEmbedded(bool $legacy)

public function typesProvider()
{
return [
$provider = [
['id', [new Type(Type::BUILTIN_TYPE_INT)]],
['guid', [new Type(Type::BUILTIN_TYPE_STRING)]],
['bigint', [new Type(Type::BUILTIN_TYPE_STRING)]],
Expand All @@ -167,7 +180,7 @@ public function typesProvider()
['decimal', [new Type(Type::BUILTIN_TYPE_STRING)]],
['bool', [new Type(Type::BUILTIN_TYPE_BOOL)]],
['binary', [new Type(Type::BUILTIN_TYPE_RESOURCE)]],
['json', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]],
['jsonArray', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]],
['foo', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation')]],
['bar', [new Type(
Type::BUILTIN_TYPE_OBJECT,
Expand Down Expand Up @@ -206,6 +219,12 @@ public function typesProvider()
)]],
['indexedByCustomType', null],
];

if (class_exists(Types::class)) {
$provider[] = ['json', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]];
}

return $provider;
}

public function testGetPropertiesCatchException()
Expand Down
Expand Up @@ -74,7 +74,7 @@ class DoctrineDummy
/**
* @Column(type="json_array")
*/
private $json;
private $jsonArray;

/**
* @Column(type="simple_array")
Expand Down

0 comments on commit 88b96ab

Please sign in to comment.