PluginProbe ʕ •ᴥ•ʔ
WP Popular Posts / 6.0.1
WP Popular Posts v6.0.1
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
990 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 if ( $post_object->id != $post_id ) {
447 $title = get_the_title($post_id);
448 } else {
449 $title = $post_object->title;
450 }
451
452 // Run the_title filter so core/plugin title hooks can
453 // be applied to the post title
454 $title = apply_filters('the_title', $title, $post_object->id);
455
456 return apply_filters('wpp_the_title', $title, $post_object->id, $post_id);
457 }
458
459 /**
460 * Return the permalink.
461 *
462 * @since 4.0.12
463 * @access private
464 * @param object $post_object
465 * @param integer $post_id
466 * @return string
467 */
468 private function get_permalink(\stdClass $post_object, int $post_id) {
469 if ( $post_object->id != $post_id ) {
470 return get_permalink($post_id);
471 }
472
473 return get_permalink($post_object->id);
474 }
475
476 /**
477 * Return the processed thumbnail.
478 *
479 * @since 3.0.0
480 * @access private
481 * @param int $post_id
482 * @return string
483 */
484 private function get_thumbnail(int $post_id)
485 {
486 $thumbnail = '';
487
488 if ( $this->public_options['thumbnail']['active'] ) {
489 $thumbnail = $this->thumbnail->get(
490 $post_id,
491 [
492 $this->public_options['thumbnail']['width'],
493 $this->public_options['thumbnail']['height']
494 ],
495 $this->admin_options['tools']['thumbnail']['source'],
496 $this->public_options['thumbnail']['crop'],
497 $this->public_options['thumbnail']['build']
498 );
499 }
500
501 return $thumbnail;
502 }
503
504 /**
505 * Return post excerpt.
506 *
507 * @since 3.0.0
508 * @access private
509 * @param object $post_object
510 * @param integer $post_id
511 * @return string
512 */
513 private function get_excerpt(\stdClass $post_object, int $post_id)
514 {
515 $excerpt = '';
516
517 if ( $this->public_options['post-excerpt']['active'] ) {
518
519 if ( $post_object->id != $post_id ) {
520 $the_post = get_post($post_id);
521
522 $excerpt = ( empty($the_post->post_excerpt) )
523 ? $the_post->post_content
524 : $the_post->post_excerpt;
525 }
526 else {
527 $excerpt = ( empty($post_object->post_excerpt) )
528 ? $post_object->post_content
529 : $post_object->post_excerpt;
530 }
531
532 // remove caption tags
533 $excerpt = preg_replace("/\[caption.*\[\/caption\]/", "", $excerpt);
534
535 // remove Flash objects
536 $excerpt = preg_replace("/<object[0-9 a-z_?*=\":\-\/\.#\,\\n\\r\\t]+/smi", "", $excerpt);
537
538 // remove iframes
539 $excerpt = preg_replace("/<iframe.*?\/iframe>/i", "", $excerpt);
540
541 // remove WP shortcodes
542 $excerpt = strip_shortcodes($excerpt);
543
544 // remove style/script tags
545 $excerpt = preg_replace('@<(script|style)[^>]*?>.*?</\\1>@si', '', $excerpt);
546
547 // remove HTML tags if requested
548 if ( $this->public_options['post-excerpt']['keep_format'] ) {
549 $excerpt = wp_kses(
550 $excerpt,
551 [
552 'a' => [
553 'href' => [],
554 'title' => []
555 ],
556 'em' => [],
557 'strong' => []
558 ]
559 );
560 } else {
561 $excerpt = wp_kses($excerpt, []);
562
563 // remove URLs, too
564 $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);
565 }
566
567 $excerpt = trim($excerpt);
568
569 }
570
571 // Balance tags, if needed
572 if ( '' !== $excerpt ) {
573
574 $more = $this->public_options['post-excerpt']['words'] ? ' ' . $this->more : $this->more;
575 $more = apply_filters('wpp_excerpt_more', $more);
576 $excerpt = Helper::truncate($excerpt, $this->public_options['post-excerpt']['length'], $this->public_options['post-excerpt']['words'], $more);
577
578 if ( $this->public_options['post-excerpt']['keep_format'] )
579 $excerpt = force_balance_tags($excerpt);
580 }
581
582 return $excerpt;
583 }
584
585 /**
586 * Return post rating.
587 *
588 * @since 3.0.0
589 * @access private
590 * @param object $post_object
591 * @return string
592 */
593 private function get_rating(\stdClass $post_object)
594 {
595 $rating = '';
596
597 if ( function_exists('the_ratings_results') && $this->public_options['rating'] ) {
598 $rating = the_ratings_results($post_object->id);
599 }
600
601 return $rating;
602 }
603
604 /**
605 * Get post date.
606 *
607 * @since 3.0.0
608 * @access private
609 * @param object $post_object
610 * @return string
611 */
612 private function get_date(\stdClass $post_object)
613 {
614 $date = '';
615
616 if ( $this->public_options['stats_tag']['date']['active'] ) {
617 if ( 'relative' == $this->public_options['stats_tag']['date']['format'] ) {
618 $date = sprintf(
619 __('%s ago', 'wordpress-popular-posts'),
620 human_time_diff(
621 strtotime($post_object->date),
622 current_time('timestamp')
623 )
624 );
625 } else {
626 $date = date_i18n(
627 ( 'wp_date_format' == $this->public_options['stats_tag']['date']['format'] ? $this->wp_date_format : $this->public_options['stats_tag']['date']['format'] ),
628 strtotime($post_object->date)
629 );
630 }
631 }
632
633 return $date;
634 }
635
636 /**
637 * Get post taxonomies.
638 *
639 * @since 3.0.0
640 * @access private
641 * @param integer $post_id
642 * @return string
643 */
644 private function get_taxonomies(int $post_id)
645 {
646 $post_tax = '';
647
648 if (
649 (isset($this->public_options['stats_tag']['category']) && $this->public_options['stats_tag']['category'])
650 || $this->public_options['stats_tag']['taxonomy']['active']
651 ) {
652
653 $taxonomy = 'category';
654
655 if (
656 $this->public_options['stats_tag']['taxonomy']['active']
657 && ! empty($this->public_options['stats_tag']['taxonomy']['name'])
658 ) {
659 $taxonomy = $this->public_options['stats_tag']['taxonomy']['name'];
660 }
661
662 $terms = wp_get_post_terms($post_id, $taxonomy);
663
664 if ( ! is_wp_error($terms) ) {
665 // Usage: https://wordpress.stackexchange.com/a/46824
666 if ( has_filter('wpp_post_exclude_terms') ) {
667 $args = apply_filters('wpp_post_exclude_terms', []);
668 $terms = wp_list_filter($terms, $args, 'NOT');
669 }
670
671 $terms = apply_filters('wpp_post_terms', $terms);
672
673 if (
674 is_array($terms)
675 && ! empty($terms)
676 ) {
677 $taxonomy_separator = esc_html(apply_filters('wpp_taxonomy_separator', ', '));
678
679 // We're going to use the taxonomy slug as a CSS class so let's escape it just in case
680 $taxonomy = esc_attr($taxonomy);
681
682 foreach ($terms as $term) {
683 $term_link = get_term_link($term);
684
685 if ( is_wp_error($term_link) )
686 continue;
687
688 $term_link = esc_url($this->translate->url($term_link, $this->translate->get_current_language()));
689 $post_tax .= "<a href=\"{$term_link}\" class=\"wpp-taxonomy {$taxonomy} {$taxonomy}-{$term->term_id}\">" . esc_html($term->name) . " </a>" . $taxonomy_separator;
690 }
691 }
692 }
693
694 if ( '' != $post_tax )
695 $post_tax = rtrim($post_tax, $taxonomy_separator);
696
697 }
698
699 return $post_tax;
700 }
701
702 /**
703 * Get post author.
704 *
705 * @since 3.0.0
706 * @access private
707 * @param object $post_object
708 * @param integer $post_id
709 * @return string
710 */
711 private function get_author(\stdClass $post_object, int $post_id)
712 {
713 $author = ( $this->public_options['stats_tag']['author'] )
714 ? get_the_author_meta('display_name', $post_object->uid != $post_id ? get_post_field('post_author', $post_id) : $post_object->uid)
715 : "";
716
717 return $author;
718 }
719
720 /**
721 * Return post views count.
722 *
723 * @since 3.0.0
724 * @access private
725 * @param object $post_object
726 * @return int|float
727 */
728 private function get_pageviews(\stdClass $post_object)
729 {
730 $pageviews = 0;
731
732 if (
733 (
734 $this->public_options['order_by'] == "views"
735 || $this->public_options['order_by'] == "avg"
736 || $this->public_options['stats_tag']['views']
737 )
738 && ( isset($post_object->pageviews) || isset($post_object->avg_views) )
739 ) {
740 $pageviews = ( $this->public_options['order_by'] == "views" || $this->public_options['order_by'] == "comments" )
741 ? $post_object->pageviews
742 : $post_object->avg_views;
743 }
744
745 return $pageviews;
746 }
747
748 /**
749 * Return post comment count.
750 *
751 * @since 3.0.0
752 * @access private
753 * @param object $post_object
754 * @return int
755 */
756 private function get_comments(\stdClass $post_object)
757 {
758 $comments = ( ( $this->public_options['order_by'] == "comments" || $this->public_options['stats_tag']['comment_count'] ) && isset($post_object->comment_count) )
759 ? $post_object->comment_count
760 : 0;
761
762 return $comments;
763 }
764
765 /**
766 * Return post metadata.
767 *
768 * @since 3.0.0
769 * @access private
770 * @param object $post_object
771 * @param integer $post_id
772 * @return array
773 */
774 //private function get_metadata(\stdClass $post_object, $post_id)
775 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 */
776 {
777 $stats = [];
778
779 $prettify_numbers = apply_filters('wpp_pretiffy_numbers', true);
780
781 // comments
782 if ( $this->public_options['stats_tag']['comment_count'] ) {
783 $comments_text = sprintf(
784 _n('%s comment', '%s comments', $comments, 'wordpress-popular-posts'),
785 $prettify_numbers ? Helper::prettify_number($comments) : number_format_i18n($comments)
786 );
787
788 $stats['comments'] = '<span class="wpp-comments">' . $comments_text . '</span>';
789 }
790
791 // views
792 if ( $this->public_options['stats_tag']['views'] ) {
793 if ( $this->public_options['order_by'] == 'avg' ) {
794 $views_text = sprintf(
795 _n('%s view per day', '%s views per day', $pageviews, 'wordpress-popular-posts'),
796 $prettify_numbers ? Helper::prettify_number($pageviews, 2) : number_format_i18n($pageviews, (fmod($pageviews, 1) !== 0.0 ? 2 : 0))
797 );
798 }
799 else {
800 $views_text = sprintf(
801 _n('%s view', '%s views', $pageviews, 'wordpress-popular-posts'),
802 $prettify_numbers ? Helper::prettify_number($pageviews) : number_format_i18n($pageviews)
803 );
804 }
805
806 $stats['views'] = '<span class="wpp-views">' . $views_text . "</span>";
807 }
808
809 // author
810 if ( $this->public_options['stats_tag']['author'] ) {
811 $author_url = get_author_posts_url($post_object->uid != $post_id ? get_post_field('post_author', $post_id) : $post_object->uid);
812 $display_name = '<a href="' . esc_url($this->translate->url($author_url, $this->translate->get_current_language())) . '">' . esc_html($author) . '</a>';
813 $stats['author'] = '<span class="wpp-author">' . sprintf(__('by %s', 'wordpress-popular-posts'), $display_name) . '</span>';
814 }
815
816 // date
817 if ( $this->public_options['stats_tag']['date']['active'] ) {
818 $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>';
819 }
820
821 // taxonomy
822 if ( ($this->public_options['stats_tag']['category'] || $this->public_options['stats_tag']['taxonomy']['active']) && $post_tax != '' ) {
823 $stats['taxonomy'] = '<span class="wpp-category">' . sprintf(__('under %s', 'wordpress-popular-posts'), $post_tax) . '</span>';
824 }
825
826 return $stats;
827 }
828
829 /**
830 * Parse content tags.
831 *
832 * @since 1.4.6
833 * @access private
834 * @param string HTML string with content tags
835 * @param array Post data
836 * @param bool Used to display post rating (if functionality is available)
837 * @return string
838 */
839 private function format_content(string $string, array $data, bool $rating) {
840
841 if ( empty($string) || ( empty($data) || ! is_array($data) ) )
842 return false;
843
844 $params = [];
845 $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';
846 preg_match_all($pattern, $string, $matches);
847
848 array_map('strtolower', $matches[0]);
849
850 if ( in_array("{pid}", $matches[0]) ) {
851 $string = str_replace("{pid}", $data['id'], $string);
852 }
853
854 if ( in_array("{current_class}", $matches[0]) ) {
855 $string = str_replace("{current_class}", ( $data['is_current_post'] ? 'current' : '' ), $string);
856 }
857
858 if ( in_array("{title}", $matches[0]) ) {
859 $string = str_replace("{title}", $data['title'], $string);
860 }
861
862 if ( in_array("{title_attr}", $matches[0]) ) {
863 $string = str_replace("{title_attr}", $data['title_attr'], $string);
864 }
865
866 if ( in_array("{meta}", $matches[0]) || in_array("{stats}", $matches[0]) ) {
867 $string = str_replace(["{meta}", "{stats}"], $data['stats'], $string);
868 }
869
870 if ( in_array("{excerpt}", $matches[0]) || in_array("{summary}", $matches[0]) ) {
871 $string = str_replace(["{excerpt}", "{summary}"], $data['summary'], $string);
872 }
873
874 if ( in_array("{image}", $matches[0]) || in_array("{thumb}", $matches[0]) ) {
875 $string = str_replace(["{image}", "{thumb}"], $data['img'], $string);
876 }
877
878 if ( in_array("{thumb_img}", $matches[0]) ) {
879 $string = str_replace("{thumb_img}", $data['img_no_link'], $string);
880 }
881
882 if ( in_array("{thumb_url}", $matches[0]) && ! empty($data['img_no_link']) ) {
883 $dom = new \DOMDocument;
884
885 if ( $dom->loadHTML($data['img_no_link']) ) {
886 $img_tag = $dom->getElementsByTagName('img');
887
888 if ( $img_tag->length ) {
889 foreach( $img_tag as $node ) {
890 if ( $node->hasAttribute('src') ) {
891 $src = $node->getAttribute('src');
892 $string = str_replace("{thumb_url}", $src, $string);
893 }
894 }
895 }
896 }
897 }
898
899 // WP-PostRatings check
900 if ( $rating ) {
901 if ( function_exists('the_ratings_results') && in_array("{rating}", $matches[0]) ) {
902 $string = str_replace("{rating}", the_ratings_results($data['id']), $string);
903 }
904
905 if ( function_exists('expand_ratings_template') && in_array("{score}", $matches[0]) ) {
906 $string = str_replace("{score}", expand_ratings_template('%RATINGS_SCORE%', $data['id']), $string);
907 // removing the redundant plus sign
908 $string = str_replace('+', '', $string);
909 }
910 }
911
912 if ( in_array("{url}", $matches[0]) ) {
913 $string = str_replace("{url}", $data['url'], $string);
914 }
915
916 if ( in_array("{text_title}", $matches[0]) ) {
917 $string = str_replace("{text_title}", $data['text_title'], $string);
918 }
919
920 if ( in_array("{author}", $matches[0]) ) {
921 $string = str_replace("{author}", $data['author'], $string);
922 }
923
924 if ( in_array("{author_copy}", $matches[0]) ) {
925 $string = str_replace("{author_copy}", $data['author_copy'], $string);
926 }
927
928 if ( in_array("{author_name}", $matches[0]) ) {
929 $string = str_replace("{author_name}", $data['author_name'], $string);
930 }
931
932 if ( in_array("{author_url}", $matches[0]) ) {
933 $string = str_replace("{author_url}", $data['author_url'], $string);
934 }
935
936 if ( in_array("{taxonomy}", $matches[0]) || in_array("{category}", $matches[0]) ) {
937 $string = str_replace(["{taxonomy}", "{category}"], $data['taxonomy'], $string);
938 }
939
940 if ( in_array("{taxonomy_copy}", $matches[0]) || in_array("{category_copy}", $matches[0]) ) {
941 $string = str_replace(["{taxonomy_copy}", "{category_copy}"], $data['taxonomy_copy'], $string);
942 }
943
944 if ( in_array("{views}", $matches[0]) ) {
945 $string = str_replace("{views}", $data['views'], $string);
946 }
947
948 if ( in_array("{views_copy}", $matches[0]) ) {
949 $string = str_replace("{views_copy}", $data['views_copy'], $string);
950 }
951
952 if ( in_array("{comments}", $matches[0]) ) {
953 $string = str_replace("{comments}", $data['comments'], $string);
954 }
955
956 if ( in_array("{comments_copy}", $matches[0]) ) {
957 $string = str_replace("{comments_copy}", $data['comments_copy'], $string);
958 }
959
960 if ( in_array("{date}", $matches[0]) ) {
961 $string = str_replace("{date}", $data['date'], $string);
962 }
963
964 if ( in_array("{date_copy}", $matches[0]) ) {
965 $string = str_replace("{date_copy}", $data['date_copy'], $string);
966 }
967
968 if ( in_array("{total_items}", $matches[0]) ) {
969 $string = str_replace("{total_items}", $data['total_items'], $string);
970 }
971
972 if ( in_array("{item_position}", $matches[0]) ) {
973 $string = str_replace("{item_position}", $data['item_position'], $string);
974 }
975
976 return apply_filters("wpp_parse_custom_content_tags", $string, $data['id']);
977 }
978
979 /**
980 * Checks whether we're currently seeing a single post/page/CPT.
981 *
982 * @since 5.0.0
983 * @return int
984 */
985 public function is_single()
986 {
987 return apply_filters('wpp_is_single', Helper::is_single());
988 }
989 }
990