PluginProbe
Ultimate Post Kit / trunk
Ultimate Post Kit vtrunk
4.2.1 4.2.2 4.2.3 4.5.0 4.5.2 4.5.3 4.2.0 4.1.18 4.1.17 4.1.16 4.1.15 4.1.14 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.0.9 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 All 145 releases
ultimate-post-kit / includes / helper.php

helper.php in Ultimate Post Kit trunk, at includes/helper.php

1,110 lines 31.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use UltimatePostKit\Ultimate_Post_Kit_Loader;
4 use Elementor\Plugin;
5
6 if (!defined('ABSPATH')) {
7 exit; // Exit if accessed directly.
8 }
9
10 /**
11 * You can easily add white label branding for for extended license or multi site license.
12 * Don't try for regular license otherwise your license will be invalid.
13 * return white label
14 */
15
16 /**
17 * You can easily add white label branding for for extended license or multi site license.
18 * Don't try for regular license otherwise your license will be invalid.
19 * return white label
20 */
21 define( 'BDTUPK_PNAME', basename( dirname( BDTUPK__FILE__ ) ) );
22 define( 'BDTUPK_PBNAME', plugin_basename( BDTUPK__FILE__ ) );
23 define( 'BDTUPK_PATH', plugin_dir_path( BDTUPK__FILE__ ) );
24 define( 'BDTUPK_URL', plugins_url( '/', BDTUPK__FILE__ ) );
25 define( 'BDTUPK_ADMIN_PATH', BDTUPK_PATH . 'admin/' );
26 define( 'BDTUPK_ADMIN_URL', BDTUPK_URL . 'admin/' );
27 define( 'BDTUPK_ADMIN_ASSETS_PATH', BDTUPK_PATH . 'admin/assets/' );
28 define( 'BDTUPK_ADMIN_ASSETS_URL', BDTUPK_URL . 'admin/assets/' );
29 define( 'BDTUPK_MODULES_PATH', BDTUPK_PATH . 'modules/' );
30 define( 'BDTUPK_INC_PATH', BDTUPK_PATH . 'includes/' );
31 define( 'BDTUPK_ASSETS_URL', BDTUPK_URL . 'assets/' );
32 define( 'BDTUPK_ASSETS_PATH', BDTUPK_PATH . 'assets/' );
33 define( 'BDTUPK_MODULES_URL', BDTUPK_URL . 'modules/' );
34
35
36 if ( ! defined( 'BDTUPK' ) ) {
37 define( 'BDTUPK', '' );
38 } //Add prefix for all widgets <span class="upk-widget-badge"></span>
39 if ( ! defined( 'BDTUPK_CP' ) ) {
40 define( 'BDTUPK_CP', '<span class="upk-widget-badge"></span>' );
41 } //Add prefix for all widgets <span class="upk-widget-badge"></span>
42 if ( ! defined( 'BDTUPK_NC' ) ) {
43 define( 'BDTUPK_NC', '<span class="upk-new-control"></span>' );
44 } //Add prefix for all widgets <span class="upk-widget-badge"></span>
45 if ( ! defined( 'BDTUPK_UC' ) ) {
46 define( 'BDTUPK_UC', '<span class="upk-updated-control"></span>' );
47 } // if you have any custom style
48
49 if ( _is_upk_pro_activated() ) {
50 if ( ! defined( 'BDTUPK_PC' ) ) {
51 define( 'BDTUPK_PC', '' );
52 } // pro control badge
53 if ( ! defined( 'BDTUPK_SLUG' ) ) {
54 define( 'BDTUPK_SLUG', 'ultimate-post-kit' );
55 } // set your own alias
56 if ( ! defined( 'BDTUPK_TITLE' ) ) {
57 define( 'BDTUPK_TITLE', 'Ultimate Post Kit' );
58 } // Set your own name for plugin
59 define( 'BDTUPK_IS_PC', '' );
60 } else {
61 if ( ! defined( 'BDTUPK_PC' ) ) {
62 define( 'BDTUPK_PC', '<span class="upk-pro-control"></span>' );
63 } // pro control badge
64 if ( ! defined( 'BDTUPK_SLUG' ) ) {
65 define( 'BDTUPK_SLUG', 'ultimate-post-kit' );
66 } // set your own alias
67 if ( ! defined( 'BDTUPK_TITLE' ) ) {
68 define( 'BDTUPK_TITLE', 'Ultimate Post Kit' );
69 } // Set your own name for plugin
70 define( 'BDTUPK_IS_PC', 'upk-disabled-control' );
71 }
72
73 function ultimate_post_kit_is_edit() {
74 return Plugin::$instance->editor->is_edit_mode();
75 }
76
77 function ultimate_post_kit_is_preview() {
78 return Plugin::$instance->preview->is_preview_mode();
79 }
80
81 // add socials list meta in user profile
82 function ultimate_post_kit_user_contact_methods( $methods, $core = false ) {
83
84 if ( $core ) {
85 $methods['email'] = __( 'Email', 'ultimate-post-kit' );
86 $methods['url'] = __( 'Website', 'ultimate-post-kit' );
87 }
88
89 $methods['facebook'] = __( 'Facebook', 'ultimate-post-kit' );
90 $methods['twitter'] = __( 'Twitter', 'ultimate-post-kit' );
91 $methods['linkedin'] = __( 'LinkedIn', 'ultimate-post-kit' );
92 $methods['github'] = __( 'GitHub', 'ultimate-post-kit' );
93 $methods['wordpress'] = __( 'WordPress', 'ultimate-post-kit' );
94 $methods['dribbble'] = __( 'Dribbble', 'ultimate-post-kit' );
95
96 return $methods;
97 }
98
99 add_filter( 'user_contactmethods', 'ultimate_post_kit_user_contact_methods' );
100
101 /**
102 * Show any alert by this function
103 *
104 * @param mixed $message [description]
105 * @param class prefix $type [description]
106 * @param boolean $close [description]
107 *
108 * @return helper [description]
109 */
110 function ultimate_post_kit_alert( $message, $type = 'warning', $close = true ) {
111 ?>
112 <div class="upk-alert-<?php echo esc_attr( $type ); ?>" data-upk-alert>
113 <?php if ( $close ) : ?>
114 <a class="upk-alert-close" data-upk-close></a>
115 <?php endif; ?>
116 <?php echo wp_kses_post( $message ); ?>
117 </div>
118 <?php
119 }
120
121 function ultimate_post_kit_get_alert( $message, $type = 'warning', $close = true ) {
122
123 $output = '<div class="upk-alert-' . $type . '" upk-alert>';
124 if ( $close ) :
125 $output .= '<a class="upk-alert-close" data-upk-close></a>';
126 endif;
127 $output .= wp_kses_post( $message );
128 $output .= '</div>';
129
130 return $output;
131 }
132
133 /**
134 * all array css classes will output as proper space
135 *
136 * @param array $classes shortcode css class as array
137 *
138 * @return array string
139 */
140
141 function ultimate_post_kit_get_post_types( $args = [] ) {
142
143 $post_type_args = [
144 'show_in_nav_menus' => true,
145 ];
146
147 if ( ! empty( $args['post_type'] ) ) {
148 $post_type_args['name'] = $args['post_type'];
149 }
150
151 $_post_types = get_post_types( $post_type_args, 'objects' );
152
153 $post_types = [ '0' => esc_html__( 'Select Type', 'ultimate-post-kit' ) ];
154
155 foreach ( $_post_types as $post_type => $object ) {
156 $post_types[ $post_type ] = $object->label;
157 }
158
159 return $post_types;
160 }
161
162 function ultimate_post_kit_get_taxonomies() {
163 $args = array(
164 'public' => true,
165 //'_builtin' => false
166
167 );
168 $output = [ '0' => esc_html__( 'Select Type', 'ultimate-post-kit' ) ];
169 $tax_output = 'objects'; // or objects
170 $taxonomies = get_taxonomies( $args, $tax_output );
171 if ( $taxonomies ) {
172 foreach ( $taxonomies as $taxonomy ) {
173 $taxonomy_label = $taxonomy->label ? $taxonomy->label : $taxonomy->name;
174 $term_count = wp_count_terms(
175 [
176 'taxonomy' => $taxonomy->name,
177 'hide_empty' => false,
178 ]
179 );
180
181 if ( is_wp_error( $term_count ) ) {
182 $term_count = 0;
183 }
184
185 $output[ $taxonomy->name ] = sprintf(
186 '%s (%d)',
187 $taxonomy_label,
188 (int) $term_count
189 );
190 }
191 }
192
193 return $output;
194 }
195
196 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
197 function upk_get_category( $post_type ) {
198 switch ( $post_type ) {
199 case 'campaign':
200 $taxonomy = 'campaign_category';
201 break;
202 case 'lightbox_library':
203 $taxonomy = 'ngg_tag';
204 break;
205 case 'give_forms':
206 $taxonomy = 'give_forms_category';
207 break;
208 case 'tribe_events':
209 $taxonomy = 'tribe_events_cat';
210 break;
211 case 'product':
212 $taxonomy = 'product_cat';
213 break;
214 default:
215 $taxonomy = 'category';
216 break;
217 }
218
219 $categories = get_the_terms( get_the_ID(), $taxonomy );
220 $_categories = [];
221 if ( $categories && !is_wp_error( $categories ) ) {
222 foreach ( $categories as $category ) {
223 // Ensure $category is an object, not an array
224 if ( is_object( $category ) && isset( $category->term_id, $category->name, $category->slug ) ) {
225 $link = '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '"
226 aria-label="' . esc_attr( 'Category ' . $category->name ) . '">'
227 . esc_html( $category->name ) .
228 '</a>';
229
230 $_categories[ $category->slug ] = $link;
231 }
232 }
233 }
234 return implode( ' ', $_categories );
235 }
236
237
238 function ultimate_post_kit_allow_tags( ?string $tag = null ) {
239 $tag_allowed = wp_kses_allowed_html( 'post' );
240
241 $tag_allowed['input'] = [
242 'class' => [],
243 'id' => [],
244 'name' => [],
245 'value' => [],
246 'checked' => [],
247 'type' => [],
248 ];
249 $tag_allowed['select'] = [
250 'class' => [],
251 'id' => [],
252 'name' => [],
253 'value' => [],
254 'multiple' => [],
255 'type' => [],
256 ];
257 $tag_allowed['option'] = [
258 'value' => [],
259 'selected' => [],
260 ];
261
262 $tag_allowed['title'] = [
263 'a' => [
264 'href' => [],
265 'title' => [],
266 'class' => [],
267 ],
268 'br' => [],
269 'em' => [],
270 'strong' => [],
271 'hr' => [],
272 ];
273
274 $tag_allowed['text'] = [
275 'a' => [
276 'href' => [],
277 'title' => [],
278 'class' => [],
279 ],
280 'br' => [],
281 'em' => [],
282 'strong' => [],
283 'hr' => [],
284 'i' => [
285 'class' => [],
286 ],
287 'span' => [
288 'class' => [],
289 ],
290 ];
291
292 $tag_allowed['svg'] = [
293 'svg' => [
294 'version' => [],
295 'xmlns' => [],
296 'viewbox' => [],
297 'xml:space' => [],
298 'xmlns:xlink' => [],
299 'x' => [],
300 'y' => [],
301 'style' => [],
302 ],
303 'g' => [],
304 'path' => [
305 'class' => [],
306 'd' => [],
307 ],
308 'ellipse' => [
309 'class' => [],
310 'cx' => [],
311 'cy' => [],
312 'rx' => [],
313 'ry' => [],
314 ],
315 'circle' => [
316 'class' => [],
317 'cx' => [],
318 'cy' => [],
319 'r' => [],
320 ],
321 'rect' => [
322 'x' => [],
323 'y' => [],
324 'transform' => [],
325 'height' => [],
326 'width' => [],
327 'class' => [],
328 ],
329 'line' => [
330 'class' => [],
331 'x1' => [],
332 'x2' => [],
333 'y1' => [],
334 'y2' => [],
335 ],
336 'style' => [],
337
338
339 ];
340
341 if ( $tag == null ) {
342 return $tag_allowed;
343 } elseif ( is_array( $tag ) ) {
344 $new_tag_allow = [];
345
346 foreach ( $tag as $_tag ) {
347 $new_tag_allow[ $_tag ] = $tag_allowed[ $_tag ];
348 }
349
350 return $new_tag_allow;
351 } else {
352 return isset( $tag_allowed[ $tag ] ) ? $tag_allowed[ $tag ] : [];
353 }
354 }
355
356 /**
357 * HexColor
358 */
359 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
360 function strToHex( $string, $steps = -10 ) {
361
362 if ( empty( $string ) ) {
363 return false;
364 }
365
366 $hex_output = sprintf( '%s', substr( md5( $string ), 0, 6 ) );
367
368 // Steps should be between -255 and 255. Negative = darker, positive = lighter
369 $steps = max( -255, min( 255, $steps ) );
370
371 // Split into three parts: R, G and B
372 $color_parts = str_split( $hex_output, 2 );
373 $output = '#';
374
375 foreach ( $color_parts as $color ) {
376 $color = hexdec( $color ); // Convert to decimal
377 $color = max( 0, min( 255, $color + $steps ) ); // Adjust color
378 $output .= str_pad( dechex( $color ), 2, '0', STR_PAD_LEFT ); // Make two char hex code
379 }
380
381 return strToUpper( $output );
382 }
383
384 /**
385 * Get the current paged number for a custom WP_Query instance.
386 *
387 * @param \WP_Query $wp_query Query object.
388 * @return int Current page number.
389 */
390 function ultimate_post_kit_get_query_paged( $wp_query ) {
391 if ( ! $wp_query instanceof \WP_Query ) {
392 return 1;
393 }
394
395 $paged_from_query = isset( $wp_query->query_vars['paged'] ) ? (int) $wp_query->query_vars['paged'] : 0;
396 $page_from_query = isset( $wp_query->query_vars['page'] ) ? (int) $wp_query->query_vars['page'] : 0;
397
398 if ( is_front_page() ) {
399 $paged = max( get_query_var( 'page' ), get_query_var( 'paged' ), $paged_from_query, $page_from_query );
400 } else {
401 $paged = max( get_query_var( 'paged' ), $paged_from_query );
402 }
403
404 return max( 1, (int) $paged );
405 }
406
407 /**
408 * Get item counter offset for paginated query loops.
409 *
410 * @param \WP_Query $wp_query Query object.
411 * @return int Zero-based offset for the first item on the current page.
412 */
413 function ultimate_post_kit_get_query_counter_offset( $wp_query ) {
414 if ( ! $wp_query instanceof \WP_Query ) {
415 return 0;
416 }
417
418 $paged = ultimate_post_kit_get_query_paged( $wp_query );
419 $posts_per_page = (int) $wp_query->get( 'posts_per_page' );
420
421 if ( 1 >= $paged || 0 >= $posts_per_page ) {
422 return 0;
423 }
424
425 return ( $paged - 1 ) * $posts_per_page;
426 }
427
428 function ultimate_post_kit_post_pagination( $wp_query, $widget_id = '' ) {
429
430 /** Stop execution if there's only 1 page */
431 if ( $wp_query->max_num_pages <= 1 ) {
432 return;
433 }
434
435 $paged = ultimate_post_kit_get_query_paged( $wp_query );
436 $max = (int) $wp_query->max_num_pages;
437
438 /** Add current page to the array */
439 if ( $paged >= 1 ) {
440 $links[] = $paged;
441 }
442
443 /** Add the pages around the current page to the array */
444 if ( $paged >= 3 ) {
445 $links[] = $paged - 1;
446 $links[] = $paged - 2;
447 }
448
449 if ( ( $paged + 2 ) <= $max ) {
450 $links[] = $paged + 2;
451 $links[] = $paged + 1;
452 }
453
454 printf( '<ul class="upk-pagination" data-widget-id="%s">' . "\n", esc_attr($widget_id) );
455
456 /** Previous Post Link */
457 if ( $paged > 1 ) {
458 $prev_page = $paged - 1;
459 if ( is_front_page() && $prev_page == 1 ) {
460 $prev_link = home_url( '/' );
461 } else {
462 $prev_link = get_pagenum_link( $prev_page );
463 }
464 printf( '<li class="upk-pagination-previous"><a href="%s" aria-label="' . esc_attr__( 'Previous Page', 'ultimate-post-kit' ) . '"><span data-upk-pagination-previous><i class="upk-icon-arrow-left-5" aria-hidden="true"></i></span></a></li>' . "\n", esc_url( $prev_link ) );
465 }
466
467 /** Link to first page, plus ellipses if necessary */
468 if ( ! in_array( 1, $links ) ) {
469 $class = 1 == $paged ? ' class="current"' : '';
470
471 // For page 1, always use home URL on front page, otherwise use get_pagenum_link
472 if ( is_front_page() ) {
473 $page_link = home_url( '/' );
474 } else {
475 $page_link = get_pagenum_link( 1 );
476 }
477
478 printf( '<li%s><a href="%s">%s</a></li>' . "\n", wp_kses_post($class), esc_url( $page_link ), '1' );
479
480 if ( ! in_array( 2, $links ) ) {
481 echo '<li class="upk-pagination-dot-dot"><span>...</span></li>';
482 }
483 }
484
485 /** Link to current page, plus 2 pages in either direction if necessary */
486 sort( $links );
487 foreach ( (array) $links as $link ) {
488 $class = $paged == $link ? ' class="upk-active"' : '';
489
490 // Use appropriate page link for front page vs other pages
491 if ( is_front_page() && $link == 1 ) {
492 $page_link = home_url( '/' );
493 } else {
494 $page_link = get_pagenum_link( $link );
495 }
496
497 printf( '<li%s><a href="%s">%s</a></li>' . "\n", wp_kses_post($class), esc_url( $page_link ), wp_kses_post($link) );
498 }
499
500 /** Link to last page, plus ellipses if necessary */
501 if ( ! in_array( $max, $links ) ) {
502 if ( ! in_array( $max - 1, $links ) ) {
503 echo '<li class="upk-pagination-dot-dot"><span>...</span></li>' . "\n";
504 }
505
506 $class = $paged == $max ? ' class="upk-active"' : '';
507 $page_link = get_pagenum_link( $max );
508
509 printf( '<li%s><a href="%s">%s</a></li>' . "\n", wp_kses_post($class), esc_url( $page_link ), wp_kses_post($max) );
510 }
511
512 /** Next Post Link */
513 if ( $paged < $max ) {
514 $next_page = $paged + 1;
515 $next_link = get_pagenum_link( $next_page );
516 printf( '<li class="upk-pagination-next"><a href="%s" aria-label="' . esc_attr__( 'Next Page', 'ultimate-post-kit' ) . '"><span data-upk-pagination-next><i class="upk-icon-arrow-right-5" aria-hidden="true"></i></span></a></li>' . "\n", esc_url( $next_link ) );
517 }
518
519 echo '</ul>' . "\n";
520 }
521
522 function ultimate_post_kit_template_edit_link( $template_id ) {
523 if ( Ultimate_Post_Kit_Loader::elementor()->editor->is_edit_mode() ) {
524
525 $final_url = add_query_arg( [ 'elementor' => '' ], get_permalink( $template_id ) );
526
527 $output = sprintf( '<a class="upk-elementor-template-edit-link" href="%s" title="%s" target="_blank"><i class="eicon-edit"></i></a>', esc_url( $final_url ), esc_html__( 'Edit Template', 'ultimate-post-kit' ) );
528
529 return $output;
530 }
531 }
532
533 function ultimate_post_kit_time_diff( $from, $to = '' ) {
534 $diff = human_time_diff( $from, $to );
535 $replace = array(
536 ' hour' => 'h',
537 ' hours' => 'h',
538 ' day' => 'd',
539 ' days' => 'd',
540 ' minute' => 'm',
541 ' minutes' => 'm',
542 ' second' => 's',
543 ' seconds' => 's',
544 );
545
546 return strtr( $diff, $replace );
547 }
548
549 function ultimate_post_kit_post_time_diff( $format = '' ) {
550 $displayAgo = esc_html__( 'ago', 'ultimate-post-kit' );
551 $post_time = get_the_time( 'U' );
552 $current_time = current_time( 'timestamp' );
553
554 if ( $format == 'short' ) {
555 $output = ultimate_post_kit_time_diff( $post_time, $current_time );
556 } else {
557 $output = human_time_diff( $post_time, $current_time );
558 }
559
560 $output = $output . ' ' . $displayAgo;
561
562 return $output;
563 }
564
565 function ultimate_post_kit_iso_time( $time ) {
566 $current_offset = (float) get_option( 'gmt_offset' );
567 $timezone_string = get_option( 'timezone_string' );
568
569 // Create a UTC+- zone if no timezone string exists.
570 //if ( empty( $timezone_string ) ) {
571 if ( 0 === $current_offset ) {
572 $timezone_string = '+00:00';
573 } elseif ( $current_offset < 0 ) {
574 $timezone_string = $current_offset . ':00';
575 } else {
576 $timezone_string = '+0' . $current_offset . ':00';
577 }
578 //}
579
580 $sub_time = [];
581 $sub_time = explode( " ", $time );
582 $final_time = $sub_time[0] . 'T' . $sub_time[1] . ':00' . $timezone_string;
583
584 return $final_time;
585 }
586
587 /**
588 * @return array
589 */
590 function ultimate_post_kit_get_menu() {
591
592 $menus = wp_get_nav_menus();
593 $items = [ 0 => esc_html__( 'Select Menu', 'ultimate-post-kit' ) ];
594 foreach ( $menus as $menu ) {
595 $items[ $menu->slug ] = $menu->name;
596 }
597
598 return $items;
599 }
600
601 /**
602 * default get_option() default value check
603 *
604 * @param string $option settings field name
605 * @param string $section the section name this field belongs to
606 * @param string $default default text if it's not found
607 *
608 * @return mixed
609 */
610 function ultimate_post_kit_option( $option, $section, $default = '' ) {
611
612 $options = get_option( $section );
613
614 if ( isset( $options[ $option ] ) ) {
615 return $options[ $option ];
616 }
617
618 return $default;
619 }
620
621 /**
622 * @return array of elementor template
623 */
624 function ultimate_post_kit_et_options() {
625
626 $templates = Ultimate_Post_Kit_Loader::elementor()->templates_manager->get_source( 'local' )->get_items();
627 $types = [];
628
629 if ( empty( $templates ) ) {
630 $template_options = [ '0' => __( 'Template Not Found!', 'ultimate-post-kit' ) ];
631 } else {
632 $template_options = [ '0' => __( 'Select Template', 'ultimate-post-kit' ) ];
633
634 foreach ( $templates as $template ) {
635 $template_options[ $template['template_id'] ] = $template['title'] . ' (' . $template['type'] . ')';
636 $types[ $template['template_id'] ] = $template['type'];
637 }
638 }
639
640 return $template_options;
641 }
642
643 /**
644 * @return array of wp default sidebars
645 */
646 function ultimate_post_kit_sidebar_options() {
647
648 global $wp_registered_sidebars;
649 $sidebar_options = [];
650
651 if ( ! $wp_registered_sidebars ) {
652 $sidebar_options[0] = esc_html__( 'No sidebars were found', 'ultimate-post-kit' );
653 } else {
654 $sidebar_options[0] = esc_html__( 'Select Sidebar', 'ultimate-post-kit' );
655
656 foreach ( $wp_registered_sidebars as $sidebar_id => $sidebar ) {
657 $sidebar_options[ $sidebar_id ] = $sidebar['name'];
658 }
659 }
660
661 return $sidebar_options;
662 }
663
664 /**
665 * @param string category name
666 *
667 * @return array of category
668 */
669 function ultimate_post_kit_get_category( $taxonomy = 'category' ) {
670
671 $post_options = [];
672
673 $post_categories = get_terms(
674 [
675 'taxonomy' => $taxonomy,
676 'hide_empty' => false,
677 ]
678 );
679
680 if ( is_wp_error( $post_categories ) ) {
681 return $post_options;
682 }
683
684 if ( false !== $post_categories and is_array( $post_categories ) ) {
685 foreach ( $post_categories as $category ) {
686 // Ensure $category is an object, not an array
687 if ( is_object( $category ) && isset( $category->slug, $category->name ) ) {
688 $post_options[ $category->slug ] = $category->name;
689 }
690 }
691 }
692
693 return $post_options;
694 }
695
696 /**
697 * @param array all ajax posted array there
698 *
699 * @return array return all setting as array
700 */
701 function ultimate_post_kit_ajax_settings( $settings ) {
702
703 $required_settings = [
704 'show_date' => true,
705 'show_comment' => true,
706 'show_link' => true,
707 'show_meta' => true,
708 'show_title' => true,
709 'show_excerpt' => true,
710 'show_lightbox' => true,
711 'show_thumbnail' => true,
712 'show_category' => false,
713 'show_tags' => false,
714 ];
715
716 foreach ( $settings as $key => $value ) {
717 if ( in_array( $key, $required_settings ) ) {
718 $required_settings[ $key ] = $value;
719 }
720 }
721
722 return $required_settings;
723 }
724
725 // BDT Blend Type
726 function ultimate_post_kit_blend_options() {
727 $blend_options = [
728 'multiply' => esc_html__( 'Multiply', 'ultimate-post-kit' ),
729 'screen' => esc_html__( 'Screen', 'ultimate-post-kit' ),
730 'overlay' => esc_html__( 'Overlay', 'ultimate-post-kit' ),
731 'darken' => esc_html__( 'Darken', 'ultimate-post-kit' ),
732 'lighten' => esc_html__( 'Lighten', 'ultimate-post-kit' ),
733 'color-dodge' => esc_html__( 'Color-Dodge', 'ultimate-post-kit' ),
734 'color-burn' => esc_html__( 'Color-Burn', 'ultimate-post-kit' ),
735 'hard-light' => esc_html__( 'Hard-Light', 'ultimate-post-kit' ),
736 'soft-light' => esc_html__( 'Soft-Light', 'ultimate-post-kit' ),
737 'difference' => esc_html__( 'Difference', 'ultimate-post-kit' ),
738 'exclusion' => esc_html__( 'Exclusion', 'ultimate-post-kit' ),
739 'hue' => esc_html__( 'Hue', 'ultimate-post-kit' ),
740 'saturation' => esc_html__( 'Saturation', 'ultimate-post-kit' ),
741 'color' => esc_html__( 'Color', 'ultimate-post-kit' ),
742 'luminosity' => esc_html__( 'Luminosity', 'ultimate-post-kit' ),
743 ];
744
745 return $blend_options;
746 }
747
748 // BDT Position
749 function ultimate_post_kit_position() {
750 $position_options = [
751 '' => esc_html__( 'Default', 'ultimate-post-kit' ),
752 'top-left' => esc_html__( 'Top Left', 'ultimate-post-kit' ),
753 'top-center' => esc_html__( 'Top Center', 'ultimate-post-kit' ),
754 'top-right' => esc_html__( 'Top Right', 'ultimate-post-kit' ),
755 'center' => esc_html__( 'Center', 'ultimate-post-kit' ),
756 'center-left' => esc_html__( 'Center Left', 'ultimate-post-kit' ),
757 'center-right' => esc_html__( 'Center Right', 'ultimate-post-kit' ),
758 'bottom-left' => esc_html__( 'Bottom Left', 'ultimate-post-kit' ),
759 'bottom-center' => esc_html__( 'Bottom Center', 'ultimate-post-kit' ),
760 'bottom-right' => esc_html__( 'Bottom Right', 'ultimate-post-kit' ),
761 ];
762
763 return $position_options;
764 }
765
766 // BDT Thumbnavs Position
767 function ultimate_post_kit_thumbnavs_position() {
768 $position_options = [
769 'top-left' => esc_html__( 'Top Left', 'ultimate-post-kit' ),
770 'top-center' => esc_html__( 'Top Center', 'ultimate-post-kit' ),
771 'top-right' => esc_html__( 'Top Right', 'ultimate-post-kit' ),
772 'center-left' => esc_html__( 'Center Left', 'ultimate-post-kit' ),
773 'center-right' => esc_html__( 'Center Right', 'ultimate-post-kit' ),
774 'bottom-left' => esc_html__( 'Bottom Left', 'ultimate-post-kit' ),
775 'bottom-center' => esc_html__( 'Bottom Center', 'ultimate-post-kit' ),
776 'bottom-right' => esc_html__( 'Bottom Right', 'ultimate-post-kit' ),
777 ];
778
779 return $position_options;
780 }
781
782 function ultimate_post_kit_navigation_position() {
783 $position_options = [
784 'top-left' => esc_html__( 'Top Left', 'ultimate-post-kit' ),
785 'top-center' => esc_html__( 'Top Center', 'ultimate-post-kit' ),
786 'top-right' => esc_html__( 'Top Right', 'ultimate-post-kit' ),
787 'center' => esc_html__( 'Center', 'ultimate-post-kit' ),
788 'center-left' => esc_html__( 'Center Left', 'ultimate-post-kit' ),
789 'center-right' => esc_html__( 'Center Right', 'ultimate-post-kit' ),
790 'bottom-left' => esc_html__( 'Bottom Left', 'ultimate-post-kit' ),
791 'bottom-center' => esc_html__( 'Bottom Center', 'ultimate-post-kit' ),
792 'bottom-right' => esc_html__( 'Bottom Right', 'ultimate-post-kit' ),
793 ];
794
795 return $position_options;
796 }
797
798
799 function ultimate_post_kit_pagination_position() {
800 $position_options = [
801 'top-left' => esc_html__( 'Top Left', 'ultimate-post-kit' ),
802 'top-center' => esc_html__( 'Top Center', 'ultimate-post-kit' ),
803 'top-right' => esc_html__( 'Top Right', 'ultimate-post-kit' ),
804 'center-left' => esc_html__( 'Center Left', 'ultimate-post-kit' ),
805 'center-right' => esc_html__( 'Center Right', 'ultimate-post-kit' ),
806 'bottom-left' => esc_html__( 'Bottom Left', 'ultimate-post-kit' ),
807 'bottom-center' => esc_html__( 'Bottom Center', 'ultimate-post-kit' ),
808 'bottom-right' => esc_html__( 'Bottom Right', 'ultimate-post-kit' ),
809 ];
810
811 return $position_options;
812 }
813
814 // Title Tags
815 function ultimate_post_kit_title_tags() {
816 $title_tags = [
817 'h1' => 'H1',
818 'h2' => 'H2',
819 'h3' => 'H3',
820 'h4' => 'H4',
821 'h5' => 'H5',
822 'h6' => 'H6',
823 'div' => 'div',
824 'span' => 'span',
825 'p' => 'p',
826 ];
827
828 return $title_tags;
829 }
830 function ultimate_post_kit_hide_on_class( $selectors ) {
831 $element_hide_on = '';
832 if ( ! empty( $selectors ) ) {
833 foreach ( $selectors as $element ) {
834
835 if ( $element == 'desktop' ) {
836 $element_hide_on .= ' upk-desktop';
837 }
838 if ( $element == 'tablet' ) {
839 $element_hide_on .= ' upk-tablet';
840 }
841 if ( $element == 'mobile' ) {
842 $element_hide_on .= ' upk-mobile';
843 }
844 }
845 }
846 return $element_hide_on;
847 }
848 function ultimate_post_kit_mask_shapes() {
849 $path = BDTUPK_ASSETS_URL . 'images/mask/';
850 $shape_name = 'shape';
851 $extension = '.svg';
852 $list = [ 0 => esc_html__( 'Select Mask', 'ultimate-post-kit' ) ];
853
854 for ( $i = 1; $i <= 20; $i++ ) {
855 $list[ $path . $shape_name . '-' . $i . $extension ] = ucwords( $shape_name . ' ' . $i );
856 }
857
858 return $list;
859 }
860
861 /**
862 * String to ID maker for any title to relavent id
863 * @param [type] string any title or string
864 * @return [type] [description]
865 */
866 function ultimate_post_kit_string_id( $string ) {
867 //Lower case everything
868 $string = strtolower( $string );
869 //Make alphanumeric (removes all other characters)
870 $string = preg_replace( "/[^a-z0-9_\s-]/", "", $string );
871 //Clean up multiple dashes or whitespaces
872 $string = preg_replace( "/[\s-]+/", " ", $string );
873 //Convert whitespaces and underscore to dash
874 $string = preg_replace( "/[\s_]/", "-", $string );
875
876 //finally return here
877 return $string;
878 }
879
880
881 function ultimate_post_kit_dashboard_link( $suffix = '#welcome' ) {
882 return add_query_arg( [ 'page' => 'ultimate_post_kit_options' . $suffix ], admin_url( 'admin.php' ) );
883 }
884
885 /**
886 * @param int $limit default limit is 25 word
887 * @param bool $strip_shortcode if you want to strip shortcode from excert text
888 * @param string $trail trail string default is ...
889 *
890 * @return string return custom limited excerpt text
891 */
892 function ultimate_post_kit_custom_excerpt( $limit = 25, $strip_shortcode = false, $trail = '' ) {
893
894 $output = get_the_content();
895
896 if ( $limit ) {
897 $output = wp_trim_words( $output, $limit, $trail );
898 }
899
900 if ( $strip_shortcode ) {
901 $output = strip_shortcodes( $output );
902 }
903
904 return wpautop( $output );
905 }
906
907 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
908 function get_user_role( $id ) {
909 $user = new WP_User( $id );
910 $role = array_shift( $user->roles );
911
912 if ( empty( $role ) ) {
913 return '';
914 }
915
916 $wp_roles = wp_roles();
917
918 if ( ! isset( $wp_roles->roles[ $role ]['name'] ) ) {
919 return '';
920 }
921
922 return translate_user_role( $wp_roles->roles[ $role ]['name'] );
923 }
924
925
926 /**
927 * @param string $content return posts content
928 * @param int $avg_reading_speed average word reading speed per minute
929 * @param string $hide_seconds whether to hide seconds (yes/no)
930 * @param string $hide_minutes whether to hide minutes (yes/no)
931 *
932 * @return string return average reading time of specifiic posts.
933 */
934
935 if ( _is_upk_pro_activated() ) {
936 function ultimate_post_kit_reading_time( $content, $avg_reading_speed, $hide_seconds = 'no', $hide_minutes = 'no' ) {
937 $total_word = str_word_count( wp_strip_all_tags( $content ) );
938 $reading_minute = floor( $total_word / $avg_reading_speed );
939 $reading_seconds = floor( $total_word % $avg_reading_speed / ( $avg_reading_speed / 60 ) );
940
941 $hide_seconds = ( $hide_seconds === 'yes' );
942 $hide_minutes = ( $hide_minutes === 'yes' );
943
944 // If hide_minutes is enabled, convert everything to seconds
945 if ( $hide_minutes ) {
946 $total_seconds = ( $reading_minute * 60 ) + $reading_seconds;
947 if ( $hide_seconds ) {
948 return '0 sec read';
949 }
950 return $total_seconds . ' sec read';
951 }
952
953 if ( $total_word >= $avg_reading_speed ) {
954 $parts = array();
955
956 if ( $reading_minute > 0 ) {
957 $parts[] = $reading_minute . ' min';
958 }
959
960 if ( ! $hide_seconds && $reading_seconds > 0 ) {
961 $parts[] = $reading_seconds . ' sec';
962 }
963
964 // If no parts and seconds are not hidden, show at least seconds
965 if ( empty( $parts ) ) {
966 if ( ! $hide_seconds ) {
967 $parts[] = $reading_seconds . ' sec';
968 } else {
969 $parts[] = $reading_minute . ' min';
970 }
971 }
972
973 return ! empty( $parts ) ? implode( ' ', $parts ) . ' read' : '0 sec read';
974 } else {
975 // For content less than reading speed, show seconds unless hidden
976 if ( $hide_seconds ) {
977 return '0 min read';
978 }
979 return $reading_seconds . ' sec read';
980 }
981 }
982 }
983
984
985 /**
986 * License Validation
987 */
988 if ( ! function_exists( 'upk_license_validation' ) ) {
989 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
990 function upk_license_validation() {
991
992 if ( function_exists( '_is_upk_pro_activated' ) && false === _is_upk_pro_activated() ) {
993 return false;
994 }
995
996 $license_key = trim( get_option( 'ultimate_post_kit_license_key' ) );
997
998 if ( isset( $license_key ) && ! empty( $license_key ) ) {
999 return true;
1000 }
1001
1002 return false;
1003 }
1004 }
1005
1006
1007 /**
1008 * Restrict a request-supplied post type to the ones this site already exposes to
1009 * anonymous visitors.
1010 *
1011 * The load-more handlers are registered on wp_ajax_nopriv_* and rebuild their WP_Query
1012 * from $_POST, so the post type they query is attacker-controlled. Post types that are
1013 * public but flagged exclude_from_search (Elementor's elementor_library, for example)
1014 * are deliberately hidden from anonymous visitors elsewhere, so they must not be
1015 * reachable here either.
1016 *
1017 * @param string|array $post_type Requested post type(s).
1018 * @param string $fallback Post type to fall back to when nothing is allowed.
1019 * @return string|array Sanitized post type(s).
1020 */
1021 if ( ! function_exists( 'ultimate_post_kit_sanitize_public_post_type' ) ) {
1022 function ultimate_post_kit_sanitize_public_post_type( $post_type, $fallback = 'post' ) {
1023
1024 $allowed = get_post_types(
1025 [
1026 'public' => true,
1027 'exclude_from_search' => false,
1028 ]
1029 );
1030
1031 if ( is_array( $post_type ) ) {
1032 $requested = array_filter( $post_type, 'is_scalar' );
1033 $requested = array_values( array_intersect( array_map( 'strval', $requested ), $allowed ) );
1034
1035 return empty( $requested ) ? $fallback : $requested;
1036 }
1037
1038 if ( ! is_scalar( $post_type ) ) {
1039 return $fallback;
1040 }
1041
1042 $post_type = (string) $post_type;
1043
1044 return isset( $allowed[ $post_type ] ) ? $post_type : $fallback;
1045 }
1046 }
1047
1048 /**
1049 * Clamp a request-supplied excerpt word count.
1050 *
1051 * excerpt_length arrives from $_POST on the unauthenticated load-more handlers and is
1052 * passed straight to wp_trim_words(), so an unbounded value returns effectively the
1053 * whole post_content instead of a teaser.
1054 *
1055 * @param mixed $length Requested word count.
1056 * @param int $default Value to use when the request supplies nothing usable.
1057 * @return int Clamped word count.
1058 */
1059 if ( ! function_exists( 'ultimate_post_kit_clamp_excerpt_length' ) ) {
1060 function ultimate_post_kit_clamp_excerpt_length( $length, $default = 20 ) {
1061
1062 $length = is_scalar( $length ) ? (int) $length : 0;
1063
1064 if ( $length < 1 ) {
1065 $length = (int) $default;
1066 }
1067
1068 return max( 1, min( 200, $length ) );
1069 }
1070 }
1071
1072 /**
1073 * Make a request-supplied Elementor icon array safe to render.
1074 *
1075 * The load-more handlers run on wp_ajax_nopriv_* and rebuild their settings from $_POST.
1076 * map_deep() preserves nested arrays, so an icon array reaches
1077 * Elementor\Icons_Manager::render_icon() exactly as the caller shaped it. The 'svg'
1078 * library branch resolves to Svg::get_inline_svg( $value['id'] ), which reads an
1079 * attachment by id with no capability or post-status check, so an icon coming from a
1080 * request must never be allowed to select it.
1081 *
1082 * @param mixed $icon Icon array as supplied by the request.
1083 * @return array|false Safe icon array, or false when nothing renderable remains.
1084 */
1085 if ( ! function_exists( 'ultimate_post_kit_sanitize_request_icon' ) ) {
1086 function ultimate_post_kit_sanitize_request_icon( $icon ) {
1087
1088 if ( ! is_array( $icon ) || empty( $icon['library'] ) || ! is_scalar( $icon['library'] ) ) {
1089 return false;
1090 }
1091
1092 $library = (string) $icon['library'];
1093
1094 // Uploaded-SVG icons are addressed by attachment id; never resolve one from a request.
1095 if ( 'svg' === $library ) {
1096 return false;
1097 }
1098
1099 // Font icons are rendered as a CSS class, so the value must stay a scalar.
1100 if ( ! isset( $icon['value'] ) || ! is_scalar( $icon['value'] ) ) {
1101 return false;
1102 }
1103
1104 return [
1105 'library' => $library,
1106 'value' => (string) $icon['value'],
1107 ];
1108 }
1109 }
1110