version = agile_tix_VERSION; } else { $this->version = '1.0.0'; } $this->agile_tix = 'agiletix-site-sync'; $this->load_dependencies(); $this->set_locale(); $this->define_admin_hooks(); $this->define_public_hooks(); } /** * Load the required dependencies for this plugin. * * Include the following files that make up the plugin: * * - agile_tix_Loader. Orchestrates the hooks of the plugin. * - agile_tix_i18n. Defines internationalization functionality. * - agile_tix_Admin. Defines all hooks for the admin area. * - agile_tix_Public. Defines all hooks for the public side of the site. * * Create an instance of the loader which will be used to register the hooks * with WordPress. * * @since 1.0.0 * @access private */ private function load_dependencies() { /** * The class responsible for orchestrating the actions and filters of the * core plugin. */ require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-loader.php'; /** * The class responsible for defining internationalization functionality * of the plugin. */ require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-i18n.php'; /** * The class responsible for defining all actions that occur in the admin area. */ require_once plugin_dir_path( __DIR__ ) . 'admin/agile-ticketing-admin.php'; /** * The class responsible for defining all actions that occur in the public-facing * side of the site. */ require_once plugin_dir_path( __DIR__ ) . 'public/agile-ticketing-public.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-options.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-post.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-data-fetcher.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-post-creator.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-rest-route.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-shortcodes.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-event-champ-integrate.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-executionTime.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-amy-moive-integrate.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-custom-support.php'; require_once plugin_dir_path( __DIR__ ) . 'includes/agile-ticketing-location-services.php'; require_once plugin_dir_path( __DIR__ ) . 'public/ats-integrate/widget-activate.php'; $this->loader = new agile_tix_Loader(); } /** * Define the locale for this plugin for internationalization. * * Uses the agile_tix_i18n class in order to set the domain and to register the hook * with WordPress. * * @since 1.0.0 * @access private */ private function set_locale() { // WordPress.org loads translations for the plugin text domain automatically. } /** * Register all of the hooks related to the admin area functionality * of the plugin. * * @since 1.0.0 * @access private */ private function define_admin_hooks() { $plugin_admin = new agile_tix_Admin( $this->get_agile_tix(), $this->get_version() ); $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' ); $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' ); $plugin_options = new agile_tix_Options( $this->get_agile_tix(), $this->get_version() ); $this->loader->add_action( 'admin_init', $plugin_options, 'agile_register_settings_tabs' ); $this->loader->add_action( 'admin_menu', $plugin_options, 'agile_options_page' ); // $this->loader->add_action('admin_footer', $plugin_options,'agile_custom_theme_map_set_required'); // $this->loader->add_action('wp_ajax_agile_get_meta_fields', $plugin_options, 'agile_get_meta_fields_ajax');//think this got scrapped in the custom rework // Add AJAX hooks for real-time utility metrics $this->loader->add_action( 'wp_ajax_agile_get_utility_metrics', 'agile_tix_Options', 'ajax_get_utility_metrics' ); $this->loader->add_filter( 'plugin_action_links_' . plugin_basename( dirname( __DIR__ ) . '/Agile_Ticketing.php' ), $plugin_options, 'agile_plugin_settings_link' ); $this->loader->add_action( 'load-toplevel_page_agile', $plugin_options, 'agile_verify_credentials_after_save' ); $this->loader->add_action( 'admin_notices', $plugin_options, 'agile_display_settings_errors' ); $this->loader->add_action( 'wp_ajax_agile_refresh_ats_data', $plugin_options, 'agile_refresh_ats_data' ); $this->loader->add_action( 'wp_ajax_agile_verify_credentials', $plugin_options, 'ajax_verify_credentials' ); $this->loader->add_action( 'wp_ajax_agile_activate_webhook', $plugin_options, 'agile_activate_webhook' ); $this->loader->add_action( 'wp_ajax_agile_get_tax_by_post_type', $plugin_options, 'agile_get_tax_by_postType' ); $this->loader->add_action( 'wp_ajax_agile_refresh_utility', $plugin_options, 'agile_refresh_utility' ); $this->loader->add_action( 'wp_ajax_agile_list_entry_points', $plugin_options, 'ajax_list_entry_points' ); $plugin_post = new agile_tix_post_type( $this->get_agile_tix(), $this->get_version() ); $this->loader->add_action( 'init', $plugin_post, 'register_agile_custom_post_type' ); $this->loader->add_action( 'pre_get_posts', $plugin_post, 'agile_post_adjust_queries' ); $this->loader->add_action( 'pre_get_posts', $plugin_post, 'ats_add_custom_post_type_to_rss_feed' ); $this->loader->add_action( 'pre_get_posts', $plugin_post, 'ats_coming_soon_feed_query' ); $rest_endpoint = new agile_tix_Rest_Route(); $this->loader->add_action( 'rest_api_init', $rest_endpoint, 'agile_register_rest_options' ); $this->loader->add_action( 'rest_api_init', $rest_endpoint, 'prefix_register_routes' ); $this->loader->add_filter( 'robots_txt', $rest_endpoint, 'agile_modify_robots' ); // $this->loader->add_action('init', $rest_endpoint, 'create_agile_API_agent_user'); // $this->loader->add_filter('rest_authentication_errors', $rest_endpoint, 'agile_whitelist_api_by_header', 10, 1); // $this->loader->add_filter('rest_pre_dispatch', $rest_endpoint, 'agile_prevalidate_ping_signature', 10, 2); $post_creator = new agile_tix_post_creator( $this->get_agile_tix(), $this->get_version() ); // $this->loader->add_action('agile_process_events_batch', $post_creator, 'agile_handle_events_batch', 10, 1); // $this->loader->add_action('agile_finalize_processing', $post_creator, 'agile_finalize_processing'); // $this->loader->add_action('admin_head', new agile_tix_Widget_Active(), 'agile_echo_head'); $activator = new agile_tix_Widget_Active(); $this->loader->add_action( 'admin_enqueue_scripts', $activator, 'agile_echo_head' ); /* $this->loader->add_action('admin_head', function() { echo ''; });*/ // $this->loader->add_action('wp_head', new agile_tix_Widget_Active(), 'agile_echo_head'); // Log when Action Scheduler is unavailable for batch processing (refreshes use AgileTix pings). $this->loader->add_action( 'action_scheduler_init', $this, 'verify_action_scheduler_setup', 20 ); // Add diagnostic checks (admin only) $this->loader->add_action( 'admin_init', $this, 'diagnose_action_scheduler', 20 ); } /** * Register all of the hooks related to the public-facing functionality * of the plugin. * * @since 1.0.0 * @access private */ private function define_public_hooks() { $plugin_public = new agile_tix_Public( $this->get_agile_tix(), $this->get_version() ); $this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_styles' ); $this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_scripts' ); $widget_active = new agile_tix_Widget_Active(); $this->loader->add_action( 'wp_enqueue_scripts', $widget_active, 'agile_echo_head' ); $plugin_options = new agile_tix_Options( $this->get_agile_tix(), $this->get_version() ); $this->loader->add_filter( 'post_thumbnail_html', $plugin_options, 'agile_hide_featured_image_conditionally', 10, 3 ); $post_creator = new agile_tix_post_creator( $this->get_agile_tix(), $this->get_version() ); $this->loader->add_action( 'agile_process_events_batch', $post_creator, 'agile_handle_events_batch', 10, 3 ); $this->loader->add_action( 'agile_finalize_processing', $post_creator, 'agile_finalize_processing' ); $this->loader->add_filter( 'action_scheduler_queue_runner_concurrent_batches', $post_creator, 'agile_increase_concurrent_batches' ); $this->loader->add_filter( 'action_scheduler_queue_runner_batch_size', $post_creator, 'agile_increase_batch_size' ); $plugin_shortcodes = new agile_tix_ShortCodes(); $this->loader->add_action( 'init', $plugin_shortcodes, 'ats_registerShortCodes' ); } /** * Run the loader to execute all of the hooks with WordPress. * * @since 1.0.0 */ public function run() { $this->loader->run(); } /** * The name of the plugin used to uniquely identify it within the context of * WordPress and to define internationalization functionality. * * @since 1.0.0 * @return string The name of the plugin. */ public function get_agile_tix() { return $this->agile_tix; } /** * The reference to the class that orchestrates the hooks with the plugin. * * @since 1.0.0 * @return agile_tix_Loader Orchestrates the hooks of the plugin. */ public function get_loader() { return $this->loader; } /** * Retrieve the version number of the plugin. * * @since 1.0.0 * @return string The version number of the plugin. */ public function get_version() { return $this->version; } /** * General utility logging function to write to our own log file instead of the bulk /wp-content/debug.log accessed with WP_DEBUG_LOG * Called with agile_tix::agile_tix_log_event("This is a test call to create the file"); * VERY IMPORTANT NOTE! this drops the log file in the larger WP_CONTENT folder instead of in the plugin's folder * This is good for for maintaining the log between plugin instances, but bad practise for a real plugin * Change the logfile path to plugin_dir_path(__FILE__) . agile_tix-log.txt before release * * @param mixed $message */ static function agile_tix_uploads_subdir() { return 'agiletix-site-sync'; } static function agile_tix_get_data_dir() { $upload_dir = wp_upload_dir(); $dir = trailingslashit( $upload_dir['basedir'] ) . self::agile_tix_uploads_subdir() . '/'; if ( ! file_exists( $dir ) ) { wp_mkdir_p( $dir ); } return $dir; } static function agile_tix_get_data_url() { $upload_dir = wp_upload_dir(); return trailingslashit( $upload_dir['baseurl'] ) . self::agile_tix_uploads_subdir() . '/'; } static function agile_tix_copy_uploads_from_subdir( $subdir ) { if ( $subdir === self::agile_tix_uploads_subdir() ) { return; } $upload_dir = wp_upload_dir(); $old_dir = trailingslashit( $upload_dir['basedir'] ) . $subdir . '/'; if ( ! is_dir( $old_dir ) ) { return; } $old_log = $old_dir . 'agile_tix-log.txt'; $new_log = self::agile_tix_get_data_dir() . 'agile_tix-log.txt'; if ( file_exists( $old_log ) && ! file_exists( $new_log ) ) { copy( $old_log, $new_log ); } } static function agile_tix_maybe_migrate_uploads_subdirectory() { if ( ! get_option( 'agile_tix_uploads_subdir_migrated' ) ) { self::agile_tix_copy_uploads_from_subdir( 'agile-ticketing' ); update_option( 'agile_tix_uploads_subdir_migrated', true ); } if ( ! get_option( 'agile_tix_uploads_plugin_subdir_migrated' ) ) { self::agile_tix_copy_uploads_from_subdir( 'agile-ticketing-plugin' ); update_option( 'agile_tix_uploads_plugin_subdir_migrated', true ); } if ( ! get_option( 'agile_tix_uploads_site_sync_migrated' ) ) { self::agile_tix_copy_uploads_from_subdir( 'agile-ticketing' ); self::agile_tix_copy_uploads_from_subdir( 'agile-ticketing-plugin' ); update_option( 'agile_tix_uploads_site_sync_migrated', true ); } } static function agile_tix_maybe_migrate_uploaded_files() { self::agile_tix_maybe_migrate_uploads_subdirectory(); if ( get_option( 'agile_tix_uploads_migrated' ) ) { return; } $legacy_log = WP_CONTENT_DIR . '/agile_tix-log.txt'; $new_log = self::agile_tix_get_data_dir() . 'agile_tix-log.txt'; if ( file_exists( $legacy_log ) && ! file_exists( $new_log ) ) { copy( $legacy_log, $new_log ); } update_option( 'agile_tix_uploads_migrated', true ); } /** * Log events to uploads directory. * * @param mixed $message Log message. */ static function agile_tix_log_event( $message ) { self::agile_tix_maybe_migrate_uploaded_files(); $log_file = self::agile_tix_get_data_dir() . 'agile_tix-log.txt'; if ( ! file_exists( $log_file ) ) { file_put_contents( $log_file, 'Log file created on ' . gmdate( 'Y-m-d H:i:s' ) . "\n" ); } $message = '[' . gmdate( 'Y-m-d H:i:s' ) . '] ' . $message . "\n"; file_put_contents( $log_file, $message, FILE_APPEND ); } /** * Log when Action Scheduler is missing. This plugin does not schedule WP-Cron events; * data refreshes are initiated by AgileTix external pings. * * @since 1.1.0 */ public function verify_action_scheduler_setup() { if ( function_exists( 'as_schedule_single_action' ) || class_exists( 'ActionScheduler', false ) ) { return; } self::agile_tix_log_event( 'Action Scheduler is not loaded. Batch post processing during refreshes requires Action Scheduler.' ); } /** * Diagnostic checks for Action Scheduler issues * Only runs in admin area * * @since 1.1.0 */ public function diagnose_action_scheduler() { // Only run for administrators if ( ! current_user_can( 'manage_options' ) ) { return; } // Only run once per admin page load static $diagnosed = false; if ( $diagnosed ) { return; } $diagnosed = true; $issues = array(); $warnings = array(); // Check if Action Scheduler is available for batch processing during refreshes. if ( ! function_exists( 'as_schedule_single_action' ) && ! class_exists( 'ActionScheduler', false ) ) { $issues[] = 'Action Scheduler is not loaded. Batch post processing will not run until Action Scheduler is available.'; } elseif ( function_exists( 'as_get_scheduled_actions' ) ) { $statuses = array( 'pending', 'in-progress', 'complete', 'failed', 'canceled' ); $all_actions_by_status = array(); foreach ( $statuses as $status ) { $all_actions_by_status[ $status ] = as_get_scheduled_actions( array( 'status' => $status, 'per_page' => -1, 'group' => 'agile_events_processing', ) ); } $pending_actions = $all_actions_by_status['pending']; $pending_count = count( $pending_actions ); if ( $pending_count > 0 ) { $warnings[] = sprintf( 'There are %d pending actions in the agile_events_processing group.', $pending_count ); foreach ( $pending_actions as $action ) { $action_id = method_exists( $action, 'get_id' ) ? $action->get_id() : 'N/A'; $hook = method_exists( $action, 'get_hook' ) ? $action->get_hook() : 'N/A'; $scheduled_timestamp = 0; if ( method_exists( $action, 'get_schedule' ) ) { $schedule = $action->get_schedule(); if ( $schedule && method_exists( $schedule, 'get_date' ) ) { $scheduled_date = $schedule->get_date(); $scheduled_timestamp = $scheduled_date ? $scheduled_date->getTimestamp() : 0; } } $now = time(); $is_overdue = $scheduled_timestamp > 0 && $scheduled_timestamp < $now; if ( $is_overdue && $action_id !== 'N/A' ) { $warnings[] = sprintf( 'Action ID %s (hook: %s) is overdue and should have executed already.', $action_id, $hook ); } } } else { $total_found = 0; foreach ( $all_actions_by_status as $actions ) { $total_found += count( $actions ); } if ( $total_found === 0 ) { $warnings[] = 'No actions found in agile_events_processing group in any status. Actions may not have been scheduled or were cleaned up.'; } } } // Log issues and warnings // if (!empty($issues)) { // foreach ($issues as $issue) { // agile_tix::agile_tix_log_event('DIAGNOSIS ISSUE: ' . $issue); // } // } // if (!empty($warnings)) { // foreach ($warnings as $warning) { // agile_tix::agile_tix_log_event('DIAGNOSIS WARNING: ' . $warning); // } // } // Store diagnostics for potential admin notice (optional) if ( ! empty( $issues ) || ! empty( $warnings ) ) { update_option( 'agile_tix_as_diagnostics', array( 'issues' => $issues, 'warnings' => $warnings, 'timestamp' => time(), ) ); } else { delete_option( 'agile_tix_as_diagnostics' ); } } }