get_settings(); } /** * Add settings page link to plugin listing. * * @param array $links * * @return array */ public static function plugin_settings_link( $links = array() ) { $settings_url = admin_url( 'admin.php?page=orderable-settings' ); $links[] = sprintf( '%s', esc_url( $settings_url ), esc_html( __( 'Settings', 'orderable' ) ) ); return $links; } /** * Add settings page. */ public static function add_settings_page() { $icon = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQ0IiBoZWlnaHQ9IjE4MyIgdmlld0JveD0iMCAwIDI0NCAxODMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTE5MC40NzggMTY2LjdDMjI3LjM2MiAxNDIuNzEgMjUzLjI3MSA5MS44NDM4IDI0MC44NTYgNTYuMzA5NUMyMjguNDQyIDIwLjk1NTcgMTc3LjUyMyAwLjkzMzgzNSAxMjMuNzI3IDAuMDMxOTUxNEM3MC4xMDk3IC0wLjg2OTkzMyAxMy42MTQgMTcuMzQ4MSAyLjI3ODkxIDUxLjI1OUMtOS4yMzYxMyA4NS4xNjk4IDI0LjU4OTMgMTM0Ljk1NCA2NS40MzE3IDE2MS4yODlDMTA2LjA5NCAxODcuNjI0IDE1My43NzQgMTkwLjY5IDE5MC40NzggMTY2LjdaTTE4My4yMzQgNzguNzIwNkMxODMuMjM0IDgzLjkyNDEgMTc4LjEwOCA5MS42Mjg3IDE2Ny4zNDggOTEuNjI4N0MxNTYuNTg4IDkxLjYyODcgMTUxLjQ2MyA4My45MjQxIDE1MS40NjMgNzguNzIwNkMxNTEuNDYzIDczLjUxNzIgMTU2LjU4OCA2NS44MTI2IDE2Ny4zNDggNjUuODEyNkMxNzguMTA4IDY1LjgxMjYgMTgzLjIzNCA3My41MTcyIDE4My4yMzQgNzguNzIwNlpNMTY5LjExOCAxMjQuNjk3QzE5NS4zNDkgMTIzLjgyMiAyMTYuMzI4IDEwMy41NzIgMjE2LjMyOCA3OC43MjA2QzIxNi4zMjggNTMuMzEyNCAxOTQuMzk5IDMyLjcxNSAxNjcuMzQ4IDMyLjcxNUMxNjcuMjU3IDMyLjcxNSAxNjcuMTY3IDMyLjcxNTMgMTY3LjA3NiAzMi43MTU3SDg2LjczNUM4MS42NjMgMzIuNzE1NyA3Ny41NTEyIDM2LjgzNTIgNzcuNTUxMiA0MS45MTY4Qzc3LjU1MTIgNDYuOTk4NSA4MS42NjMgNTEuMTE4IDg2LjczNSA1MS4xMThIMTI4LjE2TDEyOC4xNDQgNTEuMTM3MUMxMzIuOTQyIDUxLjQ1MTEgMTM2LjczNiA1NS40NDE3IDEzNi43MzYgNjAuMzE4M0MxMzYuNzM2IDY1LjQgMTMyLjYxNiA2OS41MTk1IDEyNy41MzQgNjkuNTE5NUgxMTkuMzQ4TDExOS4zNDggNjkuNTIwMkg1My4wNjExQzQ3Ljk4OTEgNjkuNTIwMiA0My44NzczIDczLjYzOTcgNDMuODc3MyA3OC43MjEzQzQzLjg3NzMgODMuODAyOSA0Ny45ODkxIDg3LjkyMjQgNTMuMDYxMSA4Ny45MjI0SDEyNy42NTJDMTMyLjY4IDg3Ljk4NTQgMTM2LjczNiA5Mi4wODA0IDEzNi43MzYgOTcuMTIyOEMxMzYuNzM2IDEwMiAxMzIuOTQyIDEwNS45OSAxMjguMTQ0IDEwNi4zMDRMMTI4LjE2MSAxMDYuMzI1SDc0LjQ5QzY5LjQxNzkgMTA2LjMyNSA2NS4zMDYyIDExMC40NDQgNjUuMzA2MiAxMTUuNTI2QzY1LjMwNjIgMTIwLjYwNyA2OS40MTc5IDEyNC43MjcgNzQuNDkgMTI0LjcyN0gxNjguMzY5QzE2OC42MjEgMTI0LjcyNyAxNjguODcxIDEyNC43MTcgMTY5LjExOCAxMjQuNjk3Wk0xNTAuODY0IDEzNy41NDVDMTUyLjA2NSAxNDEuMTE4IDE0OS41NTggMTQ2LjIzMyAxNDUuOTg4IDE0OC42NDZDMTQyLjQzNSAxNTEuMDU4IDEzNy44MjEgMTUwLjc1IDEzMy44ODUgMTQ4LjEwMkMxMjkuOTMyIDE0NS40NTQgMTI2LjY1OSAxNDAuNDQ3IDEyNy43NzMgMTM3LjAzN0MxMjguODcgMTMzLjYyNyAxMzQuMzM4IDEzMS43OTUgMTM5LjUyNyAxMzEuODg2QzE0NC43MzQgMTMxLjk3NyAxNDkuNjYyIDEzMy45OSAxNTAuODY0IDEzNy41NDVaTTE2MS42NzYgMTM3LjU0NUMxNjAuNDc0IDE0MS4xMTggMTYyLjk4MiAxNDYuMjMzIDE2Ni41NTIgMTQ4LjY0NkMxNzAuMTA0IDE1MS4wNTggMTc0LjcxOSAxNTAuNzUgMTc4LjY1NCAxNDguMTAyQzE4Mi42MDcgMTQ1LjQ1NCAxODUuODgxIDE0MC40NDcgMTg0Ljc2NiAxMzcuMDM3QzE4My42NjkgMTMzLjYyNyAxNzguMjAyIDEzMS43OTUgMTczLjAxMiAxMzEuODg2QzE2Ny44MDYgMTMxLjk3NyAxNjIuODc3IDEzMy45OSAxNjEuNjc2IDEzNy41NDVaIiBmaWxsPSIjOUNBMUE4Ii8+DQo8L3N2Zz4='; add_menu_page( 'Orderable', 'Orderable', 'manage_options', 'orderable', null, $icon, 54 ); self::$settings_framework->add_settings_page( array( 'parent_slug' => 'orderable', 'page_title' => __( 'Orderable Settings', 'orderable' ), 'menu_title' => __( 'Settings', 'orderable' ), 'capability' => 'manage_options', ) ); remove_submenu_page( 'orderable', 'orderable' ); } /** * Add default settings. * * @param array $default_settings * * @return array */ public static function default_settings( $default_settings = array() ) { $default_settings['style_style_color'] = '#000000'; $default_settings['style_style_buttons'] = 'rounded'; $default_settings['style_products_title_size'] = 20; $default_settings['style_products_price_size'] = 18; return $default_settings; } /** * Register settings. * * @param array $settings * * @return array */ public static function register_settings( $settings = array() ) { $settings = array( 'tabs' => array(), 'sections' => array(), ); $settings['tabs'] = array( array( 'id' => 'dashboard', 'title' => __( 'Dashboard', 'orderable' ), 'priority' => 0, ), array( 'id' => 'style', 'title' => __( 'Style', 'orderable' ), 'priority' => 100, ), ); $settings['sections']['style'] = array( 'tab_id' => 'style', 'section_id' => 'style', 'section_title' => __( 'General', 'orderable' ), 'section_description' => '', 'section_order' => 10, 'fields' => array( 'color' => array( 'id' => 'color', 'title' => __( 'Brand Color', 'orderable' ), 'subtitle' => __( 'Select an accent color to be used for buttons and other elements.', 'orderable' ), 'type' => 'color', 'default' => self::get_setting_default( 'style_style_color' ), ), 'buttons' => array( 'id' => 'buttons', 'title' => __( 'Button Style', 'orderable' ), 'subtitle' => __( 'Choose a button style which suits your theme.', 'orderable' ), 'type' => 'select', 'default' => self::get_setting_default( 'style_style_buttons' ), 'choices' => array( 'rounded' => __( 'Rounded', 'orderable' ), 'square' => __( 'Square', 'orderable' ), ), ), ), ); $settings['sections']['products_style'] = array( 'tab_id' => 'style', 'section_id' => 'products', 'section_title' => __( 'Product Cards', 'orderable' ), 'section_description' => '', 'section_order' => 15, 'fields' => array( 'title_size' => array( 'id' => 'title_size', 'title' => __( 'Product Title Size (px)', 'orderable' ), 'subtitle' => __( 'Set the product title font size in pixels.', 'orderable' ), 'type' => 'number', 'default' => Orderable_Settings::get_setting_default( 'style_products_title_size' ), ), 'price_size' => array( 'id' => 'price_size', 'title' => __( 'Product Price Size (px)', 'orderable' ), 'subtitle' => __( 'Set the product price font size in pixels.', 'orderable' ), 'type' => 'number', 'default' => Orderable_Settings::get_setting_default( 'style_products_price_size' ), ), ), ); return $settings; } /** * Reorder settings tabs. * * @param array $settings * * @return array */ public static function reorder_settings_tabs( $settings = array() ) { usort( $settings['tabs'], function ( $a, $b ) { $a['priority'] = empty( $a['priority'] ) ? 0 : absint( $a['priority'] ); $b['priority'] = empty( $b['priority'] ) ? 0 : absint( $b['priority'] ); return $a['priority'] - $b['priority']; } ); return $settings; } /** * Get setting default. * * @param string $setting_name * * @return bool|mixed */ public static function get_setting_default( $setting_name = '' ) { if ( empty( $setting_name ) ) { return false; } $defaults = apply_filters( 'orderable_default_settings', array() ); if ( ! isset( $defaults[ $setting_name ] ) ) { return false; } return $defaults[ $setting_name ]; } /** * Get setting. * * This method is accessible before the settings are assign to self::$settings. * * @param string $setting_name * * @return bool|mixed */ public static function get_setting( $setting_name = '' ) { if ( empty( $setting_name ) ) { return false; } $settings = get_option( self::$option_group . '_settings' ); if ( isset( $settings[ $setting_name ] ) ) { return $settings[ $setting_name ]; } return self::get_setting_default( $setting_name ); } /** * @param string $suffix * * @return bool */ public static function is_settings_page( $suffix = '' ) { if ( ! is_admin() ) { return false; } // Allow bypass from other modules. if ( apply_filters( 'orderable_is_settings_page', false ) ) { return true; } $valid_pages = apply_filters( 'orderable_valid_admin_pages', array( self::$option_group . '-settings' . $suffix, ) ); $page = filter_input( INPUT_GET, 'page', FILTER_SANITIZE_STRING ); if ( ! in_array( $page, $valid_pages, true ) ) { return false; } return true; } /** * Init onboarding. */ public static function init_onboarding() { if ( ! self::is_settings_page() || defined( 'WC_DOING_AJAX' ) ) { if ( empty( $_REQUEST['plugin_slug'] ) || 'orderable' !== $_REQUEST['plugin_slug'] ) { return; } } include_once ORDERABLE_INC_PATH . 'vendor/iconic-onboard/class-iconic-onboard.php'; $slides = apply_filters( 'orderable_onboarding_slides', array( 'welcome' => array( 'header_image' => ORDERABLE_URL . '/assets/img/onboarding/orderable-onboarding-header.jpg', 'title' => 'Welcome', 'description' => 'Thank you for choosing Orderable to add local ordering to your website. This short setup wizard will guide you though configuring Orderable.', 'button_text' => 'Begin ', 'button_icon' => '', ), 'requirements' => array( 'title' => 'Requirements', 'description' => 'Orderable requires WooCommerce for the order checkout, management, and reporting. In this step we will install WooCommerce for you. This might take a couple of minutes.', 'button_text' => 'Install & Activate WooCommerce', 'wait' => 'install_plugin', 'json_data' => array( 'wait_text' => __( 'Installing...', 'orderable' ), 'plugin_data' => array( 'name' => __( 'WooCommerce', 'orderable' ), 'repo-slug' => 'woocommerce', 'file' => 'woocommerce.php', ), ), ), 'business' => array( 'title' => 'Business Info', 'description' => 'Orderable needs some basic business information that will be used when orders are placed.', 'button_text' => 'Continue ', 'fields' => array( 'name' => array( 'id' => 'business_name', 'title' => __( 'Business Name', 'orderable' ), 'desc' => '', 'type' => 'text', 'default' => get_bloginfo( 'name' ), ), 'address' => array( 'id' => 'business_address', 'title' => __( 'Address line 1', 'orderable' ), 'desc' => '', 'type' => 'text', ), 'address_2' => array( 'id' => 'business_address_2', 'title' => __( 'Address line 2', 'orderable' ), 'desc' => '', 'type' => 'text', ), 'city' => array( 'id' => 'business_city', 'title' => __( 'City', 'orderable' ), 'desc' => '', 'type' => 'text', ), 'default_country' => array( 'id' => 'default_country', 'title' => __( 'Country / State', 'orderable' ), 'desc' => '', 'type' => 'select', 'choices' => array(), ), 'postcode' => array( 'id' => 'business_postcode', 'title' => __( 'Postcode / ZIP', 'orderable' ), 'desc' => '', 'type' => 'text', ), 'email' => array( 'id' => 'business_email', 'title' => __( 'Business Email', 'orderable' ), 'desc' => '', 'type' => 'text', 'default' => get_option( 'admin_email' ), ), array( 'id' => 'opt_in', 'title' => '', 'desc' => __( 'Please keep me up to date via email on new Orderable training and features', 'orderable' ), 'type' => 'checkbox', 'default' => 1, ), ), ), 'location' => array( "title" => "Location Info", "description" => 'Help us set up your ordering system. You can refine these details further after completing the onboarding process.', "button_text" => "Continue ", 'fields' => array( array( 'id' => 'services', 'title' => __( 'Which services do you offer?', 'orderable' ), 'desc' => '', 'type' => 'checkboxes', 'choices' => array( 'flat_rate' => __( 'Delivery', 'orderable' ), 'local_pickup' => __( 'Pickup', 'orderable' ), ), ), array( 'id' => 'days', 'title' => __( 'Which days of the week are you open?', 'orderable' ), 'desc' => '', 'type' => 'checkboxes', 'choices' => array( 1 => __( 'Monday', 'orderable' ), 2 => __( 'Tuesday', 'orderable' ), 3 => __( 'Wednesday', 'orderable' ), 4 => __( 'Thursday', 'orderable' ), 5 => __( 'Friday', 'orderable' ), 6 => __( 'Saturday', 'orderable' ), 0 => __( 'Sunday', 'orderable' ), ), ), array( 'id' => 'open_hours', 'title' => __( 'What are your normal opening hours?', 'orderable' ), 'desc' => '', 'type' => 'custom', 'default' => self::get_open_hours_fields(), ), ), ), 'done' => array( "title" => "All Done", "description" => "Congratulations, You Did It! Orderable is ready to use on your website. You've successfully completed the setup process and all that is left for you to do is create/customize your products.", "button_text" => "Save and Finish ", ), ) ); if ( function_exists( 'WC' ) ) { unset( $slides['requirements'] ); $base = wc_get_base_location(); $slides['business']['fields']['default_country']['choices'] = self::get_countries_states(); $slides['business']['fields']['default_country']['default'] = implode( ':', array_filter( $base ) ); $slides['business']['fields']['address']['default'] = WC()->countries->get_base_address(); $slides['business']['fields']['address_2']['default'] = WC()->countries->get_base_address_2(); $slides['business']['fields']['city']['default'] = WC()->countries->get_base_city(); $slides['business']['fields']['postcode']['default'] = WC()->countries->get_base_postcode(); } Orderable_Onboard::run( array( 'version' => ORDERABLE_VERSION, 'plugin_slug' => 'orderable', 'plugin_url' => ORDERABLE_URL, 'plugin_path' => ORDERABLE_PATH, 'slides' => $slides, ) ); } /** * Save the onboarding data in database. * * @param array $result Was the submission a success? * @param array $fields Submitted fields. * * @return bool|array $result */ public static function save_onboard_settings( $result, $fields ) { if ( empty( $fields['orderable_settings'] ) ) { return false; } // Get existing/default settings. $settings = get_option( 'orderable_settings', array() ); // Assign opening hours. if ( ! empty( $fields['orderable_settings']['iconic_onboard_days'] ) && is_array( $fields['orderable_settings']['iconic_onboard_days'] ) ) { $from = array( 'hour' => filter_var( $fields['orderable_settings']['iconic_onboard_open_hours']['from']['hour'], FILTER_SANITIZE_STRING ), 'minute' => filter_var( $fields['orderable_settings']['iconic_onboard_open_hours']['from']['minute'], FILTER_SANITIZE_STRING ), 'period' => filter_var( $fields['orderable_settings']['iconic_onboard_open_hours']['from']['period'], FILTER_SANITIZE_STRING ), ); $to = array( 'hour' => filter_var( $fields['orderable_settings']['iconic_onboard_open_hours']['to']['hour'], FILTER_SANITIZE_STRING ), 'minute' => filter_var( $fields['orderable_settings']['iconic_onboard_open_hours']['to']['minute'], FILTER_SANITIZE_STRING ), 'period' => filter_var( $fields['orderable_settings']['iconic_onboard_open_hours']['to']['period'], FILTER_SANITIZE_STRING ), ); $settings['store_general_open_hours'] = array(); foreach ( $fields['orderable_settings']['iconic_onboard_days'] as $day ) { $day = absint( $day ); if ( $day < 0 || $day > 6 ) { continue; } $settings['store_general_open_hours'][ $day ] = array( 'enabled' => '1', 'from' => $from, 'to' => $to, 'max_orders' => '', ); } } // Save Business details. $name = isset( $fields['orderable_settings']['iconic_onboard_business_name'] ) ? wc_clean( wp_unslash( $fields['orderable_settings']['iconic_onboard_business_name'] ) ) : ''; $address = isset( $fields['orderable_settings']['iconic_onboard_business_address'] ) ? wc_clean( wp_unslash( $fields['orderable_settings']['iconic_onboard_business_address'] ) ) : ''; $address_2 = isset( $fields['orderable_settings']['iconic_onboard_business_address_2'] ) ? wc_clean( wp_unslash( $fields['orderable_settings']['iconic_onboard_business_address_2'] ) ) : ''; $city = isset( $fields['orderable_settings']['iconic_onboard_business_city'] ) ? wc_clean( wp_unslash( $fields['orderable_settings']['iconic_onboard_business_city'] ) ) : ''; $country_state = isset( $fields['orderable_settings']['iconic_onboard_default_country'] ) ? wc_clean( wp_unslash( $fields['orderable_settings']['iconic_onboard_default_country'] ) ) : ''; $stripped_country_state = $country_state ? str_replace( array( 'country:', 'state:' ), '', $country_state ) : ''; $postcode = isset( $fields['orderable_settings']['iconic_onboard_business_postcode'] ) ? wc_clean( wp_unslash( $fields['orderable_settings']['iconic_onboard_business_postcode'] ) ) : ''; $email = isset( $fields['orderable_settings']['iconic_onboard_business_email'] ) ? wc_clean( wp_unslash( $fields['orderable_settings']['iconic_onboard_business_email'] ) ) : ''; $opt_in = isset( $fields['orderable_settings']['iconic_onboard_opt_in'] ); if ( ! empty( $name ) ) { update_option( 'blogname', $name ); } update_option( 'woocommerce_store_address', $address ); update_option( 'woocommerce_store_address_2', $address_2 ); update_option( 'woocommerce_store_city', $city ); update_option( 'woocommerce_default_country', $stripped_country_state ); update_option( 'woocommerce_store_postcode', $postcode ); update_option( 'admin_email', $email ); update_option( 'orderable_opt_in', $opt_in ); // Restrict delivery area to country/state. if ( ! empty( $stripped_country_state ) ) { update_option( 'woocommerce_allowed_countries', 'specific' ); update_option( 'woocommerce_specific_allowed_countries', array( $stripped_country_state ) ); } // Save store services. if ( ! empty( $fields['orderable_settings']['iconic_onboard_services'] ) ) { $settings['store_general_services'] = array(); $existing_zone_id = null; $zone_name = __( 'Local', 'orderable' ); $zones = WC_Shipping_Zones::get_zones(); if ( ! empty( $zones ) ) { foreach ( $zones as $zone ) { if ( $zone_name !== $zone['zone_name'] ) { continue; } $existing_zone_id = $zone['id']; $shipping_method_instances = ! empty( $zone['shipping_methods'] ) ? array_keys( $zone['shipping_methods'] ) : false; break; } } $zone = new WC_Shipping_Zone( $existing_zone_id ); $zone->set_zone_name( $zone_name ); if ( ! empty( $country_state ) ) { $zone->clear_locations(); $location_parts = explode( ':', $country_state ); switch ( $location_parts[0] ) { case 'state': $zone->add_location( $location_parts[1] . ':' . $location_parts[2], 'state' ); break; case 'country': $zone->add_location( $location_parts[1], 'country' ); break; case 'continent': $zone->add_location( $location_parts[1], 'continent' ); break; } } if ( ! empty( $shipping_method_instances ) ) { foreach ( $shipping_method_instances as $shipping_method_instance_id ) { $zone->delete_shipping_method( $shipping_method_instance_id ); } } $service_types = array( 'flat_rate' => 'delivery', 'local_pickup' => 'pickup', ); foreach ( $fields['orderable_settings']['iconic_onboard_services'] as $service ) { $service = wc_clean( $service ); $zone->add_shipping_method( $service ); $settings['store_general_services'][] = $service_types[ $service ]; } $zone->save(); } // Misc. $settings['store_general_service_hours_pickup_same'] = 1; // Save settings. update_option( 'orderable_settings', $settings ); // Return success. return $result; } /** * Get countries and states for select field. * * @return array */ public static function get_countries_states() { $countries_states = array(); if ( ! function_exists( 'WC' ) ) { return $countries_states; } $countries = WC()->countries->get_countries(); if ( empty( $countries ) ) { return $countries_states; } foreach ( $countries as $key => $value ) { $countries_states[ 'country:' . $key ] = $value; $states = WC()->countries->get_states( $key ); if ( empty( $states ) ) { continue; } $countries_states[ $key ] = array( 'group_label' => $value, 'values' => array(), ); foreach ( $states as $state_key => $state_value ) { $state_key = sprintf( 'state:%s:%s', $key, $state_key ); $countries_states[ $key ]['values'][ $state_key ] = sprintf( '%s — %s', $value, $state_value ); } } return $countries_states; } /** * Get open hours fields. * * @return string */ public static function get_open_hours_fields() { ob_start(); ?>
9, 'minute' => '00', 'period' => 'AM', ) ); ?>
5, 'minute' => '00', 'period' => 'PM', ) ); ?>

