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

Yoast / wordpress-seo / c6b3290269bc48302003905d2f25286ddbf4d026

02 Apr 2026 07:47AM UTC coverage: 49.911%. First build
c6b3290269bc48302003905d2f25286ddbf4d026

Pull #23062

github

web-flow
Merge 1057e658c into fef842521
Pull Request #23062: Register Yoast SEO abilities about analysis scores

41 of 206 new or added lines in 5 files covered. (19.9%)

19311 of 38691 relevant lines covered (49.91%)

4.03 hits per line

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

15.2
/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
         * The score retriever.
19
         *
20
         * @var Score_Retriever
21
         */
22
        private $score_retriever;
23

24
        /**
25
         * The capability helper.
26
         *
27
         * @var Capability_Helper
28
         */
29
        private $capability_helper;
30

31
        /**
32
         * The enabled analysis features checker.
33
         *
34
         * @var Enabled_Analysis_Features_Checker
35
         */
36
        private $enabled_analysis_features_checker;
37

38
        /**
39
         * Returns the conditionals based on which this loadable should be active.
40
         *
41
         * @return array<string> The conditionals.
42
         */
43
        public static function get_conditionals() {
2✔
44
                return [ Abilities_API_Conditional::class ];
2✔
45
        }
46

47
        /**
48
         * Constructor.
49
         *
50
         * @param Score_Retriever                   $score_retriever                   The score retriever.
51
         * @param Capability_Helper                 $capability_helper                 The capability helper.
52
         * @param Enabled_Analysis_Features_Checker $enabled_analysis_features_checker The enabled analysis features checker.
53
         */
NEW
54
        public function __construct(
×
55
                Score_Retriever $score_retriever,
56
                Capability_Helper $capability_helper,
57
                Enabled_Analysis_Features_Checker $enabled_analysis_features_checker
58
        ) {
NEW
59
                $this->score_retriever                   = $score_retriever;
×
NEW
60
                $this->capability_helper                 = $capability_helper;
×
NEW
61
                $this->enabled_analysis_features_checker = $enabled_analysis_features_checker;
×
62
        }
63

64
        /**
65
         * Registers hooks with WordPress.
66
         *
67
         * @return void
68
         */
69
        public function register_hooks() {
2✔
70
                \add_action( 'wp_abilities_api_categories_init', [ $this, 'register_categories' ] );
2✔
71
                \add_action( 'wp_abilities_api_init', [ $this, 'register_abilities' ] );
2✔
72
        }
73

74
        /**
75
         * Registers the Yoast SEO ability category.
76
         *
77
         * @return void
78
         */
79
        public function register_categories() {
2✔
80
                \wp_register_ability_category(
2✔
81
                        'yoast-seo',
2✔
82
                        [
2✔
83
                                'label'       => \__( 'Yoast SEO', 'wordpress-seo' ),
2✔
84
                                'description' => \__( 'SEO analysis capabilities provided by Yoast SEO.', 'wordpress-seo' ),
2✔
85
                        ],
2✔
86
                );
2✔
87
        }
88

89
        /**
90
         * Registers the Yoast SEO abilities.
91
         *
92
         * @return void
93
         */
94
        public function register_abilities() {
8✔
95
                $this->register_seo_scores_ability();
8✔
96
                $this->register_readability_scores_ability();
8✔
97
                $this->register_inclusive_language_scores_ability();
8✔
98
        }
99

100
        /**
101
         * Checks whether the current user can read scores.
102
         *
103
         * @return bool Whether the current user can read scores.
104
         */
105
        public function can_read_scores(): bool {
4✔
106
                return $this->capability_helper->current_user_can( 'wpseo_manage_options' );
4✔
107
        }
108

109
        /**
110
         * Registers the SEO scores ability if keyword analysis is enabled.
111
         *
112
         * @return void
113
         */
NEW
114
        private function register_seo_scores_ability(): void {
×
NEW
115
                if ( ! $this->enabled_analysis_features_checker->is_keyword_analysis_enabled() ) {
×
NEW
116
                        return;
×
117
                }
118

NEW
119
                $output_schema                                  = $this->get_score_output_schema();
×
NEW
120
                $output_schema['properties']['focus_keyphrase'] = [
×
NEW
121
                        'type'        => [ 'string', 'null' ],
×
NEW
122
                        'description' => \__( 'The focus keyphrase for the post, or null if not set.', 'wordpress-seo' ),
×
NEW
123
                ];
×
124

NEW
125
                \wp_register_ability(
×
NEW
126
                        'yoast-seo/get-seo-scores',
×
NEW
127
                        $this->get_shared_ability_args(
×
NEW
128
                                [
×
NEW
129
                                        'label'            => \__( 'Get SEO Scores', 'wordpress-seo' ),
×
NEW
130
                                        'description'      => \__( 'Get the SEO scores for the most recently modified posts.', 'wordpress-seo' ),
×
NEW
131
                                        'output_schema'    => $this->wrap_in_array_schema( $output_schema ),
×
NEW
132
                                        'execute_callback' => [ $this->score_retriever, 'get_seo_scores' ],
×
NEW
133
                                ],
×
NEW
134
                        ),
×
NEW
135
                );
×
136
        }
137

138
        /**
139
         * Registers the readability scores ability if content analysis is enabled.
140
         *
141
         * @return void
142
         */
