PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.2-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.2-a.1
16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / _inc / lib / class-jetpack-top-posts-helper.php
jetpack / _inc / lib Last commit date
admin-pages 3 days ago core-api 3 days ago debugger 1 month ago markdown 8 months ago class-jetpack-ai-helper.php 3 days ago class-jetpack-ai-settings.php 3 days ago class-jetpack-application-password-extras.php 5 months ago class-jetpack-blog-stats-helper.php 8 months ago class-jetpack-currencies.php 2 years ago class-jetpack-instagram-gallery-helper.php 2 months ago class-jetpack-mapbox-helper.php 3 years ago class-jetpack-newsletter-category-helper.php 8 months ago class-jetpack-podcast-feed-locator.php 3 days ago class-jetpack-podcast-helper.php 3 days ago class-jetpack-recommendations.php 2 months ago class-jetpack-spinner.php 3 months ago class-jetpack-top-posts-helper.php 3 days ago class.color.php 2 years ago class.core-rest-api-endpoints.php 3 days ago class.jetpack-automatic-install-skin.php 2 years ago class.jetpack-iframe-embed.php 3 years ago class.jetpack-password-checker.php 8 months ago class.jetpack-search-performance-logger.php 4 years ago class.media-extractor.php 3 months ago class.media-summary.php 1 month ago class.media.php 8 months ago components.php 1 month ago debugger.php 2 months ago icalendar-reader.php 2 months ago markdown.php 8 months ago plans.php 4 years ago plugins.php 4 years ago tonesque.php 8 months ago widgets.php 4 months ago
class-jetpack-top-posts-helper.php
188 lines
1 <?php
2 /**
3 * Top Posts & Pages block helper.
4 *
5 * @package automattic/jetpack
6 */
7
8 use Automattic\Jetpack\Stats\WPCOM_Stats;
9
10 /**
11 * Class Jetpack_Top_Posts_Helper
12 */
13 class Jetpack_Top_Posts_Helper {
14 /**
15 * Returns user's top posts.
16 *
17 * @param int|string $period Period of days to draw stats from, or 'all-time'.
18 * @param int $items_count Optional. Number of items to display.
19 * @param string $types Optional. Content types to include.
20 * @return array
21 */
22 public static function get_top_posts( $period, $items_count = null, $types = null ) {
23 $all_time_days = floor( ( time() - strtotime( get_option( 'site_created_date' ) ) ) / ( 60 * 60 * 24 * 365 ) );
24
25 // While we only display ten posts, users can filter out content types.
26 // As such, we should obtain a few spare posts from the Stats endpoint.
27 $posts_to_obtain_count = 30;
28
29 // We should not override cache when displaying the block on the frontend.
30 // But we should allow instant preview of changes when editing the block.
31 $is_rendering_block = ! empty( $types );
32 $override_cache = ! $is_rendering_block;
33
34 $query_args = array(
35 'max' => $posts_to_obtain_count,
36 'summarize' => true,
37 'num' => $period !== 'all-time' ? $period : $all_time_days,
38 'period' => 'day',
39 );
40
41 // Atomic or self-hosted sites via WPCOM public v1.1 endpoint.
42 if ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) {
43 $data = ( new WPCOM_Stats() )->get_top_posts( $query_args, $override_cache );
44 } else {
45 // Directly access posts on WPCOM, as Simple sites run on the same environment.
46 require_lib( 'jetpack-stats' );
47 if ( class_exists( '\Jetpack\Stats\Top_Posts' ) ) {
48 // @phan-suppress-next-line PhanUndeclaredClassMethod
49 $data = ( new \Jetpack\Stats\Top_Posts() )->get_top_posts( get_current_blog_id(), $query_args );
50 } else {
51 $data = array( 'summary' => array( 'postviews' => array() ) );
52 }
53 }
54
55 if ( is_wp_error( $data ) ) {
56 $data = array( 'summary' => array( 'postviews' => array() ) );
57 }
58
59 $acceptable_types = $is_rendering_block ? explode( ',', $types ) : array();
60
61 // Remove posts that have subsequently been deleted. The endpoint can return more
62 // entries than the `max` we asked for, so stop there, then keep only further ones
63 // the block can render, so its type filter is never starved.
64 $published = array();
65 $renderable = 0;
66
67 foreach ( (array) ( $data['summary']['postviews'] ?? array() ) as $item ) {
68 $capped = $is_rendering_block && count( $published ) >= $posts_to_obtain_count;
69
70 if ( $capped && $renderable >= $items_count ) {
71 break;
72 }
73 if ( get_post_status( $item['id'] ) !== 'publish' ) {
74 continue;
75 }
76
77 $can_render = $is_rendering_block
78 && ! empty( $item['public'] )
79 && in_array( $item['type'] ?? '', $acceptable_types, true );
80
81 if ( $capped && ! $can_render ) {
82 continue;
83 }
84
85 $published[] = $item;
86
87 if ( $can_render ) {
88 ++$renderable;
89 }
90 }
91
92 $data['summary']['postviews'] = $published;
93 $posts_retrieved = count( $published );
94
95 // Fallback to random posts if user does not have enough top content.
96 if ( $posts_retrieved < $posts_to_obtain_count ) {
97 $args = array(
98 'numberposts' => $posts_to_obtain_count - $posts_retrieved,
99 'exclude' => array_column( $data['summary']['postviews'], 'id' ),
100 'orderby' => 'rand',
101 'post_status' => 'publish',
102 );
103
104 $random_posts = get_posts( $args );
105
106 foreach ( $random_posts as $post ) {
107 $random_posts_data = array(
108 'id' => $post->ID,
109 'href' => get_permalink( $post->ID ),
110 'date' => $post->post_date,
111 'title' => $post->post_title,
112 'type' => 'post',
113 'public' => true,
114 );
115
116 $data['summary']['postviews'][] = $random_posts_data;
117 }
118
119 $data['summary']['postviews'] = array_slice( $data['summary']['postviews'], 0, 10 );
120 }
121
122 $top_posts = array();
123
124 foreach ( $data['summary']['postviews'] as $post ) {
125 // Non-public entries are discarded, so skip their thumbnail lookups entirely.
126 if ( empty( $post['public'] ) ) {
127 continue;
128 }
129
130 $post_id = $post['id'];
131 $thumbnail = get_the_post_thumbnail_url( $post_id );
132
133 if ( ! $thumbnail ) {
134 $post_images = get_attached_media( 'image', $post_id );
135 $post_image = reset( $post_images );
136 if ( $post_image ) {
137 $thumbnail = wp_get_attachment_url( $post_image->ID );
138 }
139 }
140
141 $top_post = array(
142 'id' => $post_id,
143 'author' => get_the_author_meta( 'display_name', get_post_field( 'post_author', $post_id ) ),
144 'context' => get_the_category( $post_id ) ? get_the_category( $post_id ) : get_the_tags( $post_id ),
145 // Use the local permalink to avoid stale values from the Stats API.
146 'href' => get_permalink( $post_id ),
147 'date' => get_the_date( '', $post_id ),
148 'title' => $post['title'],
149 'type' => $post['type'] ?? '',
150 'public' => $post['public'],
151 'views' => $post['views'] ?? 0,
152 'thumbnail' => $thumbnail,
153 );
154
155 /**
156 * Allows modifying the title of each individual post returned by the Top Posts helper.
157 *
158 * Applies to both the Top Posts block's front-end output and the REST
159 * response used by the block editor preview.
160 *
161 * @module stats
162 *
163 * @since 15.8
164 *
165 * @param string $post_title Post title.
166 * @param array $top_post Information about the post.
167 */
168 $top_post['title'] = apply_filters( 'jetpack_top_posts_item_title', $top_post['title'], $top_post );
169
170 $top_posts[] = $top_post;
171 }
172
173 // This applies for rendering the block front-end, but not for editing it.
174 if ( $is_rendering_block ) {
175 $top_posts = array_filter(
176 $top_posts,
177 function ( $item ) use ( $acceptable_types ) {
178 return in_array( $item['type'], $acceptable_types, true );
179 }
180 );
181
182 $top_posts = array_slice( $top_posts, 0, $items_count );
183 }
184
185 return $top_posts;
186 }
187 }
188