PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.86
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.86
51.1.86 51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 All 40 releases
← All changes | includes/controls/Ajax_Select2/Ajax_Select2_API.php +352 -0 51.1.2 → 51.1.86 View file →
@@ -1,0 +1,352 @@
1 +<?php /** @noinspection PhpUnused, SpellCheckingInspection, DuplicatedCode */
2 +
3 +namespace King_Addons\AJAX_Select2;
4 +
5 +use King_Addons\Core;
6 +use WP_Query;
7 +use WP_User_Query;
8 +
9 +if (!defined('ABSPATH')) {
10 + exit; // Exit if accessed directly.
11 +}
12 +
13 +class Ajax_Select2_API
14 +{
15 + private const ALLOWED_ACTIONS = [
16 + 'getElementorTemplates',
17 + 'getPostsByPostType',
18 + 'getPostTypeTaxonomies',
19 + 'getCustomMetaKeys',
20 + 'getUsers',
21 + 'getTaxonomies',
22 + 'getCustomMetaKeysProduct',
23 + ];
24 +
25 + public function __construct()
26 + {
27 + $this->init();
28 + }
29 +
30 + public function init(): void
31 + {
32 + add_action('rest_api_init', function () {
33 + register_rest_route(
34 + 'kingaddons/v1/ajaxselect2',
35 + '/(?P<action>\w+)/',
36 + [
37 + 'methods' => 'GET',
38 + 'callback' => [$this, 'callback'],
39 + 'permission_callback' => [$this, 'canAccess'],
40 + ]
41 + );
42 + });
43 + }
44 +
45 + public function canAccess($request): bool
46 + {
47 + $action = sanitize_key((string)($request['action'] ?? ''));
48 + $allowed_actions = array_map('sanitize_key', self::ALLOWED_ACTIONS);
49 +
50 + return current_user_can('edit_posts') && in_array($action, $allowed_actions, true);
51 + }
52 +
53 + public function callback($request)
54 + {
55 + $action = (string)($request['action'] ?? '');
56 +
57 + if (!in_array($action, self::ALLOWED_ACTIONS, true) || !is_callable([$this, $action])) {
58 + return new \WP_Error('king_addons_invalid_ajaxselect2_action', esc_html__('Invalid request.', 'king-addons'), ['status' => 400]);
59 + }
60 +
61 + return $this->{$action}($request);
62 + }
63 +
64 + public function getElementorTemplates($request): ?array
65 + {
66 + if (!current_user_can('edit_posts')) return null;
67 +
68 + $args = [
69 + 'post_type' => 'elementor_library',
70 + 'post_status' => 'publish',
71 + 'meta_key' => '_elementor_template_type',
72 + 'meta_value' => ['page', 'section', 'container'],
73 + 'numberposts' => 10
74 + ];
75 +
76 + // Load specific templates by IDs (for pre-populating selected values)
77 + if (isset($request['ids']) && !empty($request['ids'])) {
78 + $ids = array_filter(array_map('intval', explode(',', $request['ids'])));
79 + if (!empty($ids)) {
80 + $args['post__in'] = $ids;
81 + $args['numberposts'] = -1;
82 + unset($args['meta_key'], $args['meta_value']); // Allow any template type when loading by ID
83 + }
84 + }
85 +
86 + if (isset($request['s'])) {
87 + $args['s'] = sanitize_text_field((string)$request['s']);
88 + }
89 +
90 + $options = [];
91 + $the_query = new WP_Query($args);
92 +
93 + if ($the_query->have_posts()) {
94 + while ($the_query->have_posts()) {
95 + $the_query->the_post();
96 + $options[] = [
97 + 'id' => get_the_ID(),
98 + 'text' => wp_strip_all_tags(html_entity_decode(get_the_title())),
99 + ];
100 + }
101 + }
102 +
103 + wp_reset_postdata();
104 +
105 + return ['results' => $options];
106 + }
107 +
108 + public function getPostsByPostType($request): ?array
109 + {
110 + if (!current_user_can('edit_posts')) return null;
111 +
112 + $post_type = sanitize_key((string)($request['query_slug'] ?? ''));
113 +
114 + $args = [
115 + 'post_type' => $post_type,
116 + 'post_status' => $post_type === 'attachment' ? 'any' : 'publish',
117 + 'posts_per_page' => 15,
118 + ];
119 +
120 + if (isset($request['ids'])) {
121 + $args['post__in'] = array_filter(array_map('intval', explode(',', (string)$request['ids'])));
122 + }
123 +
124 + if (isset($request['s'])) {
125 + $args['s'] = sanitize_text_field((string)$request['s']);
126 + }
127 +
128 + $query = new WP_Query($args);
129 + $options = [];
130 +
131 + if ($query->have_posts()) {
132 + while ($query->have_posts()) {
133 + $query->the_post();
134 + $options[] = [
135 + 'id' => get_the_ID(),
136 + 'text' => wp_strip_all_tags(html_entity_decode(get_the_title())),
137 + ];
138 + }
139 + }
140 +
141 + wp_reset_postdata();
142 + return ['results' => $options];
143 + }
144 +
145 + public function getPostTypeTaxonomies($request): ?array
146 + {
147 + if (!current_user_can('edit_posts')) return null;
148 +
149 + $post_type = sanitize_key((string)($request['query_slug'] ?? ''));
150 +
151 + $taxonomies = get_object_taxonomies($post_type, 'objects');
152 + $options = [];
153 +
154 + if ($taxonomies) {
155 + foreach ($taxonomies as $taxonomy) {
156 +
157 + if (isset($request['s']) && stripos($taxonomy->label, sanitize_text_field((string)$request['s'])) === false) {
158 + continue;
159 + }
160 +
161 + if (isset($request['ids'])) {
162 + $ids = array_map('sanitize_key', explode(',', (string)($request['ids'] ?: '99999999')));
163 + if (!in_array($taxonomy->name, $ids)) {
164 + continue;
165 + }
166 + }
167 +
168 + $options[] = [
169 + 'id' => $taxonomy->name,
170 + 'text' => wp_strip_all_tags($taxonomy->label),
171 + ];
172 + }
173 + }
174 +
175 + return ['results' => $options];
176 + }
177 +
178 + public function getCustomMetaKeys($request)
179 + {
180 + if (!current_user_can('edit_posts')) return null;
181 +
182 + $post_types = Core::getCustomTypes('post', false);
183 + $data = [];
184 +
185 + foreach ($post_types as $slug => $name) {
186 + $posts = get_posts(['post_type' => $slug, 'posts_per_page' => -1]);
187 + $metaKeys = [];
188 +
189 + foreach ($posts as $post) {
190 + $keys = get_post_custom_keys($post->ID) ?: [];
191 + $keys = array_filter($keys, fn($k) => $k[0] !== '_');
192 + $metaKeys = array_merge($metaKeys, $keys);
193 + }
194 +
195 + $data[$slug] = array_unique($metaKeys);
196 + }
197 +
198 + $mergedKeys = array_values(
199 + array_unique(
200 + array_merge([], ...array_values($data))
201 + )
202 + );
203 +
204 + $filtered = array_filter($mergedKeys, function ($key) use ($request) {
205 + return !isset($request['s']) || strpos($key, sanitize_text_field((string)$request['s'])) !== false;
206 + });
207 +
208 + $options = array_map(fn($k) => ['id' => $k, 'text' => wp_strip_all_tags($k)], $filtered);
209 +
210 + return ['results' => $options];
211 + }
212 +
213 + public function getUsers($request)
214 + {
215 + if (!current_user_can('edit_posts')) return null;
216 +
217 + $args = [
218 + 'number' => 15,
219 + 'blog_id' => 0,
220 + ];
221 +
222 + if (!empty($request['ids'])) {
223 + $args['include'] = array_map('intval', explode(',', $request['ids']));
224 + }
225 +
226 + if (!empty($request['s'])) {
227 + $args['search'] = '*' . sanitize_text_field((string)$request['s']) . '*';
228 + }
229 +
230 + $results = (new WP_User_Query($args))->get_results();
231 +
232 + $options = array_map(
233 + fn($user) => ['id' => $user->ID, 'text' => wp_strip_all_tags($user->display_name)],
234 + $results ?: []
235 + );
236 +
237 + wp_reset_postdata();
238 +
239 + return ['results' => $options];
240 + }
241 +
242 + public function getTaxonomies($request)
243 + {
244 + if (!current_user_can('edit_posts')) return null;
245 +
246 + $tax = sanitize_key((string)($request['query_slug'] ?? ''));
247 + $args = [
248 + 'orderby' => 'name',
249 + 'order' => 'DESC',
250 + 'hide_empty' => true,
251 + 'number' => 10,
252 + ];
253 +
254 + if (isset($request['ids'])) {
255 + $args['include'] = array_filter(array_map('intval', explode(',', (string)($request['ids'] ?: '99999999'))));
256 + }
257 +
258 + if (!empty($request['s'])) {
259 + $args['name__like'] = sanitize_text_field((string)$request['s']);
260 + }
261 +
262 + $terms = get_terms($tax, $args);
263 + if (is_wp_error($terms)) {
264 + return ['results' => []];
265 + }
266 +
267 + $options = array_map(function ($term) {
268 + return [
269 + 'id' => $term->term_id,
270 + 'text' => wp_strip_all_tags($term->name),
271 + ];
272 + }, $terms);
273 +
274 + wp_reset_postdata();
275 +
276 + return ['results' => $options];
277 + }
278 +
279 + public function getCustomMetaKeysProduct($request)
280 + {
281 + if (!current_user_can('edit_posts')) return null;
282 +
283 + $options = [];
284 + $merged_meta_keys = [];
285 + $post_types = Core::getCustomTypes('post', false);
286 +
287 + foreach ($post_types as $slug => $name) {
288 + $posts = get_posts(['post_type' => $slug, 'posts_per_page' => -1]);
289 + foreach ($posts as $post) {
290 + $meta_keys = get_post_custom_keys($post->ID);
291 + if ($meta_keys) {
292 + foreach ($meta_keys as $key) {
293 + if ('_' !== substr($key, 0, 1)) {
294 + $merged_meta_keys[] = $key;
295 + }
296 + }
297 + }
298 + }
299 + }
300 +
301 + $merged_meta_keys = array_values(array_unique($merged_meta_keys));
302 + foreach ($merged_meta_keys as $key) {
303 + if (empty($request['s']) || false !== strpos($key, sanitize_text_field((string)$request['s']))) {
304 + $options[] = [
305 + 'id' => $key,
306 + 'text' => wp_strip_all_tags($key),
307 + ];
308 + }
309 + }
310 +
311 + $product_attributes = [];
312 + $products_query = new WP_Query([
313 + 'post_type' => 'product',
314 + 'posts_per_page' => -1,
315 + ]);
316 +
317 + if ($products_query->have_posts()) {
318 + while ($products_query->have_posts()) {
319 + $products_query->the_post();
320 +
321 + if (class_exists('WooCommerce')) {
322 + if (function_exists('wc_get_product')) {
323 + /** @noinspection PhpUndefinedFunctionInspection */
324 +
325 + $product = wc_get_product(get_the_ID());
326 +
327 + foreach ($product->get_attributes() as $attribute) {
328 + $product_attributes[$attribute->get_name()] = true;
329 + }
330 +
331 + }
332 + }
333 +
334 + }
335 + wp_reset_postdata();
336 + }
337 +
338 + foreach (array_keys($product_attributes) as $attribute_name) {
339 + $options[] = [
340 + 'id' => $attribute_name,
341 + 'text' => wp_strip_all_tags($attribute_name),
342 + ];
343 + }
344 +
345 + return [
346 + 'results' => $options,
347 + ];
348 + }
349 +
350 +}
351 +
352 +new Ajax_Select2_API();