SingleTableInheritanceTrait::init()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 1
cts 1
cp 1
crap 1
rs 10
1
<?php
2
3
namespace SamIT\Yii2\SingleTableInheritance;
4
5
trait SingleTableInheritanceTrait
6
{
7
    abstract public function setAttribute($name, $value);
8
9
    /**
10
     * @var string Name of the column that identifies the type of the record
11
     */
12
    private static string $typeColumn;
13
14
    /**
15
     * @var string A class name to use if the type column contains an unknown value
16
     */
17
    private static string $defaultClass;
18
19
    /**
20
     * @var string[]
21
     */
22
    private static $classToType;
23
    /**
24
     * @var string[]
25
     */
26
    private static $typeToClass;
27
28
    /**
29
     * Returns an array with keys 'map' and 'column'
30
     * where 'map' contains a map of type => class
31
     * and 'column' contains the column name
32
     * [
33
     *      'map' => [
34
     *          \app\Car::class => 'car'
35
     *      ],
36
     *      'column' => 'type'
37
     * ]
38 2
     * This function should return the same map every time
39
     * @return array
40 2
     */
41
    private static function inheritanceConfig(): array
42
    {
43 6
        throw new \Exception('Inheritance config must be implemented');
44
    }
45 6
46 2
    private static function initCache(): void
47 2
    {
48 2
        if (!isset(self::$typeColumn)) {
49 2
            $config = self::inheritanceConfig();
50
            self::$typeColumn = $config['column'];
51 6
            self::$defaultClass = $config['default'] ?? self::class;
52
            self::$classToType = $config['map'];
53
            self::$typeToClass = array_flip($config['map']);
54
        }
55
    }
56
57
    /**
58 2
     * @param $class
59
     * @return string|null
60 2
     * @throws \Exception
61 2
     */
62
    final public static function getTypeFromClass($class): ?string
63 2
    {
64 2
        self::initCache();
65
        if (isset(self::$classToType[$class])) {
66
            return self::$classToType[$class];
67
        } elseif (false !== $parent = get_parent_class($class)) {
68
            return self::getTypeFromClass($parent);
69
        }
70 2
71
        return null;
72 2
    }
73 2
74
    /**
75
     * @return string
76 2
     */
77
    final public static function getInheritanceColumn(): string
78 2
    {
79 2
        self::initCache();
80 2
        return self::$typeColumn;
81
    }
82
83
    public function init(): void
84
    {
85 2
        self::initSingleTableInheritance($this);
86
        parent::init();
87 2
    }
88
89
    /**
90 2
     * @param array $row The attributes for the row. We don't use a param type hint because the base class doesn't
91
     */
92 2
    public static function instantiate($row): self
93 2
    {
94
        return self::instantiateSingleTableInheritance($row);
95
    }
96 2
97
    private static function getClassFromType(?string $type): string
98 2
    {
99 2
        return self::$typeToClass[$type] ?? self::$defaultClass;
100
    }
101 2
102
    private static function initSingleTableInheritance(self $model): void
103 2
    {
104 2
        $model->setAttribute(self::getInheritanceColumn(), self::getTypeFromClass(static::class));
105
    }
106
107
    private static function instantiateSingleTableInheritance($row): self
108
    {
109
        self::initCache();
110
        $class = self::getClassFromType($row[self::$typeColumn] ?? null);
111
        return new $class;
112
    }
113
}
114