version = SCHEMA_AI_VERSION; $this->plugin_name = 'ai-schema-gen'; $this->load_dependencies(); $this->define_admin_hooks(); $this->define_public_hooks(); $this->define_rest_api_hooks(); $this->define_cron_hooks(); $this->define_integration_hooks(); } /** * Load all required dependencies for this plugin. */ private function load_dependencies() { $dir = SCHEMA_AI_PLUGIN_DIR; // AI classes. require_once $dir . 'includes/ai/class-content-analyzer.php'; require_once $dir . 'includes/ai/class-schema-suggester.php'; require_once $dir . 'includes/ai/class-field-extractor.php'; require_once $dir . 'includes/ai/class-ai-cache.php'; // Schema classes. require_once $dir . 'includes/schema/types/class-base-schema.php'; require_once $dir . 'includes/schema/types/class-article-schema.php'; require_once $dir . 'includes/schema/types/class-product-schema.php'; require_once $dir . 'includes/schema/types/class-recipe-schema.php'; require_once $dir . 'includes/schema/types/class-local-business-schema.php'; require_once $dir . 'includes/schema/types/class-service-schema.php'; require_once $dir . 'includes/schema/types/class-faq-schema.php'; require_once $dir . 'includes/schema/types/class-howto-schema.php'; require_once $dir . 'includes/schema/types/class-event-schema.php'; require_once $dir . 'includes/schema/types/class-review-schema.php'; require_once $dir . 'includes/schema/types/class-person-schema.php'; require_once $dir . 'includes/schema/types/class-organization-schema.php'; require_once $dir . 'includes/schema/types/class-breadcrumb-schema.php'; require_once $dir . 'includes/schema/types/class-video-schema.php'; require_once $dir . 'includes/schema/types/class-image-schema.php'; require_once $dir . 'includes/schema/types/class-course-schema.php'; require_once $dir . 'includes/schema/class-schema-factory.php'; require_once $dir . 'includes/schema/class-schema-generator.php'; require_once $dir . 'includes/schema/class-schema-validator.php'; require_once $dir . 'includes/schema/class-schema-renderer.php'; require_once $dir . 'includes/schema/class-schema-cache.php'; // Extraction classes (hybrid pipeline). require_once $dir . 'includes/extraction/class-accordion-detector.php'; require_once $dir . 'includes/extraction/class-content-extractor.php'; // Page categorization and schema decision (Phase 2 + 3). require_once $dir . 'includes/class-page-analyzer.php'; require_once $dir . 'includes/class-schema-decision-engine.php'; require_once $dir . 'includes/class-author-utils.php'; // Business subtype mapping (Phase 4). require_once $dir . 'includes/class-business-subtype.php'; // Site type system (Phase 6). require_once $dir . 'includes/class-site-type.php'; // Entity authority system (Phase 7). require_once $dir . 'includes/class-entity-settings.php'; require_once $dir . 'includes/class-schema-health-score.php'; // New schema builders (Phase 6). require_once $dir . 'includes/schema/types/class-podcast-episode-schema.php'; require_once $dir . 'includes/schema/types/class-software-application-schema.php'; require_once $dir . 'includes/schema/types/class-creative-work-schema.php'; // Automation classes. require_once $dir . 'includes/automation/class-auto-apply.php'; require_once $dir . 'includes/automation/class-scheduler.php'; require_once $dir . 'includes/automation/class-rule-engine.php'; // Integration classes (6 files). require_once $dir . 'includes/integrations/class-woocommerce.php'; require_once $dir . 'includes/integrations/class-elementor.php'; require_once $dir . 'includes/integrations/class-gutenberg.php'; require_once $dir . 'includes/integrations/class-yoast.php'; require_once $dir . 'includes/integrations/class-rank-math.php'; require_once $dir . 'includes/integrations/class-acf.php'; // API classes. require_once $dir . 'includes/api/class-rest-controller.php'; require_once $dir . 'includes/api/class-api-auth.php'; require_once $dir . 'includes/api/endpoints/class-schema-endpoint.php'; require_once $dir . 'includes/api/endpoints/class-generate-endpoint.php'; require_once $dir . 'includes/api/endpoints/class-validate-endpoint.php'; require_once $dir . 'includes/api/endpoints/class-analyze-endpoint.php'; require_once $dir . 'includes/api/endpoints/class-templates-endpoint.php'; require_once $dir . 'includes/api/endpoints/class-stats-endpoint.php'; // Sync engine. require_once $dir . 'includes/class-sync.php'; require_once $dir . 'includes/class-restore.php'; // Bulk generator. require_once $dir . 'includes/class-bulk-generator.php'; // Utility classes. require_once $dir . 'includes/utilities/class-logger.php'; require_once $dir . 'includes/utilities/class-rate-limiter.php'; require_once $dir . 'includes/utilities/class-usage-tracker.php'; require_once $dir . 'includes/utilities/class-notifications.php'; // Admin. require_once $dir . 'admin/class-admin.php'; require_once $dir . 'admin/class-promo-banner.php'; require_once $dir . 'admin/class-deactivation-feedback.php'; // Public. require_once $dir . 'public/class-public.php'; require_once $dir . 'public/class-schema-output.php'; $this->loader = new Schema_AI_Loader(); } /** * Register all admin-related hooks. */ private function define_admin_hooks() { $admin = new Schema_AI_Admin( $this->get_plugin_name(), $this->get_version() ); new Schema_AI_Promo_Banner(); new Schema_AI_Deactivation_Feedback(); // Admin menu and pages. $this->loader->add_action( 'admin_menu', $admin, 'add_admin_menu' ); $this->loader->add_action( 'admin_enqueue_scripts', $admin, 'enqueue_styles' ); $this->loader->add_action( 'admin_enqueue_scripts', $admin, 'enqueue_scripts' ); // Meta box for post editor. $this->loader->add_action( 'add_meta_boxes', $admin, 'add_schema_meta_box' ); $this->loader->add_action( 'save_post', $admin, 'save_schema_meta_box', 10, 2 ); // Admin notices (constructor self-registers hooks). new Schema_AI_Notifications(); // Plugin action links. $this->loader->add_filter( 'plugin_action_links_' . SCHEMA_AI_PLUGIN_BASENAME, $admin, 'add_action_links' ); // Admin bar "Generate Schema" button on frontend. $this->loader->add_action( 'admin_bar_menu', $admin, 'add_admin_bar_generate', 100 ); $this->loader->add_action( 'wp_enqueue_scripts', $admin, 'enqueue_admin_bar_script' ); // One-time migration: validate any schemas still stuck in "pending" status. $this->loader->add_action( 'admin_init', $this, 'maybe_validate_pending_schemas' ); // Auto-apply on post status transition. $auto_apply = new Schema_AI_Auto_Apply(); $this->loader->add_action( 'transition_post_status', $auto_apply, 'on_publish', 10, 3 ); } /** * Register all public-facing hooks. */ private function define_public_hooks() { $public = new Schema_AI_Public( $this->get_plugin_name(), $this->get_version() ); $this->loader->add_action( 'wp_enqueue_scripts', $public, 'enqueue_styles' ); $this->loader->add_action( 'wp_enqueue_scripts', $public, 'enqueue_scripts' ); // Schema JSON-LD output in wp_head. $schema_output = new Schema_AI_Schema_Output(); $this->loader->add_action( 'wp_head', $schema_output, 'render_schema_json_ld', 1 ); } /** * Register all REST API hooks. */ private function define_rest_api_hooks() { // Schema CRUD endpoint. $schema_endpoint = new Schema_AI_Schema_Endpoint(); $this->loader->add_action( 'rest_api_init', $schema_endpoint, 'register_routes' ); // AI Generate endpoint. $generate_endpoint = new Schema_AI_Generate_Endpoint(); $this->loader->add_action( 'rest_api_init', $generate_endpoint, 'register_routes' ); // Validate endpoint. $validate_endpoint = new Schema_AI_Validate_Endpoint(); $this->loader->add_action( 'rest_api_init', $validate_endpoint, 'register_routes' ); // Analyze endpoint. $analyze_endpoint = new Schema_AI_Analyze_Endpoint(); $this->loader->add_action( 'rest_api_init', $analyze_endpoint, 'register_routes' ); // Templates endpoint. $templates_endpoint = new Schema_AI_Templates_Endpoint(); $this->loader->add_action( 'rest_api_init', $templates_endpoint, 'register_routes' ); // Stats endpoint. $stats_endpoint = new Schema_AI_Stats_Endpoint(); $this->loader->add_action( 'rest_api_init', $stats_endpoint, 'register_routes' ); } /** * Register all cron event hooks. */ private function define_cron_hooks() { $scheduler = new Schema_AI_Scheduler(); $this->loader->add_action( 'schema_ai_daily_cleanup', $scheduler, 'daily_cleanup' ); $this->loader->add_action( 'schema_ai_usage_reset', $scheduler, 'usage_reset' ); $this->loader->add_action( 'schema_ai_analytics_sync', $scheduler, 'analytics_sync' ); $this->loader->add_action( 'schema_ai_validate', $scheduler, 'validate_schema', 10, 1 ); $this->loader->add_action( 'schema_ai_bulk_validate', $scheduler, 'bulk_validate' ); // Sync engine: 6-hour full sync + immediate single-page sync. $sync = new Schema_AI_Sync(); // Register the interval directly so it exists when schedule() validates it via wp_get_schedules(). // The loader only queues hooks — they aren't applied until run() — so we must bypass it here. add_filter( 'cron_schedules', array( $sync, 'add_cron_interval' ), 10, 1 ); Schema_AI_Sync::schedule(); $this->loader->add_action( Schema_AI_Sync::CRON_HOOK, $sync, 'run_sync' ); $this->loader->add_action( 'schema_ai_sync_single', $sync, 'run_single_sync', 10, 1 ); $this->loader->add_action( 'schema_ai_schema_saved', $sync, 'on_schema_saved', 10, 1 ); // Two-way entity sync: // - Stamp a local change timestamp whenever the entity profile is edited // on this site, so the backend can tell which side is newer. // - On wp-admin loads, pull the latest dashboard-side profile (throttled) // so dashboard edits appear here without waiting for the 6-hour cron. $this->loader->add_action( 'update_option_schema_ai_settings', 'Schema_AI_Entity_Settings', 'track_change', 10, 2 ); $this->loader->add_action( 'add_option_schema_ai_settings', 'Schema_AI_Entity_Settings', 'track_change', 10, 2 ); $this->loader->add_action( 'admin_init', $sync, 'maybe_pull_on_admin' ); // Restore-on-reinstall: fires when an API key is configured on an // otherwise-empty install (fresh install, or uninstall + reinstall). new Schema_AI_Restore(); // Bulk generator: 15-second poll + rapid per-page hook. $bulk = new Schema_AI_Bulk_Generator(); // Same: register the interval directly so schema_ai_15sec exists before schedule() calls wp_schedule_event(). add_filter( 'cron_schedules', array( $bulk, 'add_cron_interval' ), 10, 1 ); Schema_AI_Bulk_Generator::schedule(); $this->loader->add_action( Schema_AI_Bulk_Generator::POLL_HOOK, $bulk, 'process_next' ); $this->loader->add_action( Schema_AI_Bulk_Generator::NEXT_HOOK, $bulk, 'process_next' ); } /** * Register all third-party integration hooks. */ private function define_integration_hooks() { // WooCommerce integration. $woocommerce = new Schema_AI_WooCommerce(); $this->loader->add_action( 'woocommerce_loaded', $woocommerce, 'init' ); // Elementor integration. $elementor = new Schema_AI_Elementor(); $this->loader->add_action( 'elementor/loaded', $elementor, 'init' ); // Gutenberg: block editor integration not yet active (assets not built). // Yoast SEO: suppress all schema output. $yoast = new Schema_AI_Yoast(); $this->loader->add_filter( 'wpseo_json_ld_output', $yoast, 'filter_yoast_schema', PHP_INT_MAX, 1 ); // Rank Math: suppress all schema output across every output path. // 1. rank_math/json_ld — main head-level schema graph. // 2. the_content — FAQ blocks rendered inline in content (Gutenberg + Elementor). // 3. wp_footer — secondary schema some Rank Math versions inject in the footer. $rank_math = new Schema_AI_Rank_Math(); $this->loader->add_filter( 'rank_math/json_ld', $rank_math, 'filter_rank_math_schema', PHP_INT_MAX, 2 ); $this->loader->add_filter( 'the_content', $rank_math, 'suppress_content_schema', PHP_INT_MAX ); $this->loader->add_action( 'wp_footer', $rank_math, 'start_footer_buffer', 1 ); $this->loader->add_action( 'wp_footer', $rank_math, 'flush_footer_buffer', PHP_INT_MAX ); // AIOSEO: suppress all schema output. $this->loader->add_filter( 'aioseo_schema_output', '__return_empty_array', PHP_INT_MAX ); // ACF integration. $acf = new Schema_AI_ACF(); $this->loader->add_action( 'acf/init', $acf, 'init' ); } /** * Run the loader to execute all hooks. */ public function run() { $this->loader->run(); } /** * The name of the plugin. * * @return string */ public function get_plugin_name() { return $this->plugin_name; } /** * The reference to the loader class. * * @return Schema_AI_Loader */ public function get_loader() { return $this->loader; } /** * Retrieve the version number of the plugin. * * @return string */ public function get_version() { return $this->version; } /** * Validate any schemas stuck in "pending" status. * * Runs once via an option flag, then skips on subsequent page loads. */ public function maybe_validate_pending_schemas() { $migrated = get_option( 'schema_ai_pending_migrated', false ); if ( $migrated ) { return; } global $wpdb; $table = esc_sql( $wpdb->prefix . 'schema_ai_schemas' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Required for custom table; no WP API alternative exists. $pending = $wpdb->get_results( $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is sanitized via esc_sql() and not user input. "SELECT id, schema_data FROM {$table} WHERE validation_status = %s LIMIT 100", 'pending' ) ); if ( $pending ) { foreach ( $pending as $row ) { $schema = json_decode( $row->schema_data, true ); $status = 'invalid'; if ( is_array( $schema ) && ! empty( $schema['@type'] ) ) { $has_context = ! empty( $schema['@context'] ); $has_name = ! empty( $schema['name'] ) || ! empty( $schema['headline'] ); if ( $has_context && $has_name ) { $status = 'valid'; } elseif ( $has_context || $has_name ) { $status = 'warning'; } } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Required for custom table; write operation (UPDATE), caching not applicable. $wpdb->update( $table, array( 'validation_status' => $status ), array( 'id' => $row->id ), array( '%s' ), array( '%d' ) ); } } update_option( 'schema_ai_pending_migrated', true ); } }