PluginProbe
YayMail – WooCommerce Email Customizer / 4.3.3
YayMail – WooCommerce Email Customizer v4.3.3
4.4.4 4.4.3 4.4.2 4.4.1 trunk 1.9.6 2.1.4 2.1.5 3.2.2 3.2.6 3.2.7.1 3.2.8.1 3.2.9 3.3 3.3.1 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4 3.4.1 3.4.2 3.4.3 All 55 releases
yaymail / src / Models / ProductModel.php

ProductModel.php in YayMail – WooCommerce Email Customizer 4.3.3, at src/Models/ProductModel.php

559 lines 23.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace YayMail\Models;
4
5 use YayMail\Utils\SingletonTrait;
6
7 /**
8 * Product Model
9 *
10 * @method static ProductModel get_instance()
11 */
12 class ProductModel {
13
14 use SingletonTrait;
15
16 const DEFAULT_LIMIT = 5;
17
18 const COMMON_WP_QUERY_ARGUMENTS = [
19 'post_type' => 'product',
20 'post_status' => 'publish',
21 ];
22
23 /**
24 * Retrieves a list of terms(categories | tags | products) based on the provided parameters.
25 *
26 * This function fetches a list of terms(categories | tags | products) based on the specified search criteria and pagination options.
27 *
28 * @param array $params An associative array of parameters for the term retrieval.
29 * - 'search_string' (string): The search string to filter terms. Default is an empty string.
30 * - 'page_num' (number): The page number for paginating results. Default is "1".
31 * - 'page_size' (number): The number of terms to retrieve per page. Default is "20".
32 * - 'term_type' (string): The type of terms to retrieve. Could be "product_cat" | "product_tag" | null | ''. (null | '' is for Product).
33 * @param array $field_mapping An associative array of field mapping for the term retrieval.
34 * - 'id' (string): The field name for the term ID. Default is "id".
35 * - 'name' (string): The field name for the term name. Default is "name".
36 *
37 * @return array An associative array containing the retrieved terms.
38 * - 'list' (array): An array of term data, each with 'id' and 'name' fields.
39 * - 'next_page' (number|false): The token for the next page of results, if available.
40 */
41 public function get_terms( $params, $field_mapping = [
42 'id' => 'id',
43 'name' => 'name',
44 ] ) {
45 $page_data = $this->get_terms_page( isset( $params['term_type'] ) ? $params['term_type'] : '', $params['search_string'] ?? '', $params['page_num'] ?? 1, $params['page_size'] ?? 20 );
46
47 $result = [
48 'list' => array_map(
49 function( $item ) use ( $field_mapping ) {
50 $id_field = $field_mapping['id'] ?? 'id';
51 $name_field = $field_mapping['name'] ?? 'name';
52 return [
53 'id' => strval( isset( $item->{$id_field} ) ? $item->{$id_field} : $item->id ),
54 'name' => isset( $item->{$name_field} ) ? $item->{$name_field} : $item->name,
55 ];
56 },
57 $page_data['list']
58 ),
59 'next_page' => $page_data['next_page'],
60 ];
61
62 return $result;
63 }
64
65 /**
66 * Retrieves featured products based on the provided parameters and product type.
67 *
68 * This function allows you to retrieve featured products based on different product types or specific criteria. It delegates the retrieval of products to various specialized methods depending on the product type.
69
70 * @param array $params An associative array of parameters for retrieving featured products.
71 * - 'product_type' (string): The type of featured products to retrieve (e.g., 'newest', 'on_sale', 'featured', 'category_selections', 'tag_selections', 'product_selections'). Default is 'newest'.
72 * - 'number_of_products' (string): The number of featured products to retrieve. Default is "5".
73 * - 'sorted_by' (string): The sorting criteria for the featured products. Default is "none".
74 * - 'category_ids' (null or array): An array of category IDs to filter products by, or null if not used.
75 * - 'tag_ids' (null or array): An array of tag IDs to filter products by, or null if not used.
76 * - 'product_ids' (null or array): An array of product IDs to retrieve, or null if not used.
77 *
78 * @return array An array of featured products with details in the following format:
79 * - 'id' (int): The product's ID.
80 * - 'name' (string): The product's name.
81 * - 'sale_price_html' (string): The HTML representation of the sale price.
82 * - 'regular_price_html' (string): The HTML representation of the regular price.
83 * - 'thumbnail_src' (string): The URL of the product's thumbnail image.
84 * - 'permalink' (string): The URL to the product's page.
85 */
86 public function get_featured_products( $params ) {
87 $product_type = isset( $params['product_type'] ) ? $params['product_type'] : 'newest';
88 unset( $params['product_type'] );
89
90 switch ( $product_type ) {
91 case 'newest':
92 $products = $this->get_newest_products( $params );
93 break;
94 case 'on_sale':
95 $products = $this->get_on_sale_products( $params );
96 break;
97 case 'featured':
98 $products = $this->get_product_type_featured_products( $params );
99 break;
100 case 'category_selections':
101 $products = $this->get_by_categories( $params );
102 break;
103 case 'tag_selections':
104 $products = $this->get_by_tags( $params );
105 break;
106 case 'product_selections':
107 $products = $this->get_by_product_ids( $params );
108 break;
109 default:
110 $products = [];
111 break;
112 }//end switch
113
114 $products_response = array_map( [ $this, 'get_product_response' ], $products );
115
116 $result = [];
117
118 foreach ( $products_response as $product_response ) {
119 if ( ! empty( $product_response ) ) {
120 $result[] = $product_response;
121 }
122 }
123
124 if ( isset( $params['sorted_by'] ) && 'price_ascending' === $params['sorted_by'] ) {
125 usort(
126 $result,
127 function( $a, $b ) {
128 return (float) $a['price'] - (float) $b['price'];
129 }
130 );
131 }
132 if ( isset( $params['sorted_by'] ) && 'price_descending' === $params['sorted_by'] ) {
133 usort(
134 $result,
135 function( $a, $b ) {
136 return (float) $b['price'] - (float) $a['price'];
137 }
138 );
139 }
140 return $result;
141 }
142
143 public function get_cross_up_sells_products( $params ) {
144 $order_id = isset( $params['order_id'] ) ? $params['order_id'] : 0;
145 $linked_products_type = isset( $params['linked_products_type'] ) ? $params['linked_products_type'] : 'cross_sells';
146 $max_products_displayed = isset( $params['max_products_displayed'] ) ? $params['max_products_displayed'] : 0;
147 if ( 0 === $order_id ) {
148 return [];
149 }
150
151 if ( 'sample_order' === $order_id ) {
152 $products = wc_get_products( [ 'limit' => $max_products_displayed ] );
153 $products_response = array_map( [ $this, 'get_product_response' ], $products );
154 return $products_response;
155 }
156
157 $order = wc_get_order( $order_id );
158 $items = $order->get_items();
159 $product_ids = [];
160 $products = [];
161 foreach ( $items as $item ) {
162 if ( 'cross_sells' === $linked_products_type ) {
163 $product_ids = array_merge( $item->get_product()->get_cross_sell_ids(), $product_ids );
164 } else {
165 $product_ids = array_merge( $item->get_product()->get_upsell_ids(), $product_ids );
166 }
167 }
168 $product_ids = array_unique( $product_ids );
169
170 if ( empty( $product_ids ) ) {
171 return [];
172 }
173
174 foreach ( $product_ids as $product_id ) {
175 if ( count( $products ) < $max_products_displayed ) {
176 $products[] = wc_get_product( $product_id );
177 }
178 }
179
180 $products_response = array_map( [ $this, 'get_product_response' ], $products );
181
182 return $products_response;
183 }
184
185 /**
186 * Retrieves the newest products based on the provided criteria.
187 *
188 * This function retrieves the newest products from the WooCommerce store based on the specified criteria, including the number of products to retrieve and the sorting order.
189 *
190 * @param array $criteria An associative array of criteria for retrieving the newest products.
191 * - 'number_of_products' (string): The number of newest products to retrieve. Default is "5".
192 * - 'sorted_by' (string): The sorting criteria for the newest products. Default is "none".
193 * - 'category_ids' (null or array): An array of category IDs to filter products by, or null if not used.
194 * - 'tag_ids' (null or array): An array of tag IDs to filter products by, or null if not used.
195 * - 'product_ids' (null or array): An array of specific product IDs to retrieve, or null if not used.
196 *
197 * @param array $optional_args An associative array of optional arguments for the query.
198 *
199 * @return WC_Product_Simple[]|WC_Product_Variable[] An array of WooCommerce simple and variable product objects representing the newest products.
200 */
201 private function get_newest_products( $criteria, $optional_args = [] ) {
202 $args = [
203 'limit' => isset( $criteria['number_of_products'] ) ? $criteria['number_of_products'] : self::DEFAULT_LIMIT,
204
205 'orderby' => 'date',
206 'order' => 'DESC',
207 'status' => 'publish',
208 'tax_query' => [
209 [
210 'taxonomy' => 'product_type',
211 'field' => 'slug',
212 'terms' => 'grouped',
213 'operator' => 'NOT IN',
214 ],
215 ],
216 ];
217 if ( isset( $criteria['sorted_by'] ) && 'random' === $criteria['sorted_by'] ) {
218 $args['orderby'] = 'rand';
219 }
220
221 if ( ! empty( $optional_args ) ) {
222 $args = wp_parse_args( $args, $optional_args );
223 }
224
225 $query = new \WC_Product_Query( $args );
226 $products = $query->get_products();
227
228 return $products;
229 }
230
231 /**
232 * Retrieves products on sale based on the provided criteria.
233 *
234 * This function retrieves products on sale from the WooCommerce store based on the specified criteria, including the number of products to retrieve and the sorting order.
235 *
236 * @param array $criteria An associative array of criteria for retrieving products on sale.
237 * - 'number_of_products' (string): The number of products on sale to retrieve. Default is "5".
238 * - 'sorted_by' (string): The sorting criteria for products on sale. Default is "none".
239 * - 'category_ids' (null or array): An array of category IDs to filter products by, or null if not used.
240 * - 'tag_ids' (null or array): An array of tag IDs to filter products by, or null if not used.
241 * - 'product_ids' (null or array): An array of specific product IDs to retrieve, or null if not used.
242 * @param array $optional_args An associative array of optional arguments for the query.
243 *
244 * @return WC_Product_Simple[]|WC_Product_Variable[] An array of WooCommerce simple and variable product objects representing products on sale.
245 */
246 private function get_on_sale_products( $criteria, $optional_args = [] ) {
247 $args = [
248 'meta_query' => [
249 'relation' => 'OR',
250 [
251 'key' => '_sale_price',
252 'value' => 0,
253 'compare' => '>',
254 'type' => 'numeric',
255 ],
256 [
257 'key' => '_min_variation_sale_price',
258 'value' => 0,
259 'compare' => '>',
260 'type' => 'numeric',
261 ],
262
263 ],
264 'status' => 'publish',
265 'tax_query' => [
266 [
267 'taxonomy' => 'product_type',
268 'field' => 'slug',
269 'terms' => 'grouped',
270 'operator' => 'NOT IN',
271 ],
272 ],
273 ];
274
275 $args = array_merge(
276 self::COMMON_WP_QUERY_ARGUMENTS,
277 [
278 'posts_per_page' => isset( $criteria['number_of_products'] ) ? $criteria['number_of_products'] : self::DEFAULT_LIMIT,
279 'fields' => 'ids',
280 ],
281 $args
282 );
283
284 if ( isset( $criteria['sorted_by'] ) && 'random' === $criteria['sorted_by'] ) {
285 $args['orderby'] = 'rand';
286 }
287
288 if ( ! empty( $optional_args ) ) {
289 $args = wp_parse_args( $args, $optional_args );
290 }
291
292 $query = new \WP_QUERY( $args );
293 $product_ids = $query->posts;
294
295 $products = wc_get_products( [ 'include' => $product_ids ] );
296 return $products;
297 }
298
299 /**
300 * Retrieves featured products based on the provided criteria.
301 *
302 * This function retrieves products on sale from the WooCommerce store based on the specified criteria, including the number of products to retrieve and the sorting order.
303 *
304 * @param array $criteria An associative array of criteria for retrieving products on sale.
305 * - 'number_of_products' (string): The number of products on sale to retrieve. Default is "5".
306 * - 'sorted_by' (string): The sorting criteria for products on sale. Default is "none".
307 * - 'category_ids' (null or array): An array of category IDs to filter products by, or null if not used.
308 * - 'tag_ids' (null or array): An array of tag IDs to filter products by, or null if not used.
309 * - 'product_ids' (null or array): An array of specific product IDs to retrieve, or null if not used.
310 * @param array $optional_args An associative array of optional arguments for the query.
311 *
312 * @return WC_Product_Simple[]|WC_Product_Variable[] An array of WooCommerce simple and variable product objects representing products on sale.
313 */
314 private function get_product_type_featured_products( $criteria, $optional_args = [] ) {
315 $tax_query[] = [
316 'taxonomy' => 'product_visibility',
317 'field' => 'name',
318 'terms' => 'featured',
319 'operator' => 'IN',
320 ];
321 $tax_query[] = [
322 'taxonomy' => 'product_type',
323 'field' => 'slug',
324 'terms' => 'grouped',
325 'operator' => 'NOT IN',
326 ];
327
328 $args = array_merge(
329 self::COMMON_WP_QUERY_ARGUMENTS,
330 [
331 'posts_per_page' => isset( $criteria['number_of_products'] ) ? $criteria['number_of_products'] : self::DEFAULT_LIMIT,
332 'fields' => 'ids',
333 'status' => 'publish',
334 'tax_query' => $tax_query,
335 ]
336 );
337
338 if ( isset( $criteria['sorted_by'] ) && 'random' === $criteria['sorted_by'] ) {
339 $args['orderby'] = 'rand';
340 }
341
342 if ( ! empty( $optional_args ) ) {
343 $args = wp_parse_args( $args, $optional_args );
344 }
345
346 $query = new \WP_QUERY( $args );
347 if ( $query->have_posts() ) {
348 $product_ids = $query->posts;
349 $products = wc_get_products( [ 'include' => $product_ids ] );
350 return $products;
351 } else {
352 return [];
353 }
354 }
355
356 /**
357 * Retrieves products by category IDs based on the provided criteria.
358 *
359 * This function retrieves products from the WooCommerce store based on specified category IDs and criteria, including the number of products to retrieve and the sorting order.
360 *
361 * @param array $criteria An associative array of criteria for retrieving products by category.
362 * - 'number_of_products' (string): The number of products to retrieve by category. Default is "5".
363 * - 'sorted_by' (string): The sorting criteria for products by category. Default is "none".
364 * - 'category_ids' (array): An array of category IDs to filter products by. If empty, an empty array is returned.
365 * @param array $optional_args An associative array of optional arguments for the query.
366 *
367 * @return WC_Product_Simple[]|WC_Product_Variable[] An array of WooCommerce simple and variable product objects representing products by category.
368 */
369 private function get_by_categories( $criteria, $optional_args = [] ) {
370 if ( empty( $criteria['category_ids'] ) ) {
371 return [];
372 }
373
374 $args = [
375 'limit' => isset( $criteria['number_of_products'] ) ? $criteria['number_of_products'] : self::DEFAULT_LIMIT,
376 'product_category_id' => $criteria['category_ids'],
377 'status' => 'publish',
378 ];
379
380 if ( isset( $criteria['sorted_by'] ) && 'random' === $criteria['sorted_by'] ) {
381 $args['orderby'] = 'rand';
382 }
383
384 if ( ! empty( $optional_args ) ) {
385 $args = wp_parse_args( $args, $optional_args );
386 }
387
388 $query = new \WC_Product_Query( $args );
389 $products = $query->get_products();
390 return $products;
391 }
392
393 /**
394 * Retrieves products by tag IDs based on the provided criteria.
395 *
396 * This function retrieves products from the WooCommerce store based on specified tag IDs and criteria, including the number of products to retrieve and the sorting order.
397 *
398 * @param array $criteria An associative array of criteria for retrieving products by tag.
399 * - 'number_of_products' (string): The number of products to retrieve by tag. Default is "5".
400 * - 'sorted_by' (string): The sorting criteria for products by tag. Default is "none".
401 * - 'tag_ids' (array): An array of category IDs to filter products by. If empty, an empty array is returned.
402 * @param array $optional_args An associative array of optional arguments for the query.
403 *
404 * @return WC_Product_Simple[]|WC_Product_Variable[] An array of WooCommerce simple and variable product objects representing products by category.
405 */
406 private function get_by_tags( $criteria, $optional_args = [] ) {
407 if ( empty( $criteria['tag_ids'] ) ) {
408 return [];
409 }
410
411 $args = [
412 'limit' => isset( $criteria['number_of_products'] ) ? $criteria['number_of_products'] : self::DEFAULT_LIMIT,
413 'product_tag_id' => $criteria['tag_ids'],
414 'status' => 'publish',
415 ];
416
417 if ( isset( $criteria['sorted_by'] ) && 'random' === $criteria['sorted_by'] ) {
418 $args['orderby'] = 'rand';
419 }
420
421 if ( ! empty( $optional_args ) ) {
422 $args = wp_parse_args( $args, $optional_args );
423 }
424
425 $query = new \WC_Product_Query( $args );
426 $products = $query->get_products();
427 return $products;
428 }
429
430 /**
431 * Retrieves products by specific product IDs based on the provided criteria.
432 *
433 * This function retrieves products from the WooCommerce store based on specified product IDs and criteria, including the number of products to retrieve and the sorting order.
434 *
435 * @param array $criteria An associative array of criteria for retrieving products by specific product IDs.
436 * - 'number_of_products' (string): The number of products to retrieve by specific product IDs. Default is "5".
437 * - 'sorted_by' (string): The sorting criteria for products by specific product IDs. Default is "none".
438 * - 'product_ids' (array): An array of specific product IDs to retrieve. If empty, an empty array is returned.
439 * @param array $optional_args An associative array of optional arguments for the query.
440 *
441 * @return WC_Product_Simple[]|WC_Product_Variable[] An array of WooCommerce simple and variable product objects representing products by specific product IDs.
442 */
443 private function get_by_product_ids( $criteria, $optional_args = [] ) {
444 if ( empty( $criteria['product_ids'] ) ) {
445 return [];
446 }
447
448 $args = [
449 'limit' => -1,
450 'include' => $criteria['product_ids'],
451 'status' => 'publish',
452 'tax_query' => [
453 [
454 'taxonomy' => 'product_type',
455 'field' => 'slug',
456 'terms' => 'grouped',
457 'operator' => 'NOT IN',
458 ],
459 ],
460 ];
461
462 if ( isset( $criteria['sorted_by'] ) && 'random' === $criteria['sorted_by'] ) {
463 $args['orderby'] = 'rand';
464 }
465
466 if ( ! empty( $optional_args ) ) {
467 $args = wp_parse_args( $args, $optional_args );
468 }
469
470 $query = new \WC_Product_Query( $args );
471 $products = $query->get_products();
472 return $products;
473 }
474
475 /**
476 * Retrieves a page of terms (categories, tags, or products) based on the provided parameters.
477 *
478 * This function retrieves a page of terms, which can be categories, tags, or products, based on the specified taxonomy, search string, page number, and page size.
479 *
480 * @param string $taxonomy The taxonomy to filter terms (categories or tags) or an empty string for products.
481 * @param string $search_string The search string to filter terms or products by name. Default is an empty string.
482 * @param int $page_num The page number for paginating results. Default is 1.
483 * @param int $page_size The number of terms to retrieve per page. Default is 10.
484 * @param array $optional_args Optional WP_Query arguments to merge with default arguments.
485 *
486 * @return array An associative array containing the retrieved terms or products.
487 * - 'list' (array): An array of term or product data, each with 'id' and 'name' fields.
488 * - 'next_page' (int|false): The page number for the next page of results, or false if no more pages are available.
489 */
490 private function get_terms_page( $taxonomy, $search_string = '', $page_num = 1, $page_size = 10, $optional_args = [] ) {
491
492 // if ( class_exists( 'SitePress' ) ) {
493 // do_action( 'wpml_switch_language', $active_language );
494 // }
495 $limit = $page_size + 1;
496 // +1 in order to check for next_page
497 $offset = ( $page_num - 1 ) * $page_size;
498
499 if ( empty( $taxonomy ) ) {
500 /**
501 * Get products
502 */
503 global $wpdb;
504 $query = $wpdb->prepare(
505 "SELECT id, post_title AS name
506 FROM {$wpdb->prefix}posts
507 WHERE {$wpdb->prefix}posts.post_type = 'product'
508 AND {$wpdb->prefix}posts.post_title LIKE %s
509 ORDER BY post_title ASC
510 LIMIT %d OFFSET %d",
511 "%{$search_string}%",
512 $limit,
513 $offset
514 );
515 $list = $wpdb->get_results( $query );
516
517 } else {
518 /**
519 * Get categories or tags
520 */
521 $orderby = 'name';
522 $show_count = 0;
523 $pad_counts = 0;
524 $hierarchical = 1;
525 $empty = 0;
526
527 $args = [
528 'taxonomy' => $taxonomy,
529 'orderby' => $orderby,
530 'show_count' => $show_count,
531 'pad_counts' => $pad_counts,
532 'hierarchical' => $hierarchical,
533 'hide_empty' => $empty,
534 'number' => $limit,
535 'offset' => $offset,
536 ];
537
538 if ( ! empty( $search_string ) ) {
539 $args['name__like'] = $search_string;
540 }
541
542 $list = array_values( \get_categories( $args ) );
543 }//end if
544
545 $next_page = count( $list ) > $page_size ? $page_num + 1 : false;
546
547 if ( $next_page ) {
548 array_pop( $list );
549 }
550
551 $result = [
552 'list' => $list,
553 'next_page' => $next_page,
554 ];
555
556 return $result;
557 }
558 }
559