Test Failed
Push — develop ( c6b569...7a7654 )
by Paul
09:40
created

Shortcode::minRating()   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
eloc 1
dl 0
loc 3
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Shortcodes;
4
5
use GeminiLabs\SiteReviews\Contracts\ShortcodeContract;
6
use GeminiLabs\SiteReviews\Database;
7
use GeminiLabs\SiteReviews\Defaults\DefaultsAbstract;
8
use GeminiLabs\SiteReviews\Helper;
9
use GeminiLabs\SiteReviews\Helpers\Arr;
10
use GeminiLabs\SiteReviews\Helpers\Cast;
11
use GeminiLabs\SiteReviews\Helpers\Str;
12
use GeminiLabs\SiteReviews\Modules\Html\Builder;
13
use GeminiLabs\SiteReviews\Modules\Multilingual;
14
use GeminiLabs\SiteReviews\Modules\Rating;
15
use GeminiLabs\SiteReviews\Modules\Sanitizer;
16
use GeminiLabs\SiteReviews\Modules\Style;
17
18
abstract class Shortcode implements ShortcodeContract
19
{
20
    public array $args = [];
21
    public string $debug = '';
22
    public string $description;
23
    public string $name;
24 8
    public string $shortcode;
25
    public string $type = '';
26 8
27
    public function __construct()
28
    {
29
        $this->description = $this->shortcodeDescription();
30
        $this->name = $this->shortcodeName();
31
        $this->shortcode = $this->shortcodeTag();
32
    }
33
34
    public function apiFetchResponse(\WP_REST_Request $request): array
35
    {
36
        $option = $request['option'] ?? '';
37
        $method = Helper::buildMethodName('get', $option, 'options');
38
        if (method_exists($this, $method)) {
39
            $results = [];
40
            foreach ($this->$method($request) as $id => $title) {
41
                $results[] = compact('id', 'title');
42
            }
43
            return $results;
44
        }
45
        return [];
46
    }
47
48
    public function attributes(array $values, string $source = 'function'): array
49
    {
50
        $attributes = $this->defaults()->dataAttributes($values);
51
        $attributes = wp_parse_args($attributes, [
52
            'class' => glsr(Style::class)->styleClasses(),
53
            'data-from' => $source,
54
            'data-shortcode' => $this->shortcode,
55
            'id' => Arr::get($values, 'id'),
56
        ]);
57
        unset($attributes['data-id']);
58
        unset($attributes['data-form_id']);
59
        $attributes = glsr()->filterArray("shortcode/{$this->shortcode}/attributes", $attributes, $this);
60
        $attributes = array_map('esc_attr', $attributes);
61
        return $attributes;
62
    }
63
64
    public function build($args = [], string $type = 'shortcode'): string
65
    {
66
        $this->normalize($args, $type);
67
        $template = $this->buildTemplate();
68
        $attributes = $this->attributes($this->args, $type);
69
        $html = glsr(Builder::class)->div($template, $attributes);
70
        return sprintf('%s%s', $this->debug, $html);
71
    }
72
73
    /**
74
     * @param string|array $args
75
     */
76
    public function buildBlock($args = []): string
77
    {
78
        return $this->build(wp_parse_args($args), 'block');
79
    }
80
81
    /**
82
     * @param string|array $args
83 8
     */
84
    public function buildShortcode($args = []): string
85 8
    {
86 8
        return $this->build(wp_parse_args($args), 'shortcode');
87
    }
88
89
    public function defaults(): DefaultsAbstract
90
    {
91
        $classname = str_replace('Shortcodes\\', 'Defaults\\', get_class($this));
92
        $classname = str_replace('Shortcode', 'Defaults', $classname);
93
        return glsr($classname);
94
    }
95
96
    public function getConfig(): array
97
    {
98
        $config = $this->config();
99
        return glsr()->filterArray('shortcode/config', $config, $this->shortcode, $this);
100
    }
101
102
    public function getAssignedPostsOptions(\WP_REST_Request $request): array
103
    {
104
        $args = [
105
            'post__in' => [],
106
            'posts_per_page' => 25,
107
        ];
108
        $query = $request['search'] ?? '';
109
        if (is_numeric($query)) {
110
            $args['post__in'][] = (int) $query;
111
        } else {
112
            $args['s'] = $query;
113
        }
114
        $results = glsr(Database::class)->posts($args);
115
        $include = Cast::toArray($request['include'] ?? []);
116
        $include = array_filter($include, fn ($id) => !array_key_exists($id, $results));
117
        if (!empty($include)) {
118
            $results += glsr(Database::class)->posts([
119
                'post__in' => $include,
120
            ]);
121
        }
122
        $results = [
123
            'post_id' => esc_html_x('The Current Page', 'admin-text', 'site-reviews').' (post_id)',
124
            'parent_id' => esc_html_x('The Parent Page', 'admin-text', 'site-reviews').' (parent_id)',
125
        ] + $results;
126
        return $results;
127
    }
128
129
    public function getAssignedTermsOptions(\WP_REST_Request $request): array
130
    {
131
        $results = glsr(Database::class)->terms([
132
            'number' => 25,
133
            'search' => $request['search'] ?? '',
134
        ]);
135
        $include = Cast::toArray($request['include'] ?? []);
136
        $include = array_filter($include, fn ($id) => !array_key_exists($id, $results));
137
        if (!empty($include)) {
138
            $results += glsr(Database::class)->terms([
139
                'term_taxonomy_id' => $include,
140
            ]);
141
        }
142
        return $results;
143
    }
144
145
    public function getAssignedUsersOptions(\WP_REST_Request $request): array
146
    {
147
        $results = glsr(Database::class)->users([
148
            'number' => 25,
149
            'search_wild' => $request['search'] ?? '',
150
        ]);
151
        $include = Cast::toArray($request['include'] ?? []);
152
        $include = array_filter($include, fn ($id) => !array_key_exists($id, $results));
153
        if (!empty($include)) {
154
            $results += glsr(Database::class)->users([
155
                'include' => $include,
156
            ]);
157
        }
158
        $results = [
159
            'user_id' => esc_html_x('The Logged In User', 'admin-text', 'site-reviews').' (user_id)',
160
            'author_id' => esc_html_x('The Page Author', 'admin-text', 'site-reviews').' (author_id)',
161
            'profile_id' => esc_html_x('The Profile User', 'admin-text', 'site-reviews').' (profile_id)',
162
        ] + $results;
163
        return $results;
164
    }
165
166
    public function getDisplayOptions(): array
167
    {
168
        $options = $this->displayOptions();
169
        return glsr()->filterArray('shortcode/display-options', $options, $this->shortcode, $this);
170
    }
171
172
    public function getHideOptions(): array
173
    {
174
        $options = $this->hideOptions();
175
        return glsr()->filterArray('shortcode/hide-options', $options, $this->shortcode, $this);
176
    }
177
178
    public function getTypeOptions(): array
179
    {
180
        return glsr()->retrieveAs('array', 'review_types', []);
181
    }
182
183
    public function hasVisibleFields(array $args = []): bool
184
    {
185
        if (!empty($args)) {
186
            $this->normalize($args);
187
        }
188
        $defaults = $this->getHideOptions();
189
        $hide = $this->args['hide'] ?? [];
190
        $hide = array_flip(Arr::consolidate($hide));
191
        unset($defaults['if_empty'], $hide['if_empty']);
192
        return !empty(array_diff_key($defaults, $hide));
193
    }
194
195
    /**
196
     * @return static
197
     */
198
    public function normalize(array $args, string $type = '')
199
    {
200
        if (!empty($type)) {
201
            $this->type = $type;
202
        }
203
        $args = glsr()->filterArray('shortcode/args', $args, $this->shortcode);
204
        $args = $this->defaults()->unguardedRestrict($args);
205
        foreach ($args as $key => &$value) {
206
            $method = Helper::buildMethodName('normalize', $key);
207
            if (method_exists($this, $method)) {
208
                $value = call_user_func([$this, $method], $value, $args);
209
            }
210
        }
211
        $this->args = $args;
212
        return $this;
213
    }
214
215
    public function register(): void
216
    {
217 8
        if (!function_exists('add_shortcode')) {
218
            return;
219 8
        }
220 8
        $shortcode = (new \ReflectionClass($this))->getShortName();
221 8
        $shortcode = Str::snakeCase($shortcode);
222
        $shortcode = str_replace('_shortcode', '', $shortcode);
223
        add_shortcode($shortcode, [$this, 'buildShortcode']);
224
        glsr()->append('shortcodes', get_class($this), $shortcode);
225
    }
226
227
    protected function config(): array
228
    {
229
        return [];
230
    }
231
232
    protected function debug(array $data = []): void
233
    {
234
        if (empty($this->args['debug']) || 'shortcode' !== $this->type) {
235
            return;
236
        }
237
        $data = wp_parse_args($data, [
238
            'args' => $this->args,
239
            'shortcode' => $this->shortcode,
240
        ]);
241
        ksort($data);
242
        ob_start();
243
        glsr_debug($data);
244
        $this->debug = ob_get_clean();
245
    }
246
247
    protected function displayOptions(): array
248
    {
249
        return [];
250
    }
251
252
    protected function hideOptions(): array
253
    {
254
        return [];
255
    }
256
257
    protected function maxRating(): int
258
    {
259
        return Cast::toInt(glsr()->constant('MAX_RATING', Rating::class));
260
    }
261
262
    protected function minRating(): int
263
    {
264
        return Cast::toInt(glsr()->constant('MIN_RATING', Rating::class));
265
    }
266
267
    /**
268
     * @param string $value
269
     */
270
    protected function normalizeAssignedPosts($value): string
271
    {
272
        $values = Cast::toArray($value);
273
        $postTypes = [];
274
        foreach ($values as $postType) {
275
            if (!is_numeric($postType) && post_type_exists((string) $postType)) {
276
                $postTypes[] = $postType;
277
            }
278
        }
279
        $values = glsr(Sanitizer::class)->sanitizePostIds($values);
280
        $values = glsr(Multilingual::class)->getPostIdsForAllLanguages($values);
281
        $values = array_merge($values, $postTypes);
282
        return implode(',', $values);
283
    }
284
285
    /**
286
     * @param string $value
287
     */
288
    protected function normalizeAssignedTerms($value): string
289
    {
290
        $values = glsr(Sanitizer::class)->sanitizeTermIds($value);
291
        $values = glsr(Multilingual::class)->getTermIdsForAllLanguages($values);
292
        return implode(',', $values);
293
    }
294
295
    /**
296
     * @param string $value
297
     */
298
    protected function normalizeAssignedUsers($value): string
299
    {
300
        $values = glsr(Sanitizer::class)->sanitizeUserIds($value);
301
        return implode(',', $values);
302
    }
303
304
    /**
305
     * @param string|array $value
306
     */
307
    protected function normalizeHide($value): array
308
    {
309
        $hideKeys = array_keys($this->getHideOptions());
310
        return array_filter(Cast::toArray($value),
311
            fn ($value) => in_array($value, $hideKeys)
312
        );
313
    }
314
315
    /**
316
     * @param string $value
317
     */
318
    protected function normalizeLabels($value): array
319
    {
320
        $defaults = [
321
            __('Excellent', 'site-reviews'),
322
            __('Very good', 'site-reviews'),
323
            __('Average', 'site-reviews'),
324
            __('Poor', 'site-reviews'),
325
            __('Terrible', 'site-reviews'),
326
        ];
327
        $maxRating = $this->maxRating();
328
        $defaults = array_pad(array_slice($defaults, 0, $maxRating), $maxRating, '');
329
        $labels = array_map('trim', explode(',', $value));
330
        foreach ($defaults as $i => $label) {
331
            if (!empty($labels[$i])) {
332
                $defaults[$i] = $labels[$i];
333
            }
334
        }
335
        return array_combine(range($maxRating, 1), $defaults);
336
    }
337
338
    /**
339
     * @todo make this an abstract method in v8
340
     */
341
    protected function shortcodeDescription(): string
342
    {
343
        return '';
344
    }
345
346
    /**
347
     * @todo make this an abstract method in v8
348
     */
349
    protected function shortcodeName(): string
350
    {
351
        return '';
352
    }
353
354
    protected function shortcodeTag(): string
355
    {
356
        return Str::snakeCase(
357
            str_replace('Shortcode', '', (new \ReflectionClass($this))->getShortName())
358
        );
359
    }
360
}
361