TinymceGenerator::normalize()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 7
ccs 0
cts 5
cp 0
rs 10
cc 2
nc 2
nop 2
crap 6
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Tinymce;
4
5
use GeminiLabs\SiteReviews\Contracts\ShortcodeContract;
6
use GeminiLabs\SiteReviews\Helper;
7
use GeminiLabs\SiteReviews\Helpers\Arr;
8
9
abstract class TinymceGenerator
10
{
11
    public array $properties = [];
12
    public ShortcodeContract $shortcode;
13
    public string $tag = '';
14
    protected array $errors = [];
15
    protected array $required = [];
16
17
    abstract public function fields(): array;
18
19 8
    public function register(): void
20
    {
21 8
        $this->shortcode = $this->shortcode();
22 8
        $this->tag = $this->shortcode->tag;
0 ignored issues
show
Bug introduced by
Accessing tag on the interface GeminiLabs\SiteReviews\Contracts\ShortcodeContract suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
23 8
        $fields = $this->getFields();
24 8
        $this->properties = [
25 8
            'btn_close' => _x('Close', 'admin-text', 'site-reviews'),
26 8
            'btn_okay' => _x('Insert Shortcode', 'admin-text', 'site-reviews'),
27 8
            'errors' => $this->errors,
28 8
            'fields' => $fields,
29 8
            'label' => $this->shortcode->name,
30 8
            'required' => $this->required,
31 8
            'title' => $this->shortcode->name,
32 8
        ];
33 8
        glsr()->append('mce', $this->properties, $this->tag);
34 8
    }
35
36
    abstract public function shortcode(): ShortcodeContract;
37
38
    protected function generateFields(array $fields): array
39 8
    {
40
        $generatedFields = array_map(function ($field) {
41 8
            if (empty($field)) {
42 8
                return;
43 8
            }
44
            $type = Arr::getAs('string', $field, 'type', 'textbox');
45
            $method = Helper::buildMethodName('normalize', $type);
46
            if (method_exists($this, $method)) {
47
                return call_user_func([$this, $method], $field);
48
            }
49
        }, $fields);
50
        return array_values(array_filter($generatedFields));
51
    }
52
53
    protected function getFields(): array
54 8
    {
55
        $fields = $this->fields();
56 8
        $fields = glsr()->filterArray("tinymce/fields/{$this->shortcode->tag}", $fields);
0 ignored issues
show
Bug introduced by
Accessing tag on the interface GeminiLabs\SiteReviews\Contracts\ShortcodeContract suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
57 8
        $fields = $this->generateFields($fields);
58
        if (!empty($this->errors)) {
59
            $errors = [];
60
            foreach ($this->required as $name => $alert) {
61
                if (false === Arr::searchByKey($name, $fields, 'name')) {
62
                    $errors[] = $this->errors[$name];
63
                }
64
            }
65
            $this->errors = $errors;
66
        }
67
        return empty($this->errors)
68 8
            ? $fields
69
            : $this->errors;
70 8
    }
71 8
72 8
    protected function hideOptions(): array
73
    {
74 8
        $hideOptions = $this->shortcode->options('hide');
75 8
        $options = [];
76 8
        foreach ($hideOptions as $name => $tooltip) {
77 8
            $options[] = [
78
                'name' => "hide_{$name}",
79 8
                'text' => $name,
80 8
                'tooltip' => $tooltip,
81
                'type' => 'checkbox',
82
            ];
83 8
        }
84
        return $options;
85 8
    }
86 8
87
    protected function normalize(array $field, array $defaults): array
88
    {
89
        if (!$this->validate($field)) {
90
            return [];
91
        }
92
        $field = shortcode_atts($defaults, $field);
93
        return array_filter($field, fn ($value) => '' !== $value);
94
    }
95 8
96 8
    protected function normalizeCheckbox(array $field): array
97 8
    {
98
        return $this->normalize($field, [
99
            'checked' => false,
100 8
            'label' => '',
101
            'minHeight' => '',
102 8
            'minWidth' => '',
103 8
            'name' => false,
104 8
            'text' => '',
105 8
            'tooltip' => '',
106 8
            'type' => '',
107 8
            'value' => '',
108 8
        ]);
109 8
    }
110 8
111 8
    protected function normalizeContainer(array $field): array
112 8
    {
113
        if (!array_key_exists('html', $field) && array_key_exists('items', $field)) {
114 8
            $field['items'] = $this->generateFields($field['items']);
115
        }
116
        return $field;
117 8
    }
118
119 8
    protected function normalizeListbox(array $field): array
120
    {
121
        $listbox = $this->normalize($field, [
122 8
            'label' => '',
123 8
            'minWidth' => '',
124
            'name' => false,
125
            'options' => [],
126 8
            'placeholder' => esc_attr_x('— Select —', 'admin-text', 'site-reviews'),
127
            'tooltip' => '',
128 8
            'type' => 'listbox',
129 8
            'value' => '',
130 8
        ]);
131 8
        if (empty($listbox)) {
132 8
            return [];
133 8
        }
134 8
        if (empty($listbox['options'])) {
135 8
            return [];
136 8
        }
137 8
        if (!array_key_exists('', $listbox['options'])) {
138 8
            $listbox['options'] = Arr::prepend($listbox['options'], $listbox['placeholder'], '');
139
        }
140
        foreach ($listbox['options'] as $value => $text) {
141 8
            $listbox['values'][] = [
142
                'text' => $text,
143 8
                'value' => $value,
144 8
            ];
145
        }
146 8
        return $listbox;
147
    }
148
149 8
    protected function normalizeTextbox(array $field): array
150
    {
151 8
        return $this->normalize($field, [
152 8
            'hidden' => false,
153 8
            'label' => '',
154 8
            'maxLength' => '',
155 8
            'minHeight' => '',
156 8
            'minWidth' => '',
157 8
            'multiline' => false,
158 8
            'name' => false,
159 8
            'size' => '',
160 8
            'text' => '',
161 8
            'tooltip' => '',
162
            'type' => 'textbox',
163
            'value' => '',
164 8
        ]);
165 8
    }
166
167 8
    protected function validate(array $field): bool
168 8
    {
169 8
        $args = shortcode_atts([
170 8
            'label' => '',
171 8
            'name' => false,
172
            'required' => false,
173 8
        ], $field);
174
        if (!$args['name']) {
175
            return false;
176 8
        }
177
        return $this->validateErrors($args) && $this->validateRequired($args);
178 8
    }
179 8
180 8
    protected function validateErrors(array $args): bool
181 8
    {
182 8
        if (!isset($args['required']['error'])) {
183 8
            return true;
184 8
        }
185 8
        $this->errors[$args['name']] = $this->normalizeContainer([
186 8
            'html' => $args['required']['error'],
187 8
            'type' => 'container',
188 8
        ]);
189 8
        return false;
190 8
    }
191 8
192
    protected function validateRequired(array $args): bool
193
    {
194 8
        if (false == $args['required']) {
195
            return true;
196 8
        }
197 8
        $alert = _x('Some of the shortcode options are required.', 'admin-text', 'site-reviews');
198 8
        if (isset($args['required']['alert'])) {
199 8
            $alert = $args['required']['alert'];
200 8
        } elseif (!empty($args['label'])) {
201 8
            $alert = sprintf(
202
                _x('The "%s" option is required.', 'the option label (admin-text)', 'site-reviews'),
203
                str_replace(':', '', $args['label'])
204 8
            );
205
        }
206
        $this->required[$args['name']] = $alert;
207 8
        return false;
208
    }
209
}
210