settings = get_option( 'aitm_settings', array() ); } /** * Run the plugin */ public function run() { // Initialize thumbnail generator $this->init_thumbnail_generator(); // Initialize admin components if ( is_admin() ) { $this->init_admin(); } // Register AJAX handlers $this->init_ajax_handlers(); // Register hooks for auto generation $this->init_auto_generation_hooks(); } /** * Initialize thumbnail generator */ private function init_thumbnail_generator() { $this->thumbnail_generator = new AITM_Thumbnail_Generator( $this->settings ); } /** * Initialize admin components */ private function init_admin() { // First create main menu (Dashboard) $dashboard_page = new AITM_Dashboard_Page(); add_action( 'admin_menu', array( $dashboard_page, 'add_menu_page' ), 9 ); add_action( 'admin_enqueue_scripts', array( $dashboard_page, 'enqueue_scripts' ) ); // Add Settings page (priority 10 to be second in submenu) $admin_settings = new AITM_Admin_Settings(); add_action( 'admin_menu', array( $admin_settings, 'add_menu_page' ), 10 ); add_action( 'admin_init', array( $admin_settings, 'register_settings' ) ); add_action( 'admin_enqueue_scripts', array( $admin_settings, 'enqueue_scripts' ) ); // Add Regenerate page (priority 11 to be third in submenu) require_once AITM_PLUGIN_DIR . 'admin/class-regenerate-page.php'; $regenerate_page = new AITM_Regenerate_Page(); add_action( 'admin_menu', array( $regenerate_page, 'add_menu_page' ), 11 ); add_action( 'admin_enqueue_scripts', array( $regenerate_page, 'enqueue_scripts' ) ); // Add What's New page (priority 12 to be fourth in submenu) require_once AITM_PLUGIN_DIR . 'admin/class-whats-new-page.php'; $whats_new_page = new AITM_Whats_New_Page(); add_action( 'admin_menu', array( $whats_new_page, 'add_menu_page' ), 12 ); add_action( 'admin_enqueue_scripts', array( $whats_new_page, 'enqueue_scripts' ) ); // Initialize admin columns (thumbnail preview in posts list) new AITM_Admin_Columns(); } /** * Initialize AJAX handlers */ private function init_ajax_handlers() { // Get posts list for generation add_action( 'wp_ajax_aitm_get_posts', array( $this, 'ajax_get_posts' ) ); // Generate thumbnail for post add_action( 'wp_ajax_aitm_generate_thumbnail', array( $this, 'ajax_generate_thumbnail' ) ); // Delete thumbnail add_action( 'wp_ajax_aitm_delete_thumbnail', array( $this, 'ajax_delete_thumbnail' ) ); // Get statistics add_action( 'wp_ajax_aitm_get_statistics', array( $this, 'ajax_get_statistics' ) ); // Regenerate thumbnails handlers add_action( 'wp_ajax_aitm_get_attachments', array( $this, 'ajax_get_attachments' ) ); add_action( 'wp_ajax_aitm_regenerate_attachment', array( $this, 'ajax_regenerate_attachment' ) ); add_action( 'wp_ajax_aitm_get_thumbnail_sizes', array( $this, 'ajax_get_thumbnail_sizes' ) ); } /** * Initialize auto generation hooks */ private function init_auto_generation_hooks() { $auto_generation = $this->settings['auto_generation'] ?? true; if ( ! $auto_generation ) { return; } $enabled_post_types = $this->settings['enabled_post_types'] ?? array( 'post', 'page' ); // Hook on post save add_action( 'save_post', array( $this, 'auto_generate_on_save' ), 10, 3 ); // Hook on post status transition add_action( 'transition_post_status', array( $this, 'auto_generate_on_transition' ), 10, 3 ); } /** * Auto generate thumbnail on post save * * @param int $post_id Post ID. * @param WP_Post $post Post object. * @param bool $update Whether this is an existing post being updated. */ public function auto_generate_on_save( $post_id, $post, $update ) { // Skip autosaves and revisions if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) { return; } // Check post type $enabled_post_types = $this->settings['enabled_post_types'] ?? array( 'post', 'page' ); if ( ! in_array( $post->post_type, $enabled_post_types, true ) ) { return; } // Check post status if ( $post->post_status !== 'publish' ) { return; } // Check if already has thumbnail $overwrite_existing = $this->settings['overwrite_existing'] ?? false; if ( ! $overwrite_existing && has_post_thumbnail( $post_id ) ) { return; } // Generate thumbnail $this->thumbnail_generator->generate_for_post( $post_id ); } /** * Auto generate thumbnail on post status transition * * @param string $new_status New post status. * @param string $old_status Old post status. * @param WP_Post $post Post object. */ public function auto_generate_on_transition( $new_status, $old_status, $post ) { // Generate only when transitioning to publish if ( $new_status !== 'publish' || $old_status === 'publish' ) { return; } // Check post type $enabled_post_types = $this->settings['enabled_post_types'] ?? array( 'post', 'page' ); if ( ! in_array( $post->post_type, $enabled_post_types, true ) ) { return; } // Check if already has thumbnail $overwrite_existing = $this->settings['overwrite_existing'] ?? false; if ( ! $overwrite_existing && has_post_thumbnail( $post->ID ) ) { return; } // Generate thumbnail $this->thumbnail_generator->generate_for_post( $post->ID ); } /** * AJAX: Get posts for generation */ public function ajax_get_posts() { check_ajax_referer( 'aitm_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied', 'ai-thumbnails-maker' ) ) ); } $post_type = isset( $_POST['post_type'] ) ? sanitize_text_field( wp_unslash( $_POST['post_type'] ) ) : 'post'; $with_thumb = isset( $_POST['with_thumb'] ) ? (bool) $_POST['with_thumb'] : false; $args = array( 'post_type' => $post_type, 'post_status' => 'publish', 'posts_per_page' => -1, 'fields' => 'ids', ); // Reload settings to get fresh overwrite_existing value $fresh_settings = get_option( 'aitm_settings', array() ); $overwrite_existing = $fresh_settings['overwrite_existing'] ?? false; // If overwrite is disabled or with_thumb is false, filter posts without thumbnail if ( ! $overwrite_existing || ! $with_thumb ) { $args['meta_query'] = array( array( 'key' => '_thumbnail_id', 'compare' => 'NOT EXISTS', ), ); } $query = new WP_Query( $args ); wp_send_json_success( array( 'posts' => $query->posts ) ); } /** * AJAX: Generate thumbnail for post */ public function ajax_generate_thumbnail() { check_ajax_referer( 'aitm_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied', 'ai-thumbnails-maker' ) ) ); } $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0; if ( ! $post_id ) { wp_send_json_error( array( 'message' => __( 'Invalid post ID', 'ai-thumbnails-maker' ) ) ); } // Reload settings to get fresh values $fresh_settings = get_option( 'aitm_settings', array() ); $this->thumbnail_generator = new AITM_Thumbnail_Generator( $fresh_settings ); $result = $this->thumbnail_generator->generate_for_post( $post_id ); if ( $result['success'] ) { wp_send_json_success( $result ); } else { wp_send_json_error( $result ); } } /** * AJAX: Delete thumbnail */ public function ajax_delete_thumbnail() { check_ajax_referer( 'aitm_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied', 'ai-thumbnails-maker' ) ) ); } $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0; if ( ! $post_id ) { wp_send_json_error( array( 'message' => __( 'Invalid post ID', 'ai-thumbnails-maker' ) ) ); } $deleted = delete_post_thumbnail( $post_id ); if ( $deleted ) { wp_send_json_success( array( 'message' => __( 'Thumbnail deleted', 'ai-thumbnails-maker' ) ) ); } else { wp_send_json_error( array( 'message' => __( 'Failed to delete thumbnail', 'ai-thumbnails-maker' ) ) ); } } /** * AJAX: Get statistics */ public function ajax_get_statistics() { check_ajax_referer( 'aitm_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied', 'ai-thumbnails-maker' ) ) ); } $post_type = isset( $_POST['post_type'] ) ? sanitize_text_field( wp_unslash( $_POST['post_type'] ) ) : 'post'; // Reload settings to get fresh values $fresh_settings = get_option( 'aitm_settings', array() ); $this->thumbnail_generator = new AITM_Thumbnail_Generator( $fresh_settings ); $stats = $this->thumbnail_generator->get_statistics( $post_type ); wp_send_json_success( $stats ); } /** * AJAX: Get attachments for regeneration */ public function ajax_get_attachments() { check_ajax_referer( 'aitm_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied', 'ai-thumbnails-maker' ) ) ); } $filter = isset( $_POST['filter'] ) ? sanitize_text_field( wp_unslash( $_POST['filter'] ) ) : 'all'; $args = array( 'post_type' => 'attachment', 'post_mime_type' => 'image', 'post_status' => 'inherit', 'posts_per_page' => -1, 'fields' => 'ids', ); // Filter for featured images only if ( $filter === 'featured' ) { global $wpdb; // Try to get from cache $cache_key = 'aitm_featured_ids_' . $post_type; $featured_ids = wp_cache_get( $cache_key, 'aitm' ); if ( false === $featured_ids ) { // Get all attachment IDs that are used as featured images $featured_ids = $wpdb->get_col( "SELECT DISTINCT meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_thumbnail_id' AND meta_value > 0" ); // Cache for 5 minutes wp_cache_set( $cache_key, $featured_ids, 'aitm', 300 ); } if ( empty( $featured_ids ) ) { wp_send_json_success( array( 'attachments' => array() ) ); return; } $args['post__in'] = $featured_ids; } $query = new WP_Query( $args ); wp_send_json_success( array( 'attachments' => $query->posts ) ); } /** * AJAX: Regenerate attachment */ public function ajax_regenerate_attachment() { check_ajax_referer( 'aitm_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied', 'ai-thumbnails-maker' ) ) ); } $attachment_id = isset( $_POST['attachment_id'] ) ? absint( $_POST['attachment_id'] ) : 0; if ( ! $attachment_id ) { wp_send_json_error( array( 'message' => __( 'Invalid attachment ID', 'ai-thumbnails-maker' ) ) ); } $options = array( 'only_missing' => isset( $_POST['only_missing'] ) ? (bool) $_POST['only_missing'] : true, 'delete_old' => isset( $_POST['delete_old'] ) ? (bool) $_POST['delete_old'] : false, ); require_once AITM_PLUGIN_DIR . 'includes/class-thumbnail-regenerator.php'; $regenerator = new AITM_Thumbnail_Regenerator(); $result = $regenerator->regenerate_attachment( $attachment_id, $options ); if ( $result['success'] ) { wp_send_json_success( $result ); } else { wp_send_json_error( $result ); } } /** * AJAX: Get thumbnail sizes */ public function ajax_get_thumbnail_sizes() { check_ajax_referer( 'aitm_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied', 'ai-thumbnails-maker' ) ) ); } require_once AITM_PLUGIN_DIR . 'includes/class-thumbnail-regenerator.php'; $regenerator = new AITM_Thumbnail_Regenerator(); $sizes = $regenerator->get_registered_sizes(); wp_send_json_success( array( 'sizes' => $sizes ) ); } }