-
-
Notifications
You must be signed in to change notification settings - Fork 75
/
Copy pathEnumTypeGuesser.php
101 lines (85 loc) · 3.17 KB
/
EnumTypeGuesser.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<?php
/*
* This file is part of the FreshDoctrineEnumBundle.
*
* (c) Artem Henvald <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Fresh\DoctrineEnumBundle\Form;
use Doctrine\Persistence\ManagerRegistry;
use Fresh\DoctrineEnumBundle\DBAL\Types\AbstractEnumType;
use Fresh\DoctrineEnumBundle\Exception\EnumType\EnumTypeIsRegisteredButClassDoesNotExistException;
use JetBrains\PhpStorm\Pure;
use Symfony\Bridge\Doctrine\Form\DoctrineOrmTypeGuesser;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
/**
* EnumTypeGuesser.
*
* @author Artem Henvald <[email protected]>
* @author Jaik Dean <[email protected]>
*/
class EnumTypeGuesser extends DoctrineOrmTypeGuesser
{
/** @var string[] */
private array $registeredEnumTypes = [];
/**
* @param ManagerRegistry $registry
* @param array<string, array<string, string>> $registeredTypes
*/
#[Pure]
public function __construct(ManagerRegistry $registry, array $registeredTypes)
{
parent::__construct($registry);
foreach ($registeredTypes as $type => $details) {
$this->registeredEnumTypes[$type] = $details['class'];
}
}
/**
* @template T of object
*
* @param class-string<T> $class
* @param string $property
*
* @throws EnumTypeIsRegisteredButClassDoesNotExistException
*
* @return TypeGuess|null
*/
public function guessType(string $class, string $property): ?TypeGuess
{
$classMetadata = $this->getMetadata($class);
// If no metadata for this class - can't guess anything
if (!$classMetadata) {
return null;
}
/** @var \Doctrine\ORM\Mapping\ClassMetadata<object> $metadata */
[$metadata] = $classMetadata;
$fieldType = $metadata->getTypeOfField($property);
// This is not one of the registered ENUM types
if (!\is_string($fieldType) || !isset($this->registeredEnumTypes[$fieldType])) {
return null;
}
$registeredEnumTypeFQCN = $this->registeredEnumTypes[$fieldType];
if (!\class_exists($registeredEnumTypeFQCN)) {
$exceptionMessage = \sprintf(
'ENUM type "%s" is registered as "%s", but that class does not exist',
$fieldType,
$registeredEnumTypeFQCN
);
throw new EnumTypeIsRegisteredButClassDoesNotExistException($exceptionMessage);
}
if (!\is_subclass_of($registeredEnumTypeFQCN, AbstractEnumType::class)) {
return null;
}
/** @var AbstractEnumType<int|string, int|string> $registeredEnumTypeFQCN */
$parameters = [
'choices' => $registeredEnumTypeFQCN::getChoices(), // Get the choices from the fully qualified class name
'required' => !$metadata->isNullable($property),
];
return new TypeGuess(ChoiceType::class, $parameters, Guess::VERY_HIGH_CONFIDENCE);
}
}