PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.7.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.7.0
2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.10.0 All 48 releases
thinkrank / includes / abilities / media / class-fill-missing-alt-text.php

class-fill-missing-alt-text.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 2.7.0, at includes/abilities/media/class-fill-missing-alt-text.php

133 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Bulk fill missing alt text ability.
4 *
5 * @package ThinkRank\Abilities\Media
6 */
7
8 declare(strict_types=1);
9
10 namespace ThinkRank\Abilities\Media;
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit; // Exit if accessed directly.
14 }
15
16 /**
17 * Runs the Media Library bulk alt-text fill.
18 *
19 * The same routine the "Fill missing alt text" button in Image SEO calls, which
20 * until now existed only as a wp-admin button — so an agent could see the
21 * coverage gap and had no way to close it (#676).
22 *
23 * Batched rather than one-shot, because the AI alt source is a paid provider
24 * call per image: the manager clamps the batch itself and returns `remaining`
25 * and `next_offset`, so a caller loops until `done`.
26 */
27 class Fill_Missing_Alt_Text extends Image_Alt_Ability_Base {
28
29 /**
30 * Constructor.
31 */
32 public function __construct() {
33 $this->id = 'thinkrank/fill-missing-alt-text';
34 $this->label = __( 'Fill Missing ThinkRank Image Alt Text', 'thinkrank' );
35 $this->description = __( 'Fill in missing alt text across the Media Library using the site\'s alt text template, in batches. Returns how many images were updated plus remaining and next_offset; call again with that offset until done is true. Images that already have alt text are skipped unless overwrite is true. Call list-images with alt_status \'missing\' first to see how many need filling, and update-image-alt-text when you want to write one image yourself.', 'thinkrank' );
36 }
37
38 /**
39 * {@inheritDoc}
40 *
41 * @return array<string, bool|float|string>
42 */
43 public function get_annotations() {
44 return [
45 'readonly' => false,
46 // Writes alt text where there was none; the default leaves existing
47 // values alone, so nothing an author wrote is lost. `overwrite`
48 // changes that, which is why it defaults off and is described.
49 'destructive' => false,
50 // Re-running with the same offset is safe: an image filled by the
51 // previous run is skipped by the next one.
52 'idempotent' => true,
53 'priority' => 0.7,
54 'openWorldHint' => false,
55 ];
56 }
57
58 /**
59 * {@inheritDoc}
60 *
61 * @return array<string, mixed>
62 */
63 public function get_input_schema() {
64 return [
65 'type' => 'object',
66 'additionalProperties' => false,
67 'properties' => [
68 'offset' => [
69 'type' => 'integer',
70 'description' => __( 'Where to start. Pass the previous call\'s next_offset. Default 0.', 'thinkrank' ),
71 ],
72 'limit' => [
73 'type' => 'integer',
74 'description' => __( 'Batch size, 1-200. Clamped lower when the alt source is AI, because each image is a provider call. Default 50.', 'thinkrank' ),
75 ],
76 'overwrite' => [
77 'type' => 'boolean',
78 'description' => __( 'Replace alt text images already have. Default false.', 'thinkrank' ),
79 ],
80 ],
81 ];
82 }
83
84 /**
85 * {@inheritDoc}
86 *
87 * @return array<string, mixed>
88 */
89 public function get_output_schema() {
90 return [
91 'type' => 'object',
92 'properties' => [
93 'total' => [ 'type' => 'integer' ],
94 'processed' => [ 'type' => 'integer' ],
95 'updated' => [
96 'type' => 'integer',
97 'description' => __( 'Images whose alt text was written by this batch.', 'thinkrank' ),
98 ],
99 'skipped' => [ 'type' => 'integer' ],
100 'offset' => [ 'type' => 'integer' ],
101 'next_offset' => [ 'type' => 'integer' ],
102 'remaining' => [ 'type' => 'integer' ],
103 'done' => [
104 'type' => 'boolean',
105 'description' => __( 'True when the whole library has been walked. Call again with next_offset while this is false.', 'thinkrank' ),
106 ],
107 ],
108 ];
109 }
110
111 /**
112 * Execute ability.
113 *
114 * @param array<string, mixed> $input Ability input payload.
115 * @return array<string, mixed>
116 */
117 public function execute( $input ) {
118 $input = (array) $input;
119
120 $args = [];
121 foreach ( [ 'offset', 'limit' ] as $key ) {
122 if ( array_key_exists( $key, $input ) ) {
123 $args[ $key ] = (int) $input[ $key ];
124 }
125 }
126 if ( array_key_exists( 'overwrite', $input ) ) {
127 $args['overwrite'] = (bool) $input['overwrite'];
128 }
129
130 return $this->manager()->bulk_fill_missing_alt( $args );
131 }
132 }
133