Passed
Push — master ( 309ddd...ddc92e )
by Marijan
02:38
created

EnumType   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 122
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 45
dl 0
loc 122
rs 10
c 0
b 0
f 0
wmc 18

9 Methods

Rating   Name   Duplication   Size   Complexity  
A convertToPHPValue() 0 16 4
A convertToDatabaseValue() 0 15 3
A ensureEnumClassIsSetAndValid() 0 11 2
A assertElementNameLengthIsValid() 0 14 2
A ensureStateIsValid() 0 4 1
A ensureEnumLengthsAreValid() 0 10 3
A getSQLDeclaration() 0 6 1
A requiresSQLCommentHint() 0 5 1
A columnLength() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Zlikavac32\DoctrineEnum\DBAL\Types;
6
7
use Doctrine\DBAL\Platforms\AbstractPlatform;
8
use Doctrine\DBAL\Types\ConversionException;
9
use Doctrine\DBAL\Types\Type;
10
use LogicException;
11
use function Zlikavac32\Enum\assertFqnIsEnumClass;
12
use Zlikavac32\Enum\Enum;
13
use Zlikavac32\Enum\EnumNotFoundException;
14
15
abstract class EnumType extends Type
16
{
17
    /**
18
     * @var string|Enum
19
     */
20
    private $enumClass;
21
22
    private $checkedForNameLengths = false;
23
24
    final public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
25
    {
26
        $this->ensureStateIsValid();
27
28
        return $platform->getVarcharTypeDeclarationSQL([
29
            'length' => $this->columnLength()
30
        ]);
31
    }
32
33
    final public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
34
    {
35
        $this->ensureStateIsValid();
36
37
        if (null === $value) {
38
            return null;
39
        }
40
41
        if (false === ($value instanceof $this->enumClass)) {
42
            throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', $this->enumClass]);
43
        }
44
45
        $name = $value->name();
46
47
        return $name;
48
    }
49
50
    final public function convertToPHPValue($value, AbstractPlatform $platform): ?Enum
51
    {
52
        $this->ensureStateIsValid();
53
54
        if (null === $value) {
55
            return null;
56
        }
57
58
        if (false === is_string($value)) {
59
            throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string']);
60
        }
61
62
        try {
63
            return $this->enumClass::valueOf($value);
64
        } catch (EnumNotFoundException $e) {
65
            throw ConversionException::conversionFailed($value, $this->getName());
66
        }
67
    }
68
69
    final public function requiresSQLCommentHint(AbstractPlatform $platform)
70
    {
71
        $this->ensureStateIsValid();
72
73
        return true;
74
    }
75
76
    private function ensureStateIsValid(): void
77
    {
78
        $this->ensureEnumClassIsSetAndValid();
79
        $this->ensureEnumLengthsAreValid();
80
    }
81
82
    private function ensureEnumClassIsSetAndValid(): void
83
    {
84
        if (is_string($this->enumClass)) {
85
            return ;
86
        }
87
88
        $enumClass = $this->enumClass();
89
90
        assertFqnIsEnumClass($enumClass);
91
92
        $this->enumClass = $enumClass;
93
    }
94
95
    private function ensureEnumLengthsAreValid(): void
96
    {
97
        if ($this->checkedForNameLengths) {
98
            return ;
99
        }
100
101
        $columnLength = $this->columnLength();
102
103
        foreach ($this->enumClass::values() as $element) {
104
            $this->assertElementNameLengthIsValid($element, $columnLength);
105
        }
106
    }
107
108
    private function assertElementNameLengthIsValid(Enum $element, int $columnLength): void
109
    {
110
        $elementName = $element->name();
111
112
        if (strlen($elementName) <= $columnLength) {
113
            return ;
114
        }
115
116
        throw new LogicException(
117
            sprintf(
118
                '%s::%s() is longer than %d characters',
119
                $this->enumClass,
120
                $elementName,
121
                $columnLength
122
            )
123
        );
124
    }
125
126
    abstract protected function enumClass(): string;
127
128
    /**
129
     * Column length used for variable character column definition that will hold the enum name as a value. Override
130
     * if 32 is to big or to small.
131
     *
132
     * @return int
133
     */
134
    protected function columnLength(): int
135
    {
136
        return 32;
137
    }
138
}
139