This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||
2 | |||
3 | namespace GeminiLabs\SiteReviews\Integrations\Bricks; |
||
4 | |||
5 | use GeminiLabs\SiteReviews\Controllers\AbstractController; |
||
6 | use GeminiLabs\SiteReviews\Database; |
||
7 | use GeminiLabs\SiteReviews\Helpers\Arr; |
||
8 | use GeminiLabs\SiteReviews\Helpers\Str; |
||
9 | use GeminiLabs\SiteReviews\Helpers\Svg; |
||
10 | use GeminiLabs\SiteReviews\Modules\Sanitizer; |
||
11 | |||
12 | class Controller extends AbstractController |
||
13 | { |
||
14 | /** |
||
15 | * @param array $i18n |
||
16 | * |
||
17 | * @filter bricks/builder/i18n |
||
18 | */ |
||
19 | public function filterBuilderI18n($i18n): array |
||
20 | { |
||
21 | $i18n = Arr::consolidate($i18n); |
||
22 | $i18n[glsr()->id] = glsr()->name; |
||
23 | return $i18n; |
||
24 | } |
||
25 | |||
26 | /** |
||
27 | * @param array $controls |
||
28 | * |
||
29 | * @filter bricks/elements/site_review/controls |
||
30 | * @filter bricks/elements/site_reviews/controls |
||
31 | * @filter bricks/elements/site_reviews_form/controls |
||
32 | * @filter bricks/elements/site_reviews_summary/controls |
||
33 | */ |
||
34 | public function filterControls($controls): array |
||
35 | { |
||
36 | $sections = [ |
||
37 | 'display' => esc_html_x('Display', 'admin-text', 'site-reviews'), |
||
38 | 'hide' => esc_html_x('Hide', 'admin-text', 'site-reviews'), |
||
39 | 'schema' => esc_html_x('Schema', 'admin-text', 'site-reviews'), |
||
40 | 'text' => esc_html_x('Text', 'admin-text', 'site-reviews'), |
||
41 | ]; |
||
42 | $sectioned = []; |
||
43 | foreach ($controls as $key => $control) { |
||
44 | $group = $control['group'] ?? 'general'; |
||
45 | if (!array_key_exists($group, $sections)) { |
||
46 | $sectioned[$key] = $control; |
||
47 | continue; |
||
48 | } |
||
49 | if (!array_key_exists("separator_{$group}", $sectioned)) { |
||
50 | $sectioned["separator_{$group}"] = [ |
||
51 | 'group' => 'general', |
||
52 | 'label' => esc_html($sections[$group] ?? ucfirst($group)), |
||
53 | 'tab' => 'content', |
||
54 | 'type' => 'separator', |
||
55 | ]; |
||
56 | } |
||
57 | $control['group'] = 'general'; |
||
58 | $sectioned[$key] = $control; |
||
59 | } |
||
60 | return $sectioned; |
||
61 | } |
||
62 | |||
63 | /** |
||
64 | * @param \Bricks\Element $element |
||
0 ignored issues
–
show
|
|||
65 | * |
||
66 | * @filter bricks/element/settings:100 |
||
67 | */ |
||
68 | public function filterSettingsClass($settings, $element): array |
||
69 | { |
||
70 | $settings = Arr::consolidate($settings); |
||
71 | if (!is_a($element, BricksElement::class)) { |
||
72 | return $settings; |
||
73 | } |
||
74 | $classes = $settings['class'] ?? ''; |
||
75 | $classes = explode(' ', $classes); |
||
76 | if ($preset = $element->styledSetting('style_preset')) { |
||
77 | $classes[] = "is-style-{$preset}"; |
||
78 | } |
||
79 | $classes = $element->styledClasses($classes); |
||
80 | $classes = implode(' ', $classes); |
||
81 | $settings['class'] = glsr(Sanitizer::class)->sanitizeAttrClass($classes); |
||
82 | return $settings; |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * Consolidate multi-checkbox values because Bricks does not allow them. |
||
87 | * |
||
88 | * @param \Bricks\Element $element |
||
89 | * |
||
90 | * @filter bricks/element/settings |
||
91 | */ |
||
92 | public function filterSettingsMultiCheckbox($settings, $element): array |
||
93 | { |
||
94 | $settings = Arr::consolidate($settings); |
||
95 | if (!is_a($element, BricksElement::class)) { |
||
96 | return $settings; |
||
97 | } |
||
98 | foreach ($element->elementConfig() as $key => $control) { |
||
99 | $type = $control['type'] ?? ''; |
||
100 | $options = Arr::getAs('array', $control, 'options'); |
||
101 | if ('checkbox' !== $type || empty($options)) { |
||
102 | continue; |
||
103 | } |
||
104 | $values = array_filter( |
||
105 | array_keys($settings), |
||
106 | fn ($k) => !empty($settings[$k]) && str_starts_with($k, "{$key}_") |
||
107 | ); |
||
108 | $settings[$key] = array_map(fn ($k) => Str::removePrefix($k, "{$key}_"), $values); |
||
109 | } |
||
110 | return $settings; |
||
111 | } |
||
112 | |||
113 | /** |
||
114 | * Remove the "id::" prefix used to maintain javascript sorting. |
||
115 | * |
||
116 | * @param \Bricks\Element $element |
||
117 | * |
||
118 | * @filter bricks/element/settings |
||
119 | */ |
||
120 | public function filterSettingsPrefixedId($settings, $element): array |
||
121 | { |
||
122 | $settings = Arr::consolidate($settings); |
||
123 | if (!is_a($element, BricksElement::class)) { |
||
124 | return $settings; |
||
125 | } |
||
126 | foreach ($settings as $key => $value) { |
||
127 | if (is_string($value) && str_starts_with($value, 'id::')) { |
||
128 | $settings[$key] = Str::removePrefix($value, 'id::'); |
||
129 | continue; |
||
130 | } |
||
131 | if (is_array($value) && wp_is_numeric_array($value)) { |
||
132 | $settings[$key] = array_map( |
||
133 | fn ($val) => is_string($val) ? Str::removePrefix($val, 'id::') : '', |
||
134 | $value |
||
135 | ); |
||
136 | } |
||
137 | } |
||
138 | return $settings; |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * @filter bricks/theme_styles/controls |
||
143 | */ |
||
144 | public function filterThemeStyleControls(array $controls): array |
||
145 | { |
||
146 | $shortcodes = [ |
||
147 | 'site_review', |
||
148 | 'site_reviews', |
||
149 | 'site_reviews_form', |
||
150 | 'site_reviews_summary', |
||
151 | ]; |
||
152 | if (!class_exists('Bricks\Elements')) { |
||
153 | return $controls; |
||
154 | } |
||
155 | foreach ($shortcodes as $shortcode) { |
||
156 | if ($element = \Bricks\Elements::$elements[$shortcode] ?? false) { |
||
0 ignored issues
–
show
The type
Bricks\Elements was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||
157 | $instance = new $element['class'](); |
||
158 | $instance->set_controls(); |
||
159 | $instance->controls = apply_filters("bricks/elements/$shortcode/controls", $instance->controls); |
||
160 | $themeControls = array_filter($instance->controls, fn ($control) => !empty($control['themeStyle'])); |
||
161 | array_walk($themeControls, function (&$control) use ($shortcode) { |
||
162 | $control['group'] = $shortcode; |
||
163 | unset($control['required']); |
||
164 | }); |
||
165 | $controls[$shortcode] = $themeControls; |
||
166 | } |
||
167 | } |
||
168 | return $controls; |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * @filter bricks/theme_styles/control_groups |
||
173 | */ |
||
174 | public function filterThemeStyleGroups(array $groups): array |
||
175 | { |
||
176 | $shortcodes = [ |
||
177 | 'site_review', |
||
178 | 'site_reviews', |
||
179 | 'site_reviews_form', |
||
180 | 'site_reviews_summary', |
||
181 | ]; |
||
182 | if (!class_exists('Bricks\Elements')) { |
||
183 | return $groups; |
||
184 | } |
||
185 | foreach ($shortcodes as $shortcode) { |
||
186 | if ($element = \Bricks\Elements::$elements[$shortcode] ?? false) { |
||
187 | $groups[$shortcode] = [ |
||
188 | 'title' => sprintf('%s - %s', glsr()->name, $element['label']), |
||
189 | ]; |
||
190 | } |
||
191 | } |
||
192 | return $groups; |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * @action wp_enqueue_scripts |
||
197 | */ |
||
198 | public function printInlineStyles(): void |
||
199 | { |
||
200 | if (!function_exists('bricks_is_builder')) { |
||
201 | return; |
||
202 | } |
||
203 | if (!bricks_is_builder()) { |
||
204 | return; |
||
205 | } |
||
206 | $iconForm = Svg::encoded('assets/images/icons/bricks/icon-form.svg'); |
||
207 | $iconReview = Svg::encoded('assets/images/icons/bricks/icon-review.svg'); |
||
208 | $iconReviews = Svg::encoded('assets/images/icons/bricks/icon-reviews.svg'); |
||
209 | $iconSummary = Svg::encoded('assets/images/icons/bricks/icon-summary.svg'); |
||
210 | $css = " |
||
211 | i[class^='ti-site_review']::before { |
||
212 | background-color: currentColor; |
||
213 | content: ''; |
||
214 | display: inline-block; |
||
215 | height: 1em; |
||
216 | mask-position: center; |
||
217 | mask-repeat: no-repeat; |
||
218 | mask-size: 100%; |
||
219 | width: 1em; |
||
220 | } |
||
221 | i.ti-site_reviews_form::before { |
||
222 | mask-image: url(\"{$iconForm}\"); |
||
223 | } |
||
224 | i.ti-site_review::before { |
||
225 | mask-image: url(\"{$iconReview}\"); |
||
226 | } |
||
227 | i.ti-site_reviews::before { |
||
228 | mask-image: url(\"{$iconReviews}\"); |
||
229 | } |
||
230 | i.ti-site_reviews_summary::before { |
||
231 | mask-image: url(\"{$iconSummary}\"); |
||
232 | } |
||
233 | .glsr :is(a,button,input,textarea,select,.dz-clickable) { |
||
234 | pointer-events: none !important; |
||
235 | } |
||
236 | "; |
||
237 | wp_add_inline_style('bricks-builder', $css); |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * @action init |
||
242 | */ |
||
243 | public function registerElements(): void |
||
244 | { |
||
245 | if (class_exists('Bricks\Element')) { |
||
246 | BricksSiteReview::registerElement(); |
||
247 | BricksSiteReviews::registerElement(); |
||
248 | BricksSiteReviewsForm::registerElement(); |
||
249 | BricksSiteReviewsSummary::registerElement(); |
||
250 | } |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * @action wp_ajax_bricks_glsr_assigned_posts |
||
255 | */ |
||
256 | public function searchAssignedPosts(): void |
||
257 | { |
||
258 | $this->verifyAjaxRequest(); |
||
259 | $query = stripslashes_deep(sanitize_text_field((string) filter_input(INPUT_GET, 'search'))); |
||
260 | $args = [ |
||
261 | 'post__in' => [], |
||
262 | 'posts_per_page' => 25, |
||
263 | ]; |
||
264 | if (is_numeric($query)) { |
||
265 | $args['post__in'][] = (int) $query; |
||
266 | } else { |
||
267 | $args['s'] = $query; |
||
268 | } |
||
269 | $posts = glsr(Database::class)->posts($args); |
||
270 | if ($include = $this->includedIds($posts)) { |
||
271 | $posts += glsr(Database::class)->posts([ |
||
272 | 'post__in' => $include, |
||
273 | ]); |
||
274 | } |
||
275 | $results = $this->prefixedResults($posts); |
||
276 | if (empty($query)) { |
||
277 | $results = [ |
||
278 | 'post_id' => esc_html_x('The Current Page', 'admin-text', 'site-reviews'), |
||
279 | 'parent_id' => esc_html_x('The Parent Page', 'admin-text', 'site-reviews'), |
||
280 | ] + $results; |
||
281 | } |
||
282 | wp_send_json_success($results); |
||
283 | } |
||
284 | |||
285 | /** |
||
286 | * @action wp_ajax_bricks_glsr_assigned_terms |
||
287 | */ |
||
288 | public function searchAssignedTerms(): void |
||
289 | { |
||
290 | $this->verifyAjaxRequest(); |
||
291 | $query = stripslashes_deep(sanitize_text_field((string) filter_input(INPUT_GET, 'search'))); |
||
292 | $terms = glsr(Database::class)->terms([ |
||
293 | 'number' => 25, |
||
294 | 'search' => $query, |
||
295 | ]); |
||
296 | if ($include = $this->includedIds($terms)) { |
||
297 | $terms += glsr(Database::class)->terms([ |
||
298 | 'term_taxonomy_id' => $include, |
||
299 | ]); |
||
300 | } |
||
301 | $results = $this->prefixedResults($terms); |
||
302 | wp_send_json_success($results); |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * @action wp_ajax_bricks_glsr_assigned_users |
||
307 | */ |
||
308 | public function searchAssignedUsers(): void |
||
309 | { |
||
310 | $this->verifyAjaxRequest(); |
||
311 | $query = stripslashes_deep(sanitize_text_field((string) filter_input(INPUT_GET, 'search'))); |
||
312 | $users = glsr(Database::class)->users([ |
||
313 | 'number' => 25, |
||
314 | 'search_wild' => $query, |
||
315 | ]); |
||
316 | if ($include = $this->includedIds($users)) { |
||
317 | $users += glsr(Database::class)->users([ |
||
318 | 'include' => $include, |
||
319 | ]); |
||
320 | } |
||
321 | $results = $this->prefixedResults($users); |
||
322 | if (empty($query)) { |
||
323 | $results = [ |
||
324 | 'user_id' => esc_html_x('The Logged In User', 'admin-text', 'site-reviews'), |
||
325 | 'author_id' => esc_html_x('The Page Author', 'admin-text', 'site-reviews'), |
||
326 | 'profile_id' => esc_html_x('The Profile User', 'admin-text', 'site-reviews'), |
||
327 | ] + $results; |
||
328 | } |
||
329 | wp_send_json_success($results); |
||
330 | } |
||
331 | |||
332 | /** |
||
333 | * @action wp_ajax_bricks_glsr_author |
||
334 | */ |
||
335 | public function searchAuthor(): void |
||
336 | { |
||
337 | $this->verifyAjaxRequest(); |
||
338 | $query = stripslashes_deep(sanitize_text_field((string) filter_input(INPUT_GET, 'search'))); |
||
339 | $users = glsr(Database::class)->users([ |
||
340 | 'number' => 25, |
||
341 | 'search_wild' => $query, |
||
342 | ]); |
||
343 | if ($include = $this->includedIds($users)) { |
||
344 | $users += glsr(Database::class)->users([ |
||
345 | 'include' => $include, |
||
346 | ]); |
||
347 | } |
||
348 | $results = $this->prefixedResults($users); |
||
349 | if (empty($query)) { |
||
350 | $results = [ |
||
351 | 'user_id' => esc_html_x('The Logged In User', 'admin-text', 'site-reviews'), |
||
352 | ] + $results; |
||
353 | } |
||
354 | wp_send_json_success($results); |
||
355 | } |
||
356 | |||
357 | /** |
||
358 | * @action wp_ajax_bricks_glsr_post_id |
||
359 | */ |
||
360 | public function searchPostId(): void |
||
361 | { |
||
362 | $this->verifyAjaxRequest(); |
||
363 | $query = stripslashes_deep(sanitize_text_field((string) filter_input(INPUT_GET, 'search'))); |
||
364 | $args = [ |
||
365 | 'post__in' => [], |
||
366 | 'post_type' => glsr()->post_type, |
||
367 | 'posts_per_page' => 25, |
||
368 | ]; |
||
369 | if (is_numeric($query)) { |
||
370 | $args['post__in'][] = (int) $query; |
||
371 | } else { |
||
372 | $args['s'] = (string) $query; |
||
373 | } |
||
374 | $posts = glsr(Database::class)->posts($args); |
||
375 | if ($include = $this->includedIds($posts)) { |
||
376 | $posts += glsr(Database::class)->posts([ |
||
377 | 'post__in' => $include, |
||
378 | 'post_type' => glsr()->post_type, |
||
379 | ]); |
||
380 | } |
||
381 | $results = $this->prefixedResults($posts); |
||
382 | wp_send_json_success($results); |
||
383 | } |
||
384 | |||
385 | protected function includedIds(array $results): array |
||
386 | { |
||
387 | $ids = filter_input(INPUT_GET, 'include', FILTER_DEFAULT, FILTER_FORCE_ARRAY) ?? []; |
||
388 | $ids = array_map(fn ($id) => Str::removePrefix((string) $id, 'id::'), $ids); |
||
389 | $ids = Arr::uniqueInt($ids); |
||
390 | $ids = array_filter($ids, fn ($id) => !array_key_exists($id, $results)); |
||
391 | return $ids; |
||
392 | } |
||
393 | |||
394 | protected function prefixedResults(array $results, bool $prefixTitle = true): array |
||
395 | { |
||
396 | if ($prefixTitle) { |
||
397 | array_walk($results, function (&$title, $key) { |
||
398 | if (is_numeric($key)) { |
||
399 | $title = "{$key}: {$title}"; |
||
400 | } |
||
401 | }); |
||
402 | } |
||
403 | return array_combine( |
||
404 | array_map(fn ($key) => "id::{$key}", array_keys($results)), |
||
405 | $results |
||
406 | ); |
||
407 | } |
||
408 | |||
409 | protected function verifyAjaxRequest(): void |
||
410 | { |
||
411 | if (method_exists('Bricks\Ajax', 'verify_request')) { // @phpstan-ignore-line |
||
412 | \Bricks\Ajax::verify_request('bricks-nonce-builder'); |
||
0 ignored issues
–
show
The type
Bricks\Ajax was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||
413 | } elseif (!check_ajax_referer('bricks-nonce-builder', 'nonce', false)) { |
||
414 | wp_send_json_error('verify_nonce: "bricks-nonce-builder" is invalid.'); |
||
415 | } |
||
416 | } |
||
417 | } |
||
418 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths