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

Yoast / wordpress-seo / cd1afbc6d734421dd13291c4f9dcfc39b2ad9ebc

02 Apr 2026 12:35PM UTC coverage: 49.925%. First build
cd1afbc6d734421dd13291c4f9dcfc39b2ad9ebc

Pull #23062

github

web-flow
Merge 032e191d6 into b6af95c07
Pull Request #23062: Register Yoast SEO abilities about analysis scores

40 of 194 new or added lines in 4 files covered. (20.62%)

19311 of 38680 relevant lines covered (49.93%)

4.03 hits per line

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

22.48
/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\Conditionals\Abilities_API_Conditional;
8
use Yoast\WP\SEO\Editors\Application\Analysis_Features\Enabled_Analysis_Features_Repository;
9
use Yoast\WP\SEO\Editors\Framework\Inclusive_Language_Analysis;
10
use Yoast\WP\SEO\Editors\Framework\Keyphrase_Analysis;
11
use Yoast\WP\SEO\Editors\Framework\Readability_Analysis;
12
use Yoast\WP\SEO\Helpers\Capability_Helper;
13
use Yoast\WP\SEO\Integrations\Integration_Interface;
14

15
/**
16
 * Integration that registers Yoast SEO abilities with the WordPress Abilities API.
17
 */
18
class Abilities_Integration implements Integration_Interface {
19

20
        /**
21
         * The score retriever.
22
         *
23
         * @var Score_Retriever
24
         */
25
        private $score_retriever;
26

27
        /**
28
         * The capability helper.
29
         *
30
         * @var Capability_Helper
31
         */
32
        private $capability_helper;
33

34
        /**
35
         * The enabled analysis features repository.
36
         *
37
         * @var Enabled_Analysis_Features_Repository
38
         */
39
        private $enabled_analysis_features_repository;
40

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

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

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

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

92
        /**
93
         * Registers the Yoast SEO abilities.
94
         *
95
         * @return void
96
         */
97
        public function register_abilities() {
8✔
98
                $enabled_features = $this->enabled_analysis_features_repository->get_features_by_keys(
8✔
99
                        [
8✔
100
                                Keyphrase_Analysis::NAME,
8✔
101
                                Readability_Analysis::NAME,
8✔
102
                                Inclusive_Language_Analysis::NAME,
8✔
103
                        ],
8✔
104
                )->to_array();
8✔
105

106
                if ( $enabled_features[ Keyphrase_Analysis::NAME ] === true ) {
8✔
107
                        $this->register_seo_scores_ability();
6✔
108
                }
109

110
                if ( $enabled_features[ Readability_Analysis::NAME ] === true ) {
8✔
111
                        $this->register_readability_scores_ability();
6✔
112
                }
113

114
                if ( $enabled_features[ Inclusive_Language_Analysis::NAME ] === true ) {
8✔
115
                        $this->register_inclusive_language_scores_ability();
2✔
116
                }
117
        }
118

119
        /**
120
         * Checks whether the current user can read scores.
121
         *
122
         * @return bool Whether the current user can read scores.
123
         */
124
        public function can_read_scores(): bool {
4✔
125
                return $this->capability_helper->current_user_can( 'wpseo_manage_options' );
4✔
126
        }
127

128
        /**
129
         * Registers the SEO scores ability.
130
         *
131
         * @return void
132
         */
NEW
133
        private function register_seo_scores_ability(): void {
×
NEW
134
                $output_schema                                  = $this->get_score_output_schema();
×
NEW
135
                $output_schema['properties']['focus_keyphrase'] = [
×
NEW
136
                        'type'        => [ 'string', 'null' ],
×
NEW
137
                        'description' => \__( 'The focus keyphrase for the post, or null if not set.', 'wordpress-seo' ),
×
NEW
138
                ];
×
139

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

153
        /**
154
         * Registers the readability scores ability.
155
         *
156
         * @return void
157
         */
NEW
158
        private function register_readability_scores_ability(): void {
×
NEW
159
                \wp_register_ability(
×
NEW
160
                        'yoast-seo/get-readability-scores',
×
NEW
161
                        $this->get_shared_ability_args(
×
NEW
162
                                [
×
NEW
163
                                        'label'            => \__( 'Get Readability Scores', 'wordpress-seo' ),
×
NEW
164
                                        'description'      => \__( 'Get the readability scores for the most recently modified posts.', 'wordpress-seo' ),
×
NEW
165
                                        'output_schema'    => $this->wrap_in_array_schema( $this->get_score_output_schema() ),
×
NEW
166
                                        'execute_callback' => [ $this->score_retriever, 'get_readability_scores' ],
×
NEW
167
                                ],
×
NEW
168
                        ),
×
NEW
169
                );
×
170
        }
171

172
        /**
173
         * Registers the inclusive language scores ability.
174
         *
175
         * @return void
176
         */
NEW
177
        private function register_inclusive_language_scores_ability(): void {
×
NEW
178
                \wp_register_ability(
×
NEW
179
                        'yoast-seo/get-inclusive-language-scores',
×
NEW
180
                        $this->get_shared_ability_args(
×
NEW
181
                                [
×
NEW
182
                                        'label'            => \__( 'Get Inclusive Language Scores', 'wordpress-seo' ),
×
NEW
183
                                        'description'      => \__( 'Get the inclusive language scores for the most recently modified posts.', 'wordpress-seo' ),
×
NEW
184
                                        'output_schema'    => $this->wrap_in_array_schema( $this->get_score_output_schema() ),
×
NEW
185
                                        'execute_callback' => [ $this->score_retriever, 'get_inclusive_language_scores' ],
×
NEW
186
                                ],
×
NEW
187
                        ),
×
NEW
188
                );
×
189
        }
190

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

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

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

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