Test Failed
Push — develop ( 7aea1a...9fd874 )
by Paul
15:27
created

Controller::fetchAssignedUsers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 2
Metric Value
eloc 1
c 2
b 0
f 2
dl 0
loc 8
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Integrations\Breakdance;
4
5
use GeminiLabs\SiteReviews\Controllers\AbstractController;
6
use GeminiLabs\SiteReviews\Database\ShortcodeOptionManager;
7
use GeminiLabs\SiteReviews\Helpers\Arr;
8
use GeminiLabs\SiteReviews\Helpers\Str;
9
use GeminiLabs\SiteReviews\Helpers\Svg;
10
11
class Controller extends AbstractController
12
{
13
    /**
14
     * @filter site-reviews/modal_wrapped_by
15
     */
16
    public function filterModalWrappedBy(array $builders): array
17
    {
18
        $builders[] = 'breakdance';
19
        return $builders;
20
    }
21
22
    /**
23
     * Breakdance does not provide a way to create a multi-select dropdown
24
     * populated by an AJAX callback on init AND search. To get around this,
25
     * we use the post_chooser control and override the callback with our own.
26
     *
27
     * @action breakdance_ajax_breakdance_get_posts:1
28
     * @action wp_ajax_breakdance_get_posts:1
29
     * @action wp_ajax_nopriv_breakdance_get_posts:1
30
     */
31
    public function interceptGetPostsQuery(): void
32
    {
33
        if (!$this->verifyRequest()) {
34
            return;
35
        }
36
        $option = Str::removePrefix(filter_input(INPUT_POST, 'postType'), glsr()->prefix);
37
        $search = filter_input(INPUT_POST, 'search');
38
        $params = compact('option', 'search');
39
        $results = call_user_func([glsr(ShortcodeOptionManager::class), $option], $params);
40
        $replacements = [ // the post_chooser control requires integer keys
41
            'post_id' => -10,
42
            'parent_id' => -20,
43
            'user_id' => -30,
44
            'author_id' => -40,
45
            'profile_id' => -50,
46
        ];
47
        if (in_array($option, ['assigned_posts'])) {
48
            $thumbnailFn = fn ($id) => get_the_post_thumbnail_url($id, 'thumbnail');
49
        } elseif (in_array($option, ['assigned_users', 'author'])) {
50
            $thumbnailFn = fn ($id) => get_avatar_url($id);
51
        }
52
        $data = $this->prepareResponse($results, $thumbnailFn ?? null, $replacements);
53
        if (in_array($option, ['post_id'])) {
54
            array_walk($data, function (&$item) {
55
                $item['title'] = "{$item['id']}: {$item['title']}";
56
            });
57
        }
58
        wp_send_json_success($data, 200);
59
        exit; // @phpstan-ignore-line
60
    }
61
62
    /**
63
     * @action unofficial_i_am_kevin_geary_master_of_all_things_css_and_html
64
     */
65
    public function printInlineStyles(): void
66
    {
67
        $icon = Svg::encoded('assets/images/icon-static.svg');
68
        echo '<style>'.
69
            '.breakdance-control-wrapper:has(+ .breakdance-control-wrapper [data-test-id$="_description_alert"] .breakdance-alert-box) {'.
70
                'margin-bottom: 7px;'.
71
            '}'.
72
            '[data-test-id$="_description_alert"] .breakdance-alert-box {'.
73
                'padding-inline: 13px;',
74
                '.v-alert__border--left {'.
75
                    'display: none;'.
76
                '}',
77
            '}',
78
            '.breakdance-add-panel__element:has(.glsr-icon) .breakdance-element-badge {'.
79
                'padding: 0;'.
80
                '&::after {'.
81
                    'background-image: url("'.$icon.'");'.
82
                    'content: "";'.
83
                    'height: var(--text-lg);'.
84
                    'width: var(--text-lg);'.
85
                '}'.
86
            '}'.
87
        '</style>';
88
    }
89
90
    /**
91
     * Breakdance loads an element by filtering the result of get_declared_classes
92
     * and checking if the class is_subclass_of \Breakdance\Elements\Element.
93
     *
94
     * Controls are added dynamically from the Shortcode class to enforce consistancy
95
     * across builder integrations. As a result, we need to bypass the Element Studio
96
     * and we do this by setting the save location to $onlyForAdvancedUsers and
97
     * $excludeFromElementStudio.
98
     *
99
     * @action breakdance_loaded:5
100
     */
101
    public function registerElements(): void
102
    {
103
        $pluginDir = dirname(plugin_basename(glsr()->file));
104
        \Breakdance\Elements\registerCategory(glsr()->id, glsr()->name);
105
        \Breakdance\ElementStudio\registerSaveLocation(
106
            "{$pluginDir}/assets/breakdance/elements",
107
            'GLSR_Breakdance',
108
            'element',
109
            'Site Reviews Elements',
110
            true, // onlyForAdvancedUsers
111
            true // excludeFromElementStudio
112
        );
113
        \Breakdance\ElementStudio\registerSaveLocation(
114
            "{$pluginDir}/assets/breakdance/macros",
115
            'GLSR_Breakdance',
116
            'macro',
117
            'Site Reviews Macros',
118
            true, // onlyForAdvancedUsers
119
            true // excludeFromElementStudio
120
        );
121
        \Breakdance\ElementStudio\registerSaveLocation(
122
            "{$pluginDir}/assets/breakdance/presets",
123
            'GLSR_Breakdance',
124
            'preset',
125
            'Site Reviews Presets',
126
            true, // onlyForAdvancedUsers
127
            true // excludeFromElementStudio
128
        );
129
    }
130
131
    /**
132
     * Unfortunately we can't use this yet because Breakdance does not support
133
     * AJAX searching in multiselect controls.
134
     *
135
     * @action breakdance_loaded
136
     */
137
    public function registerRoutes(): void
138
    {
139
        return; // We can't use this yet...
140
        // $input = filter_input_array(INPUT_POST, [ // @phpstan-ignore-line
141
        //     'requestData' => [
142
        //         'context' => [
143
        //             'filter' => fn ($value) => is_numeric($value)
144
        //                 ? intval($value)
145
        //                 : strip_tags($value),
146
        //             'flags' => FILTER_REQUIRE_ARRAY,
147
        //         ],
148
        //     ],
149
        // ]);
150
        // $include = Arr::consolidate($input['requestData']['context'] ?? []);
151
        // \Breakdance\AJAX\register_handler(
152
        //     glsr()->prefix.'breakdance_assigned_posts',
153
        //     fn () => $this->fetchAssignedPosts($include),
154
        //     'edit'
155
        // );
156
        // \Breakdance\AJAX\register_handler(
157
        //     glsr()->prefix.'breakdance_assigned_terms',
158
        //     fn () => $this->fetchAssignedTerms($include),
159
        //     'edit'
160
        // );
161
        // \Breakdance\AJAX\register_handler(
162
        //     glsr()->prefix.'breakdance_assigned_users',
163
        //     fn () => $this->fetchAssignedUsers($include),
164
        //     'edit'
165
        // );
166
        // \Breakdance\AJAX\register_handler(
167
        //     glsr()->prefix.'breakdance_author',
168
        //     fn () => $this->fetchAuthor($include),
169
        //     'edit'
170
        // );
171
        // \Breakdance\AJAX\register_handler(
172
        //     glsr()->prefix.'breakdance_post_id',
173
        //     fn () => $this->fetchPostId($include),
174
        //     'edit'
175
        // );
176
    }
177
178
    /**
179
     * Unfortunately we can't use this yet because Breakdance does not support
180
     * AJAX searching in multiselect controls.
181
     */
182
    protected function fetchAssignedPosts(array $include): array
183
    {
184
        // $include = array_filter($include, fn ($id) => is_numeric($id) || in_array($id, [
185
        //     'parent_id',
186
        //     'post_id',
187
        // ]));
188
        return [];
189
    }
190
191
    /**
192
     * Unfortunately we can't use this yet because Breakdance does not support
193
     * AJAX searching in multiselect controls.
194
     */
195
    protected function fetchAssignedTerms(array $include): array
196
    {
197
        return [];
198
    }
199
200
    /**
201
     * Unfortunately we can't use this yet because Breakdance does not support
202
     * AJAX searching in multiselect controls.
203
     */
204
    protected function fetchAssignedUsers(array $include): array
205
    {
206
        // $include = array_filter($include, fn ($id) => is_numeric($id) || in_array($id, [
207
        //     'author_id',
208
        //     'profile_id',
209
        //     'user_id',
210
        // ]));
211
        return [];
212
    }
213
214
    /**
215
     * Unfortunately we can't use this yet because Breakdance does not support
216
     * AJAX searching in multiselect controls.
217
     */
218
    protected function fetchAuthor(array $include): array
219
    {
220
        // $include = array_filter($include, fn ($id) => is_numeric($id) || in_array($id, [
221
        //     'user_id',
222
        // ]));
223
        return [];
224
    }
225
226
    /**
227
     * Unfortunately we can't use this yet because Breakdance does not support
228
     * AJAX searching in multiselect controls.
229
     */
230
    protected function fetchPostId(array $include): array
231
    {
232
        return [];
233
    }
234
235
    protected function prepareResponse(array $results, ?callable $thumbnailFn = null, array $replacements = []): array
236
    {
237
        if (!$thumbnailFn) {
238
            $thumbnailFn = fn () => false;
239
        }
240
        $callback = fn ($id, $title) => [
241
            'id' => $replacements[$id] ?? $id,
242
            'title' => $title,
243
            'thumbnail' => $thumbnailFn($id),
244
        ];
245
        return array_map($callback, array_keys($results), $results);
246
    }
247
248
    protected function verifyRequest(): bool
249
    {
250
        if (!str_starts_with((string) filter_input(INPUT_POST, 'postType'), glsr()->prefix)) {
251
            return false;
252
        }
253
        if (!\Breakdance\Permissions\hasMinimumPermission('edit')) {
254
            return false;
255
        }
256
        $nonceTick = check_ajax_referer(\Breakdance\AJAX\get_nonce_key_for_ajax_requests(), false, false);
257
        if (!$nonceTick) {
258
            return false;
259
        }
260
        if (2 === $nonceTick) {
261
            $refreshNonce = \Breakdance\AJAX\get_nonce_for_ajax_requests();
262
            header('Breakdance-Refresh-Nonce:'.$refreshNonce);
263
        }
264
        return true;
265
    }
266
}
267