Completed
Push — master ( 3f280d...f8146b )
by Stefano
29s queued 11s
created

Control::email()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * BEdita, API-first content management framework
4
 * Copyright 2020 ChannelWeb Srl, Chialab Srl
5
 *
6
 * This file is part of BEdita: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
12
 */
13
14
namespace App\Form;
15
16
use Cake\Core\Configure;
17
use Cake\Utility\Hash;
18
use Cake\Utility\Inflector;
19
20
/**
21
 * Control class provides methods for form controls, customized by control type.
22
 * Used by SchemaHelper to build control options for a property schema (@see \App\View\Helper\SchemaHelper::controlOptions)
23
 */
24
class Control
25
{
26
    /**
27
     * Control types
28
     */
29
    public const CONTROL_TYPES = ['json', 'richtext', 'plaintext', 'date-time', 'date', 'checkbox', 'enum', 'categories'];
30
31
    /**
32
     * Get control by options
33
     *
34
     * @param array $options The options
35
     * @return array
36
     */
37
    public static function control(array $options): array
38
    {
39
        $type = $options['propertyType'];
40
        $value = $options['value'];
41
        $format = self::format((array)$options['schema']);
42
        if ($type === 'text' && in_array($format, ['email', 'uri'])) {
43
            return call_user_func_array(Form::getMethod(self::class, $type, $format), [$options]);
44
        }
45
        if (!in_array($type, self::CONTROL_TYPES)) {
46
            return compact('type', 'value');
47
        }
48
49
        return call_user_func_array(Form::getMethod(self::class, $type), [$options]);
50
    }
51
52
    /**
53
     * Get format from schema
54
     *
55
     * @param array $schema The schema
56
     * @return string
57
     */
58
    public static function format(array $schema): string
59
    {
60
        if (empty($schema['oneOf'])) {
61
            return '';
62
        }
63
        foreach ($schema['oneOf'] as $item) {
64
            if (array_key_exists('format', $item)) {
65
                return (string)$item['format'];
66
            }
67
        }
68
69
        return '';
70
    }
71
72
    /**
73
     * Control for json data
74
     *
75
     * @param array $options The options
76
     * @return array
77
     */
78
    public static function json(array $options): array
79
    {
80
        return [
81
            'type' => 'textarea',
82
            'v-jsoneditor' => 'true',
83
            'class' => 'json',
84
            'value' => json_encode(Hash::get($options, 'value')),
85
        ];
86
    }
87
88
    /**
89
     * Control for plaintext
90
     *
91
     * @param array $options The options
92
     * @return array
93
     */
94
    public static function plaintext(array $options): array
95
    {
96
        return [
97
            'type' => 'textarea',
98
            'value' => Hash::get($options, 'value'),
99
        ];
100
    }
101
102
    /**
103
     * Control for richtext
104
     *
105
     * @param array $options The options
106
     * @return array
107
     */
108
    public static function richtext(array $options): array
109
    {
110
        $schema = (array)Hash::get($options, 'schema');
111
        $value = Hash::get($options, 'value');
112
        $key = !empty($schema['placeholders']) ? 'v-richeditor.placeholders' : 'v-richeditor';
113
114
        return [
115
            'type' => 'textarea',
116
            $key => json_encode(Configure::read('RichTextEditor.default.toolbar', '')),
117
            'value' => $value,
118
        ];
119
    }
120
121
    /**
122
     * Control for datetime
123
     *
124
     * @param array $options The options
125
     * @return array
126
     */
127
    public static function datetime(array $options): array
128
    {
129
        return [
130
            'type' => 'text',
131
            'v-datepicker' => 'true',
132
            'date' => 'true',
133
            'time' => 'true',
134
            'value' => Hash::get($options, 'value'),
135
            'templates' => [
136
                'inputContainer' => '<div class="input datepicker {{type}}{{required}}">{{content}}</div>',
137
            ],
138
        ];
139
    }
140
141
    /**
142
     * Control for date
143
     *
144
     * @param array $options The options
145
     * @return array
146
     */
147
    public static function date(array $options): array
148
    {
149
        return [
150
            'type' => 'text',
151
            'v-datepicker' => 'true',
152
            'date' => 'true',
153
            'value' => Hash::get($options, 'value'),
154
            'templates' => [
155
                'inputContainer' => '<div class="input datepicker {{type}}{{required}}">{{content}}</div>',
156
            ],
157
        ];
158
    }
159
160
    /**
161
     * Control for categories
162
     *
163
     * @param array $options The options
164
     * @return array
165
     */
166
    public static function categories(array $options): array
167
    {
168
        $schema = (array)Hash::get($options, 'schema');
169
        $value = Hash::get($options, 'value');
170
        $categories = (array)Hash::get($schema, 'categories');
171
        $options = array_map(
172
            function ($category) {
173
                return [
174
                    'value' => Hash::get($category, 'name'),
175
                    'text' => empty($category['label']) ? $category['name'] : $category['label'],
176
                ];
177
            },
178
            $categories
179
        );
180
181
        $checked = [];
182
        if (!empty($value)) {
183
            $names = Hash::extract($value, '{n}.name');
184
            foreach ($categories as $category) {
185
                if (in_array($category['name'], $names)) {
0 ignored issues
show
Bug introduced by
It seems like $names can also be of type ArrayAccess; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

185
                if (in_array($category['name'], /** @scrutinizer ignore-type */ $names)) {
Loading history...
186
                    $checked[] = $category['name'];
187
                }
188
            }
189
        }
190
191
        return [
192
            'type' => 'select',
193
            'options' => $options,
194
            'multiple' => 'checkbox',
195
            'value' => $checked,
196
        ];
197
    }
198
199
    /**
200
     * Control for checkbox
201
     *
202
     * @param array $options The options
203
     * @return array
204
     */
205
    public static function checkbox(array $options): array
206
    {
207
        $schema = (array)Hash::get($options, 'schema');
208
        $value = Hash::get($options, 'value');
209
        if (empty($schema['oneOf'])) {
210
            return [
211
                'type' => 'checkbox',
212
                'checked' => filter_var($value, FILTER_VALIDATE_BOOLEAN),
213
            ];
214
        }
215
216
        $options = [];
217
        foreach ($schema['oneOf'] as $one) {
218
            self::oneOptions($options, $one);
219
        }
220
        if (!empty($options)) {
221
            return [
222
                'type' => 'select',
223
                'options' => $options,
224
                'multiple' => 'checkbox',
225
            ];
226
        }
227
228
        return [
229
            'type' => 'checkbox',
230
            'checked' => filter_var($value, FILTER_VALIDATE_BOOLEAN),
231
        ];
232
    }
233
234
    /**
235
     * Set options for one of `oneOf` items.
236
     *
237
     * @param array $options The options to update
238
     * @param array $one The one item to check
239
     * @return void
240
     */
241
    public static function oneOptions(array &$options, array $one): void
242
    {
243
        $type = Hash::get($one, 'type');
244
        if ($type !== 'array') {
245
            return;
246
        }
247
        $options = array_map(
248
            function ($item) {
249
                return ['value' => $item, 'text' => Inflector::humanize($item)];
250
            },
251
            (array)Hash::extract($one, 'items.enum')
252
        );
253
    }
254
255
    /**
256
     * Control for enum
257
     *
258
     * @param array $options The options
259
     * @return array
260
     */
261
    public static function enum(array $options): array
262
    {
263
        $schema = (array)Hash::get($options, 'schema');
264
        $value = Hash::get($options, 'value');
265
        $objectType = Hash::get($options, 'objectType');
266
        $property = Hash::get($options, 'property');
267
268
        if (!empty($schema['oneOf'])) {
269
            foreach ($schema['oneOf'] as $one) {
270
                if (!empty($one['enum'])) {
271
                    $schema['enum'] = $one['enum'];
272
                    array_unshift($schema['enum'], '');
273
                }
274
            }
275
        }
276
277
        return [
278
            'type' => 'select',
279
            'options' => array_map(
280
                function (string $value) use ($objectType, $property) {
281
                    $text = self::label((string)$objectType, (string)$property, $value);
282
283
                    return compact('text', 'value');
284
                },
285
                $schema['enum']
286
            ),
287
            'value' => $value,
288
        ];
289
    }
290
291
    /**
292
     * Control for email
293
     *
294
     * @param array $options The options
295
     * @return array
296
     */
297
    public static function email(array $options): array
298
    {
299
        return [
300
            'type' => 'text',
301
            'v-email' => 'true',
302
            'class' => 'email',
303
            'value' => Hash::get($options, 'value'),
304
        ];
305
    }
306
307
    /**
308
     * Control for uri
309
     *
310
     * @param array $options The options
311
     * @return array
312
     */
313
    public static function uri(array $options): array
314
    {
315
        return [
316
            'type' => 'text',
317
            'v-uri' => 'true',
318
            'class' => 'uri',
319
            'value' => Hash::get($options, 'value'),
320
        ];
321
    }
322
323
    /**
324
     * Label for property.
325
     * If set in config Properties.<type>.labels.options.<property>, return it.
326
     * Return humanize of value, otherwise.
327
     *
328
     * @param string $type The object type
329
     * @param string $property The property name
330
     * @param string $value The value
331
     * @return string
332
     */
333
    public static function label(string $type, string $property, string $value): string
334
    {
335
        $label = Configure::read(sprintf('Properties.%s.labels.options.%s', $type, $property));
336
        if (empty($label)) {
337
            return Inflector::humanize($value);
338
        }
339
        $labelVal = (string)Configure::read(sprintf('Properties.%s.labels.options.%s.%s', $type, $property, $value));
340
        if (empty($labelVal)) {
341
            return Inflector::humanize($value);
342
        }
343
344
        return $labelVal;
345
    }
346
}
347