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

Yoast / wordpress-seo / a7886492b145fdf70261f7ca2cb0fbcb3562b15b

25 Nov 2024 01:47PM UTC coverage: 54.184% (-0.03%) from 54.215%
a7886492b145fdf70261f7ca2cb0fbcb3562b15b

Pull #21852

github

web-flow
Merge b930e736a into 16577a01e
Pull Request #21852: 339 dashboard use request to get the actual scores

7593 of 13670 branches covered (55.54%)

Branch coverage included in aggregate %.

0 of 77 new or added lines in 15 files covered. (0.0%)

989 existing lines in 3 files now uncovered.

29764 of 55275 relevant lines covered (53.85%)

41521.03 hits per line

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

0.0
/src/dashboard/user-interface/scores/abstract-scores-route.php
1
<?php
2
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
3
namespace Yoast\WP\SEO\Dashboard\User_Interface\Scores;
4

5
use Exception;
6
use WP_REST_Request;
7
use WP_REST_Response;
8
use WPSEO_Capability_Utils;
9
use Yoast\WP\SEO\Conditionals\No_Conditionals;
10
use Yoast\WP\SEO\Dashboard\Application\Scores\Scores_Repository_Interface;
11
use Yoast\WP\SEO\Dashboard\Application\Taxonomies\Taxonomies_Repository;
12
use Yoast\WP\SEO\Dashboard\Domain\Content_Types\Content_Type;
13
use Yoast\WP\SEO\Dashboard\Domain\Taxonomies\Taxonomy;
14
use Yoast\WP\SEO\Dashboard\Infrastructure\Content_Types\Content_Types_Collector;
15
use Yoast\WP\SEO\Main;
16
use Yoast\WP\SEO\Repositories\Indexable_Repository;
17
use Yoast\WP\SEO\Routes\Route_Interface;
18

19
/**
20
 * Abstract scores route.
21
 */
