PluginProbe
WpStream – Live Streaming, Video on Demand, Pay Per View / 4.14.1
WpStream – Live Streaming, Video on Demand, Pay Per View v4.14.1
4.14.1 4.14.0 4.13.2 4.13.1 4.13 4.12.5 4.12.4 4.12.3 4.12.2 4.12.1 4.12 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5 4.5.1 4.5.11 4.5.11.1 4.5.11.2 4.5.11.4 4.5.11.5 4.5.11.6 All 181 releases
wpstream / hello-wpstream / framework / shortcodes-functions.php

shortcodes-functions.php in WpStream – Live Streaming, Video on Demand, Pay Per View 4.14.1, at hello-wpstream/framework/shortcodes-functions.php

681 lines 28.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Shortcodes functions.
4 *
5 * AJAX "load more" / filtering endpoints and the HTML-building helpers behind
6 * the theme's item-list and blog-list shortcodes: reading paging/filter params
7 * from the request, rendering item cards into buffered HTML, composing the
8 * hidden AJAX data holder, and generating taxonomy filter dropdowns.
9 *
10 * @package wpstream-theme
11 */
12
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 // Register the "with top bar" load-more handler for logged-out and logged-in users.
20 add_action( 'wp_ajax_nopriv_wpstream_shortcode_with_top_bar_load_more_function', 'wpstream_shortcode_with_top_bar_load_more_function' );
21 add_action( 'wp_ajax_wpstream_shortcode_with_top_bar_load_more_function', 'wpstream_shortcode_with_top_bar_load_more_function' );
22 // Guard against redeclaration.
23 if ( ! function_exists( 'wpstream_shortcode_with_top_bar_load_more_function' ) ) {
24 /**
25 * Shortcode load more (top-bar variant).
26 *
27 * Reads paging/filter parameters from $_POST, then delegates rendering to
28 * wpstream_theme_recent_items_top_bar().
29 *
30 * @return void
31 */
32 function wpstream_shortcode_with_top_bar_load_more_function() {
33 // Deliberately NO nonce here (issue #113): this is a nopriv, read-only
34 // listing renderer served on cacheable public pages — a cached nonce
35 // expires/mismatches and would break pagination for guests, while CSRF
36 // does not apply to a state-less public endpoint. All inputs below are
37 // sanitized instead.
38
39 $attributes = array();
40 $attributes['paged'] = isset( $_POST['paged'] ) ? intval( $_POST['paged'] ) : 0;
41 $attributes['type'] = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';
42 $attributes['category_ids'] = isset( $_POST['category_ids'] ) ? sanitize_text_field( wp_unslash( $_POST['category_ids'] ) ) : '';
43 $attributes['wpstream_category_ids'] = isset( $_POST['wpstream_category_ids'] ) ? sanitize_text_field( wp_unslash( $_POST['wpstream_category_ids'] ) ) : '';
44 $attributes['movie_ratings_ids'] = isset( $_POST['movie_ratings_ids'] ) ? sanitize_text_field( wp_unslash( $_POST['movie_ratings_ids'] ) ) : '';
45 $attributes['actors_ids'] = isset( $_POST['actors_ids'] ) ? sanitize_text_field( wp_unslash( $_POST['actors_ids'] ) ) : '';
46 $attributes['number'] = isset( $_POST['number'] ) ? intval( $_POST['number'] ) : 0;
47 $attributes['rownumber'] = isset( $_POST['rownumber'] ) ? intval( $_POST['rownumber'] ) : 0;
48 $attributes['sort_by'] = isset( $_POST['sort_by'] ) ? intval( $_POST['sort_by'] ) : 0;
49 $attributes['pagination_type'] = isset( $_POST['pagination_type'] ) ? intval( $_POST['pagination_type'] ) : 0;
50 $attributes['is_ajax_request'] = isset( $_POST['is_ajax'] ) ? intval( $_POST['is_ajax'] ) : 0;
51 $attributes['current_page'] = isset( $_POST['current_page'] ) ? intval( $_POST['current_page'] ) : 0;
52 $attributes['video_card'] = isset( $_POST['video_card'] ) ? intval( $_POST['video_card'] ) : 1;
53 // Render the next page of items (top-bar layout) and echo the HTML.
54 wpstream_theme_recent_items_top_bar( $attributes );
55 }
56 }
57
58
59
60 /**
61 * Shortcodes functions
62 *
63 * @package wpstream-theme
64 */
65
66 // Register the standard item-list load-more handler for logged-out and logged-in users.
67 add_action( 'wp_ajax_nopriv_wpstream_shortcode_load_more_function', 'wpstream_shortcode_load_more_function' );
68 add_action( 'wp_ajax_wpstream_shortcode_load_more_function', 'wpstream_shortcode_load_more_function' );
69 // Guard against redeclaration.
70 if ( ! function_exists( 'wpstream_shortcode_load_more_function' ) ) {
71 /**
72 * Shortcode load more (item list).
73 *
74 * Verifies the AJAX nonce, reads paging/filter parameters from $_POST, then
75 * delegates rendering to wpstream_item_list_shortcodes().
76 *
77 * @return void
78 */
79 function wpstream_shortcode_load_more_function() {
80 // Verify nonce.
81 // Reject the request when the shortcode AJAX nonce is missing or invalid.
82 if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'shortcode_nonce_ajax_action' ) ) {
83 wp_send_json_error( 'Nonce verification failed.', 403 );
84 }
85
86 $attributes = array();
87 $attributes['paged'] = isset( $_POST['paged'] ) ? intval( $_POST['paged'] ) : 0;
88 $attributes['type'] = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';
89 $attributes['category_ids'] = isset( $_POST['category_ids'] ) ? sanitize_text_field( wp_unslash( $_POST['category_ids'] ) ) : '';
90 $attributes['wpstream_category_ids'] = isset( $_POST['wpstream_category_ids'] ) ? sanitize_text_field( wp_unslash( $_POST['wpstream_category_ids'] ) ) : '';
91 $attributes['movie_ratings_ids'] = isset( $_POST['movie_ratings_ids'] ) ? sanitize_text_field( wp_unslash( $_POST['movie_ratings_ids'] ) ) : '';
92 $attributes['actors_ids'] = isset( $_POST['actors_ids'] ) ? sanitize_text_field( wp_unslash( $_POST['actors_ids'] ) ) : '';
93 $attributes['number'] = isset( $_POST['number'] ) ? intval( $_POST['number'] ) : 0;
94 $attributes['rownumber'] = isset( $_POST['rownumber'] ) ? intval( $_POST['rownumber'] ) : 0;
95 $attributes['sort_by'] = isset( $_POST['sort_by'] ) ? intval( $_POST['sort_by'] ) : 0;
96 $attributes['pagination_type'] = isset( $_POST['pagination_type'] ) ? intval( $_POST['pagination_type'] ) : 0;
97 $attributes['is_ajax_request'] = isset( $_POST['is_ajax'] ) ? intval( $_POST['is_ajax'] ) : 0;
98 $attributes['current_page'] = isset( $_POST['current_page'] ) ? intval( $_POST['current_page'] ) : 0;
99 $attributes['video_uid'] = isset( $_POST['video_uid'] ) ? sanitize_text_field( $_POST['video_uid'] ) : 0;
100 $attributes['video_card'] = isset( $_POST['video_card'] ) ? sanitize_text_field( $_POST['video_card'] ) : 1;
101 // Render the next page of item cards and echo the HTML.
102 wpstream_item_list_shortcodes( $attributes );
103 }
104 }
105
106
107 /**
108 * Shortcodes functions
109 *
110 * @package wpstream-theme
111 */
112
113 // Register the blog-list load-more handler for logged-out and logged-in users.
114 add_action( 'wp_ajax_nopriv_wpstream_shortcode_load_more_blog_list_function', 'wpstream_shortcode_load_more_blog_list_function' );
115 add_action( 'wp_ajax_wpstream_shortcode_load_more_blog_list_function', 'wpstream_shortcode_load_more_blog_list_function' );
116 // Guard against redeclaration.
117 if ( ! function_exists( 'wpstream_shortcode_load_more_blog_list_function' ) ) {
118 /**
119 * Shortcode load more (blog list).
120 *
121 * Verifies the AJAX nonce, reads paging/filter parameters from $_POST, then
122 * delegates rendering to wpstream_blog_list_shortcodes().
123 *
124 * @return void
125 */
126 function wpstream_shortcode_load_more_blog_list_function() {
127 // Verify nonce.
128 // Reject the request when the shortcode AJAX nonce is missing or invalid.
129 if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'shortcode_nonce_ajax_action' ) ) {
130 wp_send_json_error( 'Nonce verification failed.', 403 );
131 }
132
133 $attributes = array();
134 $attributes['paged'] = isset( $_POST['paged'] ) ? intval( $_POST['paged'] ) : 0;
135 $attributes['type'] = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';
136 $attributes['category_ids'] = isset( $_POST['category_ids'] ) ? sanitize_text_field( wp_unslash( $_POST['category_ids'] ) ) : '';
137 $attributes['number'] = isset( $_POST['number'] ) ? intval( $_POST['number'] ) : 0;
138 $attributes['rownumber'] = isset( $_POST['rownumber'] ) ? intval( $_POST['rownumber'] ) : 0;
139 $attributes['sort_by'] = isset( $_POST['sort_by'] ) ? intval( $_POST['sort_by'] ) : 0;
140 $attributes['pagination_type'] = isset( $_POST['pagination_type'] ) ? intval( $_POST['pagination_type'] ) : 0;
141 $attributes['is_ajax_request'] = isset( $_POST['is_ajax'] ) ? intval( $_POST['is_ajax'] ) : 0;
142 $attributes['current_page'] = isset( $_POST['current_page'] ) ? intval( $_POST['current_page'] ) : 0;
143 $attributes['blog_uid'] = isset( $_POST['blog_uid'] ) ? sanitize_text_field( $_POST['blog_uid'] ) : '';
144
145 // Render the next page of blog posts and echo the HTML.
146 wpstream_blog_list_shortcodes( $attributes );
147 }
148 }
149
150 if ( ! function_exists( 'wpstream_populate_from_get' ) ) :
151 /**
152 * Populates attributes from $_GET array if 'from_ajax' is set to 'yes'.
153 *
154 * @param array $attributes Array of attributes.
155 * @return array Populated attributes.
156 */
157 function wpstream_populate_from_get( $attributes ) {
158 // Only overlay $_GET values when this is an AJAX-driven filter request.
159 if ( isset( $_GET['from_ajax'] ) && 'yes' === $_GET['from_ajax'] ) {
160 // Bail (leaving attributes untouched) if the nonce is missing or invalid.
161 if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['nonce'] ) ), 'shortcode_nonce_ajax_action' ) ) {
162 // Nonce verification failed.
163 return $attributes;
164 }
165
166 // Copy each supported filter parameter from the query string into the attributes.
167 $attributes['type'] = isset( $_GET['type'] ) ? sanitize_text_field( wp_unslash( $_GET['type'] ) ) : '';
168 $attributes['category_ids'] = isset( $_GET['category_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['category_ids'] ) ) : '';
169 $attributes['wpstream_category_ids'] = isset( $_GET['wpstream_category_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['wpstream_category_ids'] ) ) : '';
170 $attributes['movie_ratings_ids'] = isset( $_GET['movie_ratings_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['movie_ratings_ids'] ) ) : '';
171 $attributes['actors_ids'] = isset( $_GET['actors_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['actors_ids'] ) ) : '';
172 $attributes['sort_by'] = isset( $_GET['sort_by'] ) ? sanitize_text_field( wp_unslash( $_GET['sort_by'] ) ) : '';
173 }
174
175 return $attributes;
176 }
177 endif;
178
179
180 if ( ! function_exists( 'wpstream_return_item_list_elementor' ) ) {
181 /**
182 * Returns a list of items for use in Elementor.
183 *
184 * @param WP_Query $query The WordPress query to retrieve items.
185 * @param string $items_column_class CSS class for the columns where the items will be placed.
186 */
187 function wpstream_return_item_list_elementor( $query, $items_column_class ) {
188 // Exposed to the included template so it can apply the column CSS class.
189 $overwrite_wpstream_cols_name = $items_column_class;
190
191 // Render the loop template only when the query returned results.
192 if ( $query->found_posts > 0 ) {
193 include WPSTREAM_PLUGIN_PATH . '/hello-wpstream/template-parts/single/video-loop-content.php';
194 }
195 }
196 }
197
198
199 if ( ! function_exists( 'wpstream_return_item_list_pagination' ) ) {
200 /**
201 * Returns the pagination for the item list.
202 *
203 * @param WP_Query $query The WordPress query used to retrieve items.
204 * @param int $pagination Type of pagination (1 for "Load More" button, 2 for standard pagination).
205 */
206 function wpstream_return_item_list_pagination( $query, $pagination,$uid='' ) {
207
208 // With results, print the pagination controls; otherwise print an empty-state message.
209 if ( $query->found_posts > 0 ) {
210 print wpstream_add_pagination( $query, $pagination ,$uid); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
211 } else {
212 print '<div class="wpstream-pagination">' . esc_html__( 'There are no items', 'hello-wpstream' ) . '</div>';
213 }
214 }
215 }
216
217 if ( ! function_exists( 'wpstream_return_ajax_elements' ) ) {
218 /**
219 * Returns the HTML elements for AJAX response.
220 *
221 * @param WP_Query $query The WordPress query used to retrieve items.
222 * @param string $items_column_class The CSS class for the items column.
223 * @return array An array containing the post count and HTML content.
224 */
225 function wpstream_return_ajax_elements( $query, $items_column_class,$unit='',$card_type=1 ) {
226 // Exposed to the included card templates for column sizing.
227 $overwrite_wpstream_cols_name = $items_column_class;
228
229 // Buffer the card markup so it can be returned as a string.
230 ob_start();
231 // Alternate variable name some card templates read for the grid class.
232 $card_grid_class_overwrite =$items_column_class;
233 if ( $query->found_posts > 0 ) {
234 // Render one card per post in the loop.
235 while ( $query->have_posts() ) {
236 $query->the_post();
237 // Blog items use the blog card template; everything else uses the video card template.
238 if ( 'blog' === $unit ) {
239 $blog_unit_card_type = wpstream_blog_post_card_selector(0);
240 include WPSTREAM_PLUGIN_PATH . 'hello-wpstream/' . $blog_unit_card_type;
241 } else {
242 $unit_card_type = wpstream_video_item_card_selector(intval($card_type));
243 include WPSTREAM_PLUGIN_PATH . 'hello-wpstream/' . $unit_card_type;
244 }
245 }
246 }
247 // Capture and clear the buffered markup.
248 $html = ob_get_contents();
249 ob_end_clean();
250
251 // Return the number of posts on this page plus the rendered HTML.
252 return array(
253 'post_count' => $query->post_count,
254 'html' => $html,
255 );
256 }
257 }
258
259 if ( ! function_exists( 'wpstream_add_pagination' ) ) {
260 /**
261 * Generates pagination HTML based on the pagination type.
262 *
263 * @param WP_Query $query The WordPress query object.
264 * @param int $pagination The pagination type.
265 * @return string The generated pagination HTML.
266 */
267 function wpstream_add_pagination( $query, $pagination,$uid='' ) {
268 // Accumulator for the pagination markup.
269 $return_string = '';
270
271 // Type 1: a single "Load More" button.
272 if ( 1 === intval($pagination) ) {
273 $return_string = '<div class="wpstream_load_more_wrapper wpstream-pagination"><button type="button" class="btn btn-primary wpstream_load_more">' . esc_html__( 'Load More', 'hello-wpstream' ) . '</button></div>';
274 // Type 2: numbered pagination (the generating call is currently commented out, so output is empty).
275 } elseif ( 2 === intval($pagination) ) {
276 ob_start();
277 // wpstream_shortcode_pagination( $query->max_num_pages ,2,'',$uid);
278 $return_string = ob_get_contents();
279 ob_end_clean();
280 }
281
282 return $return_string;
283 }
284 }
285
286 if ( ! function_exists( 'wpstream_compose_ajax_holder_data' ) ) {
287 /**
288 * Composes the HTML data attributes for the AJAX holder shortcode.
289 *
290 * @param array $attributes The attributes for the AJAX holder shortcode.
291 * @return string The composed HTML data attributes.
292 */
293 function wpstream_compose_ajax_holder_data( $attributes ) {
294
295 // Default card design; overridden by the attribute when present.
296 $video_card=1;
297 if(isset($attributes['video_card'])){
298 $video_card = intval($attributes['video_card']);
299 }
300
301 // Hidden holder element that the front-end JS reads to drive AJAX paging.
302 $return_string = '<div class="wpstream_ajax_holder_shortcode" style="display:none" data-video-card="'.esc_attr($video_card).'" data-current-page="' . get_the_ID() . '" data-paged="1" ';
303 // Serialize every attribute into a data-* attribute (underscores become dashes).
304 foreach ( $attributes as $key => $value ) {
305
306 $data_key_name = str_replace( '_', '-', $key );
307 $return_string .= ' data-' . esc_attr( $data_key_name ) . '="';
308 // Arrays are JSON-encoded; scalars are sanitized as text.
309 if ( is_array( $value ) ) {
310 $return_string .= wp_json_encode( $value );
311 } else {
312 $return_string .= sanitize_text_field( $value );
313 }
314 $return_string .= '"';
315 }
316
317 // Close the holder element and return the markup.
318 $return_string .= '></div>';
319 return $return_string;
320 }
321 }
322
323
324 /*
325 * Wpstream shortcode input to tax
326 *
327 *
328 */
329
330 if ( ! function_exists( 'wpstream_item_list_shortcodes_input_to_tax' ) ) {
331 /**
332 * Item list shortcodes
333 */
334 function wpstream_item_list_shortcodes_input_to_tax() {
335 // Maps each shortcode/request input key to its underlying taxonomy slug.
336 return array(
337 'actors_ids' => 'wpstream_actors',
338 'movie_ratings_ids' => 'wpstream_movie_rating',
339 'wpstream_category_ids' => 'wpstream_category',
340 'category_ids' => 'category',
341 'post_tag_ids' => 'post_tag',
342 );
343 }
344 }
345 /*
346 * Wpstream filter bar - shortcode
347 *
348 *
349 */
350
351 if ( ! function_exists( 'wpstream_filter_bar_blog_posts' ) ) {
352 /**
353 * Generates the filter bar HTML content based on the provided attributes.
354 *
355 * @param array $attributes_data The attributes data for generating the filter bar.
356 * @return string The HTML content of the filter bar.
357 */
358 function wpstream_filter_bar_blog_posts( $attributes_data ) {
359 $return_string = '';
360 // Exposed to the included template under the expected variable name.
361 $attributes = $attributes_data;
362 // Buffer the blog-list filter template into a string.
363 ob_start();
364 include WPSTREAM_PLUGIN_PATH . 'hello-wpstream/template-parts/shortcodes/blog-list-filters.php';
365 $filters = ob_get_contents();
366 ob_end_clean();
367
368 $return_string .= $filters;
369 return $return_string;
370 }
371 }
372
373
374
375
376 /*
377 * Wpstream filter bar - shortcode
378 *
379 *
380 */
381
382 if ( ! function_exists( 'wpstream_filter_bar' ) ) {
383 /**
384 * Generates the filter bar HTML content based on the provided attributes.
385 *
386 * @param array $attributes_data The attributes data for generating the filter bar.
387 * @return string The HTML content of the filter bar.
388 */
389 function wpstream_filter_bar( $attributes_data ) {
390 $return_string = '';
391 // Exposed to the included template under the expected variable name.
392 $attributes = $attributes_data;
393 // Buffer the item/property-list filter template into a string.
394 ob_start();
395 include WPSTREAM_PLUGIN_PATH . 'hello-wpstream/template-parts/shortcodes/property-list-filters.php';
396 $filters = ob_get_contents();
397 ob_end_clean();
398
399 $return_string .= $filters;
400 return $return_string;
401 }
402 }
403
404 if ( ! function_exists( 'wpstream_taxonomy_terms_dropdown' ) ) {
405 /**
406 * Generates a dropdown select element for a taxonomy's terms.
407 *
408 * @param string $taxonomy The taxonomy to retrieve terms from.
409 * @param string $selected_term_slug Optional. The slug of the selected term. Default is ''.
410 * @param array $attributes Optional. Additional attributes for the select element. Default is an empty array.
411 * @return string The HTML markup for the dropdown select element.
412 */
413 function wpstream_taxonomy_terms_dropdown( $taxonomy, $selected_term_slug = '', $attributes = '' ) {
414 // Nothing to build for an unregistered taxonomy.
415 if ( ! taxonomy_exists( $taxonomy ) ) {
416 return '';
417 }
418
419 // Initialize $selected_term_slug based on $_GET if it's not provided.
420 // Map the taxonomy to its matching request parameter to pre-select a term.
421 switch ( $taxonomy ) {
422 case 'category':
423 // Blog-list dropdowns only filter by category; pre-select it from the request.
424 $selected_term_slug = isset( $_GET['category_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['category_ids'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
425 break;
426 case 'wpstream_actors':
427 $selected_term_slug = isset( $_GET['actors_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['actors_ids'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
428 break;
429 case 'wpstream_category':
430 $selected_term_slug = isset( $_GET['wpstream_category_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['wpstream_category_ids'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
431 break;
432 case 'wpstream_movie_rating':
433 $selected_term_slug = isset( $_GET['movie_ratings_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['movie_ratings_ids'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
434 break;
435 }
436
437 // Fetch every term (including empty ones) for the taxonomy.
438 $args = array(
439 'taxonomy' => $taxonomy,
440 'hide_empty' => false, // This will include terms with 0 posts.
441 );
442 $terms = get_terms( $args );
443
444 // Start the markup for our select element.
445 $output = '<select name="' . esc_attr( $taxonomy ) . '" class="wpstream_dropdown_select wpstream_dropdown_select_trigger_ajax" id="wpstream_dropdown_' . esc_attr( $taxonomy ) . '">';
446
447 // Add a default option (optional).
448 $output .= '<option value="">';
449 // Use a custom label when provided, otherwise a translated default.
450 if ( isset( $attributes[ 'label_' . $taxonomy ] ) ) {
451 $output .= $attributes[ 'label_' . $taxonomy ];
452 } else {
453 $output .= esc_html_e( 'Select term', 'hello-wpstream' );
454 }
455
456 $output .= '</option>';
457
458 // Check if we have any terms.
459 if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
460 // One <option> per term.
461 foreach ( $terms as $term ) {
462 // Check if this term is the selected term.
463 $selected = selected( $selected_term_slug, $term->term_id, false );
464
465 // Add an option for the term.
466 $output .= sprintf(
467 '<option value="%s"%s>%s</option>',
468 esc_attr( $term->term_id ),
469 $selected,
470 esc_html( $term->name )
471 );
472 }
473 }
474
475 // Close the select element.
476 $output .= '</select>';
477
478 // Return the generated dropdown.
479 return $output;
480 }
481 }
482
483
484 if ( ! function_exists( 'wpstream_taxonomy_terms_dropdown_bootstrap' ) ) {
485 /**
486 * Generates a dropdown select element for a taxonomy's terms.
487 *
488 * @param string $taxonomy The taxonomy to retrieve terms from.
489 * @param string $selected_term_slug Optional. The slug of the selected term. Default is ''.
490 * @param array $attributes Optional. Additional attributes for the select element. Default is an empty array.
491 * @return string The HTML markup for the dropdown select element.
492 */
493 function wpstream_taxonomy_terms_dropdown_bootstrap( $taxonomy, $selected_term_slug = '', $attributes = '' ) {
494 if ( ! taxonomy_exists( $taxonomy ) ) {
495 return '';
496 }
497
498 // Initialize $selected_term_slug based on $_GET if it's not provided.
499 switch ( $taxonomy ) {
500 case 'category':
501 // Blog-list dropdowns only filter by category; pre-select it from the request.
502 $selected_term_slug = isset( $_GET['category_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['category_ids'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
503 break;
504 case 'wpstream_actors':
505 $selected_term_slug = isset( $_GET['actors_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['actors_ids'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
506 break;
507 case 'wpstream_category':
508 $selected_term_slug = isset( $_GET['wpstream_category_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['wpstream_category_ids'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
509 break;
510 case 'wpstream_movie_rating':
511 $selected_term_slug = isset( $_GET['movie_ratings_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['movie_ratings_ids'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
512 break;
513 }
514
515 $args = array(
516 'taxonomy' => $taxonomy,
517 'hide_empty' => false, // This will include terms with 0 posts.
518 );
519 $terms = get_terms( $args );
520
521 // Build the option data + select attributes for the custom Bootstrap dropdown renderer.
522 $values = array();
523 $label = '';
524 $name = esc_attr( $taxonomy );
525 $class = 'wpstream_dropdown_select wpstream_dropdown_select_trigger_ajax wpstream_dropdown_select_'.$name;
526 $id = 'wpstream_dropdown_' . esc_attr( $taxonomy );
527
528
529 // Placeholder label: custom when supplied, otherwise a translated default.
530 if ( isset( $attributes[ 'label_' . $taxonomy ] ) ) {
531 $label .= $attributes[ 'label_' . $taxonomy ];
532 } else {
533 $label .= esc_html_e( 'Select term', 'hello-wpstream' );
534 }
535
536
537
538
539 // Check if we have any terms.
540 if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
541 // Collect term id => name pairs for the dropdown options.
542 foreach ( $terms as $term ) {
543 $values[$term->term_id]=$term->name;
544 }
545 }
546
547 // Delegate the actual markup to the shared custom-dropdown builder.
548 $output = wpstream_create_custom_dropdown( $values,$name, $class, $id, $label,$selected_term_slug);
549 // Return the generated dropdown.
550 return $output;
551 }
552 }
553
554
555
556 /*
557 * Filter BLog Post list
558 *
559 */
560
561 if ( ! function_exists( 'wpstream_taxonomy_terms_dropdown_blog_post_list' ) ) {
562 /**
563 * Generates a dropdown select element for a taxonomy's terms.
564 *
565 * @param string $taxonomy The taxonomy to retrieve terms from.
566 * @param string $selected_term_slug Optional. The slug of the selected term. Default is ''.
567 * @param array $attributes Optional. Additional attributes for the select element. Default is an empty array.
568 * @return string The HTML markup for the dropdown select element.
569 */
570 function wpstream_taxonomy_terms_dropdown_blog_post_list( $taxonomy, $selected_term_slug = '', $attributes = '' ) {
571 if ( ! taxonomy_exists( $taxonomy ) ) {
572 return '';
573 }
574
575 // Blog-list dropdowns only filter by category; pre-select it from the request.
576 $selected_term_slug = isset( $_GET['category_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['category_ids'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
577
578 $args = array(
579 'taxonomy' => $taxonomy,
580 'hide_empty' => false, // This will include terms with 0 posts.
581 );
582 $terms = get_terms( $args );
583
584 // Start the markup for our select element.
585 // Blog-list variant: uses the blog-specific AJAX trigger class.
586 $output = '<select name="' . esc_attr( $taxonomy ) . '" class="wpstream_dropdown_select wpstream_dropdown_select_trigger_ajax_blog_list" id="wpstream_dropdown_' . esc_attr( $taxonomy ) . '">';
587
588 // Add a default option (optional).
589 $output .= '<option value="">';
590 // Custom label when supplied, otherwise a translated default.
591 if ( isset( $attributes[ 'label_' . $taxonomy ] ) ) {
592 $output .= $attributes[ 'label_' . $taxonomy ];
593 } else {
594 $output .= esc_html_e( 'Select term', 'hello-wpstream' );
595 }
596
597 $output .= '</option>';
598
599 // Check if we have any terms.
600 if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
601 // One <option> per term.
602 foreach ( $terms as $term ) {
603 // Check if this term is the selected term.
604 $selected = selected( $selected_term_slug, $term->term_id, false );
605
606 // Add an option for the term.
607 $output .= sprintf(
608 '<option value="%s"%s>%s</option>',
609 esc_attr( $term->term_id ),
610 $selected,
611 esc_html( $term->name )
612 );
613 }
614 }
615
616 // Close the select element.
617 $output .= '</select>';
618
619 // Return the generated dropdown.
620 return $output;
621 }
622 }
623 /*
624 * Filter BLog Post list with Bootstrea
625 *
626 */
627
628 if ( ! function_exists( 'wpstream_taxonomy_terms_dropdown_blog_post_list_with_bootstrap' ) ) {
629 /**
630 * Generates a dropdown select element for a taxonomy's terms.
631 *
632 * @param string $taxonomy The taxonomy to retrieve terms from.
633 * @param string $selected_term_slug Optional. The slug of the selected term. Default is ''.
634 * @param array $attributes Optional. Additional attributes for the select element. Default is an empty array.
635 * @return string The HTML markup for the dropdown select element.
636 */
637 function wpstream_taxonomy_terms_dropdown_blog_post_list_with_bootstrap( $taxonomy, $selected_term_slug = '', $attributes = '' ) {
638 if ( ! taxonomy_exists( $taxonomy ) ) {
639 return '';
640 }
641
642 // Blog-list dropdowns only filter by category; pre-select it from the request.
643 $selected_term_slug = isset( $_GET['category_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['category_ids'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
644
645 $args = array(
646 'taxonomy' => $taxonomy,
647 'hide_empty' => false, // This will include terms with 0 posts.
648 );
649 $terms = get_terms( $args );
650 // Build the option data + select attributes for the custom Bootstrap blog-list dropdown.
651 $values = array();
652 $label = '';
653 $name = esc_attr( $taxonomy );
654 $class = 'wpstream_dropdown_select wpstream_dropdown_select_trigger_ajax_blog_list wpstream_blog_dropdown_' . esc_attr( $taxonomy );
655 $id = 'wpstream_dropdown_' . esc_attr( $taxonomy );
656
657 // Start the markup for our select element.
658 //$output = '<select name="' . esc_attr( $taxonomy ) . '" class="wpstream_dropdown_select wpstream_dropdown_select_trigger_ajax_blog_list" id="wpstream_dropdown_' . esc_attr( $taxonomy ) . '">';
659
660 // Add a default option (optional).
661
662 if ( isset( $attributes[ 'label_' . $taxonomy ] ) ) {
663 $label .= $attributes[ 'label_' . $taxonomy ];
664 } else {
665 $label .= esc_html_e( 'Select term', 'hello-wpstream' );
666 }
667
668 // Check if we have any terms.
669 if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
670 // Collect term id => name pairs for the dropdown options.
671 foreach ( $terms as $term ) {
672 $values[$term->term_id]=$term->name;
673 }
674 }
675 // Delegate the actual markup to the shared custom-dropdown builder.
676 $output = wpstream_create_custom_dropdown( $values,$name, $class, $id, $label,$selected_term_slug);
677 // Return the generated dropdown.
678 return $output;
679 }
680 }
681