settings = $settings ?: new IWAC_Settings(); $this->converter = $converter ?: new IWAC_Converter(); add_action('admin_menu', array($this, 'add_admin_menu')); add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts')); } /** * Add admin menu */ public function add_admin_menu() { $this->page_hooks['dashboard'] = add_menu_page( __('Infinico Image Optimizer', 'infinico-image-optimizer'), __('Infinico Optimizer', 'infinico-image-optimizer'), 'manage_options', 'infinico-image-optimizer', array($this, 'admin_page'), 'dashicons-images-alt2', 30 ); add_submenu_page( 'infinico-image-optimizer', __('Dashboard', 'infinico-image-optimizer'), __('Dashboard', 'infinico-image-optimizer'), 'manage_options', 'infinico-image-optimizer', array($this, 'admin_page') ); $this->page_hooks['settings'] = add_submenu_page( 'infinico-image-optimizer', __('Settings', 'infinico-image-optimizer'), __('Settings', 'infinico-image-optimizer'), 'manage_options', 'infinico-image-optimizer-settings', array($this, 'settings_page') ); $this->page_hooks['bulk'] = add_submenu_page( 'infinico-image-optimizer', __('Bulk Conversion', 'infinico-image-optimizer'), __('Bulk Conversion', 'infinico-image-optimizer'), 'manage_options', 'infinico-image-optimizer-bulk', array($this, 'bulk_conversion_page') ); $this->page_hooks['media'] = add_submenu_page( 'infinico-image-optimizer', __('Media Library', 'infinico-image-optimizer'), __('Media Library', 'infinico-image-optimizer'), 'manage_options', 'infinico-image-optimizer-media', array($this, 'media_list_page') ); $this->page_hooks['logs'] = add_submenu_page( 'infinico-image-optimizer', __('Logs', 'infinico-image-optimizer'), __('Logs', 'infinico-image-optimizer'), 'manage_options', 'infinico-image-optimizer-logs', array($this, 'logs_page') ); } /** * Enqueue scripts and styles */ public function enqueue_scripts($hook) { $page = array_search($hook, $this->page_hooks, true); if (false === $page) { return; } if ('dashboard' !== $page && empty($this->converter->get_supported_output_formats())) { add_action('admin_notices', array($this, 'requirements_notice')); } wp_enqueue_style( 'iwac-admin-styles', IWAC_PLUGIN_URL . 'assets/css/admin-styles.css', array(), IWAC_VERSION ); wp_enqueue_script( 'iwac-admin-scripts', IWAC_PLUGIN_URL . 'assets/js/admin-scripts.js', array('jquery'), IWAC_VERSION, true ); if (in_array($page, array('dashboard', 'bulk', 'media'), true)) { wp_enqueue_script( 'iwac-converter-scripts', IWAC_PLUGIN_URL . 'assets/js/converter-scripts.js', array('jquery', 'iwac-admin-scripts'), IWAC_VERSION, true ); } wp_localize_script('iwac-admin-scripts', 'iwac_ajax', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('iwac_ajax_nonce'), 'settings' => $this->settings->get_settings(), 'urls' => array( 'dashboard' => admin_url('admin.php?page=infinico-image-optimizer'), 'settings' => admin_url('admin.php?page=infinico-image-optimizer-settings'), 'bulk' => admin_url('admin.php?page=infinico-image-optimizer-bulk'), 'media' => admin_url('admin.php?page=infinico-image-optimizer-media'), 'logs' => admin_url('admin.php?page=infinico-image-optimizer-logs'), 'readme' => IWAC_PLUGIN_URL . 'README.md', ), 'defaults' => array( 'default_format' => 'webp', 'webp_quality' => 80, 'avif_quality' => 70, 'convert_on_upload' => 0, 'keep_original' => 1, 'bulk_batch_size' => 5, ), 'strings' => array( 'converting' => __('Converting...', 'infinico-image-optimizer'), 'converted' => __('Converted', 'infinico-image-optimizer'), 'convert_selected' => __('Convert Selected', 'infinico-image-optimizer'), 'convert_to_format' => /* translators: Image format, such as WebP or AVIF. */ __('Convert to %s', 'infinico-image-optimizer'), 'please_select_images' => __('Please select images to convert.', 'infinico-image-optimizer'), 'please_choose_action' => __('Please choose a bulk action first.', 'infinico-image-optimizer'), 'ajax_error' => __('AJAX error occurred.', 'infinico-image-optimizer'), 'confirm_bulk' => __('Are you sure you want to convert all selected images?', 'infinico-image-optimizer'), 'conversion_completed' => __('Conversion completed!', 'infinico-image-optimizer'), 'images_converted' => __('images converted', 'infinico-image-optimizer'), 'reset_confirm' => __('Reset all settings fields back to default values?', 'infinico-image-optimizer'), 'info_text' => __('Infinico Image Optimizer lets you convert media library images to WebP and AVIF, review logs, and manage optimization settings from one dashboard.', 'infinico-image-optimizer'), ), )); if ('logs' === $page) { wp_enqueue_script( 'iwac-logs-viewer', IWAC_PLUGIN_URL . 'assets/js/logs-viewer.js', array('jquery'), IWAC_VERSION, true ); } } /** * Explain missing image support on the plugin's own screens. */ public function requirements_notice() { echo '

'; esc_html_e('Image conversion requires GD or Imagick with WebP or AVIF support. Ask your hosting provider to enable a supported image format.', 'infinico-image-optimizer'); echo '

'; } /** * Admin dashboard page */ public function admin_page() { if (!current_user_can('manage_options')) { wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'infinico-image-optimizer')); } include IWAC_PLUGIN_DIR . 'templates/admin-dashboard.php'; } /** * Settings page */ public function settings_page() { if (!current_user_can('manage_options')) { wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'infinico-image-optimizer')); } include IWAC_PLUGIN_DIR . 'templates/settings-page.php'; } /** * Bulk conversion page */ public function bulk_conversion_page() { if (!current_user_can('manage_options')) { wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'infinico-image-optimizer')); } include IWAC_PLUGIN_DIR . 'templates/bulk-conversion.php'; } /** * Media list page */ public function media_list_page() { if (!current_user_can('manage_options')) { wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'infinico-image-optimizer')); } include IWAC_PLUGIN_DIR . 'templates/media-list.php'; } /** * Logs page */ public function logs_page() { if (!current_user_can('manage_options')) { wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'infinico-image-optimizer')); } include IWAC_PLUGIN_DIR . 'templates/logs.php'; } /** * Add actions to media library rows */ public function add_media_actions($actions, $post) { if ($post->post_type !== 'attachment' || !wp_attachment_is_image($post->ID)) { return $actions; } $file_path = get_attached_file($post->ID); $extension = $file_path ? strtolower(pathinfo($file_path, PATHINFO_EXTENSION)) : ''; if (! in_array($extension, $this->converter->get_supported_input_formats(), true)) { return $actions; } $supported_formats = $this->converter->get_supported_output_formats(); if (empty($supported_formats)) { return $actions; } $conversion_status = $this->converter->get_conversion_status($post->ID); foreach ($supported_formats as $format) { if (!isset($conversion_status[$format])) { $actions['convert_to_' . $format] = sprintf( '%s', $post->ID, esc_attr($format), esc_html(sprintf(/* translators: Image format, such as WebP or AVIF. */ __('Convert to %s', 'infinico-image-optimizer'), strtoupper($format))) ); } else { $actions['convert_to_' . $format] = sprintf( '%s (%s)', esc_html(sprintf(/* translators: Image format, such as WebP or AVIF. */ __('Converted to %s', 'infinico-image-optimizer'), strtoupper($format))), esc_html(date_i18n(get_option('date_format'), $conversion_status[$format]['converted_at'])) ); } } return $actions; } /** * Get images for dashboard */ public function get_images_for_dashboard($page = 1, $per_page = 20) { $args = array( 'post_type' => 'attachment', 'post_mime_type' => 'image', 'posts_per_page' => $per_page, 'paged' => $page, 'post_status' => 'inherit', ); $query = new WP_Query($args); $images = array(); foreach ($query->posts as $post) { $metadata = wp_get_attachment_metadata($post->ID); $conversion_status = $this->converter->get_conversion_status($post->ID); $size_bytes = 0; $file_path = get_attached_file($post->ID); $filename = $file_path ? basename($file_path) : $post->post_title; $source_extension = $file_path ? strtolower(pathinfo($file_path, PATHINFO_EXTENSION)) : ''; $is_convertible_source = in_array($source_extension, $this->converter->get_supported_input_formats(), true); $is_next_gen_source = in_array($source_extension, array('webp', 'avif'), true) && $file_path && is_file($file_path) && filesize($file_path) > 0 && wp_getimagesize($file_path); if (isset($metadata['filesize'])) { $size_bytes = (int) $metadata['filesize']; } elseif ($file_path && file_exists($file_path)) { $size_bytes = filesize($file_path); } if ($conversion_status) { $primary_conversion = reset($conversion_status); $size_bytes = (int) $primary_conversion['original_size']; } $images[] = array( 'id' => $post->ID, 'title' => $post->post_title, 'url' => wp_get_attachment_url($post->ID), 'edit_url' => get_edit_post_link($post->ID, ''), 'filename' => $filename, 'uploaded_label' => sprintf( /* translators: %s is a human-readable relative time. */ /* translators: Number of images. */ __('Uploaded: %s ago', 'infinico-image-optimizer'), human_time_diff(get_post_time('U', true, $post), current_time('timestamp', true)) ), 'size' => $size_bytes ? size_format($size_bytes) : '', 'size_bytes' => $size_bytes, 'dimensions' => isset($metadata['width']) && isset($metadata['height']) ? $metadata['width'] . 'x' . $metadata['height'] : '', 'conversions' => $conversion_status, 'source_extension' => $source_extension, 'is_convertible_source' => $is_convertible_source, 'is_next_gen_source' => $is_next_gen_source, ); } return array( 'images' => $images, 'total' => $query->found_posts, 'pages' => $query->max_num_pages, ); } }