22
abstract class Abstract_Scores_Route implements Route_Interface {
23

24
        use No_Conditionals;
25

26
        /**
27
         * The namespace of the rout.
28
         *
29
         * @var string
30
         */
31
        public const ROUTE_NAMESPACE = Main::API_V1_NAMESPACE;
32

33
        /**
34
         * The prefix of the rout.
35
         *
36
         * @var string
37
         */
38
        public const ROUTE_PREFIX = null;
39

40
        /**
41
         * The content types collector.
42
         *
43
         * @var Content_Types_Collector
44
         */
45
        protected $content_types_collector;
46

47
        /**
48
         * The taxonomies repository.
49
         *
50
         * @var Taxonomies_Repository
51
         */
52
        protected $taxonomies_repository;
53

54
        /**
55
         * The indexable repository.
56
         *
57
         * @var Indexable_Repository
58
         */
59
        protected $indexable_repository;
60

61
        /**
62
         * The scores repository.
63
         *
64
         * @var Scores_Repository_Interface
65
         */
66
        protected $scores_repository;
67

68
        /**
69
         * Sets the collectors.
70
         *
71
         * @required
72
         *
73
         * @param Content_Types_Collector $content_types_collector The content type collector.
74
         *
75
         * @return void
76
         */
77
        public function set_collectors(
×
78
                Content_Types_Collector $content_types_collector
79
        ) {
80
                $this->content_types_collector = $content_types_collector;
×
81
        }
82

83
        /**
84
         * Sets the repositories.
85
         *
86
         * @required
87
         *
88
         * @param Taxonomies_Repository $taxonomies_repository The taxonomies repository.
89
         * @param Indexable_Repository  $indexable_repository  The indexable repository.
90
         *
91
         * @return void
92
         */
93
        public function set_repositories(
×
94
                Taxonomies_Repository $taxonomies_repository,
95
                Indexable_Repository $indexable_repository
96
        ) {
97
                $this->taxonomies_repository = $taxonomies_repository;
×
98
                $this->indexable_repository  = $indexable_repository;
×
99
        }
100

101
        /**
102
         * Returns the route prefix.
103
         *
104
         * @return string The route prefix.
105
         *
106
         * @throws Exception If the ROUTE_PREFIX constant is not set in the child class.
107
         */
NEW
108
        public static function get_route_prefix() {
×
109
                $class  = static::class;
×
110
                $prefix = $class::ROUTE_PREFIX;
×
111

112
                if ( $prefix === null ) {
×
113
                        throw new Exception( 'Score route without explicit prefix' );
×
114
                }
115

116
                return $prefix;
×
117
        }
118

119
        /**
120
         * Registers routes for scores.
121
         *
122
         * @return void
123
         */
124
        public function register_routes() {
×
125
                \register_rest_route(
×
NEW
126
                        self::ROUTE_NAMESPACE,
×
127
                        $this->get_route_prefix(),
×
128
                        [
129
                                [
130
                                        'methods'             => 'GET',
×
131
                                        'callback'            => [ $this, 'get_scores' ],
×
132
                                        'permission_callback' => [ $this, 'permission_manage_options' ],
×
133
                                        'args'                => [
134
                                                'contentType' => [
135
                                                        'required'          => true,
136
                                                        'type'              => 'string',
137
                                                        'sanitize_callback' => 'sanitize_text_field',
138
                                                ],
139
                                                'taxonomy' => [
140
                                                        'required'          => false,
141
                                                        'type'              => 'string',
142
                                                        'default'           => '',
143
                                                        'sanitize_callback' => 'sanitize_text_field',
144
                                                ],
145
                                                'term' => [
146
                                                        'required'          => false,
147
                                                        'type'              => 'integer',
×
148
                                                        'default'           => null,
149
                                                        'sanitize_callback' => static function ( $param ) {
150
                                                                return \intval( $param );
×
151
                                                        },
×
152
                                                ],
153
                                        ],
154
                                ],
155
                        ]
156
                );
157
        }
158

159
        /**
160
         * Gets the scores of a specific content type.
161
         *
162
         * @param WP_REST_Request $request The request object.
163
         *
164
         * @return WP_REST_Response The success or failure response.
165
         */
166
        public function get_scores( WP_REST_Request $request ) {
×
167
                try {
168
                        $content_type = $this->get_content_type( $request['contentType'] );
×
169
                        $taxonomy     = $this->get_taxonomy( $request['taxonomy'], $content_type );
×
170
                        $term_id      = $this->get_validated_term_id( $request['term'], $taxonomy );
×
171
                } catch ( Exception $exception ) {
×
172
                        return new WP_REST_Response(
×
173
                                [
174
                                        'error' => $exception->getMessage(),
×
175
                                ],
176
                                $exception->getCode()
×
177
                        );
178
                }
179

180
                return new WP_REST_Response(
×
181
                        $this->scores_repository->get_scores( $content_type, $taxonomy, $term_id ),
×
182
                        200
×
183
                );
184
        }
185

186
        /**
187
         * Gets the content type object.
188
         *
189
         * @param string $content_type The content type.
190
         *
191
         * @return Content_Type|null The content type object.
192
         *
193
         * @throws Exception When the content type is invalid.
194
         */
195
        protected function get_content_type( string $content_type ): ?Content_Type {
×
196
                $content_types = $this->content_types_collector->get_content_types()->get();
×
197

198
                if ( isset( $content_types[ $content_type ] ) && \is_a( $content_types[ $content_type ], Content_Type::class ) ) {
×
199
                        return $content_types[ $content_type ];
×
200
                }
201

202
                throw new Exception( 'Invalid content type.', 400 );
×
203
        }
204

205
        /**
206
         * Gets the taxonomy object.
207
         *
208
         * @param string       $taxonomy     The taxonomy.
209
         * @param Content_Type $content_type The content type that the taxonomy is filtering.
210
         *
211
         * @return Taxonomy|null The taxonomy object.
212
         *
213
         * @throws Exception When the taxonomy is invalid.
214
         */
215
        protected function get_taxonomy( string $taxonomy, Content_Type $content_type ): ?Taxonomy {
×
216
                if ( $taxonomy === '' ) {
×
217
                        return null;
×
218
                }
219

220
                $valid_taxonomy = $this->taxonomies_repository->get_content_type_taxonomy( $content_type->get_name() );
×
221

222
                if ( $valid_taxonomy && $valid_taxonomy->get_name() === $taxonomy ) {
×
223
                        return $valid_taxonomy;
×
224
                }
225

226
                throw new Exception( 'Invalid taxonomy.', 400 );
×
227
        }
228

229
        /**
230
         * Gets the term ID validated against the given taxonomy.
231
         *
232
         * @param int|null      $term_id  The term ID to be validated.
233
         * @param Taxonomy|null $taxonomy The taxonomy.
234
         *
235
         * @return bool The validated term ID.
236
         *
237
         * @throws Exception When the term id is invalidated.
238
         */
239
        protected function get_validated_term_id( ?int $term_id, ?Taxonomy $taxonomy ): ?int {
×
240
                if ( $term_id !== null && $taxonomy === null ) {
×
241
                        throw new Exception( 'Term needs a provided taxonomy.', 400 );
×
242
                }
243

244
                if ( $term_id === null && $taxonomy !== null ) {
×
245
                        throw new Exception( 'Taxonomy needs a provided term.', 400 );
×
246
                }
247

248
                if ( $term_id !== null ) {
×
249
                        $term = \get_term( $term_id );
×
250
                        if ( ! $term || \is_wp_error( $term ) ) {
×
251
                                throw new Exception( 'Invalid term.', 400 );
×
252
                        }
253

254
                        if ( $taxonomy !== null && $term->taxonomy !== $taxonomy->get_name() ) {
×
255
                                throw new Exception( 'Invalid term.', 400 );
×
256
                        }
257
                }
258

259
                return $term_id;
×
260
        }
261

262
        /**
263
         * Permission callback.
264
         *
265
         * @return bool True when user has the 'wpseo_manage_options' capability.
266
         */
267
        public function permission_manage_options() {
×
268
                return WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' );
×
269
        }
270
}
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

© 2025 Coveralls, Inc