PluginProbe ʕ •ᴥ•ʔ
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 18.0
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v18.0
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 19.1 19.10 19.11 19.12 19.13 19.14 19.2 19.3 19.4 19.5 19.5.1 19.6 19.6.1 19.7 19.7.1 19.7.2 19.8 19.9 20.0 20.1 20.10 20.11 20.12 20.13 20.2 20.2.1 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.8.1 21.9 21.9.1 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.8.1 24.9 25.0 25.1 25.2 25.3 25.3.1 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.1.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.1.1 27.2 27.3 27.4
wordpress-seo / admin / statistics / class-statistics-service.php
wordpress-seo / admin / statistics Last commit date
class-statistics-integration.php 6 years ago class-statistics-service.php 5 years ago
class-statistics-service.php
259 lines
1 <?php
2 /**
3 * WPSEO plugin file.
4 *
5 * @package WPSEO\Admin\Statistics
6 */
7
8 /**
9 * Class WPSEO_Statistics_Service.
10 */
11 class WPSEO_Statistics_Service {
12
13 /**
14 * Cache transient id.
15 *
16 * @var string
17 */
18 const CACHE_TRANSIENT_KEY = 'wpseo-statistics-totals';
19
20 /**
21 * Class that generates interesting statistics about things.
22 *
23 * @var WPSEO_Statistics
24 */
25 protected $statistics;
26
27 /**
28 * Statistics labels.
29 *
30 * @var string[]
31 */
32 protected $labels;
33
34 /**
35 * WPSEO_Statistics_Service contructor.
36 *
37 * @param WPSEO_Statistics $statistics The statistics class to retrieve statistics from.
38 */
39 public function __construct( WPSEO_Statistics $statistics ) {
40 $this->statistics = $statistics;
41 }
42
43 /**
44 * Fetches statistics by REST request.
45 *
46 * @return WP_REST_Response The response object.
47 */
48 public function get_statistics() {
49 // Switch to the user locale with fallback to the site locale.
50 switch_to_locale( \get_user_locale() );
51
52 $this->labels = $this->labels();
53 $statistics = $this->statistic_items();
54
55 $data = [
56 'header' => $this->get_header_from_statistics( $statistics ),
57 'seo_scores' => $statistics['scores'],
58 ];
59
60 return new WP_REST_Response( $data );
61 }
62
63 /**
64 * Gets a header summarizing the given statistics results.
65 *
66 * @param array $statistics The statistics results.
67 *
68 * @return string The header summing up the statistics results.
69 */
70 private function get_header_from_statistics( array $statistics ) {
71 // Personal interpretation to allow release, should be looked at later.
72 if ( $statistics['division'] === false ) {
73 return __( 'You don\'t have any published posts, your SEO scores will appear here once you make your first post!', 'wordpress-seo' );
74 }
75
76 if ( $statistics['division']['good'] > 0.66 ) {
77 return __( 'Hey, your SEO is doing pretty well! Check out the stats:', 'wordpress-seo' );
78 }
79
80 return __( 'Below are your published posts\' SEO scores. Now is as good a time as any to start improving some of your posts!', 'wordpress-seo' );
81 }
82
83 /**
84 * An array representing items to be added to the At a Glance dashboard widget.
85 *
86 * @return array The statistics for the current user.
87 */
88 private function statistic_items() {
89 $transient = $this->get_transient();
90 $user_id = get_current_user_id();
91
92 if ( isset( $transient[ $user_id ] ) ) {
93 return $transient[ $user_id ];
94 }
95
96 return $this->set_statistic_items_for_user( $transient, $user_id );
97 }
98
99 /**
100 * Gets the statistics transient value. Returns array if transient wasn't set.
101 *
102 * @return array|mixed Returns the transient or an empty array if the transient doesn't exist.
103 */
104 private function get_transient() {
105 $transient = get_transient( self::CACHE_TRANSIENT_KEY );
106
107 if ( $transient === false ) {
108 return [];
109 }
110
111 return $transient;
112 }
113
114 /**
115 * Set the statistics transient cache for a specific user.
116 *
117 * @param array $transient The current stored transient with the cached data.
118 * @param int $user The user's ID to assign the retrieved values to.
119 *
120 * @return array The statistics transient for the user.
121 */
122 private function set_statistic_items_for_user( $transient, $user ) {
123 $scores = $this->get_seo_scores_with_post_count();
124 $division = $this->get_seo_score_division( $scores );
125
126 $transient[ $user ] = [
127 // Use array_values because array_filter may return non-zero indexed arrays.
128 'scores' => array_values( array_filter( $scores, [ $this, 'filter_items' ] ) ),
129 'division' => $division,
130 ];
131
132 set_transient( self::CACHE_TRANSIENT_KEY, $transient, DAY_IN_SECONDS );
133
134 return $transient[ $user ];
135 }
136
137 /**
138 * Gets the division of SEO scores.
139 *
140 * @param array $scores The SEO scores.
141 *
142 * @return array|bool The division of SEO scores, false if there are no posts.
143 */
144 private function get_seo_score_division( array $scores ) {
145 $total = 0;
146 $division = [];
147
148 foreach ( $scores as $score ) {
149 $total += $score['count'];
150 }
151
152 if ( $total === 0 ) {
153 return false;
154 }
155
156 foreach ( $scores as $score ) {
157 $division[ $score['seo_rank'] ] = ( $score['count'] / $total );
158 }
159
160 return $division;
161 }
162
163 /**
164 * Get all SEO ranks and data associated with them.
165 *
166 * @return array An array of SEO scores and associated data.
167 */
168 private function get_seo_scores_with_post_count() {
169 $ranks = WPSEO_Rank::get_all_ranks();
170
171 return array_map( [ $this, 'map_rank_to_widget' ], $ranks );
172 }
173
174 /**
175 * Converts a rank to data usable in the dashboard widget.
176 *
177 * @param WPSEO_Rank $rank The rank to map.
178 *
179 * @return array The mapped rank.
180 */
181 private function map_rank_to_widget( WPSEO_Rank $rank ) {
182 return [
183 'seo_rank' => $rank->get_rank(),
184 'label' => $this->get_label_for_rank( $rank ),
185 'count' => $this->statistics->get_post_count( $rank ),
186 'link' => $this->get_link_for_rank( $rank ),
187 ];
188 }
189
190 /**
191 * Returns a dashboard widget label to use for a certain rank.
192 *
193 * @param WPSEO_Rank $rank The rank to return a label for.
194 *
195 * @return string The label for the rank.
196 */
197 private function get_label_for_rank( WPSEO_Rank $rank ) {
198 return $this->labels[ $rank->get_rank() ];
199 }
200
201 /**
202 * Determines the labels for the various scoring ranks that are known within Yoast SEO.
203 *
204 * @return array Array containing the translatable labels.
205 */
206 private function labels() {
207 return [
208 WPSEO_Rank::NO_FOCUS => sprintf(
209 /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag */
210 __( 'Posts %1$swithout%2$s a focus keyphrase', 'wordpress-seo' ),
211 '<strong>',
212 '</strong>'
213 ),
214 WPSEO_Rank::BAD => sprintf(
215 /* translators: %s expands to the score */
216 __( 'Posts with the SEO score: %s', 'wordpress-seo' ),
217 '<strong>' . __( 'Needs improvement', 'wordpress-seo' ) . '</strong>'
218 ),
219 WPSEO_Rank::OK => sprintf(
220 /* translators: %s expands to the score */
221 __( 'Posts with the SEO score: %s', 'wordpress-seo' ),
222 '<strong>' . __( 'OK', 'wordpress-seo' ) . '</strong>'
223 ),
224 WPSEO_Rank::GOOD => sprintf(
225 /* translators: %s expands to the score */
226 __( 'Posts with the SEO score: %s', 'wordpress-seo' ),
227 '<strong>' . __( 'Good', 'wordpress-seo' ) . '</strong>'
228 ),
229 WPSEO_Rank::NO_INDEX => __( 'Posts that should not show up in search results', 'wordpress-seo' ),
230 ];
231 }
232
233 /**
234 * Filter items if they have a count of zero.
235 *
236 * @param array $item The item to potentially filter out.
237 *
238 * @return bool Whether or not the count is zero.
239 */
240 private function filter_items( $item ) {
241 return $item['count'] !== 0;
242 }
243
244 /**
245 * Returns a link for the overview of posts of a certain rank.
246 *
247 * @param WPSEO_Rank $rank The rank to return a link for.
248 *
249 * @return string The link that shows an overview of posts with that rank.
250 */
251 private function get_link_for_rank( WPSEO_Rank $rank ) {
252 if ( current_user_can( 'edit_others_posts' ) === false ) {
253 return esc_url( admin_url( 'edit.php?post_status=publish&post_type=post&seo_filter=' . $rank->get_rank() . '&author=' . get_current_user_id() ) );
254 }
255
256 return esc_url( admin_url( 'edit.php?post_status=publish&post_type=post&seo_filter=' . $rank->get_rank() ) );
257 }
258 }
259