Test Failed
Push — main ( 706477...92dbda )
by Yaroslav
03:43
created

FlexibleAttribute::getFlexibleFileAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace NovaFlexibleContent\Http;
4
5
use Illuminate\Support\Arr;
6
7
class FlexibleAttribute
8
{
9
    /**
10
     * The attribute key name of all flexible field in request.
11
     *
12
     * @var string
13
     */
14
    const REGISTER_FLEXIBLE_FIELD_NAME = '___nova_flexible_content_fields';
15
16
    /**
17
     * The string that identifies an "upload" value.
18
     *
19
     * @var string
20
     */
21
    const FILE_INDICATOR = '___upload-';
22
23
    /**
24
     * The string between the group identifier
25
     * and the actual attribute.
26
     *
27
     * @var string
28
     */
29
    const GROUP_SEPARATOR = '__';
30
31
    /**
32
     * The original attribute name
33
     *
34
     * @var string
35
     */
36
    public $original;
37
38
    /**
39
     * The layout group identifier part
40
     *
41
     * @var string
42
     */
43
    public $group;
44
45
    /**
46
     * The layout group identifier part
47
     *
48
     * @var string
49
     */
50
    public string $name;
51
52
    /**
53
     * The aggregate key (true = increment)
54
     *
55
     * @var bool|string
56
     */
57
    public $key;
58
59
    /**
60
     * Whether the attribute begins with the file indicator
61
     *
62
     * @var bool
63
     */
64
    public bool $upload;
65
66
    /**
67
     * Create a new attribute instance
68
     *
69
     * @param  string  $original
70
     * @param  mixed  $group
71
     * @return void
72
     */
73 1
    public function __construct($original, $group = null)
74
    {
75 1
        $this->original = $original;
76 1
        $this->setUpload();
77 1
        $this->setGroup($group);
78 1
        $this->setKey();
79 1
        $this->setName();
80
    }
81
82
    /**
83
     * Build an attribute from its components
84
     *
85
     * @param string $name
86
     * @param string|null $group
87
     * @param mixed $key
88
     * @param bool $upload
89
     * @return FlexibleAttribute
90
     */
91 1
    public static function make(string $name, ?string $group = null, ?string $key = null, bool $upload = false): static
92
    {
93 1
        $original = $upload ? static::FILE_INDICATOR : '';
94 1
        $original .= static::formatGroupPrefix($group) ?? '';
95 1
        $original .= $name;
96 1
        $original .= $key ? '['.($key !== true ? $key : '').']' : '';
0 ignored issues
show
introduced by
The condition $key !== true is always true.
Loading history...
97
98 1
        return new static($original, $group);
99
    }
100
101
    /**
102
     * Check if attribute is a flexible fields register
103
     */
104
    public function isFlexibleFieldsRegister(): bool
105
    {
106
        return $this->name === static::REGISTER_FLEXIBLE_FIELD_NAME;
107
    }
108
109
    /**
110
     * Check if attribute or given value match a probable file
111
     *
112
     * @param  mixed  $value
113
     * @return bool
114
     */
115 1
    public function isFlexibleFile($value = null): bool
116
    {
117 1
        if (!is_null($value) && !is_string($value)) {
118
            return false;
119 1
        } elseif (is_null($value)) {
0 ignored issues
show
introduced by
The condition is_null($value) is always true.
Loading history...
120 1
            return $this->upload;
121
        }
122
123 1
        return strpos($value, static::FILE_INDICATOR) === 0;
124
    }
125
126
    /**
127
     * Return a FlexibleAttribute instance matching the target upload field
128
     *
129
     * @param  mixed  $value
130
     * @return \NovaFlexibleContent\Http\FlexibleAttribute
131
     */
132
    public function getFlexibleFileAttribute($value): static
133
    {
134
        return new static($value, $this->group);
135
    }
136
137
    /**
138
     * Check if attribute represents an array item
139
     *
140
     * @return bool
141
     */
142 1
    public function isAggregate(): bool
143
    {
144 1
        return !is_null($this->key);
145
    }
146
147
    /**
148
     * Check if the found group key is used in the attribute's name
149
     *
150
     * @return bool
151
     */
152 1
    public function hasGroupInName(): bool
153
    {
154 1
        if (is_null($this->group)) {
0 ignored issues
show
introduced by
The condition is_null($this->group) is always false.
Loading history...
155 1
            return false;
156
        }
157
158
        $position = strpos($this->original, $this->groupPrefix());
159
        $index    = $this->isFlexibleFile() ? strlen(static::FILE_INDICATOR) : 0;
160
161
        return $position === $index;
162
    }
163
164
    /**
165
     * Get the group prefix string.
166
     */
167
    public function groupPrefix(?string $group = null): ?string
168
    {
169
        return static::formatGroupPrefix($group ?? $this->group);
170
    }
171
172
    /**
173
     * Get a group prefix string.
174
     */
175 1
    public static function formatGroupPrefix(?string $group = null): ?string
176
    {
177 1
        return $group ? $group.static::GROUP_SEPARATOR : null;
178
    }
179
180
    /**
181
     * Set given value in given using the current attribute definition
182
     *
183
     * @param  array  $attributes
184
     * @param  string  $value
185
     * @return array
186
     */
187
    public function setDataIn(&$attributes, $value): array
188
    {
189
        $value = is_string($value) && $value === '' ? null : $value;
190
191
        if (!$this->isAggregate()) {
192
            $attributes[$this->name] = $value;
193
194
            return $attributes;
195
        }
196
197
        if (!isset($attributes[$this->name])) {
198
            $attributes[$this->name] = [];
199
        } elseif (!is_array($attributes[$this->name])) {
200
            $attributes[$this->name] = [$attributes[$this->name]];
201
        }
202
203
        if ($this->key === true) {
204
            $attributes[$this->name][] = $value;
205
        } else {
206
            data_set($attributes[$this->name], $this->key, $value);
0 ignored issues
show
Bug introduced by
It seems like $this->key can also be of type false; however, parameter $key of data_set() does only seem to accept array|string, 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

206
            data_set($attributes[$this->name], /** @scrutinizer ignore-type */ $this->key, $value);
Loading history...
207
        }
208
209
        return $attributes;
210
    }
211
212
    /**
213
     * Remove current attribute from given array
214
     *
215
     * @param  array  $attributes
216
     * @return array
217
     */
218
    public function unsetDataIn(&$attributes)
219
    {
220
        if (!$this->isAggregate() || !is_array($attributes[$this->name])) {
221
            unset($attributes[$this->name]);
222
223
            return $attributes;
224
        }
225
226
        if ($this->key === true) {
227
            array_shift($attributes[$this->name]);
228
        } else {
229
            Arr::forget($attributes[$this->name], $this->key);
230
        }
231
232
        return $attributes;
233
    }
234
235
    /**
236
     * Return a new instance with appended key
237
     *
238
     * @param  string  $key
239
     * @return \NovaFlexibleContent\Http\FlexibleAttribute
240
     */
241
    public function nest($key)
242
    {
243
        $append = implode('', array_map(function ($segment) {
244
            return '['.$segment.']';
245
        }, explode('.', $key)));
246
247
        return new static($this->original.$append, $this->group);
248
    }
249
250
    /**
251
     * Check attribute is an "upload" attribute and define it on the object
252
     *
253
     * @param  mixed  $group
254
     * @return void
255
     */
256 1
    protected function setUpload()
257
    {
258 1
        $this->upload = $this->isFlexibleFile($this->original);
259
    }
260
261
    /**
262
     * Check if given group identifier is included in original
263
     * attribute. If so, set it as the group property.
264
     *
265
     * @param  mixed  $group
266
     * @return void
267
     */
268 1
    protected function setGroup($group = null): void
269
    {
270 1
        if (!$group) {
271 1
            return;
272
        }
273
274
        $group = strval($group);
275
276
        if (strpos($this->original, $this->groupPrefix($group)) !== false) {
277
            $this->group = $group;
278
        }
279
    }
280
281
    /**
282
     * Check if the original attribute contains an aggregate syntax.
283
     * If so, extract the aggregate key and assign it to the key property.
284
     *
285
     * @return void
286
     */
287 1
    protected function setKey(): void
288
    {
289 1
        preg_match('/^.+?(\[.*\])?$/', $this->original, $arrayMatches);
290
291 1
        if (!isset($arrayMatches[1])) {
292 1
            return;
293
        }
294
295
        preg_match_all('/(?:\[([^\[\]]*)\])+?/', $arrayMatches[1], $keyMatches);
296
297
        $key = implode('.', array_map(function ($segment) {
298
            return $this->getCleanKeySegment($segment);
299
        }, $keyMatches[1]));
300
301
        $this->key = strlen($key) ? $key : true;
302
    }
303
304
    /**
305
     * Formats a key segment (removes unwanted characters, removes
306
     * group references from).
307
     *
308
     * @param  string  $segment
309
     * @return string
310
     */
311
    protected function getCleanKeySegment($segment): string
312
    {
313
        $segment = trim($segment, "'\" \t\n\r\0\x0B");
314
315
        if ($this->group && strpos($segment, $this->groupPrefix()) === 0) {
316
            return (new static($segment, $this->group))->name;
317
        }
318
319
        return $segment;
320
    }
321
322
    /**
323
     * Extract the attribute's final name
324
     *
325
     * @return void
326
     */
327 1
    protected function setName(): void
328
    {
329 1
        $name = trim($this->original);
330
331 1
        if ($this->isFlexibleFile()) {
332
            $position = strpos($name, static::FILE_INDICATOR) + strlen(static::FILE_INDICATOR);
333
            $name     = substr($name, $position);
334
        }
335
336 1
        if ($this->hasGroupInName()) {
337
            $position = strpos($name, $this->group) + strlen($this->groupPrefix());
338
            $name     = substr($name, $position);
339
        }
340
341 1
        if ($this->isAggregate()) {
342
            $position = strpos($name, '[');
343
            $name     = substr($name, 0, $position);
344
        }
345
346 1
        $this->name = $name;
347
    }
348
}
349