Completed
Push — master ( 677152...3fdf27 )
by Propa
02:40
created

TranslatableBootForm::mapArguments()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 6
rs 9.4286
cc 2
eloc 3
nc 2
nop 1
1
<?php namespace Propaganistas\LaravelTranslatableBootForms;
2
3
use AdamWathan\BootForms\BootForm;
4
5
class TranslatableBootForm
6
{
7
8
    /**
9
     * BootForm implementation.
10
     *
11
     * @var \AdamWathan\BootForms\BootForm
12
     */
13
    protected $form;
14
15
    /**
16
     * Array holding config values.
17
     *
18
     * @var array
19
     */
20
    protected $config;
21
22
    /**
23
     * Array of locale keys.
24
     *
25
     * @var array
26
     */
27
    protected $locales;
28
29
    /**
30
     * The current element type this class is working on.
31
     *
32
     * @var string
33
     */
34
    protected $element;
35
36
    /**
37
     * The array of arguments to pass in when creating the element.
38
     *
39
     * @var array
40
     */
41
    protected $arguments = [];
42
43
    /**
44
     * A keyed array of method => arguments to call on the created input.
45
     *
46
     * @var array
47
     */
48
    protected $methods = [];
49
50
    /**
51
     * Boolean indicating if the element should be cloned with corresponding translation name attributes.
52
     *
53
     * @var bool
54
     */
55
    protected $cloneElement = false;
56
57
    /**
58
     * Boolean indicating if the element should have an indication that is it a translation.
59
     *
60
     * @var bool
61
     */
62
    protected $translatableIndicator = false;
63
64
    /**
65
     * Array holding the mappable element arguments.
66
     *
67
     * @var array
68
     */
69
    private $mappableArguments = [
70
        'text'           => ['label', 'name'],
71
        'textarea'       => ['label', 'name'],
72
        'password'       => ['label', 'name'],
73
        'date'           => ['label', 'name'],
74
        'email'          => ['label', 'name'],
75
        'file'           => ['label', 'name'],
76
        'inputGroup'     => ['label', 'name'],
77
        'radio'          => ['label', 'name'],
78
        'inlineRadio'    => ['label', 'name'],
79
        'checkbox'       => ['label', 'name'],
80
        'inlineCheckbox' => ['label', 'name'],
81
        'select'         => ['label', 'name', 'options'],
82
        'button'         => ['label', 'name', 'type'],
83
        'submit'         => ['value', 'type'],
84
        'hidden'         => ['name'],
85
        'label'          => ['label'],
86
        'open'           => [],
87
        'openHorizontal' => ['columnSizes'],
88
        'close'          => [],
89
    ];
90
91
    /**
92
     * Array holding the methods to call during element behavior processing.
93
     *
94
     * @var array
95
     */
96
    private $elementBehaviors = [
97
        'text'           => ['cloneElement', 'translatableIndicator'],
98
        'textarea'       => ['cloneElement', 'translatableIndicator'],
99
        'password'       => ['cloneElement', 'translatableIndicator'],
100
        'date'           => ['cloneElement', 'translatableIndicator'],
101
        'email'          => ['cloneElement', 'translatableIndicator'],
102
        'file'           => ['cloneElement', 'translatableIndicator'],
103
        'inputGroup'     => ['cloneElement', 'translatableIndicator'],
104
        'radio'          => ['cloneElement', 'translatableIndicator'],
105
        'inlineRadio'    => ['cloneElement', 'translatableIndicator'],
106
        'checkbox'       => ['cloneElement', 'translatableIndicator'],
107
        'inlineCheckbox' => ['cloneElement', 'translatableIndicator'],
108
        'select'         => ['cloneElement', 'translatableIndicator'],
109
        'button'         => ['cloneElement'],
110
        'submit'         => ['cloneElement'],
111
        'hidden'         => ['cloneElement'],
112
        'label'          => [],
113
        'open'           => [],
114
        'openHorizontal' => [],
115
        'close'          => [],
116
    ];
117
118
    /**
119
     * Form constructor.
120
     *
121
     * @param \AdamWathan\BootForms\BootForm $form
122
     */
123
    public function __construct(BootForm $form)
124
    {
125
        $this->form = $form;
126
        $this->config = [
127
            'form-group-class' => config('translatable-bootforms::form-group-class'),
128
            'input-locale-attribute' => config('translatable-bootforms::input-locale-attribute'),
129
            'label-locale-indicator' => config('translatable-bootforms::label-locale-indicator'),
130
        ];
131
    }
132
133
    /**
134
     * Magic __call method.
135
     *
136
     * @param string $method
137
     * @param array  $parameters
138
     * @return \Propaganistas\LaravelTranslatableBootForms\TranslatableBootForm
139
     */
140
    public function __call($method, $parameters)
141
    {
142
        // New translatable form element.
143
        if (is_null($this->element())) {
144
            $method = camel_case(substr($method, 12));
145
            $this->element($method);
146
            $this->arguments($this->mapArguments($parameters));
147
        }
148
        // Calling methods on the translatable form element.
149
        else {
150
            $this->addMethod($method, $parameters);
151
        }
152
153
        return $this;
154
    }
155
156
    /**
157
     * Magic __toString method.
158
     *
159
     * @return string
160
     */
161
    public function __toString()
162
    {
163
        return $this->render();
164
    }
165
166
    /**
167
     * Resets the properties.
168
     *
169
     * @return $this
170
     */
171
    protected function reset()
172
    {
173
        $this->element = null;
174
        $this->arguments = [];
175
        $this->methods = [];
176
        $this->cloneElement = false;
177
        $this->translatableIndicator = false;
178
179
        return $this;
180
    }
181
182
    /**
183
     * Get or set the available locales.
184
     *
185
     * @param array|null $locales
186
     * @return array
187
     */
188
    public function locales(array $locales = null)
189
    {
190
        return is_null($locales)
191
            ? $this->locales
192
            : ($this->locales = $locales);
193
    }
194
195
    /**
196
     * Get or set the current element.
197
     *
198
     * @param string|null $element
199
     * @return string
200
     */
201
    protected function element($element = null)
202
    {
203
        return is_null($element)
204
            ? $this->element
205
            : ($this->element = $element);
206
    }
207
208
    /**
209
     * Get or set the arguments.
210
     *
211
     * @param array|null $arguments
212
     * @return array
213
     */
214
    protected function arguments(array $arguments = null)
215
    {
216
        return is_null($arguments)
217
            ? $this->arguments
218
            : ($this->arguments = $arguments);
219
    }
220
221
    /**
222
     * Get or set the methods.
223
     *
224
     * @param array|null $methods
225
     * @return array
226
     */
227
    protected function methods(array $methods = null)
228
    {
229
        return is_null($methods)
230
            ? $this->methods
231
            : ($this->methods = $methods);
232
    }
233
234
    /**
235
     * Get or set the current element.
236
     *
237
     * @param bool|null $clone
238
     * @return bool
239
     */
240
    protected function cloneElement(bool $clone = null)
241
    {
242
        return is_null($clone)
243
            ? $this->cloneElement
244
            : ($this->cloneElement = (bool) $clone);
245
    }
246
247
    /**
248
     * Get or set the translatable indicator boolean.
249
     *
250
     * @param bool|null $add
251
     * @return bool
252
     */
253
    protected function translatableIndicator(bool $add = null)
254
    {
255
        return is_null($add)
256
            ? $this->translatableIndicator
257
            : ($this->translatableIndicator = (bool) $add);
258
    }
259
260
    /**
261
     * Overwrites an argument.
262
     *
263
     * @param string       $argument
264
     * @param string|array $value
265
     */
266
    protected function overwriteArgument($argument, $value)
267
    {
268
        $arguments = $this->arguments();
269
270
        $arguments[$argument] = $value;
271
272
        $this->arguments($arguments);
273
    }
274
275
    /**
276
     * Adds a method.
277
     *
278
     * @param string       $name
279
     * @param string|array $parameters
280
     */
281
    protected function addMethod($name, $parameters)
282
    {
283
        $methods = $this->methods();
284
285
        $methods[] = compact('name','parameters');
286
287
        $this->methods($methods);
288
    }
289
290
    /**
291
     * Renders the current translatable form element.
292
     *
293
     * @return string
294
     */
295
    public function render()
296
    {
297
        $this->applyElementBehavior();
298
299
        $elements = [];
300
301
        if ($this->cloneElement()) {
302
            $this->addMethod('addGroupClass', $this->config['form-group-class']);
303
304
            $originalArguments = $this->arguments();
305
            $originalMethods = $this->methods();
306
307
            foreach ($this->locales() as $locale => $language) {
308
                $this->arguments($originalArguments);
309
                $this->methods($originalMethods);
310
                $this->overwriteArgument('name', $locale . '[' . $originalArguments['name'] . ']');
311
                if ($this->translatableIndicator()) {
312
                    $this->setTranslatableLabelIndicator($locale);
313
                }
314
                $this->addMethod('attribute', [$this->config['input-locale-attribute'], $locale]);
315
                $elements[] = $this->createInput();
316
            }
317
        } else {
318
            $elements[] = $this->createInput();
319
        }
320
321
        $this->reset();
322
323
        return implode('', $elements);
324
    }
325
326
    /**
327
     * Creates an input element using the supplied arguments and methods.
328
     *
329
     * @return mixed
330
     */
331
    protected function createInput()
332
    {
333
        // Create element using arguments.
334
        $element = $this->form->{$this->element()}(...array_values($this->arguments()));
335
336
        // Apply requested methods.
337
        foreach ($this->methods() as $method) {
338
            $methodName = $method['name'];
339
            $methodParameters = $method['parameters'];
340
            if (is_array($methodParameters)) {
341
                $element->{$methodName}(...$methodParameters);
342
            } elseif (!empty($methodParameters)) {
343
                $element->{$methodName}($methodParameters);
344
            } else {
345
                $element->{$methodName}();
346
            }
347
348
        }
349
350
        return $element;
351
    }
352
353
    /**
354
     * Add specific element behavior to the current translatable form element.
355
     */
356
    protected function applyElementBehavior()
357
    {
358
        $behaviors = isset($this->elementBehaviors[$this->element()]) ? $this->elementBehaviors[$this->element()] : [];
359
360
        foreach ($behaviors as $behavior) {
361
            $this->{$behavior}(true);
362
        }
363
    }
364
365
    /**
366
     * Maps the form element arguments to their name.
367
     *
368
     * @param array $arguments
369
     * @return array
370
     */
371
    protected function mapArguments(array $arguments)
372
    {
373
        $keys = isset($this->mappableArguments[$this->element()]) ? $this->mappableArguments[$this->element()] : [];
374
375
        return array_combine(array_slice($keys, 0, count($arguments)), $arguments);
376
    }
377
378
    /**
379
     * Add a locale indicator to the label.
380
     *
381
     * @param string $locale
382
     */
383
    protected function setTranslatableLabelIndicator($locale)
384
    {
385
        $localizedLabel = str_replace('%label', $this->arguments()['label'], $this->config['label-locale-indicator']);
386
        $this->overwriteArgument('label', str_replace('%locale', $locale, $localizedLabel));
387
    }
388
389
}