Completed
Push — master ( 7c9586...c8ce39 )
by Oscar
01:44
created

FieldFactory::get()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
declare(strict_types = 1);
3
4
namespace SimpleCrud;
5
6
use SimpleCrud\Fields\Boolean;
7
use SimpleCrud\Fields\Date;
8
use SimpleCrud\Fields\Datetime;
9
use SimpleCrud\Fields\Decimal;
10
use SimpleCrud\Fields\Field;
11
use SimpleCrud\Fields\FieldInterface;
12
use SimpleCrud\Fields\Integer;
13
use SimpleCrud\Fields\Json;
14
use SimpleCrud\Fields\Point;
15
use SimpleCrud\Fields\Set;
16
17
/**
18
 * Class to create instances of fields.
19
 */
20
final class FieldFactory implements FieldFactoryInterface
21
{
22
    private $defaultType = Field::class;
23
    private $fields = [
24
        Boolean::class => [
25
            'names' => ['active', '/^(is|has)[A-Z]/'],
26
            'types' => ['boolean'],
27
            'config' => [],
28
        ],
29
        Date::class => [
30
            'names' => [],
31
            'types' => ['date'],
32
            'config' => [],
33
        ],
34
        Datetime::class => [
35
            'names' => ['pubdate', '/[a-z]At$/'],
36
            'types' => ['datetime'],
37
            'config' => [],
38
        ],
39
        Decimal::class => [
40
            'names' => [],
41
            'types' => ['decimal', 'float', 'real'],
42
            'config' => [],
43
        ],
44
        Field::class => [
45
            'names' => [],
46
            'types' => [],
47
            'config' => [],
48
        ],
49
        Integer::class => [
50
            'names' => ['id','/_id$/'],
51
            'types' => ['bigint', 'int', 'mediumint', 'smallint', 'tinyint', 'year'],
52
            'config' => [],
53
        ],
54
        Json::class => [
55
            'names' => [],
56
            'types' => ['json'],
57
            'config' => [],
58
        ],
59
        Point::class => [
60
            'names' => [],
61
            'types' => ['point'],
62
            'config' => [],
63
        ],
64
        Set::class => [
65
            'names' => [],
66
            'types' => ['set'],
67
            'config' => [],
68
        ],
69
    ];
70
71
    public function defineField(string $className, array $definition): self
72
    {
73
        if (isset($this->fields[$className])) {
74
            $this->fields[$className] = $definition;
75
            return $this;
76
        }
77
78
        $this->fields = [$className => $definition] + $this->fields;
79
80
        return $this;
81
    }
82
83
    public function getFieldDefinition(string $className): ?array
84
    {
85
        return $this->fields[$className] ?? null;
86
    }
87
88
    /**
89
     * @see FieldFactoryInterface
90
     *
91
     * {@inheritdoc}
92
     */
93
    public function get(Table $table, array $info): FieldInterface
94
    {
95
        $className = $this->getClassName($info['name'], $info['type']);
96
97
        if (class_exists($className)) {
98
            $field = new $className($table, $info);
99
            $config = $this->fields[$className]['config'] ?? [];
100
101
            foreach ($config as $name => $value) {
102
                $field->setConfig($name, $value);
103
            }
104
105
            return $field;
106
        }
107
108
        throw new SimpleCrudException("No field class found for '{$className}'");
109
    }
110
111
    /**
112
     * Get the field class name.
113
     */
114
    private function getClassName(string $name, string $type): ?string
115
    {
116
        foreach ($this->fields as $className => $definition) {
117
            foreach ($definition['names'] as $defName) {
118
                if ($defName === $name || ($defName[0] === '/' && preg_match($defName, $name))) {
119
                    return $className;
120
                }
121
            }
122
123
            if (in_array($type, $definition['types'])) {
124
                return $className;
125
            }
126
        }
127
128
        return $this->defaultType;
129
    }
130
}
131