PluginProbe
Auto Alt Text / 2.4.0
Auto Alt Text v2.4.0
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
auto-alt-text / src / App / Setup.php

Setup.php in Auto Alt Text 2.4.0, at src/App/Setup.php

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