NEW
143
        private function register_readability_scores_ability(): void {
×
NEW
144
                if ( ! $this->enabled_analysis_features_checker->is_content_analysis_enabled() ) {
×
NEW
145
                        return;
×
146
                }
147

NEW
148
                \wp_register_ability(
×
NEW
149
                        'yoast-seo/get-readability-scores',
×
NEW
150
                        $this->get_shared_ability_args(
×
NEW
151
                                [
×
NEW
152
                                        'label'            => \__( 'Get Readability Scores', 'wordpress-seo' ),
×
NEW
153
                                        'description'      => \__( 'Get the readability scores for the most recently modified posts.', 'wordpress-seo' ),
×
NEW
154
                                        'output_schema'    => $this->wrap_in_array_schema( $this->get_score_output_schema() ),
×
NEW
155
                                        'execute_callback' => [ $this->score_retriever, 'get_readability_scores' ],
×
NEW
156
                                ],
×
NEW
157
                        ),
×
NEW
158
                );
×
159
        }
160

161
        /**
162
         * Registers the inclusive language scores ability if inclusive language analysis is enabled.
163
         *
164
         * @return void
165
         */
NEW
166
        private function register_inclusive_language_scores_ability(): void {
×
NEW
167
                if ( ! $this->enabled_analysis_features_checker->is_inclusive_language_enabled() ) {
×
NEW
168
                        return;
×
169
                }
170

NEW
171
                \wp_register_ability(
×
NEW
172
                        'yoast-seo/get-inclusive-language-scores',
×
NEW
173
                        $this->get_shared_ability_args(
×
NEW
174
                                [
×
NEW
175
                                        'label'            => \__( 'Get Inclusive Language Scores', 'wordpress-seo' ),
×
NEW
176
                                        'description'      => \__( 'Get the inclusive language scores for the most recently modified posts.', 'wordpress-seo' ),
×
NEW
177
                                        'output_schema'    => $this->wrap_in_array_schema( $this->get_score_output_schema() ),
×
NEW
178
                                        'execute_callback' => [ $this->score_retriever, 'get_inclusive_language_scores' ],
×
NEW
179
                                ],
×
NEW
180
                        ),
×
NEW
181
                );
×
182
        }
183

184
        // phpcs:disable SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint -- Too complicated of a param declaration for this case.
185

186
        /**
187
         * Returns the shared ability arguments merged with ability-specific arguments.
188
         *
189
         * @param array<string, mixed> $ability_specific_args The ability-specific arguments.
190
         *
191
         * @return array<string, mixed> The merged ability arguments.
192
         */
NEW
193
        private function get_shared_ability_args( array $ability_specific_args ): array {
×
194
        // phpcs:enable SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint
NEW
195
                return \array_merge(
×
NEW
196
                        [
×
NEW
197
                                'category'            => 'yoast-seo',
×
NEW
198
                                'input_schema'        => [
×
NEW
199
                                        'type'       => 'object',
×
NEW
200
                                        'properties' => [
×
NEW
201
                                                'number_of_posts' => [
×
NEW
202
                                                        'type'        => 'integer',
×
NEW
203
                                                        'description' => \__( 'The number of recently modified posts to retrieve scores for. Defaults to 10.', 'wordpress-seo' ),
×
NEW
204
                                                        'minimum'     => 1,
×
NEW
205
                                                        'maximum'     => 100,
×
NEW
206
                                                        'default'     => 10,
×
NEW
207
                                                ],
×
NEW
208
                                        ],
×
NEW
209
                                ],
×
NEW
210
                                'permission_callback' => [ $this, 'can_read_scores' ],
×
NEW
211
                                'meta'                => [
×
NEW
212
                                        'show_in_rest' => true,
×
NEW
213
                                        'annotations'  => [
×
NEW
214
                                                'readonly'    => true,
×
NEW
215
                                                'destructive' => false,
×
NEW
216
                                                'idempotent'  => true,
×
NEW
217
                                        ],
×
NEW
218
                                        'mcp'          => [
×
NEW
219
                                                'public' => true,
×
NEW
220
                                        ],
×
NEW
221
                                ],
×
NEW
222
                        ],
×
NEW
223
                        $ability_specific_args,
×
NEW
224
                );
×
225
        }
226

227
        /**
228
         * Wraps an item schema in an array schema.
229
         *
230
         * @param array<string, array<string, string>> $item_schema The item schema.
231
         *
232
         * @return array<string, array<string, string>> The array schema.
233
         */
NEW
234
        private function wrap_in_array_schema( array $item_schema ): array {
×
NEW
235
                return [
×
NEW
236
                        'type'  => 'array',
×
NEW
237
                        'items' => $item_schema,
×
NEW
238
                ];
×
239
        }
240

241
        /**
242
         * Returns the score output schema, including the title property.
243
         *
244
         * @return array<string, array<string, string>> The score output schema.
245
         */
NEW
246
        private function get_score_output_schema(): array {
×
NEW
247
                return [
×
NEW
248
                        'type'       => 'object',
×
NEW
249
                        'properties' => [
×
NEW
250
                                'title' => [
×
NEW
251
                                        'type'        => 'string',
×
NEW
252
                                        'description' => \__( 'The post title.', 'wordpress-seo' ),
×
NEW
253
                                ],
×
NEW
254
                                'score' => [
×
NEW
255
                                        'type'        => 'string',
×
NEW
256
                                        'enum'        => [ 'na', 'bad', 'ok', 'good' ],
×
NEW
257
                                        'description' => \__( 'The score slug.', 'wordpress-seo' ),
×
NEW
258
                                ],
×
NEW
259
                                'label' => [
×
NEW
260
                                        'type'        => 'string',
×
NEW
261
                                        'description' => \__( 'A human-readable label for the score.', 'wordpress-seo' ),
×
NEW
262
                                ],
×
NEW
263
                        ],
×
NEW
264
                ];
×
265
        }
266
}
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