PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.5
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / src / abilities / application / score-retriever.php

score-retriever.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.5, at src/abilities/application/score-retriever.php

192 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
4 namespace Yoast\WP\SEO\Abilities\Application;
5
6 use WPSEO_Rank;
7 use Yoast\WP\SEO\Abilities\Domain\Score_Result;
8 use Yoast\WP\SEO\Repositories\Indexable_Repository;
9
10 /**
11 * Application service that retrieves SEO, readability, and inclusive language scores
12 * for the most recently modified posts.
13 */
14 class Score_Retriever {
15
16 /**
17 * The default number of posts to retrieve.
18 *
19 * @var int
20 */
21 private const DEFAULT_NUMBER_OF_POSTS = 10;
22
23 /**
24 * The maximum number of posts to retrieve.
25 *
26 * @var int
27 */
28 private const MAX_NUMBER_OF_POSTS = 100;
29
30 /**
31 * The indexable repository.
32 *
33 * @var Indexable_Repository
34 */
35 private $indexable_repository;
36
37 /**
38 * Constructor.
39 *
40 * @param Indexable_Repository $indexable_repository The indexable repository.
41 */
42 public function __construct(
43 Indexable_Repository $indexable_repository
44 ) {
45 $this->indexable_repository = $indexable_repository;
46 }
47
48 /**
49 * Retrieves the SEO scores for the most recently modified posts.
50 *
51 * @param array<string, int> $input The input containing optional 'number_of_posts'.
52 *
53 * @return array<int, array<string, string|null>> The SEO score data for each post.
54 */
55 public function get_seo_scores( array $input ): array {
56 $indexables = $this->get_recent_indexables( $this->get_number_of_posts( $input ) );
57
58 return \array_map( [ $this, 'build_seo_score_for_indexable' ], $indexables );
59 }
60
61 /**
62 * Retrieves the readability scores for the most recently modified posts.
63 *
64 * @param array<string, int> $input The input containing optional 'number_of_posts'.
65 *
66 * @return array<int, array<string, string>> The readability score data for each post.
67 */
68 public function get_readability_scores( array $input ): array {
69 $indexables = $this->get_recent_indexables( $this->get_number_of_posts( $input ) );
70
71 return \array_map( [ $this, 'build_readability_score_for_indexable' ], $indexables );
72 }
73
74 /**
75 * Retrieves the inclusive language scores for the most recently modified posts.
76 *
77 * @param array<string, int> $input The input containing optional 'number_of_posts'.
78 *
79 * @return array<int, array<string, string>> The inclusive language score data for each post.
80 */
81 public function get_inclusive_language_scores( array $input ): array {
82 $indexables = $this->get_recent_indexables( $this->get_number_of_posts( $input ) );
83
84 return \array_map( [ $this, 'build_inclusive_language_score_for_indexable' ], $indexables );
85 }
86
87 /**
88 * Builds the SEO score result for a single indexable.
89 *
90 * @param object $indexable The indexable object.
91 *
92 * @return array<string, string|null> The SEO score data.
93 */
94 private function build_seo_score_for_indexable( $indexable ): array {
95 $title = $this->get_indexable_title( $indexable );
96 $rank = WPSEO_Rank::from_numeric_score( (int) $indexable->primary_focus_keyword_score );
97 $result = ( new Score_Result(
98 $title,
99 $rank->get_rank(),
100 $rank->get_label(),
101 ) )->to_array();
102
103 $result['focus_keyphrase'] = $indexable->primary_focus_keyword;
104 return $result;
105 }
106
107 /**
108 * Builds the readability score result for a single indexable.
109 *
110 * @param object $indexable The indexable object.
111 *
112 * @return array<string, string> The readability score data.
113 */
114 private function build_readability_score_for_indexable( $indexable ): array {
115 $title = $this->get_indexable_title( $indexable );
116 $rank = WPSEO_Rank::from_numeric_score( (int) $indexable->readability_score );
117
118 return ( new Score_Result(
119 $title,
120 $rank->get_rank(),
121 $rank->get_label(),
122 ) )->to_array();
123 }
124
125 /**
126 * Builds the inclusive language score result for a single indexable.
127 *
128 * @param object $indexable The indexable object.
129 *
130 * @return array<string, string> The inclusive language score data.
131 */
132 private function build_inclusive_language_score_for_indexable( $indexable ): array {
133 $title = $this->get_indexable_title( $indexable );
134 $score = (int) $indexable->inclusive_language_score;
135
136 if ( $score === 0 ) {
137 return ( new Score_Result(
138 $title,
139 'na',
140 \__( 'Not available', 'wordpress-seo' ),
141 ) )->to_array();
142 }
143
144 $rank = WPSEO_Rank::from_numeric_score( $score );
145
146 return ( new Score_Result(
147 $title,
148 $rank->get_rank(),
149 $rank->get_inclusive_language_label(),
150 ) )->to_array();
151 }
152
153 /**
154 * Returns the title for an indexable, with a fallback.
155 *
156 * @param object $indexable The indexable object.
157 *
158 * @return string The post title.
159 */
160 private function get_indexable_title( $indexable ): string {
161 if ( ! empty( $indexable->breadcrumb_title ) ) {
162 return $indexable->breadcrumb_title;
163 }
164
165 return \__( '(no title)', 'wordpress-seo' );
166 }
167
168 /**
169 * Retrieves the most recently modified post indexables.
170 *
171 * @param int $number_of_posts The number of posts to retrieve.
172 *
173 * @return array<object> The indexable objects.
174 */
175 private function get_recent_indexables( int $number_of_posts ): array {
176 return $this->indexable_repository->get_recently_modified_posts( 'post', $number_of_posts, false );
177 }
178
179 /**
180 * Extracts and clamps the number of posts from the input.
181 *
182 * @param array<string, int> $input The input array.
183 *
184 * @return int The clamped number of posts.
185 */
186 private function get_number_of_posts( array $input ): int {
187 $number = ( $input['number_of_posts'] ?? self::DEFAULT_NUMBER_OF_POSTS );
188
189 return \min( self::MAX_NUMBER_OF_POSTS, \max( 1, (int) $number ) );
190 }
191 }
192