PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.0
Booktics – Appointment Booking Calendar for Service Businesses v1.0.0
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.0, at base/query-builders/query-builder.php

334 lines 7.7 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 orWhere( $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 whereIn( $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 * Add a meta query condition for NULL value
118 *
119 * @param string $key
120 *
121 * @return $this
122 */
123 public function whereNull( $key ) {
124 $this->meta_query[] = array(
125 'key' => $key,
126 'compare' => 'NOT EXISTS',
127 );
128
129 return $this;
130 }
131
132 /**
133 * Add a taxonomy query (generic)
134 *
135 * @param string $taxonomy
136 * @param string|array $terms
137 * @param string $field
138 *
139 * @return $this
140 */
141 public function taxonomy( $taxonomy, $terms, $field = 'slug' ) {
142 $this->tax_query[] = array(
143 'taxonomy' => $taxonomy,
144 'field' => $field,
145 'terms' => (array) $terms,
146 );
147
148 return $this;
149 }
150
151 /**
152 * Add a category query
153 *
154 * @param string|int $slugOrId
155 *
156 * @return $this
157 */
158 public function category( $slugOrId ) {
159 return $this->taxonomy( 'category', $slugOrId, is_numeric( $slugOrId ) ? 'term_id' : 'slug' );
160 }
161
162 /**
163 * Add a tag query
164 *
165 * @param string|int $slugOrId
166 *
167 * @return $this
168 */
169 public function tag( $slugOrId ) {
170 return $this->taxonomy( 'post_tag', $slugOrId, is_numeric( $slugOrId ) ? 'term_id' : 'slug' );
171 }
172
173 /**
174 * Set order by custom field
175 *
176 * @param string $field
177 * @param string $direction
178 *
179 * @return $this
180 */
181 public function orderBy( $field, $direction = 'ASC' ) {
182 $this->args['orderby'] = 'meta_value';
183 $this->args['meta_key'] = $field;
184 $this->args['order'] = $direction;
185
186 return $this;
187 }
188
189 /**
190 * Execute query and return all matched model instances
191 *
192 * @return array
193 */
194 public function get() {
195 $this->args['numberposts'] = - 1;
196
197 if ( $meta = $this->build_meta_query() ) {
198 $this->args['meta_query'] = $meta;
199 }
200
201 if ( $this->tax_query ) {
202 $this->args['tax_query'] = count( $this->tax_query ) > 1
203 ? array_merge( array( 'relation' => 'AND' ), $this->tax_query )
204 : $this->tax_query;
205 }
206
207 $posts = get_posts( $this->args );
208
209 return array_map(
210 function ( $post ) {
211 return new $this->model( $post );
212 }, $posts
213 );
214 }
215
216 /**
217 * Paginate the query results
218 *
219 * @param int $per_page
220 * @param int $page
221 *
222 * @return array
223 */
224 public function paginate( $per_page = 10, $page = 1 ) {
225 $this->args['posts_per_page'] = $per_page;
226 $this->args['paged'] = $page;
227
228 if ( $meta = $this->build_meta_query() ) {
229 $this->args['meta_query'] = $meta;
230 }
231
232 if ( $this->tax_query ) {
233 $this->args['tax_query'] = count( $this->tax_query ) > 1
234 ? array_merge( array( 'relation' => 'AND' ), $this->tax_query )
235 : $this->tax_query;
236 }
237
238 $query = new WP_Query( $this->args );
239
240 return array(
241 'items' => array_map(
242 function ( $p ) {
243 return new $this->model( $p );
244 }, $query->posts
245 ),
246 'total' => $query->found_posts,
247 'per_page' => $per_page,
248 'current_page' => $page,
249 'last_page' => ceil( $query->found_posts / $per_page ),
250 );
251 }
252
253 /**
254 * Return first matched model or null
255 *
256 * @return null|PostModel
257 */
258 public function first() {
259 $this->args['numberposts'] = 1;
260
261 if ( $meta = $this->build_meta_query() ) {
262 $this->args['meta_query'] = $meta;
263 }
264
265 if ( $this->tax_query ) {
266 $this->args['tax_query'] = $this->tax_query;
267 }
268
269 $posts = get_posts( $this->args );
270
271 return $posts ? new $this->model( $posts[0] ) : null;
272 }
273
274 /**
275 * Count number of matched posts
276 *
277 * @return int
278 */
279 public function count() {
280 $this->args['posts_per_page'] = 1;
281 $this->args['fields'] = 'ids';
282
283 if ( $meta = $this->build_meta_query() ) {
284 $this->args['meta_query'] = $meta;
285 }
286
287 if ( $this->tax_query ) {
288 $this->args['tax_query'] = $this->tax_query;
289 }
290
291 $query = new WP_Query( $this->args );
292
293 return $query->found_posts;
294 }
295
296 /**
297 * Check if any record exists
298 *
299 * @return bool
300 */
301 public function exists() {
302 return $this->count() > 0;
303 }
304
305 /**
306 * Build meta_query with AND/OR relations
307 *
308 * @return array
309 */
310 protected function build_meta_query() {
311 $meta = array();
312
313 if ( $this->meta_query ) {
314 $meta[] = count( $this->meta_query ) > 0
315 ? array_merge( array( 'relation' => 'AND' ), $this->meta_query )
316 : $this->meta_query[0];
317 }
318
319 if ( $this->meta_query_or ) {
320 $meta[] = count( $this->meta_query_or ) > 0
321 ? array_merge( array( 'relation' => 'OR' ), $this->meta_query_or )
322 : $this->meta_query_or[0];
323 }
324
325 if ( count( $meta ) === 1 ) {
326 return $meta[0];
327 } elseif ( count( $meta ) > 0 ) {
328 return array_merge( array( 'relation' => 'AND' ), $meta );
329 }
330
331 return array();
332 }
333 }
334