Cancelled
Push — master ( 28a5cf...9e6262 )
by Paul
06:07
created

Builder::buildFormSelect()   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
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
crap 2
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules\Html;
4
5
use GeminiLabs\SiteReviews\Defaults\BuilderDefaults;
6
use GeminiLabs\SiteReviews\Helper;
7
use GeminiLabs\SiteReviews\Modules\Html\Attributes;
8
9
class Builder
10
{
11
	const INPUT_TYPES = [
12
		'button', 'checkbox', 'date', 'datetime-local', 'email', 'file', 'hidden', 'image', 'month',
13
		'number', 'password', 'radio', 'range', 'reset', 'search', 'submit', 'tel', 'text', 'time',
14
		'url', 'week',
15
	];
16
17
	const TAGS_FORM = [
18
		'input', 'select', 'textarea',
19
	];
20
21
	const TAGS_STRUCTURE = [
22
		'div', 'form', 'nav', 'ol', 'section', 'ul',
23
	];
24
25
	const TAGS_TEXT = [
26
		'a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'i', 'label', 'li', 'option', 'p', 'pre', 'small',
27
		'span',
28
	];
29
30
	/**
31
	 * @var array
32
	 */
33
	public $args = [];
34
35
	/**
36
	 * @var array
37
	 */
38
	public $globals = [];
39
40
	/**
41
	 * @var bool
42
	 */
43
	public $render = false;
44
45
	/**
46
	 * @var string
47
	 */
48
	public $tag;
49
50 7
	public function __construct( array $globals = [] )
51
	{
52 7
		$this->globals = $globals;
53 7
	}
54
55
	/**
56
	 * @param string $method
57
	 * @param array $args
58
	 * @return string|void
59
	 */
60 7
	public function __call( $method, $args )
61
	{
62 7
		$instance = new static( $this->globals );
63 7
		$instance->setTagFromMethod( $method );
64 7
		call_user_func_array( [$instance, 'normalize'], $args += ['',''] );
65 7
		$tags = array_merge( static::TAGS_FORM, static::TAGS_STRUCTURE, static::TAGS_TEXT );
66 7
		$generatedTag = in_array( $instance->tag, $tags )
67 7
			? $instance->buildTag()
68 7
			: $instance->buildCustomField();
69 7
		if( !$this->render ) {
70 7
			return $generatedTag;
71
		}
72
		echo $generatedTag;
73
	}
74
75
	/**
76
	 * @param string $property
77
	 * @param mixed $value
78
	 * @return void
79
	 */
80
	public function __set( $property, $value )
81
	{
82
		$properties = [
83
			'args' => 'is_array',
84
			'globals' => 'is_array',
85
			'render' => 'is_bool',
86
			'tag' => 'is_string',
87
		];
88
		if( !isset( $properties[$property] )
89
			|| empty( array_filter( [$value], $properties[$property] ))
90
		)return;
91
		$this->$property = $value;
92
	}
93
94
	/**
95
	 * @return string
96
	 */
97 7
	public function getClosingTag()
98
	{
99 7
		return '</'.$this->tag.'>';
100
	}
101
102
	/**
103
	 * @return string
104
	 */
105 7
	public function getOpeningTag()
106
	{
107 7
		$attributes = glsr( Attributes::class )->{$this->tag}( $this->args )->toString();
108 7
		return '<'.trim( $this->tag.' '.$attributes ).'>';
109
	}
110
111
	/**
112
	 * @return string|void
113
	 */
114
	protected function buildCustomField()
115
	{
116
		$className = glsr( Helper::class )->buildClassName( $this->tag, __NAMESPACE__.'\Fields' );
117
		if( !class_exists( $className )) {
118
			glsr_log()->error( 'Field missing: '.$className );
119
			return;
120
		}
121
		return (new $className( $this ))->build();
122
	}
123
124
	/**
125
	 * @return string|void
126
	 */
127 7
	protected function buildDefaultTag( $text = '' )
128
	{
129 7
		if( empty( $text )) {
130 7
			$text = $this->args['text'];
131
		}
132 7
		return $this->getOpeningTag().$text.$this->getClosingTag();
133
	}
134
135
	/**
136
	 * @return string|void
137
	 */
138
	protected function buildFieldDescription()
139
	{
140
		if( empty( $this->args['description'] ))return;
141
		if( !empty( $this->globals['is_widget'] )) {
142
			return $this->small( $this->args['description'] );
143
		}
144
		return $this->p( $this->args['description'], ['class' => 'description'] );
0 ignored issues
show
Bug introduced by
The method p() does not exist on GeminiLabs\SiteReviews\Modules\Html\Builder. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

144
		return $this->/** @scrutinizer ignore-call */ p( $this->args['description'], ['class' => 'description'] );
Loading history...
145
	}
146
147
	/**
148
	 * @return string|void
149
	 */
150
	protected function buildFormInput()
151
	{
152
		if( !in_array( $this->args['type'], ['checkbox', 'radio'] )) {
153
			return $this->buildFormLabel().$this->getOpeningTag();
154
		}
155
		return empty( $this->args['options'] )
156
			? $this->buildFormInputChoice()
157
			: $this->buildFormInputMultiChoice();
158
	}
159
160
	/**
161
	 * @return string|void
162
	 */
163
	protected function buildFormInputChoice()
164
	{
165
		return $this->label( $this->getOpeningTag().' '.$this->args['text'] );
166
	}
167
168
	/**
169
	 * @return string|void
170
	 */
171
	protected function buildFormInputMultiChoice()
172
	{
173
		$options = array_reduce( array_keys( $this->args['options'] ), function( $carry, $key ) {
174
			return $carry.$this->li( $this->{$this->args['type']}([
175
				'checked' => in_array( $key, (array)$this->args['value'] ),
176
				'name' => $this->args['name'].'[]',
177
				'text' => $this->args['options'][$key],
178
				'value' => $key,
179
			]));
180
		});
181
		return $this->ul( $options, ['class' => $this->args['class']] );
0 ignored issues
show
Bug introduced by
The method ul() does not exist on GeminiLabs\SiteReviews\Modules\Html\Builder. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

181
		return $this->/** @scrutinizer ignore-call */ ul( $options, ['class' => $this->args['class']] );
Loading history...
182
	}
183
184
	/**
185
	 * @return void|string
186
	 */
187
	protected function buildFormLabel()
188
	{
189
		if( empty( $this->args['label'] ) || $this->args['type'] == 'hidden' )return;
190
		return $this->label([
191
			'for' => $this->args['id'],
192
			'text' => $this->args['label'],
193
		]);
194
	}
195
196
	/**
197
	 * @return string|void
198
	 */
199
	protected function buildFormSelect()
200
	{
201
		return $this->buildFormLabel().$this->buildDefaultTag( $this->buildFormSelectOptions() );
202
	}
203
204
	/**
205
	 * @return string|void
206
	 */
207
	protected function buildFormSelectOptions()
208
	{
209
		return array_reduce( array_keys( $this->args['options'] ), function( $carry, $key ) {
210
			return $carry.$this->option([
211
				'selected' => $this->args['value'] == $key,
212
				'text' => $this->args['options'][$key],
213
				'value' => $key,
214
			]);
215
		});
216
	}
217
218
	/**
219
	 * @return string|void
220
	 */
221
	protected function buildFormTextarea()
222
	{
223
		return $this->buildFormLabel().$this->buildDefaultTag();
224
	}
225
226
	/**
227
	 * @return string|void
228
	 */
229 7
	protected function buildTag()
230
	{
231 7
		if( !in_array( $this->tag, static::TAGS_FORM )) {
232 7
			return $this->buildDefaultTag();
233
		}
234
		return call_user_func( [$this, 'buildForm'.ucfirst( $this->tag )] ).$this->buildFieldDescription();
235
	}
236
237
	/**
238
	 * @param string|array ...$params
239
	 * @return void
240
	 */
241 7
	protected function normalize( ...$params )
242
	{
243 7
		if( is_string( $params[0] ) || is_numeric( $params[0] )) {
244 7
			$this->setNameOrTextAttributeForTag( $params[0] );
245
		}
246 7
		if( is_array( $params[0] )) {
247
			$this->args += $params[0];
248
		}
249 7
		else if( is_array( $params[1] )) {
250 7
			$this->args += $params[1];
251
		}
252 7
		$this->args = glsr( BuilderDefaults::class )->merge( $this->args );
253 7
	}
254
255
	/**
256
	 * @param string $value
257
	 * @return void
258
	 */
259 7
	protected function setNameOrTextAttributeForTag( $value )
260
	{
261 7
		$attribute = in_array( $this->tag, static::TAGS_FORM )
262
			? 'name'
263 7
			: 'text';
264 7
		$this->args[$attribute] = $value;
265 7
	}
266
267
	/**
268
	 * @param string $method
269
	 * @return void
270
	 */
271 7
	protected function setTagFromMethod( $method )
272
	{
273 7
		$this->tag = strtolower( $method );
274 7
		if( in_array( $this->tag, static::INPUT_TYPES )) {
275
			$this->args['type'] = $this->tag;
276
			$this->tag = 'input';
277
		}
278 7
	}
279
}
280