Passed
Pull Request — master (#23)
by Adrien
17:46 queued 04:32
created

SetType::convertToPHPValue()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 6
c 1
b 0
f 0
nc 5
nop 2
dl 0
loc 13
ccs 7
cts 7
cp 1
crap 4
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ecodev\Felix\DBAL\Types;
6
7
use Doctrine\DBAL\Platforms\AbstractPlatform;
8
use Doctrine\DBAL\Types\Type;
9
use Exception;
10
use InvalidArgumentException;
11
use ReflectionClass;
12
13
abstract class SetType extends Type
14
{
15 1
    public function getSqlDeclaration(array $column, AbstractPlatform $platform): string
16
    {
17 1
        $possibleValues = $this->getPossibleValues();
18 1
        $quotedPossibleValues = implode(', ', array_map(fn ($str) => "'" . $str . "'", $possibleValues));
19
20 1
        $sql = 'SET(' . $quotedPossibleValues . ')';
21
22 1
        return $sql;
23
    }
24
25
    /**
26
     * @return ($value is null ? null : array)
27
     */
28 3
    public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?array
29
    {
30 3
        if ($value === null) {
31 1
            return null;
32
        }
33
34 3
        $values = is_string($value) ? preg_split('/,/', $value, -1, PREG_SPLIT_NO_EMPTY) : null;
35 3
        if (!$this->isValid($values)) {
36 2
            throw new InvalidArgumentException("Invalid '" . $value . "' value fetched from database for set " . $this->getName());
37
        }
38
39
        /** @var array $values */
40 1
        return $values;
41
    }
42
43
    /**
44
     * @return ($value is null ? null : string)
45
     */
46 4
    public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?string
47
    {
48 4
        if ($value === null) {
49 1
            return null;
50
        }
51
52 4
        $result = is_array($value) ? implode(',', $value) : null;
53 4
        if (!$this->isValid($value)) {
54 3
            throw new InvalidArgumentException("Invalid '" . $result . "' value to be stored in database for set " . $this->getName());
55
        }
56
57 1
        return $result;
58
    }
59
60 6
    private function isValid(mixed $values): bool
61
    {
62 6
        if (!is_array($values)) {
63 3
            return false;
64
        }
65
66 3
        $possibleValues = $this->getPossibleValues();
67 3
        foreach ($values as $value) {
68 3
            if (!in_array($value, $possibleValues, true)) {
69 2
                return false;
70
            }
71
        }
72
73 1
        return true;
74
    }
75
76
    /**
77
     * Return all possibles values as an array of string.
78
     *
79
     * @return string[]
80
     */
81
    abstract protected function getPossibleValues(): array;
82
83
    /**
84
     * Returns the type name based on actual class name and possible values.
85
     */
86 6
    public function getName(): string
87
    {
88 6
        $class = new ReflectionClass($this);
89 6
        $shortClassName = $class->getShortName();
90 6
        $typeName = preg_replace('/Type$/', '', $shortClassName);
91
92 6
        if ($typeName === null) {
93
            throw new Exception('Could not extract set name from class name');
94
        }
95
96 6
        return $typeName;
97
    }
98
99 1
    public function getMappedDatabaseTypes(AbstractPlatform $platform): array
100
    {
101 1
        return ['set'];
102
    }
103
}
104