PluginProbe
Boxzilla – WordPress Popup Builder / 3.4.11
Boxzilla – WordPress Popup Builder v3.4.11
3.4.11 3.4.10 3.4.9 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 trunk 3.0 3.0.1 3.0.2 3.0.3 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 All 72 releases
← All changes | src/admin/class-autocomplete.php +135 -64 3.03.4.11 View file →
@@ -1,80 +1,151 @@
1 1 <?php
2 2
3 3 namespace Boxzilla\Filter;
4 4
5 -class Autocomplete {
5 +if (! defined('ABSPATH')) {
6 + exit;
7 +}
6 8
7 - public function add_hooks() {
8 - add_action( 'wp_ajax_boxzilla_autocomplete', array( $this, 'ajax' ) );
9 - }
9 +class Autocomplete
10 +{
11 + private const MAX_RESULTS = 20;
10 12
11 - /**
12 - * AJAX listener for autocomplete
13 - */
14 - public function ajax() {
15 - $q = ( isset( $_GET['q'] ) ) ? sanitize_text_field( $_GET['q'] ) : '';
16 - $type = ( isset( $_GET['type'] ) && in_array( $_GET['type'], array( 'page', 'post', 'category', 'post_type' ) ) ) ? $_GET['type'] : 'post';
13 + public function init(): void
14 + {
15 + add_action('wp_ajax_boxzilla_autocomplete', [ $this, 'ajax' ], 10, 0);
16 + }
17 17
18 - // do nothing if supplied 'q' parameter is omitted or empty
19 - // or less than 2 characters long
20 - if( empty( $q ) || strlen( $q ) < 2 ) {
21 - die();
22 - }
18 + /**
19 + * AJAX listener for autocomplete
20 + */
21 + public function ajax(): void
22 + {
23 + if (! current_user_can('edit_box')) {
24 + wp_die('', '', [ 'response' => 403 ]);
25 + }
23 26
24 - switch( $type ) {
27 + $q = isset($_GET['q']) ? sanitize_text_field(wp_unslash($_GET['q'])) : '';
28 + $allowed_types = [ 'page', 'post', 'category', 'post_type', 'post_tag' ];
29 + $type = isset($_GET['type']) ? sanitize_key(wp_unslash($_GET['type'])) : '';
30 + if (! in_array($type, $allowed_types, true)) {
31 + $type = 'post';
32 + }
25 33
26 - default:
27 - case 'post':
28 - case 'page':
29 - echo $this->list_posts( $q, $type );
30 - break;
34 + // do nothing if supplied 'q' parameter is omitted or empty
35 + // or less than 2 characters long
36 + if (empty($q) || strlen($q) < 2) {
37 + wp_die();
38 + }
31 39
32 - case 'category':
33 - echo $this->list_categories( $q );
34 - break;
40 + switch ($type) {
41 + default:
42 + case 'post':
43 + case 'page':
44 + echo esc_html($this->list_posts($q, $type));
45 + break;
35 46
36 - case 'post_type':
37 - echo $this->list_post_types( $q );
38 - break;
39 - }
47 + case 'category':
48 + echo esc_html($this->list_categories($q));
49 + break;
40 50
41 - die();
42 - }
51 + case 'post_type':
52 + echo esc_html($this->list_post_types($q));
53 + break;
43 54
44 - /**
45 - * @param string $query
46 - * @param string $post_type
47 - *
48 - * @return string
49 - */
50 - protected function list_posts( $query, $post_type = 'post' ) {
51 - global $wpdb;
52 - $sql = $wpdb->prepare( "SELECT p.post_name FROM $wpdb->posts p WHERE p.post_type = '%s' AND p.post_status = 'publish' AND ( p.post_title LIKE '%s' OR p.post_name LIKE '%s' ) GROUP BY p.post_name", $post_type, $query . '%%', $query . '%%' );
53 - $post_slugs = $wpdb->get_col( $sql );
54 - return join( $post_slugs, PHP_EOL );
55 - }
55 + case 'post_tag':
56 + echo esc_html($this->list_tags($q));
57 + break;
58 + }
56 59
57 - /**
58 - * @param string $query
59 - *
60 - * @return string
61 - */
62 - protected function list_categories( $query ) {
63 - $categories = get_terms( 'category', array( 'name__like' => $query, 'fields' => 'names', 'hide_empty' => false ) );
64 - return join( $categories, PHP_EOL );
65 - }
60 + wp_die();
61 + }
66 62
67 - /**
68 - * @param string $query
69 - *
70 - * @return string
71 - */
72 - protected function list_post_types( $query ) {
73 - $post_types = get_post_types( array( 'public' => true ), 'names' );
74 - $matched_post_types = array_filter( $post_types, function( $name ) use( $query ) {
75 - return strpos( $name, $query ) === 0;
76 - });
63 + /**
64 + * @param string $query
65 + * @param string $post_type
66 + *
67 + * @return string
68 + */
69 + protected function list_posts($query, $post_type = 'post')
70 + {
71 + global $wpdb;
72 + $like = $wpdb->esc_like($query) . '%';
73 + $limit = self::MAX_RESULTS;
77 74
78 - return join( $matched_post_types, PHP_EOL );
79 - }
80 -}
75 + $post_slugs = $wpdb->get_col(
76 + $wpdb->prepare(
77 + "SELECT p.post_name FROM $wpdb->posts p WHERE p.post_type = %s AND p.post_status = 'publish' AND ( p.post_title LIKE %s OR p.post_name LIKE %s ) GROUP BY p.post_name ORDER BY p.post_name ASC LIMIT %d",
78 + $post_type,
79 + $like,
80 + $like,
81 + $limit
82 + )
83 + );
84 + return join(PHP_EOL, $post_slugs);
85 + }
86 +
87 + /**
88 + * @param string $query
89 + *
90 + * @return string
91 + */
92 + protected function list_categories($query)
93 + {
94 + $terms = get_terms([
95 + 'taxonomy' => 'category',
96 + 'name__like' => $query,
97 + 'number' => self::MAX_RESULTS,
98 + 'fields' => 'names',
99 + 'hide_empty' => false,
100 + ]);
101 +
102 + if (is_wp_error($terms)) {
103 + return '';
104 + }
105 +
106 + return join(PHP_EOL, $terms);
107 + }
108 +
109 + /**
110 + * @param string $query
111 + *
112 + * @return string
113 + */
114 + protected function list_tags($query)
115 + {
116 + $terms = get_terms([
117 + 'taxonomy' => 'post_tag',
118 + 'name__like' => $query,
119 + 'number' => self::MAX_RESULTS,
120 + 'fields' => 'names',
121 + 'hide_empty' => false,
122 + ]);
123 +
124 + if (is_wp_error($terms)) {
125 + return '';
126 + }
127 +
128 + return join(PHP_EOL, $terms);
129 + }
130 +
131 +
132 + /**
133 + * @param string $query
134 + *
135 + * @return string
136 + */
137 + protected function list_post_types($query)
138 + {
139 + $post_types = get_post_types([ 'public' => true ], 'names');
140 + $matched_post_types = array_filter(
141 + $post_types,
142 + function ($name) use ($query) {
143 + return strpos($name, $query) === 0;
144 + }
145 + );
146 +
147 + $matched_post_types = array_slice($matched_post_types, 0, self::MAX_RESULTS);
148 +
149 + return join(PHP_EOL, $matched_post_types);
150 + }
151 +}