PluginProbe
Auto Alt Text / trunk
Auto Alt Text vtrunk
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 / CLI / AutoAltTextCommand.php

AutoAltTextCommand.php in Auto Alt Text trunk, at src/App/CLI/AutoAltTextCommand.php

220 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace AATXT\App\CLI;
6
7 use AATXT\App\Admin\PluginOptions;
8 use AATXT\App\Services\AltTextService;
9 use AATXT\Config\Constants;
10
11 final class AutoAltTextCommand extends \WP_CLI_Command
12 {
13 private AltTextService $altTextService;
14
15 public function __construct(AltTextService $altTextService)
16 {
17 $this->altTextService = $altTextService;
18 }
19
20 /**
21 * Generate and save image alt text for attachments.
22 *
23 * ## OPTIONS
24 *
25 * [--ids=<ids>]
26 * : Comma-separated list of attachment IDs.
27 *
28 * [--all]
29 * : Process attachments using a query (images only). Use with --limit/--offset to batch.
30 *
31 * [--limit=<n>]
32 * : Max number of attachments to process when using --all.
33 *
34 * [--offset=<n>]
35 * : Offset when using --all.
36 *
37 * [--dry-run]
38 * : Do not update metadata; only show what would happen.
39 *
40 * [--force]
41 * : Overwrite existing alt text even if the plugin setting "Keep existing alt text" is enabled.
42 *
43 * ## EXAMPLES
44 *
45 * wp auto-alt-text generate --ids=123,456
46 * wp auto-alt-text generate --all --limit=200 --offset=0
47 * wp auto-alt-text generate --all --limit=200 --offset=200
48 *
49 * @subcommand generate
50 */
51 public function generate(array $args, array $assocArgs): void
52 {
53 $idsArg = isset($assocArgs['ids']) ? (string) $assocArgs['ids'] : '';
54 $all = isset($assocArgs['all']);
55 $dryRun = isset($assocArgs['dry-run']);
56 $force = isset($assocArgs['force']);
57
58 $isQueryMode = ($idsArg === '' && $all);
59
60 $limit = isset($assocArgs['limit'])
61 ? (int) $assocArgs['limit']
62 : ($isQueryMode ? 100 : -1);
63
64 $offset = isset($assocArgs['offset']) ? (int) $assocArgs['offset'] : 0;
65
66 if ($isQueryMode) {
67 if ($limit < 1) {
68 \WP_CLI::error('Invalid --limit. Must be >= 1 when using --all.');
69 }
70 } else {
71 if ($limit < 1 && $limit !== -1) {
72 \WP_CLI::error('Invalid --limit. Must be >= 1.');
73 }
74 }
75
76 if ($offset < 0) {
77 \WP_CLI::error('Invalid --offset. Must be >= 0.');
78 }
79
80 if ($idsArg === '' && ! $all) {
81 \WP_CLI::error('Specify either --ids=<csv> or --all');
82 }
83
84 $ids = [];
85 if ($idsArg !== '') {
86 $ids = array_values(array_filter(array_map('absint', preg_split('/\s*,\s*/', $idsArg))));
87 $ids = array_values(array_unique($ids));
88 }
89
90 if (! $isQueryMode && $ids === []) {
91 \WP_CLI::success('No attachments found.');
92 return;
93 }
94
95 $preserveOptionKey = Constants::AATXT_OPTION_FIELD_PRESERVE_EXISTING_ALT_TEXT;
96 $originalPreserve = get_option($preserveOptionKey);
97
98 if ($force) {
99 update_option($preserveOptionKey, 0);
100 }
101
102 $processed = 0;
103 $updated = 0;
104 $skipped = 0;
105 $failed = 0;
106
107 if ($isQueryMode) {
108 $countQuery = new \WP_Query([
109 'post_type' => 'attachment',
110 'post_status' => 'inherit',
111 'post_mime_type' => 'image',
112 'fields' => 'ids',
113 'posts_per_page' => 1,
114 'offset' => 0,
115 'orderby' => 'ID',
116 'order' => 'DESC',
117 ]);
118
119 $totalToProcess = max(0, (int) $countQuery->found_posts - $offset);
120 } else {
121 $totalToProcess = count($ids);
122 }
123
124 $progress = \WP_CLI\Utils\make_progress_bar('Generating alt text', $totalToProcess);
125
126 try {
127 $currentOffset = $offset;
128 $batchIds = $ids;
129
130 while (true) {
131 if ($isQueryMode) {
132 $query = new \WP_Query([
133 'post_type' => 'attachment',
134 'post_status' => 'inherit',
135 'post_mime_type' => 'image',
136 'fields' => 'ids',
137 'posts_per_page' => $limit,
138 'offset' => $currentOffset,
139 'orderby' => 'ID',
140 'order' => 'DESC',
141 'no_found_rows' => true,
142 ]);
143
144 $batchIds = array_map('intval', $query->posts);
145 if ($batchIds === []) {
146 break;
147 }
148
149 $currentOffset += count($batchIds);
150 } else {
151 if ($batchIds === []) {
152 break;
153 }
154 }
155
156 foreach ($batchIds as $attachmentId) {
157 $attachmentId = (int) $attachmentId;
158
159 if ($attachmentId < 1) {
160 $failed++;
161 $processed++;
162 $progress->tick();
163 continue;
164 }
165
166 if (! wp_attachment_is_image($attachmentId)) {
167 $skipped++;
168 $processed++;
169 $progress->tick();
170 continue;
171 }
172
173 if (! $force && PluginOptions::preserveExistingAltText()) {
174 $existingAlt = (string) get_post_meta($attachmentId, '_wp_attachment_image_alt', true);
175 if ($existingAlt !== '') {
176 $skipped++;
177 $processed++;
178 $progress->tick();
179 continue;
180 }
181 }
182
183 $altText = $this->altTextService->generateForAttachment($attachmentId);
184
185 if ($altText === '') {
186 $failed++;
187 $processed++;
188 $progress->tick();
189 continue;
190 }
191
192 if (! $dryRun) {
193 update_post_meta($attachmentId, '_wp_attachment_image_alt', $altText);
194 }
195
196 $updated++;
197 $processed++;
198 $progress->tick();
199 }
200
201 if (! $isQueryMode) {
202 break;
203 }
204 }
205 } finally {
206 $progress->finish();
207 if ($force) {
208 update_option($preserveOptionKey, $originalPreserve);
209 }
210 }
211
212 \WP_CLI::log('Processed: ' . $processed);
213 \WP_CLI::log('Updated: ' . $updated . ($dryRun ? ' (dry-run)' : ''));
214 \WP_CLI::log('Skipped: ' . $skipped);
215 \WP_CLI::log('Failed: ' . $failed);
216
217 \WP_CLI::success('Done.');
218 }
219 }
220