Completed
Push — master ( 841809...a453a7 )
by Artem
11s
created

AbstractEnumType::getRandomValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
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 values
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(): string
118
    {
119
        return $this->name ?: \array_search(\get_class($this), self::getTypesMap(), true);
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 random value for the ENUM field.
148
     *
149
     * @static
150
     *
151
     * @return int|string
152
     */
153
    public static function getRandomValue()
154
    {
155
        $values = self::getValues();
156
        $randomKey = \random_int(0, \count($values) - 1);
157
158
        return $values[$randomKey];
159
    }
160
161
    /**
162
     * Get array of ENUM Values, where ENUM values are keys and their readable versions are values.
163
     *
164
     * @static
165
     *
166
     * @return array Array of values with readable format
167
     */
168
    public static function getReadableValues(): array
169
    {
170
        return static::$choices;
171
    }
172
173
    /**
174
     * Asserts that given choice exists in the array of ENUM values.
175
     *
176
     * @param string $value ENUM value
177
     *
178
     * @throws \InvalidArgumentException
179
     */
180
    public static function assertValidChoice(string $value): void
181
    {
182 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...
183
            throw new \InvalidArgumentException(\sprintf('Invalid value "%s" for ENUM type "%s".', $value, static::class));
184
        }
185
    }
186
187
    /**
188
     * Get value in readable format.
189
     *
190
     * @param string $value ENUM value
191
     *
192
     * @static
193
     *
194
     * @return string $value Value in readable format
195
     */
196
    public static function getReadableValue(string $value): string
197
    {
198
        static::assertValidChoice($value);
199
200
        return static::$choices[$value];
201
    }
202
203
    /**
204
     * Check if some string value exists in the array of ENUM values.
205
     *
206
     * @param string $value ENUM value
207
     *
208
     * @static
209
     *
210
     * @return bool
211
     */
212
    public static function isValueExist(string $value): bool
213
    {
214
        return isset(static::$choices[$value]);
215
    }
216
217
    /**
218
     * Gets an array of database types that map to this Doctrine type.
219
     *
220
     * @param AbstractPlatform $platform
221
     *
222
     * @return array
223
     */
224
    public function getMappedDatabaseTypes(AbstractPlatform $platform): array
225
    {
226
        if ($platform instanceof MySqlPlatform) {
227
            return \array_merge(parent::getMappedDatabaseTypes($platform), ['enum']);
228
        }
229
230
        return parent::getMappedDatabaseTypes($platform);
231
    }
232
}
233