if ( ! defined( 'BDTUPK_CP' ) ) {
define( 'BDTUPK_CP', '' );
} //Add prefix for all widgets
if ( ! defined( 'BDTUPK_NC' ) ) {
define( 'BDTUPK_NC', '' );
} //Add prefix for all widgets
if ( ! defined( 'BDTUPK_UC' ) ) {
define( 'BDTUPK_UC', '' );
} // if you have any custom style
if ( _is_upk_pro_activated() ) {
if ( ! defined( 'BDTUPK_PC' ) ) {
define( 'BDTUPK_PC', '' );
} // pro control badge
if ( ! defined( 'BDTUPK_SLUG' ) ) {
define( 'BDTUPK_SLUG', 'ultimate-post-kit' );
} // set your own alias
if ( ! defined( 'BDTUPK_TITLE' ) ) {
define( 'BDTUPK_TITLE', 'Ultimate Post Kit' );
} // Set your own name for plugin
define( 'BDTUPK_IS_PC', '' );
} else {
if ( ! defined( 'BDTUPK_PC' ) ) {
define( 'BDTUPK_PC', '' );
} // pro control badge
if ( ! defined( 'BDTUPK_SLUG' ) ) {
define( 'BDTUPK_SLUG', 'ultimate-post-kit' );
} // set your own alias
if ( ! defined( 'BDTUPK_TITLE' ) ) {
define( 'BDTUPK_TITLE', 'Ultimate Post Kit' );
} // Set your own name for plugin
define( 'BDTUPK_IS_PC', 'upk-disabled-control' );
}
function ultimate_post_kit_is_edit() {
return Plugin::$instance->editor->is_edit_mode();
}
function ultimate_post_kit_is_preview() {
return Plugin::$instance->preview->is_preview_mode();
}
// add socials list meta in user profile
function ultimate_post_kit_user_contact_methods( $methods, $core = false ) {
if ( $core ) {
$methods['email'] = __( 'Email', 'ultimate-post-kit' );
$methods['url'] = __( 'Website', 'ultimate-post-kit' );
}
$methods['facebook'] = __( 'Facebook', 'ultimate-post-kit' );
$methods['twitter'] = __( 'Twitter', 'ultimate-post-kit' );
$methods['linkedin'] = __( 'LinkedIn', 'ultimate-post-kit' );
$methods['github'] = __( 'GitHub', 'ultimate-post-kit' );
$methods['wordpress'] = __( 'WordPress', 'ultimate-post-kit' );
$methods['dribbble'] = __( 'Dribbble', 'ultimate-post-kit' );
return $methods;
}
add_filter( 'user_contactmethods', 'ultimate_post_kit_user_contact_methods' );
/**
* Show any alert by this function
*
* @param mixed $message [description]
* @param class prefix $type [description]
* @param boolean $close [description]
*
* @return helper [description]
*/
function ultimate_post_kit_alert( $message, $type = 'warning', $close = true ) {
?>
';
if ( $close ) :
$output .= '';
endif;
$output .= wp_kses_post( $message );
$output .= '';
return $output;
}
/**
* all array css classes will output as proper space
*
* @param array $classes shortcode css class as array
*
* @return array string
*/
function ultimate_post_kit_get_post_types( $args = [] ) {
$post_type_args = [
'show_in_nav_menus' => true,
];
if ( ! empty( $args['post_type'] ) ) {
$post_type_args['name'] = $args['post_type'];
}
$_post_types = get_post_types( $post_type_args, 'objects' );
$post_types = [ '0' => esc_html__( 'Select Type', 'ultimate-post-kit' ) ];
foreach ( $_post_types as $post_type => $object ) {
$post_types[ $post_type ] = $object->label;
}
return $post_types;
}
function ultimate_post_kit_get_taxonomies() {
$args = array(
'public' => true,
//'_builtin' => false
);
$output = [ '0' => esc_html__( 'Select Type', 'ultimate-post-kit' ) ];
$tax_output = 'objects'; // or objects
$taxonomies = get_taxonomies( $args, $tax_output );
if ( $taxonomies ) {
foreach ( $taxonomies as $taxonomy ) {
$taxonomy_label = $taxonomy->label ? $taxonomy->label : $taxonomy->name;
$term_count = wp_count_terms(
[
'taxonomy' => $taxonomy->name,
'hide_empty' => false,
]
);
if ( is_wp_error( $term_count ) ) {
$term_count = 0;
}
$output[ $taxonomy->name ] = sprintf(
'%s (%d)',
$taxonomy_label,
(int) $term_count
);
}
}
return $output;
}
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
function upk_get_category( $post_type ) {
switch ( $post_type ) {
case 'campaign':
$taxonomy = 'campaign_category';
break;
case 'lightbox_library':
$taxonomy = 'ngg_tag';
break;
case 'give_forms':
$taxonomy = 'give_forms_category';
break;
case 'tribe_events':
$taxonomy = 'tribe_events_cat';
break;
case 'product':
$taxonomy = 'product_cat';
break;
default:
$taxonomy = 'category';
break;
}
$categories = get_the_terms( get_the_ID(), $taxonomy );
$_categories = [];
if ( $categories && !is_wp_error( $categories ) ) {
foreach ( $categories as $category ) {
// Ensure $category is an object, not an array
if ( is_object( $category ) && isset( $category->term_id, $category->name, $category->slug ) ) {
$link = ''
. esc_html( $category->name ) .
'';
$_categories[ $category->slug ] = $link;
}
}
}
return implode( ' ', $_categories );
}
function ultimate_post_kit_allow_tags( ?string $tag = null ) {
$tag_allowed = wp_kses_allowed_html( 'post' );
$tag_allowed['input'] = [
'class' => [],
'id' => [],
'name' => [],
'value' => [],
'checked' => [],
'type' => [],
];
$tag_allowed['select'] = [
'class' => [],
'id' => [],
'name' => [],
'value' => [],
'multiple' => [],
'type' => [],
];
$tag_allowed['option'] = [
'value' => [],
'selected' => [],
];
$tag_allowed['title'] = [
'a' => [
'href' => [],
'title' => [],
'class' => [],
],
'br' => [],
'em' => [],
'strong' => [],
'hr' => [],
];
$tag_allowed['text'] = [
'a' => [
'href' => [],
'title' => [],
'class' => [],
],
'br' => [],
'em' => [],
'strong' => [],
'hr' => [],
'i' => [
'class' => [],
],
'span' => [
'class' => [],
],
];
$tag_allowed['svg'] = [
'svg' => [
'version' => [],
'xmlns' => [],
'viewbox' => [],
'xml:space' => [],
'xmlns:xlink' => [],
'x' => [],
'y' => [],
'style' => [],
],
'g' => [],
'path' => [
'class' => [],
'd' => [],
],
'ellipse' => [
'class' => [],
'cx' => [],
'cy' => [],
'rx' => [],
'ry' => [],
],
'circle' => [
'class' => [],
'cx' => [],
'cy' => [],
'r' => [],
],
'rect' => [
'x' => [],
'y' => [],
'transform' => [],
'height' => [],
'width' => [],
'class' => [],
],
'line' => [
'class' => [],
'x1' => [],
'x2' => [],
'y1' => [],
'y2' => [],
],
'style' => [],
];
if ( $tag == null ) {
return $tag_allowed;
} elseif ( is_array( $tag ) ) {
$new_tag_allow = [];
foreach ( $tag as $_tag ) {
$new_tag_allow[ $_tag ] = $tag_allowed[ $_tag ];
}
return $new_tag_allow;
} else {
return isset( $tag_allowed[ $tag ] ) ? $tag_allowed[ $tag ] : [];
}
}
/**
* HexColor
*/
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
function strToHex( $string, $steps = -10 ) {
if ( empty( $string ) ) {
return false;
}
$hex_output = sprintf( '%s', substr( md5( $string ), 0, 6 ) );
// Steps should be between -255 and 255. Negative = darker, positive = lighter
$steps = max( -255, min( 255, $steps ) );
// Split into three parts: R, G and B
$color_parts = str_split( $hex_output, 2 );
$output = '#';
foreach ( $color_parts as $color ) {
$color = hexdec( $color ); // Convert to decimal
$color = max( 0, min( 255, $color + $steps ) ); // Adjust color
$output .= str_pad( dechex( $color ), 2, '0', STR_PAD_LEFT ); // Make two char hex code
}
return strToUpper( $output );
}
/**
* Get the current paged number for a custom WP_Query instance.
*
* @param \WP_Query $wp_query Query object.
* @return int Current page number.
*/
function ultimate_post_kit_get_query_paged( $wp_query ) {
if ( ! $wp_query instanceof \WP_Query ) {
return 1;
}
$paged_from_query = isset( $wp_query->query_vars['paged'] ) ? (int) $wp_query->query_vars['paged'] : 0;
$page_from_query = isset( $wp_query->query_vars['page'] ) ? (int) $wp_query->query_vars['page'] : 0;
if ( is_front_page() ) {
$paged = max( get_query_var( 'page' ), get_query_var( 'paged' ), $paged_from_query, $page_from_query );
} else {
$paged = max( get_query_var( 'paged' ), $paged_from_query );
}
return max( 1, (int) $paged );
}
/**
* Get item counter offset for paginated query loops.
*
* @param \WP_Query $wp_query Query object.
* @return int Zero-based offset for the first item on the current page.
*/
function ultimate_post_kit_get_query_counter_offset( $wp_query ) {
if ( ! $wp_query instanceof \WP_Query ) {
return 0;
}
$paged = ultimate_post_kit_get_query_paged( $wp_query );
$posts_per_page = (int) $wp_query->get( 'posts_per_page' );
if ( 1 >= $paged || 0 >= $posts_per_page ) {
return 0;
}
return ( $paged - 1 ) * $posts_per_page;
}
function ultimate_post_kit_post_pagination( $wp_query, $widget_id = '' ) {
/** Stop execution if there's only 1 page */
if ( $wp_query->max_num_pages <= 1 ) {
return;
}
$paged = ultimate_post_kit_get_query_paged( $wp_query );
$max = (int) $wp_query->max_num_pages;
/** Add current page to the array */
if ( $paged >= 1 ) {
$links[] = $paged;
}
/** Add the pages around the current page to the array */
if ( $paged >= 3 ) {
$links[] = $paged - 1;
$links[] = $paged - 2;
}
if ( ( $paged + 2 ) <= $max ) {
$links[] = $paged + 2;
$links[] = $paged + 1;
}
printf( '' . "\n";
}
function ultimate_post_kit_template_edit_link( $template_id ) {
if ( Ultimate_Post_Kit_Loader::elementor()->editor->is_edit_mode() ) {
$final_url = add_query_arg( [ 'elementor' => '' ], get_permalink( $template_id ) );
$output = sprintf( '', esc_url( $final_url ), esc_html__( 'Edit Template', 'ultimate-post-kit' ) );
return $output;
}
}
function ultimate_post_kit_time_diff( $from, $to = '' ) {
$diff = human_time_diff( $from, $to );
$replace = array(
' hour' => 'h',
' hours' => 'h',
' day' => 'd',
' days' => 'd',
' minute' => 'm',
' minutes' => 'm',
' second' => 's',
' seconds' => 's',
);
return strtr( $diff, $replace );
}
function ultimate_post_kit_post_time_diff( $format = '' ) {
$displayAgo = esc_html__( 'ago', 'ultimate-post-kit' );
$post_time = get_the_time( 'U' );
$current_time = current_time( 'timestamp' );
if ( $format == 'short' ) {
$output = ultimate_post_kit_time_diff( $post_time, $current_time );
} else {
$output = human_time_diff( $post_time, $current_time );
}
$output = $output . ' ' . $displayAgo;
return $output;
}
function ultimate_post_kit_iso_time( $time ) {
$current_offset = (float) get_option( 'gmt_offset' );
$timezone_string = get_option( 'timezone_string' );
// Create a UTC+- zone if no timezone string exists.
//if ( empty( $timezone_string ) ) {
if ( 0 === $current_offset ) {
$timezone_string = '+00:00';
} elseif ( $current_offset < 0 ) {
$timezone_string = $current_offset . ':00';
} else {
$timezone_string = '+0' . $current_offset . ':00';
}
//}
$sub_time = [];
$sub_time = explode( " ", $time );
$final_time = $sub_time[0] . 'T' . $sub_time[1] . ':00' . $timezone_string;
return $final_time;
}
/**
* @return array
*/
function ultimate_post_kit_get_menu() {
$menus = wp_get_nav_menus();
$items = [ 0 => esc_html__( 'Select Menu', 'ultimate-post-kit' ) ];
foreach ( $menus as $menu ) {
$items[ $menu->slug ] = $menu->name;
}
return $items;
}
/**
* default get_option() default value check
*
* @param string $option settings field name
* @param string $section the section name this field belongs to
* @param string $default default text if it's not found
*
* @return mixed
*/
function ultimate_post_kit_option( $option, $section, $default = '' ) {
$options = get_option( $section );
if ( isset( $options[ $option ] ) ) {
return $options[ $option ];
}
return $default;
}
/**
* @return array of elementor template
*/
function ultimate_post_kit_et_options() {
$templates = Ultimate_Post_Kit_Loader::elementor()->templates_manager->get_source( 'local' )->get_items();
$types = [];
if ( empty( $templates ) ) {
$template_options = [ '0' => __( 'Template Not Found!', 'ultimate-post-kit' ) ];
} else {
$template_options = [ '0' => __( 'Select Template', 'ultimate-post-kit' ) ];
foreach ( $templates as $template ) {
$template_options[ $template['template_id'] ] = $template['title'] . ' (' . $template['type'] . ')';
$types[ $template['template_id'] ] = $template['type'];
}
}
return $template_options;
}
/**
* @return array of wp default sidebars
*/
function ultimate_post_kit_sidebar_options() {
global $wp_registered_sidebars;
$sidebar_options = [];
if ( ! $wp_registered_sidebars ) {
$sidebar_options[0] = esc_html__( 'No sidebars were found', 'ultimate-post-kit' );
} else {
$sidebar_options[0] = esc_html__( 'Select Sidebar', 'ultimate-post-kit' );
foreach ( $wp_registered_sidebars as $sidebar_id => $sidebar ) {
$sidebar_options[ $sidebar_id ] = $sidebar['name'];
}
}
return $sidebar_options;
}
/**
* @param string category name
*
* @return array of category
*/
function ultimate_post_kit_get_category( $taxonomy = 'category' ) {
$post_options = [];
$post_categories = get_terms(
[
'taxonomy' => $taxonomy,
'hide_empty' => false,
]
);
if ( is_wp_error( $post_categories ) ) {
return $post_options;
}
if ( false !== $post_categories and is_array( $post_categories ) ) {
foreach ( $post_categories as $category ) {
// Ensure $category is an object, not an array
if ( is_object( $category ) && isset( $category->slug, $category->name ) ) {
$post_options[ $category->slug ] = $category->name;
}
}
}
return $post_options;
}
/**
* @param array all ajax posted array there
*
* @return array return all setting as array
*/
function ultimate_post_kit_ajax_settings( $settings ) {
$required_settings = [
'show_date' => true,
'show_comment' => true,
'show_link' => true,
'show_meta' => true,
'show_title' => true,
'show_excerpt' => true,
'show_lightbox' => true,
'show_thumbnail' => true,
'show_category' => false,
'show_tags' => false,
];
foreach ( $settings as $key => $value ) {
if ( in_array( $key, $required_settings ) ) {
$required_settings[ $key ] = $value;
}
}
return $required_settings;
}
// BDT Blend Type
function ultimate_post_kit_blend_options() {
$blend_options = [
'multiply' => esc_html__( 'Multiply', 'ultimate-post-kit' ),
'screen' => esc_html__( 'Screen', 'ultimate-post-kit' ),
'overlay' => esc_html__( 'Overlay', 'ultimate-post-kit' ),
'darken' => esc_html__( 'Darken', 'ultimate-post-kit' ),
'lighten' => esc_html__( 'Lighten', 'ultimate-post-kit' ),
'color-dodge' => esc_html__( 'Color-Dodge', 'ultimate-post-kit' ),
'color-burn' => esc_html__( 'Color-Burn', 'ultimate-post-kit' ),
'hard-light' => esc_html__( 'Hard-Light', 'ultimate-post-kit' ),
'soft-light' => esc_html__( 'Soft-Light', 'ultimate-post-kit' ),
'difference' => esc_html__( 'Difference', 'ultimate-post-kit' ),
'exclusion' => esc_html__( 'Exclusion', 'ultimate-post-kit' ),
'hue' => esc_html__( 'Hue', 'ultimate-post-kit' ),
'saturation' => esc_html__( 'Saturation', 'ultimate-post-kit' ),
'color' => esc_html__( 'Color', 'ultimate-post-kit' ),
'luminosity' => esc_html__( 'Luminosity', 'ultimate-post-kit' ),
];
return $blend_options;
}
// BDT Position
function ultimate_post_kit_position() {
$position_options = [
'' => esc_html__( 'Default', 'ultimate-post-kit' ),
'top-left' => esc_html__( 'Top Left', 'ultimate-post-kit' ),
'top-center' => esc_html__( 'Top Center', 'ultimate-post-kit' ),
'top-right' => esc_html__( 'Top Right', 'ultimate-post-kit' ),
'center' => esc_html__( 'Center', 'ultimate-post-kit' ),
'center-left' => esc_html__( 'Center Left', 'ultimate-post-kit' ),
'center-right' => esc_html__( 'Center Right', 'ultimate-post-kit' ),
'bottom-left' => esc_html__( 'Bottom Left', 'ultimate-post-kit' ),
'bottom-center' => esc_html__( 'Bottom Center', 'ultimate-post-kit' ),
'bottom-right' => esc_html__( 'Bottom Right', 'ultimate-post-kit' ),
];
return $position_options;
}
// BDT Thumbnavs Position
function ultimate_post_kit_thumbnavs_position() {
$position_options = [
'top-left' => esc_html__( 'Top Left', 'ultimate-post-kit' ),
'top-center' => esc_html__( 'Top Center', 'ultimate-post-kit' ),
'top-right' => esc_html__( 'Top Right', 'ultimate-post-kit' ),
'center-left' => esc_html__( 'Center Left', 'ultimate-post-kit' ),
'center-right' => esc_html__( 'Center Right', 'ultimate-post-kit' ),
'bottom-left' => esc_html__( 'Bottom Left', 'ultimate-post-kit' ),
'bottom-center' => esc_html__( 'Bottom Center', 'ultimate-post-kit' ),
'bottom-right' => esc_html__( 'Bottom Right', 'ultimate-post-kit' ),
];
return $position_options;
}
function ultimate_post_kit_navigation_position() {
$position_options = [
'top-left' => esc_html__( 'Top Left', 'ultimate-post-kit' ),
'top-center' => esc_html__( 'Top Center', 'ultimate-post-kit' ),
'top-right' => esc_html__( 'Top Right', 'ultimate-post-kit' ),
'center' => esc_html__( 'Center', 'ultimate-post-kit' ),
'center-left' => esc_html__( 'Center Left', 'ultimate-post-kit' ),
'center-right' => esc_html__( 'Center Right', 'ultimate-post-kit' ),
'bottom-left' => esc_html__( 'Bottom Left', 'ultimate-post-kit' ),
'bottom-center' => esc_html__( 'Bottom Center', 'ultimate-post-kit' ),
'bottom-right' => esc_html__( 'Bottom Right', 'ultimate-post-kit' ),
];
return $position_options;
}
function ultimate_post_kit_pagination_position() {
$position_options = [
'top-left' => esc_html__( 'Top Left', 'ultimate-post-kit' ),
'top-center' => esc_html__( 'Top Center', 'ultimate-post-kit' ),
'top-right' => esc_html__( 'Top Right', 'ultimate-post-kit' ),
'center-left' => esc_html__( 'Center Left', 'ultimate-post-kit' ),
'center-right' => esc_html__( 'Center Right', 'ultimate-post-kit' ),
'bottom-left' => esc_html__( 'Bottom Left', 'ultimate-post-kit' ),
'bottom-center' => esc_html__( 'Bottom Center', 'ultimate-post-kit' ),
'bottom-right' => esc_html__( 'Bottom Right', 'ultimate-post-kit' ),
];
return $position_options;
}
// Title Tags
function ultimate_post_kit_title_tags() {
$title_tags = [
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'h4' => 'H4',
'h5' => 'H5',
'h6' => 'H6',
'div' => 'Div',
'span' => 'Span',
'p' => 'P',
];
return $title_tags;
}
function ultimate_post_kit_hide_on_class( $selectors ) {
$element_hide_on = '';
if ( ! empty( $selectors ) ) {
foreach ( $selectors as $element ) {
if ( $element == 'desktop' ) {
$element_hide_on .= ' upk-desktop';
}
if ( $element == 'tablet' ) {
$element_hide_on .= ' upk-tablet';
}
if ( $element == 'mobile' ) {
$element_hide_on .= ' upk-mobile';
}
}
}
return $element_hide_on;
}
function ultimate_post_kit_mask_shapes() {
$path = BDTUPK_ASSETS_URL . 'images/mask/';
$shape_name = 'shape';
$extension = '.svg';
$list = [ 0 => esc_html__( 'Select Mask', 'ultimate-post-kit' ) ];
for ( $i = 1; $i <= 20; $i++ ) {
$list[ $path . $shape_name . '-' . $i . $extension ] = ucwords( $shape_name . ' ' . $i );
}
return $list;
}
/**
* String to ID maker for any title to relavent id
* @param [type] string any title or string
* @return [type] [description]
*/
function ultimate_post_kit_string_id( $string ) {
//Lower case everything
$string = strtolower( $string );
//Make alphanumeric (removes all other characters)
$string = preg_replace( "/[^a-z0-9_\s-]/", "", $string );
//Clean up multiple dashes or whitespaces
$string = preg_replace( "/[\s-]+/", " ", $string );
//Convert whitespaces and underscore to dash
$string = preg_replace( "/[\s_]/", "-", $string );
//finally return here
return $string;
}
function ultimate_post_kit_dashboard_link( $suffix = '#welcome' ) {
return add_query_arg( [ 'page' => 'ultimate_post_kit_options' . $suffix ], admin_url( 'admin.php' ) );
}
/**
* @param int $limit default limit is 25 word
* @param bool $strip_shortcode if you want to strip shortcode from excert text
* @param string $trail trail string default is ...
*
* @return string return custom limited excerpt text
*/
function ultimate_post_kit_custom_excerpt( $limit = 25, $strip_shortcode = false, $trail = '' ) {
$output = get_the_content();
if ( $limit ) {
$output = wp_trim_words( $output, $limit, $trail );
}
if ( $strip_shortcode ) {
$output = strip_shortcodes( $output );
}
return wpautop( $output );
}
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
function get_user_role( $id ) {
$user = new WP_User( $id );
$role = array_shift( $user->roles );
if ( empty( $role ) ) {
return '';
}
$wp_roles = wp_roles();
if ( ! isset( $wp_roles->roles[ $role ]['name'] ) ) {
return '';
}
return translate_user_role( $wp_roles->roles[ $role ]['name'] );
}
/**
* @param string $content return posts content
* @param int $avg_reading_speed average word reading speed per minute
* @param string $hide_seconds whether to hide seconds (yes/no)
* @param string $hide_minutes whether to hide minutes (yes/no)
*
* @return string return average reading time of specifiic posts.
*/
if ( _is_upk_pro_activated() ) {
function ultimate_post_kit_reading_time( $content, $avg_reading_speed, $hide_seconds = 'no', $hide_minutes = 'no' ) {
$avg_reading_speed = is_scalar( $avg_reading_speed ) ? (int) $avg_reading_speed : 0;
$avg_reading_speed = $avg_reading_speed > 0 ? $avg_reading_speed : 200;
$total_word = str_word_count( wp_strip_all_tags( $content ) );
$reading_minute = floor( $total_word / $avg_reading_speed );
$reading_seconds = floor( $total_word % $avg_reading_speed / ( $avg_reading_speed / 60 ) );
$hide_seconds = ( $hide_seconds === 'yes' );
$hide_minutes = ( $hide_minutes === 'yes' );
// If hide_minutes is enabled, convert everything to seconds
if ( $hide_minutes ) {
$total_seconds = ( $reading_minute * 60 ) + $reading_seconds;
if ( $hide_seconds ) {
return '0 sec read';
}
return $total_seconds . ' sec read';
}
if ( $total_word >= $avg_reading_speed ) {
$parts = array();
if ( $reading_minute > 0 ) {
$parts[] = $reading_minute . ' min';
}
if ( ! $hide_seconds && $reading_seconds > 0 ) {
$parts[] = $reading_seconds . ' sec';
}
// If no parts and seconds are not hidden, show at least seconds
if ( empty( $parts ) ) {
if ( ! $hide_seconds ) {
$parts[] = $reading_seconds . ' sec';
} else {
$parts[] = $reading_minute . ' min';
}
}
return ! empty( $parts ) ? implode( ' ', $parts ) . ' read' : '0 sec read';
} else {
// For content less than reading speed, show seconds unless hidden
if ( $hide_seconds ) {
return '0 min read';
}
return $reading_seconds . ' sec read';
}
}
}
/**
* License Validation
*/
if ( ! function_exists( 'upk_license_validation' ) ) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- established function name relied on across the plugin family / feedback SDK; renaming would break integration.
function upk_license_validation() {
if ( function_exists( '_is_upk_pro_activated' ) && false === _is_upk_pro_activated() ) {
return false;
}
$license_key = trim( get_option( 'ultimate_post_kit_license_key' ) );
if ( isset( $license_key ) && ! empty( $license_key ) ) {
return true;
}
return false;
}
}
/**
* Restrict a request-supplied post type to the ones this site already exposes to
* anonymous visitors.
*
* The load-more handlers are registered on wp_ajax_nopriv_* and rebuild their WP_Query
* from $_POST, so the post type they query is attacker-controlled. Post types that are
* public but flagged exclude_from_search (Elementor's elementor_library, for example)
* are deliberately hidden from anonymous visitors elsewhere, so they must not be
* reachable here either.
*
* @param string|array $post_type Requested post type(s).
* @param string $fallback Post type to fall back to when nothing is allowed.
* @return string|array Sanitized post type(s).
*/
if ( ! function_exists( 'ultimate_post_kit_sanitize_public_post_type' ) ) {
function ultimate_post_kit_sanitize_public_post_type( $post_type, $fallback = 'post' ) {
$is_allowed = static function ( $type ) {
$object = get_post_type_object( $type );
return $object && is_post_type_viewable( $type ) && empty( $object->exclude_from_search );
};
if ( is_array( $post_type ) ) {
$requested = array_filter( $post_type, 'is_scalar' );
$requested = array_values( array_filter( array_map( 'strval', $requested ), $is_allowed ) );
return empty( $requested ) ? $fallback : $requested;
}
if ( ! is_scalar( $post_type ) ) {
return $fallback;
}
$post_type = (string) $post_type;
return $is_allowed( $post_type ) ? $post_type : $fallback;
}
}
/**
* Clamp a request-supplied excerpt word count.
*
* excerpt_length arrives from $_POST on the unauthenticated load-more handlers and is
* passed straight to wp_trim_words(), so an unbounded value returns effectively the
* whole post_content instead of a teaser.
*
* @param mixed $length Requested word count.
* @param int $default Value to use when the request supplies nothing usable.
* @return int Clamped word count.
*/
if ( ! function_exists( 'ultimate_post_kit_clamp_excerpt_length' ) ) {
function ultimate_post_kit_clamp_excerpt_length( $length, $default = 20 ) {
$length = is_scalar( $length ) ? (int) $length : 0;
if ( $length < 1 ) {
$length = (int) $default;
}
return max( 1, min( 200, $length ) );
}
}
/**
* Make a request-supplied Elementor icon array safe to render.
*
* The load-more handlers run on wp_ajax_nopriv_* and rebuild their settings from $_POST.
* map_deep() preserves nested arrays, so an icon array reaches
* Elementor\Icons_Manager::render_icon() exactly as the caller shaped it. The 'svg'
* library branch resolves to Svg::get_inline_svg( $value['id'] ), which reads an
* attachment by id with no capability or post-status check, so an icon coming from a
* request must never be allowed to select it.
*
* @param mixed $icon Icon array as supplied by the request.
* @return array|false Safe icon array, or false when nothing renderable remains.
*/
if ( ! function_exists( 'ultimate_post_kit_sanitize_request_icon' ) ) {
function ultimate_post_kit_sanitize_request_icon( $icon ) {
if ( ! is_array( $icon ) || empty( $icon['library'] ) || ! is_scalar( $icon['library'] ) ) {
return false;
}
$library = (string) $icon['library'];
// Uploaded-SVG icons are addressed by attachment id; never resolve one from a request.
if ( 'svg' === $library ) {
return false;
}
// Font icons are rendered as a CSS class, so the value must stay a scalar.
if ( ! isset( $icon['value'] ) || ! is_scalar( $icon['value'] ) ) {
return false;
}
return [
'library' => $library,
'value' => (string) $icon['value'],
];
}
}