PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.1
Booktics – Appointment Booking Calendar for Service Businesses v1.0.1
1.0.29 1.0.28 1.0.27 1.0.26 1.0.25 1.0.24 1.0.23 1.0.22 1.0.21 1.0.20 1.0.19 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.2 1.0.3 All 31 releases
booktics / base / query-builders / query-builder.php

query-builder.php in Booktics – Appointment Booking Calendar for Service Businesses 1.0.1, at base/query-builders/query-builder.php

347 lines 8.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Query_Bulder Class
4 *
5 * @package Booktics/Query_Builders
6 */
7
8 namespace Booktics\Query_Builders;
9
10 use Booktics\Abstracts\Post_Model;
11 use WP_Query;
12
13 class Query_Builder {
14 /**
15 * Store post model object
16 *
17 * @var object
18 */
19 protected object $model;
20
21 /**
22 * Store meta query
23 *
24 * @var array<int,array<string,mixed>>
25 */
26 protected array $meta_query = array();
27
28 /**
29 * Store or meta query data
30 *
31 * @var array<int,array<string,mixed>>
32 */
33 protected array $meta_query_or = array();
34
35 /**
36 * Store tax query
37 *
38 * @var array<int,array<string,mixed>>
39 */
40 protected array $tax_query = array();
41
42 /**
43 * Store all args
44 *
45 * @var array<string,mixed>
46 */
47 protected array $args = array();
48
49 /**
50 * Constructor
51 *
52 * @param Object $model The model class name
53 */
54 public function __construct( $model ) {
55 $this->model = $model;
56 $this->args['post_type'] = $model->get_post_type();
57 $this->args['post_status'] = Post_Model::$accepted_statuses;
58 }
59
60 /**
61 * Add a meta query condition (AND)
62 *
63 * @param string|array $key Meta key or array of conditions
64 * @param string $compare Comparison operator
65 * @param mixed $value Meta value
66 *
67 * @return $this
68 */
69 public function where( $key, $value = null, $compare = '=' ) {
70 if ( is_array( $key ) ) {
71 foreach ( $key as $condition ) {
72 $this->where( ...$condition );
73 }
74
75 return $this;
76 }
77
78 $this->meta_query[] = compact( 'key', 'value', 'compare' );
79
80 return $this;
81 }
82
83 /**
84 * Add an OR meta query condition
85 *
86 * @param string $key
87 * @param string $compare
88 * @param mixed $value
89 *
90 * @return $this
91 */
92 public function or_where( $key, $value = null, $compare = '=' ) {
93 $this->meta_query_or[] = compact( 'key', 'value', 'compare' );
94
95 return $this;
96 }
97
98 /**
99 * Add a WHERE IN meta query condition
100 *
101 * @param string $key
102 * @param array $values
103 *
104 * @return $this
105 */
106 public function where_in( $key, array $values ) {
107 $this->meta_query[] = array(
108 'key' => $key,
109 'value' => $values,
110 'compare' => 'IN',
111 );
112
113 return $this;
114 }
115
116 /**
117 * Exclude posts by ID from query results
118 *
119 * @param int|array $ids Post ID or array of post IDs to exclude
120 *
121 * @return $this
122 */
123 public function where_not_ids( $ids ) {
124 $this->args['post__not_in'] = (array) $ids;
125
126 return $this;
127 }
128
129 /**
130 * Add a meta query condition for NULL value
131 *
132 * @param string $key
133 *
134 * @return $this
135 */
136 public function where_null( $key ) {
137 $this->meta_query[] = array(
138 'key' => $key,
139 'compare' => 'NOT EXISTS',
140 );
141
142 return $this;
143 }
144
145 /**
146 * Add a taxonomy query (generic)
147 *
148 * @param string $taxonomy
149 * @param string|array $terms
150 * @param string $field
151 *
152 * @return $this
153 */
154 public function taxonomy( $taxonomy, $terms, $field = 'slug' ) {
155 $this->tax_query[] = array(
156 'taxonomy' => $taxonomy,
157 'field' => $field,
158 'terms' => (array) $terms,
159 );
160
161 return $this;
162 }
163
164 /**
165 * Add a category query
166 *
167 * @param string|int $slugOrId
168 *
169 * @return $this
170 */
171 public function category( $slugOrId ) {
172 return $this->taxonomy( 'category', $slugOrId, is_numeric( $slugOrId ) ? 'term_id' : 'slug' );
173 }
174
175 /**
176 * Add a tag query
177 *
178 * @param string|int $slugOrId
179 *
180 * @return $this
181 */
182 public function tag( $slugOrId ) {
183 return $this->taxonomy( 'post_tag', $slugOrId, is_numeric( $slugOrId ) ? 'term_id' : 'slug' );
184 }
185
186 /**
187 * Set order by custom field
188 *
189 * @param string $field
190 * @param string $direction
191 *
192 * @return $this
193 */
194 public function orderBy( $field, $direction = 'ASC' ) {
195 $this->args['orderby'] = 'meta_value';
196 $this->args['meta_key'] = $field;
197 $this->args['order'] = $direction;
198
199 return $this;
200 }
201
202 /**
203 * Execute query and return all matched model instances
204 *
205 * @return array
206 */
207 public function get() {
208 $this->args['numberposts'] = - 1;
209
210 if ( $meta = $this->build_meta_query() ) {
211 $this->args['meta_query'] = $meta;
212 }
213
214 if ( $this->tax_query ) {
215 $this->args['tax_query'] = count( $this->tax_query ) > 1
216 ? array_merge( array( 'relation' => 'AND' ), $this->tax_query )
217 : $this->tax_query;
218 }
219
220 $posts = get_posts( $this->args );
221
222 return array_map(
223 function ( $post ) {
224 return new $this->model( $post );
225 }, $posts
226 );
227 }
228
229 /**
230 * Paginate the query results
231 *
232 * @param int $per_page
233 * @param int $page
234 *
235 * @return array
236 */
237 public function paginate( $per_page = 10, $page = 1 ) {
238 $this->args['posts_per_page'] = $per_page;
239 $this->args['paged'] = $page;
240
241 if ( $meta = $this->build_meta_query() ) {
242 $this->args['meta_query'] = $meta;
243 }
244
245 if ( $this->tax_query ) {
246 $this->args['tax_query'] = count( $this->tax_query ) > 1
247 ? array_merge( array( 'relation' => 'AND' ), $this->tax_query )
248 : $this->tax_query;
249 }
250
251 $query = new WP_Query( $this->args );
252
253 return array(
254 'items' => array_map(
255 function ( $p ) {
256 return new $this->model( $p );
257 }, $query->posts
258 ),
259 'total' => $query->found_posts,
260 'per_page' => $per_page,
261 'current_page' => $page,
262 'last_page' => ceil( $query->found_posts / $per_page ),
263 );
264 }
265
266 /**
267 * Return first matched model or null
268 *
269 * @return null|PostModel
270 */
271 public function first() {
272 $this->args['numberposts'] = 1;
273
274 if ( $meta = $this->build_meta_query() ) {
275 $this->args['meta_query'] = $meta;
276 }
277
278 if ( $this->tax_query ) {
279 $this->args['tax_query'] = $this->tax_query;
280 }
281
282 $posts = get_posts( $this->args );
283
284 return $posts ? new $this->model( $posts[0] ) : null;
285 }
286
287 /**
288 * Count number of matched posts
289 *
290 * @return int
291 */
292 public function count() {
293 $this->args['posts_per_page'] = 1;
294 $this->args['fields'] = 'ids';
295
296 if ( $meta = $this->build_meta_query() ) {
297 $this->args['meta_query'] = $meta;
298 }
299
300 if ( $this->tax_query ) {
301 $this->args['tax_query'] = $this->tax_query;
302 }
303
304 $query = new WP_Query( $this->args );
305
306 return $query->found_posts;
307 }
308
309 /**
310 * Check if any record exists
311 *
312 * @return bool
313 */
314 public function exists() {
315 return $this->count() > 0;
316 }
317
318 /**
319 * Build meta_query with AND/OR relations
320 *
321 * @return array
322 */
323 protected function build_meta_query() {
324 $meta = array();
325
326 if ( $this->meta_query ) {
327 $meta[] = count( $this->meta_query ) > 0
328 ? array_merge( array( 'relation' => 'AND' ), $this->meta_query )
329 : $this->meta_query[0];
330 }
331
332 if ( $this->meta_query_or ) {
333 $meta[] = count( $this->meta_query_or ) > 0
334 ? array_merge( array( 'relation' => 'OR' ), $this->meta_query_or )
335 : $this->meta_query_or[0];
336 }
337
338 if ( count( $meta ) === 1 ) {
339 return $meta[0];
340 } elseif ( count( $meta ) > 0 ) {
341 return array_merge( array( 'relation' => 'AND' ), $meta );
342 }
343
344 return array();
345 }
346 }
347