term_id, 'visibility', true ); ?>

get_results( "SELECT DISTINCT tm.term_id FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id INNER JOIN $wpdb->termmeta AS tm ON t.term_id = tm.term_id WHERE tt.taxonomy = 'product_cat' AND tm.meta_key = 'visibility' AND tm.meta_value IN ( 'hidden' ) UNION DISTINCT SELECT DISTINCT term_id FROM $wpdb->term_taxonomy WHERE parent IN ( SELECT DISTINCT tm.term_id FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id INNER JOIN $wpdb->termmeta AS tm ON t.term_id = tm.term_id WHERE tt.taxonomy = 'product_cat' AND tm.meta_key = 'visibility' AND tm.meta_value IN ( 'hidden' ) )", ARRAY_A ); if ( is_wp_error( $results ) || empty( $results ) ) { return apply_filters( 'orderable_hidden_categories', $hidden_categories ); } $hidden_categories = array_map( 'absint', wp_list_pluck( $results, 'term_id' ) ); return apply_filters( 'orderable_hidden_categories', $hidden_categories ); } /** * Add logo to settings page. */ public static function settings_logo( $title = '' ) { return sprintf( '', esc_url( ORDERABLE_ASSETS_URL . 'img/orderable-logo.svg' ) ); } /** * Add version number to settings page. */ public static function version_number() { printf( 'v%s', ORDERABLE_VERSION ); } }