PluginProbe
Orderable – Restaurant & Food Ordering System / 1.14.0
Orderable – Restaurant & Food Ordering System v1.14.0
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 / modules / timings / class-timings-order.php

class-timings-order.php in Orderable – Restaurant & Food Ordering System 1.14.0, at inc/modules/timings/class-timings-order.php

475 lines 14.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Module: Timings order.
4 *
5 * @package Orderable/Classes
6 */
7
8 defined( 'ABSPATH' ) || exit;
9
10 /**
11 * Timings order class.
12 */
13 class Orderable_Timings_Order {
14 /**
15 * Init.
16 */
17 public static function run() {
18 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_assets' ) );
19 add_action( 'admin_footer', array( __CLASS__, 'enqueue_daterange_script' ) );
20 add_filter( 'woocommerce_get_order_item_totals', array( __CLASS__, 'add_to_order_details' ), 10, 3 );
21 add_action( 'woocommerce_admin_order_data_after_billing_address', array( __CLASS__, 'add_to_admin_order' ), 10, 1 );
22 add_filter( 'manage_edit-shop_order_columns', array( __CLASS__, 'add_admin_order_columns' ), 20 );
23 add_filter( 'manage_edit-shop_order_sortable_columns', array( __CLASS__, 'add_admin_order_sortable_columns' ) );
24 add_action( 'manage_shop_order_posts_custom_column', array( __CLASS__, 'add_admin_order_columns_content' ), 10, 2 );
25 add_action( 'pre_get_posts', array( __CLASS__, 'update_query_to_filter_admin_orders' ), 100 );
26 add_filter( 'woocommerce_shop_order_list_table_prepare_items_query_args', array( __CLASS__, 'update_query_args_to_filter_admin_orders' ), 100 );
27 add_action( 'restrict_manage_posts', array( __CLASS__, 'due_date_filter' ), 60 );
28 add_action( 'woocommerce_order_list_table_restrict_manage_orders', array( __CLASS__, 'due_date_filter' ), 60 );
29 add_action( 'woocommerce_admin_order_preview_start', array( __CLASS__, 'modify_order_preview_template' ) );
30 add_filter( 'woocommerce_admin_order_preview_get_order_details', array( __CLASS__, 'modify_order_preview_get_order_details' ), 10, 2 );
31
32 // HPOS Compatibility.
33 add_action( 'admin_init', array( __CLASS__, 'add_due_date_time_custom_column' ) );
34 }
35
36 /**
37 * Enqueue assets.
38 */
39 public static function enqueue_assets() {
40 if ( ! Orderable_Orders::is_orders_page() ) {
41 return;
42 }
43
44 wp_enqueue_script( 'momentjs', ORDERABLE_ASSETS_URL . 'vendor/moment/moment.min.js', array( 'jquery' ), ORDERABLE_VERSION, true );
45 wp_enqueue_script( 'daterangepicker', ORDERABLE_ASSETS_URL . 'vendor/daterangepicker/daterangepicker.js', array( 'jquery', 'momentjs' ), ORDERABLE_VERSION, true );
46 wp_enqueue_style( 'daterangepicker', ORDERABLE_ASSETS_URL . 'vendor/daterangepicker/daterangepicker.css', array(), ORDERABLE_VERSION );
47
48 wp_localize_script(
49 'daterangepicker',
50 'orderable_timings_daterangepicker',
51 array(
52 'today' => esc_html__( 'Today', 'orderable' ),
53 'tomorrow' => esc_html__( 'Tomorrow', 'orderable' ),
54 'next_7_days' => esc_html__( 'Next 7 Days', 'orderable' ),
55 'next_30_days' => esc_html__( 'Next 30 Days', 'orderable' ),
56 'custom_range' => esc_html__( 'Custom Range', 'orderable' ),
57 'clear' => esc_html__( 'Clear', 'orderable' ),
58 'apply' => esc_html__( 'Apply', 'orderable' ),
59 )
60 );
61 }
62
63 /**
64 * Add date range script.
65 */
66 public static function enqueue_daterange_script() {
67 if ( ! Orderable_Orders::is_orders_page() ) {
68 return;
69 }
70 ?>
71 <script>
72 var orderable_date_picker = {
73 /**
74 * On ready.
75 */
76 ready: function() {
77 orderable_date_picker.init();
78 orderable_date_picker.watch();
79 },
80
81 /**
82 * Init datepicker.
83 */
84 init: function() {
85 var ranges = {};
86 ranges[orderable_timings_daterangepicker.today] = [ moment(), moment() ];
87 ranges[orderable_timings_daterangepicker.tomorrow] = [ moment().add( 1, 'days' ), moment().add( 1, 'days' ) ];
88 ranges[orderable_timings_daterangepicker.next_7_days] = [ moment(), moment().add( 6, 'days' ) ];
89 ranges[orderable_timings_daterangepicker.next_30_days] = [ moment(), moment().add( 29, 'days' ) ];
90
91 jQuery( 'input[name="orderable_due_date"]' ).daterangepicker( {
92 opens: 'left',
93 autoUpdateInput: false,
94 alwaysShowCalendars: true,
95 locale: {
96 format: 'YYYY/MM/DD',
97 cancelLabel: orderable_timings_daterangepicker.clear,
98 applyLabel: orderable_timings_daterangepicker.apply,
99 customRangeLabel: orderable_timings_daterangepicker.custom_range,
100 daysOfWeek: [
101 '<?php esc_html_e( 'Su', 'orderable' ); ?>',
102 '<?php esc_html_e( 'Mo', 'orderable' ); ?>',
103 '<?php esc_html_e( 'Tu', 'orderable' ); ?>',
104 '<?php esc_html_e( 'We', 'orderable' ); ?>',
105 '<?php esc_html_e( 'Th', 'orderable' ); ?>',
106 '<?php esc_html_e( 'Fr', 'orderable' ); ?>',
107 '<?php esc_html_e( 'Sa', 'orderable' ); ?>',
108 ],
109 monthNames: [
110 '<?php esc_html_e( 'January', 'orderable' ); ?>',
111 '<?php esc_html_e( 'February', 'orderable' ); ?>',
112 '<?php esc_html_e( 'March', 'orderable' ); ?>',
113 '<?php esc_html_e( 'April', 'orderable' ); ?>',
114 '<?php esc_html_e( 'May', 'orderable' ); ?>',
115 '<?php esc_html_e( 'June', 'orderable' ); ?>',
116 '<?php esc_html_e( 'July', 'orderable' ); ?>',
117 '<?php esc_html_e( 'August', 'orderable' ); ?>',
118 '<?php esc_html_e( 'September', 'orderable' ); ?>',
119 '<?php esc_html_e( 'October', 'orderable' ); ?>',
120 '<?php esc_html_e( 'November', 'orderable' ); ?>',
121 '<?php esc_html_e( 'December', 'orderable' ); ?>'
122 ],
123 },
124 ranges: ranges,
125 } );
126 },
127
128 /**
129 * Watch datepicker events.
130 */
131 watch: function() {
132 jQuery( document.body ).on( 'apply.daterangepicker', 'input[name="orderable_due_date"]', function( ev, picker ) {
133 jQuery( this ).val( picker.startDate.format( 'YYYY/MM/DD' ) + ' - ' + picker.endDate.format( 'YYYY/MM/DD' ) );
134 } );
135
136 jQuery( document.body ).on( 'cancel.daterangepicker', 'input[name="orderable_due_date"]', function( ev, picker ) {
137 jQuery( this ).val( '' );
138 } );
139 }
140 };
141
142 jQuery( document ).ready( orderable_date_picker.ready );
143 jQuery( document ).on( 'orderable-live-view-updated', orderable_date_picker.init );
144 </script>
145 <?php
146 }
147
148 /**
149 * Add date and time to order details.
150 *
151 * @param array $total_rows
152 * @param WC_Order $order
153 * @param bool $tax_display
154 *
155 * @return array
156 */
157 public static function add_to_order_details( $total_rows, $order, $tax_display ) {
158 $data = self::get_order_date_time( $order );
159 $order_total = $total_rows['order_total'];
160
161 unset( $total_rows['order_total'] );
162
163 foreach ( $data as $key => $value ) {
164 if ( 'order_timestamp' === $key || empty( $value['value'] ) ) {
165 continue;
166 }
167
168 $total_rows[ 'orderable_' . $key ] = array(
169 'label' => wptexturize( $value['label'] . ':' ),
170 'value' => wptexturize( $value['value'] ),
171 );
172 }
173
174 $total_rows['order_total'] = $order_total;
175
176 return $total_rows;
177 }
178
179 /**
180 * @param WC_Order $order
181 */
182 public static function add_to_admin_order( $order ) {
183 $data = self::get_order_date_time( $order );
184
185 foreach ( $data as $key => $value ) {
186 if ( 'order_timestamp' === $key || empty( $value['value'] ) ) {
187 continue;
188 }
189
190 echo '<p><strong>' . $value['label'] . ':</strong> <br>' . $value['value'] . '</p>';
191 }
192 }
193
194 /**
195 * Get order date/time.
196 *
197 * @param WC_Order $order
198 *
199 * @return array
200 */
201 public static function get_order_date_time( $order ) {
202 return apply_filters(
203 'orderable_get_order_date_time',
204 array(
205 'order_date' => array(
206 'value' => $order->get_meta( 'orderable_order_date' ),
207 'label' => __( 'Date', 'orderable' ),
208 ),
209 'order_time' => array(
210 'value' => $order->get_meta( 'orderable_order_time' ),
211 'label' => __( 'Time', 'orderable' ),
212 ),
213 'order_timestamp' => array(
214 'value' => $order->get_meta( '_orderable_order_timestamp' ),
215 'label' => __( 'Timestamp', 'orderable' ),
216 ),
217 ),
218 $order
219 );
220 }
221
222 /**
223 * Add columns to admin orders screen.
224 *
225 * @param array $columns
226 *
227 * @return array
228 */
229 public static function add_admin_order_columns( $columns ) {
230 $columns['orderable_order_data'] = __( 'Due Date/Time', 'orderable' );
231
232 return $columns;
233 }
234
235 /**
236 * Add columns content to admin orders screen.
237 *
238 * @param $column_name
239 * @param $post_id
240 */
241 public static function add_admin_order_columns_content( $column_name, $post_id ) {
242 if ( 'orderable_order_data' === $column_name ) {
243 $order = wc_get_order( $post_id );
244 $data = self::get_order_date_time( $order );
245
246 if ( ! empty( $data['order_date']['value'] ) ) {
247 printf( '<p><strong>%s</strong>: %s</p>', __( 'Date', 'orderable' ), $data['order_date']['value'] );
248 }
249
250 if ( ! empty( $data['order_time']['value'] ) ) {
251 printf( '<p><strong>%s</strong>: %s</p>', __( 'Time', 'orderable' ), $data['order_time']['value'] );
252 }
253 }
254 }
255
256 /**
257 * Register columns as sortable.
258 *
259 * @param array $columns
260 *
261 * @return array
262 */
263 public static function add_admin_order_sortable_columns( $columns ) {
264 $columns['orderable_order_data'] = '_orderable_order_timestamp';
265
266 return $columns;
267 }
268
269 /**
270 * Update query object to filter orders by due date.
271 *
272 * @param WP_Query $query The query to retrieve the orders.
273 */
274 public static function update_query_to_filter_admin_orders( $query ) {
275 if ( ! Orderable_Orders::is_orders_page() || 'shop_order' !== $query->get( 'post_type' ) ) {
276 return;
277 }
278
279 $args = array(
280 'orderby' => empty( $_GET['orderby'] ) ? '' : sanitize_text_field( wp_unslash( $_GET['orderby'] ) ), // phpcs:ignore WordPress.Security.NonceVerification
281 'due_date' => array_filter( self::get_filtered_due_date() ),
282 );
283
284 self::update_query( $query, $args );
285 }
286
287 /**
288 * Update query args to filter orders by due date.
289 *
290 * @param array $query_args The query args used to retrieve the orders.
291 * @return array
292 */
293 public static function update_query_args_to_filter_admin_orders( $query_args ) {
294 if ( ! Orderable_Orders::is_orders_page() ) {
295 return $query_args;
296 }
297
298 if ( empty( $_GET['_orderable_filter_orders_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_orderable_filter_orders_nonce'] ) ), 'orderable_filter_orders' ) ) {
299 return $query_args;
300 }
301
302 $meta_query = empty( $query_args['meta_query'] ) || ! is_array( $query_args['meta_query'] ) ? array() : $query_args['meta_query'];
303
304 $order_by = empty( $_GET['orderby'] ) ? '' : sanitize_text_field( wp_unslash( $_GET['orderby'] ) );
305 $due_date = array_filter( self::get_filtered_due_date() );
306
307 if ( ! empty( $order_by ) ) {
308 $meta_query[] = array(
309 'key' => $query_args['orderby'],
310 'compare' => 'EXISTS',
311 );
312 }
313
314 if ( ! empty( $due_date['start_timestamp'] ) && ! empty( $due_date['end_timestamp'] ) ) {
315 $meta_query[] = array(
316 'key' => '_orderable_order_timestamp',
317 'value' => array( $due_date['start_timestamp'], $due_date['end_timestamp'] ),
318 'type' => 'numeric',
319 'compare' => 'BETWEEN',
320 );
321 }
322
323 $query_args['meta_query'] = $meta_query; // phpcs:ignore WordPress.DB.SlowDBQuery
324
325 return $query_args;
326 }
327
328 /**
329 * Update orders query.
330 *
331 * @param WP_Query $query
332 * @param array $args
333 */
334 public static function update_query( $query, $args = array() ) {
335 $defaults = array(
336 'orderby' => '',
337 'due_date' => '',
338 );
339
340 $args = wp_parse_args( $args, $defaults );
341 $meta_query = (array) $query->get( 'meta_query' );
342
343 if ( ! empty( $args['orderby'] ) && '_orderable_order_timestamp' === $args['orderby'] ) {
344 $meta_query[] = array(
345 'key' => $args['orderby'],
346 'compare' => 'EXISTS',
347 );
348 }
349
350 if ( ! empty( $args['due_date'] ) && ! empty( $args['due_date']['start_timestamp'] ) && ! empty( $args['due_date']['end_timestamp'] ) ) {
351 $meta_query[] = array(
352 'key' => '_orderable_order_timestamp',
353 'value' => array( $args['due_date']['start_timestamp'], $args['due_date']['end_timestamp'] ),
354 'type' => 'numeric',
355 'compare' => 'BETWEEN',
356 );
357 }
358
359 $query->set( 'meta_query', $meta_query );
360 }
361
362 /**
363 * Due date filter.
364 */
365 public static function due_date_filter() {
366 if ( ! Orderable_Orders::is_orders_page() ) {
367 return;
368 }
369
370 $due_date = self::get_filtered_due_date();
371 ?>
372 <input type="text" name="orderable_due_date" value="<?php echo esc_attr( $due_date['formatted'] ); ?>" placeholder="<?php esc_attr_e( 'Filter by due date', 'orderable' ); ?>" style="min-width: 195px;" />
373 <?php
374 }
375
376 /**
377 * Get filtered due date.
378 *
379 * @return array
380 */
381 public static function get_filtered_due_date() {
382 $return = array(
383 'start' => '',
384 'start_timestamp' => '',
385 'end' => '',
386 'end_timestamp' => '',
387 'formatted' => '',
388 );
389
390 $due_date = empty( $_GET['orderable_due_date'] ) ? '' : sanitize_text_field( wp_unslash( $_GET['orderable_due_date'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
391
392 if ( ! $due_date ) {
393 return $return;
394 }
395
396 $due_date_exploded = explode( ' - ', $due_date );
397
398 $return['start'] = isset( $due_date_exploded[0] ) ? $due_date_exploded[0] : false;
399 $return['end'] = isset( $due_date_exploded[1] ) ? $due_date_exploded[1] : false;
400 $return['formatted'] = $due_date;
401
402 if ( $return['start'] ) {
403 $start = DateTime::createFromFormat( 'Y/m/d H:i:s', $return['start'] . ' 00:00:00', wp_timezone() );
404
405 $return['start_timestamp'] = $start->getTimestamp();
406 }
407
408 if ( $return['end'] ) {
409 $end = DateTime::createFromFormat( 'Y/m/d H:i:s', $return['end'] . ' 00:00:00', wp_timezone() );
410
411 $return['end_timestamp'] = $end->getTimestamp();
412 }
413
414 if ( isset( $start ) && ( ! $return['end'] || $return['end'] === $return['start'] ) ) {
415 $start->add( new DateInterval( 'P1D' ) );
416
417 $return['end_timestamp'] = $start->getTimestamp();
418 }
419
420 return $return;
421 }
422
423 /**
424 * Modify preview order template.
425 */
426 public static function modify_order_preview_template() {
427 ?>
428 <# if ( data.orderable.order_date.value ) { #>
429 <div class="wc-order-preview-addresses" style="padding: 0;">
430 <div class="wc-order-preview-address">
431 <strong>{{ data.orderable.order_date.label }}</strong>
432 {{ data.orderable.order_date.value }}
433 </div>
434 <# if ( data.orderable.order_time.value ) { #>
435 <div class="wc-order-preview-address">
436 <strong>{{ data.orderable.order_time.label }}</strong>
437 {{ data.orderable.order_time.value }}
438 </div>
439 <# } #>
440 </div>
441 <# } #>
442 <?php
443 }
444
445 /**
446 * Modify preview order details.
447 *
448 * @param array $data
449 * @param WC_Order $order
450 *
451 * @return array
452 */
453 public static function modify_order_preview_get_order_details( $data, $order ) {
454 $data['orderable'] = self::get_order_date_time( $order );
455
456 return $data;
457 }
458
459 /**
460 * Add Due Date/Time custom column.
461 *
462 * Compatible with HPOS.
463 *
464 * @return void
465 */
466 public static function add_due_date_time_custom_column() {
467 $shop_order_page_screen_id = wc_get_page_screen_id( 'shop-order' );
468
469 add_filter( "manage_{$shop_order_page_screen_id}_columns", array( __CLASS__, 'add_admin_order_columns' ), 10 );
470 add_filter( 'woocommerce_shop_order_list_table_sortable_columns', array( __CLASS__, 'add_admin_order_sortable_columns' ) );
471
472 add_action( "manage_{$shop_order_page_screen_id}_custom_column", array( __CLASS__, 'add_admin_order_columns_content' ), 10, 2 );
473 }
474 }
475