api_handler ) ) { return; } $this->load_options(); // Instantiate handlers (Dependency Injection) $this->logger = new AINP_Status_Logger(); $this->api_handler = new AINP_Api_Handler( $this->options, $this->logger ); $this->image_handler = new AINP_Image_Handler( $this->options, $this->logger, $this->api_handler ); $this->processor = new AINP_Post_Processor( $this->options, $this->logger, $this->api_handler, $this->image_handler ); $this->cron_handler = new AINP_Cron_Handler( $this->options, $this->logger, $this->processor ); $this->ajax = new AINP_Ajax( $this ); $this->admin = new AINP_Admin( $this ); $this->define_hooks(); } /** * Loads the plugin options from the database, merging with defaults. */ public function load_options() { $this->options = get_option( 'ainp_settings', $this->get_default_options() ); // Ensure specific modules adhere to free limitations if somehow modified directly in DB $this->options['enable_auto_search'] = false; // Force disabled for Free compliance logic $this->options['module_force_ia_image'] = false; // Force disabled // Pass the loaded options to handler instances if they exist (refresh state). if ( isset( $this->api_handler ) ) { $this->api_handler->set_options( $this->options ); } if ( isset( $this->image_handler ) ) { $this->image_handler->set_options( $this->options ); } if ( isset( $this->processor ) ) { $this->processor->set_options( $this->options ); } if ( isset( $this->cron_handler ) ) { $this->cron_handler->set_options( $this->options ); } } /** * Defines all plugin hooks for WordPress. */ private function define_hooks() { // Shutdown function for fatal error catching register_shutdown_function( array( $this, 'handle_fatal_shutdown' ) ); // Initialization and Core WP Hooks add_action( 'init', array( $this, 'register_custom_post_status' ) ); add_filter( 'display_post_states', array( $this, 'add_display_post_states' ), 10, 2 ); // Admin Area Hooks add_action( 'admin_init', array( $this->cron_handler, 'check_and_trigger_overdue_cron_on_admin_load' ) ); add_action( 'admin_menu', array( $this->admin, 'admin_menu_page' ) ); add_action( 'admin_enqueue_scripts', array( $this->admin, 'enqueue_admin_scripts' ) ); // Registers all wp_ajax_* actions $this->ajax->register_ajax_hooks(); // Admin Columns (Post List) add_filter( 'manage_posts_columns', array( $this, 'add_image_column_head' ) ); add_action( 'manage_posts_custom_column', array( $this, 'add_image_column_content' ), 10, 2 ); // Cron Job Hooks add_action( AINP_AUTO_FETCH_CRON_HOOK, array( $this->cron_handler, 'execute_automatic_search_callback' ) ); add_action( AINP_GENERATE_IMAGE_HOOK, array( $this->image_handler, 'execute_image_generation_task' ), 10, 1 ); add_action( AINP_PROCESS_BATCH_HOOK, array( $this->cron_handler, 'execute_batch_item' ) ); // Shortcode and Content Filtering add_shortcode( 'ainp_native_publisher', array( $this, 'render_shortcode' ) ); add_filter( 'wp_kses_allowed_html', array( $this, 'allow_custom_html_tags' ), 10, 2 ); // Add custom cron schedules filter add_filter( 'cron_schedules', array( $this->cron_handler, 'add_custom_cron_schedules' ) ); } /** * Returns the default options for the plugin. * * @return array Default options. */ public function get_default_options() { return array( // General Settings 'sources_config' => array(), 'item_processing_timeout' => 180, 'respect_interval' => 4, 'api_request_delay' => 2, 'enable_feed_cache' => true, 'feed_cache_duration' => 300, 'default_post_status' => 'draft', 'default_author_id' => 1, 'target_language' => 'Portuguese (Brazil)', // API Settings 'main_ia_provider' => 'groq', // Default Free 'gemini_api_key' => '', 'gemini_model_selection' => 'gemini-1.5-flash-001', 'groq_api_key' => '', 'groq_model_selection' => 'llama-3.1-8b-instant', 'imagen_api_key' => '', 'imagen_project_id' => '', 'imagen_location' => 'us-central1', // Image Settings 'main_image_provider' => 'unsplash', // Default Free 'unsplash_access_key' => '', // Fetching Settings 'manual_search_depth_choice' => '1', 'manual_search_depth_custom' => 5, 'enable_auto_search' => false, 'auto_search_interval' => 'disabled', 'auto_search_depth' => '1', // Module Settings 'module_rewrite_content' => true, 'module_generate_title' => true, 'module_generate_category' => true, 'module_generate_tags' => true, 'module_generate_images' => true, 'module_force_ia_image' => false, 'module_add_watermark' => false, // Disabled in Free default 'module_source_credit' => true, 'module_keyword_filters' => false, // Advanced Settings 'enable_execution_timeout_guard' => true, 'delete_awaiting_image_on_completion' => true, 'image_processing_mode' => 'async', // Keyword Filters & Source Credits 'include_keywords' => '', 'exclude_keywords' => '', 'source_credit_format' => '
' . esc_html__( 'Source:', 'ainp-ai-native-publisher' ) . ' {source_name}
', // AI Prompts (Defaults) 'prompt_originality_prefix' => 'Act as an expert journalist. In addition to rewriting the following text, you must add a new layer of value, such as critical analysis, relevant historical context, or a unique perspective that goes beyond simple reporting.', 'prompt_rewrite' => "Rewrite the following news article in formal, neutral, and impartial language, with a minimum of 300 words. The rewrite should expand the text with relevant additional information that can be inferred from the topic. Structure the text with clear paragraphs, and **any subtitle must be formatted as a bold H2 heading (e.g., `' . esc_html__( 'No aggregated news found matching the criteria.', 'ainp-ai-native-publisher' ) . '
'; } return $output; } // --- Helper methods for dashboard stats --- public function get_total_plugin_posts_count() { global $wpdb; $count = wp_cache_get( 'ainp_total_plugin_posts_count', 'ainp-ai-native-publisher' ); if ( false === $count ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type = 'post' AND p.post_status IN ('publish', 'draft', 'pending', 'future', 'private', %s) AND pm.meta_key = '_ainp_guid'", AINP_AWAITING_IMAGE_STATUS ) ); wp_cache_set( 'ainp_total_plugin_posts_count', $count, 'ainp-ai-native-publisher', 10 * MINUTE_IN_SECONDS ); } return $count ? (int) $count : 0; } public function get_total_ia_generated_images_count() { global $wpdb; $count = wp_cache_get( 'ainp_total_ia_generated_images_count', 'ainp-ai-native-publisher' ); if ( false === $count ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value IN (%s, %s)", AINP_IMAGE_SOURCE_META_KEY, 'ia_generated', 'ia_generated_fallback' ) ); wp_cache_set( 'ainp_total_ia_generated_images_count', $count, 'ainp-ai-native-publisher', 10 * MINUTE_IN_SECONDS ); } return $count ? (int) $count : 0; } public function get_active_rss_feeds_count() { $sources = $this->options['sources_config'] ?? array(); return count( $sources ); } } /** * Begins execution of the plugin. */ function ainp_run() { return AINP_Native_Publisher::get_instance(); } add_action( 'plugins_loaded', 'ainp_run', 10 ); /** * Adds a "Settings" link to the plugin action links. */ function ainp_add_settings_link( $links ) { $settings_link = '' . __( 'Settings', 'ainp-ai-native-publisher' ) . ''; array_unshift( $links, $settings_link ); return $links; } add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'ainp_add_settings_link' );