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 / location / admin / class-location-admin.php

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

493 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Module: Location.
4 *
5 * @package Orderable/Classes
6 */
7
8 defined( 'ABSPATH' ) || exit;
9
10 /**
11 * Addons module class.
12 */
13 class Orderable_Location_Admin {
14 /**
15 * Init.
16 */
17 public static function run() {
18 add_action( 'init', array( __CLASS__, 'load_classes' ) );
19 add_action( 'current_screen', array( __CLASS__, 'save_data' ) );
20 add_action( 'admin_menu', array( __CLASS__, 'add_settings_page' ) );
21 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'load_styles' ) );
22 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'load_scripts' ) );
23 add_filter( 'orderable_onboard_settings_saved', array( __CLASS__, 'onboard_settings_saved' ) );
24
25 add_filter( 'orderable_valid_admin_pages', array( __CLASS__, 'add_valid_admin_pages' ) );
26 }
27
28 /**
29 * Load classes.
30 *
31 * @return void
32 */
33 public static function load_classes() {
34 $meta_boxes = array(
35 'location-store-address-meta-box' => 'Orderable_Location_Store_Address_Meta_Box',
36 'location-open-hours-meta-box' => 'Orderable_Location_Open_Hours_Meta_Box',
37 'location-store-services-meta-box' => 'Orderable_Location_Store_Services_Meta_Box',
38 'location-order-options-meta-box' => 'Orderable_Location_Order_Options_Meta_Box',
39 'location-holidays-meta-box' => 'Orderable_Location_Holidays_Meta_Box',
40 );
41
42 Orderable_Helpers::load_classes(
43 $meta_boxes,
44 'location/admin/meta-boxes',
45 ORDERABLE_MODULES_PATH
46 );
47 }
48
49 /**
50 * Check if we should load the assets.
51 *
52 * @param string $asset_type The type of asset:`styles` or `scripts`.
53 * @return boolean
54 */
55 protected static function should_load_assets( $asset_type ) {
56 if ( ! function_exists( 'get_current_screen' ) ) {
57 return false;
58 }
59
60 $current_screen = get_current_screen();
61
62 if ( empty( $current_screen->id ) ) {
63 return false;
64 }
65
66 /**
67 * Filter the pages allowed to load the location assets.
68 *
69 * @since 1.18.0
70 * @hook orderable_location_allowed_pages_to_load_assets
71 * @param array $allowed_pages The allowed pages.
72 * @param string $asset_type The type of asset:`styles` or `scripts`.
73 * @param string $current_screen_id The ID of screen.
74 * @return array New value
75 */
76 $allowed_pages = apply_filters(
77 'orderable_location_allowed_pages_to_load_assets',
78 array(
79 'orderable_page_orderable-location',
80 'orderable_page_orderable-delivery-zones',
81 'edit-orderable_locations',
82 'woocommerce_page_wc-settings',
83 ),
84 $asset_type,
85 $current_screen->id
86 );
87
88 return is_array( $allowed_pages ) && in_array( $current_screen->id, $allowed_pages, true );
89 }
90
91 /**
92 * Enqueue admin styles.
93 *
94 * @return void
95 */
96 public static function load_styles() {
97 if ( ! self::should_load_assets( 'styles' ) ) {
98 return;
99 }
100
101 $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
102
103 wp_register_style(
104 'jquery-ui-css',
105 ORDERABLE_URL . 'inc/vendor/wp-settings-framework/assets/vendor/jquery-ui/jquery-ui.css',
106 array(),
107 ORDERABLE_VERSION
108 );
109
110 wp_enqueue_style(
111 'orderable-location-css',
112 ORDERABLE_URL . 'inc/modules/location/assets/admin/css/location' . $suffix . '.css',
113 array( 'woocommerce_admin_styles', 'jquery-ui-css' ),
114 ORDERABLE_VERSION
115 );
116 }
117
118 /**
119 * Enqueue admin scripts.
120 *
121 * @return void
122 */
123 public static function load_scripts() {
124 if ( ! self::should_load_assets( 'scripts' ) ) {
125 return;
126 }
127
128 $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
129
130 wp_enqueue_script(
131 'orderable-location-js',
132 ORDERABLE_URL . 'inc/modules/location/assets/admin/js/main' . $suffix . '.js',
133 array( 'wc-enhanced-select', 'jquery-ui-datepicker' ),
134 ORDERABLE_VERSION,
135 true
136 );
137
138 wp_localize_script(
139 'orderable-location-js',
140 'orderable_dz_js_vars',
141 array(
142 'ajax_url' => admin_url( 'admin-ajax.php' ),
143 'nonce' => wp_create_nonce( 'orderable-dz-nonce' ),
144 'action' => 'orderable_dz_crud',
145 'text' => array(
146 'modal_add' => esc_html__( 'Add Delivery Zone', 'orderable-pro' ),
147 'modal_update' => esc_html__( 'Update Delivery Zone', 'orderable-pro' ),
148 'zone_title' => esc_html__( 'Delivery Zone', 'orderable-pro' ),
149 'zone_edit' => esc_html__( 'Edit', 'orderable-pro' ),
150 'zone_remove' => esc_html__( 'Remove', 'orderable-pro' ),
151 'zone_confirm_remove' => esc_html__( 'Are you sure you want to remove this zone?', 'orderable-pro' ),
152 'zone_confirm_delete' => esc_html__( 'Are you sure you want to delete this zone?', 'orderable-pro' ),
153 'successfully_added' => esc_html__( 'successfully added!', 'orderable-pro' ),
154 'successfully_updated' => esc_html__( 'successfully updated!', 'orderable-pro' ),
155 'successfully_removed' => esc_html__( 'successfully removed!', 'orderable-pro' ),
156 ),
157 )
158 );
159 }
160
161 /**
162 * Add valid admin page.
163 *
164 * @param array $pages The admin pages slug.
165 */
166 public static function add_valid_admin_pages( $pages = array() ) {
167 $pages[] = 'orderable-location';
168
169 return $pages;
170 }
171
172 /**
173 * Add settings page.
174 */
175 public static function add_settings_page() {
176 add_submenu_page(
177 'orderable',
178 __( 'Location', 'orderable' ),
179 __( 'Location', 'orderable' ),
180 'manage_options',
181 'orderable-location',
182 array( __CLASS__, 'page_content' ),
183 3
184 );
185 }
186
187 /**
188 * Page content.
189 */
190 public static function page_content() {
191 if ( ! current_user_can( 'manage_options' ) ) {
192 wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'orderable' ) );
193 }
194 ?>
195 <div class="wrap">
196 <h1 class="wp-heading-inline">
197 <?php echo esc_html__( 'Location', 'orderable' ); ?>
198 </h1>
199
200 <form method="post">
201 <?php self::save_location_nonce_field(); ?>
202 <div id="poststuff">
203 <div id="post-body" class="metabox-holder columns-2">
204 <div id="post-body-content">
205 <?php self::metabox_ui_wrapper( Orderable_Location_Store_Address_Meta_Box::class ); ?>
206 <?php self::metabox_ui_wrapper( Orderable_Location_Open_Hours_Meta_Box::class ); ?>
207 <?php self::metabox_ui_wrapper( Orderable_Location_Store_Services_Meta_Box::class ); ?>
208 <?php self::metabox_ui_wrapper( Orderable_Location_Order_Options_Meta_Box::class ); ?>
209 <?php self::metabox_ui_wrapper( Orderable_Location_Holidays_Meta_Box::class ); ?>
210 </div>
211 <div id="postbox-container-1" class="postbox-container">
212 <div id="major-publishing-actions" style="overflow: hidden; margin-bottom: 20px; border: 1px solid #DCDCDE;">
213 <button class="button button-primary button-large" type="submit">
214 <?php echo esc_html__( 'Save Changes', 'orderable' ); ?>
215 </button>
216 </div>
217
218 <div class="orderable-cta">
219 <h3 class="orderable-cta__title"><?php _e( 'Unlock Multi-Location Power with Orderable Pro', 'orderable' ); ?></h3>
220 <p class="orderable-cta__description"><?php _e( 'Manage multiple locations effortlessly with Orderable Pro, perfect for businesses with more than one location. Take control of your delivery and pickup services like never before.', 'orderable' ); ?></p>
221 <p><a href="<?php echo esc_url( Orderable_Helpers::get_pro_url( 'multi-location', 'pricing' ) ); ?>" class="orderable-admin-button orderable-admin-button--pro" target="_blank"><span class="dashicons dashicons-star-filled"></span> <?php _e( 'Upgrade Now', 'orderable' ); ?></a></p>
222 <p><?php _e( 'or', 'orderable' ); ?> <a href="<?php echo esc_url( Orderable_Helpers::get_pro_url( 'multi-location' ) ); ?>" target="_blank"><?php _e( 'learn more', 'orderable' ); ?></a></p>
223 </div>
224 </div>
225 </div>
226 </div>
227 </form>
228 </div>
229 <?php
230 }
231
232 /**
233 * Add meta box HTML elements wrapper.
234 *
235 * @param string $meta_box_class The meta box class.
236 * @return void
237 */
238 protected static function metabox_ui_wrapper( $meta_box_class ) {
239 if ( ! class_exists( $meta_box_class ) ) {
240 return;
241 }
242
243 if ( ! is_callable( $meta_box_class, 'output' ) ) {
244 return;
245 }
246
247 $title = is_callable( $meta_box_class, 'get_title' ) ? call_user_func( array( $meta_box_class, 'get_title' ) ) : '';
248 ?>
249 <div id="<?php echo esc_attr( strtolower( $meta_box_class ) ); ?>" class="postbox">
250 <div class="postbox-header">
251 <h2>
252 <?php echo esc_html( $title ); ?>
253 </h2>
254 </div>
255 <div class="inside">
256 <?php call_user_func( array( $meta_box_class, 'output' ) ); ?>
257 </div>
258 </div>
259 <?php
260 }
261
262 /**
263 * Save the orderable location data.
264 *
265 * @return void
266 */
267 public static function save_data() {
268 global $post;
269
270 if ( ! function_exists( 'get_current_screen' ) ) {
271 return;
272 }
273
274 $current_screen = get_current_screen();
275
276 if ( empty( $current_screen->id ) ) {
277 return;
278 }
279
280 if (
281 'orderable_page_orderable-location' !== $current_screen->id &&
282 ( empty( $post ) || 'orderable_locations' !== $post->post_type )
283 ) {
284 return;
285 }
286
287 if ( empty( $_POST ) || ! check_admin_referer( 'orderable_location_save', '_wpnonce_orderable_location' ) ) {
288 return;
289 }
290
291 /**
292 * Filter the location data to be saved.
293 *
294 * @since 1.8.0
295 * @hook orderable_location_get_save_data
296 * @param array $data The data to be saved.
297 * @param int $post_id The post ID.
298 * @return array New value
299 */
300 $data = apply_filters( 'orderable_location_get_save_data', get_option( 'orderable_settings', array() ) );
301
302 if ( empty( $data ) ) {
303 return;
304 }
305
306 /**
307 * Fires when location data is saved.
308 *
309 * @since 1.8.0
310 * @hook orderable_location_save_data
311 * @param array $data The location data.
312 */
313 do_action( 'orderable_location_save_data', $data );
314
315 self::clear_location_data_cache( $data );
316 }
317
318 /**
319 * Clear location cache when updated.
320 *
321 * @param array $data The data saved.
322 * @return void
323 */
324 protected static function clear_location_data_cache( $data ) {
325 global $post;
326
327 $post_id = ! empty( $post ) ? $post->ID : null;
328 $location_id = Orderable_Location::get_location_id( $post_id );
329
330 if ( empty( $location_id ) ) {
331 return;
332 }
333
334 $location_data_cache_key = 'orderable_get_location_data_' . $location_id;
335 $time_slots_cache_key = 'orderable_time_slots_' . $location_id;
336
337 wp_cache_delete( $location_data_cache_key );
338 wp_cache_delete( $time_slots_cache_key . '_delivery' );
339 wp_cache_delete( $time_slots_cache_key . '_pickup' );
340 wp_cache_delete( 'orderable_zones' );
341
342 foreach ( WC_Shipping_Zones::get_zones() as $zone ) {
343 wp_cache_delete( 'orderable_time_slots_for_zone_' . $zone['zone_id'] );
344 }
345
346 if ( empty( $data['store_general_service_hours_delivery'] ) || ! is_array( $data['store_general_service_hours_delivery'] ) ) {
347 return;
348 }
349
350 foreach ( $data['store_general_service_hours_delivery'] as $time_slot ) {
351 if ( empty( $time_slot['time_slot_id'] ) ) {
352 continue;
353 }
354
355 wp_cache_delete( 'orderable_zones_time_slot_' . $time_slot['time_slot_id'] );
356 }
357 }
358
359 /**
360 * Output a nonce field to save the location data.
361 *
362 * @return void
363 */
364 public static function save_location_nonce_field() {
365 wp_nonce_field( 'orderable_location_save', '_wpnonce_orderable_location' );
366 }
367
368 /**
369 * Get the field value sent via POST.
370 *
371 * @param string $field_name The field name to retrieve.
372 * @return string
373 */
374 public static function get_posted_value( $field_name ) {
375 $nonce = empty( $_POST['_wpnonce_orderable_location'] ) ? false : sanitize_text_field( wp_unslash( $_POST['_wpnonce_orderable_location'] ) );
376
377 if ( ! wp_verify_nonce( $nonce, 'orderable_location_save' ) ) {
378 return '';
379 }
380
381 if ( ! is_string( $field_name ) || empty( $_POST[ $field_name ] ) ) {
382 return '';
383 }
384
385 return sanitize_text_field( wp_unslash( $_POST[ $field_name ] ) );
386 }
387
388 /**
389 * Add location data when onboard settings are saved.
390 *
391 * @param array $fields Field data.
392 */
393 public static function onboard_settings_saved( $fields = array() ) {
394 $orderable_fields = isset( $fields['orderable_settings'] ) ? $fields['orderable_settings'] : array();
395
396 if ( empty( $orderable_fields ) ) {
397 return;
398 }
399
400 global $wpdb;
401
402 // Format open days.
403 $open_days = ! empty( $orderable_fields['iconic_onboard_days'] ) ? array_map( 'absint', $orderable_fields['iconic_onboard_days'] ) : array();
404
405 // Create an array with 7 items, each containing $orderable_fields['iconic_onboard_open_hours'].
406 $posted_open_hours = ! empty( $orderable_fields['iconic_onboard_open_hours'] ) ? $orderable_fields['iconic_onboard_open_hours'] : array();
407
408 if ( ! empty( $posted_open_hours ) ) {
409 $posted_open_hours['enabled'] = false;
410 $posted_open_hours['max_orders'] = '';
411
412 $open_hours = array_fill( 0, 7, $posted_open_hours );
413
414 // Update the 'enabled' key for each day based on the existence of the day key in $open_days
415 foreach ( $open_hours as $day_key => $day_data ) {
416 $open_hours[ $day_key ]['enabled'] = in_array( $day_key, $open_days, true );
417 }
418 }
419
420 $data = array(
421 'override_default_open_hours' => 1,
422 'open_hours' => maybe_serialize( $open_hours ),
423 'delivery' => ! empty( $orderable_fields['iconic_onboard_services'] ) && in_array( 'flat_rate', $orderable_fields['iconic_onboard_services'], true ),
424 'pickup' => ! empty( $orderable_fields['iconic_onboard_services'] ) && in_array( 'local_pickup', $orderable_fields['iconic_onboard_services'], true ),
425 'address_line_1' => isset( $orderable_fields['iconic_onboard_business_address'] ) ? $orderable_fields['iconic_onboard_business_address'] : '',
426 'address_line_2' => isset( $orderable_fields['iconic_onboard_business_address_2'] ) ? $orderable_fields['iconic_onboard_business_address_2'] : '',
427 'city' => isset( $orderable_fields['iconic_onboard_business_city'] ) ? $orderable_fields['iconic_onboard_business_city'] : '',
428 'country_state' => isset( $orderable_fields['iconic_onboard_default_country'] ) ? $orderable_fields['iconic_onboard_default_country'] : '',
429 'postcode_zip' => isset( $orderable_fields['iconic_onboard_business_postcode'] ) ? $orderable_fields['iconic_onboard_business_postcode'] : '',
430 'is_main_location' => 1,
431 );
432
433 // Get main location ID.
434 $main_location_id = Orderable_Location::get_main_location_id();
435
436 if ( empty( $main_location_id ) ) {
437 $update = $wpdb->insert(
438 $wpdb->orderable_locations,
439 $data
440 );
441 } else {
442 $update = $wpdb->update(
443 $wpdb->orderable_locations,
444 $data,
445 array(
446 'location_id' => $main_location_id,
447 ),
448 null,
449 array(
450 'location_id' => '%d',
451 )
452 );
453 }
454
455 if ( ! $update || is_wp_error( $update ) ) {
456 return;
457 }
458
459 if ( ! empty( $open_hours ) && ! empty( $open_days ) ) {
460 $main_location_id = $main_location_id ? $main_location_id : Orderable_Location::get_main_location_id();
461
462 // Check if any time slots exists for this location.
463 $existing_time_slots = intval(
464 $wpdb->get_var(
465 $wpdb->prepare(
466 "SELECT COUNT(*) FROM {$wpdb->orderable_location_time_slots} WHERE location_id = %d",
467 $main_location_id
468 )
469 )
470 );
471
472 // If not, let's add one.
473 if ( $existing_time_slots <= 0 ) {
474 $wpdb->insert(
475 $wpdb->orderable_location_time_slots,
476 array(
477 'location_id' => $main_location_id,
478 'service_type' => 'delivery',
479 'days' => maybe_serialize( array_map( 'strval', $open_days ) ),
480 'period' => 'all-day',
481 'time_from' => '',
482 'time_to' => '',
483 'frequency' => '',
484 'cutoff' => '',
485 'max_orders' => '',
486 'has_zones' => 0,
487 )
488 );
489 }
490 }
491 }
492 }
493