Completed
Push — master ( 55e3ba...9e6dea )
by Artem
11s
created

AbstractEnumType::convertToPHPValue()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 2
1
<?php
2
/*
3
 * This file is part of the FreshDoctrineEnumBundle
4
 *
5
 * (c) Artem Henvald <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types=1);
12
13
namespace Fresh\DoctrineEnumBundle\DBAL\Types;
14
15
use Doctrine\DBAL\Platforms\AbstractPlatform;
16
use Doctrine\DBAL\Platforms\MySqlPlatform;
17
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
18
use Doctrine\DBAL\Platforms\SqlitePlatform;
19
use Doctrine\DBAL\Platforms\SQLServerPlatform;
20
use Doctrine\DBAL\Types\Type;
21
22
/**
23
 * AbstractEnumType.
24
 *
25
 * Provides support of ENUM type for Doctrine in Symfony applications.
26
 *
27
 * @author Artem Henvald <[email protected]>
28
 * @author Ben Davies <[email protected]>
29
 * @author Jaik Dean <[email protected]>
30
 */
31
abstract class AbstractEnumType extends Type
32
{
33
    /** @var string */
34
    protected $name = '';
35
36
    /**
37
     * @var array Array of ENUM Values, where ENUM values are keys and their readable versions are values
38
     *
39
     * @static
40
     */
41
    protected static $choices = [];
42
43
    /**
44
     * {@inheritdoc}
45
     *
46
     * @throws \InvalidArgumentException
47
     */
48
    public function convertToDatabaseValue($value, AbstractPlatform $platform)
49
    {
50
        if (null === $value) {
51
            return null;
52
        }
53
54 View Code Duplication
        if (!isset(static::$choices[$value])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
55
            throw new \InvalidArgumentException(\sprintf('Invalid value "%s" for ENUM "%s".', $value, $this->getName()));
56
        }
57
58
        return $value;
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64
    public function convertToPHPValue($value, AbstractPlatform $platform)
65
    {
66
        if (!isset(static::$choices[$value])) {
67
            return $value;
68
        }
69
70
        // Check whether choice list is using integers as valies
71
        $choice = static::$choices[$value];
72
        $choices = array_flip(static::$choices);
73
        if (is_int($choices[$choice])) {
74
            return (int) $value;
75
        }
76
77
        return $value;
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
84
    {
85
        $values = \implode(
86
            ', ',
87
            \array_map(
88
                function ($value) {
89
                    return "'{$value}'";
90
                },
91
                static::getValues()
92
            )
93
        );
94
95
        if ($platform instanceof SqlitePlatform) {
96
            return \sprintf('TEXT CHECK(%s IN (%s))', $fieldDeclaration['name'], $values);
97
        }
98
99
        if ($platform instanceof PostgreSqlPlatform || $platform instanceof SQLServerPlatform) {
100
            return \sprintf('VARCHAR(255) CHECK(%s IN (%s))', $fieldDeclaration['name'], $values);
101
        }
102
103
        return \sprintf('ENUM(%s)', $values);
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function requiresSQLCommentHint(AbstractPlatform $platform): bool
110
    {
111
        return true;
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117
    public function getName()
118
    {
119
        return $this->name ?: \array_search(\get_class($this), self::getTypesMap(), true);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->name ?: \array_se...::getTypesMap(), true); of type false|integer|string adds false to the return on line 119 which is incompatible with the return type declared by the abstract method Doctrine\DBAL\Types\Type::getName of type string. It seems like you forgot to handle an error condition.
Loading history...
120
    }
121
122
    /**
123
     * Get readable choices for the ENUM field.
124
     *
125
     * @static
126
     *
127
     * @return array Values for the ENUM field
128
     */
129
    public static function getChoices(): array
130
    {
131
        return \array_flip(static::$choices);
132
    }
133
134
    /**
135
     * Get values for the ENUM field.
136
     *
137
     * @static
138
     *
139
     * @return array Values for the ENUM field
140
     */
141
    public static function getValues(): array
142
    {
143
        return \array_keys(static::$choices);
144
    }
145
146
    /**
147
     * Get array of ENUM Values, where ENUM values are keys and their readable versions are values.
148
     *
149
     * @static
150
     *
151
     * @return array Array of values with readable format
152
     */
153
    public static function getReadableValues(): array
154
    {
155
        return static::$choices;
156
    }
157
158
    /**
159
     * Asserts that given choice exists in the array of ENUM values.
160
     *
161
     * @param string $value ENUM value
162
     *
163
     * @throws \InvalidArgumentException
164
     */
165
    public static function assertValidChoice(string $value)
166
    {
167 View Code Duplication
        if (!isset(static::$choices[$value])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
168
            throw new \InvalidArgumentException(\sprintf('Invalid value "%s" for ENUM type "%s".', $value, static::class));
169
        }
170
    }
171
172
    /**
173
     * Get value in readable format.
174
     *
175
     * @param string $value ENUM value
176
     *
177
     * @static
178
     *
179
     * @return string $value Value in readable format
180
     *
181
     * @throws \InvalidArgumentException
182
     */
183
    public static function getReadableValue(string $value): string
184
    {
185
        static::assertValidChoice($value);
186
187
        return static::$choices[$value];
188
    }
189
190
    /**
191
     * Check if some string value exists in the array of ENUM values.
192
     *
193
     * @param string $value ENUM value
194
     *
195
     * @static
196
     *
197
     * @return bool
198
     */
199
    public static function isValueExist(string $value): bool
200
    {
201
        return isset(static::$choices[$value]);
202
    }
203
204
    /**
205
     * Gets an array of database types that map to this Doctrine type.
206
     *
207
     * @param AbstractPlatform $platform
208
     *
209
     * @return array
210
     */
211
    public function getMappedDatabaseTypes(AbstractPlatform $platform): array
212
    {
213
        if ($platform instanceof MySqlPlatform) {
214
            return \array_merge(parent::getMappedDatabaseTypes($platform), ['enum']);
215
        }
216
217
        return parent::getMappedDatabaseTypes($platform);
218
    }
219
}
220