PluginProbe ʕ •ᴥ•ʔ
WP Popular Posts / 6.1.0
WP Popular Posts v6.1.0
4.0.8 4.0.9 4.1.0 4.1.1 4.1.2 4.2.0 4.2.1 4.2.2 5.0.0 5.0.1 5.0.2 5.1.0 5.2.0 5.2.1 5.2.2 5.2.3 5.2.4 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.1.0 6.1.1 6.1.2 6.1.3 6.1.4 6.2.0 6.2.1 6.3.0 6.3.1 6.3.2 6.3.3 6.3.4 6.4.0 6.4.1 6.4.2 7.0.0 7.0.1 7.1.0 7.2.0 7.3.0 7.3.1 7.3.2 7.3.3 7.3.4 7.3.5 7.3.6 7.3.7 7.3.8 7.4.0 trunk 2.3.7 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 4.0.2 4.0.3 4.0.5 4.0.6
wordpress-popular-posts / src / Output.php
wordpress-popular-posts / src Last commit date
Activation 3 years ago Admin 3 years ago Block 3 years ago Container 3 years ago Front 3 years ago Rest 3 years ago Traits 3 years ago Widget 3 years ago Bootstrap.php 3 years ago Cache.php 3 years ago Helper.php 3 years ago I18N.php 3 years ago Image.php 3 years ago Output.php 3 years ago Query.php 3 years ago Settings.php 3 years ago Themer.php 3 years ago Translate.php 3 years ago WordPressPopularPosts.php 3 years ago deprecated.php 3 years ago template-tags.php 3 years ago
Output.php
1001 lines
1 <?php
2 /**
3 * This class formats the HTML output of every popular posts listing.
4 *
5 *
6 * @package WordPressPopularPosts
7 * @author Hector Cabrera <me@cabrerahector.com>
8 */
9
10 namespace WordPressPopularPosts;
11
12 class Output {
13
14 /**
15 * Popular posts data.
16 *
17 * @since 4.0.0
18 * @var string
19 */
20 private $data;
21
22 /**
23 * HTML output.
24 *
25 * @since 4.0.0
26 * @var string
27 */
28 private $output;
29
30 /**
31 * Widget / shortcode settings.
32 *
33 * @since 4.0.0
34 * @var array
35 */
36 private $public_options = [];
37
38 /**
39 * Administrative settings.
40 *
41 * @since 2.3.3
42 * @var array
43 */
44 private $admin_options = [];
45
46 /**
47 * Default excerpt 'more' string.
48 *
49 * @since 4.2.1
50 * @var string
51 */
52 private $more;
53
54 /**
55 * Image object
56 *
57 * @since 4.0.2
58 * @var WordPressPopularPosts\Image
59 */
60 private $thumbnail;
61
62 /**
63 * Translate object.
64 *
65 * @var \WordPressPopularPosts\Translate $translate
66 * @access private
67 */
68 private $translate;
69
70 /**
71 * Themer object.
72 *
73 * @var \WordPressPopularPosts\Themer $themer
74 * @access private
75 */
76 private $themer;
77
78 /**
79 * WordPress Date format.
80 *
81 * @var string
82 * @access private
83 */
84 private $wp_date_format;
85
86 /**
87 * Constructor.
88 *
89 * @since 4.0.0
90 * @param array $public_options
91 * @param array $admin_options
92 * @param WordPressPopularPosts\Image $thumbnail
93 * @param WordPressPopularPosts\Translate $translate
94 * @param WordPressPopularPosts\Themer $themer
95 */
96 public function __construct(array $public_options, array $admin_options, Image $thumbnail, Translate $translate, Themer $themer)
97 {
98 $this->public_options = $public_options;
99 $this->admin_options = $admin_options;
100 $this->thumbnail = $thumbnail;
101 $this->translate = $translate;
102 $this->themer = $themer;
103
104 $this->more = '...';
105
106 $this->wp_date_format = get_option('date_format');
107
108 if ( ! $this->wp_date_format )
109 $this->wp_date_format = 'F j, Y';
110 }
111
112 /**
113 * Sets data.
114 *
115 * @since 5.0.0
116 * @param array
117 */
118 public function set_data(array $data = [])
119 {
120 $this->data = $data;
121 }
122
123 /**
124 * Sets public options.
125 *
126 * @since 5.0.0
127 * @param array
128 */
129 public function set_public_options(array $public_options = [])
130 {
131 $this->public_options = Helper::merge_array_r(
132 Settings::get('widget_options'),
133 $public_options
134 );
135 }
136
137 /**
138 * Output the HTML.
139 *
140 * @since 4.0.0
141 */
142 public function output()
143 {
144 echo $this->get_output();
145 }
146
147 /**
148 * Return the HTML.
149 *
150 * @since 4.0.0
151 * @return string
152 */
153 public function get_output()
154 {
155 $this->output = "\n" . ( WP_DEBUG ? '<!-- WordPress Popular Posts v' . WPP_VERSION . ( $this->admin_options['tools']['cache']['active'] ? ' - cached' : '' ) . ' -->' : '' ) . "\n" . $this->output;
156 return $this->output;
157 }
158
159 /**
160 * Build the HTML output.
161 *
162 * @since 4.0.0
163 */
164 public function build_output()
165 {
166 // Got some posts, format 'em!
167 if ( ! empty($this->data) ) {
168
169 $this->output = '';
170
171 // Allow WP themers / coders access to raw data
172 // so they can build their own output
173 if ( has_filter('wpp_custom_html') ) {
174 $this->output .= apply_filters('wpp_custom_html', $this->data, $this->public_options);
175 return;
176 }
177
178 if (
179 isset($this->public_options['theme']['name'])
180 && $this->public_options['theme']['name']
181 ) {
182 $this->output .= '<div class="popular-posts-sr">';
183
184 if ( @file_exists(get_stylesheet_directory() . '/wordpress-popular-posts/themes/' . $this->public_options['theme']['name'] . '/style.css') ) {
185 $theme_stylesheet = get_stylesheet_directory() . '/wordpress-popular-posts/themes/' . $this->public_options['theme']['name'] . '/style.css';
186 } else {
187 $theme_stylesheet = $this->themer->get_theme($this->public_options['theme']['name'])['path'] . '/style.css';
188 }
189
190 $theme_css_rules = wp_strip_all_tags(file_get_contents($theme_stylesheet), true);
191 $additional_styles = '';
192
193 if ( has_filter('wpp_additional_theme_styles') ) {
194 $additional_styles = wp_strip_all_tags(apply_filters('wpp_additional_theme_styles', '', $this->public_options['theme']['name']), true);
195
196 if ( $additional_styles )
197 $additional_styles = ' /* additional rules */ ' . $additional_styles;
198 }
199
200 $this->output .= '<style>' . $theme_css_rules . $additional_styles . '</style>';
201 }
202
203 /* Open HTML wrapper */
204 // Output a custom wrapper
205 if (
206 isset($this->public_options['markup']['custom_html'])
207 && $this->public_options['markup']['custom_html']
208 && isset($this->public_options['markup']['wpp-start'])
209 && isset($this->public_options['markup']['wpp-end'])
210 ){
211 $this->output .= "\n" . htmlspecialchars_decode($this->public_options['markup']['wpp-start'], ENT_QUOTES) ."\n";
212 }
213 // Output the default wrapper
214 else {
215
216 $classes = "wpp-list";
217
218 if ( $this->public_options['thumbnail']['active'] )
219 $classes .= " wpp-list-with-thumbnails";
220
221 $this->output .= "\n" . "<ul class=\"{$classes}\">" . "\n";
222
223 }
224
225 $position = 0;
226
227 // Format each post
228 foreach( $this->data as $post_object ) {
229 $position++;
230 $this->output .= $this->render_post($post_object, $position);
231 }
232
233 /* Close HTML wrapper */
234 // Output a custom wrapper
235 if (
236 isset($this->public_options['markup']['custom_html'])
237 && $this->public_options['markup']['custom_html']
238 && isset($this->public_options['markup']['wpp-start'])
239 && isset($this->public_options['markup']['wpp-end'])
240 ){
241 $this->output .= "\n" . htmlspecialchars_decode($this->public_options['markup']['wpp-end'], ENT_QUOTES) ."\n";
242 }
243 // Output default wrapper
244 else {
245 $this->output .= "</ul>" . "\n";
246 }
247
248 if (
249 isset($this->public_options['theme']['name'])
250 && $this->public_options['theme']['name']
251 ) {
252 $this->output .= "</div>";
253 }
254
255 }
256 // Got nothing to show, give 'em the old "Sorry. No data so far." message!
257 else {
258 $this->output = apply_filters('wpp_no_data', "<p class=\"wpp-no-data\">" . __('Sorry. No data so far.', 'wordpress-popular-posts') . "</p>");
259 }
260 }
261
262 /**
263 * Build the HTML markup for a single post.
264 *
265 * @since 4.0.0
266 * @access private
267 * @param object $post_object
268 * @param integer $position
269 * @return string
270 */
271 private function render_post(\stdClass $post_object, int $position = 1)
272 {
273 $is_single = $this->is_single();
274 $post = '';
275 $post_id = $post_object->id;
276 $trid = $this->translate->get_object_id(
277 $post_object->id,
278 get_post_type($post_object->id)
279 );
280
281 if ( $post_id != $trid ) {
282 $post_id = $trid;
283 }
284
285 $is_current_post = ( $is_single && ($is_single == $post_id || $is_single == $post_object->id) ) ? true : false;
286
287 // Permalink
288 $permalink = esc_url($this->get_permalink($post_object, $post_id));
289
290 // Post title (and title attribute)
291 $post_title_attr = esc_attr(wp_strip_all_tags($this->get_title($post_object, $post_id)));
292 $post_title = $this->get_title($post_object, $post_id);
293
294 if ( $this->public_options['shorten_title']['active'] ) {
295 $length = ( filter_var($this->public_options['shorten_title']['length'], FILTER_VALIDATE_INT) && $this->public_options['shorten_title']['length'] > 0 )
296 ? $this->public_options['shorten_title']['length']
297 : 25;
298
299 $more = $this->public_options['shorten_title']['words'] ? ' ' . $this->more : $this->more;
300 $more = apply_filters('wpp_title_more', $more);
301 $post_title = Helper::truncate($post_title, $length, $this->public_options['shorten_title']['words'], $more);
302 }
303
304 // Thumbnail
305 $post_thumbnail = $this->get_thumbnail($post_id);
306
307 // Post excerpt
308 $post_excerpt = $this->get_excerpt($post_object, $post_id);
309
310 // Post rating
311 $post_rating = $this->get_rating($post_object);
312
313 /**
314 * Post meta
315 */
316
317 // Post date
318 $post_date = $this->get_date($post_object);
319
320 // Post taxonomies
321 $post_taxonomies = $this->get_taxonomies($post_id);
322
323 // Post author
324 $post_author = $this->get_author($post_object, $post_id);
325
326 // Post views count
327 $post_views = $this->get_pageviews($post_object);
328
329 // Post comments count
330 $post_comments = $this->get_comments($post_object);
331
332 // Post meta
333 $meta_arr = $this->get_metadata(
334 $post_object,
335 $post_id,
336 $post_date,
337 $post_taxonomies,
338 $post_author,
339 $post_views,
340 $post_comments
341 );
342
343 if (
344 is_array($meta_arr)
345 && ! empty($meta_arr)
346 && "views" == $this->public_options['order_by']
347 ) {
348 $keys = ['views', 'comments', 'author', 'date', 'taxonomy'];
349 $new_meta_arr = [];
350
351 foreach($keys as $key) {
352 if ( isset($meta_arr[$key]))
353 $new_meta_arr[$key] = $meta_arr[$key];
354 }
355
356 if ( ! empty($new_meta_arr) )
357 $meta_arr = $new_meta_arr;
358 }
359
360 $post_meta_separator = esc_html(apply_filters('wpp_post_meta_separator', ' | '));
361 $post_meta = join($post_meta_separator, $meta_arr);
362
363 $prettify_numbers = apply_filters('wpp_pretiffy_numbers', true);
364
365 // Build custom HTML output
366 if ( $this->public_options['markup']['custom_html'] ) {
367 $data = [
368 'id' => $post_id,
369 'is_current_post' => $is_current_post,
370 'title' => '<a href="' . $permalink . '" ' . ($post_title_attr !== $post_title ? 'title="' . $post_title_attr . '" ' : '' ) . 'class="wpp-post-title" target="' . esc_attr($this->admin_options['tools']['link']['target']) . '">' . $post_title . '</a>',
371 'title_attr' => $post_title_attr,
372 'summary' => $post_excerpt,
373 'stats' => $post_meta,
374 'img' => ( ! empty($post_thumbnail) ) ? '<a href="' . $permalink . '" ' . ($post_title_attr !== $post_title ? 'title="' . $post_title_attr . '" ' : '' ) . 'target="' . esc_attr($this->admin_options['tools']['link']['target']) . '">' . $post_thumbnail . '</a>' : '',
375 'img_no_link' => $post_thumbnail,
376 'url' => $permalink,
377 'text_title' => $post_title,
378 'taxonomy' => $post_taxonomies,
379 'taxonomy_copy' => isset($meta_arr['taxonomy']) ? $meta_arr['taxonomy'] : null,
380 'author' => ( ! empty($post_author) ) ? '<a href="' . esc_url(get_author_posts_url($post_object->uid != $post_id ? get_post_field('post_author', $post_id) : $post_object->uid )) . '">' . esc_html($post_author) . '</a>' : '',
381 'author_copy' => isset($meta_arr['author']) ? $meta_arr['author'] : null,
382 'author_name' => esc_html($post_author),
383 'author_url' => ( ! empty($post_author) ) ? esc_url(get_author_posts_url($post_object->uid != $post_id ? get_post_field('post_author', $post_id) : $post_object->uid)) : '',
384 'views' => ( $this->public_options['order_by'] == "views" || $this->public_options['order_by'] == "comments" ) ? ($prettify_numbers ? Helper::prettify_number($post_views) : number_format_i18n($post_views)) : ($prettify_numbers ? Helper::prettify_number($post_views, 2) : number_format_i18n($post_views, 2)),
385 'views_copy' => isset($meta_arr['views']) ? $meta_arr['views'] : null,
386 'comments' => $prettify_numbers ? Helper::prettify_number($post_comments) : number_format_i18n($post_comments),
387 'comments_copy' => isset($meta_arr['comments']) ? $meta_arr['comments'] : null,
388 'date' => $post_date,
389 'date_copy' => isset($meta_arr['date']) ? $meta_arr['date'] : null,
390 'total_items' => count($this->data),
391 'item_position' => $position
392 ];
393 $post = $this->format_content(htmlspecialchars_decode($this->public_options['markup']['post-html'], ENT_QUOTES), $data, $this->public_options['rating']). "\n";
394 } // Use the "stock" HTML output
395 else {
396 $wpp_post_class = [];
397
398 if ( $is_current_post ) {
399 $wpp_post_class[] = "current";
400 }
401
402 // Allow themers / plugin developer
403 // to add custom classes to each post
404 $wpp_post_class = apply_filters("wpp_post_class", $wpp_post_class, $post_id);
405
406 $post_thumbnail = ( ! empty($post_thumbnail) )
407 ? "<a href=\"{$permalink}\" " . ($post_title_attr !== $post_title ? "title=\"{$post_title_attr}\" " : "") . "target=\"" . esc_attr($this->admin_options['tools']['link']['target']) . "\">{$post_thumbnail}</a>\n"
408 : "";
409
410 $post_excerpt = ( ! empty($post_excerpt) )
411 ? " <span class=\"wpp-excerpt\">{$post_excerpt}</span>\n"
412 : "";
413
414 $post_meta = ( ! empty($post_meta) )
415 ? " <span class=\"wpp-meta post-stats\">{$post_meta}</span>\n"
416 : '';
417
418 $post_rating = ( ! empty($post_rating) )
419 ? " <span class=\"wpp-rating\">{$post_rating}</span>\n"
420 : "";
421
422 $post =
423 "<li" . ( ( is_array($wpp_post_class) && ! empty($wpp_post_class) ) ? ' class="' . esc_attr(implode(" ", $wpp_post_class)) . '"' : '') . ">\n"
424 . $post_thumbnail
425 . "<a href=\"{$permalink}\" " . ($post_title_attr !== $post_title ? "title=\"{$post_title_attr}\" " : "") . "class=\"wpp-post-title\" target=\"" . esc_attr($this->admin_options['tools']['link']['target']) . "\">{$post_title}</a>\n"
426 . $post_excerpt
427 . $post_meta
428 . $post_rating
429 . "</li>\n";
430 }
431
432 return apply_filters('wpp_post', $post, $post_object, $this->public_options);
433 }
434
435 /**
436 * Return the processed post/page title.
437 *
438 * @since 3.0.0
439 * @access private
440 * @param object $post_object
441 * @param integer $post_id
442 * @return string
443 */
444 private function get_title(\stdClass $post_object, int $post_id)
445 {
446 $title = '';
447
448 if ( $post_object->id != $post_id ) {
449 $title = get_the_title($post_id);
450 } else {
451 $title = $post_object->title;
452 }
453
454 // Run the_title filter so core/plugin title hooks can
455 // be applied to the post title
456 $title = apply_filters('the_title', $title, $post_object->id);
457
458 return apply_filters('wpp_the_title', $title, $post_object->id, $post_id);
459 }
460
461 /**
462 * Return the permalink.
463 *
464 * @since 4.0.12
465 * @access private
466 * @param object $post_object
467 * @param integer $post_id
468 * @return string
469 */
470 private function get_permalink(\stdClass $post_object, int $post_id) {
471 if ( $post_object->id != $post_id ) {
472 return get_permalink($post_id);
473 }
474
475 return get_permalink($post_object->id);
476 }
477
478 /**
479 * Return the processed thumbnail.
480 *
481 * @since 3.0.0
482 * @access private
483 * @param int $post_id
484 * @return string
485 */
486 private function get_thumbnail(int $post_id)
487 {
488 $thumbnail = '';
489
490 if ( $this->public_options['thumbnail']['active'] ) {
491 $thumbnail = $this->thumbnail->get(
492 $post_id,
493 [
494 $this->public_options['thumbnail']['width'],
495 $this->public_options['thumbnail']['height']
496 ],
497 $this->admin_options['tools']['thumbnail']['source'],
498 $this->public_options['thumbnail']['crop'],
499 $this->public_options['thumbnail']['build']
500 );
501 }
502
503 return $thumbnail;
504 }
505
506 /**
507 * Return post excerpt.
508 *
509 * @since 3.0.0
510 * @access private
511 * @param object $post_object
512 * @param integer $post_id
513 * @return string
514 */
515 private function get_excerpt(\stdClass $post_object, int $post_id)
516 {
517 $excerpt = '';
518
519 if ( $this->public_options['post-excerpt']['active'] ) {
520
521 if ( $post_object->id != $post_id ) {
522 $the_post = get_post($post_id);
523
524 $excerpt = ( empty($the_post->post_excerpt) )
525 ? $the_post->post_content
526 : $the_post->post_excerpt;
527 }
528 else {
529 $excerpt = ( empty($post_object->post_excerpt) )
530 ? $post_object->post_content
531 : $post_object->post_excerpt;
532 }
533
534 // remove caption tags
535 $excerpt = preg_replace("/\[caption.*\[\/caption\]/", "", $excerpt);
536
537 // remove Flash objects
538 $excerpt = preg_replace("/<object[0-9 a-z_?*=\":\-\/\.#\,\\n\\r\\t]+/smi", "", $excerpt);
539
540 // remove iframes
541 $excerpt = preg_replace("/<iframe.*?\/iframe>/i", "", $excerpt);
542
543 // remove WP shortcodes
544 $excerpt = strip_shortcodes($excerpt);
545
546 // remove style/script tags
547 $excerpt = preg_replace('@<(script|style)[^>]*?>.*?</\\1>@si', '', $excerpt);
548
549 // remove blocks that are not appropriate for the excerpt
550 $excerpt = excerpt_remove_blocks($excerpt);
551
552 // remove HTML tags if requested
553 if ( $this->public_options['post-excerpt']['keep_format'] ) {
554 $excerpt = wp_kses(
555 $excerpt,
556 [
557 'a' => [
558 'href' => [],
559 'title' => []
560 ],
561 'em' => [],
562 'strong' => []
563 ]
564 );
565 } else {
566 $excerpt = wp_kses($excerpt, []);
567
568 // remove URLs, too
569 $excerpt = preg_replace('_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS', '', $excerpt);
570 }
571
572 // remove HTML comments
573 $excerpt = preg_replace('/<!--.*?-->/ms', '', $excerpt);
574
575 // remove extra whitespaces
576 $excerpt = preg_replace('/\s\s+/', ' ', $excerpt);
577
578 $excerpt = trim($excerpt);
579
580 }
581
582 // Balance tags, if needed
583 if ( '' !== $excerpt ) {
584
585 $more = $this->public_options['post-excerpt']['words'] ? ' ' . $this->more : $this->more;
586 $more = apply_filters('wpp_excerpt_more', $more);
587 $excerpt = Helper::truncate($excerpt, $this->public_options['post-excerpt']['length'], $this->public_options['post-excerpt']['words'], $more);
588
589 if ( $this->public_options['post-excerpt']['keep_format'] )
590 $excerpt = force_balance_tags($excerpt);
591 }
592
593 return $excerpt;
594 }
595
596 /**
597 * Return post rating.
598 *
599 * @since 3.0.0
600 * @access private
601 * @param object $post_object
602 * @return string
603 */
604 private function get_rating(\stdClass $post_object)
605 {
606 $rating = '';
607
608 if ( function_exists('the_ratings_results') && $this->public_options['rating'] ) {
609 $rating = the_ratings_results($post_object->id);
610 }
611
612 return $rating;
613 }
614
615 /**
616 * Get post date.
617 *
618 * @since 3.0.0
619 * @access private
620 * @param object $post_object
621 * @return string
622 */
623 private function get_date(\stdClass $post_object)
624 {
625 $date = '';
626
627 if ( $this->public_options['stats_tag']['date']['active'] ) {
628 if ( 'relative' == $this->public_options['stats_tag']['date']['format'] ) {
629 $date = sprintf(
630 __('%s ago', 'wordpress-popular-posts'),
631 human_time_diff(
632 strtotime($post_object->date),
633 current_time('timestamp')
634 )
635 );
636 } else {
637 $date = date_i18n(
638 ( 'wp_date_format' == $this->public_options['stats_tag']['date']['format'] ? $this->wp_date_format : $this->public_options['stats_tag']['date']['format'] ),
639 strtotime($post_object->date)
640 );
641 }
642 }
643
644 return apply_filters('wpp_the_date', $date, $post_object->id);
645 }
646
647 /**
648 * Get post taxonomies.
649 *
650 * @since 3.0.0
651 * @access private
652 * @param integer $post_id
653 * @return string
654 */
655 private function get_taxonomies(int $post_id)
656 {
657 $post_tax = '';
658
659 if (
660 (isset($this->public_options['stats_tag']['category']) && $this->public_options['stats_tag']['category'])
661 || $this->public_options['stats_tag']['taxonomy']['active']
662 ) {
663
664 $taxonomy = 'category';
665
666 if (
667 $this->public_options['stats_tag']['taxonomy']['active']
668 && ! empty($this->public_options['stats_tag']['taxonomy']['name'])
669 ) {
670 $taxonomy = $this->public_options['stats_tag']['taxonomy']['name'];
671 }
672
673 $terms = wp_get_post_terms($post_id, $taxonomy);
674
675 if ( ! is_wp_error($terms) ) {
676 // Usage: https://wordpress.stackexchange.com/a/46824
677 if ( has_filter('wpp_post_exclude_terms') ) {
678 $args = apply_filters('wpp_post_exclude_terms', []);
679 $terms = wp_list_filter($terms, $args, 'NOT');
680 }
681
682 $terms = apply_filters('wpp_post_terms', $terms);
683
684 if (
685 is_array($terms)
686 && ! empty($terms)
687 ) {
688 $taxonomy_separator = esc_html(apply_filters('wpp_taxonomy_separator', ', '));
689
690 // We're going to use the taxonomy slug as a CSS class so let's escape it just in case
691 $taxonomy = esc_attr($taxonomy);
692
693 foreach ($terms as $term) {
694 $term_link = get_term_link($term);
695
696 if ( is_wp_error($term_link) )
697 continue;
698
699 $term_link = esc_url($this->translate->url($term_link, $this->translate->get_current_language()));
700 $post_tax .= "<a href=\"{$term_link}\" class=\"wpp-taxonomy {$taxonomy} {$taxonomy}-{$term->term_id}\">" . esc_html($term->name) . " </a>" . $taxonomy_separator;
701 }
702 }
703 }
704
705 if ( '' != $post_tax )
706 $post_tax = rtrim($post_tax, $taxonomy_separator);
707
708 }
709
710 return $post_tax;
711 }
712
713 /**
714 * Get post author.
715 *
716 * @since 3.0.0
717 * @access private
718 * @param object $post_object
719 * @param integer $post_id
720 * @return string
721 */
722 private function get_author(\stdClass $post_object, int $post_id)
723 {
724 $author = ( $this->public_options['stats_tag']['author'] )
725 ? get_the_author_meta('display_name', $post_object->uid != $post_id ? get_post_field('post_author', $post_id) : $post_object->uid)
726 : "";
727
728 return $author;
729 }
730
731 /**
732 * Return post views count.
733 *
734 * @since 3.0.0
735 * @access private
736 * @param object $post_object
737 * @return int|float
738 */
739 private function get_pageviews(\stdClass $post_object)
740 {
741 $pageviews = 0;
742
743 if (
744 (
745 $this->public_options['order_by'] == "views"
746 || $this->public_options['order_by'] == "avg"
747 || $this->public_options['stats_tag']['views']
748 )
749 && ( isset($post_object->pageviews) || isset($post_object->avg_views) )
750 ) {
751 $pageviews = ( $this->public_options['order_by'] == "views" || $this->public_options['order_by'] == "comments" )
752 ? $post_object->pageviews
753 : $post_object->avg_views;
754 }
755
756 return $pageviews;
757 }
758
759 /**
760 * Return post comment count.
761 *
762 * @since 3.0.0
763 * @access private
764 * @param object $post_object
765 * @return int
766 */
767 private function get_comments(\stdClass $post_object)
768 {
769 $comments = ( ( $this->public_options['order_by'] == "comments" || $this->public_options['stats_tag']['comment_count'] ) && isset($post_object->comment_count) )
770 ? $post_object->comment_count
771 : 0;
772
773 return $comments;
774 }
775
776 /**
777 * Return post metadata.
778 *
779 * @since 3.0.0
780 * @access private
781 * @param object $post_object
782 * @param integer $post_id
783 * @return array
784 */
785 //private function get_metadata(\stdClass $post_object, $post_id)
786 private function get_metadata(\stdClass $post_object, int $post_id, string $date, string $post_tax, string $author, $pageviews, int $comments) /** @TODO: starting PHP 8.0 $pageviews can be declared as mixed $pageviews */
787 {
788 $stats = [];
789
790 $prettify_numbers = apply_filters('wpp_pretiffy_numbers', true);
791
792 // comments
793 if ( $this->public_options['stats_tag']['comment_count'] ) {
794 $comments_text = sprintf(
795 _n('%s comment', '%s comments', $comments, 'wordpress-popular-posts'),
796 $prettify_numbers ? Helper::prettify_number($comments) : number_format_i18n($comments)
797 );
798
799 $stats['comments'] = '<span class="wpp-comments">' . $comments_text . '</span>';
800 }
801
802 // views
803 if ( $this->public_options['stats_tag']['views'] ) {
804 if ( $this->public_options['order_by'] == 'avg' ) {
805 $views_text = sprintf(
806 _n('%s view per day', '%s views per day', $pageviews, 'wordpress-popular-posts'),
807 $prettify_numbers ? Helper::prettify_number($pageviews, 2) : number_format_i18n($pageviews, (fmod($pageviews, 1) !== 0.0 ? 2 : 0))
808 );
809 }
810 else {
811 $views_text = sprintf(
812 _n('%s view', '%s views', $pageviews, 'wordpress-popular-posts'),
813 $prettify_numbers ? Helper::prettify_number($pageviews) : number_format_i18n($pageviews)
814 );
815 }
816
817 $stats['views'] = '<span class="wpp-views">' . $views_text . "</span>";
818 }
819
820 // author
821 if ( $this->public_options['stats_tag']['author'] ) {
822 $author_url = get_author_posts_url($post_object->uid != $post_id ? get_post_field('post_author', $post_id) : $post_object->uid);
823 $display_name = '<a href="' . esc_url($this->translate->url($author_url, $this->translate->get_current_language())) . '">' . esc_html($author) . '</a>';
824 $stats['author'] = '<span class="wpp-author">' . sprintf(__('by %s', 'wordpress-popular-posts'), $display_name) . '</span>';
825 }
826
827 // date
828 if ( $this->public_options['stats_tag']['date']['active'] ) {
829 $stats['date'] = '<span class="wpp-date">' . ( 'relative' == $this->public_options['stats_tag']['date']['format'] ? sprintf(__('posted %s', 'wordpress-popular-posts'), $date) : sprintf(__('posted on %s', 'wordpress-popular-posts'), $date) ) . '</span>';
830 }
831
832 // taxonomy
833 if ( ($this->public_options['stats_tag']['category'] || $this->public_options['stats_tag']['taxonomy']['active']) && $post_tax != '' ) {
834 $stats['taxonomy'] = '<span class="wpp-category">' . sprintf(__('under %s', 'wordpress-popular-posts'), $post_tax) . '</span>';
835 }
836
837 return $stats;
838 }
839
840 /**
841 * Parse content tags.
842 *
843 * @since 1.4.6
844 * @access private
845 * @param string HTML string with content tags
846 * @param array Post data
847 * @param bool Used to display post rating (if functionality is available)
848 * @return string
849 */
850 private function format_content(string $string, array $data, bool $rating) {
851
852 if ( empty($string) || ( empty($data) || ! is_array($data) ) )
853 return false;
854
855 $params = [];
856 $pattern = '/\{(pid|current_class|excerpt|summary|meta|stats|title|title_attr|image|thumb|thumb_img|thumb_url|rating|score|url|text_title|author|author_copy|author_name|author_url|taxonomy|taxonomy_copy|category|category_copy|views|views_copy|comments|comments_copy|date|date_copy|total_items|item_position)\}/i';
857 preg_match_all($pattern, $string, $matches);
858
859 array_map('strtolower', $matches[0]);
860
861 if ( in_array("{pid}", $matches[0]) ) {
862 $string = str_replace("{pid}", $data['id'], $string);
863 }
864
865 if ( in_array("{current_class}", $matches[0]) ) {
866 $string = str_replace("{current_class}", ( $data['is_current_post'] ? 'current' : '' ), $string);
867 }
868
869 if ( in_array("{title}", $matches[0]) ) {
870 $string = str_replace("{title}", $data['title'], $string);
871 }
872
873 if ( in_array("{title_attr}", $matches[0]) ) {
874 $string = str_replace("{title_attr}", $data['title_attr'], $string);
875 }
876
877 if ( in_array("{meta}", $matches[0]) || in_array("{stats}", $matches[0]) ) {
878 $string = str_replace(["{meta}", "{stats}"], $data['stats'], $string);
879 }
880
881 if ( in_array("{excerpt}", $matches[0]) || in_array("{summary}", $matches[0]) ) {
882 $string = str_replace(["{excerpt}", "{summary}"], $data['summary'], $string);
883 }
884
885 if ( in_array("{image}", $matches[0]) || in_array("{thumb}", $matches[0]) ) {
886 $string = str_replace(["{image}", "{thumb}"], $data['img'], $string);
887 }
888
889 if ( in_array("{thumb_img}", $matches[0]) ) {
890 $string = str_replace("{thumb_img}", $data['img_no_link'], $string);
891 }
892
893 if ( in_array("{thumb_url}", $matches[0]) && ! empty($data['img_no_link']) ) {
894 $dom = new \DOMDocument;
895
896 if ( $dom->loadHTML($data['img_no_link']) ) {
897 $img_tag = $dom->getElementsByTagName('img');
898
899 if ( $img_tag->length ) {
900 foreach( $img_tag as $node ) {
901 if ( $node->hasAttribute('src') ) {
902 $src = $node->getAttribute('src');
903 $string = str_replace("{thumb_url}", $src, $string);
904 }
905 }
906 }
907 }
908 }
909
910 // WP-PostRatings check
911 if ( $rating ) {
912 if ( function_exists('the_ratings_results') && in_array("{rating}", $matches[0]) ) {
913 $string = str_replace("{rating}", the_ratings_results($data['id']), $string);
914 }
915
916 if ( function_exists('expand_ratings_template') && in_array("{score}", $matches[0]) ) {
917 $string = str_replace("{score}", expand_ratings_template('%RATINGS_SCORE%', $data['id']), $string);
918 // removing the redundant plus sign
919 $string = str_replace('+', '', $string);
920 }
921 }
922
923 if ( in_array("{url}", $matches[0]) ) {
924 $string = str_replace("{url}", $data['url'], $string);
925 }
926
927 if ( in_array("{text_title}", $matches[0]) ) {
928 $string = str_replace("{text_title}", $data['text_title'], $string);
929 }
930
931 if ( in_array("{author}", $matches[0]) ) {
932 $string = str_replace("{author}", $data['author'], $string);
933 }
934
935 if ( in_array("{author_copy}", $matches[0]) ) {
936 $string = str_replace("{author_copy}", $data['author_copy'], $string);
937 }
938
939 if ( in_array("{author_name}", $matches[0]) ) {
940 $string = str_replace("{author_name}", $data['author_name'], $string);
941 }
942
943 if ( in_array("{author_url}", $matches[0]) ) {
944 $string = str_replace("{author_url}", $data['author_url'], $string);
945 }
946
947 if ( in_array("{taxonomy}", $matches[0]) || in_array("{category}", $matches[0]) ) {
948 $string = str_replace(["{taxonomy}", "{category}"], $data['taxonomy'], $string);
949 }
950
951 if ( in_array("{taxonomy_copy}", $matches[0]) || in_array("{category_copy}", $matches[0]) ) {
952 $string = str_replace(["{taxonomy_copy}", "{category_copy}"], $data['taxonomy_copy'], $string);
953 }
954
955 if ( in_array("{views}", $matches[0]) ) {
956 $string = str_replace("{views}", $data['views'], $string);
957 }
958
959 if ( in_array("{views_copy}", $matches[0]) ) {
960 $string = str_replace("{views_copy}", $data['views_copy'], $string);
961 }
962
963 if ( in_array("{comments}", $matches[0]) ) {
964 $string = str_replace("{comments}", $data['comments'], $string);
965 }
966
967 if ( in_array("{comments_copy}", $matches[0]) ) {
968 $string = str_replace("{comments_copy}", $data['comments_copy'], $string);
969 }
970
971 if ( in_array("{date}", $matches[0]) ) {
972 $string = str_replace("{date}", $data['date'], $string);
973 }
974
975 if ( in_array("{date_copy}", $matches[0]) ) {
976 $string = str_replace("{date_copy}", $data['date_copy'], $string);
977 }
978
979 if ( in_array("{total_items}", $matches[0]) ) {
980 $string = str_replace("{total_items}", $data['total_items'], $string);
981 }
982
983 if ( in_array("{item_position}", $matches[0]) ) {
984 $string = str_replace("{item_position}", $data['item_position'], $string);
985 }
986
987 return apply_filters("wpp_parse_custom_content_tags", $string, $data['id']);
988 }
989
990 /**
991 * Checks whether we're currently seeing a single post/page/CPT.
992 *
993 * @since 5.0.0
994 * @return int
995 */
996 public function is_single()
997 {
998 return apply_filters('wpp_is_single', Helper::is_single());
999 }
1000 }
1001