Completed
Push — master ( 77b50b...7ba73a )
by Steve
46s
created

FieldsBuilder::getLocation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
nc 1
cc 1
eloc 2
nop 0
1
<?php
2
3
namespace StoutLogic\AcfBuilder;
4
5
class FieldsBuilder extends Builder
6
{
7
    protected $config = [];
8
    protected $fields = [];
9
    protected $location = null;
10
    protected $name;
11
12
    public function __construct($name, $groupConfig = [])
13
    {
14
        $this->name = $name;
15
        $this->setGroupConfig('key', $name);
16
        $this->setGroupConfig('title', $this->generateLabel($name));
17
18
        $this->config = array_merge($this->config, $groupConfig);
19
    }
20
21
    public function setGroupConfig($key, $value)
22
    {
23
        $this->config[$key] = $value;
24
25
        return $this;
26
    }
27
28
    public function getName()
29
    {
30
        return $this->name;
31
    }
32
33
    /**
34
     * Namespace a group key
35
     * Append the namespace 'group' before the set key.
36
     *
37
     * @param  string $key Field Key
38
     * @return string      Field Key
39
     */
40
    private function namespaceGroupKey($key)
41
    {
42
        if (strpos($key, 'group_') !== 0) {
43
            $key = 'group_'.$key;
44
        }
45
        return $key;
46
    }
47
48
    /**
49
     * Build the final config array. Build any other builders that may exist
50
     * in the config.
51
     * @return array    final field config
52
     */
53
    public function build()
54
    {
55
        return array_merge($this->config, [
56
            'fields' => $this->buildFields(),
57
            'location' => $this->buildLocation(),
58
            'key' => $this->namespaceGroupKey($this->config['key']),
59
        ]);
60
    }
61
62
    private function buildFields()
63
    {
64
        $fields = array_map(function($field) {
65
            return ($field instanceof Builder) ? $field->build() : $field;
66
        }, $this->getFields());
67
68
        return $this->transformFields($fields);
69
    }
70
71
    private function transformFields($fields)
72
    {
73
        $conditionalTransform = new Transform\ConditionalLogic($this);
74
        $namespaceFieldKeyTransform = new Transform\NamespaceFieldKey($this);
75
76
        return
77
            $namespaceFieldKeyTransform->transform(
78
                $conditionalTransform->transform($fields)
79
            );
80
    }
81
82
    private function buildLocation()
83
    {
84
        $location = $this->getLocation();
85
        return ($location instanceof Builder) ? $location->build() : $location;
86
    }
87
88
    /**
89
     * Add multiple fields either via an array or from another builder
90
     * @param mixed $fields array of fields or a FieldBuilder
91
     */
92
    public function addFields($fields)
93
    {
94
        if ($fields instanceof FieldsBuilder) {
95
            $fields = clone $fields;
96
            foreach ($fields->getFields() as $field) {
97
                $this->pushField($field);
98
            }
99
        } else {
100
            foreach ($fields as $field) {
101
                $this->pushField($field);
102
            }
103
        }
104
105
        return $this;
106
    }
107
108
    public function addField($name, $args = [])
109
    {
110
        $field = array_merge([
111
            'key' => $name,
112
            'name' => $name,
113
            'label' => $this->generateLabel($name),
114
        ], $args);
115
116
        $this->pushField($field);
117
118
        return $this;
119
    }
120
121
    protected function addFieldType($name, $type, $args = [])
122
    {
123
        return $this->addField($name, array_merge([
124
            'type' => $type,
125
        ], $args));
126
    }
127
128
    public function addText($name, $args = [])
129
    {
130
        return $this->addFieldType($name, 'text', $args);
131
    }
132
133
    public function addTextarea($name, $args = [])
134
    {
135
        return $this->addFieldType($name, 'textarea', $args);
136
    }
137
138
    public function addNumber($name, $args = [])
139
    {
140
        return $this->addFieldType($name, 'number', $args);
141
    }
142
143
    public function addEmail($name, $args = [])
144
    {
145
        return $this->addFieldType($name, 'email', $args);
146
    }
147
148
    public function addUrl($name, $args = [])
149
    {
150
        return $this->addFieldType($name, 'url', $args);
151
    }
152
153
    public function addPassword($name, $args = [])
154
    {
155
        return $this->addFieldType($name, 'password', $args);
156
    }
157
158
    public function addWysiwyg($name, $args = [])
159
    {
160
        return $this->addFieldType($name, 'wysiwyg', $args);
161
    }
162
163
    public function addOembed($name, $args = [])
164
    {
165
        return $this->addFieldType($name, 'oembed', $args);
166
    }
167
168
    public function addImage($name, $args = [])
169
    {
170
        return $this->addFieldType($name, 'image', $args);
171
    }
172
173
    public function addFile($name, $args = [])
174
    {
175
        return $this->addFieldType($name, 'file', $args);
176
    }
177
178
    public function addGallery($name, $args = [])
179
    {
180
        return $this->addFieldType($name, 'gallery', $args);
181
    }
182
183
    public function addTrueFalse($name, $args = [])
184
    {
185
        return $this->addFieldType($name, 'true_false', $args);
186
    }
187
188
    public function addSelect($name, $args = [])
189
    {
190
        return $this->addFieldType($name, 'select', $args);
191
    }
192
193
    public function addRadio($name, $args = [])
194
    {
195
        return $this->addFieldType($name, 'radio', $args);
196
    }
197
198
    public function addCheckbox($name, $args = [])
199
    {
200
        return $this->addFieldType($name, 'checkbox', $args);
201
    }
202
203
    public function addPostObject($name, $args = [])
204
    {
205
        return $this->addFieldType($name, 'post_object', $args);
206
    }
207
208
    public function addPostLink($name, $args = [])
209
    {
210
        return $this->addFieldType($name, 'post_link', $args);
211
    }
212
213
    public function addRelationship($name, $args = [])
214
    {
215
        return $this->addFieldType($name, 'relationship', $args);
216
    }
217
218
    public function addTaxonomy($name, $args = [])
219
    {
220
        return $this->addFieldType($name, 'taxonomy', $args);
221
    }
222
223
    public function addUser($name, $args = [])
224
    {
225
        return $this->addFieldType($name, 'user', $args);
226
    }
227
228
    public function addDatePicker($name, $args = [])
229
    {
230
        return $this->addFieldType($name, 'date_picker', $args);
231
    }
232
233
    public function addTimePicker($name, $args = [])
234
    {
235
        return $this->addFieldType($name, 'time_picker', $args);
236
    }
237
238
    public function addDateTimePicker($name, $args = [])
239
    {
240
        return $this->addFieldType($name, 'date_time_picker', $args);
241
    }
242
243
    public function addColorPicker($name, $args = [])
244
    {
245
        return $this->addFieldType($name, 'color_picker', $args);
246
    }
247
248 View Code Duplication
    public function addTab($label, $args = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
249
    {
250
        $name = $this->generateName($label).'_tab';
251
        $args = array_merge([
252
            'label' => $label,
253
        ], $args);
254
255
        return $this->addFieldType($name, 'tab', $args);
256
    }
257
258
    public function endpoint($value = 1)
259
    {
260
        return $this->setConfig('endpoint', $value);
261
    }
262
263 View Code Duplication
    public function addMessage($label, $message, $args = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
264
    {
265
        $name = $this->generateName($label).'_message';
266
        $args = array_merge([
267
            'label' => $label,
268
            'message' => $message,
269
        ], $args);
270
271
        return $this->addFieldType($name, 'message', $args);
272
    }
273
274
    public function addRepeater($name, $args = [])
275
    {
276
        $repeaterBuilder = new RepeaterBuilder($name, $args);
277
        $repeaterBuilder->setParentContext($this);
278
        $this->pushField($repeaterBuilder);
279
280
        return $repeaterBuilder;
281
    }
282
283
    public function addFlexibleContent($name, $args = [])
284
    {
285
        $flexibleContentBuilder = new FlexibleContentBuilder($name, $args);
286
        $flexibleContentBuilder->setParentContext($this);
287
        $this->pushField($flexibleContentBuilder);
288
289
        return $flexibleContentBuilder;
290
    }
291
292
    public function addChoice($choice, $label = null)
293
    {
294
        $field = $this->popLastField();
295
296
        array_key_exists('choices', $field) ?: $field['choices'] = [];
297
        $label ?: $label = $choice;
298
299
        $field['choices'][$choice] = $label;
300
        $this->pushField($field);
301
302
        return $this;
303
    }
304
305
    public function addChoices()
306
    {
307
        foreach (func_get_args() as $choice) {
308
            if (is_array($choice)) {
309
                $values = each($choice);
310
                $this->addChoice($values['key'], $values['value']);
311
            } else {
312
                $this->addChoice($choice);
313
            }
314
        }
315
316
        return $this;
317
    }
318
319
    public function conditional($name, $operator, $value)
320
    {
321
        $field = $this->popLastField();
322
        $conditionalBuilder = new ConditionalBuilder($name, $operator, $value);
323
        $conditionalBuilder->setParentContext($this);
324
325
        $field['conditional_logic'] = $conditionalBuilder;
326
        $this->pushField($field);
327
328
        return $conditionalBuilder;
329
    }
330
331
    public function getFields()
332
    {
333
        return $this->fields;
334
    }
335
336
    /**
337
     * Return the index in the $this->fields array looked up by the field's name
338
     * @param  string $name Field Name
339
     *
340
     * @throws FieldNotFoundException if the field name doesn't exist
341
     *
342
     * @return integer Field Index
343
     */
344
    protected function getFieldIndexByName($name)
345
    {
346
        foreach ($this->fields as $index => $field) {
347
            if ($field['name'] === $name) {
348
                return $index;
349
            }
350
        }
351
352
        throw new FieldNotFoundException("Field name '{$name}' not found.");
353
    }
354
355
    public function getFieldByName($name)
356
    {
357
        return $this->fields[$this->getFieldIndexByName($name)];
358
    }
359
360
    /**
361
     * Modify an already defined field
362
     * @param  string $name   Name of the field
363
     * @param  mixed  $modify Array of field configs or a closure that accepts
364
     *                        a FieldsBuilder and returns a FieldsBuilder.
365
     *
366
     * @throws ModifyFieldReturnTypeException if $modify is a closure and doesn't
367
     *                                        return a FieldsBuilder.
368
     *
369
     * @return FieldsBuilder  $this
370
     */
371
    public function modifyField($name, $modify)
372
    {
373
        $index = $this->getFieldIndexByName($name);
374
375
        if ($modify instanceof \Closure) {
376
            // Initialize Modifying FieldsBuilder
377
            $modifyBuilder = new FieldsBuilder('');
378
            $modifyBuilder->addFields([$this->fields[$index]]);
379
380
            // Modify Field
381
            $modifyBuilder = $modify($modifyBuilder);
382
383
            // Check if a FieldsBuilder is returned
384
            if (!$modifyBuilder instanceof FieldsBuilder) {
385
                throw new ModifyFieldReturnTypeException(gettype($modifyBuilder));
386
            } else {
387
                // Build Modifcations
388
                $modifyConfig = $modifyBuilder->build();
389
390
                // Build Modifcations
391
                array_splice($this->fields, $index, 1, $modifyConfig['fields']);
392
            }
393
        } else {
394
            $this->fields[$index] = array_merge($this->fields[$index], $modify);
395
        }
396
397
        return $this;
398
    }
399
400
    /**
401
     * Remove a field by name
402
     * @param  string $name Field to remove
403
     *
404
     * @return FieldsBuilder  $this
405
     */
406
    public function removeField($name)
407
    {
408
        $index = $this->getFieldIndexByName($name);
409
        unset($this->fields[$index]);
410
411
        return $this;
412
    }
413
414
    public function defaultValue($value)
415
    {
416
        return $this->setConfig('default_value', $value);
417
    }
418
419
    public function required($value = true)
420
    {
421
        return $this->setConfig('required', $value ? 1 : 0);
422
    }
423
424
    public function instructions($value)
425
    {
426
        return $this->setConfig('instructions', $value);
427
    }
428
429
    public function setConfig($key, $value)
430
    {
431
        $field = $this->popLastField();
432
        $field[$key] = $value;
433
        $this->pushField($field);
434
435
        return $this;
436
    }
437
438
    public function setLocation($param, $operator, $value)
439
    {
440
        if ($this->getParentContext()) {
441
            return $this->getParentContext()->setLocation($param, $operator, $value);
0 ignored issues
show
Documentation Bug introduced by
The method setLocation does not exist on object<StoutLogic\AcfBuilder\Builder>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
442
        }
443
444
        $this->location = new LocationBuilder($param, $operator, $value);
445
        $this->location->setParentContext($this);
446
447
        return $this->location;
448
    }
449
450
    public function getLocation()
451
    {
452
        return $this->location;
453
    }
454
455
    protected function popLastField()
456
    {
457
        return array_pop($this->fields);
458
    }
459
460
    protected function pushField($field)
461
    {
462
        $this->fields[] = $field;
463
    }
464
465
    protected function generateLabel($name)
466
    {
467
        return ucwords(str_replace("_", " ", $name));
468
    }
469
470
    protected function generateName($name)
471
    {
472
        return strtolower(str_replace(" ", "_", $name));
473
    }
474
}
475