Passed
Push — develop ( 5338a4...74435c )
by Richard
02:48
created

FieldFactory::isStringImageField()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 5
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
namespace Riclep\Storyblok;
4
5
use Illuminate\Support\Str;
6
use Riclep\Storyblok\Fields\Asset;
7
use Riclep\Storyblok\Fields\Image;
8
use Riclep\Storyblok\Fields\MultiAsset;
9
use Riclep\Storyblok\Fields\RichText;
10
use Riclep\Storyblok\Fields\SvgImage;
11
use Riclep\Storyblok\Fields\Table;
12
13
class FieldFactory
14
{
15
    /**
16
     * Works out what class should be used for the given block’s content
17
     *
18
     * @param $block
19
     * @param $field
20
     * @param $key
21
     * @return \Illuminate\Support\Collection|mixed|Asset|Image|MultiAsset|RichText|Table
22
     */
23
    public function build($block, $field, $key): mixed
24
    {
25
        $isClassField = $this->classField($block, $field, $key);
26
27
        if ($isClassField) {
28
            return $isClassField;
29
        }
30
31
        // single item relations
32
        if (Str::isUuid($field) && ($block->_autoResolveRelations || in_array($key, $block->_resolveRelations, true) || array_key_exists($key, $block->_resolveRelations))) {
33
34
            if (array_key_exists($key, $block->_resolveRelations)) {
35
                return $block->getRelation(new RequestStory(), $field, $block->_resolveRelations[$key]);
36
            }
37
38
            return $block->getRelation(new RequestStory(), $field);
39
        }
40
41
        // complex fields
42
        if (is_array($field) && !empty($field)) {
43
            return $this->arrayField($block, $field, $key);
44
        }
45
46
        // legacy and string image fields
47
        if ($this->isStringImageField($field)) {
48
            return new Image($field, $block);
49
        }
50
51
        // strings or anything else - do nothing
52
        return $field;
53
    }
54
55
    /**
56
     * @param $block
57
     * @param $field
58
     * @param $key
59
     * @return mixed
60
     */
61
    protected function classField($block, $field, $key): mixed
62
    {
63
        // does the Block assign any $_casts? This is key (field) => value (class)
64
        if (array_key_exists($key, $block->getCasts())) {
65
            $casts = $block->getCasts();
66
            return new $casts[$key]($field, $block);
67
        }
68
69
        // find Fields specific to this Block matching: BlockNameFieldName
70
        if ($class = $block->getChildClassName('Field', $block->component() . '_' . $key)) {
71
            return new $class($field, $block);
72
        }
73
74
        // auto-match Field classes
75
        if ($class = $block->getChildClassName('Field', $key)) {
76
            return new $class($field, $block);
77
        }
78
79
        return false;
80
    }
81
82
    /**
83
     * If given an array field we need more processing to determine the class
84
     *
85
     * @param $block
86
     * @param $field
87
     * @param $key
88
     * @return \Illuminate\Support\Collection|mixed|Asset|Image|MultiAsset|RichText|Table
89
     */
90
    protected function arrayField($block, $field, $key): mixed
91
    {
92
        // match link fields
93
        if (array_key_exists('linktype', $field)) {
94
            $class = 'Riclep\Storyblok\Fields\\' . Str::studly($field['linktype']) . 'Link';
95
96
            return new $class($field, $block);
97
        }
98
99
        // match rich-text fields
100
        if (array_key_exists('type', $field) && $field['type'] === 'doc') {
101
            return new RichText($field, $block);
102
        }
103
104
        // match asset fields - detecting raster images
105
        if (array_key_exists('fieldtype', $field) && $field['fieldtype'] === 'asset') {
106
            // legacy and string image fields
107
            if ($this->isStringImageField($field['filename'])) {
108
                return new Image($field, $block);
109
            }
110
111
            if ($this->isSvgImageField($field['filename'])) {
112
                return new SvgImage($field, $block);
113
            }
114
115
            return new Asset($field, $block);
116
        }
117
118
        // match table fields
119
        if (array_key_exists('fieldtype', $field) && $field['fieldtype'] === 'table') {
120
            return new Table($field, $block);
121
        }
122
123
        if (array_key_exists(0, $field)) {
124
            return $this->relationField($block, $field, $key);
125
        }
126
127
        // just return the array
128
        return $field;
129
    }
130
131
    protected function relationField($block, $field, $key) {
132
        // it’s an array of relations - request them if we’re auto or manual resolving
133
        if (Str::isUuid($field[0])) {
134
            if ($block->_autoResolveRelations || array_key_exists($key, $block->_resolveRelations) || in_array($key, $block->_resolveRelations, true)) {
135
136
                // they’re passing a custom class
137
                if (array_key_exists($key, $block->_resolveRelations)) {
138
                    $relations = collect($field)->transform(fn($relation) => $block->getRelation(new RequestStory(), $relation, $block->_resolveRelations[$key]));
139
                } else {
140
                    $relations = collect($field)->transform(fn($relation) => $block->getRelation(new RequestStory(), $relation));
141
                }
142
143
                if ($block->_filterRelations) {
144
                    $relations = $relations->filter();
145
                }
146
147
                return $relations;
148
            }
149
        }
150
151
        // has child items - single option, multi option and Blocks fields
152
        if (is_array($field[0])) {
153
            // resolved relationships - entire story is returned, we just want the content and a few meta items
154
            if (array_key_exists('content', $field[0])) {
155
                return collect($field)->transform(function ($relation) use ($block) {
156
                    $class = $block->getChildClassName('Block', $relation['content']['component']);
157
                    $relationClass = new $class($relation['content'], $block);
158
159
                    $relationClass->addMeta([
160
                        'name' => $relation['name'],
161
                        'published_at' => $relation['published_at'],
162
                        'full_slug' => $relation['full_slug'],
163
                    ]);
164
165
                    return $relationClass;
166
                });
167
            }
168
169
            // this field holds blocks!
170
            if (array_key_exists('component', $field[0])) {
171
                return collect($field)->transform(function ($childBlock) use ($block) {
172
                    $class = $block->getChildClassName('Block', $childBlock['component']);
173
174
                    return new $class($childBlock, $block);
175
                });
176
            }
177
178
            // multi assets
179
            if (array_key_exists('filename', $field[0])) {
180
                return new MultiAsset($field, $block);
181
            }
182
        }
183
184
        return $field;
185
    }
186
187
    /**
188
     * Check if given string is a string image field
189
     *
190
     * @param  $filename
191
     * @return boolean
192
     */
193
    public function isStringImageField($filename): bool
194
    {
195
        $allowed_extentions = ['.jpg', '.jpeg', '.png', '.gif', '.webp'];
196
197
        return is_string($filename) && Str::of($filename)->lower()->endsWith($allowed_extentions);
198
    }
199
200
    /**
201
     * Check if given string is a string image field
202
     *
203
     * @param  $filename
204
     * @return boolean
205
     */
206
    public function isSvgImageField($filename): bool
207
    {
208
        $allowed_extentions = ['.svg', '.svgz'];
209
210
        return is_string($filename) && Str::of($filename)->lower()->endsWith($allowed_extentions);
211
    }
212
}
213