Test Failed
Push — develop ( 8fa5d6...c76118 )
by Paul
07:13
created

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