PluginProbe
Orderable – Restaurant & Food Ordering System / 1.19.1
Orderable – Restaurant & Food Ordering System v1.19.1
0.1.4 0.1.5 0.2.0 1.0.0 1.1.0 1.1.1 1.10.0 1.10.1 1.11.0 1.12.0 1.12.1 1.12.2 1.13.0 1.14.0 1.15.0 1.16.0 1.17.0 1.17.1 1.18.0 1.19.0 1.19.1 1.19.2 1.2.0 1.20.0 1.20.1 All 44 releases
orderable / inc / class-helpers.php

class-helpers.php in Orderable – Restaurant & Food Ordering System 1.19.1, at inc/class-helpers.php

577 lines 15.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Helper methods.
4 *
5 * @package Orderable/Classes
6 */
7
8 defined( 'ABSPATH' ) || exit;
9
10 /**
11 * Helpers class.
12 */
13 class Orderable_Helpers {
14 /**
15 * Get term ID by slug.
16 *
17 * @param string $slug
18 * @param string $taxonomy
19 *
20 * @return int|bool
21 */
22 public static function get_term_id_by_slug( $slug, $taxonomy = 'product_cat' ) {
23 global $wpdb;
24
25 $results = $wpdb->get_var(
26 $wpdb->prepare(
27 'SELECT DISTINCT t.term_id
28 FROM wp_term_taxonomy AS tt
29 INNER JOIN wp_terms AS t ON tt.term_id = t.term_id
30 WHERE t.slug = %s
31 AND tt.taxonomy = %s',
32 $slug,
33 $taxonomy
34 )
35 );
36
37 return $results ? absint( $results ) : false;
38 }
39
40 /**
41 * Load classes.
42 *
43 * @param array $classes Key = filename / Value = Class name.
44 * @param string $module Module folder name.
45 */
46 public static function load_classes( $classes, $module, $root = ORDERABLE_MODULES_PATH ) {
47 foreach ( $classes as $file_name => $class_name ) {
48 $path = $root . $module . '/class-' . $file_name . '.php';
49
50 if ( ! file_exists( $path ) ) {
51 continue;
52 }
53
54 require_once $path;
55
56 if ( ! method_exists( $class_name, 'run' ) ) {
57 continue;
58 }
59
60 $class_name::run();
61 }
62 }
63
64 /**
65 * Get pro button.
66 *
67 * @param string $campaign
68 * @param string $text
69 * @param bool $lock_icon
70 *
71 * @return string
72 */
73 public static function get_pro_button( $campaign = '', $text = '', $lock_icon = true ) {
74 $text = empty( $text ) ? __( 'Available in Pro', 'orderable' ) : $text;
75 $lock_icon = $lock_icon ? '<span class="dashicons dashicons-lock"></span>' : '';
76 $url = self::get_pro_url( $campaign );
77
78 return sprintf( '<a href="%s" class="orderable-admin-button orderable-admin-button--pro" target="_blank">%s %s</a>', esc_url( $url ), $lock_icon, $text );
79 }
80
81 /**
82 * Get pro URL.
83 *
84 * @param string $campaign Campaign.
85 *
86 * @return string
87 */
88 public static function get_pro_url( $campaign = '', $path = '' ) {
89 $campaign = ! empty( $campaign ) ? sprintf( '&utm_campaign=%s', $campaign ) : '';
90
91 return sprintf( 'https://orderable.com/%s?utm_source=Orderable&utm_medium=Plugin%s', $path, $campaign );
92 }
93
94 /**
95 * Prepare post type labels.
96 *
97 * @param array $labels
98 *
99 * @return array|bool
100 */
101 public static function prepare_post_type_labels( $labels = array() ) {
102 if ( empty( $labels ) ) {
103 return false;
104 }
105
106 return array(
107 'name' => $labels['plural'],
108 'singular_name' => $labels['singular'],
109 'menu_name' => $labels['plural'],
110 'name_admin_bar' => $labels['singular'],
111 'add_new' => __( 'Add New', 'orderable' ),
112 'add_new_item' => sprintf( __( 'Add New %s', 'orderable' ), $labels['singular'] ),
113 'new_item' => sprintf( __( 'New %s', 'orderable' ), $labels['singular'] ),
114 'edit_item' => sprintf( __( 'Edit %s', 'orderable' ), $labels['singular'] ),
115 'view_item' => sprintf( __( 'View %s', 'orderable' ), $labels['singular'] ),
116 'all_items' => $labels['plural'],
117 'search_items' => sprintf( __( 'Search %s', 'orderable' ), $labels['plural'] ),
118 'parent_item_colon' => sprintf( __( 'Parent %s:', 'orderable' ), $labels['plural'] ),
119 'not_found' => sprintf( __( 'No %s found.', 'orderable' ), strtolower( $labels['plural'] ) ),
120 'not_found_in_trash' => sprintf( __( 'No %s found in trash.', 'orderable' ), strtolower( $labels['plural'] ) ),
121 'featured_image' => sprintf( _x( '%s Featured Image', 'Overrides the “Featured Image” phrase for this post type. Added in 4.3', 'orderable' ), $labels['singular'] ),
122 'set_featured_image' => _x( 'Set featured image', 'Overrides the “Set featured image” phrase for this post type. Added in 4.3', 'orderable' ),
123 'remove_featured_image' => _x( 'Remove featured image', 'Overrides the “Remove featured image” phrase for this post type. Added in 4.3', 'orderable' ),
124 'use_featured_image' => _x( 'Use as featured image', 'Overrides the “Use as featured image” phrase for this post type. Added in 4.3', 'orderable' ),
125 'archives' => sprintf( _x( '%s archives', 'The post type archive label used in nav menus. Default “Post Archives”. Added in 4.4', 'orderable' ), $labels['plural'] ),
126 'insert_into_item' => sprintf( _x( 'Insert into %s', 'Overrides the “Insert into post”/”Insert into page” phrase (used when inserting media into a post). Added in 4.4', 'orderable' ), strtolower( $labels['singular'] ) ),
127 'uploaded_to_this_item' => sprintf( _x( 'Uploaded to this %s', 'Overrides the “Uploaded to this post”/”Uploaded to this page” phrase (used when viewing media attached to a post). Added in 4.4', 'orderable' ), strtolower( $labels['singular'] ) ),
128 'filter_items_list' => sprintf( _x( 'Filter %s list', 'Screen reader text for the filter links heading on the post type listing screen. Default “Filter posts list”/”Filter pages list”. Added in 4.4', 'orderable' ), strtolower( $labels['plural'] ) ),
129 'items_list_navigation' => sprintf( _x( '%s list navigation', 'Screen reader text for the pagination heading on the post type listing screen. Default “Posts list navigation”/”Pages list navigation”. Added in 4.4', 'orderable' ), $labels['plural'] ),
130 'items_list' => sprintf( _x( '%s list', 'Screen reader text for the items list heading on the post type listing screen. Default “Posts list”/”Pages list”. Added in 4.4', 'orderable' ), $labels['plural'] ),
131 );
132 }
133
134 /**
135 * Outputs the pro feature modal.
136 */
137 public static function orderable_pro_modal() {
138 require_once self::get_template_path( 'templates/admin/orderable-pro-modal.php' );
139 }
140
141 /**
142 * Custom kses method so we can also modify CSS properties allowed.
143 *
144 * @param string $content
145 * @param string $context
146 *
147 * @return string
148 */
149 public static function kses( $content, $context = '' ) {
150 if ( empty( $content ) ) {
151 return $content;
152 }
153
154 // Modify allowed CSS.
155 add_filter( 'safe_style_css', array( __CLASS__, 'safe_css' ) );
156
157 $content = wp_kses( $content, self::kses_allowed_html( $context ) );
158
159 // Disable CSS modification.
160 remove_filter( 'safe_style_css', array( __CLASS__, 'safe_css' ) );
161
162 return $content;
163 }
164
165 /**
166 * Sanitise output and allow form elements.
167 *
168 * @param string $context
169 *
170 * @return array
171 */
172 public static function kses_allowed_html( $context = '' ) {
173 $allowed_html = wp_kses_allowed_html( 'post' );
174
175 if ( 'form' === $context ) {
176 $allowed_attributes = array(
177 'name' => array(),
178 'class' => array(),
179 'value' => array(),
180 'type' => array(),
181 'selected' => array(),
182 );
183
184 $allowed_html['span'] = $allowed_attributes;
185 $allowed_html['select'] = $allowed_attributes;
186 $allowed_html['option'] = $allowed_attributes;
187 $allowed_html['input'] = $allowed_attributes;
188 }
189
190 return $allowed_html;
191 }
192
193 /**
194 * Modify safe CSS values.
195 *
196 * @param array $safe_css
197 *
198 * @return array
199 */
200 public static function safe_css( $safe_css = array() ) {
201 $safe_css[] = 'display';
202
203 return $safe_css;
204 }
205
206 /**
207 * Delete Orderable transients.
208 */
209 public static function delete_orderable_transients() {
210 global $wpdb;
211
212 $wpdb->query(
213 "
214 DELETE FROM $wpdb->options
215 WHERE option_name LIKE ('%%\_transient\_timeout\_orderable\_%%')
216 OR option_name LIKE ('%%\_transient\_orderable\_%%')
217 "
218 );
219 }
220
221 /**
222 * Has notices?
223 *
224 * @return bool
225 */
226 public static function has_notices() {
227 return ! empty( WC()->session->get( 'wc_notices', array() ) );
228 }
229
230 /**
231 * Is a variable product type?
232 *
233 * @param string $product_type The product type.
234 * @return boolean
235 */
236 public static function is_variable_product( $product_type ) {
237 $variable_types = array(
238 'variable',
239 'variable-subscription',
240 );
241
242 /**
243 * Filter the variable types used by the is_variable_product function.
244 *
245 * @param array $variable_types The variable types.
246 *
247 * @return array New variable types.
248 * @since 1.4.0
249 * @hook orderable_variable_types
250 */
251 $variable_types = apply_filters( 'orderable_variable_types', $variable_types );
252
253 return in_array( $product_type, $variable_types, true );
254 }
255
256 /**
257 * Is a variation product type?
258 *
259 * @param string $product_type The product type.
260 * @return boolean
261 */
262 public static function is_variation_product( $product_type ) {
263 $variation_types = array(
264 'variation',
265 'subscription_variation',
266 );
267
268 /**
269 * Filter the variable types used by the is_variable_product function.
270 *
271 * @param array $variation_types The variable types.
272 *
273 * @return array New variation types.
274 * @since 1.4.0
275 * @hook orderable_variation_types
276 */
277 $variation_types = apply_filters( 'orderable_variation_types', $variation_types );
278
279 return in_array( $product_type, $variation_types, true );
280 }
281
282 /** Add image to media library.
283 *
284 * @param string $url URL.
285 * @param int $associated_with_post Post ID if media is associated to post.
286 * @param string $file_name File name.
287 *
288 * @return bool|int|WP_Error
289 */
290 public static function add_to_media( $url, $associated_with_post = 0, $file_name = '' ) {
291 require_once ABSPATH . 'wp-admin/includes/file.php';
292 require_once ABSPATH . 'wp-admin/includes/media.php';
293 require_once ABSPATH . 'wp-admin/includes/image.php';
294
295 $tmp = download_url( $url );
296 $post_id = $associated_with_post;
297 $file_array = array();
298
299 // Set variables for storage.
300 // fix file filename for query strings.
301 preg_match( '/[^\?]+\.(jpg|jpe|jpeg|gif|png|apk)/i', $url, $matches );
302
303 if ( empty( $matches ) ) {
304 return false;
305 }
306
307 $file_array['name'] = ! empty( $file_name ) ? $file_name : basename( $matches[0] );
308 $file_array['tmp_name'] = $tmp;
309
310 // If error storing temporarily, unlink.
311 if ( is_wp_error( $tmp ) ) {
312 @unlink( $file_array['tmp_name'] );
313
314 return false;
315 }
316
317 // do the validation and storage stuff.
318 $id = media_handle_sideload( $file_array, $post_id );
319
320 // If error storing permanently, unlink.
321 if ( is_wp_error( $id ) ) {
322 @unlink( $file_array['tmp_name'] );
323
324 return false;
325 }
326
327 return $id;
328 }
329
330 /**
331 * Check for the template in theme if exits then returns the file path
332 * in theme, else returns the path in plugin.
333 *
334 * This function simplifies the path in the theme to orderable/{module-slug}/template.php.
335 * For example if the path of file in plugin is
336 * /inc/modules/drawer/templates/floating-cart.php then the path in the theme
337 * would be orderable/drawer/floating-cart.php.
338 *
339 * @param string $file File to load.
340 * @param string $module Module slug example 'addons-pro'. Default: false.
341 * @param bool $pro Whether to find the template in pro plugin. Default: false.
342 *
343 * @return string
344 */
345 public static function get_template_path( $file, $module = false, $pro = false ) {
346 // Look for the file in theme.
347 // Remove 'templates/' if it exists in the start.
348 if ( 'templates/' === substr( $file, 0, 10 ) ) {
349 $file = substr( $file, 10 );
350 }
351
352 $theme_path = 'orderable/' . $file;
353
354 if ( $module ) {
355 $theme_path = sprintf( 'orderable/%s/%s', $module, $file );
356 }
357
358 // If template found in the theme, then return the theme path.
359 $theme_template = locate_template( $theme_path );
360 if ( $theme_template ) {
361 return $theme_template;
362 }
363
364 // Else look in the plugin.
365
366 if ( $pro && ! defined( 'ORDERABLE_PRO_PATH' ) ) {
367 return false;
368 }
369
370 $orderable_path = $pro ? ORDERABLE_PRO_PATH : ORDERABLE_PATH;
371
372 if ( $module ) {
373 return sprintf( '%sinc/modules/%s/templates/%s', $orderable_path, $module, $file );
374 } else {
375 return $orderable_path . 'templates/' . $file;
376 }
377 }
378
379 /**
380 * Get the allowed HTML tags to SVG.
381 *
382 * This function is usefull when we need to escape
383 * SVG elements using wp_kses().
384 *
385 * @return array
386 */
387 public static function get_svg_allowed_html_tags() {
388 $allowed_html_tags['svg'] = array(
389 'xmlns' => array(),
390 'fill' => array(),
391 'height' => array(),
392 'width' => array(),
393 'viewbox' => array(),
394 );
395
396 $allowed_html_tags['g'] = array();
397
398 $allowed_html_tags['circle'] = array(
399 'cx' => array(),
400 'cy' => array(),
401 'r' => array(),
402 );
403
404 $allowed_html_tags['rect'] = array(
405 'x' => array(),
406 'y' => array(),
407 'rx' => array(),
408 'height' => array(),
409 'width' => array(),
410 'transform' => array(),
411 'fill' => array(),
412 );
413
414 $allowed_html_tags['path'] = array(
415 'd' => array(),
416 'fill' => array(),
417 'fill-rule' => array(),
418 'clip-rule' => array(),
419 );
420
421 /**
422 * Filter the allowed SVG tags.
423 *
424 * @since 1.18.0
425 * @hook orderable_allowed_svg_tags
426 * @param array $allowed_html_tags The SVG allowed tags.
427 * @return array New value
428 */
429 $allowed_html_tags = apply_filters( 'orderable_allowed_svg_tags', $allowed_html_tags );
430
431 return $allowed_html_tags;
432 }
433
434 /**
435 * Check if a product is in the cart and return the cart item
436 * if true. Otherwise, it returns false.
437 *
438 * @param int $product_id The product ID.
439 * @return array|false
440 */
441 public static function is_product_in_the_cart( $product_id ) {
442 $cart_item = false;
443
444 if ( is_admin() || empty( WC()->cart ) ) {
445 return $cart_item;
446 }
447
448 foreach ( WC()->cart->get_cart() as $cart_item_data ) {
449 if ( $product_id !== $cart_item_data['product_id'] ) {
450 continue;
451 }
452
453 $cart_item = $cart_item_data;
454 break;
455 }
456
457 return $cart_item;
458 }
459
460 /**
461 * Get product quantity in the cart.
462 *
463 * If the product type is variation, it returns
464 * the quantity based on the variable product (parent).
465 *
466 * @param in $product_id The product ID.
467 * @return int
468 */
469 public static function get_product_quantity_in_the_cart( $product_id ) {
470 $quantity = 0;
471
472 if ( is_admin() && ! wp_doing_ajax() ) {
473 return $quantity;
474 }
475
476 if ( empty( WC()->cart ) ) {
477 return $quantity;
478 }
479
480 foreach ( WC()->cart->get_cart() as $cart_item ) {
481 if ( $product_id !== $cart_item['product_id'] ) {
482 continue;
483 }
484
485 $quantity += absint( $cart_item['quantity'] );
486 }
487
488 return $quantity;
489 }
490
491 /**
492 * Get product image 2x size.
493 *
494 * @param WC_Product $product The product.
495 * @param string $size_name The size name to compare with.
496 * @return array|false
497 */
498 public static function get_product_image_2x( WC_Product $product, string $size_name ) {
499 if ( ! $product->get_image_id() ) {
500 return false;
501 }
502
503 $sizes = wp_list_sort(
504 array_filter(
505 wp_get_registered_image_subsizes(),
506 function( $image_size ) {
507 if ( empty( $image_size['height'] ) || empty( $image_size['width'] ) ) {
508 return false;
509 }
510
511 if ( ! is_numeric( $image_size['height'] ) || ! is_numeric( $image_size['width'] ) ) {
512 return false;
513 }
514
515 return true;
516 }
517 ),
518 [ 'width', 'height' ],
519 'ASC',
520 true
521 );
522
523 if ( empty( $sizes[ $size_name ]['width'] ) || empty( $sizes[ $size_name ]['height'] ) ) {
524 return false;
525 }
526
527 if ( ! is_numeric( $sizes[ $size_name ]['width'] ) || ! is_numeric( $sizes[ $size_name ]['height'] ) ) {
528 return false;
529 }
530
531 $width_2x = 2 * $sizes[ $size_name ]['width'];
532 $height_2x = 2 * $sizes[ $size_name ]['height'];
533
534 foreach ( $sizes as $size_name => $size ) {
535 if ( $size['width'] < $width_2x || $size['height'] < $height_2x ) {
536 continue;
537 }
538
539 $image = wp_get_attachment_image_src( $product->get_image_id(), $size_name );
540
541 if ( ! $image ) {
542 continue;
543 }
544 }
545
546 if ( empty( $image ) ) {
547 return false;
548 }
549
550 $image = [
551 'src' => $image[0],
552 'width' => $image[1],
553 'height' => $image[2],
554 'is_resized' => $image[3],
555 ];
556
557 return $image;
558 }
559
560 /**
561 * Check the WooCommerce version
562 *
563 * @param string $version_to_compare The version to compare.
564 * @param string $operator The operator to compare. The same operators used by `version_compare`.
565 * @return bool
566 */
567 public static function woocommerce_version_compare( $version_to_compare, $operator ) {
568 $woocommerce_version = WC()->version ?? false;
569
570 if ( ! $woocommerce_version ) {
571 return false;
572 }
573
574 return version_compare( $woocommerce_version, $version_to_compare, $operator );
575 }
576 }
577