PluginProbe
MarqueeX – Smooth Marquee Slider, News Ticker & Post Marquee for Block Editor & Elementor / 0.6.0
MarqueeX – Smooth Marquee Slider, News Ticker & Post Marquee for Block Editor & Elementor v0.6.0
0.6.0 0.5.4 0.5.3 0.5.2 0.5.1 0.5.0 0.4.0 0.3.3 0.3.2 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.1.0 0.1.1 0.1.2 0.2.0 0.2.1 0.2.2 0.2.3 0.3.0 0.3.1
marqueex / includes / Traits / MarqueeSource.php

MarqueeSource.php in MarqueeX – Smooth Marquee Slider, News Ticker & Post Marquee for Block Editor & Elementor 0.6.0, at includes/Traits/MarqueeSource.php

129 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Wpxero\Marqueex\Traits;
4
5 if (!defined('ABSPATH')) {
6 exit;
7 }
8
9 /**
10 * Shared post-source helpers for the dynamic marquee widgets.
11 *
12 * These methods were previously copy-pasted byte-for-byte across the
13 * TextMarquee, NewsTicker and ImageMarquee widgets. Consolidated here so a
14 * single fix applies to all three. Behavior is unchanged from the originals.
15 */
16 trait MarqueeSource {
17
18 /**
19 * Get available post types (public, navigable; sensitive types filtered out).
20 */
21 private function get_post_types() {
22 $post_types = get_post_types(['public' => true, 'show_in_nav_menus' => true], 'objects');
23 $post_types = wp_list_pluck($post_types, 'label', 'name');
24
25 // Security: Filter out sensitive post types
26 $excluded_types = ['elementor_library', 'attachment', 'revision', 'nav_menu_item'];
27 return array_diff_key($post_types, array_flip($excluded_types));
28 }
29
30 /**
31 * Get available post categories keyed by term id.
32 */
33 private function get_post_categories() {
34 $categories = get_categories(['hide_empty' => false]);
35 $options = [];
36
37 foreach ($categories as $category) {
38 if ($category instanceof \WP_Term) {
39 $options[intval($category->term_id)] = sanitize_text_field($category->name);
40 }
41 }
42
43 return $options;
44 }
45
46 /**
47 * Build sanitized WP_Query args for the marquee post source.
48 */
49 private function get_query_args($settings = []) {
50 $settings = wp_parse_args($settings, [
51 'post_type' => 'post',
52 'posts_per_page' => 6,
53 'category_ids' => [],
54 'orderby' => 'date',
55 'order' => 'desc',
56 ]);
57
58 // Security: Sanitize and validate inputs
59 $post_type = sanitize_text_field($settings['post_type']);
60 $posts_per_page = min(50, max(1, intval($settings['posts_per_page']))); // Limit to prevent performance issues
61 $orderby = in_array($settings['orderby'], ['date', 'title', 'rand', 'menu_order']) ? $settings['orderby'] : 'date';
62 $order = strtoupper($settings['order']) === 'ASC' ? 'ASC' : 'DESC';
63
64 $args = [
65 'post_type' => $post_type,
66 'post_status' => 'publish',
67 'ignore_sticky_posts' => true,
68 'posts_per_page' => $posts_per_page,
69 'no_found_rows' => true, // Performance: Skip pagination queries
70 'update_post_meta_cache' => false, // Performance: Skip meta cache if not needed
71 'update_post_term_cache' => false, // Performance: Skip term cache if not needed
72 ];
73
74 // Order by & order
75 if ('rand' === $orderby) {
76 $args['orderby'] = 'rand';
77 } else {
78 $args['orderby'] = $orderby;
79 $args['order'] = $order;
80 }
81
82 // Category filter with security validation
83 if (!empty($settings['category_ids']) && $post_type === 'post') {
84 $category_ids = array_map('intval', (array) $settings['category_ids']);
85 $category_ids = array_filter($category_ids, function ($id) {
86 return $id > 0 && term_exists($id, 'category');
87 });
88
89 if (!empty($category_ids)) {
90 $args['category__in'] = $category_ids;
91 }
92 }
93
94 return $args;
95 }
96
97 /**
98 * Duplicate the post list until there are enough items for a smooth,
99 * seamless marquee loop.
100 */
101 private function ensure_minimum_posts($posts) {
102 if (empty($posts)) {
103 return [];
104 }
105
106 // Duplicate posts until we reach the minimum needed for a smooth marquee.
107 while (count($posts) < 10) {
108 $posts = array_merge($posts, $posts);
109 }
110
111 return $posts;
112 }
113
114 /**
115 * Resolve the link target for a post, honoring custom URLs.
116 */
117 private function get_post_url($post) {
118 if (!$post instanceof \WP_Post) {
119 return '';
120 }
121
122 if (isset($post->is_custom) && $post->is_custom && !empty($post->custom_url)) {
123 return esc_url_raw($post->custom_url);
124 }
125
126 return get_permalink($post) ?: '';
127 }
128 }
129