Passed
Push — master ( e1bca8...147f66 )
by Richard
15:35 queued 13s
created

FieldFactory::build()   C

Complexity

Conditions 12
Paths 8

Size

Total Lines 40
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 12
eloc 16
c 2
b 0
f 0
nc 8
nop 3
dl 0
loc 40
rs 6.9666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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