PluginProbe
Post Grid Gutenberg Blocks – PostX / 5.1.1
Post Grid Gutenberg Blocks – PostX v5.1.1
5.1.1 5.1.0 5.0.41 5.0.39 5.0.38 5.0.37 5.0.36 5.0.35 5.0.34 5.0.33 5.0.32 5.0.31 5.0.30 5.0.29 5.0.28 5.0.27 5.0.26 5.0.25 5.0.23 5.0.24 5.0.22 5.0.21 5.0.20 5.0.19 5.0.18 All 240 releases
ultimate-post / classes / Functions.php

Functions.php in Post Grid Gutenberg Blocks – PostX 5.1.1, at classes/Functions.php

3,135 lines 110.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Common Functions.
4 *
5 * @package ULTP\Functions
6 * @since v.1.0.0
7 */
8
9 namespace ULTP;
10
11 use ULTP\Includes\Durbin\Xpo;
12
13 defined( 'ABSPATH' ) || exit;
14
15 /**
16 * Functions class.
17 *
18 * Provides utility functions for Ultimate Post plugin.
19 *
20 * @package ULTP\Functions
21 * @since 4.0.0
22 */
23 class Functions {
24
25 /**
26 * Funtion
27 *
28 * @since v.3.2.4
29 *
30 * Instance of the class.
31 *
32 * @var Functions | null
33 */
34 private static $instance = null;
35
36 /**
37 * Setup class.
38 *
39 * @since v.1.0.0
40 */
41 public function __construct() {
42 }
43
44 /**
45 * Gets the instance of \ULTP\Functions class
46 *
47 * @return Functions
48 * @since v.3.2.4
49 */
50 public static function get_instance() {
51 if ( ! isset( $GLOBALS['ultp_settings'] ) ) {
52 $GLOBALS['ultp_settings'] = get_option( 'ultp_options' );
53 }
54
55 if ( is_null( self::$instance ) ) {
56 self::$instance = new self();
57 }
58
59 return self::$instance;
60 }
61
62 /**
63 * ID for the Builder Post or Normal Post
64 *
65 * @since v.2.3.1
66 * @return NUMBER | is Builder or not
67 */
68 public function get_ID() {
69 $id = $this->is_builder();
70 return $id ? $id : ( function_exists( 'is_shop' ) ? ( is_shop() ? wc_get_page_id( 'shop' ) : get_the_ID() ) : get_the_ID() );
71 }
72
73 /**
74 * Checking Statement of Dynamic Site Builder
75 *
76 * @since v.2.3.1
77 * @return BOOLEAN | is Builder or not
78 */
79 public function is_archive_builder() {
80 $id = get_the_ID();
81 return get_post_type( $id ) == 'ultp_builder' ? get_post_meta( $id, '__ultp_builder_type', true ) : false;
82 }
83
84 /**
85 * Set Link with the Parameters
86 *
87 * @since v.1.1.0
88 * @param string $url .
89 * @param string $tag .
90 * @return STRING | URL with Arg
91 */
92 public function get_premium_link( $url = null, $tag = '' ) {
93 return Xpo::generate_utm_link(
94 array(
95 'url' => $url,
96 'utmKey' => $tag,
97 )
98 );
99 }
100
101
102 /**
103 * Quick Query
104 *
105 * @since v.1.1.0
106 * @param ARRAY $prams Quick query parameters.
107 * @param ARRAY $args Query arguments to modify.
108 * @return ARRAY
109 */
110 public function get_quick_query( $prams, $args ) {
111 switch ( $prams['queryQuick'] ) {
112 case 'related_posts':
113 global $post;
114 $p_id = isset( $post->ID ) && $post->ID ? $post->ID : ( isset( $_POST['postId'] ) ? sanitize_text_field( wp_unslash( $_POST['postId'] ) ) : '' ); //phpcs:disable WordPress.Security.NonceVerification.Missing
115 if ( $p_id ) {
116 $args['post__not_in'] = array( $p_id ); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
117 }
118 break;
119 case 'related_tag':
120 global $post;
121 $p_id = isset( $post->ID ) && $post->ID ? $post->ID : ( isset( $prams['current_post'] ) && $prams['current_post'] ? $prams['current_post'] : ( isset( $_POST['postId'] ) ? sanitize_text_field( wp_unslash( $_POST['postId'] ) ) : '' ) ); //phpcs:disable ordPress.Security.NonceVerification.Missing
122 if ( $p_id ) {
123 $args['tax_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
124 array(
125 'taxonomy' => 'post_tag',
126 'terms' => $this->get_terms_id( $p_id, 'post_tag' ),
127 'field' => 'term_id',
128 ),
129 );
130 $args['post__not_in'] = array( $p_id ); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
131 }
132 break;
133 case 'related_category':
134 global $post;
135 $p_id = isset( $post->ID ) && $post->ID ? $post->ID : ( isset( $prams['current_post'] ) && $prams['current_post'] ? $prams['current_post'] : ( isset( $_POST['postId'] ) ? sanitize_text_field( wp_unslash( $_POST['postId'] ) ) : '' ) ); //phpcs:disable ordPress.Security.NonceVerification.Missing
136 if ( $p_id ) {
137 $args['tax_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
138 array(
139 'taxonomy' => 'category',
140 'terms' => $this->get_terms_id( $p_id, 'category' ),
141 'field' => 'term_id',
142 ),
143 );
144 $args['post__not_in'] = array( $p_id ); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
145 }
146 break;
147 case 'related_cat_tag':
148 global $post;
149 $p_id = isset( $post->ID ) && $post->ID ? $post->ID : ( isset( $prams['current_post'] ) && $prams['current_post'] ? $prams['current_post'] : ( isset( $_POST['postId'] ) ? sanitize_text_field( wp_unslash( $_POST['postId'] ) ) : '' ) ); //phpcs:disable ordPress.Security.NonceVerification.Missing
150 if ( $p_id ) {
151 $args['tax_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
152 array(
153 'taxonomy' => 'post_tag',
154 'terms' => $this->get_terms_id( $p_id, 'post_tag' ),
155 'field' => 'term_id',
156 ),
157 array(
158 'taxonomy' => 'category',
159 'terms' => $this->get_terms_id( $p_id, 'category' ),
160 'field' => 'term_id',
161 ),
162 );
163 $args['post__not_in'] = array( $p_id ); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
164 }
165 break;
166 case 'sticky_posts':
167 $sticky = get_option( 'sticky_posts' );
168 if ( is_array( $sticky ) ) {
169 rsort( $sticky );
170 // $sticky = array_slice($sticky, 0, $args['posts_per_page']);
171 }
172 $args['ignore_sticky_posts'] = 1;
173 $args['post__in'] = $sticky;
174 break;
175 case 'latest_post_published':
176 $args['orderby'] = 'date';
177 $args['order'] = 'DESC';
178 $args['ignore_sticky_posts'] = 1;
179 break;
180 case 'latest_post_modified':
181 $args['orderby'] = 'modified';
182 $args['order'] = 'DESC';
183 $args['ignore_sticky_posts'] = 1;
184 break;
185 case 'oldest_post_published':
186 $args['orderby'] = 'date';
187 $args['order'] = 'ASC';
188 break;
189 case 'oldest_post_modified':
190 $args['orderby'] = 'modified';
191 $args['order'] = 'ASC';
192 break;
193 case 'alphabet_asc':
194 $args['orderby'] = 'title';
195 $args['order'] = 'ASC';
196 break;
197 case 'alphabet_desc':
198 $args['orderby'] = 'title';
199 $args['order'] = 'DESC';
200 break;
201 case 'random_post':
202 $args['orderby'] = 'rand';
203 $args['order'] = 'ASC';
204 break;
205 case 'random_post_7_days':
206 $args['orderby'] = 'rand';
207 $args['order'] = 'ASC';
208 $args['date_query'] = array( array( 'after' => '1 week ago' ) );
209 break;
210 case 'random_post_30_days':
211 $args['orderby'] = 'rand';
212 $args['order'] = 'ASC';
213 $args['date_query'] = array( array( 'after' => '1 month ago' ) );
214 break;
215 case 'most_comment':
216 $args['orderby'] = 'comment_count';
217 $args['order'] = 'DESC';
218 break;
219 case 'most_comment_1_day':
220 $args['orderby'] = 'comment_count';
221 $args['order'] = 'DESC';
222 $args['date_query'] = array( array( 'after' => '1 day ago' ) );
223 break;
224 case 'most_comment_7_days':
225 $args['orderby'] = 'comment_count';
226 $args['order'] = 'DESC';
227 $args['date_query'] = array( array( 'after' => '1 week ago' ) );
228 break;
229 case 'most_comment_30_days':
230 $args['orderby'] = 'comment_count';
231 $args['order'] = 'DESC';
232 $args['date_query'] = array( array( 'after' => '1 month ago' ) );
233 break;
234 case 'popular_post_1_day_view':
235 $args['meta_key'] = '__post_views_count'; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Needed by the block query; the user picks these filters.
236 $args['orderby'] = 'meta_value_num';
237 $args['order'] = 'DESC';
238 $args['date_query'] = array( array( 'after' => '1 day ago' ) );
239 break;
240 case 'popular_post_7_days_view':
241 $args['meta_key'] = '__post_views_count'; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Needed by the block query; the user picks these filters.
242 $args['orderby'] = 'meta_value_num';
243 $args['order'] = 'DESC';
244 $args['date_query'] = array( array( 'after' => '1 week ago' ) );
245 break;
246 case 'popular_post_30_days_view':
247 $args['meta_key'] = '__post_views_count'; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Needed by the block query; the user picks these filters.
248 $args['orderby'] = 'meta_value_num';
249 $args['order'] = 'DESC';
250 $args['date_query'] = array( array( 'after' => '1 month ago' ) );
251 break;
252 case 'popular_post_all_times_view':
253 $args['meta_key'] = '__post_views_count'; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Needed by the block query; the user picks these filters.
254 $args['orderby'] = 'meta_value_num';
255 $args['order'] = 'DESC';
256 break;
257 default:
258 // code...
259 break;
260 }
261 return $args;
262 }
263
264 /**
265 * Get All Term IDs for a Post in a Taxonomy
266 *
267 * @since v.2.4.12
268 * @param INT|STRING $id Post ID to get terms for.
269 * @param STRING $type Taxonomy name (e.g. 'category', 'post_tag').
270 * @return ARRAY
271 */
272 public function get_terms_id( $id, $type ) {
273 $data = array();
274 $arr = get_the_terms( $id, $type );
275 if ( is_array( $arr ) ) {
276 foreach ( $arr as $key => $val ) {
277 $data[] = $val->term_id;
278 }
279 }
280 return $data;
281 }
282
283 /**
284 * Get all reusable block IDs referenced in a post's content
285 *
286 * @since v.1.1.0
287 * @param INT|STRING $post_id .
288 * @return ARRAY
289 */
290 public function get_reusable_ids( $post_id ) {
291 $reusable_id = array();
292 if ( $post_id ) {
293 $post = get_post( $post_id );
294 if ( isset( $post->post_content ) ) {
295 if (
296 has_blocks( $post->post_content ) &&
297 strpos( $post->post_content, 'wp:block' ) &&
298 strpos( $post->post_content, '"ref"' ) !== false
299 ) {
300 $blocks = parse_blocks( $post->post_content );
301 foreach ( $blocks as $key => $value ) {
302 if ( isset( $value['attrs']['ref'] ) ) {
303 $reusable_id[] = $value['attrs']['ref'];
304 }
305 }
306 }
307 }
308 }
309 return $reusable_id;
310 }
311
312 /**
313 * Safely reads file contents using WordPress Filesystem API
314 *
315 * @since v.4.1.8
316 * @param STRING $path .
317 * @return STRING|ARRAY.
318 */
319 public function get_path_file_contents( $path ) {
320 global $wp_filesystem;
321 if ( ! $wp_filesystem ) {
322 require_once ABSPATH . 'wp-admin/includes/file.php';
323 $init_fs = WP_Filesystem();
324 if ( ! $init_fs ) {
325 return '';
326 }
327 }
328
329 if ( $wp_filesystem->exists( $path ) ) {
330 return $wp_filesystem->get_contents( $path );
331 } else {
332 return '';
333 }
334 }
335
336 /**
337 * Builds and returns inline CSS for a post and its reusable blocks
338 *
339 * @since v.4.1.8
340 * @param INT|STRING $post_id .
341 * @param BOOLEAN $call_common .
342 * @return STRING|ARRAY.
343 */
344 public function build_css_for_inline_print( $post_id, $call_common = true ) {
345 // Callers pass a template ID from builder settings or shortcode attributes; it goes into
346 // a file path and the id attribute below, so only a positive integer is accepted.
347 $post_id = absint( $post_id );
348 if ( $post_id ) {
349 $upload_dir_url = wp_get_upload_dir();
350 $upload_css_dir_url = trailingslashit( $upload_dir_url['basedir'] );
351
352 $css_dir_url = trailingslashit( $upload_dir_url['baseurl'] );
353 if ( is_ssl() ) {
354 $css_dir_url = str_replace( 'http://', 'https://', $css_dir_url );
355 }
356 $reusable_css = '';
357 $reusable_id = $this->get_reusable_ids( $post_id );
358 if ( ! empty( $reusable_id ) ) {
359 foreach ( $reusable_id as $id ) {
360 $reusable_dir_path = $upload_css_dir_url . "ultimate-post/ultp-css-{$id}.css";
361 if ( file_exists( $reusable_dir_path ) ) {
362 $reusable_css .= $this->get_path_file_contents( $reusable_dir_path );
363 } else {
364 $reusable_css .= get_post_meta( $reusable_id, '_ultp_css', true );
365 }
366 }
367 }
368
369 $css_dir_path = $upload_css_dir_url . "ultimate-post/ultp-css-{$post_id}.css";
370 $css = '';
371 if ( file_exists( $css_dir_path ) ) {
372 $css = $this->get_path_file_contents( $css_dir_path );
373 } else {
374 $css = get_post_meta( $post_id, '_ultp_css', true );
375 }
376 if ( $reusable_css . $css ) {
377 if ( $call_common ) {
378 $this->register_scripts_common();
379 }
380 return '<style id="ultp-post-' . $post_id . '" type="text/css">' . wp_strip_all_tags( $reusable_css . $css ) . '</style>';
381 }
382 }
383 return '';
384 }
385
386
387 /**
388 * Get Global Plugin Settings
389 *
390 * @since v.1.0.0
391 * @param STRING $key of the Option .
392 * @return ARRAY|STRING .
393 */
394 public function get_setting( $key = '' ) {
395 $data = $GLOBALS['ultp_settings'];
396 if ( $key != '' ) {
397 return isset( $data[ $key ] ) ? $data[ $key ] : '';
398 } else {
399 return $data;
400 }
401 }
402
403
404 /**
405 * Settings that are safe to send to the browser.
406 *
407 * Same as get_setting() without secrets: the OpenAI key is replaced by
408 * `chatgpt_has_key`. Use this for anything localized to a script. get_setting()
409 * itself is unchanged, because callers write its result back to the option.
410 *
411 * @return array
412 */
413 public function get_client_settings() {
414 $data = $this->get_setting();
415 if ( ! is_array( $data ) ) {
416 return array();
417 }
418 $data['chatgpt_has_key'] = ! empty( $data['chatgpt_secret_key'] );
419 unset( $data['chatgpt_secret_key'] );
420 return $data;
421 }
422
423
424 /**
425 * Set Option Settings
426 *
427 * @since v.1.0.0
428 * @param STRING | $key of the Option (STRING) .
429 * @param STRING | $val Value (STRING) .
430 */
431 public function set_setting( $key = '', $val = '' ) {
432 if ( $key != '' ) {
433 $data = $GLOBALS['ultp_settings'];
434 $data[ $key ] = $val;
435 update_option( 'ultp_options', $data );
436 $GLOBALS['ultp_settings'] = $data;
437 do_action( 'ultp_settings_updated', $key, $val );
438 }
439 }
440
441
442 /**
443 * Get Image HTML
444 *
445 * @since v.1.0.0
446 * @param STRING | $url .
447 * @param STRING | $size .
448 * @param STRING | $class .
449 * @param STRING | $alt .
450 * @param STRING | $lazy .
451 * @param ARRAY | $darkImg .
452 * @param STRING | $srcset .
453 * @return STRING
454 */
455 public function get_image_html( $url = '', $size = 'full', $class = '', $alt = '', $lazy = '', $darkImg = array(), $srcset = '' ) {
456 $class = sanitize_html_class( $class );
457 $alt = preg_replace( '/[^A-Za-z0-9_ -]/', '', $alt );
458 $hasDarkImage = ( $darkImg['enable'] && $darkImg['url'] ) ? ' ultp-light-image-block ' : '';
459 $alt = $alt ? ' alt="' . $alt . '" ' : '';
460 $lazy_data = $lazy ? ' loading="lazy"' : '';
461
462 $dlMode = isset( $_COOKIE['ultplocalDLMode'] ) ? sanitize_key( wp_unslash( $_COOKIE['ultplocalDLMode'] ) ) : ultimate_post()->get_dl_mode();
463
464 $lightMode = $hasDarkImage ? ( $dlMode == 'ultplight' ? '' : 'inactive ' ) : '';
465 $darkMode = $hasDarkImage ? ( $hasDarkImage && $dlMode == 'ultpdark' ? '' : ' inactive ' ) : '';
466
467 $image = '<img ' . $lazy_data . $srcset . ' class="' . $class . $hasDarkImage . $lightMode . '" ' . $alt . ' src="' . esc_url( $url ) . '" />';
468 if ( $hasDarkImage ) {
469 $image .= '<img ' . $lazy_data . $darkImg['srcset'] . ' class="' . $class . $darkMode . ' ultp-dark-image-block " ' . $alt . ' src="' . esc_url( $darkImg['url'] ) . '" />';
470 }
471 return $image;
472 }
473
474
475 /**
476 * Get Image HTML
477 *
478 * @since v.1.0.0
479 * @param STRING | $attach_id .
480 * @param STRING | $size .
481 * @param STRING | $class .
482 * @param STRING | $alt .
483 * @param STRING | $srcset .
484 * @param STRING | $lazy .
485 * @return STRING
486 */
487 public function get_image( $attach_id, $size = 'full', $class = '', $alt = '', $srcset = '', $lazy = '' ) {
488 $img_alt = get_post_meta( $attach_id, '_wp_attachment_image_alt', true );
489 $alt = $img_alt ? $img_alt : $alt;
490 $alt = $alt ? ' alt="' . esc_html( $alt ) . '" ' : '';
491 $class = $class ? ' class="' . $class . '" ' : '';
492 $size = ( ultimate_post()->get_setting( 'disable_image_size' ) == 'yes' && strpos( $size, 'ultp_layout_' ) !== false ) ? 'full' : $size;
493 $lazy_data = $lazy ? ' loading="lazy"' : '';
494 $srcset_data = $srcset ? ' srcset="' . esc_attr( wp_get_attachment_image_srcset( $attach_id ) ) . '"' : '';
495 return '<img ' . $srcset_data . $lazy_data . $class . $alt . ' src="' . wp_get_attachment_image_url( $attach_id, $size ) . '" />';
496 }
497
498
499 /**
500 * Get Excerpt Text
501 *
502 * @since v.1.0.0
503 * @param STRING | $post_id .
504 * @param NUMBER | $limit .
505 * @return STRING
506 */
507 public function excerpt( $post_id, $limit = 55 ) {
508 $content = preg_replace( '/(\[postx_template[\s\w="]*)]/m', '', get_the_excerpt( $post_id ) ); // Remove postx_template shortcode form Content
509 return apply_filters( 'the_excerpt', wp_trim_words( $content, $limit ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Core hook.
510 }
511
512 /**
513 * Builder Attributes
514 *
515 * @since v.1.0.0
516 * @param STRING | $type .
517 * @return STRING
518 */
519 public function get_builder_attr( $type ) {
520 $builder_data = '';
521 if ( $type == 'archiveBuilder' || $type == 'archiveBuilderFilter' ) {
522 if ( is_archive() ) {
523 if ( is_date() ) {
524 if ( is_year() ) {
525 $builder_data = 'date###' . get_the_date( 'Y' );
526 } elseif ( is_month() ) {
527 $builder_data = 'date###' . get_the_date( 'Y-n' );
528 } elseif ( is_day() ) {
529 $builder_data = 'date###' . get_the_date( 'Y-n-j' );
530 }
531 } elseif ( is_author() ) {
532 $builder_data = 'author###' . get_the_author_meta( 'ID' );
533 } else {
534 $obj = get_queried_object();
535 if ( isset( $obj->taxonomy ) ) {
536 $builder_data = 'taxonomy###' . $obj->taxonomy . '###' . $obj->slug;
537 }
538 }
539 } elseif ( is_search() ) {
540 $builder_data = 'search###' . get_search_query( true );
541 }
542 }
543 if ( $type == 'archiveBuilderFilter' ) {
544 return $builder_data ? $builder_data : '';
545 }
546 return $builder_data ? 'data-builder="' . $builder_data . '"' : '';
547 }
548
549
550 /**
551 * Determines if the builder is enabled based on the plugin settings.
552 *
553 * @param STRING $builder Optional. The builder name (currently unused).
554 * @return BOOL True if the builder is enabled, false otherwise.
555 */
556 public function is_builder( $builder = '' ) {
557 $id = '';
558 if ( ultimate_post()->get_setting( 'ultp_builder' ) != 'false' ) {
559 $page_id = ultimate_post()->builder_check_conditions( 'return_ib' );
560 if ( $page_id ) {
561 $id = $page_id;
562 }
563 }
564 return $id;
565 }
566
567
568 /**
569 * Get Post Number Depending On Device
570 *
571 * @since v.2.5.4
572 * @param MIXED | $preDef .
573 * @param MIXED | $prev .
574 * @param MIXED | $current .
575 * @return STRING
576 */
577 public function get_post_number( $preDef, $prev, $current ) {
578
579 $current = is_object( $current ) ? json_decode( wp_json_encode( $current ), true ) : $current;
580 if ( array(
581 'lg' => $preDef,
582 'sm' => $preDef,
583 'xs' => $preDef,
584 ) == $current ) {
585 if ( $preDef != $prev ) {
586 return $prev;
587 }
588 }
589
590 $lg = isset( $current['lg'] ) ? $current['lg'] : $prev;
591 $sm = isset( $current['sm'] ) ? $current['sm'] : $lg;
592 $xs = isset( $current['xs'] ) ? $current['xs'] : $lg;
593 if ( $lg == $sm && $sm == $xs ) {
594 return $lg;
595 } else {
596 global $ultpDevide;
597 $currentDevice = ! empty( $ultpDevide ) ? $ultpDevide : $this->isDevice();
598 if ( $currentDevice == 'mobile' ) {
599 return $xs;
600 } elseif ( $currentDevice == 'tablet' ) {
601 return $sm;
602 } else {
603 return $lg;
604 }
605 }
606 }
607
608
609 /**
610 * Get Post Number Depending On Device
611 *
612 * @since v.2.5.4
613 * @return STRING | Device Type
614 */
615 public function isDevice() {
616 $useragent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_key( $_SERVER['HTTP_USER_AGENT'] ) : '';
617 $device = 'desktop';
618 if ( $useragent ) {
619 if ( preg_match( '/(tablet|ipad|playbook)|(android(?!.*(mobi|opera mini)))/i', strtolower( $useragent ) ) ) {
620 $device = 'tablet';
621 } elseif ( preg_match( '/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i', $useragent ) || preg_match( '/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i', substr( $useragent, 0, 4 ) ) ) {
622 $device = 'mobile';
623 }
624 }
625 global $ultpDevide;
626 $ultpDevide = $device;
627 return $device;
628 }
629
630
631 /**
632 * Get Raw Value from Objects
633 *
634 * @since v.2.5.3
635 * @param ARRAY | $attr .
636 * @return STRING | Device Type
637 */
638 public function get_value( $attr ) {
639 $data = array();
640 if ( is_array( $attr ) ) {
641 foreach ( $attr as $val ) {
642 $data[] = $val->value;
643 }
644 }
645 return $data;
646 }
647
648 /**
649 * QueryArgs for Filter
650 *
651 * @since v.2.8.9
652 * @param ARRAY | $attr .
653 * @return ARRAY
654 */
655 public function getFilterQueryArgs( $attr ) {
656 $tax_value = ( strlen( $attr['queryTaxValue'] ) > 2 ) ? $attr['queryTaxValue'] : array();
657 $tax_value = is_array( $tax_value ) ? $tax_value : json_decode( $tax_value );
658
659 $tax_value = ( isset( $tax_value[0] ) && is_object( $tax_value[0] ) ) ? $this->get_value( $tax_value ) : $tax_value;
660
661 if ( is_array( $tax_value ) && count( $tax_value ) > 0 ) {
662 $relation = isset( $attr['queryRelation'] ) ? $attr['queryRelation'] : 'OR';
663
664 // Adv Filter Query Relation Override
665 if ( isset( $attr['advFilterEnable'] ) && $attr['advFilterEnable'] === true && isset( $attr['advRelation'] ) ) {
666 $relation = 'AND' === $attr['advRelation'] || 'OR' === $attr['advRelation'] ? $attr['advRelation'] : $relation;
667 }
668
669 $var = array( 'relation' => $relation );
670 foreach ( $tax_value as $val ) {
671 $tax_name = $attr['queryTax'];
672 // For Custom Terms
673 if ( $attr['queryTax'] == 'multiTaxonomy' ) {
674 $temp = explode( '###', $val );
675 if ( isset( $temp[1] ) ) {
676
677 if ( $temp[1] === '_all' ) {
678 continue;
679 }
680
681 $val = $temp[1];
682 $tax_name = $temp[0];
683 }
684 }
685 $var[] = array(
686 'taxonomy' => $tax_name,
687 'field' => 'slug',
688 'terms' => $val,
689 );
690 }
691 }
692 return isset( $var ) ? $var : array();
693 }
694
695 /**
696 * Query Builder
697 *
698 * @since v.1.0.0
699 * @param ARRAY | $attr .
700 * @return ARRAY
701 */
702 public function get_query( $attr ) {
703 $builder = isset( $attr['builder'] ) ? $attr['builder'] : '';
704 $post_type = isset( $attr['queryType'] ) ? $attr['queryType'] : 'post';
705 $get_post_type = isset( $attr['queryPostType'] ) ? $attr['queryPostType'] : '';
706 if ( $post_type != 'archiveBuilder' && ! empty( $get_post_type ) && $post_type == 'customPostType' ) {
707 $post_type = $get_post_type;
708 }
709
710 if ( $post_type == 'archiveBuilder' && ( $builder || $this->is_builder( $builder ) ) ) {
711 $archive_query = array();
712 if ( $builder ) {
713 $str = explode( '###', $builder );
714 if ( isset( $str[0] ) ) {
715 if ( $str[0] == 'taxonomy' ) {
716 if ( isset( $str[1] ) && isset( $str[2] ) ) {
717 $archive_query['tax_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
718 array(
719 'taxonomy' => $str[1],
720 'field' => 'slug',
721 'terms' => $str[2],
722 ),
723 );
724 }
725 } elseif ( $str[0] == 'author' ) {
726 if ( isset( $str[1] ) ) {
727 $archive_query['author'] = $str[1];
728 }
729 } elseif ( $str[0] == 'search' ) {
730 if ( isset( $str[1] ) ) {
731 $archive_query['s'] = $str[1];
732 }
733 } elseif ( $str[0] == 'date' ) {
734 if ( isset( $str[1] ) ) {
735 $all_date = explode( '-', $str[1] );
736 if ( ! empty( $all_date ) ) {
737 $arg = array();
738 if ( isset( $all_date[0] ) ) {
739 $arg['year'] = $all_date[0];
740 }
741 if ( isset( $all_date[1] ) ) {
742 $arg['month'] = $all_date[1];
743 }
744 if ( isset( $all_date[2] ) ) {
745 $arg['day'] = $all_date[2];
746 }
747 $archive_query['date_query'][] = $arg;
748 }
749 }
750 }
751 }
752 } else {
753 global $wp_query;
754 $archive_query = $wp_query->query_vars;
755 }
756 $archive_query['posts_per_page'] = isset( $attr['queryNumber'] ) ? $attr['queryNumber'] : 1;
757 $archive_query['paged'] = isset( $attr['paged'] ) ? $attr['paged'] : 1;
758
759 $archive_query['paged'] = ! wp_doing_ajax() && isset( $_GET[ $attr['blockId'] . '_page' ] ) && is_numeric( $_GET[ $attr['blockId'] . '_page' ] ) ? // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page number for block pagination.
760 intval( $_GET[ $attr['blockId'] . '_page' ] ) : // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page number for block pagination.
761 $archive_query['paged'];
762
763 if ( isset( $attr['queryOffset'] ) && $attr['queryOffset'] ) {
764 $offset = $this->get_offset( $attr['queryOffset'], $archive_query );
765 $archive_query = array_merge( $archive_query, $offset );
766 }
767
768 // Include Remove from Version 2.5.4
769 if ( isset( $attr['queryInclude'] ) && $attr['queryInclude'] ) {
770 $_include = explode( ',', $attr['queryInclude'] );
771 if ( is_array( $_include ) && count( $_include ) ) {
772 $archive_query['post__in'] = isset( $archive_query['post__in'] ) ? array_merge( $archive_query['post__in'], $_include ) : $_include;
773 $archive_query['ignore_sticky_posts'] = 1;
774 $archive_query['orderby'] = 'post__in';
775 }
776 }
777
778 if ( isset( $attr['queryExclude'] ) && $attr['queryExclude'] ) {
779 $_exclude = ( substr( $attr['queryExclude'], 0, 1 ) === '[' ) ? $this->get_value( json_decode( $attr['queryExclude'] ) ) : explode( ',', $attr['queryExclude'] );
780 if ( is_array( $_exclude ) && count( $_exclude ) ) {
781 $archive_query['post__not_in'] = isset( $archive_query['post__not_in'] ) ? array_merge( $archive_query['post__not_in'], $_exclude ) : $_exclude; // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
782 }
783 }
784
785 if ( isset( $attr['querySticky'] ) && $attr['querySticky'] ) {
786 if ( filter_var( $attr['querySticky'], FILTER_VALIDATE_BOOLEAN ) ) {
787 $sticky = get_option( 'sticky_posts', array() );
788 $archive_query['post__not_in'] = isset( $archive_query['post__not_in'] ) ? array_merge( $archive_query['post__not_in'], $sticky ) : $sticky; // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
789 }
790 }
791 // ===============
792 if ( isset( $attr['queryUnique'] ) && $attr['queryUnique'] ) {
793 global $ultp_unique_ID;
794 if ( isset( $ultp_unique_ID[ $attr['queryUnique'] ] ) ) {
795 $archive_query['post__not_in'] = isset( $archive_query['post__not_in'] ) ? array_merge( $archive_query['post__not_in'], $ultp_unique_ID[ $attr['queryUnique'] ] ) : $ultp_unique_ID[ $attr['queryUnique'] ]; // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
796 }
797 }
798 // ===============
799
800 $archive_query['post_status'] = 'publish';
801 if ( is_user_logged_in() ) {
802 if ( current_user_can( 'editor' ) || current_user_can( 'administrator' ) ) {
803 $archive_query['post_status'] = array( 'publish', 'private' );
804 }
805 }
806 // queryOrder
807 if ( ! isset( $archive_query['orderby'] ) ) {
808 $archive_query['orderby'] = isset( $attr['queryOrderBy'] ) ? $attr['queryOrderBy'] : 'date';
809 }
810 if ( ! isset( $archive_query['queryOrder'] ) ) {
811 $archive_query['order'] = isset( $attr['queryOrder'] ) ? $attr['queryOrder'] : 'ASC';
812 }
813
814 // Quick Query Support for Builder
815 if ( isset( $attr['queryQuick'] ) ) {
816 if ( $attr['queryQuick'] != '' ) {
817 $archive_query = ultimate_post()->get_quick_query( $attr, $archive_query );
818 }
819 }
820
821 if ( ! isset( $attr['ajaxCall'] ) ) {
822 if ( isset( $attr['filterShow'] ) && $attr['filterShow'] && $attr['filterShow'] != 'false' ) {
823 if ( isset( $attr['filterType'] ) && isset( $attr['filterValue'] ) ) {
824 $filterValue = strlen( $attr['filterValue'] ) > 2 ? $attr['filterValue'] : array();
825 $filterValue = is_array( $filterValue ) ? $filterValue : json_decode( $filterValue );
826 if ( count( $filterValue ) > 0 && $attr['filterType'] ) {
827 $final = array( 'relation' => 'OR' );
828 foreach ( $filterValue as $key => $val ) {
829 $final[] = array(
830 'taxonomy' => $attr['filterType'],
831 'field' => 'slug',
832 'terms' => $val,
833 );
834 }
835 $archive_query['tax_query'] = $final; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
836 }
837 }
838 }
839 }
840 // from v.3.0.7 - for search builder
841 if ( is_search() ) {
842 $archive_query['orderby'] = 'relevance';
843 if ( isset( $_GET['ultp_exclude'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only public search filter (search block exclude).
844 $ultp_exclude = json_decode( sanitize_text_field( wp_unslash( $_GET['ultp_exclude'] ) ), true ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only public search filter.
845 if ( is_array( $ultp_exclude ) ) {
846 $all_types = get_post_types( array( 'public' => true ), 'names' );
847 $post_type = array_diff( $all_types, $ultp_exclude );
848 $archive_query['post_type'] = $post_type;
849 }
850 }
851 }
852
853 return apply_filters( 'ultp_archive_query', $archive_query );
854 }
855
856 // When you use load more pagination block for a grid that did not have load more feature,
857 // the incoming posts would not align properly with the blocks design and looked bad.
858 // This fixes that.
859 if (
860 isset( $attr['paginationType'] ) &&
861 isset( $attr['queryNumber2'] ) &&
862 isset( $attr['notFirstLoad'] ) &&
863 $attr['paginationType'] === 'loadMore' &&
864 $attr['notFirstLoad']
865 ) {
866 $query_number = $attr['queryNumber2'];
867 // $query_number = isset($attr['queryNumber']) ? $attr['queryNumber'] : 3;
868 } else {
869 $query_number = isset( $attr['queryNumber'] ) ? $attr['queryNumber'] : 3;
870 }
871
872 $paged = isset( $attr['paged'] ) ? $attr['paged'] : 1;
873 $paged = ! wp_doing_ajax() &&
874 isset( $attr['blockId'] ) &&
875 isset( $_GET[ $attr['blockId'] . '_page' ] ) && // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page number for block pagination.
876 is_numeric( $_GET[ $attr['blockId'] . '_page' ] ) ? // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page number for block pagination.
877 intval( $_GET[ $attr['blockId'] . '_page' ] ) : // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page number for block pagination.
878 $paged;
879
880 $query_args = array(
881 'posts_per_page' => $query_number,
882 'post_type' => is_array( $post_type ) && ! empty( $post_type ) ? $post_type : ( 'archiveBuilder' == $post_type ? 'post' : ( is_string( $post_type ) ? is_array( json_decode( $post_type ) ) ? json_decode( $post_type ) : $post_type : $post_type ) ),
883 'orderby' => isset( $attr['queryOrderBy'] ) ? $attr['queryOrderBy'] : 'date',
884 'order' => isset( $attr['queryOrder'] ) ? $attr['queryOrder'] : 'desc',
885 'paged' => $paged,
886 'post_status' => 'publish',
887 );
888
889 // For Private Post 'private'.
890 if ( is_user_logged_in() ) {
891 if ( current_user_can( 'editor' ) || current_user_can( 'administrator' ) ) {
892 $query_args['post_status'] = array( 'publish', 'private' );
893 }
894 }
895
896 if ( $attr['queryType'] == 'posts' ) {
897 if ( isset( $attr['queryPosts'] ) && $attr['queryPosts'] ) {
898 unset( $query_args['post_type'] );
899 $data = json_decode( isset( $attr['queryPosts'] ) ? $attr['queryPosts'] : '[]' );
900 $final = $this->get_value( $data );
901 if ( count( $final ) > 0 ) {
902 $query_args['post__in'] = $final;
903 // $query_args['posts_per_page'] = -1;
904 }
905 $query_args['ignore_sticky_posts'] = 1;
906 return $query_args;
907 }
908 } elseif ( $attr['queryType'] == 'customPosts' ) {
909 if ( isset( $attr['queryCustomPosts'] ) && $attr['queryCustomPosts'] ) {
910 $query_args['post_type'] = $this->get_post_type();
911 $data = json_decode( isset( $attr['queryCustomPosts'] ) ? $attr['queryCustomPosts'] : '[]' );
912 $final = $this->get_value( $data );
913 if ( count( $final ) > 0 ) {
914 $query_args['post__in'] = $final;
915 // $query_args['posts_per_page'] = -1;
916 }
917 $query_args['ignore_sticky_posts'] = 1;
918 return $query_args;
919 }
920 }
921
922 if ( isset( $attr['queryExcludeAuthor'] ) && $attr['queryExcludeAuthor'] ) {
923 $data = json_decode( isset( $attr['queryExcludeAuthor'] ) ? $attr['queryExcludeAuthor'] : '[]' );
924 $final = $this->get_value( $data );
925 if ( count( $final ) > 0 ) {
926 $query_args['author__not_in'] = $final;
927 }
928 }
929
930 if ( isset( $attr['queryOrderBy'] ) && isset( $attr['metaKey'] ) ) {
931 if ( $attr['queryOrderBy'] == 'meta_value_num' ) {
932 $query_args['meta_key'] = $attr['metaKey']; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Needed by the block query; the user picks these filters.
933 }
934 }
935
936 // Include Remove from Version 2.5.4.
937 if ( isset( $attr['queryInclude'] ) && $attr['queryInclude'] ) {
938 $_include = explode( ',', $attr['queryInclude'] );
939 if ( is_array( $_include ) && count( $_include ) ) {
940 $query_args['post__in'] = isset( $query_args['post__in'] ) ? array_merge( $query_args['post__in'], $_include ) : $_include;
941 $query_args['ignore_sticky_posts'] = 1;
942 $query_args['orderby'] = 'post__in';
943 }
944 }
945
946 if ( isset( $attr['queryTax'] ) ) {
947 if ( isset( $attr['queryTaxValue'] ) ) {
948 $var = $this->getFilterQueryArgs( $attr );
949 if ( isset( $var ) && count( $var ) > 1 ) {
950 $query_args['tax_query'] = $var; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
951 }
952 }
953 }
954
955 if ( isset( $attr['queryExcludeTerm'] ) && $attr['queryExcludeTerm'] ) {
956 $temp = json_decode( $attr['queryExcludeTerm'] );
957 $_term = array();
958 foreach ( $temp as $val ) {
959 $temp = explode( '###', $val->value );
960 if ( isset( $temp[1] ) ) {
961 if ( is_array( $_term ) && array_key_exists( $temp[0], $_term ) ) {
962 $_term[ $temp[0] ][] = $temp[1];
963 } else {
964 $_term[ $temp[0] ] = array( $temp[1] );
965 }
966 }
967 }
968 if ( count( $_term ) > 0 ) {
969 $final = array( 'relation' => 'AND' );
970 foreach ( $_term as $key => $val ) {
971 $final[] = array(
972 'taxonomy' => $key,
973 'field' => 'slug',
974 'terms' => $val,
975 'operator' => 'NOT IN',
976 );
977 }
978
979 if ( is_array( $query_args ) && array_key_exists( 'tax_query', $query_args ) ) {
980 $query_args['tax_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
981 'relation' => 'AND',
982 $query_args['tax_query'],
983 );
984 $query_args['tax_query'][] = $final;
985 } else {
986 $query_args['tax_query'] = $final; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
987 }
988 }
989 }
990
991 if ( isset( $attr['queryExclude'] ) && $attr['queryExclude'] ) {
992 $_exclude = ( substr( $attr['queryExclude'], 0, 1 ) === '[' ) ? $this->get_value( json_decode( $attr['queryExclude'] ) ) : explode( ',', $attr['queryExclude'] );
993 if ( is_array( $_exclude ) && count( $_exclude ) ) {
994 $query_args['post__not_in'] = isset( $query_args['post__not_in'] ) ? array_merge( $query_args['post__not_in'], $_exclude ) : $_exclude; // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
995 }
996 }
997
998 if ( isset( $attr['queryUnique'] ) && $attr['queryUnique'] ) {
999 global $ultp_unique_ID;
1000 if ( isset( $ultp_unique_ID[ $attr['queryUnique'] ] ) ) {
1001 $query_args['post__not_in'] = isset( $query_args['post__not_in'] ) ? array_merge( $query_args['post__not_in'], $ultp_unique_ID[ $attr['queryUnique'] ] ) : $ultp_unique_ID[ $attr['queryUnique'] ]; // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
1002 }
1003 }
1004 // exclude current post from Post blocks // v.2.9.6.
1005 if ( is_single() && get_the_ID() ) {
1006 $query_args['post__not_in'] = isset( $query_args['post__not_in'] ) ? array_merge( $query_args['post__not_in'], array( get_the_ID() ) ) : array( get_the_ID() ); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
1007 }
1008
1009 if ( isset( $attr['queryQuick'] ) ) {
1010 if ( $attr['queryQuick'] != '' && $post_type != 'archiveBuilder' ) {
1011 $query_args = ultimate_post()->get_quick_query( $attr, $query_args );
1012 }
1013 }
1014
1015 if ( isset( $attr['queryOffset'] ) && $attr['queryOffset'] ) {
1016 $offset = $this->get_offset( $attr['queryOffset'], $query_args );
1017 $query_args = array_merge( $query_args, $offset );
1018 }
1019
1020 if ( isset( $attr['queryAuthor'] ) && $attr['queryAuthor'] ) {
1021 $_include = ( substr( $attr['queryAuthor'], 0, 1 ) === '[' ) ? $this->get_value( json_decode( $attr['queryAuthor'] ) ) : explode( ',', $attr['queryAuthor'] );
1022 if ( is_array( $_include ) && count( $_include ) ) {
1023 $query_args['author__in'] = $_include;
1024 }
1025 }
1026
1027 if ( isset( $attr['querySearch'] ) && $attr['querySearch'] ) {
1028 $query_args['s'] = $attr['querySearch'];
1029 }
1030
1031 if ( isset( $attr['querySticky'] ) && $attr['querySticky'] ) {
1032 if ( filter_var( $attr['querySticky'], FILTER_VALIDATE_BOOLEAN ) ) {
1033 $sticky = get_option( 'sticky_posts', array() );
1034 $query_args['post__not_in'] = isset( $query_args['post__not_in'] ) ? array_merge( $query_args['post__not_in'], $sticky ) : $sticky; // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
1035 }
1036 }
1037
1038 if ( ! isset( $attr['ajaxCall'] ) ) {
1039 if ( isset( $attr['filterShow'] ) && $attr['filterShow'] && $attr['filterShow'] != 'false' ) {
1040 if ( isset( $attr['checkFilter'] ) && isset( $attr['queryTax'] ) && isset( $attr['queryTaxValue'] ) ) {
1041 $var = $this->getFilterQueryArgs( $attr );
1042 if ( isset( $var ) && count( $var ) > 1 ) {
1043 $query_args['tax_query'] = $var; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
1044 }
1045 } elseif ( isset( $attr['filterType'] ) && isset( $attr['filterValue'] ) ) {
1046 $filterValue = strlen( $attr['filterValue'] ) > 2 ? $attr['filterValue'] : array();
1047 $filterValue = is_array( $filterValue ) ? $filterValue : json_decode( $filterValue );
1048 if ( is_array( $filterValue ) && count( $filterValue ) > 0 && $attr['filterType'] ) {
1049 $final = array( 'relation' => 'OR' );
1050 foreach ( $filterValue as $key => $val ) {
1051 $final[] = array(
1052 'taxonomy' => $attr['filterType'],
1053 'field' => 'slug',
1054 'terms' => $val,
1055 // 'operator' => '=',
1056 );
1057 }
1058 $query_args['tax_query'] = $final; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
1059 }
1060 }
1061 }
1062 }
1063
1064 // Advanced Filter Select Dropdown Default value.
1065 // only on initial page load.
1066 if (
1067 ! wp_doing_ajax() &&
1068 isset( $attr['advFilterEnable'] ) &&
1069 $attr['advFilterEnable'] === true &&
1070 isset( $attr['defQueryTax'] ) &&
1071 count( $attr['defQueryTax'] ) > 0
1072 ) {
1073 $tax_query = array(
1074 'relation' =>
1075 isset( $attr['advRelation'] ) &&
1076 ( 'AND' === $attr['advRelation'] || 'OR' === $attr['advRelation'] )
1077 ? $attr['advRelation'] : 'AND',
1078 );
1079 $is_valid = false;
1080
1081 foreach ( $attr['defQueryTax'] as $_ => $defQueryTaxValue ) {
1082 $term = explode( '###', $defQueryTaxValue );
1083
1084 // Validation
1085 if (
1086 ! in_array( $term[0], array( 'category', 'tags', 'author', 'custom_tax' ), true ) ||
1087 '_all' === $term[1] ||
1088 empty( $term[1] )
1089 ) {
1090 continue;
1091 }
1092
1093 if ( 'author' === $term[0] ) {
1094
1095 if ( ! is_numeric( $term[1] ) ) {
1096 continue;
1097 }
1098
1099 $query_args['author__in'] = $term[1];
1100 } elseif ( 'custom_tax' === $term[0] && isset( $attr['queryType'] ) ) {
1101 $post_type = sanitize_key( $attr['queryType'] );
1102 $slug = sanitize_key( $term[1] );
1103
1104 // These are not custom post type.
1105 if ( in_array( $post_type, array( 'posts', 'customPosts' ), true ) ) {
1106 continue;
1107 }
1108
1109 $taxonomy = $this->get_taxonomy_by_term_slug( $post_type, $slug );
1110
1111 if ( ! empty( $taxonomy ) ) {
1112 $q = array(
1113 'field' => 'slug',
1114 'taxonomy' => $taxonomy,
1115 'terms' => $slug,
1116 );
1117
1118 $tax_query[] = $q;
1119 $is_valid = true;
1120 }
1121 } else {
1122 if ( ! is_numeric( $term[1] ) ) {
1123 continue;
1124 }
1125
1126 $q = array(
1127 'field' => 'term_id',
1128 'taxonomy' => 'tags' === $term[0] ? 'post_tag' : 'category',
1129 'terms' => $term[1],
1130 );
1131
1132 $tax_query[] = $q;
1133 $is_valid = true;
1134 }
1135 }
1136
1137 if ( $is_valid ) {
1138 $query_args['tax_query'] = $tax_query; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Needed by the block query; the user picks these filters.
1139 }
1140 }
1141 // $query_args['test'] = is_array( $post_type ) && ! empty( $post_type ) ? $post_type : ( 'archiveBuilder' === $post_type ? 'post' : ( is_string( $post_type ) ? json_decode( $post_type ) : $post_type ) );
1142 $query_args['wpnonce'] = wp_create_nonce( 'ultp-public-nonce' );
1143
1144 return apply_filters( 'ultp_frontend_query', $query_args );
1145 }
1146
1147 /**
1148 * Get Page Offset
1149 *
1150 * @since v.1.0.0
1151 * @param NUMBER | $queryOffset Offset .
1152 * @param ARRAY | $query_args Query .
1153 * @return ARRAY
1154 */
1155 function get_offset( $queryOffset, $query_args ) {
1156 $query = array();
1157 if ( $query_args['paged'] > 1 ) {
1158 $offset_post = wp_get_recent_posts( $query_args, OBJECT );
1159 if ( count( $offset_post ) > 0 ) {
1160 $offset = array();
1161 for ( $x = count( $offset_post ); $x > count( $offset_post ) - $queryOffset; $x-- ) {
1162 $offset[] = $offset_post[ $x - 1 ]->ID;
1163 }
1164 $query['post__not_in'] = $offset; // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Needed by the block query; the user picks these filters.
1165 }
1166 } else {
1167 $query['offset'] = isset( $queryOffset ) ? $queryOffset : 0;
1168 }
1169 return $query;
1170 }
1171
1172
1173 /**
1174 * Get Page Number
1175 *
1176 * @since v.1.0.0
1177 * @param array $attr Attribute of the Query.
1178 * @param int $post_number Post Number.
1179 * @return ARRAY
1180 */
1181 public function get_page_number( $attr, $post_number ) {
1182 if ( $post_number > 0 ) {
1183 if ( isset( $attr['queryOffset'] ) && $attr['queryOffset'] ) {
1184 $post_number = $post_number - (int) $attr['queryOffset'];
1185 }
1186 $post_per_page = isset( $attr['queryNumber'] ) ? ( $attr['queryNumber'] ? $attr['queryNumber'] : 1 ) : 3;
1187 $pages = ceil( $post_number / $post_per_page );
1188 return $pages ? $pages : 1;
1189 } else {
1190 return 1;
1191 }
1192 }
1193
1194
1195 /**
1196 * Get Image Size
1197 *
1198 * @since v.1.0.0
1199 * @return ARRAY
1200 */
1201 public function get_image_size() {
1202 $sizes = get_intermediate_image_sizes();
1203 $filter = array( 'full' => 'Full' );
1204 foreach ( $sizes as $value ) {
1205 $title = ucwords( str_replace( array( '_', '-', 'ultp' ), array( ' ', ' ', 'PostX' ), $value ) );
1206 switch ( $value ) {
1207 case 'thumbnail':
1208 $title = $title . ' [150x150]';
1209 break;
1210 case 'medium':
1211 $title = $title . ' [300x300]';
1212 break;
1213 case 'large':
1214 $title = $title . ' [1024x1024]';
1215 break;
1216 case 'ultp_layout_landscape_large':
1217 $title = $title . ' [1200x800]';
1218 break;
1219 case 'ultp_layout_landscape':
1220 $title = $title . ' [870x570]';
1221 break;
1222 case 'ultp_layout_portrait':
1223 $title = $title . ' [600x900]';
1224 break;
1225 case 'ultp_layout_square':
1226 $title = $title . ' [600x600]';
1227 break;
1228 default:
1229 break;
1230 }
1231 $filter[ $value ] = $title;
1232 }
1233 return $filter;
1234 }
1235
1236
1237 /**
1238 * Get All PostType Registered
1239 *
1240 * @since v.1.0.0
1241 * @return ARRAY
1242 */
1243 public function get_post_type() {
1244 $filter = apply_filters( 'ultp_public_post_type', true );
1245 $post_type = get_post_types( ( $filter ? array( 'public' => true ) : '' ), 'names' );
1246 return array_diff( $post_type, array( 'attachment' ) );
1247 }
1248
1249 /**
1250 * Get Pagination Url
1251 *
1252 * @since v.2.8.9
1253 *
1254 * @param NUMBER $pageNo The page number for pagination.
1255 * @param STRING $baseUrl The base URL to append the pagination parameter to.
1256 *
1257 * @return STRING The generated pagination URL.
1258 */
1259 public function generatePaginationUrl( $pageNo, $baseUrl ) {
1260 if ( $baseUrl ) {
1261 $url = $baseUrl . ( $pageNo == 1 ? '' : 'page/' . $pageNo );
1262 } else {
1263 $url = get_pagenum_link( $pageNo );
1264 }
1265 return $url;
1266 }
1267 /**
1268 * Get Pagination HTML
1269 *
1270 * @since v.1.0.0
1271 * @param INT $pages Number of pages.
1272 * @param STRING $paginationNav Pagination navigation type.
1273 * @param STRING $paginationText Pagination text.
1274 * @param BOOL $paginationAjax Whether to use AJAX pagination.
1275 * @param STRING $baseUrl Base URL for pagination links.
1276 * @param STRING $blockId Block ID for pagination.
1277 * @return STRING
1278 */
1279 public function pagination( $pages = '', $paginationNav = '', $paginationText = '', $paginationAjax = true, $baseUrl = '', $blockId = '' ) {
1280 $html = '';
1281 $showitems = 3;
1282 $paged = is_front_page() ? get_query_var( 'page' ) : get_query_var( 'paged' );
1283 $paged = $paged ? $paged : 1;
1284
1285 $paged = ! wp_doing_ajax() &&
1286 isset( $_GET[ $blockId . '_page' ] ) && // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page number for block pagination.
1287 is_numeric( $_GET[ $blockId . '_page' ] ) ? // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page number for block pagination.
1288 intval( $_GET[ $blockId . '_page' ] ) : $paged; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only page number for block pagination.
1289
1290 if ( $pages == '' ) {
1291 global $wp_query;
1292 $pages = $wp_query->max_num_pages;
1293 if ( ! $pages ) {
1294 $pages = 1;
1295 }
1296 }
1297
1298 $data = ( $paged >= 3 ? array( ( $paged - 1 ), $paged, $paged + 1 ) : array( 1, 2, 3 ) );
1299
1300 $paginationText = explode( '|', $paginationText );
1301
1302 $prev_text = isset( $paginationText[0] ) ? esc_html( $paginationText[0] ) : __( 'Previous', 'ultimate-post' );
1303 $next_text = isset( $paginationText[1] ) ? esc_html( $paginationText[1] ) : __( 'Next', 'ultimate-post' );
1304
1305 if ( 1 != $pages ) {
1306 $html .= '<ul class="ultp-pagination">';
1307 $display_none = 'style="display:none"';
1308 if ( $paged > 1 || $paginationAjax && $pages > 1 ) {
1309 $html .= '<li class="ultp-prev-page-numbers" ' . ( $paged == 1 ? $display_none : '' ) . '><a href="' . $this->generatePaginationUrl( $paged - 1, $baseUrl ) . '">' . ultimate_post()->get_svg_icon( 'leftAngle2' ) . ' ' . ( $paginationNav == 'textArrow' ? $prev_text : '' ) . '</a></li>';
1310 }
1311 if ( $pages > 3 ) {
1312 $html .= '<li class="ultp-first-pages" ' . ( $paged < 2 ? $display_none : '' ) . ' data-current="1"><a href="' . $this->generatePaginationUrl( 1, $baseUrl ) . '">1</a></li>';
1313 }
1314 if ( $paged > 3 || $paginationAjax && $pages > 4 ) {
1315 $html .= '<li class="ultp-first-dot"' . ( $paged == 1 ? $display_none : '' ) . '><a href="#">...</a></li>';
1316 }
1317 foreach ( $data as $i ) {
1318 if ( $pages > 3 && $pages == $i ) {
1319 continue;
1320 }
1321 if ( $pages >= $i ) {
1322 $html .= ( $paged == $i ) ? '<li class="ultp-center-item pagination-active" data-current="' . $i . '"><a href="' . $this->generatePaginationUrl( $i, $baseUrl ) . '">' . $i . '</a></li>' : '<li class="ultp-center-item" data-current="' . $i . '" ' . ( ( $pages > 4 && $paged == 2 && $i == 1 && ! $paginationAjax ) ? $display_none : '' ) . '><a href="' . $this->generatePaginationUrl( $i, $baseUrl ) . '">' . $i . '</a></li>';
1323 }
1324 }
1325 if ( $pages != ( $paged + 2 ) || $paginationAjax && $pages > 4 ) {
1326 $html .= '<li class="ultp-last-dot" ' . ( $pages <= $paged + 1 ? $display_none : '' ) . '><a href="#">...</a></li>';
1327 }
1328 if ( $pages > 3 ) {
1329 $html .= '<li class="ultp-last-pages' . ( $paged == $pages ? ' pagination-active' : '' ) . '" data-current="' . $pages . '"><a href="' . $this->generatePaginationUrl( $pages, $baseUrl ) . '">' . $pages . '</a></li>';
1330 }
1331 if ( $paged != $pages ) {
1332 $html .= '<li class="ultp-next-page-numbers"><a href="' . $this->generatePaginationUrl( $paged + 1, $baseUrl ) . '">' . ( $paginationNav == 'textArrow' ? $next_text : '' ) . ultimate_post()->get_svg_icon( 'rightAngle2' ) . '</a></li>';
1333 }
1334 $html .= '</ul>';
1335 }
1336 return $html;
1337 }
1338
1339 /**
1340 * Svg Icon Source
1341 *
1342 * @since v.1.0.0
1343 * @param STRING $ultp_icons Name of the SVG icon file (without extension).
1344 * @return STRING
1345 */
1346 public function get_svg_icon( $ultp_icons = '' ) {
1347 $svg = '';
1348 if ( $ultp_icons ) {
1349 $icon = $this->svg_icon_compatibility( $ultp_icons );
1350 $svg = $this->get_path_file_contents( ULTP_PATH . 'assets/img/iconpack/' . $icon . '.svg' );
1351 }
1352 return $svg;
1353 }
1354
1355 /**
1356 * Get Taxonomy Lists
1357 *
1358 * @since v.1.0.0
1359 * @param STRING|ARRAY $prams Taxonomy slug or arguments array.
1360 * @return ARRAY
1361 */
1362 public function taxonomy( $prams = 'category' ) {
1363 $data = array();
1364
1365 $terms = get_terms(
1366 is_string( $prams ) ? array(
1367 'taxonomy' => $prams,
1368 'hide_empty' => false,
1369 ) : $prams
1370 );
1371 if ( ! is_wp_error( $terms ) ) {
1372 foreach ( $terms as $val ) {
1373 $data[ urldecode_deep( $val->slug ) ] = $val->name;
1374 }
1375 }
1376 return $data;
1377 }
1378
1379
1380 /**
1381 * Get Taxonomy Lists
1382 *
1383 * @since v.2.9.0
1384 * @param STRING $tax_slug Taxonomy slug.
1385 * @param INT $number Number of terms to retrieve.
1386 * @return ARRAY
1387 */
1388 public function builder_preview( $tax_slug, $number ) {
1389 $data = array();
1390 $term_data = get_terms(
1391 array(
1392 'taxonomy' => $tax_slug,
1393 'hide_empty' => true,
1394 'number' => $number,
1395 'parent' => 0,
1396 )
1397 );
1398 if ( ! empty( $term_data ) ) {
1399 foreach ( $term_data as $terms ) {
1400 $data[] = $this->get_tax_data( $terms );
1401 }
1402 }
1403 return $data;
1404 }
1405
1406 /**
1407 * Get Taxonomy Data Lists
1408 *
1409 * @since v.1.0.0
1410 * @param object $terms Taxonomy Object.
1411 * @return ARRAY
1412 */
1413 public function get_tax_data( $terms ) {
1414 $temp = array();
1415 $thumbnail_id = $this->get_term_image_id( $terms );
1416 $image_src = array();
1417 if ( $thumbnail_id ) {
1418 $image_sizes = ultimate_post()->get_image_size();
1419 foreach ( $image_sizes as $key => $value ) {
1420 $img_src = wp_get_attachment_image_src( $thumbnail_id, $key, false );
1421 if ( $img_src ) {
1422 $image_src[ $key ] = $img_src[0];
1423 }
1424 }
1425 }
1426 $temp['url'] = get_term_link( $terms );
1427 $temp['thumbnail_id'] = $thumbnail_id ? (string) $thumbnail_id : '';
1428 $temp['name'] = $terms->name;
1429 $temp['desc'] = $terms->description;
1430 $temp['count'] = $terms->count;
1431 $temp['image'] = $image_src;
1432 $color = $this->get_term_color( $terms );
1433 $temp['color'] = $color ? $color : '#037fff';
1434 return $temp;
1435 }
1436
1437 /**
1438 * Image attachment ID of a term, set by PostX Pro's Taxonomy Image & Color add-on.
1439 *
1440 * PostX Pro answers `ultp_term_image_id` only while the add-on is on.
1441 *
1442 * @param WP_Term $term Term.
1443 * @return INT Attachment ID, or 0.
1444 */
1445 public function get_term_image_id( $term ) {
1446 // PostX Pro before 1.9.0 does not hook the filter below.
1447 if ( Xpo::is_pro_before_1_9_0() ) {
1448 return absint( $this->get_term_meta_from_old_pro( $term, 'image' ) );
1449 }
1450 return absint( apply_filters( 'ultp_term_image_id', 0, $term ) );
1451 }
1452
1453 /**
1454 * Colour of a term, set by PostX Pro's Taxonomy Image & Color add-on.
1455 *
1456 * PostX Pro answers `ultp_term_color` only while the add-on is on.
1457 *
1458 * @param WP_Term $term Term.
1459 * @return STRING Colour, or ''.
1460 */
1461 public function get_term_color( $term ) {
1462 // PostX Pro before 1.9.0 does not hook the filter below.
1463 if ( Xpo::is_pro_before_1_9_0() ) {
1464 return (string) $this->get_term_meta_from_old_pro( $term, 'color' );
1465 }
1466 $color = apply_filters( 'ultp_term_color', '', $term );
1467 return is_string( $color ) ? $color : '';
1468 }
1469
1470 /**
1471 * Get a term's image or colour as PostX Pro before 1.9.0 expects
1472 *
1473 * Newer versions provide them through the `ultp_term_image_id` and `ultp_term_color` filters.
1474 *
1475 * @param WP_Term $term Term.
1476 * @param STRING $type 'image' or 'color'.
1477 * @return STRING
1478 */
1479 private function get_term_meta_from_old_pro( $term, $type ) {
1480 if ( ! $term instanceof \WP_Term ) {
1481 return '';
1482 }
1483 $value = get_term_meta( $term->term_id, 'image' === $type ? 'ultp_category_image' : 'ultp_category_color', true );
1484 return is_scalar( $value ) ? (string) $value : '';
1485 }
1486
1487 public function get_category_data( $catSlug, $number = 40, $type = '', $tax_slug = 'category', $archiveBuilder = '' ) {
1488 $data = array();
1489 if ( $type == 'child' ) {
1490 if ( $archiveBuilder ) {
1491 $data = $this->builder_preview( $tax_slug, $number );
1492 } else {
1493 if ( is_category() ) {
1494 $catSlug = array( get_queried_object()->slug );
1495 }
1496 $image = '';
1497 if ( ! empty( $catSlug ) ) {
1498 foreach ( $catSlug as $cat ) {
1499 $parent_term = get_term_by( 'slug', $cat, $tax_slug );
1500 if ( ! empty( $parent_term ) ) {
1501 $term_data = get_terms(
1502 array(
1503 'taxonomy' => $tax_slug,
1504 'hide_empty' => true,
1505 'number' => $number,
1506 'parent' => $parent_term->term_id,
1507 )
1508 );
1509 if ( ! empty( $term_data ) ) {
1510 foreach ( $term_data as $terms ) {
1511 $data[] = $this->get_tax_data( $terms );
1512 }
1513 }
1514 }
1515 }
1516 }
1517 }
1518 } elseif ( $type == 'parent' ) {
1519 $term_data = is_category() ? array( get_term( get_queried_object()->parent, 'category' ) ) : get_terms(
1520 array(
1521 'taxonomy' => $tax_slug,
1522 'hide_empty' => true,
1523 'number' => $number,
1524 'parent' => 0,
1525 )
1526 );
1527 if ( $archiveBuilder && ! empty( $term_data ) ) {
1528 $term_data = array( $term_data[0] );
1529 }
1530 if ( ! empty( $term_data ) ) {
1531 foreach ( $term_data as $terms ) {
1532 if ( ! empty( $terms->term_id ) ) {
1533 $data[] = $this->get_tax_data( $terms );
1534 }
1535 }
1536 }
1537 } elseif ( $type == 'custom' ) {
1538 foreach ( $catSlug as $cat ) {
1539 $terms = get_term_by( 'slug', $cat, $tax_slug );
1540 if ( ! empty( $terms ) ) {
1541 $data[] = $this->get_tax_data( $terms );
1542 }
1543 }
1544 } elseif ( $type == 'immediate_child' ) {
1545 if ( $archiveBuilder ) {
1546 $data = $this->builder_preview( $tax_slug, $number );
1547 } else {
1548 $id_ = get_queried_object();
1549 if ( isset( $id_->term_id ) ) {
1550 $term_data = get_terms(
1551 array(
1552 'taxonomy' => $tax_slug,
1553 'hide_empty' => true,
1554 'number' => 100,
1555 'parent' => $id_->term_id,
1556 )
1557 );
1558 if ( ! empty( $term_data ) ) {
1559 foreach ( $term_data as $terms ) {
1560 $data[] = $this->get_tax_data( $terms );
1561 }
1562 }
1563 }
1564 }
1565 } elseif ( $type == 'allchild' ) {
1566 if ( $archiveBuilder ) {
1567 $data = $this->builder_preview( $tax_slug, $number );
1568 } else {
1569 $id_ = get_queried_object();
1570 if ( isset( $id_->term_taxonomy_id ) ) {
1571 $termchildren = get_term_children( $id_->term_taxonomy_id, $tax_slug );
1572 foreach ( $termchildren as $key => $value ) {
1573 $terms = get_term_by( 'id', $value, $tax_slug );
1574 $data[] = $this->get_tax_data( $terms );
1575 }
1576 }
1577 }
1578 } elseif ( $type == 'current_level' ) {
1579 if ( $archiveBuilder ) {
1580 $data = $this->builder_preview( $tax_slug, $number );
1581 } else {
1582 $id_ = get_queried_object();
1583 if ( isset( $id_->parent ) ) {
1584 $term_data = get_terms(
1585 array(
1586 'taxonomy' => $tax_slug,
1587 'hide_empty' => true,
1588 'number' => $number,
1589 'parent' => $id_->parent,
1590 )
1591 );
1592 if ( ! empty( $term_data ) ) {
1593 foreach ( $term_data as $terms ) {
1594 if ( $terms->term_id != $id_->term_id ) {
1595 $data[] = $this->get_tax_data( $terms );
1596 }
1597 }
1598 }
1599 }
1600 }
1601 } else {
1602 $term_data = get_terms(
1603 array(
1604 'taxonomy' => $tax_slug,
1605 'hide_empty' => true,
1606 'number' => $number,
1607 )
1608 );
1609 if ( ! empty( $term_data ) ) {
1610 foreach ( $term_data as $terms ) {
1611 $data[] = $this->get_tax_data( $terms );
1612 }
1613 }
1614 }
1615 return $data;
1616 }
1617
1618
1619 /**
1620 * Get Next Previous HTML.
1621 *
1622 * @since v.1.0.0
1623 * @return STRING
1624 */
1625 public function next_prev() {
1626 $html = '';
1627 $html .= '<ul>';
1628 $html .= '<li>';
1629 $html .= '<a class="ultp-prev-action ultp-disable" href="#">';
1630 $html .= ultimate_post()->get_svg_icon( 'leftAngle2' ) . '<span class="screen-reader-text">' . esc_html__( 'Previous', 'ultimate-post' ) . '</span>';
1631 $html .= '</a>';
1632 $html .= '</li>';
1633 $html .= '<li>';
1634 $html .= '<a class="ultp-next-action">';
1635 $html .= ultimate_post()->get_svg_icon( 'rightAngle2' ) . '<span class="screen-reader-text">' . esc_html__( 'Next', 'ultimate-post' ) . '</span>';
1636 $html .= '</a>';
1637 $html .= '</li>';
1638 $html .= '</ul>';
1639 return $html;
1640 }
1641
1642
1643 /**
1644 * Get Loading HTML
1645 *
1646 * @since v.1.0.0
1647 * @return STRING
1648 */
1649 public function postx_loading() {
1650 $html = '';
1651 $style = ultimate_post()->get_setting( 'preloader_style' );
1652 if ( $style == 'style2' ) {
1653 $html .= '<div class="ultp-loading-spinner" style="width:100%;height:100%"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>'; // ultp-block-items-wrap
1654 } else {
1655 $html .= '<div class="ultp-loading-blocks" style="width:100%;height:100%;"><div style="left: 0;top: 0;animation-delay:0s;"></div><div style="left: 21px;top: 0;animation-delay:0.125s;"></div><div style="left: 42px;top: 0;animation-delay:0.25s;"></div><div style="left: 0;top: 21px;animation-delay:0.875s;"></div><div style="left: 42px;top: 21px;animation-delay:0.375s;"></div><div style="left: 0;top: 42px;animation-delay:0.75s;"></div><div style="left: 42px;top: 42px;animation-delay:0.625s;"></div><div style="left: 21px;top: 42px;animation-delay:0.5s;"></div></div>';
1656 }
1657 return '<div class="ultp-loading">' . $html . '</div>';
1658 }
1659
1660
1661 /**
1662 * Get Filter HTML
1663 *
1664 * @since v.1.0.0
1665 * @param STRING $filterText Filter Text.
1666 * @param STRING $filterType Filter Type.
1667 * @param ARRAY|STRING $filterValue Filter Value.
1668 * @param STRING $filterMobileText Filter Mobile Text.
1669 * @param BOOL $filterMobile Enable Filter Mobile.
1670 * @return STRING
1671 */
1672 public function filter_html( $filterText = '', $filterType = '', $filterValue = '[]', $filterMobileText = '...', $filterMobile = true ) {
1673 $html = '';
1674 $html .= '<ul ' . ( $filterMobile ? 'class="ultp-flex-menu"' : '' ) . ' data-name="' . ( $filterMobileText ? esc_attr( $filterMobileText ) : '&nbsp;' ) . '">';
1675 $cat = $this->taxonomy( $filterType );
1676 if ( $filterText ) {
1677 // Already passed through wp_kses() by the caller, which keeps the allowed HTML.
1678 $html .= '<li class="filter-item"><a class="filter-active" data-taxonomy="" href="#">' . $filterText . '</a></li>';
1679 }
1680 if ( $filterValue ) {
1681 $filterValue = strlen( $filterValue ) > 2 ? $filterValue : array();
1682 $filterValue = is_array( $filterValue ) ? $filterValue : json_decode( $filterValue );
1683 if ( is_array( $filterValue ) && count( $filterValue ) ) {
1684 foreach ( $filterValue as $val ) {
1685 $val = isset( $val->value ) ? $val->value : $val;
1686 if ( ! is_scalar( $val ) ) {
1687 continue;
1688 }
1689 $html .= '<li class="filter-item"><a data-taxonomy="' . esc_attr( $val ) . '" href="#">' . esc_html( isset( $cat[ $val ] ) ? $cat[ $val ] : $val ) . '</a></li>';
1690 }
1691 }
1692 }
1693 $html .= '</ul>';
1694 return $html;
1695 }
1696
1697
1698 /**
1699 * Check License Status
1700 *
1701 * @since v.2.4.2
1702 * @return BOOLEAN | Is pro license active or not
1703 */
1704 public function is_lc_active() {
1705 return Xpo::is_lc_active();
1706 }
1707
1708
1709 /**
1710 * Get the request body for the template service
1711 *
1712 * PostX Pro adds its license key through the `ultp_template_request_body` filter.
1713 *
1714 * @param ARRAY $body Request body.
1715 * @param STRING $context Which request it is: builder_premade, starter_posts, starter_content or single_page.
1716 * @return ARRAY
1717 */
1718 public function get_template_request_body( $body, $context ) {
1719 $filtered = apply_filters( 'ultp_template_request_body', $body, $context );
1720 $body = is_array( $filtered ) ? $filtered : $body;
1721
1722 // PostX Pro before 1.9.0 does not hook the filter above, so its license key is added here.
1723 if ( ! isset( $body['license'] ) && Xpo::is_pro_before_1_9_0() ) {
1724 $body['license'] = Xpo::get_lc_key();
1725 }
1726
1727 return $body;
1728 }
1729
1730
1731 /**
1732 * Validate if the template service URL is from an allowed domain (SSRF protection).
1733 *
1734 * @param STRING $url The URL to validate.
1735 * @return BOOL True if allowed, false otherwise.
1736 */
1737 public function is_allowed_template_endpoint( $url ) {
1738 $allowed_domains = array(
1739 'postxkit.wpxpo.com',
1740 );
1741
1742 $parsed_url = wp_parse_url( $url );
1743 if ( ! $parsed_url || empty( $parsed_url['host'] ) ) {
1744 return false;
1745 }
1746
1747 $host = strtolower( $parsed_url['host'] );
1748
1749 foreach ( $allowed_domains as $domain ) {
1750 $domain = strtolower( $domain );
1751
1752 // Exact match OR valid subdomain
1753 if ( $host === $domain || substr( $host, - ( strlen( $domain ) + 1 ) ) === '.' . $domain ) {
1754 return true;
1755 }
1756 }
1757
1758 return false;
1759 }
1760
1761 /**
1762 * Get SEO Meta
1763 *
1764 * @since v.2.4.3
1765 * @param INT $post_id Post ID.
1766 * @param INT $show_seo_meta Show SEO meta flag.
1767 * @param INT $show_full_excerpt Show full excerpt flag.
1768 * @param INT $excerpt_limit Excerpt word limit.
1769 * @return STRING SEO Meta Description or Excerpt.
1770 */
1771 public function get_excerpt( $post_id = 0, $show_seo_meta = 0, $show_full_excerpt = 0, $excerpt_limit = 55 ) {
1772 $html = '';
1773 if ( $show_seo_meta ) {
1774 // PostX Pro answers this filter with the description from the active SEO plugin.
1775 $str = apply_filters( 'ultp_seo_meta_excerpt', '', $post_id );
1776 $str = is_string( $str ) ? $str : '';
1777
1778 // PostX Pro before 1.9.0 does not hook the filter above.
1779 if ( ! $str && Xpo::is_pro_before_1_9_0() ) {
1780 $str = $this->get_seo_meta_from_old_pro( $post_id );
1781 }
1782 $html = $str ? $str : ultimate_post()->excerpt( $post_id, $excerpt_limit );
1783 } elseif ( $show_full_excerpt == 0 ) {
1784 $html = ultimate_post()->excerpt( $post_id, $excerpt_limit );
1785 } else {
1786 $html = get_the_excerpt();
1787 }
1788 return $html;
1789 }
1790
1791 /**
1792 * Get the SEO meta description from PostX Pro before 1.9.0
1793 *
1794 * Newer versions provide it through the `ultp_seo_meta_excerpt` filter.
1795 *
1796 * @param INT $post_id Post ID.
1797 * @return STRING
1798 */
1799 private function get_seo_meta_from_old_pro( $post_id ) {
1800 $str = '';
1801 if ( function_exists( 'ultimate_post_pro' ) ) {
1802 if ( ultimate_post()->get_setting( 'ultp_yoast' ) == 'true' ) {
1803 $str = method_exists( ultimate_post_pro(), 'get_yoast_meta' ) ? ultimate_post_pro()->get_yoast_meta( $post_id ) : '';
1804 } elseif ( ultimate_post()->get_setting( 'ultp_rankmath' ) == 'true' ) {
1805 $str = method_exists( ultimate_post_pro(), 'get_rankmath_meta' ) ? ultimate_post_pro()->get_rankmath_meta( $post_id ) : '';
1806 } elseif ( ultimate_post()->get_setting( 'ultp_aioseo' ) == 'true' ) {
1807 $str = method_exists( ultimate_post_pro(), 'get_aioseo_meta' ) ? ultimate_post_pro()->get_aioseo_meta( $post_id ) : '';
1808 } elseif ( ultimate_post()->get_setting( 'ultp_seopress' ) == 'true' ) {
1809 $str = method_exists( ultimate_post_pro(), 'get_seopress_meta' ) ? ultimate_post_pro()->get_seopress_meta( $post_id ) : '';
1810 } elseif ( ultimate_post()->get_setting( 'ultp_squirrly' ) == 'true' ) {
1811 $str = method_exists( ultimate_post_pro(), 'get_squirrly_meta' ) ? ultimate_post_pro()->get_squirrly_meta( $post_id ) : '';
1812 }
1813 }
1814 return $str;
1815 }
1816
1817 /**
1818 * Get embedded video HTML.
1819 *
1820 * @since v.1.0.0
1821 * @param STRING $url Video URL.
1822 * @param BOOL $autoPlay Whether to autoplay the video.
1823 * @param BOOL $loop Whether to loop the video.
1824 * @param BOOL $mute Whether to mute the video.
1825 * @param BOOL $playback Whether to show playback controls.
1826 * @param STRING $preload Preload attribute value.
1827 * @param ARRAY | string $poster Poster image for the video.
1828 * @param BOOL $inline Whether to play inline.
1829 * @param ARRAY | string $size Size for oEmbed.
1830 * @return STRING | false Video embed HTML or false on failure.
1831 */
1832 public function get_embeded_video( $url, $autoPlay, $loop, $mute, $playback, $preload, $poster, $inline, $size, $location = '' ) {
1833 $vidAutoPlay = $vidloop = $vidloop = $vidmute = $vidplayback = $vidPoster = $vidInline = '';
1834
1835 $video_type = '';
1836 // Determine video type
1837 $video_type = 'local';
1838 if ( strpos( $url, 'youtube.com' ) !== false || strpos( $url, 'youtu.be' ) !== false ) {
1839 $video_type = 'youtube';
1840 } elseif ( strpos( $url, 'vimeo.com' ) !== false ) {
1841 $video_type = 'vimeo';
1842 }
1843
1844 // Get poster URL
1845 $poster_url = '';
1846 if ( is_array( $poster ) && isset( $poster['url'] ) ) {
1847 $poster_url = $poster['url'];
1848 } elseif ( is_string( $poster ) ) {
1849 $poster_url = $poster;
1850 }
1851
1852 // Prepare size attributes
1853 $width = is_array( $size ) && isset( $size['width'] ) ? $size['width'] : 560;
1854 $height = is_array( $size ) && isset( $size['height'] ) ? $size['height'] : 315;
1855
1856 $video_id = '';
1857
1858 if ( $url ) {
1859 $regex = '/(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})/';
1860 if ( preg_match( $regex, $url, $matches ) ) {
1861 $video_id = $matches[1];
1862 }
1863 }
1864
1865 // Create data attributes for lazy loading
1866 $data_attrs = array(
1867 'data-video-url' => is_scalar( $url ) ? esc_attr( $url ) : '',
1868 'data-video-type' => is_scalar( $video_type ) ? esc_attr( $video_type ) : '',
1869 'data-autoplay' => ! empty( $autoPlay ) ? '1' : '0',
1870 'data-loop' => ! empty( $loop ) ? '1' : '0',
1871 'data-mute' => ! empty( $mute ) ? '1' : '0',
1872 'data-controls' => ! empty( $playback ) ? '1' : '0',
1873 'data-preload' => is_scalar( $preload ) ? esc_attr( $preload ) : '',
1874 'data-poster' => is_scalar( $poster_url ) ? esc_attr( $poster_url ) : '',
1875 'data-playsinline' => ! empty( $inline ) ? '1' : '0',
1876 'data-width' => is_scalar( $width ) ? esc_attr( $width ) : '',
1877 'data-height' => is_scalar( $height ) ? esc_attr( $height ) : '',
1878 'data-video-id' => is_scalar( $video_id ) ? esc_attr( $video_id ) : '',
1879 );
1880
1881 $data_string = implode(
1882 ' ',
1883 array_map(
1884 function ( $key, $value ) {
1885 return $key . '="' . $value . '"';
1886 },
1887 array_keys( $data_attrs ),
1888 $data_attrs
1889 )
1890 );
1891
1892 $html = '<div class="ultp-video-wrapper ultp-embaded-video"' . $data_string . '></div>';
1893
1894 if ( $location == '' ) {
1895 return $html;
1896 }
1897
1898 if ( $autoPlay ) {
1899 $vidAutoPlay = 'autoplay';
1900 }
1901 if ( $poster ) {
1902 $vidPoster = 'poster="' . $poster['url'] . '"';
1903 }
1904 if ( $loop ) {
1905 $vidloop = 'loop';
1906 }
1907 if ( $mute ) {
1908 $vidmute = 'muted';
1909 }
1910 if ( $playback ) {
1911 $vidplayback = 'controls';
1912 }
1913 if ( $inline ) {
1914 $vidInline = 'playsinline';
1915 }
1916 if ( ! empty( $url ) ) {
1917 $embeded = wp_oembed_get( $url, $size );
1918 if ( $embeded == false ) {
1919 $format = '';
1920 $url = strtolower( $url );
1921 if ( strpos( $url, '.mp4' ) ) {
1922 $format = 'mp4';
1923 } elseif ( strpos( $url, '.ogg' ) ) {
1924 $format = 'ogg';
1925 } elseif ( strpos( $url, '.webm' ) ) {
1926 $format = 'WebM';
1927 }
1928 $embeded = '<video
1929 ' . $vidloop . '
1930 ' . $vidmute . '
1931 ' . $vidplayback . '
1932 preload="' . $preload . '"
1933 ' . $vidAutoPlay . '
1934 ' . $vidPoster . '
1935 ' . $vidInline . '
1936 class="ultp-video-html"
1937 ><source src="' . $url . '" type="video/' . $format . '">' . __( 'Your browser does not support the video tag.', 'ultimate-post' ) . '</video>';
1938 return '<div class="ultp-video-wrapper">' . $embeded . '</div>';
1939 }
1940 return '<div class="ultp-video-wrapper ultp-embaded-video">' . $embeded . '</div>';
1941 } else {
1942 return false;
1943 }
1944 }
1945
1946 /**
1947 * Get Public taxonomy Lists
1948 *
1949 * @since v.2.7.0
1950 * @return ARRAY | Taxonomy Lists as array
1951 */
1952 public function get_taxonomy_list() {
1953 $taxonomy = get_taxonomies( array( 'public' => true ) );
1954 return empty( $taxonomy ) ? array() : array_keys( $taxonomy );
1955 }
1956
1957 /**
1958 * Content Print
1959 *
1960 * @since v.2.7.0
1961 * @param int $post_id Post ID.
1962 * @param string $builder_type Builder type.
1963 * @return void | Content of the Post
1964 */
1965 public function get_post_content( $post_id, $builder_type = '' ) {
1966 $content_post = get_post( $post_id );
1967 $content = $content_post->post_content;
1968 if ( $builder_type == 'divi' || $builder_type == 'elementor' ) {
1969 $content = apply_filters( 'the_content', $content ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Core hook.
1970 } else {
1971 global $wp_embed;
1972 $content = $wp_embed->autoembed( $content );
1973 $content = do_blocks( $content );
1974 $content = do_shortcode( $content );
1975 }
1976 $content = str_replace( ']]>', ']]&gt;', $content );
1977 $content = preg_replace( '%<p>&nbsp;\s*</p>%', '', $content );
1978 $content = preg_replace( '/^(?:<br\s*\/?>\s*)+/', '', $content );
1979 echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Rendered post content (do_blocks/the_content), the same markup core prints for the post.
1980 }
1981
1982 /**
1983 * String Part finder inside array.
1984 *
1985 * @since v.2.7.0 updated 4.1.12
1986 *
1987 * @param STRING $part The part of the string to search for.
1988 * @param ARRAY $data The array to search within.
1989 * @param STRING $toR Return type: 'bool', 'value', or default (array).
1990 * @return MIXED Returns true/false, value, or array depending on $toR.
1991 * @since v.2.7.0 updated 4.1.12
1992 */
1993 public function in_array_part( $part, $data, $toR = '' ) {
1994 $res = array();
1995 foreach ( $data as $key => $val ) {
1996 if ( strpos( $val, $part ) !== false ) {
1997 if ( $toR == 'bool' ) {
1998 return true;
1999 } elseif ( $toR == 'value' ) {
2000 return $val;
2001 }
2002 $res[ $key ] = $val;
2003 }
2004 }
2005 if ( $toR == 'bool' ) {
2006 return false;
2007 } elseif ( $toR == 'value' ) {
2008 return '';
2009 }
2010 return $res;
2011 }
2012
2013 /**
2014 * Builder Conditions
2015 *
2016 * @since v.2.7.0 updated 4.1.12
2017 * @param STRING $type Type of return value.
2018 * @param MIXED $cus_condition Custom conditions array or value.
2019 * @return MIXED ID or Path.
2020 */
2021 public function builder_check_conditions( $type = 'return', $cus_condition = '' ) {
2022 $page_id = '';
2023 $conditions = $cus_condition ? $cus_condition : get_option( 'ultp_builder_conditions', array() );
2024
2025 if ( $type == 'header' || $type == 'footer' ) {
2026 if ( ! empty( $conditions[ $type ] ) ) {
2027 foreach ( $conditions[ $type ] as $key => $val ) {
2028 if ( 'publish' == get_post_status( $key ) && ! empty( $val ) ) {
2029 if ( in_array( 'include/' . $type . '/entire_site', $val ) ) {
2030 $page_id = $key;
2031 } elseif ( in_array( 'exclude/' . $type . '/entire_site', $val ) ) {
2032 $page_id = '';
2033 }
2034
2035 $c_page = ( is_archive() || is_search() ) ? 'archive' : 'singular';
2036 $hf_archive = $this->in_array_part( $type . '/' . $c_page, $val, '' );
2037 if ( ! empty( $hf_archive ) ) {
2038 foreach ( $hf_archive as $k => $v ) {
2039 if ( strpos( $v, 'include/' . $type . '/' . $c_page ) !== false ) {
2040 $temp = $this->builder_check_conditions( 'return_' . $type, array( $c_page => array( $key => array( str_replace( $type . '/', '', $v ) ) ) ) );
2041 $page_id = $temp ? $temp : $page_id;
2042 } elseif ( strpos( $v, 'exclude/' . $type . '/' . $c_page ) !== false ) {
2043 $temp = $this->builder_check_conditions( 'return_' . $type, array( $c_page => array( $key => array( str_replace( 'exclude/' . $type, 'include', $v ) ) ) ) );
2044 $page_id = $temp ? '' : $page_id;
2045 }
2046 }
2047 }
2048 }
2049 }
2050 }
2051 } else {
2052 // 404 page .
2053 if ( ! empty( $conditions['404'] ) && is_404() ) {
2054 foreach ( $conditions['404'] as $key => $val ) {
2055 if ( 'publish' == get_post_status( $key ) ) {
2056 $page_id = $key;
2057 }
2058 }
2059 }
2060 // Singular or Front Page .
2061 elseif (
2062 (
2063 ! empty( $conditions['singular'] ) ||
2064 ! empty( $conditions['front_page'] )
2065 ) &&
2066 (
2067 is_singular() ||
2068 is_front_page() ||
2069 is_home()
2070 )
2071 ) {
2072 $obj = get_queried_object();
2073 $queried_is_obj = is_object( $obj );
2074 // front page only .
2075 if (
2076 ( is_front_page() && is_home() ) ||
2077 ( is_home() && ! $queried_is_obj ) ||
2078 ( is_singular() && is_front_page() && $queried_is_obj )
2079 ) {
2080 $f_conditions = array();
2081 if ( ! empty( $conditions['front_page'] ) ) {
2082 $f_conditions = $conditions['front_page'];
2083 } elseif ( ! empty( $conditions['singular'] ) ) {
2084 $f_conditions = $conditions['singular'];
2085 }
2086 if ( ! empty( $f_conditions ) ) {
2087 foreach ( $f_conditions as $key => $val ) {
2088 if ( ( is_array( $val ) && in_array( 'include/singular/front_page', $val ) ) ||
2089 ( is_array( $val ) && in_array( 'include/front_page', $val ) ) ||
2090 'include/front_page' == $val
2091 ) {
2092 if ( 'publish' == get_post_status( $key ) ) {
2093 $page_id = $key;
2094 }
2095 }
2096 // Default Front / Home page Header Footer Compatibility .
2097 elseif ( is_array( $val ) && 'publish' == get_post_status( $key ) && ( $type == 'return_header' || $type == 'return_footer' ) ) {
2098 $base_include = 'include/singular/' . $obj->post_type;
2099 $base_exclude = 'exclude/singular/' . $obj->post_type;
2100 $specific_include = $base_include . '/' . $obj->ID;
2101 $specific_exclude = $base_exclude . '/' . $obj->ID;
2102
2103 if ( in_array( $specific_include, $val ) ) {
2104 $page_id = $key;
2105 } elseif ( in_array( $specific_exclude, $val ) ) {
2106 $page_id = '';
2107 } elseif ( in_array( $base_include, $val ) ) {
2108 $page_id = $key;
2109 } elseif ( in_array( $base_exclude, $val ) ) {
2110 $page_id = '';
2111 }
2112 }
2113 }
2114 }
2115 }
2116 // Singular page .
2117 elseif ( ! empty( $conditions['singular'] ) ) {
2118 foreach ( $conditions['singular'] as $key => $val ) {
2119 if ( 'publish' == get_post_status( $key ) ) {
2120 // All Post Type. -----Prority 1 .
2121 if ( $queried_is_obj ) {
2122 if ( in_array( 'include/singular/' . $obj->post_type, $val ) ) {
2123 $page_id = $key;
2124 } elseif ( in_array( 'exclude/singular/' . $obj->post_type, $val ) ) {
2125 $page_id = '';
2126 }
2127 }
2128
2129 $singular_in_tax = $this->in_array_part( '/singular/in_', $val, '' );
2130 if ( ! empty( $singular_in_tax ) ) {
2131 $tax_list = $this->get_taxonomy_list();
2132 foreach ( $tax_list as $tax ) {
2133 if ( in_array( 'include/singular/in_' . $tax . '_children', $singular_in_tax ) ) {
2134 $page_id = $key;
2135 } elseif ( in_array( 'exclude/singular/in_' . $tax . '_children', $singular_in_tax ) ) {
2136 $page_id = '';
2137 }
2138
2139 if ( $queried_is_obj ) {
2140 $singular_in_tax_children = $this->in_array_part( '/singular/in_' . $tax . '_children/', $singular_in_tax, '' );
2141 foreach ( $singular_in_tax_children as $v ) {
2142 $data = explode( '/', $v );
2143 if ( isset( $data[3] ) && $data[3] ) {
2144 $childs = get_term_children( $data[3], $tax );
2145 if ( ! empty( $childs ) && has_term( $childs, $tax ) ) {
2146 $page_id = $data[0] == 'exclude' ? '' : $key;
2147 }
2148 }
2149 }
2150 }
2151
2152 if ( in_array( 'include/singular/in_' . $tax, $singular_in_tax ) ) {
2153 if ( $tax == 'post_tag' && $queried_is_obj ) {
2154 $cat = get_the_terms( $obj->ID, 'post_tag' );
2155 if ( ! empty( $cat ) ) {
2156 $page_id = $key;
2157 }
2158 } else {
2159 $page_id = $key;
2160 }
2161 } elseif ( in_array( 'exclude/singular/in_' . $tax, $singular_in_tax ) ) {
2162 $page_id = '';
2163 }
2164
2165 if ( $queried_is_obj ) {
2166 $singular_in_tax_only = $this->in_array_part( '/singular/in_' . $tax . '/', $singular_in_tax, '' );
2167 foreach ( $singular_in_tax_only as $v ) {
2168 $data = explode( '/', $v );
2169 if ( isset( $data[3] ) && $data[3] ) {
2170 if ( is_object_in_term( $obj->ID, $tax, $data[3] ) ) {
2171 $page_id = $data[0] == 'exclude' ? '' : $key;
2172 }
2173 }
2174 }
2175 }
2176 }
2177 }
2178
2179 // Posts by author -----Prority 9 .
2180 if ( in_array( 'include/singular/post_by_author', $val ) ) {
2181 $page_id = $key;
2182 } elseif ( in_array( 'exclude/singular/post_by_author', $val ) ) {
2183 $page_id = '';
2184 }
2185 if ( $queried_is_obj ) {
2186 if ( in_array( 'include/singular/post_by_author/' . $obj->post_author, $val ) ) {
2187 $page_id = $key;
2188 } elseif ( in_array( 'exclude/singular/post_by_author/' . $obj->post_author, $val ) ) {
2189 $page_id = '';
2190 }
2191 // Post Type with specific id -----Prority 10 .
2192 if ( in_array( 'include/singular/' . $obj->post_type . '/' . $obj->ID, $val ) ) {
2193 $page_id = $key;
2194 } elseif ( in_array( 'exclude/singular/' . $obj->post_type . '/' . $obj->ID, $val ) ) {
2195 $page_id = '';
2196 }
2197 }
2198 }
2199 }
2200 }
2201 }
2202
2203 // Archive and Search Page .
2204 elseif ( ! empty( $conditions['archive'] ) ) {
2205 // Search Page .
2206 if ( is_search() ) {
2207 foreach ( $conditions['archive'] as $key => $val ) {
2208 if ( 'publish' == get_post_status( $key ) ) {
2209 if ( in_array( 'include/archive/search', $val ) ) {
2210 $page_id = $key;
2211 } elseif ( in_array( 'exclude/archive/search', $val ) ) {
2212 $page_id = '';
2213 }
2214 }
2215 }
2216 }
2217 // Archive Page .
2218 elseif ( is_archive() ) {
2219 $is_cat = is_category();
2220 $is_tag = is_tag();
2221 $is_tax = is_tax();
2222 $is_date = is_date();
2223 $is_author = is_author();
2224 $taxonomy = ( $is_cat || $is_tag || $is_tax ) ? get_queried_object() : (object) array();
2225
2226 foreach ( $conditions['archive'] as $key => $val ) {
2227 if ( 'publish' == get_post_status( $key ) ) {
2228 // This section is for all archive page .
2229 if ( in_array( 'include/archive', $val ) ) {
2230 $page_id = $key;
2231 } elseif ( in_array( 'exclude/archive', $val ) ) {
2232 $page_id = '';
2233 }
2234 // For Category .
2235 if ( $is_cat ) {
2236 // all category .
2237 if ( in_array( 'include/archive/category', $val ) ) {
2238 $page_id = $key;
2239 } elseif ( in_array( 'exclude/archive/category', $val ) ) {
2240 $page_id = '';
2241 }
2242 // specific category .
2243 if ( in_array( 'include/archive/category/' . $taxonomy->term_id, $val ) ) {
2244 $page_id = $key;
2245 } elseif ( in_array( 'exclude/archive/category/' . $taxonomy->term_id, $val ) ) {
2246 $page_id = '';
2247 }
2248
2249 // any child of category .
2250 if ( in_array( 'include/archive/any_child_of_category', $val ) ) {
2251 $page_id = $key;
2252 } elseif ( in_array( 'exclude/archive/any_child_of_category', $val ) ) {
2253 $page_id = '';
2254 }
2255
2256 $any_child_of_cat = $this->in_array_part( 'archive/any_child_of_category/', $val, '' );
2257 if ( ! empty( $any_child_of_cat ) ) {
2258 foreach ( $any_child_of_cat as $v ) {
2259 $data = explode( '/', $v );
2260 if ( isset( $data[3] ) && $data[3] ) {
2261 if ( term_is_ancestor_of( $data[3], $taxonomy->term_id, 'category' ) ) {
2262 $page_id = $data[0] == 'exclude' ? '' : $key;
2263 }
2264 }
2265 }
2266 }
2267
2268 // all child of category .
2269 if ( in_array( 'include/archive/child_of_category', $val ) ) {
2270 $page_id = $key;
2271 } elseif ( in_array( 'exclude/archive/child_of_category', $val ) ) {
2272 $page_id = '';
2273 }
2274 // specific child of category .
2275 if ( in_array( 'include/archive/child_of_category/' . $taxonomy->parent, $val ) ) {
2276 $page_id = $key;
2277 } elseif ( in_array( 'exclude/archive/child_of_category/' . $taxonomy->parent, $val ) ) {
2278 $page_id = '';
2279 }
2280 }
2281 // For Tag .
2282 elseif ( $is_tag ) {
2283 if ( in_array( 'include/archive/post_tag', $val ) ) {
2284 $page_id = $key;
2285 } elseif ( in_array( 'exclude/archive/post_tag', $val ) ) {
2286 $page_id = '';
2287 }
2288 if ( in_array( 'include/archive/post_tag/' . $taxonomy->term_id, $val ) ) {
2289 $page_id = $key;
2290 } elseif ( in_array( 'exclude/archive/post_tag/' . $taxonomy->term_id, $val ) ) {
2291 $page_id = '';
2292 }
2293 }
2294 // Other taxonomy .
2295 elseif ( $is_tax ) {
2296 if ( in_array( 'include/archive/' . $taxonomy->taxonomy, $val ) ) {
2297 $page_id = $key;
2298 } elseif ( in_array( 'exclude/archive/' . $taxonomy->taxonomy, $val ) ) {
2299 $page_id = '';
2300 }
2301
2302 if ( in_array( 'include/archive/' . $taxonomy->taxonomy . '/' . $taxonomy->term_id, $val ) ) {
2303 $page_id = $key;
2304 } elseif ( in_array( 'exclude/archive/' . $taxonomy->taxonomy . '/' . $taxonomy->term_id, $val ) ) {
2305 $page_id = '';
2306 }
2307
2308 if ( in_array( 'include/archive/any_child_of_' . $taxonomy->taxonomy, $val ) ) {
2309 $page_id = $key;
2310 } elseif ( in_array( 'exclude/archive/any_child_of_' . $taxonomy->taxonomy, $val ) ) {
2311 $page_id = '';
2312 }
2313
2314 $any_child_of_tax = $this->in_array_part( 'archive/any_child_of_' . $taxonomy->taxonomy . '/', $val, '' );
2315 if ( ! empty( $any_child_of_tax ) ) {
2316 foreach ( $any_child_of_tax as $v ) {
2317 $data = explode( '/', $v );
2318 if ( isset( $data[3] ) && $data[3] ) {
2319 if ( term_is_ancestor_of( $data[3], $taxonomy->term_id, $taxonomy->taxonomy ) ) {
2320 $page_id = $data[0] == 'exclude' ? '' : $key;
2321 }
2322 }
2323 }
2324 }
2325
2326 if ( in_array( 'include/archive/child_of_' . $taxonomy->taxonomy, $val ) ) {
2327 $page_id = $key;
2328 } elseif ( in_array( 'exclude/archive/child_of_' . $taxonomy->taxonomy, $val ) ) {
2329 $page_id = '';
2330 }
2331
2332 if ( in_array( 'include/archive/child_of_' . $taxonomy->taxonomy . '/' . $taxonomy->parent, $val ) ) {
2333 $page_id = $key;
2334 } elseif ( in_array( 'exclude/archive/child_of_' . $taxonomy->taxonomy . '/' . $taxonomy->parent, $val ) ) {
2335 $page_id = '';
2336 }
2337 }
2338 // For Date.
2339 elseif ( $is_date ) {
2340 if ( in_array( 'include/archive/date', $val ) ) {
2341 $page_id = $key;
2342 } elseif ( in_array( 'exclude/archive/date', $val ) ) {
2343 $page_id = '';
2344 }
2345 }
2346 // For Author.
2347 elseif ( $is_author ) {
2348 if ( in_array( 'include/archive/author', $val ) ) {
2349 $page_id = $key;
2350 } elseif ( in_array( 'exclude/archive/author', $val ) ) {
2351 $page_id = '';
2352 }
2353 $author_id = get_the_author_meta( 'ID' );
2354 if ( in_array( 'include/archive/author/' . $author_id, $val ) ) {
2355 $page_id = $key;
2356 } elseif ( in_array( 'exclude/archive/author/' . $author_id, $val ) ) {
2357 $page_id = '';
2358 }
2359 }
2360 }
2361 }
2362 }
2363 }
2364 }
2365 return $page_id;
2366 }
2367
2368 /**
2369 * Get Date Default Format
2370 *
2371 * @since v.2.7.2
2372 * @param STRING $format Format type.
2373 * @return ARRAY | Default Data
2374 */
2375 public function get_format( $format ) {
2376 if ( $format == 'default_date' ) {
2377 return get_option( 'date_format' );
2378 } elseif ( $format == 'default_date_time' ) {
2379 return get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
2380 } else {
2381 return $format;
2382 }
2383 }
2384
2385 /**
2386 * Common Frontend and Backend CSS and JS Scripts
2387 *
2388 * @since v.1.0.0
2389 */
2390 public function register_scripts_common() {
2391 if ( ! ( isset( $GLOBALS['wp_scripts'] ) && isset( $GLOBALS['wp_scripts']->registered ) && isset( $GLOBALS['wp_scripts']->registered['ultp-script'] ) ) ) {
2392 wp_enqueue_style( 'ultp-style', ULTP_URL . 'assets/css/style.min.css', array(), ULTP_VER );
2393 wp_enqueue_script( 'ultp-script', ULTP_URL . 'assets/js/ultp.min.js', array( 'jquery', 'wp-api-fetch' ), ULTP_VER, true );
2394 wp_localize_script(
2395 'ultp-script',
2396 'ultp_data_frontend',
2397 array(
2398 'url' => ULTP_URL,
2399 'ultpSavedDLMode' => ultimate_post()->get_dl_mode(),
2400 'ajax' => admin_url( 'admin-ajax.php' ),
2401 'security' => wp_create_nonce( 'ultp-public-nonce' ),
2402 'home_url' => home_url(),
2403 'dark_logo' => get_option( 'ultp_site_dark_logo', false ),
2404 )
2405 );
2406 }
2407 }
2408
2409 /**
2410 * Get Dark Light Mode
2411 *
2412 * @since 4.0.0
2413 * @return STRING | Dark Light Mode .
2414 */
2415 public function get_dl_mode() {
2416 $data = get_option( 'postx_global', array() );
2417 $mode = 'ultplight';
2418 if ( ! empty( $data ) ) {
2419 $mode = isset( $data['enableDark'] ) && $data['enableDark'] ? 'ultpdark' : 'ultplight';
2420 }
2421 return $mode;
2422 }
2423
2424 /**
2425 * Get Page Post Id ( Kadence element )
2426 *
2427 * @since v.2.8.9
2428 * @param STRING|INT $blockId Block ID to search for.
2429 * @return NULL
2430 */
2431 public function get_page_post_id( $blockId ) {
2432 global $wpdb;
2433 $post_meta = $wpdb->get_row( $wpdb->prepare( 'SELECT post_id FROM ' . $wpdb->prefix . 'postmeta WHERE meta_key=%s AND meta_value LIKE %s', '_ultp_css', '%.ultp-block-' . $blockId . '%' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
2434 // For FSE theme
2435 if ( ! $post_meta ) {
2436 if ( wp_is_block_theme() ) {
2437 $template = $wpdb->get_row( $wpdb->prepare( 'SELECT ID FROM ' . $wpdb->prefix . 'posts WHERE post_content LIKE %s', '%"blockId":"' . $blockId . '"%' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
2438 if ( isset( $template->ID ) ) {
2439 return $template->ID;
2440 }
2441 }
2442 }
2443 if ( $post_meta && isset( $post_meta->post_id ) ) {
2444 return $post_meta->post_id;
2445 }
2446 return ultimate_post()->get_ID();
2447 }
2448
2449
2450 /**
2451 * Get no Result found html
2452 *
2453 * @since v.2.9.0
2454 * @param STRING $text No result found text.
2455 * @return STRING | Taxonomy Lists as array
2456 */
2457 public function get_no_result_found_html( $text ) {
2458 return $text ? '<div class="ultp-not-found-message" role="alert">' . wp_kses( $text, ultimate_post()->ultp_allowed_html_tags() ) . '</div>' : '';
2459 }
2460
2461 /**
2462 * Get all Saved Templates Lists
2463 *
2464 * @since v.2.9.9
2465 * @param STRING $post_type Post type to retrieve.
2466 * @param STRING $empty Empty value for the select field.
2467 * @return STRING | Taxonomy Lists as array
2468 */
2469 public function get_all_lists( $post_type = 'post', $empty = '' ) {
2470 $args = array(
2471 'post_type' => $post_type,
2472 'post_status' => 'publish',
2473 'posts_per_page' => -1,
2474 );
2475 $loop = new \WP_Query( $args );
2476 $data[ $empty ? $empty : '' ] = __( '- Select Template -', 'ultimate-post' );
2477 if ( $loop->have_posts() ) {
2478 foreach ( $loop->posts as $post ) {
2479 $data[ $post->ID ] = $post->post_title;
2480 }
2481 }
2482 wp_reset_postdata();
2483 return $data;
2484 }
2485
2486 /**
2487 * Get ID from the Youtube URL
2488 *
2489 * @since v.3.1.7
2490 * @param STRING $url The Youtube URL .
2491 * @return STRING | Taxonomy Lists as array
2492 */
2493 public function get_youtube_id( $url = '' ) {
2494 if ( strpos( $url, 'youtu' ) !== false ) {
2495 $reg = '/youtu(?:.*\/v\/|.*v\=|\.be\/)([A-Za-z0-9_\-]{11})/m';
2496 preg_match( $reg, $url, $matches );
2497 if ( isset( $matches[1] ) ) {
2498 return $matches[1];
2499 }
2500 }
2501 return false;
2502 }
2503
2504 /**
2505 * Get Option Value bypassing cache
2506 * Inspired By WordPress Core get_option
2507 *
2508 * @since v.3.1.6
2509 * @param STRING $option Option Name.
2510 * @param BOOLEAN $default_value option default value.
2511 * @return mixed
2512 */
2513 public function get_option_without_cache( $option, $default_value = false ) {
2514 global $wpdb;
2515
2516 if ( is_scalar( $option ) ) {
2517 $option = trim( $option );
2518 }
2519
2520 if ( empty( $option ) ) {
2521 return false;
2522 }
2523
2524 $value = $default_value;
2525
2526 $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
2527
2528 if ( is_object( $row ) ) {
2529 $value = $row->option_value;
2530 } else {
2531 return apply_filters( "ultp_default_option_{$option}", $default_value, $option );
2532 }
2533
2534 return apply_filters( "ultp_option_{$option}", maybe_unserialize( $value ), $option );
2535 }
2536
2537 /**
2538 * Get Transient Value bypassing cache
2539 * Inspired By WordPress Core get_transient
2540 *
2541 * @since v.3.1.6
2542 * @param STRING $transient Transient Name.
2543 * @return MIXED
2544 */
2545 public function get_transient_without_cache( $transient ) {
2546 $transient_option = '_transient_' . $transient;
2547 $transient_timeout = '_transient_timeout_' . $transient;
2548 $timeout = $this->get_option_without_cache( $transient_timeout );
2549
2550 if ( false !== $timeout && $timeout < time() ) {
2551 delete_option( $transient_option );
2552 delete_option( $transient_timeout );
2553 $value = false;
2554 }
2555
2556 if ( ! isset( $value ) ) {
2557 $value = $this->get_option_without_cache( $transient_option );
2558 }
2559
2560 return apply_filters( "ultp_transient_{$transient}", $value, $transient );
2561 }
2562
2563 /**
2564 * Set transient without adding to the cache
2565 * Inspired By WordPress Core set_transient
2566 *
2567 * @since v.3.1.6
2568 * @param STRING $transient Transient Name.
2569 * @param MIXED $value Transient Value.
2570 * @param INTEGER $expiration Time until expiration in seconds.
2571 * @return BOOL
2572 */
2573 public function set_transient_without_cache( $transient, $value, $expiration = 0 ) {
2574 $expiration = (int) $expiration;
2575
2576 $transient_timeout = '_transient_timeout_' . $transient;
2577 $transient_option = '_transient_' . $transient;
2578
2579 $result = false;
2580
2581 if ( false === $this->get_option_without_cache( $transient_option ) ) {
2582 $autoload = 'yes';
2583 if ( $expiration ) {
2584 $autoload = 'no';
2585 $this->add_option_without_cache( $transient_timeout, time() + $expiration, 'no' );
2586 }
2587 $result = $this->add_option_without_cache( $transient_option, $value, $autoload );
2588 } else {
2589 /*
2590 * If expiration is requested, but the transient has no timeout option,
2591 * delete, then re-create transient rather than update.
2592 */
2593 $update = true;
2594
2595 if ( $expiration ) {
2596 if ( false === $this->get_option_without_cache( $transient_timeout ) ) {
2597 delete_option( $transient_option );
2598 $this->add_option_without_cache( $transient_timeout, time() + $expiration, 'no' );
2599 $result = $this->add_option_without_cache( $transient_option, $value, 'no' );
2600 $update = false;
2601 } else {
2602 update_option( $transient_timeout, time() + $expiration );
2603 }
2604 }
2605
2606 if ( $update ) {
2607 $result = update_option( $transient_option, $value );
2608 }
2609 }
2610
2611 return $result;
2612 }
2613
2614 /**
2615 * Add option without adding to the cache
2616 * Inspired By WordPress Core set_transient
2617 *
2618 * @since v.3.1.6
2619 * @param STRING $option option name.
2620 * @param STRING $value option value.
2621 * @param STRING $autoload whether to load WordPress startup.
2622 * @return BOOL
2623 */
2624 public function add_option_without_cache( $option, $value = '', $autoload = 'yes' ) {
2625 global $wpdb;
2626
2627 if ( is_scalar( $option ) ) {
2628 $option = trim( $option );
2629 }
2630
2631 if ( empty( $option ) ) {
2632 return false;
2633 }
2634
2635 wp_protect_special_option( $option );
2636
2637 if ( is_object( $value ) ) {
2638 $value = clone $value;
2639 }
2640
2641 $value = sanitize_option( $option, $value );
2642
2643 /*
2644 * Make sure the option doesn't already exist.
2645 */
2646
2647 if ( apply_filters( "ultp_default_option_{$option}", false, $option, false ) !== $this->get_option_without_cache( $option ) ) {
2648 return false;
2649 }
2650
2651 $serialized_value = maybe_serialize( $value );
2652 $autoload = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
2653
2654 $result = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)", $option, $serialized_value, $autoload ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
2655 if ( ! $result ) {
2656 return false;
2657 }
2658
2659 return true;
2660 }
2661
2662 /**
2663 * Permission_check_for_restapi
2664 *
2665 * @since v.3.2.4
2666 * @param STRING/Bool $post_id .
2667 * @param STRING $cap STRING .
2668 * @return BOOL
2669 */
2670 public function permission_check_for_restapi( $post_id = false, $cap = '' ) {
2671 $cap = $cap ? $cap : 'edit_others_posts';
2672 $is_passed = false;
2673 if ( $post_id ) {
2674 $post_author = (int) get_post_field( 'post_author', $post_id );
2675 $is_passed = (int) get_current_user_id() === $post_author;
2676 }
2677 return $is_passed || current_user_can( $cap );
2678 }
2679
2680 /**
2681 * Sanitize params
2682 *
2683 * @param MIXED $params Parameters to sanitize.
2684 * @return array|bool|mixed|string
2685 * @since v.4.0.0
2686 */
2687 public function ultp_rest_sanitize_params( $params ) {
2688 if ( is_array( $params ) ) {
2689 return array_map( array( $this, 'ultp_rest_sanitize_params' ), $params );
2690 } elseif ( is_bool( $params ) ) {
2691 return rest_sanitize_boolean( $params );
2692 } elseif ( is_object( $params ) ) {
2693 return $params;
2694 } else {
2695 return sanitize_text_field( $params );
2696 }
2697 }
2698
2699 /**
2700 * Get Adv Filter Data Attributes
2701 *
2702 * @param ARRAY|NULL $attr .
2703 * @param ARRAY|NULL $filter_attributes .
2704 * @return string
2705 * @since v.3.2.5
2706 */
2707 public function get_adv_data_attrs( $attr, $filter_attributes = null ) {
2708 // Adv Filter Integration.
2709 $adv_filter_dataset = array();
2710
2711 if ( $filter_attributes ) {
2712 $adv_filter_dataset[] = 'data-filter-value="' . htmlspecialchars( $filter_attributes['queryTaxValue'] ) . '"';
2713 $adv_filter_dataset[] = 'data-filter-type="' . htmlspecialchars( $filter_attributes['queryTax'] ) . '"';
2714
2715 $is_adv = isset( $filter_attributes['isAdv'] ) ? $filter_attributes['isAdv'] : 0;
2716 $adv_filter_dataset[] = 'data-filter-is-adv="' . $is_adv . '"';
2717
2718 if ( $is_adv ) {
2719 if ( isset( $filter_attributes['queryAuthor'] ) ) {
2720 $adv_filter_dataset[] = "data-filter-author='" . $filter_attributes['queryAuthor'] . "'";
2721 }
2722
2723 if ( isset( $filter_attributes['queryOrder'] ) ) {
2724 $adv_filter_dataset[] = "data-filter-order='" . $filter_attributes['queryOrder'] . "'";
2725 }
2726
2727 if ( isset( $filter_attributes['queryOrderBy'] ) ) {
2728 $adv_filter_dataset[] = "data-filter-orderby='" . $filter_attributes['queryOrderBy'] . "'";
2729 }
2730
2731 if ( isset( $filter_attributes['search'] ) ) {
2732 $adv_filter_dataset[] = 'data-filter-search="' . $filter_attributes['search'] . '"';
2733 }
2734
2735 if ( isset( $filter_attributes['queryQuick'] ) && $filter_attributes['queryQuick'] ) {
2736 $adv_filter_dataset[] = 'data-filter-adv-sort="' . $filter_attributes['queryQuick'] . '"';
2737 }
2738 }
2739 }
2740
2741 if ( $attr && isset( $attr['advFilterEnable'] ) && $attr['advFilterEnable'] ) {
2742 $adv_filter_dataset[] = 'data-filter-is-adv="1"';
2743 $adv_filter_dataset[] = 'data-filter-type="multiTaxonomy"';
2744
2745 $data_filter_value = isset( $attr['filterValue'] ) && $attr['filterValue'] ? $attr['filterValue'] : '[]';
2746 $adv_filter_dataset[] = 'data-filter-value="' . htmlspecialchars( $data_filter_value ) . '"';
2747
2748 $data_author = isset( $attr['queryAuthor'] ) && $attr['queryAuthor'] ? $attr['queryAuthor'] : '[]';
2749 $adv_filter_dataset[] = 'data-filter-author="' . $data_author . '"';
2750
2751 $data_order = isset( $attr['queryOrder'] ) && $attr['queryOrder'] ? $attr['queryOrder'] : 'DESC';
2752 $adv_filter_dataset[] = 'data-filter-order="' . $data_order . '"';
2753
2754 $data_orderby = isset( $attr['queryOrderBy'] ) && $attr['queryOrderBy'] ? $attr['queryOrderBy'] : 'date';
2755 $adv_filter_dataset[] = 'data-filter-orderby="' . $data_orderby . '"';
2756
2757 $adv_filter_dataset[] = 'data-filter-search="' . ( isset( $attr['querySearch'] ) ? $attr['querySearch'] : '' ) . '"';
2758
2759 $adv_filter_dataset[] = 'data-filter-adv-sort="' . ( isset( $attr['queryQuick'] ) ? $attr['queryQuick'] : '' ) . '"';
2760 }
2761
2762 $adv_filter_dataset = implode( ' ', $adv_filter_dataset );
2763 return $adv_filter_dataset;
2764 }
2765
2766 /**
2767 * Custom Text kses
2768 *
2769 * @since v.4.0.2
2770 * @param MIXED $extras .
2771 * @return ARRAY|BOOL|MIXED|STRING
2772 */
2773 public function ultp_allowed_html_tags( $extras = array() ) {
2774 $allowed = array(
2775 'a' => array(
2776 'href' => true,
2777 'title' => true,
2778 ),
2779 'abbr' => array(
2780 'title' => true,
2781 ),
2782 'b' => array(),
2783 'br' => array(),
2784 'blockquote' => array(
2785 'cite' => true,
2786 ),
2787 'em' => array(),
2788 'i' => array(),
2789 'q' => array(
2790 'cite' => true,
2791 ),
2792 'strong' => array(
2793 'class' => true,
2794 'style' => true,
2795 ),
2796 'mark' => array(
2797 'class' => true,
2798 'style' => true,
2799 ),
2800 );
2801
2802 return array_merge( $allowed, $extras );
2803 }
2804
2805 /**
2806 * Allowed Block Tags
2807 *
2808 * @since v.4.0.2
2809 * @param STRING $search Optional. Tag name to check.
2810 * @return ARRAY|BOOL Returns array of allowed tags or bool if $search is provided.
2811 */
2812 public function ultp_allowed_block_tags( $search = '' ) {
2813 $array_lists = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span', 'p', 'div', 'section', 'article' );
2814 return $search ? in_array( $search, $array_lists ) : $array_lists;
2815 }
2816
2817 /**
2818 * Formats datasets for html
2819 *
2820 * @since v.4.0.2
2821 *
2822 * @param ARRAY $datasets .
2823 * @return STRING
2824 */
2825 public function get_formatted_datasets( &$datasets ) {
2826 $res = '';
2827 foreach ( $datasets as $key => $value ) {
2828 $res .= ' data-' . $key . '="' . $value . '" ';
2829 }
2830 return $res;
2831 }
2832
2833 /**
2834 * Sanitizes attributes after running necessary checks
2835 *
2836 * @since v.4.1.0
2837 *
2838 * @param ARRAY $attr The attributes array to sanitize.
2839 * @param STRING $key The key to check in the attributes array.
2840 * @param callable|null $sanitize_callback Callback function to sanitize the value.
2841 * @param MIXED $def_value Default value to return if key is not set.
2842 * @return MIXED Sanitized value or default value.
2843 */
2844 public function sanitize_attr( &$attr, $key, $sanitize_callback = null, $def_value = '' ) {
2845 return isset( $attr[ $key ] ) && $attr[ $key ] ?
2846 (
2847 $sanitize_callback ?
2848 $sanitize_callback( $attr[ $key ] ) :
2849 $attr[ $key ]
2850 )
2851 : $def_value;
2852 }
2853
2854 /**
2855 * Checks if dynamic content is active
2856 *
2857 * @since v.4.1.1
2858 *
2859 * @param ARRAY $attr The attributes to check for dynamic content.
2860 * @return BOOLEAN
2861 */
2862 public function is_dc_active( &$attr ) {
2863 if ( class_exists( '\ULTP\DCService' ) ) {
2864 return \ULTP\DCService::is_dc_active( $attr );
2865 }
2866 return false;
2867 }
2868
2869
2870 /**
2871 * Checks all the taxonomy of a post type for a given slug. Returns the taxonomy
2872 * if it exists.
2873 *
2874 * @since v.4.1.16
2875 *
2876 * @param STRING $post_type The post type.
2877 * @param STRING $slug The slug.
2878 * @return STRING|NULL The taxonomy name or null if not found.
2879 */
2880 public function get_taxonomy_by_term_slug( $post_type, $slug ) {
2881 $taxonomies = get_object_taxonomies( $post_type );
2882 foreach ( $taxonomies as $taxonomy ) {
2883 $res = get_term_by( 'slug', $slug, $taxonomy );
2884
2885 if ( ! empty( $res ) ) {
2886 return $taxonomy;
2887 }
2888 }
2889
2890 return null;
2891 }
2892 /**
2893 * Resolve Icon Alias
2894 *
2895 * @since v.4.0.0
2896 * @param STRING $icon_name The icon name or alias to resolve.
2897 * @return STRING|FALSE Returns the resolved icon name or false if no alias found.
2898 */
2899 public function svg_icon_compatibility( $icon_name = '' ) {
2900 if ( empty( $icon_name ) ) {
2901 return 'warning_triangle_solid';
2902 }
2903 // Get icon aliases mapping
2904 $icon_aliases = array(
2905 // Arrow aliases
2906 'angle_bottom_left_line' => 'arrow_down_bottom_left_solid',
2907 'angle_bottom_right_line' => 'arrow_down_bottom_right_solid',
2908 'angle_top_left_line' => 'arrow_up_top_left_solid',
2909 'angle_top_right_line' => 'arrow_up_top_right_solid',
2910 'rightFillAngle' => 'right_triangle_angle_play_arrow_forward_solid',
2911 'leftAngle2' => 'arrow_left_previous_backward_chevron_line',
2912 'rightAngle2' => 'arrow_right_next_forward_chevron_line',
2913 'collapse_bottom_line' => 'arrow_down_dropdown_maximize_chevron_line',
2914 'arrowUp2' => 'arrow_up_dropdown_minimize_chevron_line',
2915 'longArrowUp2' => 'long_arrow_up_top_increase_solid',
2916
2917 // Circle arrow aliases
2918 'arrow_left_circle_line' => 'arrow_left_backward_circle_line',
2919 'arrow_bottom_circle_line' => 'arrow_down_bottom_downward_circle_line',
2920 'arrow_right_circle_line' => 'arrow_right_forward_circle_line',
2921 'arrow_top_circle_line' => 'arrow_up_top_upward_circle_line',
2922
2923 // Close/Cross aliases
2924 'close_circle_line' => 'cross_close_x_minimize_circle_line',
2925 'close_line' => 'cross_x_close_minimize_line',
2926
2927 // Direction aliases
2928 'arrow_down_line' => 'arrow_down_bottom_downward_line',
2929 'leftArrowLg' => 'arrow_left_backward_line',
2930 'rightArrowLg' => 'arrow_left_forward_line',
2931 'arrow_up_line' => 'long_arrow_up_top_increase_line',
2932
2933 // Solid direction aliases
2934 'down_solid' => 'arrow_down_bottom_downward_circle_solid',
2935 'right_solid' => 'arrow_right_forward_circle_solid',
2936 'left_solid' => 'arrow_left_backward_circle_solid',
2937 'up_solid' => 'arrow_up_top_upward_circle_solid',
2938
2939 // Move aliases
2940 'bottom_right_line' => 'arrow_move_up_right_line',
2941 'bottom_left_line' => 'arrow_move_up_left_line',
2942 'top_left_angle_line' => 'arrow_move_down_left_line',
2943 'top_right_line' => 'arrow_move_down_right_line',
2944
2945 // Utility aliases
2946 'at_line' => 'at_a_mail_line',
2947 'refresh' => 'refresh_reset_cycle_loop_infinity_line',
2948 'cart_line' => 'shopping_cart_line',
2949 'cart_solid' => 'add_plus_shopping_cart_solid',
2950 'cog_line' => 'settings_tool_function_line',
2951 'cog_solid' => 'settings_tool_function_solid',
2952 'clock' => 'clock_reading_time_1_line',
2953 'book' => 'book_line',
2954 'download_line' => 'download_1_line',
2955 'download_solid' => 'download_1_solid',
2956 'downlod_bottom_solid' => 'download_1_solid',
2957
2958 // Visibility aliases
2959 'eye' => 'view_count_show_visible_eye_open_2_line',
2960 'hidden_line' => 'hidden_hide_invisible_line',
2961
2962 // Location aliases
2963 'home_line' => 'home_house_line',
2964 'home_solid' => 'home_house_solid',
2965 'location_line' => 'location_gps_map_line',
2966 'location_solid' => 'location_gps_map_solid',
2967
2968 // Emotion aliases
2969 'love_line' => 'heart_love_wishlist_favourite_line',
2970 'love_solid' => 'heart_love_wishlist_favourite_solid',
2971
2972 // Media aliases
2973 'play_line' => 'play_media_video_circle_line',
2974 'videoplay' => 'right_triangle_angle_play_arrow_forward_solid',
2975 'left_angle_solid' => 'left_triangle_angle_arrow_backward_solid',
2976
2977 // Shape aliases
2978 'caretArrow' => 'caret_up_top_triangle_angle_arrow_upward_solid',
2979 'rectangle_solid' => 'square_rounded_solid',
2980 'triangle_solid' => 'triangle_shape_solid',
2981
2982 // Status aliases
2983 'restriction_line' => 'restriction_no_stop_line',
2984 'right_circle_line' => 'correct_save_check_circle_line',
2985 'save_line' => 'correct_save_check_line',
2986 'search_line' => 'search_magnify_line',
2987 'search_solid' => 'search_magnify_solid',
2988
2989 // Warning aliases
2990 'notice_circle_solid' => 'warning_circle_solid',
2991 'notice_solid' => 'warning_triangle_solid',
2992 'warning_circle_line' => 'warning_circle_line',
2993 'warning_triangle_line' => 'warning_triangle_line',
2994
2995 // Category aliases
2996 'cat1' => 'category_file_documents_1_solid',
2997 'cat2' => 'category_book_line',
2998 'cat3' => 'category_file_documents_2_line',
2999 'cat4' => 'category_file_documents_3_line',
3000 'cat5' => 'category_file_documents_3_solid',
3001 'cat6' => 'category_file_documents_4_line',
3002 'cat7' => 'category_book_line',
3003
3004 // Comment aliases
3005 'commentCount1' => 'messege_comment_1_line',
3006 'commentCount2' => 'messege_comment_3_solid',
3007 'commentCount3' => 'messege_comment_3_line',
3008 'commentCount4' => 'messege_comment_6_line',
3009 'commentCount5' => 'messege_comment_7_line',
3010 'commentCount6' => 'messege_comment_8_line',
3011 'comment' => 'messege_comment_4_line',
3012
3013 // Date aliases
3014 'date1' => 'calendar_date_4_line',
3015 'date2' => 'calendar_date_1_solid',
3016 'date3' => 'calendar_date_2_line',
3017 'date4' => 'calendar_date_4_solid',
3018 'date5' => 'calendar_date_3_line',
3019 'calendar' => 'calendar_date_3_line',
3020
3021 // Reading time aliases
3022 'readingTime1' => 'clock_reading_time_3_line',
3023 'readingTime2' => 'clock_reading_time_2_line',
3024 'readingTime3' => 'book_reading_time_line',
3025 'readingTime4' => 'clock_reading_time_1_line',
3026 'readingTime5' => 'hourglass_timer_time_line',
3027
3028 // Tag aliases
3029 'tag1' => 'tag_bookmark_save_favourite_mark_discount_sale_line',
3030 'tag2' => 'price_tag_label_category_sale_discount_solid',
3031 'tag3' => 'price_tag_label_category_sale_discount_line',
3032 'tag4' => 'price_tag_offer_sale_coupon_solid',
3033 'tag5' => 'price_tag_label_category_sale_discount_line',
3034 'tag6' => 'growth_increase_up_solid',
3035
3036 // View count aliases
3037 'viewCount1' => 'view_count_show_visible_eye_open_1_line',
3038 'viewCount2' => 'view_count_show_visible_eye_open_2_line',
3039 'viewCount3' => 'view_count_show_visible_eye_open_3_line',
3040 'viewCount4' => 'view_count_show_visible_eye_open_4_solid',
3041 'viewCount5' => 'view_count_show_visible_eye_open_5_solid',
3042 'viewCount6' => 'view_count_show_visible_eye_open_5_solid',
3043
3044 // Author aliases
3045 'author1' => 'author_user_human_1_line',
3046 'author2' => 'author_user_human_4_line',
3047 'author3' => 'author_user_human_4_solid',
3048 'author4' => 'author_user_human_4_line',
3049 'author5' => 'author_user_human_3_solid',
3050 'author6' => 'author_user_human_6_line',
3051 'user' => 'author_user_human_3_line',
3052
3053 // Device aliases
3054 'desktop' => 'desktop_monitor_computer_line',
3055 'laptop' => 'laptop_computer_line',
3056 'tablet' => 'tablet_ipad_pad_line',
3057 'mobile' => 'mobile_smartphone_phone_line',
3058
3059 // Emoji aliases
3060 'angry_line' => 'angry_emoji_line',
3061 'angry_solid' => 'angry_emoji_solid',
3062 'confused_line' => 'confused_emoji_line',
3063 'confused_solid' => 'confused_emoji_solid',
3064 'happy_line' => 'happy_emoji_line',
3065 'happy_solid' => 'happy_emoji_solid',
3066 'smile_line' => 'smile_emoji_line',
3067 'smile_solid' => 'smile_emoji_solid',
3068
3069 // Social aliases
3070 'share_line' => 'social_community_line',
3071 'share' => 'share_social_solid',
3072 'apple_solid' => 'apple_logo_icon_solid',
3073 'android_solid' => 'android_logo_icon_solid',
3074 'google_solid' => 'google_logo_icon_solid',
3075 'messenger' => 'messenger_logo_icon_solid',
3076 'microsoft_solid' => 'microsoft_logo_icon_solid',
3077 'mail' => 'mail_email_messege_solid',
3078 'facebook' => 'facebook_logo_icon_solid',
3079 'twitter' => 'twitter_x_logo_icon_line',
3080 'link' => 'link_chains_line',
3081
3082 // Misc aliases
3083 'media_document' => 'media_document',
3084 'arrowDown2' => 'arrow_down_dropdown_maximize_chevron_line',
3085 'setting' => 'settings_tool_function_solid',
3086 'upload_solid' => 'upload_1_solid',
3087
3088 // Empty aliases for missing icons (return empty string)
3089 'correct_solid' => 'correct_save_check_circle_line',
3090 'dot_solid' => 'dot_circle_solid',
3091 'right_circle_solid' => 'correct_save_check_circle_solid',
3092 'full_screen' => 'full_screen_corners_out_solid',
3093 'zoom_in' => 'zoom_in_magnifying_glass_plus_line',
3094 'zoom_out' => 'zoom_out_magnifying_glass_minus_line',
3095 'gallery_indicator' => 'gallery_indicator_image_solid',
3096 'ascending' => 'sort_ascending_order_solid',
3097 'descending' => 'sort_descending_order_line',
3098 'unlink' => 'unlink_link_break_line',
3099 'rocket' => 'rocket_fly_boost_launch_pro_line',
3100 'unlock' => 'unlocked_open_security_solid',
3101 'connect' => 'plugin_connect_socket_integration_solid',
3102 'leftAngle' => 'arrow_left_previous_backward_chevron_line',
3103 'rightAngle' => 'right_triangle_angle_play_arrow_forward_line',
3104 'plus2' => '',
3105 'hamicon_1' => 'left_align_1_line',
3106 // extra in assets\img\iconpack folder
3107 'hamicon_2' => 'hemicon_2_line',
3108 'hamicon_3' => 'hemicon_3_line',
3109 'hamicon_4' => 'hamicon_5_line',
3110 'hamicon_5' => 'hamicon_4_sloid',
3111 'hamicon_6' => 'hamicon_6_line',
3112 'instagram_solid' => 'instagram_logo_icon_solid',
3113 'linkedin' => 'linkedin_logo_icon_solid',
3114 'pause_solid' => 'pause_solid',
3115 'pinterest' => 'pinterest_logo_icon_solid',
3116 'reddit' => 'reddit_logo_icon_solid',
3117 'skype' => 'skype_logo_icon_solid',
3118 'tiktok_lite_solid' => 'tiktok_logo_icon_line',
3119 'tiktok_solid' => 'tiktok_logo_icon_circle_solid',
3120 'whatsapp' => 'whatsapp_logo_icon_solid',
3121 'wordpress_lite_solid' => 'wordpress_logo_icon_solid',
3122 'wordpress_solid' => 'wordpress_logo_icon_2_solid',
3123 'wrong_solid' => 'cross_close_x_minimize_circle_solid',
3124 'youtube_solid' => 'youtube_logo_icon_solid',
3125 'five_star_line' => 'star_rating_line',
3126 'rightAngleBold' => 'arrow_right_next_forward_chevron_line',
3127 'leftAngleBold' => 'arrow_left_previous_backward_chevron_line',
3128 'plus' => 'plus',
3129 'reset_left_line' => 'refresh_reset_cycle_loop_infinity_line',
3130 );
3131 // Return resolved alias or false if not found
3132 return isset( $icon_aliases[ $icon_name ] ) ? $icon_aliases[ $icon_name ] : $icon_name;
3133 }
3134 }
3135