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