PluginProbe ʕ •ᴥ•ʔ
WP Popular Posts / 7.3.8
WP Popular Posts v7.3.8
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 / Block / Widget / Widget.php
wordpress-popular-posts / src / Block / Widget Last commit date
Widget.php 1 year ago edit.js 1 year ago editor.css 4 years ago widget.js 8 months ago
Widget.php
517 lines
1 <?php
2 namespace WordPressPopularPosts\Block\Widget;
3
4 use WordPressPopularPosts\{ Helper, Image, Output, Themer, Translate };
5 use WordPressPopularPosts\Block\Block;
6 use WordPressPopularPosts\Traits\QueriesPosts;
7
8 class Widget extends Block
9 {
10
11 use QueriesPosts;
12
13 /**
14 * Administrative settings.
15 *
16 * @since 5.4.0
17 * @var array
18 * @access private
19 */
20 private $config = [];
21
22 /**
23 * Image object.
24 *
25 * @since 5.4.0
26 * @var WordPressPopularPosts\Image
27 * @access private
28 */
29 private $thumbnail;
30
31 /**
32 * Output object.
33 *
34 * @since 5.4.0
35 * @var \WordPressPopularPosts\Output
36 * @access private
37 */
38 private $output;
39
40 /**
41 * Translate object.
42 *
43 * @since 5.4.0
44 * @var \WordPressPopularPosts\Translate $translate
45 * @access private
46 */
47 private $translate;
48
49 /**
50 * Themer object.
51 *
52 * @since 5.4.0
53 * @var \WordPressPopularPosts\Themer $themer
54 * @access private
55 */
56 private $themer;
57
58 /**
59 * Default attributes.
60 *
61 * @since 5.4.0
62 * @var array $defaults
63 * @access private
64 */
65 private $defaults;
66
67 /**
68 * Construct.
69 *
70 * @since 5.4.0
71 * @param array $config
72 * @param \WordPressPopularPosts\Output $output
73 * @param \WordPressPopularPosts\Image $image
74 * @param \WordPressPopularPosts\Translate $translate
75 * @param \WordPressPopularPosts\Themer $themer
76 */
77 public function __construct(array $config, Output $output, Image $thumbnail, Translate $translate, Themer $themer)
78 {
79 $this->config = $config;
80 $this->output = $output;
81 $this->thumbnail = $thumbnail;
82 $this->translate = $translate;
83 $this->themer = $themer;
84
85 $this->defaults = [
86 'title' => '',
87 'limit' => 10,
88 'offset' => 0,
89 'range' => 'daily',
90 'time_unit' => 'hour',
91 'time_quantity' => 24,
92 'freshness' => false,
93 'order_by' => 'views',
94 'post_type' => 'post',
95 'pid' => '', // Deprecated
96 'exclude' => '',
97 'cat' => '',
98 'taxonomy' => 'category',
99 'tax' => '',
100 'term_id' => '',
101 'author' => '',
102 'title_length' => 0,
103 'title_by_words' => 0,
104 'excerpt_length' => 0,
105 'excerpt_format' => 0,
106 'excerpt_by_words' => 0,
107 'thumbnail_width' => 0,
108 'thumbnail_height' => 0,
109 'thumbnail_build' => 'manual',
110 'thumbnail_size' => '',
111 'rating' => false,
112 'stats_comments' => false,
113 'stats_views' => true,
114 'stats_author' => false,
115 'stats_date' => false,
116 'stats_date_format' => 'F j, Y',
117 'stats_category' => false,
118 'stats_taxonomy' => false,
119 'custom_html' => false,
120 'wpp_start' => '<ul class="wpp-list">',
121 'wpp_end' => '</ul>',
122 'header_start' => '<h2>',
123 'header_end' => '</h2>',
124 'post_html' => '',
125 'theme' => ''
126 ];
127 }
128
129 /**
130 * Registers the block.
131 *
132 * @since 5.4.0
133 */
134 public function register()
135 {
136 // Block editor is not available, bail.
137 if ( ! function_exists('register_block_type') ) {
138 return;
139 }
140
141 $block_editor_support = apply_filters('wpp_block_editor_support', true);
142
143 if ( ! $block_editor_support ) {
144 return;
145 }
146
147 wp_register_script(
148 'block-wpp-widget-js',
149 plugin_dir_url(dirname(dirname(dirname(__FILE__)))) . 'assets/js/blocks/block-wpp-widget.js',
150 ['wp-blocks', 'wp-i18n', 'wp-element', 'wp-block-editor', 'wp-server-side-render'],
151 filemtime(plugin_dir_path(dirname(dirname(dirname(__FILE__)))) . 'assets/js/blocks/block-wpp-widget.js')
152 );
153
154 wp_localize_script(
155 'block-wpp-widget-js',
156 '_wordpress_popular_posts',
157 [
158 'can_show_rating' => function_exists('the_ratings_results')
159 ]
160 );
161
162 wp_register_style(
163 'block-wpp-editor-css',
164 plugins_url('editor.css', __FILE__),
165 [],
166 filemtime(plugin_dir_path(__FILE__) . 'editor.css')
167 );
168
169 register_block_type(
170 'wordpress-popular-posts/widget',
171 [
172 'editor_style' => 'block-wpp-editor-css',
173 'editor_script' => 'block-wpp-widget-js',
174 'render_callback' => [$this, 'render'],
175 'attributes' => [
176 '_editMode' => [
177 'type' => 'boolean',
178 'default' => true
179 ],
180 '_isSelected' => [
181 'type' => 'boolean',
182 'default' => false
183 ],
184 'title' => [
185 'type' => 'string',
186 'default' => ''
187 ],
188 'limit' => [
189 'type' =>'number',
190 'default' => 10
191 ],
192 'offset' => [
193 'type' => 'number',
194 'default' => 0
195 ],
196 'order_by' => [
197 'type' => 'string',
198 'default' => 'views'
199 ],
200 'range' => [
201 'type' => 'string',
202 'default' => 'last24hours'
203 ],
204 'time_quantity' => [
205 'type' => 'number',
206 'default' => 24
207 ],
208 'time_unit' => [
209 'type' => 'string',
210 'default' => 'hour'
211 ],
212 'freshness' => [
213 'type' => 'boolean',
214 'default' => false
215 ],
216 /* filters */
217 'post_type' => [
218 'type' => 'string',
219 'default' => 'post'
220 ],
221 'pid' => /* Deprecated */ [
222 'type' => 'string',
223 'default' => ''
224 ],
225 'exclude' => [
226 'type' => 'string',
227 'default' => ''
228 ],
229 'author' => [
230 'type' => 'string',
231 'default' => ''
232 ],
233 'tax' => [
234 'type' => 'string',
235 'default' => ''
236 ],
237 'term_id' => [
238 'type' => 'string',
239 'default' => ''
240 ],
241 /* post settings */
242 'shorten_title' => [
243 'type' => 'boolean',
244 'default' => false
245 ],
246 'title_length' => [
247 'type' =>'number',
248 'default' => 0
249 ],
250 'title_by_words' => [
251 'type' =>'number',
252 'default' => 0
253 ],
254 'display_post_excerpt' => [
255 'type' => 'boolean',
256 'default' => false
257 ],
258 'excerpt_format' => [
259 'type' => 'boolean',
260 'default' => false
261 ],
262 'excerpt_length' => [
263 'type' =>'number',
264 'default' => 0
265 ],
266 'excerpt_by_words' => [
267 'type' =>'number',
268 'default' => 0
269 ],
270 'display_post_thumbnail' => [
271 'type' => 'boolean',
272 'default' => false
273 ],
274 'thumbnail_width' => [
275 'type' =>'number',
276 'default' => 0
277 ],
278 'thumbnail_height' => [
279 'type' =>'number',
280 'default' => 0
281 ],
282 'thumbnail_build' => [
283 'type' => 'string',
284 'default' => 'manual'
285 ],
286 'thumbnail_size' => [
287 'type' => 'string',
288 'default' => ''
289 ],
290 'rating' => [
291 'type' => 'boolean',
292 'default' => false
293 ],
294 /* stats tag settings */
295 'stats_comments' => [
296 'type' => 'boolean',
297 'default' => false
298 ],
299 'stats_views' => [
300 'type' => 'boolean',
301 'default' => true
302 ],
303 'stats_author' => [
304 'type' => 'boolean',
305 'default' => false
306 ],
307 'stats_date' => [
308 'type' => 'boolean',
309 'default' => false
310 ],
311 'stats_date_format' => [
312 'type' => 'string',
313 'default' => 'F j, Y'
314 ],
315 'stats_taxonomy' => [
316 'type' => 'boolean',
317 'default' => false
318 ],
319 'taxonomy' => [
320 'type' => 'string',
321 'default' => 'category'
322 ],
323 /* HTML markup settings */
324 'custom_html' => [
325 'type' => 'boolean',
326 'default' => false
327 ],
328 'header_start' => [
329 'type' => 'string',
330 'default' => '<h2>'
331 ],
332 'header_end' => [
333 'type' => 'string',
334 'default' => '</h2>'
335 ],
336 'wpp_start' => [
337 'type' => 'string',
338 'default' => '<ul class="wpp-list">'
339 ],
340 'wpp_end' => [
341 'type' => 'string',
342 'default' => '</ul>'
343 ],
344 'post_html' => [
345 'type' => 'string',
346 'default' => '<li class="{current_class}">{thumb} {title} <span class="wpp-meta post-stats">{stats}</span></li>'
347 ],
348 'theme' => [
349 'type' => 'string',
350 'default' => ''
351 ],
352 ]
353 ]
354 );
355 }
356
357 /**
358 * Renders the block.
359 *
360 * @since 5.4.0
361 * @param array
362 * @return string
363 */
364 public function render(array $attributes)
365 {
366 extract($this->parse_attributes($attributes));
367
368 $html = '<div class="popular-posts' . (( isset($attributes['className']) && $attributes['className'] ) ? ' ' . esc_attr($attributes['className']) : '') . '">';
369
370 // possible values for "Time Range" and "Order by"
371 $time_units = ['minute', 'hour', 'day', 'week', 'month'];
372 $range_values = ['daily', 'last24hours', 'weekly', 'last7days', 'monthly', 'last30days', 'all', 'custom'];
373 $order_by_values = ['comments', 'views', 'avg'];
374
375 $theme_data = $this->themer->get_theme($theme);
376
377 if ( ! isset($theme_data['json']) ) {
378 $theme = '';
379 }
380
381 $query_args = [
382 'title' => strip_tags($title), // phpcs:ignore WordPress.WP.AlternativeFunctions.strip_tags_strip_tags -- We want the behavior of strip_tags
383 'limit' => ( ! empty($limit) && Helper::is_number($limit) && $limit > 0 ) ? $limit : 10,
384 'offset' => ( ! empty($offset) && Helper::is_number($offset) && $offset >= 0 ) ? $offset : 0,
385 'range' => ( in_array($range, $range_values) ) ? $range : 'daily',
386 'time_quantity' => ( ! empty($time_quantity) && Helper::is_number($time_quantity) && $time_quantity > 0 ) ? $time_quantity : 24,
387 'time_unit' => ( in_array($time_unit, $time_units) ) ? $time_unit : 'hour',
388 'freshness' => empty($freshness) ? false : $freshness,
389 'order_by' => ( in_array($order_by, $order_by_values) ) ? $order_by : 'views',
390 'post_type' => empty($post_type) ? 'post' : $post_type,
391 'pid' => rtrim(preg_replace('|[^0-9,]|', '', $pid), ','), /** Deprecated */
392 'exclude' => rtrim(preg_replace('|[^0-9,]|', '', $exclude), ','),
393 'taxonomy' => empty($tax) ? 'category' : $tax,
394 'term_id' => rtrim(preg_replace('|[^0-9,;-]|', '', $term_id), ','),
395 'author' => rtrim(preg_replace('|[^0-9,]|', '', $author), ','),
396 'shorten_title' => [
397 'active' => ( (bool) $attributes['shorten_title'] && ! empty($title_length) && Helper::is_number($title_length) && $title_length > 0 ),
398 'length' => ( ! empty($title_length) && Helper::is_number($title_length) ) ? $title_length : 0,
399 'words' => (( ! empty($title_by_words) && Helper::is_number($title_by_words) && $title_by_words > 0 )),
400 ],
401 'post-excerpt' => [
402 'active' => ( (bool) $attributes['display_post_excerpt'] && ! empty($excerpt_length) && Helper::is_number($excerpt_length) && $excerpt_length > 0 ),
403 'length' => ( ! empty($excerpt_length) && Helper::is_number($excerpt_length) ) ? $excerpt_length : 0,
404 'keep_format' => ( ! empty($excerpt_format) && Helper::is_number($excerpt_format) && $excerpt_format > 0 ),
405 'words' => ( ! empty($excerpt_by_words) && Helper::is_number($excerpt_by_words) && $excerpt_by_words > 0 ),
406 ],
407 'thumbnail' => [
408 'active' => ( 'predefined' == $thumbnail_build && (bool) $attributes['display_post_thumbnail'] ) ? true : ( ! empty($thumbnail_width) && Helper::is_number($thumbnail_width) && $thumbnail_width > 0 ),
409 'width' => ( ! empty($thumbnail_width) && Helper::is_number($thumbnail_width) && $thumbnail_width > 0 ) ? $thumbnail_width : 0,
410 'height' => ( ! empty($thumbnail_height) && Helper::is_number($thumbnail_height) && $thumbnail_height > 0 ) ? $thumbnail_height : 0,
411 'build' => 'predefined' == $thumbnail_build ? 'predefined' : 'manual',
412 'size' => empty($thumbnail_size) ? '' : $thumbnail_size,
413 ],
414 'rating' => (bool) $attributes['rating'],
415 'stats_tag' => [
416 'comment_count' => (bool) $attributes['stats_comments'],
417 'views' => (bool) $attributes['stats_views'],
418 'author' => (bool) $attributes['stats_author'],
419 'date' => [
420 'active' => (bool) $attributes['stats_date'],
421 'format' => empty($stats_date_format) ? 'F j, Y' : $stats_date_format
422 ],
423 'taxonomy' => [
424 'active' => (bool) $attributes['stats_taxonomy'],
425 'name' => empty($taxonomy) ? 'category' : $taxonomy,
426 ]
427 ],
428 'markup' => [
429 'custom_html' => (bool) $attributes['custom_html'],
430 'wpp-start' => empty($wpp_start) ? '' : $wpp_start,
431 'wpp-end' => empty($wpp_end) ? '' : $wpp_end,
432 'title-start' => empty($header_start) ? '' : $header_start,
433 'title-end' => empty($header_end) ? '' : $header_end,
434 'post-html' => empty($post_html) ? '<li>{thumb} {title} <span class="wpp-meta post-stats">{stats}</span></li>' : $post_html
435 ],
436 'theme' => [
437 'name' => empty($theme) ? '' : $theme
438 ]
439 ];
440
441 // Post / Page / CTP filter
442 $query_args['exclude'] = $query_args['pid'];
443
444 $ids = array_filter(explode(',', $query_args['exclude']), 'is_numeric');
445 // Got no valid IDs, clear
446 if ( empty($ids) ) {
447 $query_args['pid'] = '';
448 $query_args['exclude'] = '';
449 }
450
451 // Taxonomy filter
452 $ids = array_filter(explode(',', $query_args['term_id']), 'is_numeric');
453 // Got no valid term IDs, clear
454 if ( empty($ids) ) {
455 $query_args['term_id'] = '';
456 }
457
458 // Author filter
459 $ids = array_filter(explode(',', $query_args['author']), 'is_numeric');
460 // Got no valid IDs, clear
461 if ( empty($ids) ) {
462 $query_args['author'] = '';
463 }
464
465 // Has the user set a title?
466 if (
467 ! empty($query_args['title'])
468 && ! empty($query_args['markup']['title-start'])
469 && ! empty($query_args['markup']['title-end'])
470 ) {
471 $header_html = htmlspecialchars_decode($query_args['markup']['title-start'], ENT_QUOTES) . $query_args['title'] . htmlspecialchars_decode($query_args['markup']['title-end'], ENT_QUOTES);
472 $header_html = apply_filters('wpp_custom_header_html', $header_html, $query_args);
473 $header_html = Helper::sanitize_html($header_html, $query_args);
474 $html .= $header_html;
475 }
476
477 $isAdmin = isset($_GET['isSelected']) ? $_GET['isSelected'] : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- isSelected is a boolean from wp-admin
478
479 if ( $this->config['tools']['ajax'] && ! is_customize_preview() && ! $isAdmin ) {
480 $html .= '<script type="application/json" data-id="wpp-block-inline-js">' . json_encode($query_args) . '</script>';
481 $html .= '<div class="wpp-widget-block-placeholder"></div>';
482
483 return $html . '</div>';
484 }
485
486 $popular_posts = $this->maybe_query($query_args);
487
488 $this->output->set_data($popular_posts->get_posts());
489 $this->output->set_public_options($query_args);
490 $this->output->build_output();
491
492 $html .= $this->output->get_output();
493
494 $html .= '</div>';
495
496 return $html;
497 }
498
499 /**
500 * Parses attributes.
501 *
502 * @since 5.4.0
503 * @param array
504 * @return array
505 */
506 private function parse_attributes(array $atts = [])
507 {
508 $out = array();
509
510 foreach ( $this->defaults as $name => $default ) {
511 $out[$name] = array_key_exists($name, $atts) ? trim($atts[$name]) : $default;
512 }
513
514 return $out;
515 }
516 }
517