PhpEnumType::getSQLDeclaration()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 3
rs 10
ccs 2
cts 2
cp 1
crap 1
1
<?php
2
declare(strict_types=1);
3
4
namespace JDecool\Doctrine\Type;
5
6
use Doctrine\DBAL\DBALException;
7
use Doctrine\DBAL\Platforms\AbstractPlatform;
8
use Doctrine\DBAL\Types\Type;
9
use JDecool\Doctrine\Exception\InvalidArgumentException;
10
use MabeEnum\Enum;
11
use function call_user_func;
12
use function implode;
13
use function is_string;
14
use function is_subclass_of;
15
use function method_exists;
16
use function sprintf;
17
18
class PhpEnumType extends Type
19
{
20
    /** @var string */
21
    private $name;
22
    /** @var string */
23
    protected $enumClass = Enum::class;
24
25
    /**
26
     * Gets the name of this type.
27
     *
28
     * @return string
29
     */
30 2
    public function getName()
31
    {
32 2
        return $this->name ?: 'enum';
33
    }
34
35
    /**
36
     * Gets the SQL declaration snippet for a field of this type.
37
     *
38
     * @param array $fieldDeclaration The field declaration.
39
     * @param AbstractPlatform $platform The currently used database platform.
40
     *
41
     * @return string
42
     */
43 1
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
44
    {
45 1
        return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration);
46
    }
47
48
    /**
49
     * @param string|null $value
50
     * @param AbstractPlatform $platform
51
     * @return mixed
52
     * @throws InvalidArgumentException
53
     */
54 4
    public function convertToPHPValue($value, AbstractPlatform $platform)
55
    {
56 4
        if ($value === null) {
57 1
            return null;
58
        }
59
60
        // If the enumeration provides a casting method, apply it
61 3
        if (method_exists($this->enumClass, 'castValueIn')) {
62
            /** @var callable $castValueIn */
63 1
            $castValueIn = [$this->enumClass, 'castValueIn'];
64 1
            $value = $castValueIn($value);
65
        }
66
67
        // Check if the value is valid for this enumeration
68
        /** @var callable $isValidCallable */
69 3
        $isValidCallable = [$this->enumClass, 'hasValue'];
70 3
        $isValid = $isValidCallable($value);
71 3
        if (! $isValid) {
72
            /** @var callable $toArray */
73 1
            $toArray = [$this->enumClass, 'getConstants'];
74 1
            throw new InvalidArgumentException(sprintf(
75 1
                'The value "%s" is not valid for the enum "%s". Expected one of ["%s"]',
76 1
                $value,
77 1
                $this->enumClass,
78 1
                implode('", "', $toArray())
79
            ));
80
        }
81
82 2
        return call_user_func([$this->enumClass, 'byValue'], $value);
83
    }
84
85 8
    public function convertToDatabaseValue($value, AbstractPlatform $platform)
86
    {
87 8
        if ($value === null) {
88 1
            return null;
89
        }
90
91
        // If the enumeration provides a casting method, apply it
92 7
        if (method_exists($this->enumClass, 'castValueOut')) {
93
            /** @var callable $castValueOut */
94 1
            $castValueOut = [$this->enumClass, 'castValueOut'];
95 1
            return $castValueOut($value);
96
        }
97
98 6
        return $value->getValue();
99
    }
100
101
    /**
102
     * @param string $typeNameOrEnumClass
103
     * @param string|null $enumClass
104
     * @throws InvalidArgumentException
105
     * @throws DBALException
106
     */
107 18
    public static function registerEnumType($typeNameOrEnumClass, $enumClass = null)
108
    {
109 18
        $typeName = $typeNameOrEnumClass;
110 18
        $enumClass = $enumClass ?: $typeNameOrEnumClass;
111
112 18
        if (! is_subclass_of($enumClass, Enum::class)) {
113 1
            throw new InvalidArgumentException(sprintf(
114 1
                'Provided enum class "%s" is not valid. Enums must extend "%s"',
115 1
                $enumClass,
116 1
                Enum::class
117
            ));
118
        }
119
120
        // Register and customize the type
121 17
        self::addType($typeName, static::class);
122
        /** @var PhpEnumType $type */
123 17
        $type = self::getType($typeName);
124 17
        $type->name = $typeName;
125 17
        $type->enumClass = $enumClass;
126
    }
127
128
    /**
129
     * @param array $types
130
     * @throws InvalidArgumentException
131
     * @throws DBALException
132
     */
133 2
    public static function registerEnumTypes(array $types)
134
    {
135 2
        foreach ($types as $typeName => $enumClass) {
136 2
            $typeName = is_string($typeName) ? $typeName : $enumClass;
137 2
            static::registerEnumType($typeName, $enumClass);
138
        }
139
    }
140
141
    /**
142
     * @param AbstractPlatform $platform
143
     * @return boolean
144
     */
145 1
    public function requiresSQLCommentHint(AbstractPlatform $platform)
146
    {
147 1
        return true;
148
    }
149
}
150