Passed
Push — master ( c4a808...c45372 )
by Gabriel
15:08
created

Definition::getField()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace ByTIC\Models\SmartProperties\Definitions;
4
5
use ByTIC\Models\SmartProperties\Properties\AbstractProperty\Generic;
6
use ByTIC\Models\SmartProperties\Properties\AbstractProperty\Generic as Property;
7
use ByTIC\Models\SmartProperties\RecordsTraits\HasSmartProperties\RecordsTrait;
8
use Exception;
9
use Nip\Records\RecordManager;
10
11
/**
12
 * Class Definition
13
 * @package ByTIC\Models\SmartProperties\Definitions
14
 */
15
class Definition implements \Serializable
16
{
17
    use Traits\HasName;
18
    use Traits\HasPlaces;
19
    use Traits\Serializable;
20
21
    /**
22
     * @var RecordManager|RecordsTrait
23
     */
24
    protected $manager;
25
26
27
    /**
28
     * @var string
29
     */
30
    protected $label = null;
31
32
    /**
33
     * @var string
34
     */
35
    protected $field;
36
37
    protected $items = null;
38
    protected $itemsAliases = [];
39
40
    protected $defaultValue = null;
41
42
    /**
43
     * @param $name
44
     *
45
     * @return Property
46
     * @throws Exception
47
     */
48
    public function getItem($name): Property
49
    {
50
        $items = $this->getItems();
51
        if (!$this->hasItem($name)) {
52
            throw new Exception(
53
                'Bad Item [' . $name . '] for smart property 
54
                [' . $this->getManager()->getController() . '::' . $this->getName() . ']
55
                [' . implode(',', array_keys($items)) . ']'
0 ignored issues
show
Bug introduced by
It seems like $items can also be of type null; however, parameter $array of array_keys() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

55
                [' . implode(',', array_keys(/** @scrutinizer ignore-type */ $items)) . ']'
Loading history...
56
            );
57
        }
58
        if (isset($this->itemsAliases[$name])) {
59
            $name = $this->itemsAliases[$name];
60
        }
61
        return $items[$name];
62
    }
63
64
    /**
65
     * @return null|Property[]
66
     */
67
    public function getItems(): ?array
68
    {
69
        if ($this->items == null) {
70
            $this->initItems();
71
        }
72
73
        return $this->items;
74
    }
75
76
    public function initItems()
77
    {
78
        $names = $this->getPlaces();
79
        $this->items = [];
80
        foreach ($names as $name) {
81
            $object = $this->newProperty($name);
82
            $this->addItem($object);
83
        }
84
    }
85
86
    /**
87
     * @return string|null
88
     */
89
    public function getField(): ?string
90
    {
91
        return $this->field;
92
    }
93
94
    /**
95
     * @param mixed $field
96
     */
97
    public function setField($field)
98
    {
99
        $this->field = $field;
100
    }
101
102
    /**
103
     * @return RecordManager
104
     */
105
    public function getManager()
106
    {
107
        return $this->manager;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->manager also could return the type ByTIC\Models\SmartProper...Properties\RecordsTrait which is incompatible with the documented return type Nip\Records\RecordManager.
Loading history...
108
    }
109
110
    /**
111
     * @param RecordManager|RecordsTrait $manager
112
     */
113
    public function setManager($manager)
114
    {
115
        $this->manager = $manager;
116
    }
117
118
    /**
119
     * @return string
120
     */
121
    public function getLabel(): ?string
122
    {
123
        if ($this->label === null) {
124
            $this->initLabel();
125
        }
126
127
        return $this->label;
128
    }
129
130
    /**
131
     * @param string $label
132
     */
133
    public function setLabel(string $label)
134
    {
135
        $this->label = $label;
136
    }
137
138
    protected function initLabel()
139
    {
140
        $name = inflector()->pluralize($this->getName());
141
        $this->setLabel($name);
142
    }
143
144
    /**
145
     * @param string $type
146
     *
147
     * @return Property
148
     */
149
    public function newProperty($type = null): Property
150
    {
151
        $className = $this->getPropertyClass($type);
0 ignored issues
show
Bug introduced by
It seems like $type can also be of type string; however, parameter $type of ByTIC\Models\SmartProper...ion::getPropertyClass() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

151
        $className = $this->getPropertyClass(/** @scrutinizer ignore-type */ $type);
Loading history...
152
        $object = new $className();
153
        /** @var Property $object */
154
        $object->setManager($this->getManager());
155
        $object->setField($this->getField());
156
        $object->setNamespace($this->getPropertyItemsRootNamespace());
157
        return $object;
158
    }
159
160
    /**
161
     * @param null $type
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $type is correct as it would always require null to be passed?
Loading history...
162
     *
163
     * @return string
164
     */
165
    public function getPropertyClass($type = null): string
166
    {
167
        $type = $type ?: $this->getDefaultValue();
0 ignored issues
show
introduced by
$type is of type null, thus it always evaluated to false.
Loading history...
168
        $type = str_replace(DIRECTORY_SEPARATOR, '\\', $type);
169
170
        return $this->getPropertyItemsRootNamespace() . inflector()->classify($type);
171
    }
172
173
    /**
174
     * @return string
175
     */
176
    public function getDefaultValue(): ?string
177
    {
178
        if ($this->defaultValue === null) {
179
            $this->initDefaultValue();
180
        }
181
182
        return $this->defaultValue;
183
    }
184
185
    /**
186
     * @param null $defaultValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $defaultValue is correct as it would always require null to be passed?
Loading history...
187
     */
188
    public function setDefaultValue($defaultValue)
189
    {
190
        $this->defaultValue = $defaultValue;
191
    }
192
193
    /**
194
     * @param Generic $object
195
     */
196
    protected function addItem(Property $object)
197
    {
198
        $this->items[$object->getName()] = $object;
199
        $aliases = $object->getAliases();
200
        foreach ($aliases as $alias) {
201
            $this->itemsAliases[$alias] = $object->getName();
202
        }
203
    }
204
205
    protected function initDefaultValue()
206
    {
207
        $managerDefaultValue = $this->getDefaultValueFromManager();
208
        if ($managerDefaultValue && $this->hasItem($managerDefaultValue)) {
209
            $defaultValue = $managerDefaultValue;
210
        } else {
211
            $keys = array_keys($this->getItems());
0 ignored issues
show
Bug introduced by
It seems like $this->getItems() can also be of type null; however, parameter $array of array_keys() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

211
            $keys = array_keys(/** @scrutinizer ignore-type */ $this->getItems());
Loading history...
212
            $defaultValue = reset($keys);
213
        }
214
        $this->setDefaultValue($defaultValue);
0 ignored issues
show
Bug introduced by
It seems like $defaultValue can also be of type string and true; however, parameter $defaultValue of ByTIC\Models\SmartProper...tion::setDefaultValue() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

214
        $this->setDefaultValue(/** @scrutinizer ignore-type */ $defaultValue);
Loading history...
215
    }
216
217
    /**
218
     * @return bool|string
219
     */
220
    protected function getDefaultValueFromManager()
221
    {
222
        $method = 'getDefault' . $this->getName();
223
        if (method_exists($this->getManager(), $method)) {
224
            return $this->getManager()->{$method}();
225
        }
226
227
        return false;
228
    }
229
230
    /**
231
     * @param $name
232
     * @return bool
233
     */
234
    public function hasItem($name): bool
235
    {
236
        $items = $this->getItems();
237
238
        return isset($items[$name]) || isset($this->itemsAliases[$name]);
239
    }
240
241
    /**
242
     * @return string
243
     */
244
    protected function getPropertyItemsRootNamespace(): string
245
    {
246
        $manager = $this->getManager();
247
        $method = 'get' . $this->getName() . 'ItemsRootNamespace';
248
        if (method_exists($manager, $method)) {
249
            return $manager->{$method}();
250
        }
251
252
        $method = 'get' . $this->getName() . 'Namespace';
253
        if (method_exists($manager, $method)) {
254
            return $manager->{$method}();
255
        }
256
257
        return $manager->getModelNamespace() . $this->getLabel() . '\\';
258
    }
259
260
    /**
261
     * @param $name
262
     *
263
     * @return array
264
     */
265
    public function getValues($name): array
266
    {
267
        $return = [];
268
        $items = $this->getItems();
269
270
        foreach ($items as $type) {
271
            $method = 'get' . ucfirst($name);
272
            if (method_exists($type, $method)) {
273
                $return[] = $type->$method();
274
            } else {
275
                $return[] = $type->{$name};
276
            }
277
        }
278
279
        return $return;
280
    }
281
}
282