' . esc_html__( 'ABCT Smart Orders Free was not initialized because ABCT Smart Orders Pro is active. Keep only Pro enabled on this site.', 'abct-smart-orders' ) . '
';
};
add_action( 'admin_notices', $abct_so_free_conflict_notice );
add_action( 'network_admin_notices', $abct_so_free_conflict_notice );
return;
}
if ( ! defined( 'ABCT_SO_FREE_BOOTSTRAPPED' ) ) {
define( 'ABCT_SO_FREE_BOOTSTRAPPED', true );
}
define( 'ABCT_SO_VERSION', '1.5.10' );
define( 'ABCT_SO_DB_VERSION', '1.5.0' );
define( 'ABCT_SO_PLUGIN_FILE', __FILE__ );
define( 'ABCT_SO_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'ABCT_SO_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
if ( ! defined( 'ABCT_PRODUCT_SLUG' ) ) {
define( 'ABCT_PRODUCT_SLUG', 'abctransfer-smart-orders' );
}
/**
* Loaded files errors.
*
* @var array
*/
$GLOBALS['abct_so_load_errors'] = array();
/**
* Safely include plugin files.
*
* @param string $relative_path Relative plugin path.
* @return bool
*/
function abct_so_safe_require( $relative_path ) {
$file_path = ABCT_SO_PLUGIN_DIR . ltrim( $relative_path, '/' );
if ( ! file_exists( $file_path ) ) {
$GLOBALS['abct_so_load_errors'][] = sprintf(
/* translators: %s: missing file path */
__( 'Missing required file: %s', 'abct-smart-orders' ),
str_replace( ABCT_SO_PLUGIN_DIR, '', $file_path )
);
return false;
}
try {
require_once $file_path;
return true;
} catch ( Throwable $e ) {
$GLOBALS['abct_so_load_errors'][] = sprintf(
/* translators: %s: file path */
__( 'Failed loading file safely: %s', 'abct-smart-orders' ),
str_replace( ABCT_SO_PLUGIN_DIR, '', $file_path )
);
error_log( '[ABCT Smart Orders] Safe require error (' . $relative_path . '): ' . $e->getMessage() );
return false;
}
}
abct_so_safe_require( 'includes/class-abct-status.php' );
abct_so_safe_require( 'includes/class-abct-status-manager.php' );
abct_so_safe_require( 'includes/database.php' );
abct_so_safe_require( 'includes/functions-hours.php' );
abct_so_safe_require( 'includes/upsell-functions.php' );
abct_so_safe_require( 'admin/settings-page.php' );
/**
* Resolve operational capability.
*
* @return string
*/
function abct_get_operations_capability() {
/**
* Filter operational capability for ABCT runtime.
*
* @param string $capability Capability key.
*/
return (string) apply_filters( 'abct_operations_capability', 'manage_woocommerce' );
}
/**
* Check if current user can operate ABCT operational flows.
*
* @return bool
*/
function abct_user_can_manage_operations() {
return current_user_can( abct_get_operations_capability() );
}
/**
* Register explicit Orders module menu in admin.
*
* @return string
*/
function abct_resolve_orders_parent_menu() {
global $menu;
$registered = array();
if ( is_array( $menu ) ) {
foreach ( $menu as $item ) {
if ( is_array( $item ) && ! empty( $item[2] ) ) {
$registered[] = (string) $item[2];
}
}
}
if ( in_array( 'abct-live-orders', $registered, true ) ) {
return 'abct-live-orders';
}
if ( in_array( 'abct-store-settings', $registered, true ) ) {
return 'abct-store-settings';
}
return '';
}
/**
* Register explicit Orders module menu in admin.
*
* @return void
*/
function abct_register_orders_module() {
$capability = abct_get_operations_capability();
$parent = abct_resolve_orders_parent_menu();
if ( '' !== $parent ) {
add_submenu_page(
$parent,
__( 'Orders', 'abct-smart-orders' ),
__( 'Orders', 'abct-smart-orders' ),
$capability,
'abct-production-board',
'abct_render_production_board'
);
return;
}
add_menu_page(
__( 'ABCT Orders', 'abct-smart-orders' ),
__( 'Orders', 'abct-smart-orders' ),
$capability,
'abct-production-board',
'abct_render_production_board',
'dashicons-list-view',
56
);
}
if ( apply_filters( 'abct_enable_legacy_orders_menu', false ) ) {
add_action( 'admin_menu', 'abct_register_orders_module' );
}
/**
* Render production board callback.
*
* @return void
*/
function abct_render_production_board() {
$page_file = plugin_dir_path( __FILE__ ) . 'admin/production-board-page.php';
if ( ! file_exists( $page_file ) ) {
echo '' . esc_html__( 'Production Board', 'abct-smart-orders' ) . '
' . esc_html__( 'Production Board is available in Smart Orders Pro.', 'abct-smart-orders' ) . '
';
return;
}
require_once $page_file;
if ( function_exists( 'abct_render_production_board_page' ) ) {
abct_render_production_board_page();
}
}
/**
* Legacy Orders module asset bridge.
*
* Reuses the canonical Production Board enqueue/localize pipeline
* to avoid duplicate bootstrap, duplicate polling and payload drift.
*
* @param string $hook Current admin hook.
* @return void
*/
function abct_enqueue_orders_module_assets( $hook ) {
if ( ! in_array( $hook, array( 'toplevel_page_abct-production-board', 'abct-live-orders_page_abct-production-board', 'abct-store-settings_page_abct-production-board' ), true ) ) {
return;
}
if ( function_exists( 'abct_enqueue_production_board_assets' ) ) {
abct_enqueue_production_board_assets( $hook );
}
}
if ( apply_filters( 'abct_enable_legacy_orders_menu', false ) ) {
add_action( 'admin_enqueue_scripts', 'abct_enqueue_orders_module_assets' );
}
/**
* Fallback activation callback.
*
* @return void
*/
function abct_so_activate_plugin() {
if ( function_exists( 'abct_activate_plugin' ) ) {
abct_activate_plugin();
}
}
register_activation_hook( ABCT_SO_PLUGIN_FILE, 'abct_so_activate_plugin' );
/**
* Deactivation callback.
*
* @return void
*/
function abct_so_deactivate_plugin() {
if ( function_exists( 'abct_queue_clear_cleanup_schedule' ) ) {
abct_queue_clear_cleanup_schedule();
}
}
register_deactivation_hook( ABCT_SO_PLUGIN_FILE, 'abct_so_deactivate_plugin' );
/**
* Check WooCommerce status without forcing dependency.
*
* @return bool
*/
function abct_so_is_woocommerce_active() {
if ( ! function_exists( 'is_plugin_active' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
return function_exists( 'is_plugin_active' ) && is_plugin_active( 'woocommerce/woocommerce.php' );
}
/**
* Main plugin class.
*/
class ABCT_Smart_Orders {
/**
* Indicates if modular core loaded.
*
* @var bool
*/
private $core_loaded = false;
/**
* Constructor.
*/
public function __construct() {
add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
// FIX: Ensure DB schema is upgraded for existing installs.
add_action( 'plugins_loaded', array( $this, 'maybe_upgrade_database' ), 20 );
add_action( 'admin_notices', array( $this, 'render_admin_notices' ) );
add_action( 'plugins_loaded', array( $this, 'bootstrap_core' ), 30 );
add_action( 'admin_menu', array( $this, 'maybe_register_legacy_admin_menu' ), 20 );
add_action( 'admin_enqueue_scripts', array( $this, 'maybe_enqueue_legacy_admin_assets' ) );
}
/**
* Load plugin textdomain.
*
* @return void
*/
public function load_textdomain() {
load_plugin_textdomain( 'abct-smart-orders', false, dirname( plugin_basename( ABCT_SO_PLUGIN_FILE ) ) . '/languages' );
}
/**
* Upgrade DB schema when needed.
*
* @return void
*/
public function maybe_upgrade_database() {
if ( function_exists( 'abct_maybe_upgrade_database' ) ) {
abct_maybe_upgrade_database();
}
}
/**
* Bootstrap modular core loader.
*
* @return void
*/
public function bootstrap_core() {
$core_files = array(
'core/class-abct-core-container.php',
'core/class-abct-module-interface.php',
'modules/scheduling/class-abct-scheduling-module.php',
'modules/menu/class-abct-menu-module.php',
'core/class-abct-core-loader.php',
);
foreach ( $core_files as $core_file ) {
try {
if ( ! abct_so_safe_require( $core_file ) ) {
return;
}
} catch ( Throwable $e ) {
$GLOBALS['abct_so_load_errors'][] = __( 'A core module failed to load safely. Using legacy admin fallback.', 'abct-smart-orders' );
error_log( '[ABCT Smart Orders] Core file load error: ' . $e->getMessage() );
return;
}
}
$required = array(
'ABCT_Core_Loader',
'ABCT_Core_Container',
'ABCT_Module_Interface',
'ABCT_Scheduling_Module',
'ABCT_Menu_Module',
);
foreach ( $required as $class_name ) {
if ( class_exists( $class_name ) || interface_exists( $class_name ) ) {
continue;
}
$GLOBALS['abct_so_load_errors'][] = sprintf(
/* translators: %s: class name */
__( 'Missing required class: %s', 'abct-smart-orders' ),
$class_name
);
error_log( '[ABCT Smart Orders] Missing required class: ' . $class_name );
return;
}
try {
ABCT_Core_Loader::boot();
$this->core_loaded = true;
} catch ( Throwable $e ) {
$GLOBALS['abct_so_load_errors'][] = __( 'Core modules failed to initialize safely. Check server error log.', 'abct-smart-orders' );
error_log( '[ABCT Smart Orders] Core bootstrap error: ' . $e->getMessage() );
}
}
/**
* Register legacy admin menu only if modular core is unavailable.
*
* @return void
*/
public function maybe_register_legacy_admin_menu() {
if ( $this->core_loaded && $this->is_admin_menu_registered( 'abct-smart-orders' ) ) {
return;
}
$this->register_admin_menu();
}
/**
* Check if an admin menu slug is already registered.
*
* @param string $menu_slug Menu slug.
* @return bool
*/
private function is_admin_menu_registered( $menu_slug ) {
global $menu;
if ( empty( $menu ) || ! is_array( $menu ) ) {
return false;
}
foreach ( $menu as $item ) {
if ( ! is_array( $item ) || empty( $item[2] ) ) {
continue;
}
if ( (string) $menu_slug === (string) $item[2] ) {
return true;
}
}
return false;
}
/**
* Resolve a safe admin capability for legacy menu fallback.
*
* @return string
*/
private function get_legacy_menu_capability() {
$capability = abct_get_operations_capability();
if ( current_user_can( $capability ) ) {
return $capability;
}
return 'manage_options';
}
/**
* Enqueue legacy assets only if modular core is unavailable.
*
* @param string $hook Hook suffix.
* @return void
*/
public function maybe_enqueue_legacy_admin_assets( $hook ) {
if ( $this->core_loaded ) {
return;
}
$this->enqueue_admin_assets( $hook );
}
/**
* Render plugin load warnings.
*
* @return void
*/
public function render_admin_notices() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
if ( ! abct_so_is_woocommerce_active() ) {
echo '' . esc_html__( 'ABCT Smart Orders:', 'abct-smart-orders' ) . ' ' . esc_html__( 'WooCommerce is not available.', 'abct-smart-orders' ) . '
';
}
if ( empty( $GLOBALS['abct_so_load_errors'] ) || ! is_array( $GLOBALS['abct_so_load_errors'] ) ) {
return;
}
echo '' . esc_html__( 'ABCTransfer Smart Orders:', 'abct-smart-orders' ) . '
';
foreach ( $GLOBALS['abct_so_load_errors'] as $message ) {
echo '- ' . esc_html( $message ) . '
';
}
echo '
';
}
/**
* Register admin menus.
*
* @return void
*/
public function register_admin_menu() {
$capability = $this->get_legacy_menu_capability();
$live_callback = array( $this, 'render_missing_live_orders_page' );
$settings_callback = function_exists( 'abct_render_settings_page' ) ? 'abct_render_settings_page' : array( $this, 'render_missing_settings_page' );
add_menu_page(
__( 'Smart Orders', 'abct-smart-orders' ),
__( 'Smart Orders', 'abct-smart-orders' ),
$capability,
'abct-smart-orders',
$live_callback,
'dashicons-store',
56
);
add_submenu_page(
'abct-smart-orders',
__( 'Store Schedule', 'abct-smart-orders' ),
__( 'Store Schedule', 'abct-smart-orders' ),
$capability,
'abct-edit-schedule',
$settings_callback
);
}
/**
* Fallback renderer when live orders callback is unavailable.
*
* @return void
*/
public function render_missing_live_orders_page() {
echo '' . esc_html__( 'Smart Orders Free', 'abct-smart-orders' ) . '
' . esc_html__( 'Core modules are temporarily unavailable. Please reload this page.', 'abct-smart-orders' ) . '
';
}
/**
* Fallback renderer when settings callback is unavailable.
*
* @return void
*/
public function render_missing_settings_page() {
echo '' . esc_html__( 'Edit Schedule', 'abct-smart-orders' ) . '
' . esc_html__( 'Settings page callback is unavailable.', 'abct-smart-orders' ) . '
';
}
/**
* Enqueue admin styles/scripts.
*
* @param string $hook Hook suffix.
* @return void
*/
public function enqueue_admin_assets( $hook ) {
if ( ! in_array( $hook, array( 'toplevel_page_abct-live-orders', 'abct-live-orders_page_abct-edit-schedule' ), true ) ) {
return;
}
wp_enqueue_style(
'abct-admin',
ABCT_SO_PLUGIN_URL . 'assets/css/admin.css',
array(),
ABCT_SO_VERSION
);
if ( 'toplevel_page_abct-live-orders' !== $hook ) {
return;
}
wp_enqueue_script(
'abct-orders',
ABCT_SO_PLUGIN_URL . 'assets/js/orders.js',
array( 'jquery' ),
ABCT_SO_VERSION,
true
);
wp_localize_script(
'abct-orders',
'abctOrders',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'abct_orders_nonce' ),
'pollInterval' => 5000,
'soundUrl' => ABCT_SO_PLUGIN_URL . 'assets/sounds/sound_1.mp3',
'i18n' => array(
'customer' => __( 'Customer', 'abct-smart-orders' ),
'phone' => __( 'Phone', 'abct-smart-orders' ),
'total' => __( 'Total', 'abct-smart-orders' ),
'createdAt' => __( 'Created at', 'abct-smart-orders' ),
'orderData' => __( 'Order Data', 'abct-smart-orders' ),
'noOrders' => __( 'No orders found.', 'abct-smart-orders' ),
'new' => __( 'New', 'abct-smart-orders' ),
'preparing' => __( 'Preparing', 'abct-smart-orders' ),
'finished' => __( 'Finished', 'abct-smart-orders' ),
),
)
);
}
}
new ABCT_Smart_Orders();