*/ class All_Sources_Images_Admin { /** * The ID of this plugin. * * @since 4.0.0 * @access private * @var string $plugin_name The ID of this plugin. */ private $plugin_name; /** * The version of this plugin. * * @since 4.0.0 * @access private * @var string $version The current version of this plugin. */ private $version; /** * Hook suffix for the Media submenu page. * * @var string */ private $media_picker_hook = ''; /** * Hook suffix for the top-level media browser page. * * @var string */ private $media_picker_top_level_hook = ''; /** * Hook suffix for the Search submenu under the plugin menu. * * @var string */ private $media_picker_search_submenu_hook = ''; /** * Default post ID for media picker. * * @since 6.1.8 * @var int */ private $media_picker_default_post_id = 0; /** * Initialize the class and set its properties. * * @since 4.0.0 * @param string $plugin_name The name of this plugin. * @param string $version The version of this plugin. */ public function __construct( $plugin_name, $version ) { $this->plugin_name = $plugin_name; $this->version = $version; $ALLSI_generation = $this->ALLSI_generation_features(); // Cron settings for scheduled generation $cron_options = wp_parse_args( get_option( 'ALLSI_plugin_cron_settings' ) ); // Register cron hook for automated image generation add_action( 'ALLSI_cron_image_generation', array(&$this, 'ALLSI_execute_cron_generation') ); // Register hook for scheduled image generation (used by plugin integrations) add_action( 'ALLSI_generate_scheduled_image', array(&$this, 'ALLSI_generate_scheduled_image') ); // Robust publish hooks for automatic image generation on publish. add_action( 'transition_post_status', array( $this, 'ALLSI_auto_image_transition_post_status' ), 20, 3 ); add_action( 'wp_after_insert_post', array( $this, 'ALLSI_auto_image_after_insert_post' ), 20, 4 ); // Testing APIs function with Ajax call add_action( 'wp_ajax_allsi_test_apis', array(&$this, 'ALLSI_test_apis') ); /* Gutenberg Block */ // Scripts for Block & Translations add_action( 'init', array(&$this, 'ALLSI_register_mpt_block') ); add_action( 'enqueue_block_editor_assets', array(&$this, 'ALLSI_enqueue_style_block') ); // Register media picker page only once (avoid duplicates from multiple class instances) static $media_picker_registered = false; if ( ! $media_picker_registered ) { add_action( 'admin_menu', array( $this, 'ALLSI_register_media_picker_page' ) ); $media_picker_registered = true; } add_action( 'admin_enqueue_scripts', array( $this, 'ALLSI_enqueue_media_picker_assets' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'ALLSI_enqueue_media_modal_assets' ) ); add_action( 'enqueue_block_editor_assets', array( $this, 'ALLSI_enqueue_media_modal_assets' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'ALLSI_enqueue_front_media_modal_assets' ) ); // Gutenberg Block : Translate search term (called once before searching multiple banks) add_action( 'wp_ajax_allsi_translate_search', array(&$this, 'ALLSI_translate_search_ajax') ); // Gutenberg Block : Searching images with APIs add_action( 'wp_ajax_allsi_block_searching_images', array(&$this, 'ALLSI_block_searching_images') ); // Gutenberg Block : Download images from APIs add_action( 'wp_ajax_allsi_block_downloading_image', array(&$this, 'ALLSI_block_downloading_image') ); // Log viewer actions (Others > Logging) add_action( 'wp_ajax_allsi_get_log_contents', array( $this, 'ALLSI_get_log_contents_ajax' ) ); add_action( 'wp_ajax_allsi_clear_log', array( $this, 'ALLSI_clear_log_ajax' ) ); // Extend timeout request for wp_remote_request() with dalle $options_banks = wp_parse_args( get_option( 'ALLSI_plugin_banks_settings' ), $this->ALLSI_default_options_banks_settings( TRUE ) ); if ( isset( $options_banks['api_chosen_auto'] ) && true === in_array( 'dallev1', $options_banks['api_chosen_auto'] ) ) { add_filter( 'http_request_timeout', array(&$this, 'ALLSI_custom_http_request_timeout') ); } // Migration v5 to v6 add_action( 'init', array(&$this, 'ALLSI_migration') ); add_action( 'plugins_loaded', array( $this, 'ALLSI_maybe_boot_elementor' ), 20 ); if ( did_action( 'elementor/loaded' ) ) { $this->ALLSI_maybe_boot_elementor(); } else { add_action( 'elementor/init', array( $this, 'ALLSI_maybe_boot_elementor' ) ); } } /** * Trigger the automatic image generation process upon saving a post * * @since 5.0.0 * @access public */ public function ALLSI_trigger_save_post() { $log = $this->ALLSI_monolog_call(); $log->info( 'Launch Automatic plugin' ); //$automatic_generation = new All_Sources_Images_Generation($this->plugin_name, $this->version); // Add a callback function to the save_post action to handle image generation add_action( 'save_post', function ( $post_id ) { // Skip if this is an autosave if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } // Skip if this is a revision if ( wp_is_post_revision( $post_id ) ) { return; } // Check if WPeMatico campaign_fetch class is active (it's instantiated during feed processing) if ( class_exists( 'wpematico_campaign_fetch' ) ) { return; } // Check if we're in a WPeMatico cron/ajax context if ( defined( 'WPEMATICO_VERSION' ) && ( doing_action( 'wpematico_cron' ) || did_action( 'wpematico_init_fetching' ) || did_action( 'Wpematico_init_fetching' ) ) ) { return; } // Skip if triggered by FeedWordPress if ( class_exists( 'FeedWordPress' ) && doing_action( 'syndicated_item' ) ) { return; } // Check if we already scheduled generation for this post (prevents duplicates) $transient_key = 'ALLSI_scheduled_' . $post_id; if ( get_transient( $transient_key ) ) { return; } set_transient( $transient_key, true, 120 ); // Schedule a single event with a delay to avoid conflicts wp_schedule_single_event( time() + 5, // 5 seconds apart for each block 'ALLSI_generate_scheduled_image', array($post_id) ); } ); } /** * Generate images for all blocks when called by the scheduled event * Uses post meta flags per image block to prevent duplicates * * @since 6.0.0 * @access public */ public function ALLSI_generate_scheduled_image( $post_id ) { $post_id = absint( $post_id ); $log = $this->ALLSI_monolog_call(); $log->info( '=== SCHEDULED GENERATION START for post ID: ' . $post_id . ' ===' ); if ( 0 === $post_id ) { $log->info( 'Invalid post ID, exiting scheduled generation' ); return; } // Always clear queue lock for this post when the scheduled task starts. delete_transient( 'ALLSI_auto_image_queued_' . $post_id ); if ( ! $this->ALLSI_auto_image_should_process_post( $post_id ) ) { $log->info( 'Post does not match Auto Image filters, exiting' ); return; } // Retrieve main settings from the plugin options $main_settings = get_option( 'ALLSI_plugin_main_settings' ); $img_blocks = isset( $main_settings['image_block'] ) ? $main_settings['image_block'] : array(); if ( empty( $img_blocks ) ) { $log->info( 'No image blocks configured, exiting' ); return; } // Check rewrite_featured setting $rewrite_featured = isset( $main_settings['rewrite_featured'] ) && $main_settings['rewrite_featured'] === 'true'; $log->info( 'Rewrite featured setting: ' . ( $rewrite_featured ? 'enabled' : 'disabled' ) ); $automatic_generation = new All_Sources_Images_Generation($this->plugin_name, $this->version); // Iterate through each image block foreach ( $img_blocks as $key_img_block => $img_block ) { $meta_key = '_ALLSI_block_' . $key_img_block . '_status'; $current_status = get_post_meta( $post_id, $meta_key, true ); $log->info( 'Block ' . $key_img_block . ' status: ' . ( $current_status ?: 'empty' ) ); // Skip if already completed or in progress if ( $current_status === 'completed' ) { $log->info( 'Block ' . $key_img_block . ' already completed, skipping' ); continue; } if ( $current_status === 'processing' ) { // Check if processing started more than 2 minutes ago (stuck process) $started_at = get_post_meta( $post_id, '_ALLSI_block_' . $key_img_block . '_started', true ); if ( $started_at && ( time() - intval( $started_at ) ) < 120 ) { $log->info( 'Block ' . $key_img_block . ' is being processed by another instance, skipping' ); continue; } $log->info( 'Block ' . $key_img_block . ' was stuck, retrying' ); } // Mark as processing with timestamp update_post_meta( $post_id, $meta_key, 'processing' ); update_post_meta( $post_id, '_ALLSI_block_' . $key_img_block . '_started', time() ); $log->info( 'Starting generation for block ' . $key_img_block ); try { // Generate the image for this specific block $automatic_generation->ALLSI_create_thumb( $post_id, 0, // $check_value_enable 1, // $check_post_type 1, // $check_category $rewrite_featured, // $rewrite_featured - pass the setting! false, null, null, $key_img_block, true ); // Mark as completed update_post_meta( $post_id, $meta_key, 'completed' ); delete_post_meta( $post_id, '_ALLSI_block_' . $key_img_block . '_started' ); $log->info( 'Block ' . $key_img_block . ' completed successfully' ); } catch ( Exception $e ) { // Mark as failed so it can be retried update_post_meta( $post_id, $meta_key, 'failed' ); $log->error( 'Block ' . $key_img_block . ' failed: ' . $e->getMessage() ); } } $log->info( '=== SCHEDULED GENERATION END for post ID: ' . $post_id . ' ===' ); } /** * Schedule auto image generation when a post transitions to publish. * * @param string $new_status New post status. * @param string $old_status Old post status. * @param WP_Post $post Post object. */ public function ALLSI_auto_image_transition_post_status( $new_status, $old_status, $post ) { if ( 'publish' !== $new_status || 'publish' === $old_status ) { return; } if ( ! ( $post instanceof WP_Post ) ) { return; } $this->ALLSI_auto_image_schedule_post( $post->ID, 'transition_post_status' ); } /** * Fallback publish trigger for importers and integrations that bypass the classic editor flow. * * @param int $post_id Post ID. * @param WP_Post $post Post object. * @param bool $update Whether this is an existing post being updated. * @param WP_Post|null $post_before Previous post object. */ public function ALLSI_auto_image_after_insert_post( $post_id, $post, $update, $post_before ) { if ( ! ( $post instanceof WP_Post ) ) { return; } if ( 'publish' !== $post->post_status ) { return; } // Skip normal content updates that were already published before. if ( true === (bool) $update && ( $post_before instanceof WP_Post ) && 'publish' === $post_before->post_status ) { return; } $this->ALLSI_auto_image_schedule_post( $post_id, 'wp_after_insert_post' ); } /** * Queue a single delayed event for image generation. * * @param int $post_id Post ID. * @param string $reason Hook name used for logging. */ private function ALLSI_auto_image_schedule_post( $post_id, $reason = '' ) { $post_id = absint( $post_id ); if ( 0 === $post_id ) { return; } if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) { return; } if ( ! $this->ALLSI_auto_image_should_process_post( $post_id ) ) { return; } $transient_key = 'ALLSI_auto_image_queued_' . $post_id; if ( get_transient( $transient_key ) ) { return; } if ( wp_next_scheduled( 'ALLSI_generate_scheduled_image', array( $post_id ) ) ) { return; } set_transient( $transient_key, true, 120 ); wp_schedule_single_event( time() + 5, 'ALLSI_generate_scheduled_image', array( $post_id ) ); $log = $this->ALLSI_monolog_call(); $log->info( 'Auto image scheduled', array( 'post_id' => $post_id, 'reason' => sanitize_text_field( (string) $reason ), ) ); } /** * Validate if a post matches Auto Image publish filters. * * @param int|WP_Post $post Post object or post ID. * @return bool */ private function ALLSI_auto_image_should_process_post( $post ) { if ( ! ( $post instanceof WP_Post ) ) { $post = get_post( $post ); } if ( ! ( $post instanceof WP_Post ) ) { return false; } if ( wp_is_post_revision( $post->ID ) || wp_is_post_autosave( $post->ID ) ) { return false; } if ( 'publish' !== $post->post_status ) { return false; } $options = wp_parse_args( get_option( 'ALLSI_plugin_auto_image_settings' ), $this->ALLSI_default_options_auto_image_settings( true ) ); if ( empty( $options['enabled'] ) || 'enable' !== $options['enabled'] ) { return false; } $allowed_post_types = array(); if ( ! empty( $options['post_types'] ) && is_array( $options['post_types'] ) ) { $allowed_post_types = array_values( array_unique( array_filter( array_map( 'sanitize_key', $options['post_types'] ) ) ) ); } if ( ! empty( $allowed_post_types ) && ! in_array( $post->post_type, $allowed_post_types, true ) ) { return false; } $excluded_ids = $this->ALLSI_auto_image_parse_ids( isset( $options['exclude_post_ids'] ) ? $options['exclude_post_ids'] : '' ); if ( in_array( $post->ID, $excluded_ids, true ) ) { return false; } $selected_term_ids = array(); if ( ! empty( $options['term_ids'] ) && is_array( $options['term_ids'] ) ) { $selected_term_ids = array_values( array_unique( array_filter( array_map( 'absint', $options['term_ids'] ) ) ) ); } if ( ! empty( $selected_term_ids ) ) { $taxonomies = get_object_taxonomies( $post->post_type, 'names' ); if ( empty( $taxonomies ) ) { return false; } $post_term_ids = wp_get_post_terms( $post->ID, $taxonomies, array( 'fields' => 'ids' ) ); if ( is_wp_error( $post_term_ids ) || empty( $post_term_ids ) ) { return false; } $post_term_ids = array_map( 'absint', $post_term_ids ); if ( empty( array_intersect( $selected_term_ids, $post_term_ids ) ) ) { return false; } } return true; } /** * Parse a comma-separated list of IDs and return unique integers. * * @param string $ids_raw Raw CSV string. * @return array */ private function ALLSI_auto_image_parse_ids( $ids_raw ) { if ( ! is_string( $ids_raw ) || '' === trim( $ids_raw ) ) { return array(); } preg_match_all( '/\d+/', $ids_raw, $matches ); if ( empty( $matches[0] ) ) { return array(); } return array_values( array_unique( array_filter( array_map( 'absint', $matches[0] ) ) ) ); } /** * Clear ASI block status meta for a post (useful for re-generation) * * @param int $post_id The post ID. */ public function clear_block_status( $post_id ) { $post_id = absint( $post_id ); if ( 0 === $post_id ) { return; } $all_meta = get_post_meta( $post_id ); if ( empty( $all_meta ) || ! is_array( $all_meta ) ) { return; } foreach ( array_keys( $all_meta ) as $meta_key ) { if ( 0 === strpos( (string) $meta_key, '_ALLSI_block_' ) ) { delete_post_meta( $post_id, $meta_key ); } } } /** * Execute cron-based automated image generation * Called by WordPress cron hook 'ALLSI_cron_image_generation' * * @since 6.1.7 * @access public */ public function ALLSI_execute_cron_generation() { $log = $this->ALLSI_monolog_call(); $log->info( 'Starting cron image generation' ); // Get cron settings $cron_options = get_option( 'ALLSI_plugin_cron_settings' ); // Verify cron is enabled if ( !isset( $cron_options['enable_cron'] ) || $cron_options['enable_cron'] !== 'enable' ) { $log->info( 'Cron is disabled, exiting' ); return; } // Get post types to process $post_types = isset( $cron_options['cron_post_types'] ) ? $cron_options['cron_post_types'] : array( 'post' ); // Get posts per run $posts_per_run = isset( $cron_options['posts_per_run'] ) ? absint( $cron_options['posts_per_run'] ) : 5; // Build date query $date_query = array(); if ( isset( $cron_options['posts_date_mode'] ) && $cron_options['posts_date_mode'] === 'relative' ) { $date_value = isset( $cron_options['posts_date_value'] ) ? absint( $cron_options['posts_date_value'] ) : 5; $date_unit = isset( $cron_options['posts_date_unit'] ) ? $cron_options['posts_date_unit'] : 'days'; $date_query = array( array( 'after' => $date_value . ' ' . $date_unit . ' ago', 'inclusive' => true, ), ); } // Query posts without featured images $args = array( 'post_type' => $post_types, 'posts_per_page' => $posts_per_run, 'post_status' => 'publish', 'meta_query' => array( array( 'key' => '_thumbnail_id', 'compare' => 'NOT EXISTS', ), ), 'orderby' => 'date', 'order' => 'DESC', ); if ( !empty( $date_query ) ) { $args['date_query'] = $date_query; } $query = new WP_Query( $args ); $log->info( 'Found ' . $query->found_posts . ' posts without featured images' ); if ( $query->have_posts() ) { $automatic_generation = new All_Sources_Images_Generation( $this->plugin_name, $this->version ); $main_settings = get_option( 'ALLSI_plugin_main_settings' ); $img_blocks = isset( $main_settings['image_block'] ) ? $main_settings['image_block'] : array(); while ( $query->have_posts() ) { $query->the_post(); $post_id = get_the_ID(); $log->info( 'Processing post ID: ' . $post_id ); // Process each image block for this post foreach ( $img_blocks as $key_img_block => $img_block ) { $automatic_generation->ALLSI_create_thumb( $post_id, 0, 1, 1, 0, false, null, null, $key_img_block, true ); } } wp_reset_postdata(); } $log->info( 'Cron image generation completed' ); } /** * Trigger when hook wp_insert_post is fired * * @since 5.0.3 * @access public */ public function ALLSI_trigger_wp_insert_post( $post_ID ) { } public function ALLSI_trigger_wp_automatic( $post_data ) { $log = $this->ALLSI_monolog_call(); $log->info( 'Launch WordPress Automatic Plugin' ); $automatic_generation = new All_Sources_Images_Generation($this->plugin_name, $this->version); $main_settings = get_option( 'ALLSI_plugin_main_settings' ); $img_blocks = $main_settings['image_block']; foreach ( $img_blocks as $key_img_block => $img_block ) { $automatic_generation->ALLSI_create_thumb( $post_data['post_id'], '0', '1', '1', '0', false, null, null, $key_img_block, false ); } } /** * Register all of the hooks related to the admin area functionality * of the plugin. * * @since 4.0.0 * @access private */ private function ALLSI_generation_features() { $ALLSI_generation = new All_Sources_Images_Generation($this->plugin_name, $this->version); return $ALLSI_generation; } /** * Get proxy configuration for HTTP requests * Returns proxy args to merge with wp_remote_get/wp_remote_post args * * @since 6.1.7 * @return array Proxy configuration array */ // Cloudflare Worker constants (hardcoded for automatic fallback) const ALLSI_CLOUDFLARE_WORKER_URL = 'https://noisy-heart-6060.estebandezafra.workers.dev'; const ALLSI_CLOUDFLARE_WORKER_TOKEN = 'TTSHFHRwllzM1RDctruMT0daz4sYmTKAj1V3y8VFlL6mVwdt4oYWWolwYrvLz1PS'; // Sources that support automatic Cloudflare fallback when no API key is configured const ALLSI_CLOUDFLARE_FALLBACK_SOURCES = array( 'pixabay', 'pexels', 'unsplash', 'flickr', 'giphy' ); public function ALLSI_get_proxy_args() { $proxy_options = $this->ALLSI_get_proxy_settings(); // Only return proxy args if legacy proxy is enabled and configured if ( empty( $proxy_options['enable_proxy'] ) || 'enable' !== $proxy_options['enable_proxy'] ) { return array(); } if ( empty( $proxy_options['proxy_address'] ) ) { return array(); } $proxy_host = preg_replace( '#^https?://#i', '', trim( $proxy_options['proxy_address'] ) ); $proxy_port = ! empty( $proxy_options['proxy_port'] ) ? $proxy_options['proxy_port'] : '80'; $proxy_url = $proxy_host . ':' . $proxy_port; if ( ! empty( $proxy_options['proxy_username'] ) && ! empty( $proxy_options['proxy_password'] ) ) { $proxy_url = $proxy_options['proxy_username'] . ':' . $proxy_options['proxy_password'] . '@' . $proxy_url; } return array( 'proxy' => 'https://' . $proxy_url, ); } private function ALLSI_get_proxy_settings() { static $cache = null; if ( null === $cache ) { $cache = wp_parse_args( get_option( 'ALLSI_plugin_proxy_settings' ), $this->ALLSI_default_options_proxy_settings( false ) ); } return $cache; } /** * Check if a source supports Cloudflare fallback */ public function ALLSI_source_supports_cloudflare_fallback( $service ) { return in_array( $service, self::ALLSI_CLOUDFLARE_FALLBACK_SOURCES, true ); } /** * Check if legacy proxy is enabled by user */ public function ALLSI_is_legacy_proxy_enabled() { $options = $this->ALLSI_get_proxy_settings(); return ! empty( $options['enable_proxy'] ) && 'enable' === $options['enable_proxy'] && ! empty( $options['proxy_address'] ); } public function ALLSI_current_proxy_mode() { // For backward compatibility - now only returns 'legacy' or 'disabled' $options = $this->ALLSI_get_proxy_settings(); if ( ! empty( $options['enable_proxy'] ) && 'enable' === $options['enable_proxy'] ) { return 'legacy'; } return 'disabled'; } /** * Get Cloudflare Worker bootstrap configuration (uses hardcoded constants) */ private function ALLSI_get_cloudflare_bootstrap() { return array( 'worker_url' => self::ALLSI_CLOUDFLARE_WORKER_URL, 'token' => self::ALLSI_CLOUDFLARE_WORKER_TOKEN, ); } private function ALLSI_get_cloudflare_service_map() { return array( 'pixabay' => array( 'key_location' => 'query', 'key_name' => 'key' ), 'pexels' => array( 'key_location' => 'header', 'key_name' => 'Authorization' ), 'unsplash' => array( 'key_location' => 'header', 'key_name' => 'Authorization' ), 'giphy' => array( 'key_location' => 'query', 'key_name' => 'api_key' ), 'flickr' => array( 'key_location' => 'query', 'key_name' => 'api_key' ), 'openverse' => array( 'key_location' => 'none' ), 'cc_search' => array( 'key_location' => 'none' ), 'youtube' => array( 'key_location' => 'query', 'key_name' => 'key' ), 'google_image' => array( 'key_location' => 'query', 'key_name' => 'key' ), 'pixabay_video' => array( 'key_location' => 'query', 'key_name' => 'key' ), 'dallev1' => array( 'key_location' => 'header', 'key_name' => 'Authorization' ), 'stability' => array( 'key_location' => 'header', 'key_name' => 'Authorization' ), 'replicate' => array( 'key_location' => 'header', 'key_name' => 'Authorization' ), 'gemini' => array( 'key_location' => 'query', 'key_name' => 'key' ), 'workers_ai' => array( 'key_location' => 'header', 'key_name' => 'Authorization' ), 'google_translate'=> array( 'key_location' => 'query', 'key_name' => 'key' ), 'cloudflare_ai' => array( 'key_location' => 'header', 'key_name' => 'Authorization' ), ); } private function ALLSI_strip_credentials_from_request( $service, &$url, array &$args ) { $map = $this->ALLSI_get_cloudflare_service_map(); if ( empty( $map[ $service ] ) ) { return; } $config = $map[ $service ]; if ( 'header' === $config['key_location'] && ! empty( $config['key_name'] ) ) { if ( isset( $args['headers'][ $config['key_name'] ] ) ) { unset( $args['headers'][ $config['key_name'] ] ); } } if ( 'query' === $config['key_location'] && ! empty( $config['key_name'] ) ) { $url = remove_query_arg( $config['key_name'], $url ); } } private function ALLSI_merge_http_args( array $base, array $extra ) { if ( empty( $extra ) ) { return $base; } if ( isset( $extra['headers'] ) ) { if ( isset( $base['headers'] ) && is_array( $base['headers'] ) ) { $base['headers'] = array_merge( $base['headers'], $extra['headers'] ); } else { $base['headers'] = $extra['headers']; } unset( $extra['headers'] ); } return array_merge( $base, $extra ); } private function ALLSI_prepare_http_args( array $args ) { if ( empty( $args['method'] ) ) { $args['method'] = 'GET'; } $args['method'] = strtoupper( $args['method'] ); return $args; } private function ALLSI_remote_request_via_cloudflare( $service, $url, array $args ) { $bootstrap = $this->ALLSI_get_cloudflare_bootstrap(); $worker_url = untrailingslashit( $bootstrap['worker_url'] ); // Use URL-safe base64 encoding: replace + with -, / with _, remove = $encoded_url_b64 = rtrim( strtr( base64_encode( $url ), '+/', '-_' ), '=' ); $final_url = add_query_arg( array( 'servicio' => $service, 'token' => $bootstrap['token'], 'url_b64' => $encoded_url_b64, ), $worker_url ); unset( $args['proxy'] ); return wp_remote_request( $final_url, $args ); } /** * Main remote request function * * Logic: * 1. If source supports Cloudflare fallback AND use_cloudflare_fallback is true -> use Cloudflare * 2. If legacy proxy is enabled -> use legacy proxy * 3. Otherwise -> direct request */ public function ALLSI_remote_request( $service, $url, array $args = array(), $use_cloudflare_fallback = false ) { $args = $this->ALLSI_prepare_http_args( $args ); // Check if we should use Cloudflare fallback (source has no API key configured) if ( $use_cloudflare_fallback && $this->ALLSI_source_supports_cloudflare_fallback( $service ) ) { return $this->ALLSI_remote_request_via_cloudflare( $service, $url, $args ); } // Apply legacy proxy if enabled $proxy_args = $this->ALLSI_get_proxy_args(); $args = $this->ALLSI_merge_http_args( $args, $proxy_args ); return wp_remote_request( $url, $args ); } public function ALLSI_remote_get( $service, $url, array $args = array(), $use_cloudflare_fallback = false ) { $args['method'] = 'GET'; return $this->ALLSI_remote_request( $service, $url, $args, $use_cloudflare_fallback ); } public function ALLSI_remote_post( $service, $url, array $args = array(), $use_cloudflare_fallback = false ) { $args['method'] = 'POST'; return $this->ALLSI_remote_request( $service, $url, $args, $use_cloudflare_fallback ); } /** * Register the stylesheets for the admin area. * * @since 4.0.0 */ public function enqueue_styles( $hook ) { // Post Editor if ( $hook == 'post.php' || $hook == 'post-new.php' ) { wp_enqueue_style( 'mpt-post', plugin_dir_url( __FILE__ ) . 'css/all-sources-images-post.css', array(), $this->version, 'all' ); } // ASI Admin Pages (new UI) $ALLSI_pages = array( 'toplevel_page_allsi-new-settings', 'all-sources-images_page_allsi-new-settings', 'all-sources-images_page_allsi-new-automatic', 'all-sources-images_page_allsi-new-bulk-generation' ); if ( in_array( $hook, $ALLSI_pages ) ) { wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/all-sources-images-admin.css', array(), $this->version, 'all' ); } } /** * Register the JavaScript for the admin area. * * @since 4.0.0 */ public function enqueue_scripts( $hook ) { global $pagenow; $post_types_default = $this->ALLSI_default_posts_types(); $block = wp_parse_args( get_option( 'ALLSI_plugin_block_settings' ), $this->ALLSI_default_options_block_settings( TRUE ) ); $options_banks = wp_parse_args( get_option( 'ALLSI_plugin_banks_settings' ), $this->ALLSI_default_options_banks_settings( TRUE ) ); $options_auto = wp_parse_args( get_option( 'ALLSI_plugin_main_settings' ), $this->ALLSI_default_options_main_settings( TRUE ) ); // Scripts for new UI pages $ALLSI_new_pages = array( 'toplevel_page_allsi-new-settings', 'all-sources-images_page_allsi-new-settings', 'all-sources-images_page_allsi-new-automatic', 'all-sources-images_page_allsi-new-bulk-generation' ); if ( in_array( $hook, $ALLSI_new_pages ) ) { // Use WordPress Core jQuery UI wp_enqueue_script( 'jquery-ui-core' ); wp_enqueue_script( 'jquery-ui-tabs' ); wp_enqueue_script( 'jquery-ui-sortable' ); wp_enqueue_script( 'jquery-ui-draggable' ); wp_enqueue_script( 'jquery-ui-droppable' ); } wp_enqueue_script( 'mpt-rating', plugin_dir_url( __FILE__ ) . 'js/rating-admin.js', array('jquery'), $this->version, false ); // Old bulk generation scripts removed - now using bulk-generation.js via new-ui-assets.php // Source/Settings scripts (new page) if ( in_array( $hook, array( 'toplevel_page_allsi-new-settings', 'all-sources-images_page_allsi-new-settings' ), true ) ) { wp_enqueue_script( 'allsi-source', plugins_url( 'js/source.js', __FILE__ ), array('jquery', 'jquery-ui-core') ); wp_localize_script( 'allsi-source', 'allsiApisTestingAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'api_testing_nonce' ), 'successful_testing' => esc_html__( 'Your API key works!', 'all-sources-images' ), 'error_key' => esc_html__( "Your API key doesn't work.", 'all-sources-images' ), 'error_testing' => esc_html__( 'An error has occurred with the remote API.', 'all-sources-images' ), ) ); } // JavaScript Variables for nonce, admin-jax.php path and translations $js_vars = array( 'wp_ajax_url' => admin_url( 'admin-ajax.php' ), 'translations' => array( 'successful' => esc_html__( 'Successful generation !!', 'all-sources-images' ), 'error_generation' => esc_html__( 'Error with images generation', 'all-sources-images' ), 'error_plugin' => esc_html__( 'Error with the plugin', 'all-sources-images' ), 'search_terms' => esc_html__( 'Search Terms', 'all-sources-images' ), 'img_resolution' => esc_html__( 'Image Resolution', 'all-sources-images' ), 'img_size' => esc_html__( 'Image Size', 'all-sources-images' ), 'img_bank' => esc_html__( 'Image Bank', 'all-sources-images' ), ), ); $bulk_generation_flag = filter_input( INPUT_POST, 'all-sources-images', FILTER_UNSAFE_RAW ); $ids_mpt_generation_raw = filter_input( INPUT_GET, 'ids_mpt_generation', FILTER_UNSAFE_RAW ); $cats_raw = filter_input( INPUT_GET, 'cats', FILTER_UNSAFE_RAW ); if ( ! empty( $bulk_generation_flag ) || ! empty( $ids_mpt_generation_raw ) || ! empty( $cats_raw ) ) { $ids_from_cats = ''; if ( ! empty( $cats_raw ) ) { $taxo_term = get_term( absint( $cats_raw ) ); if ( empty( $taxo_term ) ) { return false; } $cpts = get_post_types( array( 'public' => true, ), 'names' ); $post_ids = get_posts( array( 'numberposts' => -1, 'tax_query' => array(array( 'taxonomy' => $taxo_term->taxonomy, 'field' => 'slug', 'terms' => $taxo_term->slug, )), 'post_type' => array(), 'post_status' => array( 'publish', 'draft', 'pending', 'future', 'private' ), 'fields' => 'ids', ) ); $ids = ''; foreach ( $post_ids as $post_id ) { $ids .= $post_id . ','; } $ids_from_cats = substr_replace( $ids, '', -1 ); } $ids_param = is_string( $ids_mpt_generation_raw ) ? sanitize_text_field( $ids_mpt_generation_raw ) : ''; // Use IDs from category if available, otherwise from URL parameter $ids = ! empty( $ids_from_cats ) ? $ids_from_cats : $ids_param; $ids = array_map( 'intval', explode( ',', trim( $ids, ',' ) ) ); $count = count( $ids ); $ids = json_encode( $ids ); $ajax_nonce = wp_create_nonce( 'ajax_nonce_All_Sources_Images' ); $image_blocks = isset( $options_auto['image_block'] ) && is_array( $options_auto['image_block'] ) ? $options_auto['image_block'] : array(); $counter_image_block = ! empty( $image_blocks ) ? count( $image_blocks ) : 1; if ( isset( $options_auto['bulk_generation_interval'] ) && (int) $options_auto['bulk_generation_interval'] !== 0 ) { $remaining_seconds = $this->cron_scheduled(); } else { $remaining_seconds = 0; } $js_vars['sendposts'] = array( 'posts' => $ids, 'count' => $count, 'block_counter' => $counter_image_block, 'interval' => $remaining_seconds, 'nonce' => $ajax_nonce, ); } //Include Main dashboard Js if ( in_array( $hook, $ALLSI_new_pages ) || ($pagenow == 'index.php' || $pagenow == 'post.php' || $pagenow == 'post-new.php') && in_array( get_post_type( get_the_ID() ), $post_types_default['choosed_post_type'] ) ) { wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/all-sources-images-admin.js', array('jquery'), $this->version, array( 'strategy' => 'defer', ) ); } if ( $hook == 'all-sources-images_page_allsi-new-automatic' ) { $image_blocks = ( isset( $options_auto['image_block'] ) ? $options_auto['image_block'] : array() ); // Calculating the current block index based on existing blocks $blockIndex = count( $image_blocks ) + 1; // Starts after the existing blocks wp_localize_script( $this->plugin_name, 'allsiAutomaticSettings', array( 'blockIndex' => $blockIndex, ) ); } $current_post_ID = json_encode( array_map( 'intval', array(get_the_ID()) ) ); $post_nounce = wp_create_nonce( 'ajax_nonce_All_Sources_Images' ); // Check if dalle is the first chosen image bank if ( isset( $options_banks['api_chosen_auto'] ) && true === in_array( 'dallev1', $options_banks['api_chosen_auto'] ) && 'dallev1' === reset( $options_banks['api_chosen_auto'] ) ) { $dalle = "true"; } else { $dalle = "false"; } if ( TRUE === $block['enable_manual_search'] ) { $block['enable_manual_search'] = "true"; } /* General settings */ $post_vars['postgeneration'] = array( 'wp_ajax_url' => admin_url( 'admin-ajax.php' ), 'postID' => $current_post_ID, 'generateImg' => plugin_dir_url( __FILE__ ) . 'img/generate.png', 'strGenerate' => esc_html__( 'Generation', 'all-sources-images' ), 'strNoGenerate' => esc_html__( 'Generate Automatically', 'all-sources-images' ), 'strDalleGenerate' => esc_html__( 'Dall-e v3 Generation may take 20 to 40 seconds. Please be patient', 'all-sources-images' ), 'strManualGenerate' => esc_html__( 'Generate Manually', 'all-sources-images' ), 'strNoRewrite' => esc_html__( 'Edit your overwrite settings if you want a new image', 'all-sources-images' ), 'strConfirmReplace' => esc_html__( 'A featured image already exists. Do you want to replace it with a new one?', 'all-sources-images' ), 'manual_search' => $block['enable_manual_search'], 'dalle' => $dalle, 'nonce' => $post_nounce, ); // Do not include this file into unselected posts types if ( ($pagenow == 'index.php' || $pagenow == 'post.php' || $pagenow == 'post-new.php') && in_array( get_post_type( get_the_ID() ), $post_types_default['choosed_post_type'] ) ) { wp_localize_script( $this->plugin_name, 'allsiGenerationSpecificPostJsVars', $post_vars ); } /* Translation for JS file */ $translations_var['translations'] = array( 'only_one_featured' => esc_html__( 'Only one featured image per post is possible', 'all-sources-images' ), 'delete_logs' => esc_html__( 'Are you sure to delete all logs ?', 'all-sources-images' ), 'no_interval' => esc_html__( 'No interval', 'all-sources-images' ), 'per_minute' => esc_html__( 'per minute', 'all-sources-images' ), 'per_hour' => esc_html__( 'per hour', 'all-sources-images' ), ); wp_localize_script( $this->plugin_name, 'allsiTranslationsJsVars', $translations_var ); wp_localize_script( 'common-mpt', 'allsiTranslationsJsVars', $translations_var ); wp_localize_script( 'mpt-rating', 'allsiTranslationsJsVars', $translations_var ); wp_localize_script( 'images-generation', 'allsiGenerationVars', $js_vars ); } public function cron_scheduled() { // interval delay $options = wp_parse_args( get_option( 'ALLSI_plugin_main_settings' ) ); $options_interval = $options['bulk_generation_interval']; // Switch interval options into seconds switch ( $options_interval ) { case '0': return false; case '1': $interval_seconds = 20; break; case '2': $interval_seconds = 30; break; case '3': $interval_seconds = 60; break; case '4': $interval_seconds = 120; break; case '5': $interval_seconds = 240; break; case '6': $interval_seconds = 600; break; case '7': $interval_seconds = 3600; break; default: return false; } return $interval_seconds; } /** * Show main menu item * * @since 4.0.0 * @since 6.2.0 Simplified to only use new UI pages */ public function ALLSI_main_settings() { // Main menu now opens Search directly. $this->media_picker_top_level_hook = add_menu_page( __( 'All Sources Images Options', 'all-sources-images' ), 'All Sources Images', 'ALLSI_manage', 'allsi-media-browser', array( $this, 'ALLSI_render_media_picker_page' ), 'dashicons-images-alt2', 81 ); // First child: Search (same page as parent). $this->media_picker_search_submenu_hook = add_submenu_page( 'allsi-media-browser', __( 'Search', 'all-sources-images' ), __( 'Search', 'all-sources-images' ), 'ALLSI_manage', 'allsi-media-browser', array( $this, 'ALLSI_render_media_picker_page' ) ); // Include new UI menus (Settings, Automatic, Bulk Generation) include_once plugin_dir_path( __FILE__ ) . 'partials/new-ui/new-ui-menus.php'; ALLSI_set_new_ui_admin( $this ); ALLSI_register_new_ui_menus(); /* Bulk Generation link for posts & custom post type */ $post_type_availables = get_option( 'ALLSI_plugin_posts_settings' ); if ( isset( $post_type_availables['choosed_post_type'] ) ) { if ( false == $post_type_availables['choosed_post_type'] ) { $post_type_availables['choosed_post_type'] = array(); } } else { $post_types_default = get_post_types( '', 'objects' ); unset( $post_types_default['attachment'], $post_types_default['revision'], $post_types_default['nav_menu_item'], $post_types_default['custom_css'], $post_types_default['customize_changeset'], $post_types_default['oembed_cache'], $post_types_default['user_request'], $post_types_default['wp_block'], $post_types_default['wp_template'], $post_types_default['wp_template_part'], $post_types_default['wp_global_styles'], $post_types_default['wp_navigation'] ); $post_type_availables = array(); $post_type_availables['choosed_post_type'] = array(); foreach ( $post_types_default as $post_type ) { $post_type_availables['choosed_post_type'][$post_type->name] = $post_type->name; } } foreach ( $post_type_availables['choosed_post_type'] as $screen ) { add_filter( 'bulk_actions-edit-' . $screen, array(&$this, 'ALLSI_add_bulk_actions') ); // Text on dropdown add_action( 'handle_bulk_actions-edit-' . $screen, array(&$this, 'ALLSI_bulk_action_handler'), 10, 3 ); // Redirection } // Genererate link for Categories add_filter( 'category_row_actions', array(&$this, 'ALLSI_add_bulk_action_category'), 10, 2 ); // Loop with each taxo for Genrate link $args_taxo = array( 'public' => true, ); $taxonomies = get_taxonomies( $args_taxo ); $taxonomies = array_diff( $taxonomies, ['post_tag', 'post_format'] ); foreach ( $taxonomies as $taxonomy ) { add_filter( $taxonomy . '_row_actions', array(&$this, 'ALLSI_add_bulk_action_category'), 10, 2 ); } } /** * Main actions * * @since 4.0.0 */ public function ALLSI_main_actions() { if ( !current_user_can( 'ALLSI_manage' ) ) { wp_die( esc_html__( 'You do not have sufficient permissions.', 'all-sources-images' ) ); } //register_setting('ASI-plugin-posts-settings', 'ALLSI_plugin_posts_settings'); register_setting( 'ASI-plugin-block-settings', 'ALLSI_plugin_block_settings', array( 'sanitize_callback' => array( $this, 'ALLSI_sanitize_block_settings' ), ) ); register_setting( 'ASI-plugin-main-settings', 'ALLSI_plugin_main_settings', array( 'sanitize_callback' => array($this, 'ALLSI_sanitize_main_settings'), ) ); register_setting( 'ASI-plugin-auto-image-settings', 'ALLSI_plugin_auto_image_settings', array( 'sanitize_callback' => array( $this, 'ALLSI_sanitize_auto_image_settings' ), ) ); register_setting( 'ASI-plugin-banks-settings', 'ALLSI_plugin_banks_settings', array( 'sanitize_callback' => array($this, 'ALLSI_sanitize_banks_settings'), ) ); register_setting( 'ASI-plugin-interval-settings', 'ALLSI_plugin_interval_settings', array( 'sanitize_callback' => array( $this, 'ALLSI_sanitize_interval_settings' ), ) ); register_setting( 'ASI-plugin-cron-settings', 'ALLSI_plugin_cron_settings', array( 'sanitize_callback' => array($this, 'ALLSI_sanitize_cron_settings'), ) ); register_setting( 'ASI-plugin-rights-settings', 'ALLSI_plugin_rights_settings', array( 'sanitize_callback' => array( $this, 'ALLSI_sanitize_rights_settings' ), ) ); register_setting( 'ASI-plugin-proxy-settings', 'ALLSI_plugin_proxy_settings', array( 'sanitize_callback' => array( $this, 'ALLSI_sanitize_proxy_settings' ), ) ); register_setting( 'ASI-plugin-logs-settings', 'ALLSI_plugin_logs_settings', array( 'sanitize_callback' => array( $this, 'ALLSI_sanitize_logs_settings' ), ) ); require_once dirname( __FILE__ ) . '/partials/delete_log.php'; add_filter( 'map_meta_cap', array(&$this, 'ALLSI_map_manage_options_capability'), 10, 4 ); } /** * Change to "ALLSI_manage" rights for all plugin forms * * @since 5.2.11 */ public function ALLSI_map_manage_options_capability( $caps, $cap, $user_id, $args ) { // Check if the capability being checked is 'manage_options' if ( $cap === 'manage_options' ) { // Check if the form is submitting a specific option related to your plugin // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WordPress Settings API in options.php $option_page = isset( $_POST['option_page'] ) ? sanitize_text_field( wp_unslash( $_POST['option_page'] ) ) : ''; if ( $option_page && in_array( $option_page, array( 'ASI-plugin-proxy-settings', 'ASI-plugin-main-settings', 'ASI-plugin-auto-image-settings', 'ASI-plugin-block-settings', 'ASI-plugin-cron-settings', 'ASI-plugin-logs-settings', 'ASI-plugin-rights-settings', 'ASI-plugin-banks-settings' ) ) ) { // If the user has the 'ALLSI_manage' capability, grant access to manage the options if ( current_user_can( 'ALLSI_manage' ) ) { $caps = array('ALLSI_manage'); } } } return $caps; } /** * Get current url * * @since 4.0.0 */ public function ALLSI_current_url() { $requested_url = ( is_ssl() ? 'https://' : 'http://' ); $requested_url .= isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : ''; $requested_url .= isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; return $requested_url; } /** * Default banks name * * @since 6.0.0 */ public function ALLSI_banks_name_auto() { /* Banks for Automatic Bulk */ $list_api_auto = array( esc_html__( 'Google Image (API)', 'all-sources-images' ) => array('google_image', true), esc_html__( 'DALL·E (v3)', 'all-sources-images' ) => array('dallev1', true), esc_html__( 'Openverse', 'all-sources-images' ) => array('cc_search', true), esc_html__( 'Flickr', 'all-sources-images' ) => array('flickr', true), esc_html__( 'Pixabay', 'all-sources-images' ) => array('pixabay', true), esc_html__( 'GIPHY', 'all-sources-images' ) => array('giphy', true), esc_html__( 'Youtube', 'all-sources-images' ) => array('youtube', true), esc_html__( 'Unsplash', 'all-sources-images' ) => array('unsplash', true), esc_html__( 'Pexels', 'all-sources-images' ) => array('pexels', true), esc_html__( 'Stable Diffusion', 'all-sources-images' ) => array('stability', true), esc_html__( 'Replicate', 'all-sources-images' ) => array('replicate', true), esc_html__( 'Gemini (Google AI)', 'all-sources-images' ) => array('gemini', true), esc_html__( 'Cloudflare Workers AI', 'all-sources-images' ) => array('workers_ai', true), esc_html__( 'Google Translate', 'all-sources-images' ) => array('google_translate', true), ); return $list_api_auto; } public function ALLSI_banks_name_manual() { $list_api_manual = array( esc_html__( 'Google Image (API)', 'all-sources-images' ) => array('google_image', true), esc_html__( 'DALL·E (v3)', 'all-sources-images' ) => array('dallev1', true), esc_html__( 'Openverse', 'all-sources-images' ) => array('cc_search', true), esc_html__( 'Flickr', 'all-sources-images' ) => array('flickr', true), esc_html__( 'Pixabay', 'all-sources-images' ) => array('pixabay', true), esc_html__( 'GIPHY', 'all-sources-images' ) => array('giphy', true), esc_html__( 'Youtube', 'all-sources-images' ) => array('youtube', true), esc_html__( 'Unsplash', 'all-sources-images' ) => array('unsplash', true), esc_html__( 'Pexels', 'all-sources-images' ) => array('pexels', true), esc_html__( 'Stable Diffusion', 'all-sources-images' ) => array('stability', true), esc_html__( 'Replicate', 'all-sources-images' ) => array('replicate', true), esc_html__( 'Gemini (Google AI)', 'all-sources-images' ) => array('gemini', true), esc_html__( 'Cloudflare Workers AI', 'all-sources-images' ) => array('workers_ai', true), ); return $list_api_manual; } /** * Codes for AI-based generators * * @since 6.1.8 */ public function ALLSI_ai_source_codes() { return array( 'dallev1', 'stability', 'replicate', 'gemini', 'workers_ai', ); } /** * Get default posts types & categories * * @since 5.0.0 */ public function ALLSI_default_posts_types() { $post_types_default['choosed_post_type'] = get_post_types(); unset( $post_types_default['choosed_post_type']['attachment'], $post_types_default['choosed_post_type']['revision'], $post_types_default['choosed_post_type']['nav_menu_item'], $post_types_default['choosed_post_type']['custom_css'], $post_types_default['choosed_post_type']['customize_changeset'], $post_types_default['choosed_post_type']['oembed_cache'], $post_types_default['choosed_post_type']['user_request'], $post_types_default['choosed_post_type']['wp_block'], $post_types_default['choosed_post_type']['wp_template'], $post_types_default['choosed_post_type']['wp_template_part'], $post_types_default['choosed_post_type']['wp_global_styles'], $post_types_default['choosed_post_type']['wp_navigation'] ); $categories_default = get_terms( array( 'taxonomy' => 'category', 'hide_empty' => false, ) ); foreach ( $categories_default as $category ) { $post_types_default['choosed_categories'][$category->slug] = $category->name; } return $post_types_default; } /** * Default values for Image admin tabs * * @since 4.0.0 */ public function ALLSI_default_options_main_settings( $never_set = FALSE ) { $default_options = array( 'image_block' => array( 1 => array( 'image_location' => 'featured', 'api_chosen' => 'pixabay', 'based_on' => 'title', 'translation_EN' => 'true', 'title_selection' => 'full_title', 'selected_image' => 'first_result', ), ), 'image_filename' => 'title', 'rewrite_featured' => '', 'image_reuse' => '', 'image_flip' => '', 'image_crop' => '', 'bulk_generation_interval' => 0, ); return $default_options; } /** * Default values for Auto Image tab * * @since 6.2.0 */ public function ALLSI_default_options_auto_image_settings( $never_set = FALSE ) { $default_options = array( 'enabled' => 'disable', 'post_types' => array(), 'term_ids' => array(), 'exclude_post_ids' => '', ); return $default_options; } /** * Default values for "Source" (Banks) admin tabs * * @since 4.0.0 */ public function ALLSI_default_options_banks_settings( $never_set = FALSE ) { // Migration from v4 to v5 $options_banks = get_option( 'ALLSI_plugin_banks_settings' ); if ( isset( $options_banks['api_chosen'] ) && !isset( $options_banks['api_chosen_auto'] ) ) { // Already chosen bank as selected $ar_bank_auto = array($options_banks['api_chosen']); } else { // Default banks - Pixabay as primary $ar_bank_auto = array('pixabay', 'openverse'); } // Default manual banks: stock image sources selected by default (as shown in settings UI) // Order: Pixabay, Flickr, Openverse (cc_search), Unsplash, GIPHY, Pexels // AI sources and YouTube/Google Image excluded by default $default_options = array( 'api_chosen_manual' => array( 'pixabay', 'flickr', 'cc_search', 'unsplash', 'giphy', 'pexels', ), 'api_chosen_auto' => $ar_bank_auto, 'googleimage' => array( 'cxid' => '', 'apikey' => '', 'search_country' => 'en', 'img_color' => '', 'filetype' => '', 'imgsz' => 'large', 'imgtype' => '', 'safe' => 'moderate', 'rights' => array(), ), 'dallev1' => array( 'apikey' => '', 'imgsize' => '1024x1024', ), 'stability' => array( 'apikey' => '', 'model' => 'sd3-large', 'aspect_ratio' => '16:9', 'output_format' => 'jpeg', 'use_negative_prompt' => '', ), 'replicate' => array( 'apikey' => '', 'model' => 'black-forest-labs/flux-schnell', 'output_format' => 'webp', 'aspect_ratio' => '16:9', ), 'gemini' => array( 'apikey' => '', 'model' => 'gemini-2.5-flash-image', 'aspect_ratio' => '1:1', 'image_size' => '', ), 'workers_ai' => array( 'account_id' => '', 'api_token' => '', 'model' => '@cf/black-forest-labs/flux-1-schnell', 'steps' => 4, 'negative_prompt' => '', ), 'cc_search' => array( 'source' => 1, 'rights' => '', 'imgtype' => '', 'aspect_ratio' => 'tall', ), 'flickr' => array( 'apikey' => '', 'rights' => '', 'imgtype' => 7, ), 'pixabay' => array( 'username' => '', 'apikey' => '', 'imgtype' => 'all', 'search_country' => 'en', 'orientation' => 'all', 'min_width' => 0, 'min_height' => 0, 'safesearch' => 'false', ), 'pexels' => array( 'apikey' => '', 'orientation' => '', 'size' => 'large', 'color' => '', 'locale' => 'en-US', ), 'giphy' => array( 'apikey' => '', 'rating' => 'g', 'lang' => 'en', 'limit' => 25, 'media_type'=> 'gifs', 'bundle' => '', ), 'unsplash' => array( 'apikey' => '', 'orientation' => '', 'content_filter' => 'low', 'color' => '', ), 'youtube' => array( 'apikey' => '', 'thumbnail_quality' => 'high', 'search_order' => 'relevance', 'video_duration' => 'any', 'safe_search' => 'moderate', 'max_results' => 5, 'region_code' => '', ), 'google_translate' => array( 'apikey' => '', ), ); return $default_options; } /** * Default values for Interval admin tabs * * @since 4.0.0 */ /* public function ALLSI_default_options_interval_settings( $never_set = FALSE ) { $default_options = array( // Interval 'bulk_generation_interval' => 0 ); return $default_options; }*/ /** * Default values for Gutenberg Block * * @since 4.0.0 */ public function ALLSI_default_options_block_settings( $never_set = FALSE ) { $default_options = array( 'enable_manual_search' => true, 'translation_EN' => 'true', 'source_lang' => '', // Empty = auto-detect from WordPress language 'translate_alt' => '', 'translate_alt_lang' => '', 'google_translate_apikey' => '', ); return $default_options; } /** * Default values for Cron admin tabs * * @since 4.0.0 */ public function ALLSI_default_options_cron_settings( $never_set = FALSE ) { $default_options = array( 'enable_cron' => 'disable', 'cron_post_types' => array('post', 'page'), 'cron_interval_value'=> 5, 'cron_interval_unit' => 'minutes', 'posts_date_mode' => 'all', 'posts_date_value' => 5, 'posts_date_unit' => 'days', 'posts_per_run' => 5, ); return $default_options; } /** * Default values for Rights admin tabs * * @since 5.2.11 */ public function ALLSI_default_options_rights_settings( $never_set = FALSE ) { $default_options = array( 'rights_editor' => '', 'rights_author' => '', 'rights_contributor' => '', 'rights_subscriber' => '', ); return $default_options; } /** * Default values for Proxy admin tabs * * @since 4.0.0 */ public function ALLSI_default_options_proxy_settings( $never_set = FALSE ) { $default_options = array( 'enable_proxy' => 'disable', 'proxy_mode' => 'legacy', 'proxy_address' => '', 'proxy_port' => '80', 'proxy_username' => '', 'proxy_password' => '', 'cloudflare_worker_url' => '', 'cloudflare_token' => '', ); return $default_options; } /** * Default values for logs admin tabs * * @since 4.0.0 */ public function ALLSI_default_options_logs_settings( $never_set = FALSE ) { $default_options = array( 'logs' => '', ); return $default_options; } /** * Create file for logs * * @since 4.0.0 */ private function ALLSI_log_file( $check = false ) { $logs_dir = ALLSI_ensure_logs_dir(); if ( false === $logs_dir ) { if ( true === $check ) { return false; } return false; } $files = @scandir( $logs_dir ); $result = ''; if ( !empty( $files ) ) { foreach ( $files as $key => $value ) { if ( !in_array( $value, array('.', '..'), true ) ) { if ( !is_dir( $logs_dir . $value ) && strstr( $value, '.log' ) ) { $result = $value; } } } } if ( true == $check && empty( $result ) ) { return false; } if ( empty( $result ) ) { $result = 'mpt-' . wp_generate_password( 14, false, false ) . '.log'; } return $result; } /** * Get the absolute path to the current log file. * * @return string|false */ private function ALLSI_get_log_file_path() { $logs_dir = ALLSI_ensure_logs_dir(); if ( false === $logs_dir ) { return false; } $log_file = $this->ALLSI_log_file( true ); if ( empty( $log_file ) ) { return false; } $log_path = $logs_dir . $log_file; if ( ! is_file( $log_path ) || ! is_readable( $log_path ) ) { return false; } return $log_path; } /** * Read log contents, optionally tailing large files for performance. * * @param int $max_bytes Maximum bytes to read from the end of the file. * * @return array */ private function ALLSI_read_log_contents( $max_bytes = 200000 ) { $log_path = $this->ALLSI_get_log_file_path(); if ( false === $log_path ) { return array( 'content' => '', 'filename' => '', 'truncated' => false, 'size' => 0, ); } $file_size = filesize( $log_path ); if ( false === $file_size || $file_size <= 0 ) { return array( 'content' => '', 'filename' => basename( $log_path ), 'truncated' => false, 'size' => 0, ); } $truncated = false; $content = ''; $max_bytes = max( 1024, absint( $max_bytes ) ); if ( $file_size > $max_bytes ) { $truncated = true; $handle = fopen( $log_path, 'rb' ); if ( false !== $handle ) { fseek( $handle, -$max_bytes, SEEK_END ); $content = fread( $handle, $max_bytes ); fclose( $handle ); } if ( false === $content ) { $content = ''; } $content = ltrim( (string) $content ); } else { $content = file_get_contents( $log_path ); if ( false === $content ) { $content = ''; } } return array( 'content' => (string) $content, 'filename' => basename( $log_path ), 'truncated' => $truncated, 'size' => (int) $file_size, ); } /** * Build log viewer data for rendering and AJAX responses. * * @param int $max_bytes Maximum bytes to read from log file. * * @return array */ public function ALLSI_get_log_view_data( $max_bytes = 200000 ) { $log_data = $this->ALLSI_read_log_contents( $max_bytes ); if ( empty( $log_data['filename'] ) ) { return array( 'content' => '', 'filename' => '', 'truncated' => false, 'size' => 0, 'message' => __( 'No log file found.', 'all-sources-images' ), ); } $message = sprintf( /* translators: %s: log file name */ __( 'Viewing log file: %s', 'all-sources-images' ), $log_data['filename'] ); if ( ! empty( $log_data['truncated'] ) ) { $message .= ' ' . __( '(showing latest entries)', 'all-sources-images' ); } $log_data['message'] = $message; return $log_data; } /** * AJAX: return log contents for the Logging viewer. */ public function ALLSI_get_log_contents_ajax() { check_ajax_referer( 'allsi_log_viewer_nonce', 'nonce' ); if ( ! current_user_can( 'ALLSI_manage' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied.', 'all-sources-images' ) ), 403 ); } $log_data = $this->ALLSI_get_log_view_data(); wp_send_json_success( $log_data ); } /** * AJAX: clear the active log file. */ public function ALLSI_clear_log_ajax() { check_ajax_referer( 'allsi_log_viewer_nonce', 'nonce' ); if ( ! current_user_can( 'ALLSI_manage' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied.', 'all-sources-images' ) ), 403 ); } $log_path = $this->ALLSI_get_log_file_path(); if ( false === $log_path ) { wp_send_json_success( array( 'content' => '', 'filename' => '', 'truncated' => false, 'size' => 0, 'message' => __( 'No log file found.', 'all-sources-images' ), ) ); } $deleted = wp_delete_file( $log_path ); if ( false === $deleted && file_exists( $log_path ) ) { wp_send_json_error( array( 'message' => __( 'Unable to clear log file.', 'all-sources-images' ) ) ); } wp_send_json_success( array( 'content' => '', 'filename' => '', 'truncated' => false, 'size' => 0, 'message' => __( 'Log file cleared.', 'all-sources-images' ), ) ); } /** * Create file for logs * * @since 4.0.0 */ public function ALLSI_monolog_call() { $main_settings = get_option( 'ALLSI_plugin_logs_settings' ); // Ensure the logger class is loaded if ( ! class_exists( 'ALLSI_Logger' ) ) { require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-allsi-logger.php'; } // Check if logs enabled if ( ! empty( $main_settings['logs'] ) && true == $main_settings['logs'] ) { $logs_dir = ALLSI_ensure_logs_dir(); if ( false === $logs_dir ) { return new ALLSI_Nolog(); } $logfile = $this->ALLSI_log_file(); $log = new ALLSI_Logger( 'ALLSI_logger', $logs_dir . $logfile, true ); } else { $log = new ALLSI_Nolog(); } return $log; } /** * Check if interval generation is enabled * * @since 4.0.0 */ public function ALLSI_check_interval() { $options = wp_parse_args( get_option( 'ALLSI_plugin_main_settings' ), $this->ALLSI_default_options_main_settings( TRUE ) ); $value_bulk_generation_interval = ( isset( $options['bulk_generation_interval'] ) ? (int) $options['bulk_generation_interval'] : 0 ); if ( 0 == $value_bulk_generation_interval ) { return false; } else { return true; } } /** * Check if interval generation is enabled * * @since 4.0.0 */ public function ALLSI_do_interval_cron( $new_ids_to_add = false ) { // Get processing ids $interval_posts_to_generate = get_transient( 'ALLSI_interval_generation' ); if ( ! is_array( $interval_posts_to_generate ) ) { $interval_posts_to_generate = array(); } // Default status to "generation done". The loop below sets it to false when it finds work. $no_more_post_to_generate = true; $new_ids_to_add_array = is_array( $new_ids_to_add ) ? $new_ids_to_add : array(); $has_new_ids_to_add = ! empty( $new_ids_to_add_array ); $new_ids_to_add_is_false = ( false === $new_ids_to_add ); foreach ( $interval_posts_to_generate as $post => $post_val ) { $continue_loop = false; // Get the first post not already generated if ( FALSE == $interval_posts_to_generate[$post]['processed'] ) { // Change default status to "generation processing" $no_more_post_to_generate = false; // Generation $launch_MPT = new All_Sources_Images_Generation($this->plugin_name, $this->version); $ALLSI_return = $launch_MPT->ALLSI_create_thumb( $interval_posts_to_generate[$post]['id'], '0', '0', '0', '0' ); // Get the return status if ( $ALLSI_return == null ) { // Settings $main_settings = get_option( 'ALLSI_plugin_main_settings' ); // Image location $image_location = ( !empty( $main_settings['image_location'] ) ? $main_settings['image_location'] : 'featured' ); if ( has_post_thumbnail( $interval_posts_to_generate[$post]['id'] ) && "featured" === $image_location ) { $interval_posts_to_generate[$post]['processed'] = 'already-exist'; $continue_loop = true; } else { // Add the status to this speficic post : Problem $interval_posts_to_generate[$post]['processed'] = 'error'; } } else { // Add the status to theis speficic post : ok $interval_posts_to_generate[$post]['processed'] = true; } // Limit only to the first post if ( TRUE !== $continue_loop ) { break; } } } // Generation done and new ids to generate if ( TRUE == $no_more_post_to_generate && $has_new_ids_to_add ) { // Delete old posts delete_transient( 'ALLSI_interval_generation' ); $new_posts_to_generate = array(); foreach ( $new_ids_to_add_array as $id ) { $new_posts_to_generate[] = array( 'id' => (int) $id, 'processed' => false, ); } // Add news posts set_transient( 'ALLSI_interval_generation', $new_posts_to_generate ); } elseif ( TRUE == $no_more_post_to_generate && $new_ids_to_add_is_false ) { // Generation done // Nothing to add/do } elseif ( FALSE == $no_more_post_to_generate && $has_new_ids_to_add ) { // Update with new ids (added at the end) foreach ( $new_ids_to_add_array as $id ) { $interval_posts_to_generate[] = array( 'id' => (int) $id, 'processed' => false, ); } // Allow ids into the array only once. Avoid duplicate ids (Remove the last ones) $temp_generate_posts = array(); foreach ( $interval_posts_to_generate as &$v ) { if ( !isset( $temp_generate_posts[$v['id']] ) ) { $temp_generate_posts[$v['id']] =& $v; } } $interval_posts_to_generate = array_values( $temp_generate_posts ); // Add news posts set_transient( 'ALLSI_interval_generation', $interval_posts_to_generate ); } else { // Generation not finished : Updating transient set_transient( 'ALLSI_interval_generation', $interval_posts_to_generate ); } } /** * Add "Generate featured images" into bulk menu for categories * * @since 4.0.0 */ public function ALLSI_add_bulk_action_category( $actions, $tag ) { $actions['atp'] = '' . esc_html__( 'Generate featured images', 'all-sources-images' ) . ''; return $actions; } /** * Redirection for bulk action * * @since 4.0.0 */ public function ALLSI_bulk_action_handler( $redirect_to, $action_name, $post_ids ) { if ( 'bulk_regenerate_thumbnails' === $action_name ) { $ids = implode( ',', array_map( 'intval', $post_ids ) ); wp_safe_redirect( admin_url( 'admin.php?page=allsi-new-bulk-generation&auto_generate_ids=' . $ids ) ); exit; } return $redirect_to; } /** * Add "Generate featured images" into bulk menu for posts * * @since 4.0.0 */ public function ALLSI_add_bulk_actions( $actions ) { // Enqueue the bulk actions script with localized text wp_enqueue_script( 'allsi-bulk-actions', plugin_dir_url( __FILE__ ) . 'js/bulk-actions.js', array( 'jquery' ), $this->version, true ); wp_localize_script( 'allsi-bulk-actions', 'allsiBulkActions', array( 'optionText' => esc_html__( 'Generate Images (ASI)', 'all-sources-images' ), ) ); return $actions; } /** * Testing if APIs works into settings page * * @since 5.0.0 */ public function ALLSI_test_apis() { check_ajax_referer( 'api_testing_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( __( 'Permission denied.', 'all-sources-images' ) ); } // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified above with check_ajax_referer(). $apiKey = isset( $_POST['apikey'] ) ? sanitize_text_field( wp_unslash( $_POST['apikey'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified above with check_ajax_referer(). $cxId = isset( $_POST['cxid'] ) ? sanitize_text_field( wp_unslash( $_POST['cxid'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified above with check_ajax_referer(). $apiBank = isset( $_POST['apibank'] ) ? sanitize_text_field( wp_unslash( $_POST['apibank'] ) ) : ''; $response = ''; if ( 'pixabay' === $apiBank ) { $apiUrl = "https://pixabay.com/api/?key=" . $apiKey . "&q=exemple"; $response = $this->ALLSI_remote_get( 'pixabay', $apiUrl ); } elseif ( 'google_image' === $apiBank ) { if ( ! class_exists( 'ALLSI_Source_Google_Image' ) ) { wp_send_json_error( __( 'Google Image source is unavailable.', 'all-sources-images' ) ); } if ( empty( $cxId ) ) { wp_send_json_error( __( 'CX ID is required for Google Custom Search.', 'all-sources-images' ) ); } $default_options = $this->ALLSI_default_options_banks_settings( true ); $google_defaults = isset( $default_options['googleimage'] ) ? $default_options['googleimage'] : array(); $google_options = array_merge( $google_defaults, array( 'apikey' => $apiKey, 'cxid' => $cxId, 'imgsz' => isset( $google_defaults['imgsz'] ) ? $google_defaults['imgsz'] : 'large', ) ); $proxy_args = $this->ALLSI_get_proxy_args(); $source = new ALLSI_Source_Google_Image(); $context = array( 'options' => array( 'googleimage' => $google_options ), 'search' => 'asi test', 'proxy_args' => $proxy_args, 'generation' => $this, 'get_only_thumb' => true, ); $result = $source->generate( $context ); if ( is_wp_error( $result ) ) { wp_send_json_error( $result->get_error_message() ); } if ( isset( $result['items'] ) && ! empty( $result['items'] ) ) { wp_send_json_success( wp_json_encode( $result ) ); } wp_send_json_error( __( 'No results found or there was an error.', 'all-sources-images' ) ); } elseif ( 'dalle' === $apiBank ) { if ( ! class_exists( 'ALLSI_Source_Dallev1' ) ) { wp_send_json_error( __( 'DALL·E source is unavailable.', 'all-sources-images' ) ); } if ( empty( $apiKey ) ) { wp_send_json_error( __( 'API key is required.', 'all-sources-images' ) ); } $default_options = $this->ALLSI_default_options_banks_settings( true ); $dalle_defaults = isset( $default_options['dallev1'] ) ? $default_options['dallev1'] : array(); $dalle_options = array_merge( $dalle_defaults, array( 'apikey' => $apiKey ) ); $proxy_args = $this->ALLSI_get_proxy_args(); $source = new ALLSI_Source_Dallev1(); $context = array( 'options' => array( 'dallev1' => $dalle_options ), 'search' => 'asi dalle test', 'proxy_args' => $proxy_args, 'get_only_thumb' => true, ); $result = $source->generate( $context ); if ( is_wp_error( $result ) ) { wp_send_json_error( $result->get_error_message() ); } if ( isset( $result['data'] ) && ! empty( $result['data'] ) ) { wp_send_json_success( wp_json_encode( $result ) ); } wp_send_json_error( __( 'No results found or there was an error.', 'all-sources-images' ) ); } elseif ( 'youtube' === $apiBank ) { if ( ! class_exists( 'ALLSI_Source_Youtube' ) ) { wp_send_json_error( __( 'YouTube source is unavailable.', 'all-sources-images' ) ); } $default_options = $this->ALLSI_default_options_banks_settings( true ); $youtube_defaults = isset( $default_options['youtube'] ) ? $default_options['youtube'] : array(); $youtube_options = array_merge( $youtube_defaults, array( 'apikey' => $apiKey, 'max_results' => 1 ) ); $proxy_args = $this->ALLSI_get_proxy_args(); $source = new ALLSI_Source_Youtube(); $context = array( 'options' => array( 'youtube' => $youtube_options ), 'search' => 'asi test', 'proxy_args' => $proxy_args, 'generation' => $this, 'get_only_thumb' => true, ); $result = $source->generate( $context ); if ( is_wp_error( $result ) ) { wp_send_json_error( $result->get_error_message() ); } if ( isset( $result['items'] ) && ! empty( $result['items'] ) ) { wp_send_json_success( wp_json_encode( $result ) ); } wp_send_json_error( __( 'No results found or there was an error.', 'all-sources-images' ) ); } elseif ( 'unsplash' === $apiBank ) { $apiUrl = "https://api.unsplash.com/search/photos?query=test&client_id={$apiKey}"; $response = $this->ALLSI_remote_get( 'unsplash', $apiUrl ); } elseif ( 'giphy' === $apiBank ) { if ( empty( $apiKey ) ) { wp_send_json_error( __( 'API key is required.', 'all-sources-images' ) ); } $query_args = array( 'api_key' => $apiKey, 'q' => 'asi test', 'limit' => 1, 'rating' => 'pg', 'lang' => 'en', ); $apiUrl = add_query_arg( $query_args, 'https://api.giphy.com/v1/gifs/search' ); $response = $this->ALLSI_remote_get( 'giphy', $apiUrl ); if ( is_wp_error( $response ) ) { wp_send_json_error( __( 'Error connecting to the API.', 'all-sources-images' ) ); } $status_code = wp_remote_retrieve_response_code( $response ); $body = wp_remote_retrieve_body( $response ); if ( 200 !== $status_code ) { $decoded = json_decode( $body, true ); $message = isset( $decoded['meta']['msg'] ) ? $decoded['meta']['msg'] : __( 'Unexpected GIPHY API response.', 'all-sources-images' ); wp_send_json_error( $message, $status_code ); } wp_send_json_success( $body ); return; } elseif ( 'pexels' === $apiBank ) { $apiUrl = "https://api.pexels.com/v1/search?query=nature&per_page=1"; $response = $this->ALLSI_remote_get( 'pexels', $apiUrl, array( 'headers' => array( 'Authorization' => $apiKey, ), ) ); } elseif ( 'stability' === $apiBank ) { if ( empty( $apiKey ) ) { wp_send_json_error( __( 'API key is required.', 'all-sources-images' ) ); } $request_args = array( 'headers' => array( 'Authorization' => 'Bearer ' . $apiKey, 'Accept' => 'application/json', ), 'timeout' => 20, ); $response = $this->ALLSI_remote_get( 'stability', 'https://api.stability.ai/v1/user/account', $request_args ); if ( is_wp_error( $response ) ) { wp_send_json_error( __( 'Error connecting to Stability AI.', 'all-sources-images' ) ); } $code = wp_remote_retrieve_response_code( $response ); $body = wp_remote_retrieve_body( $response ); if ( 200 === $code ) { wp_send_json_success( $body ); } $decoded = json_decode( $body, true ); $message = isset( $decoded['message'] ) ? $decoded['message'] : __( 'Unexpected Stability AI response.', 'all-sources-images' ); wp_send_json_error( $message, $code ); } elseif ( 'replicate' === $apiBank ) { // test Replicate API key by listing models $apiUrl = 'https://api.replicate.com/v1/models'; $response = $this->ALLSI_remote_get( 'replicate', $apiUrl, array( 'headers' => array( 'Authorization' => 'Token ' . $apiKey, 'Content-Type' => 'application/json', ), 'timeout' => 10, ) ); // Handle HTTP error if ( is_wp_error( $response ) ) { wp_send_json_error( 'Error connecting to Replicate API.' ); } // Check status code for unauthorized vs ok $code = wp_remote_retrieve_response_code( $response ); if ( 200 === $code ) { wp_send_json_success( wp_remote_retrieve_body( $response ) ); } elseif ( 401 === $code ) { wp_send_json_error( 'unauthorized', 401 ); } else { wp_send_json_error( 'Unexpected status: ' . $code, $code ); } } elseif ( 'gemini' === $apiBank ) { if ( empty( $apiKey ) ) { wp_send_json_error( __( 'API key is required.', 'all-sources-images' ) ); } $apiUrl = add_query_arg( array( 'key' => $apiKey, 'pageSize' => 1, ), 'https://generativelanguage.googleapis.com/v1beta/models' ); $response = $this->ALLSI_remote_get( 'gemini', $apiUrl, array( 'timeout' => 15, ) ); if ( is_wp_error( $response ) ) { wp_send_json_error( 'Error connecting to Gemini API.' ); } $code = wp_remote_retrieve_response_code( $response ); $body = wp_remote_retrieve_body( $response ); if ( 200 === $code ) { wp_send_json_success( $body ); } $decoded = json_decode( $body, true ); $message = isset( $decoded['error']['message'] ) ? $decoded['error']['message'] : __( 'Unexpected Gemini API response.', 'all-sources-images' ); wp_send_json_error( $message, $code ); } elseif ( 'workers_ai' === $apiBank ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified at function start with check_ajax_referer(). $account_id = isset( $_POST['account_id'] ) ? sanitize_text_field( wp_unslash( $_POST['account_id'] ) ) : ''; if ( empty( $account_id ) ) { wp_send_json_error( __( 'Account ID is required.', 'all-sources-images' ) ); } if ( empty( $apiKey ) ) { wp_send_json_error( __( 'API token is required.', 'all-sources-images' ) ); } // Use the AI finetunes endpoint to verify credentials (lightweight, read-only) $apiUrl = sprintf( 'https://api.cloudflare.com/client/v4/accounts/%s/ai/finetunes', rawurlencode( $account_id ) ); $request_args = array( 'headers' => array( 'Authorization' => 'Bearer ' . $apiKey, 'Content-Type' => 'application/json', ), 'timeout' => 15, ); $response = $this->ALLSI_remote_get( 'workers_ai', $apiUrl, $request_args ); if ( is_wp_error( $response ) ) { wp_send_json_error( __( 'Error connecting to Cloudflare Workers AI.', 'all-sources-images' ) ); } $code = wp_remote_retrieve_response_code( $response ); $body = wp_remote_retrieve_body( $response ); $decoded = json_decode( $body, true ); // Check if response indicates success (even empty results mean valid credentials) if ( 200 === $code && isset( $decoded['success'] ) && true === $decoded['success'] ) { wp_send_json_success( $body ); } // Handle specific error cases $message = ''; if ( isset( $decoded['errors'][0]['message'] ) ) { $message = $decoded['errors'][0]['message']; } elseif ( isset( $decoded['messages'][0] ) ) { $message = $decoded['messages'][0]; } elseif ( 401 === $code || 403 === $code ) { $message = __( 'Invalid API token or insufficient permissions. Ensure your token has Workers AI:Read permission.', 'all-sources-images' ); } elseif ( 404 === $code ) { $message = __( 'Account not found. Please verify your Account ID.', 'all-sources-images' ); } else { $message = __( 'Unexpected Workers AI response.', 'all-sources-images' ); } wp_send_json_error( $message, $code ); } else { $response = ''; wp_send_json_error( 'Unknown API bank: ' . $apiBank ); } if ( is_wp_error( $response ) ) { wp_send_json_error( 'Error connecting to the API.' ); } else { wp_send_json_success( $response['body'] ); } } /** * Register MPT Gutenberg Block * * @since 5.0.0 */ public function ALLSI_register_mpt_block() { $banks = wp_parse_args( get_option( 'ALLSI_plugin_banks_settings' ), $this->ALLSI_default_options_banks_settings( TRUE ) ); if ( isset( $banks['api_chosen_manual']['envato'] ) ) { unset($banks['api_chosen_manual']['envato']); } $manual_bank_labels = array(); $manual_banks = $this->ALLSI_banks_name_manual(); foreach ( $manual_banks as $label => $data ) { $manual_bank_labels[$data[0]] = $label; } $asset_file = (include plugin_dir_path( __FILE__ ) . 'blocks/allsi-images/build/index.asset.php'); wp_register_script( 'allsi-minimasonry', plugins_url( 'blocks/allsi-images/build/minimasonry.min.js', __FILE__ ), array(), filemtime( plugin_dir_path( __FILE__ ) . 'blocks/allsi-images/build/minimasonry.min.js' ), true ); $script_dependencies = $asset_file['dependencies']; $script_dependencies[] = 'allsi-minimasonry'; wp_register_style( 'allsi-images-editor-style', plugins_url( 'blocks/allsi-images/build/allsi-images-editor.css', __FILE__ ), array(), filemtime( plugin_dir_path( __FILE__ ) . 'blocks/allsi-images/build/allsi-images-editor.css' ) ); wp_register_script( 'allsi-images-script', plugins_url( 'blocks/allsi-images/build/index.js', __FILE__ ), $script_dependencies, $asset_file['version'] ); register_block_type( 'allsi/allsi-images', array( 'editor_script' => 'allsi-images-script', ) ); $default_post_id = apply_filters( 'ALLSI_media_picker_default_post_id', 0 ); $this->media_picker_default_post_id = $default_post_id; $block_settings = wp_parse_args( get_option( 'ALLSI_plugin_block_settings' ), $this->ALLSI_default_options_block_settings( TRUE ) ); $translation_en_active = ( ! empty( $block_settings['translation_EN'] ) && $block_settings['translation_EN'] == 'true' ); $translate_alt_active = ( ! empty( $block_settings['translate_alt'] ) && $block_settings['translate_alt'] == 'true' ); $translate_alt_lang = ( ! empty( $block_settings['translate_alt_lang'] ) ? $block_settings['translate_alt_lang'] : '' ); wp_localize_script( 'allsi-images-script', 'allsiAjax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'admin_url' => admin_url(), 'nonce' => wp_create_nonce( 'ALLSI_gutenberg_block' ), 'choosed_banks' => $banks['api_chosen_manual'], 'available_banks' => $manual_bank_labels, 'licensing_data' => '1', // All features available 'path_default_img' => plugins_url( '/blocks/allsi-images/img/', __FILE__ ), 'ai_sources' => $this->ALLSI_ai_source_codes(), 'default_post_id' => $default_post_id, 'translation_en' => $translation_en_active, 'translate_alt' => $translate_alt_active, 'translate_alt_lang' => $translate_alt_lang, ) ); // Locate character strings wp_set_script_translations( 'allsi-images-script', 'all-sources-images', plugin_dir_path( __DIR__ ) . 'languages' ); add_action( 'admin_enqueue_scripts', function ( $hook ) { // Checks whether you are on an editing page if ( 'post.php' === $hook || 'post-new.php' === $hook ) { wp_enqueue_script( 'manual-search', plugins_url( 'js/manual_search.js', __FILE__ ), array('wp-blocks', 'wp-data'), $this->version, true ); } } ); // Note: Translations are loaded automatically by WordPress.org for plugins hosted there. } /** * Enqueue style for MPT Gutenberg Block * * @since 5.0.0 */ public function ALLSI_enqueue_style_block() { wp_enqueue_style( 'allsi-images-editor-style' ); } /** * Register Media submenu page for standalone image explorer. */ public function ALLSI_register_media_picker_page() { $this->media_picker_hook = add_submenu_page( 'upload.php', __( 'All Sources Images', 'all-sources-images' ), __( 'All Sources Images', 'all-sources-images' ), 'upload_files', 'allsi-media-browser', array( $this, 'ALLSI_render_media_picker_page' ) ); } /** * Render container for the standalone explorer. */ public function ALLSI_render_media_picker_page() { echo '
' . esc_html__( 'Search and download media from your connected sources without leaving the Media Library.', 'all-sources-images' ) . '
'; echo ''; echo '