PluginProbe
Auto Alt Text / 2.5.2
Auto Alt Text v2.5.2
3.0.3 2.8.2 1.3.1 1.3.2 2.0.0 2.1.0 2.1.1 2.2.0 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.5.0 2.5.1 2.5.2 2.5.3 2.6.0 2.6.1 2.7.0 2.8.0 2.8.1 All 28 releases
← All changes | src/App/Setup.php +276 -27 2.8.22.5.2 View file →
@@ -1,49 +1,298 @@
1 1 <?php
2 2
3 3 namespace AATXT\App;
4 4
5 -use AATXT\App\Core\Container;
6 -use AATXT\App\Core\PluginBootstrap;
7 -use AATXT\App\Services\AltTextService;
5 +use AATXT\App\Admin\MediaLibrary;
6 +use AATXT\App\AIProviders\Anthropic\AnthropicResponse;
7 +use AATXT\App\Exceptions\Anthropic\AnthropicException;
8 +use AATXT\App\Logging\DBLogger;
9 +use AATXT\App\Admin\PluginOptions;
10 +use AATXT\App\AIProviders\Azure\AzureComputerVisionCaptionsResponse;
11 +use AATXT\App\AIProviders\OpenAI\Fallback;
12 +use AATXT\App\AIProviders\OpenAI\OpenAIVision;
13 +use AATXT\App\Exceptions\Azure\AzureException;
14 +use AATXT\App\Exceptions\OpenAI\OpenAIException;
15 +use AATXT\Config\Constants;
16 +use WpOrg\Requests\Exception;
8 17
9 -/**
10 - * Legacy Setup class maintained for backward compatibility.
11 - *
12 - * @deprecated 2.6.0 Use PluginBootstrap::init() and dependency injection for new code.
13 - * All methods in this class are deprecated and will be removed in v3.0.0.
14 - * Use AltTextService via dependency injection instead of Setup::altText().
15 - */
18 +
16 19 class Setup
17 20 {
21 + private static ?self $instance = null;
22 +
23 + private function __construct()
24 + {
25 + //
26 + }
27 +
18 28 /**
19 - * Register plugin functionalities.
20 - *
21 - * @deprecated 2.6.0 Use PluginBootstrap::init() instead.
29 + * Register plugin functionalities
22 30 * @return void
23 31 */
24 32 public static function register(): void
25 33 {
26 - _deprecated_function(__METHOD__, '2.6.0', 'PluginBootstrap::init()');
27 - PluginBootstrap::init(AATXT_FILE_ABSPATH);
34 + if (is_null(self::$instance)) {
35 + self::$instance = new self();
36 + }
37 +
38 + //Register plugin options pages
39 + PluginOptions::register();
40 + //Register medial library hooks
41 + MediaLibrary::register();
42 +
43 + register_activation_hook(AATXT_FILE_ABSPATH, [self::$instance, 'activatePlugin']);
44 + register_deactivation_hook(AATXT_FILE_ABSPATH, [self::$instance, 'deactivatePlugin']);
45 +
46 + // When attachment is uploaded, create alt text
47 + add_action('add_attachment', [self::$instance, 'addAltText']);
48 + // When plugin is loaded, load text domain
49 + add_action('plugins_loaded', [self::$instance, 'loadTextDomain']);
50 + // Add settings link to the plugin in the plugins listing
51 + add_filter('plugin_action_links_auto-alt-text/auto-alt-text.php', [self::$instance, 'settingsLink']);
52 + // Register bulk action for media library
53 + add_filter('bulk_actions-upload', [self::$instance, 'registerBulkAction']);
54 + // Handle alt text generation bulk action for media library
55 + add_action('load-upload.php', [self::$instance, 'handleAltTextBulkAction']);
56 + // Display a notice after alt text generation bulk action
57 + add_action('admin_notices', [self::$instance, 'altTextBulkActionAdminNotice']);
28 58 }
29 59
30 60 /**
31 - * Generate alt text for an attachment.
32 - *
33 - * This method is kept for backward compatibility with external code
34 - * that may call Setup::altText() directly.
35 - *
36 - * @deprecated 2.6.0 Use AltTextService::generateForAttachment() via dependency injection instead.
37 - * @param int $postId The attachment post ID
38 - * @return string Generated alt text, or empty string if generation fails
61 + * Register bulk action for media library
39 62 */
63 + public static function registerBulkAction(array $actions): array
64 + {
65 + $actions['auto_alt_text'] = esc_attr__('Generate Alt Text', 'auto-alt-text');
66 + return $actions;
67 + }
68 +
69 + /**
70 + * Handle alt text generation bulk action for media library
71 + */
72 + public static function handleAltTextBulkAction()
73 + {
74 + $mediaUpdated = 0;
75 + $wpListTable = _get_list_table('WP_Media_List_Table');
76 + $action = $wpListTable->current_action();
77 +
78 + if ($action === 'auto_alt_text') {
79 + // Recupera l'elenco degli ID dei media selezionati
80 + $mediaIds = isset($_REQUEST['media']) ? $_REQUEST['media'] : array();
81 +
82 + // Imposta l'alt text per ogni media selezionato
83 + foreach ($mediaIds as $mediaId) {
84 + $altText = self::altText($mediaId);
85 + if (!empty($altText)) {
86 + update_post_meta($mediaId, '_wp_attachment_image_alt', $altText);
87 + $mediaUpdated++;
88 + }
89 + }
90 +
91 + $callBackData = [
92 + 'mediaSelected' => count($mediaIds),
93 + 'mediaUpdated' => $mediaUpdated,
94 + 'auto_alt_text' => '1',
95 + ];
96 +
97 + // Redirect alla pagina della media library con un messaggio di successo
98 + $sendback = add_query_arg(
99 + $callBackData,
100 + admin_url('upload.php')
101 + );
102 + wp_redirect($sendback);
103 + exit();
104 + }
105 + }
106 +
107 + /**
108 + * Display a notice after alt text generation bulk action
109 + */
110 + public static function altTextBulkActionAdminNotice()
111 + {
112 + if (isset($_REQUEST['auto_alt_text'])) {
113 + $mediaSelected = intval($_REQUEST['mediaSelected']);
114 + $mediaUpdated = intval($_REQUEST['mediaUpdated']);
115 +
116 + $errorLogDisclaimer = __('Take a look at the', 'auto-alt-text') . ' <a href="' . esc_url(menu_page_url(Constants::AATXT_PLUGIN_OPTION_LOG_PAGE_SLUG, false)) . '">' . __('error log', 'auto-alt-text') . '</a>.';
117 +
118 + if ($mediaUpdated === 0) {
119 + printf('<div id="message" class="notice notice-error is-dismissible"><p>' . esc_attr__('No Alt Text has been set.', 'auto-alt-text') . ' %s</p></div>', $errorLogDisclaimer);
120 + } elseif ($mediaSelected === $mediaUpdated) {
121 + /**
122 + * translators:
123 + * %s = number of images processed
124 + */
125 + printf('<div id="message" class="updated notice is-dismissible"><p>' . esc_attr__('The Alt Text has been set for %s media.', 'auto-alt-text') . '</p></div>', $mediaUpdated);
126 + } else {
127 + /**
128 + * translators:
129 + * %1$s = number of media items successfully updated
130 + * %2$s = total number of media items selected
131 + * %3$s = HTML disclaimer/link to the error log
132 + */
133 + printf(
134 + '<div id="message" class="notice notice-warning is-dismissible"><p>%s</p></div>',
135 + sprintf(
136 + /* translators: 1 = updated count, 2 = selected count, 3 = disclaimer HTML */
137 + __( 'The Alt Text has been set for %1$s of %2$s media. %3$s', 'auto-alt-text' ),
138 + number_format_i18n( $mediaUpdated ),
139 + number_format_i18n( $mediaSelected ),
140 + wp_kses_post( $errorLogDisclaimer )
141 + )
142 + );
143 + }
144 + }
145 + }
146 +
147 + /**
148 + * Create a Logs table on plugin activation
149 + */
150 + public static function activatePlugin(): void
151 + {
152 + DBLogger::make()->createLogTable();
153 + }
154 +
155 + /**
156 + * Drop Logs table on plugin deactivation
157 + */
158 + public static function deactivatePlugin(): void
159 + {
160 + DBLogger::make()->dropLogTable();
161 + }
162 +
163 + /**
164 + * Add link to the options page of the plugin in the plugins listing
165 + */
166 + public static function settingsLink(array $links): array
167 + {
168 + $url = esc_url(add_query_arg(
169 + 'page',
170 + 'auto-alt-text-options',
171 + get_admin_url() . 'admin.php'
172 + ));
173 + $settingsLink = "<a href='$url'>" . esc_html__('Settings', 'auto-alt-text') . '</a>';
174 + $links[] = $settingsLink;
175 +
176 + return $links;
177 + }
178 +
179 + /**
180 + * Load text domain
181 + * @return void
182 + */
183 + public static function loadTextDomain(): void
184 + {
185 + load_plugin_textdomain('auto-alt-text', false, AATXT_LANGUAGES_RELATIVE_PATH);
186 + }
187 +
188 + /**
189 + * @param array<string> $allowedMimeTypes
190 + */
191 + private static function allowedMimeTypesList(array $allowedMimeTypes): string
192 + {
193 + return str_replace('image/', '' , implode(', ', $allowedMimeTypes));
194 + }
195 +
196 + /**
197 + * @param int $postId
198 + * @return string
199 + */
40 200 public static function altText(int $postId): string
41 201 {
42 - _deprecated_function(__METHOD__, '2.6.0', 'AltTextService::generateForAttachment()');
202 + if (!wp_attachment_is_image($postId)) {
203 + return '';
204 + }
43 205
44 - $container = Container::make();
45 - $altTextService = $container->get(AltTextService::class);
206 + if (PluginOptions::preserveExistingAltText()) {
207 + $altText = get_post_meta($postId, '_wp_attachment_image_alt', TRUE);
46 208
47 - return $altTextService->generateForAttachment($postId);
209 + if (!empty($altText)) {
210 + return $altText;
211 + }
212 + }
213 +
214 + $mimeType = get_post_mime_type($postId);
215 +
216 + switch (PluginOptions::typology()) {
217 + case Constants::AATXT_OPTION_TYPOLOGY_CHOICE_AZURE:
218 + if (!in_array($mimeType, Constants::AATXT_AZURE_ALLOWED_MIME_TYPES, true)) {
219 + $formats = self::allowedMimeTypesList(Constants::AATXT_AZURE_ALLOWED_MIME_TYPES);
220 + (DBLogger::make())->writeImageLog($postId, "You uploaded an unsupported image. Please make sure your image has of one the following formats: $formats");
221 + return '';
222 + }
223 + try {
224 + $altText = (AltTextGeneratorAi::make(AzureComputerVisionCaptionsResponse::make()))->altText($postId);
225 + } catch (AzureException $e) {
226 + (DBLogger::make())->writeImageLog($postId, "Azure - " . $e->getMessage());
227 + }
228 + break;
229 + case Constants::AATXT_OPTION_TYPOLOGY_CHOICE_ANTHROPIC:
230 + if (!in_array($mimeType, Constants::AATXT_ANTHROPIC_ALLOWED_MIME_TYPES, true)) {
231 + $formats = self::allowedMimeTypesList(Constants::AATXT_ANTHROPIC_ALLOWED_MIME_TYPES);
232 + (DBLogger::make())->writeImageLog($postId, "You uploaded an unsupported image. Please make sure your image has of one the following formats: $formats");
233 + return '';
234 + }
235 +
236 + try {
237 + $altText = (AltTextGeneratorAi::make(AnthropicResponse::make()))->altText($postId);
238 + } catch (AnthropicException $e) {
239 + $errorMessage = "Anthropic - " . ' - ' . $e->getMessage();
240 + (DBLogger::make())->writeImageLog($postId, $errorMessage);
241 + }
242 +
243 + break;
244 + case Constants::AATXT_OPTION_TYPOLOGY_CHOICE_OPENAI:
245 + if (!in_array($mimeType, Constants::AATXT_OPENAI_ALLOWED_MIME_TYPES, true)) {
246 + $formats = self::allowedMimeTypesList(Constants::AATXT_OPENAI_ALLOWED_MIME_TYPES);
247 + (DBLogger::make())->writeImageLog($postId, "You uploaded an unsupported image. Please make sure your image has of one the following formats: $formats");
248 + return '';
249 + }
250 + try {
251 + $altText = (AltTextGeneratorAi::make(OpenAIVision::make()))->altText($postId);
252 + } catch (OpenAIException $e) {
253 + //If vision model fails, try with a fallback model
254 + $errorMessage = "OpenAI - " . Constants::AATXT_OPENAI_VISION_MODEL . ' - ' . $e->getMessage();
255 + (DBLogger::make())->writeImageLog($postId, $errorMessage);
256 + try {
257 + $altText = (AltTextGeneratorAi::make(Fallback::make()))->altText($postId);
258 + } catch (OpenAIException $e) {
259 + $errorMessage = "OpenAI - " . $e->getMessage();
260 + (DBLogger::make())->writeImageLog($postId, $errorMessage);
261 + }
262 + }
263 + break;
264 + case Constants::AATXT_OPTION_TYPOLOGY_CHOICE_ARTICLE_TITLE:
265 + // If Article title is selected as alt text generating typology
266 + $parentId = wp_get_post_parent_id($postId);
267 + if ($parentId) {
268 + $altText = (AltTextGeneratorParentPostTitle::make())->altText($postId);
269 + } else {
270 + //If media has not a parent use the Attachment Title method as fallback
271 + $altText = (AltTextGeneratorAttachmentTitle::make())->altText($postId);
272 + }
273 + break;
274 + case Constants::AATXT_OPTION_TYPOLOGY_CHOICE_ATTACHMENT_TITLE:
275 + // If Attachment title is selected as alt text generating typology
276 + $altText = (AltTextGeneratorAttachmentTitle::make())->altText($postId);
277 + break;
278 + default:
279 + return '';
280 + }
281 +
282 + return $altText ?? '';
283 + }
284 +
285 + /**
286 + * @param int $postId
287 + * @return void
288 + */
289 + public static function addAltText(int $postId): void
290 + {
291 + $altText = self::altText($postId);
292 + if (empty($altText)) {
293 + return;
294 + }
295 +
296 + update_post_meta($postId, '_wp_attachment_image_alt', $altText);
48 297 }
49 298 }