• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / 046dda49737990aaf226c7a79a2a6ce1713916fe

30 Mar 2026 12:26PM UTC coverage: 49.882%. First build
046dda49737990aaf226c7a79a2a6ce1713916fe

Pull #23062

github

web-flow
Merge ce5f97aaa into 733ad6d2c
Pull Request #23062: Register Yoast SEO abilities about analysis scores

41 of 228 new or added lines in 5 files covered. (17.98%)

19311 of 38713 relevant lines covered (49.88%)

4.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

14.73
/src/abilities/user-interface/abilities-integration.php
1
<?php
2

3
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
4
namespace Yoast\WP\SEO\Abilities\User_Interface;
5

6
use Yoast\WP\SEO\Abilities\Application\Score_Retriever;
7
use Yoast\WP\SEO\Abilities\Infrastructure\Enabled_Analysis_Features_Checker;
8
use Yoast\WP\SEO\Conditionals\Abilities_API_Conditional;
9
use Yoast\WP\SEO\Helpers\Capability_Helper;
10
use Yoast\WP\SEO\Integrations\Integration_Interface;
11

12
/**
13
 * Integration that registers Yoast SEO abilities with the WordPress Abilities API.
14
 */
15
class Abilities_Integration implements Integration_Interface {
16

17
        /**
18
         * Valid ratings for SEO scores.
19
         *
20
         * @var array<string>
21
         */
22
        private const SEO_RATINGS = [ 'na', 'bad', 'ok', 'good', 'noindex' ];
23

24
        /**
25
         * Valid ratings for content analysis scores (readability and inclusive language).
26
         *
27
         * @var array<string>
28
         */
29
        private const CONTENT_ANALYSIS_RATINGS = [ 'na', 'bad', 'ok', 'good' ];
30

31
        /**
32
         * The score retriever.
33
         *
34
         * @var Score_Retriever
35
         */
36
        private $score_retriever;
37

38
        /**
39
         * The capability helper.
40
         *
41
         * @var Capability_Helper
42
         */
43
        private $capability_helper;
44

45
        /**
46
         * The enabled analysis features checker.
47
         *
48
         * @var Enabled_Analysis_Features_Checker
49
         */
50
        private $enabled_analysis_features_checker;
51

52
        /**
53
         * Returns the conditionals based on which this loadable should be active.
54
         *
55
         * @return array<string> The conditionals.
56
         */
57
        public static function get_conditionals() {
2✔
58
                return [ Abilities_API_Conditional::class ];
2✔
59
        }
60

61
        /**
62
         * Constructor.
63
         *
64
         * @param Score_Retriever                   $score_retriever                   The score retriever.
65
         * @param Capability_Helper                 $capability_helper                 The capability helper.
66
         * @param Enabled_Analysis_Features_Checker $enabled_analysis_features_checker The enabled analysis features checker.
67
         */
NEW
68
        public function __construct(
×
69
                Score_Retriever $score_retriever,
70
                Capability_Helper $capability_helper,
71
                Enabled_Analysis_Features_Checker $enabled_analysis_features_checker
72
        ) {
NEW
73
                $this->score_retriever                   = $score_retriever;
×
NEW
74
                $this->capability_helper                 = $capability_helper;
×
NEW
75
                $this->enabled_analysis_features_checker = $enabled_analysis_features_checker;
×
76
        }
77

78
        /**
79
         * Registers hooks with WordPress.
80
         *
81
         * @return void
82
         */
83
        public function register_hooks() {
2✔
84
                \add_action( 'wp_abilities_api_categories_init', [ $this, 'register_categories' ] );
2✔
85
                \add_action( 'wp_abilities_api_init', [ $this, 'register_abilities' ] );
2✔
86
        }
87

88
        /**
89
         * Registers the Yoast SEO ability category.
90
         *
91
         * @return void
92
         */
93
        public function register_categories() {
2✔
94
                \wp_register_ability_category(
2✔
95
                        'yoast-seo',
2✔
96
                        [
2✔
97
                                'label'       => \__( 'Yoast SEO', 'wordpress-seo' ),
2✔
98
                                'description' => \__( 'SEO analysis capabilities provided by Yoast SEO.', 'wordpress-seo' ),
2✔
99
                        ],
2✔
100
                );
2✔
101
        }
102

103
        /**
104
         * Registers the Yoast SEO abilities.
105
         *
106
         * @return void
107
         */
108
        public function register_abilities() {
8✔
109
                $this->register_seo_scores_ability();
8✔
110
                $this->register_readability_scores_ability();
8✔
111
                $this->register_inclusive_language_scores_ability();
8✔
112
        }
113

114
        /**
115
         * Checks whether the current user can read scores.
116
         *
117
         * @return bool Whether the current user can read scores.
118
         */
119
        public function can_read_scores(): bool {
4✔
120
                return $this->capability_helper->current_user_can( 'wpseo_manage_options' );
4✔
121
        }
122

123
        /**
124
         * Registers the SEO scores ability if keyword analysis is enabled.
125
         *
126
         * @return void
127
         */
NEW
128
        private function register_seo_scores_ability(): void {
×
NEW
129
                if ( ! $this->enabled_analysis_features_checker->is_keyword_analysis_enabled() ) {
×
NEW
130
                        return;
×
131
                }
132

NEW
133
                $output_schema                                  = $this->get_score_output_schema( self::SEO_RATINGS );
×
NEW
134
                $output_schema['properties']['focus_keyphrase'] = [
×
NEW
135
                        'type'        => [ 'string', 'null' ],
×
NEW
136
                        'description' => \__( 'The focus keyphrase for the post, or null if not set.', 'wordpress-seo' ),
×
NEW
137
                ];
×
138

NEW
139
                \wp_register_ability(
×
NEW
140
                        'yoast-seo/get-seo-scores',
×
NEW
141
                        $this->get_shared_ability_args(
×
NEW
142
                                [
×
NEW
143
                                        'label'            => \__( 'Get SEO Scores', 'wordpress-seo' ),
×
NEW
144
                                        'description'      => \__( 'Get the SEO scores for the most recently modified posts.', 'wordpress-seo' ),
×
NEW
145
                                        'output_schema'    => $this->wrap_in_array_schema( $output_schema ),
×
NEW
146
                                        'execute_callback' => [ $this->score_retriever, 'get_seo_scores' ],
×
NEW
147
                                ],
×
NEW
148
                        ),
×
NEW
149
                );
×
150
        }
151

152
        /**
153
         * Registers the readability scores ability if content analysis is enabled.
154
         *
155
         * @return void
156
         */
NEW
157
        private function register_readability_scores_ability(): void {
×
NEW
158
                if ( ! $this->enabled_analysis_features_checker->is_content_analysis_enabled() ) {
×
NEW
159
                        return;
×
160
                }
161

NEW
162
                \wp_register_ability(
×
NEW
163
                        'yoast-seo/get-readability-scores',
×
NEW
164
                        $this->get_shared_ability_args(
×
NEW
165
                                [
×
NEW
166
                                        'label'            => \__( 'Get Readability Scores', 'wordpress-seo' ),
×
NEW
167
                                        'description'      => \__( 'Get the readability scores for the most recently modified posts.', 'wordpress-seo' ),
×
NEW
168
                                        'output_schema'    => $this->wrap_in_array_schema( $this->get_score_output_schema( self::CONTENT_ANALYSIS_RATINGS ) ),
×
NEW
169
                                        'execute_callback' => [ $this->score_retriever, 'get_readability_scores' ],
×
NEW
170
                                ],
×
NEW
171
                        ),
×
NEW
172
                );
×
173
        }
174

175
        /**
176
         * Registers the inclusive language scores ability if inclusive language analysis is enabled.
177
         *
178
         * @return void
179
         */
NEW
180
        private function register_inclusive_language_scores_ability(): void {
×
NEW
181
                if ( ! $this->enabled_analysis_features_checker->is_inclusive_language_enabled() ) {
×
NEW
182
                        return;
×
183
                }
184

NEW
185
                \wp_register_ability(
×
NEW
186
                        'yoast-seo/get-inclusive-language-scores',
×
NEW
187
                        $this->get_shared_ability_args(
×
NEW
188
                                [
×
NEW
189
                                        'label'            => \__( 'Get Inclusive Language Scores', 'wordpress-seo' ),
×
NEW
190
                                        'description'      => \__( 'Get the inclusive language scores for the most recently modified posts.', 'wordpress-seo' ),
×
NEW
191
                                        'output_schema'    => $this->wrap_in_array_schema( $this->get_score_output_schema( self::CONTENT_ANALYSIS_RATINGS ) ),
×
NEW
192
                                        'execute_callback' => [ $this->score_retriever, 'get_inclusive_language_scores' ],
×
NEW
193
                                ],
×
NEW
194
                        ),
×
NEW
195
                );
×
196
        }
197

198
        /**
199
         * Returns the shared ability arguments merged with ability-specific arguments.
200
         *
201
         * @param array<string, array<string, string>> $ability_specific_args The ability-specific arguments.
202
         *
203
         * @return array<string, array<string, string>> The merged ability arguments.
204
         */
NEW
205
        private function get_shared_ability_args( array $ability_specific_args ): array {
×
NEW
206
                return \array_merge(
×
NEW
207
                        [
×
NEW
208
                                'category'            => 'yoast-seo',
×
NEW
209
                                'input_schema'        => [
×
NEW
210
                                        'type'       => 'object',
×
NEW
211
                                        'properties' => [
×
NEW
212
                                                'number_of_posts' => [
×
NEW
213
                                                        'type'        => 'integer',
×
NEW
214
                                                        'description' => \__( 'The number of recently modified posts to retrieve scores for. Defaults to 10.', 'wordpress-seo' ),
×
NEW
215
                                                        'minimum'     => 1,
×
NEW
216
                                                        'maximum'     => 100,
×
NEW
217
                                                        'default'     => 10,
×
NEW
218
                                                ],
×
NEW
219
                                        ],
×
NEW
220
                                ],
×
NEW
221
                                'permission_callback' => [ $this, 'can_read_scores' ],
×
NEW
222
                                'meta'                => [
×
NEW
223
                                        'show_in_rest' => true,
×
NEW
224
                                        'annotations'  => [
×
NEW
225
                                                'readonly'    => true,
×
NEW
226
                                                'destructive' => false,
×
NEW
227
                                                'idempotent'  => true,
×
NEW
228
                                        ],
×
NEW
229
                                        'mcp'          => [
×
NEW
230
                                                'public' => true,
×
NEW
231
                                        ],
×
NEW
232
                                ],
×
NEW
233
                        ],
×
NEW
234
                        $ability_specific_args,
×
NEW
235
                );
×
236
        }
237

238
        /**
239
         * Wraps an item schema in an array schema.
240
         *
241
         * @param array<string, array<string, string>> $item_schema The item schema.
242
         *
243
         * @return array<string, array<string, string>> The array schema.
244
         */
NEW
245
        private function wrap_in_array_schema( array $item_schema ): array {
×
NEW
246
                return [
×
NEW
247
                        'type'  => 'array',
×
NEW
248
                        'items' => $item_schema,
×
NEW
249
                ];
×
250
        }
251

252
        /**
253
         * Returns the score output schema for a specific set of valid ratings, including the title property.
254
         *
255
         * @param array<string> $ratings The valid rating slugs for this score type.
256
         *
257
         * @return array<string, array<string, string>> The score output schema.
258
         */
NEW
259
        private function get_score_output_schema( array $ratings ): array {
×
NEW
260
                return [
×
NEW
261
                        'type'       => 'object',
×
NEW
262
                        'properties' => [
×
NEW
263
                                'title'  => [
×
NEW
264
                                        'type'        => 'string',
×
NEW
265
                                        'description' => \__( 'The post title.', 'wordpress-seo' ),
×
NEW
266
                                ],
×
NEW
267
                                'score'  => [
×
NEW
268
                                        'type'        => 'integer',
×
NEW
269
                                        'description' => \__( 'The numeric score from 0 to 100.', 'wordpress-seo' ),
×
NEW
270
                                ],
×
NEW
271
                                'rating' => [
×
NEW
272
                                        'type'        => 'string',
×
NEW
273
                                        'enum'        => $ratings,
×
NEW
274
                                        'description' => \__( 'The rating slug.', 'wordpress-seo' ),
×
NEW
275
                                ],
×
NEW
276
                                'label'  => [
×
NEW
277
                                        'type'        => 'string',
×
NEW
278
                                        'description' => \__( 'A human-readable label for the rating.', 'wordpress-seo' ),
×
NEW
279
                                ],
×
NEW
280
                        ],
×
NEW
281
                ];
×
282
        }
283
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc