- WordPress core y plugins - Tema Twenty Twenty-Four configurado - Plugin allow-unfiltered-html.php simplificado - .gitignore configurado para excluir wp-config.php y uploads 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
943 lines
26 KiB
PHP
Executable File
943 lines
26 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Thrive Themes - https://thrivethemes.com
|
|
*
|
|
* @package thrive-visual-editor
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit; // Silence is golden!
|
|
}
|
|
|
|
/**
|
|
* Class TCB_Utils
|
|
*/
|
|
class TCB_Utils {
|
|
/**
|
|
* Wrap content in tag with id and/or class
|
|
*
|
|
* @param $content
|
|
* @param string $tag
|
|
* @param string $id
|
|
* @param string|array $class
|
|
* @param array $attr
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function wrap_content( $content, $tag = '', $id = '', $class = '', $attr = [] ) {
|
|
$class = is_array( $class ) ? trim( implode( ' ', $class ) ) : $class;
|
|
|
|
if ( empty( $tag ) && ! ( empty( $id ) && empty( $class ) ) ) {
|
|
$tag = 'div';
|
|
}
|
|
|
|
$attributes = '';
|
|
foreach ( $attr as $key => $value ) {
|
|
/* if the value is null, only add the key ( this is used for attributes that have no value, such as 'disabled', 'checked', etc ) */
|
|
if ( is_null( $value ) ) {
|
|
$attributes .= ' ' . $key;
|
|
} else {
|
|
$attributes .= ' ' . $key . '="' . esc_attr( $value ) . '"';
|
|
}
|
|
}
|
|
|
|
if ( ! empty( $tag ) ) {
|
|
$content = '<' . $tag . ( empty( $id ) ? '' : ' id="' . $id . '"' ) . ( empty( $class ) ? '' : ' class="' . $class . '"' ) . $attributes . '>' . $content . '</' . $tag . '>';
|
|
}
|
|
|
|
return $content;
|
|
}
|
|
|
|
/**
|
|
* Get all the banned post types for the post list/grid.
|
|
*
|
|
* @return mixed|void
|
|
*/
|
|
public static function get_banned_post_types() {
|
|
$banned_types = [
|
|
'attachment',
|
|
'revision',
|
|
'nav_menu_item',
|
|
'custom_css',
|
|
'customize_changeset',
|
|
'oembed_cache',
|
|
'project',
|
|
'et_pb_layout',
|
|
'tcb_lightbox',
|
|
'focus_area',
|
|
'thrive_optin',
|
|
'thrive_ad_group',
|
|
'thrive_ad',
|
|
'thrive_slideshow',
|
|
'thrive_slide_item',
|
|
'tve_lead_shortcode',
|
|
'tve_lead_2s_lightbox',
|
|
'tve_form_type',
|
|
'tve_lead_group',
|
|
'tve_lead_1c_signup',
|
|
TCB_CT_POST_TYPE,
|
|
'tcb_symbol',
|
|
'td_nm_notification',
|
|
];
|
|
|
|
/**
|
|
* Filter that other plugins can hook to add / remove ban types from post grid
|
|
*/
|
|
return apply_filters( 'tcb_post_grid_banned_types', $banned_types );
|
|
}
|
|
|
|
/**
|
|
* Get the image source for the id.
|
|
* This is used in TTB, don't delete it
|
|
*
|
|
* @param $image_id
|
|
* @param string $size
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public static function get_image_src( $image_id, $size = 'full' ) {
|
|
$image_info = wp_get_attachment_image_src( $image_id, $size );
|
|
|
|
return empty( $image_info ) || empty( $image_info[0] ) ? '' : $image_info[0];
|
|
}
|
|
|
|
/**
|
|
* Get the pagination data that we want to localize.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_pagination_localized_data() {
|
|
$localized_data = [];
|
|
|
|
/* Apply a filter in case we want to add more pagination types from elsewhere. */
|
|
$all_pagination_types = apply_filters( 'tcb_post_list_pagination_types', TCB_Pagination::$all_types );
|
|
|
|
foreach ( $all_pagination_types as $type ) {
|
|
$instance = tcb_pagination( $type );
|
|
|
|
$localized_data[ $instance->get_type() ] = $instance->get_content();
|
|
}
|
|
|
|
/* we need this when we add new post lists to the page and they need a pagination element wrapper */
|
|
$localized_data['pagination_wrapper'] = tcb_pagination( TCB_Pagination::NONE )->render();
|
|
|
|
$localized_data['label_formats'] = array(
|
|
'pages' => tcb_template( 'pagination/label-pages.php', null, true ),
|
|
'posts' => tcb_template( 'pagination/label-posts.php', null, true ),
|
|
);
|
|
|
|
return $localized_data;
|
|
}
|
|
|
|
/**
|
|
* Adapt the pagination button component that inherits the button component by disabling some controls and adding new controls.
|
|
*
|
|
* @param $components
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public static function get_pagination_button_config( $components ) {
|
|
$components['pagination_button'] = $components['button'];
|
|
unset( $components['button'] );
|
|
|
|
$all_controls = array_keys( $components['pagination_button']['config'] );
|
|
|
|
/* disable all the controls except the ones that we want to be enabled */
|
|
$disabled_controls = array_diff( $all_controls, [ 'MasterColor', 'icon_side' ] );
|
|
|
|
/* we have to add this manually */
|
|
$disabled_controls = array_merge( $disabled_controls, [ '.tcb-button-link-container' ] );
|
|
|
|
$components['pagination_button']['disabled_controls'] = array_values( $disabled_controls );
|
|
$components['pagination_button']['config']['icon_layout'] = array(
|
|
'config' => array(
|
|
'name' => __( 'Button Layout', 'thrive-cb' ),
|
|
'full-width' => true,
|
|
'buttons' => array(
|
|
array(
|
|
'value' => 'text',
|
|
'text' => __( 'Text Only', 'thrive-cb' ),
|
|
),
|
|
array(
|
|
'value' => 'icon',
|
|
'text' => __( 'Icon Only', 'thrive-cb' ),
|
|
),
|
|
array(
|
|
'value' => 'text_plus_icon',
|
|
'text' => __( 'Icon&Text', 'thrive-cb' ),
|
|
),
|
|
),
|
|
/* default is defined here so it can be overwritten by elements that inherit */
|
|
'default' => 'text',
|
|
),
|
|
'extends' => 'ButtonGroup',
|
|
);
|
|
|
|
$components['animation']['disabled_controls'] = [ '.btn-inline.anim-link', '.btn-inline.anim-popup' ];
|
|
|
|
/* add the root prefix in order to make this more specific than paragraph spacing settings from containers */
|
|
$components['layout']['config']['MarginAndPadding']['css_prefix'] = tcb_selection_root() . ' ';
|
|
|
|
$components['layout']['disabled_controls'] = [ 'Display', 'Alignment' ];
|
|
|
|
$components['scroll'] = [ 'hidden' => true ];
|
|
$components['responsive'] = [ 'hidden' => true ];
|
|
$components['shared-styles'] = [ 'hidden' => true ];
|
|
|
|
return $components;
|
|
}
|
|
|
|
/**
|
|
* Get the date/time format options for the wordpress date settings, and append a custom setting.
|
|
* Can return an associative array of key-value pairs, or multiple arrays of name/value.
|
|
*
|
|
* @param string $type
|
|
* @param bool $key_value_pairs
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_post_date_format_options( $type = 'date', $key_value_pairs = false ) {
|
|
|
|
if ( $type === 'time' ) {
|
|
/**
|
|
* Filters the default time formats.
|
|
*
|
|
* @param string[] Array of default time formats.
|
|
*/
|
|
$formats = array_unique( apply_filters( 'time_formats', array( __( 'g:i a', 'thrive-cb' ), 'g:i A', 'H:i' ) ) );
|
|
} else {
|
|
/**
|
|
* Filters the default date formats.
|
|
*
|
|
* @param string[] Array of default date formats.
|
|
*/
|
|
$formats = array_unique( apply_filters( 'date_formats', array( __( 'F j, Y', 'thrive-cb' ), 'Y-m-d', 'm/d/Y', 'd/m/Y' ) ) );
|
|
}
|
|
|
|
$custom_option_name = __( 'Custom', 'thrive-cb' );
|
|
|
|
if ( $key_value_pairs ) {
|
|
foreach ( $formats as $format ) {
|
|
$options[ $format ] = get_the_time( $format );
|
|
}
|
|
|
|
$options['custom'] = $custom_option_name;
|
|
} else {
|
|
$options = array_map( function ( $format ) {
|
|
return array(
|
|
'name' => get_the_time( $format ),
|
|
'value' => $format,
|
|
);
|
|
}, $formats );
|
|
|
|
$options[] = [
|
|
'name' => $custom_option_name,
|
|
'value' => '',
|
|
];
|
|
}
|
|
|
|
return $options;
|
|
}
|
|
|
|
/**
|
|
* Get some inline shortcodes for the Pagination Label element.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_pagination_inline_shortcodes() {
|
|
return array(
|
|
'Post list pagination' => array(
|
|
array(
|
|
'option' => __( 'Current page number', 'thrive-cb' ),
|
|
'value' => 'tcb_pagination_current_page',
|
|
),
|
|
array(
|
|
'option' => __( 'Total number of pages', 'thrive-cb' ),
|
|
'value' => 'tcb_pagination_total_pages',
|
|
),
|
|
array(
|
|
'option' => __( 'Number of posts on this page', 'thrive-cb' ),
|
|
'value' => 'tcb_pagination_current_posts',
|
|
),
|
|
array(
|
|
'option' => __( 'Total number of posts', 'thrive-cb' ),
|
|
'value' => 'tcb_pagination_total_posts',
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get inline shortcodes for the Post List element.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_post_list_inline_shortcodes() {
|
|
$date_format_options = static::get_post_date_format_options( 'date', true );
|
|
$date_formats = array_keys( $date_format_options );
|
|
|
|
$time_format_options = static::get_post_date_format_options( 'time', true );
|
|
|
|
return array(
|
|
'Post' => array(
|
|
array(
|
|
'name' => __( 'Post title', 'thrive-cb' ),
|
|
'option' => __( 'Post title', 'thrive-cb' ),
|
|
'value' => 'tcb_post_title',
|
|
'input' => array(
|
|
'link' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Link to post title', 'thrive-cb' ),
|
|
'value' => true,
|
|
),
|
|
'target' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Open in new tab', 'thrive-cb' ),
|
|
'value' => false,
|
|
'disable_br' => true,
|
|
),
|
|
'rel' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'No follow', 'thrive-cb' ),
|
|
'value' => false,
|
|
),
|
|
),
|
|
),
|
|
array(
|
|
'name' => date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ),
|
|
'option' => __( 'Post date', 'thrive-cb' ),
|
|
'value' => 'tcb_post_published_date',
|
|
'input' => array(
|
|
'type' => array(
|
|
'type' => 'select',
|
|
'label' => __( 'Display', 'thrive-cb' ),
|
|
'value' => array(
|
|
'published' => __( 'Published date', 'thrive-cb' ),
|
|
'modified' => __( 'Modified date', 'thrive-cb' ),
|
|
),
|
|
),
|
|
'date-format-select' => array(
|
|
'type' => 'select',
|
|
'label' => __( 'Date format', 'thrive-cb' ),
|
|
'value' => $date_format_options,
|
|
),
|
|
'date-format' => array(
|
|
'type' => 'input',
|
|
'label' => __( 'Format string', 'thrive-cb' ),
|
|
'value' => $date_formats[0],
|
|
),
|
|
'show-time' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Show time?', 'thrive-cb' ),
|
|
'value' => false,
|
|
),
|
|
'time-format-select' => array(
|
|
'type' => 'select',
|
|
'label' => __( 'Time format', 'thrive-cb' ),
|
|
'value' => $time_format_options,
|
|
),
|
|
'time-format' => array(
|
|
'type' => 'input',
|
|
'label' => __( 'Format string', 'thrive-cb' ),
|
|
'value' => '',
|
|
),
|
|
'link' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Link to archive', 'thrive-cb' ),
|
|
'value' => false,
|
|
),
|
|
'target' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Open in new tab', 'thrive-cb' ),
|
|
'value' => true,
|
|
'disable_br' => true,
|
|
),
|
|
'rel' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'No follow', 'thrive-cb' ),
|
|
'value' => false,
|
|
),
|
|
),
|
|
),
|
|
array(
|
|
'name' => __( 'Author name', 'thrive-cb' ),
|
|
'option' => __( 'Author name', 'thrive-cb' ),
|
|
'value' => 'tcb_post_author_name',
|
|
'input' => array(
|
|
'link' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Link to author profile', 'thrive-cb' ),
|
|
'value' => false,
|
|
),
|
|
'target' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Open in new tab', 'thrive-cb' ),
|
|
'value' => true,
|
|
'disable_br' => true,
|
|
),
|
|
'rel' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'No follow', 'thrive-cb' ),
|
|
'value' => false,
|
|
),
|
|
),
|
|
),
|
|
array(
|
|
'name' => __( 'Author role', 'thrive-cb' ),
|
|
'option' => __( 'Author role', 'thrive-cb' ),
|
|
'value' => 'tcb_post_author_role',
|
|
),
|
|
array(
|
|
'name' => __( 'Author bio', 'thrive-cb' ),
|
|
'option' => __( 'Author bio', 'thrive-cb' ),
|
|
'value' => 'tcb_post_author_bio',
|
|
),
|
|
array(
|
|
'name' => 24,
|
|
'option' => __( 'Number of comments', 'thrive-cb' ),
|
|
'value' => 'tcb_post_comments_number',
|
|
),
|
|
),
|
|
'Taxonomies' => array(
|
|
array(
|
|
'name' => __( 'Category-1, Category-2, Category-3', 'thrive-cb' ),
|
|
'option' => __( 'List of categories', 'thrive-cb' ),
|
|
'value' => 'tcb_post_categories',
|
|
'input' => array(
|
|
'link' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Link to archive', 'thrive-cb' ),
|
|
'value' => true,
|
|
),
|
|
'target' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Open in new tab', 'thrive-cb' ),
|
|
'value' => false,
|
|
'disable_br' => true,
|
|
),
|
|
'rel' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'No follow', 'thrive-cb' ),
|
|
'value' => false,
|
|
),
|
|
),
|
|
),
|
|
array(
|
|
'name' => __( 'Tag-1, Tag-2, Tag-3', 'thrive-cb' ),
|
|
'option' => __( 'List of tags', 'thrive-cb' ),
|
|
'value' => 'tcb_post_tags',
|
|
'input' => array(
|
|
'default' => array(
|
|
'type' => 'input',
|
|
'label' => __( 'Default value', 'thrive-cb' ),
|
|
'value' => '',
|
|
),
|
|
'link' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Link to archive', 'thrive-cb' ),
|
|
'value' => true,
|
|
),
|
|
'target' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'Open in new tab', 'thrive-cb' ),
|
|
'value' => false,
|
|
'disable_br' => true,
|
|
),
|
|
'rel' => array(
|
|
'type' => 'checkbox',
|
|
'label' => __( 'No follow', 'thrive-cb' ),
|
|
'value' => false,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Return the post formats supported by the current theme.
|
|
*
|
|
* @return array|mixed
|
|
*/
|
|
public static function get_supported_post_formats() {
|
|
$post_formats = [];
|
|
|
|
if ( current_theme_supports( 'post-formats' ) ) {
|
|
$post_formats = get_theme_support( 'post-formats' );
|
|
|
|
if ( is_array( $post_formats[0] ) ) {
|
|
$post_formats = $post_formats[0];
|
|
}
|
|
}
|
|
|
|
return $post_formats;
|
|
}
|
|
|
|
/**
|
|
* Return the preview URL for this post( symbol or anything that has post meta ) ID along with height/width.
|
|
* If no URL is found, this can return a placeholder, if one was provided through the parameter.
|
|
*
|
|
* @param int $post_id
|
|
* @param string $sub_path
|
|
* @param array $placeholder_data
|
|
*
|
|
* @return array|mixed
|
|
*/
|
|
public static function get_thumb_data( $post_id, $sub_path, $placeholder_data = [] ) {
|
|
|
|
$upload_dir = wp_upload_dir();
|
|
$path = $sub_path . '/' . $post_id . '.png';
|
|
|
|
$thumb_path = static::get_uploads_path( $path, $upload_dir );
|
|
$thumb_url = trailingslashit( $upload_dir['baseurl'] ) . $path;
|
|
|
|
/* check if we have preview data in the post meta */
|
|
$thumb_data = static::get_thumbnail_data_from_id( $post_id );
|
|
|
|
/* if the post meta is empty, look inside the file and get the data directly from the it */
|
|
if ( empty( $thumb_data['url'] ) ) {
|
|
if ( file_exists( $thumb_path ) && ini_get( 'allow_url_fopen' ) ) {
|
|
list( $width, $height ) = getimagesize( $thumb_path );
|
|
|
|
$thumb_data = [
|
|
'url' => $thumb_url,
|
|
'h' => $height,
|
|
'w' => $width,
|
|
];
|
|
} else {
|
|
/* if no file is found and no placeholder is provided, return all the values set to blank */
|
|
if ( empty( $placeholder_data ) ) {
|
|
$thumb_data = [
|
|
'url' => '',
|
|
'h' => '',
|
|
'w' => '',
|
|
];
|
|
} else {
|
|
/* if a placeholder is provided, use it */
|
|
$thumb_data = $placeholder_data;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $thumb_data;
|
|
}
|
|
|
|
/**
|
|
* Return the uploads physical path.
|
|
* Things can be appended to it by providing something in $path.
|
|
*
|
|
* @param string $path
|
|
* @param array $upload_dir
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function get_uploads_path( $path = '', $upload_dir = [] ) {
|
|
if ( empty( $upload_dir ) ) {
|
|
$upload_dir = wp_upload_dir();
|
|
}
|
|
|
|
return trailingslashit( $upload_dir['basedir'] ) . $path;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the image metadata for the provided post ID.
|
|
*
|
|
* @param $post_id
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_thumbnail_data_from_id( $post_id ) {
|
|
return get_post_meta( $post_id, TCB_THUMBNAIL_META_KEY, true );
|
|
}
|
|
|
|
/**
|
|
* Set the image metadata for the provided post ID.
|
|
*
|
|
* @param $post_id
|
|
* @param $thumb_data
|
|
*/
|
|
public static function save_thumbnail_data( $post_id, $thumb_data ) {
|
|
update_post_meta( $post_id, TCB_THUMBNAIL_META_KEY, $thumb_data );
|
|
}
|
|
|
|
/**
|
|
* Check if we're inside the editor and filter the result.
|
|
*
|
|
* @param boolean $ajax_check
|
|
*
|
|
* @return mixed|void
|
|
*/
|
|
public static function in_editor_render( $ajax_check = false ) {
|
|
return apply_filters( 'tcb_in_editor_render', is_editor_page_raw( $ajax_check ) );
|
|
}
|
|
|
|
/**
|
|
* Check if we're in a REST request.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function is_rest() {
|
|
return defined( 'REST_REQUEST' ) && REST_REQUEST;
|
|
}
|
|
|
|
/**
|
|
* Returns the content at the given path
|
|
* A more simpler and general version of tcb_template()
|
|
*
|
|
* @param string $full_path
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function return_part( $full_path ) {
|
|
$content = '';
|
|
|
|
if ( file_exists( $full_path ) ) {
|
|
ob_start();
|
|
include $full_path;
|
|
$content = trim( ob_get_contents() );
|
|
ob_end_clean();
|
|
}
|
|
|
|
return $content;
|
|
}
|
|
|
|
/**
|
|
* parse and combine all font links => ensure a single request is sent out for a font
|
|
* Combines
|
|
*
|
|
* @import url("//fonts.googleapis.com/css?family=Muli:400,800,900,600&subset=latin");
|
|
* +
|
|
* @import url("//fonts.googleapis.com/css?family=Muli:400,900,600&subset=latin");
|
|
* into:
|
|
* @import url("//fonts.googleapis.com/css?family=Muli:400,600,800,900&subset=latin");
|
|
*
|
|
* @param array $imports
|
|
* @param string $return return type. Can be 'link' or 'import'
|
|
*
|
|
* @return array array of unique @import statements
|
|
*/
|
|
public static function merge_google_fonts( $imports, $return = 'import' ) {
|
|
return array_map( function ( $font_data ) use ( $return ) {
|
|
return TCB_Utils::build_font_string( $font_data, $return );
|
|
}, array_values( static::parse_css_imports( $imports ) ) );
|
|
}
|
|
|
|
/**
|
|
* Parses an array of CSS import statements and structures the data based on family and weights
|
|
* Merges all weights for a family
|
|
*
|
|
* @param array $imports
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function parse_css_imports( $imports ) {
|
|
$data = [];
|
|
foreach ( array_unique( $imports ) as $import ) {
|
|
$font = static::parse_css_import( $import );
|
|
if ( ! isset( $data[ $font['family'] ] ) ) {
|
|
$data[ $font['family'] ] = $font;
|
|
} else {
|
|
$data[ $font['family'] ]['weights'] += $font['weights'];
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Parses an `@import` statement and generates an array containing useful data about the font (family, weights, subset etc)
|
|
* !!IMPORTANT: this only treats google fonts!!
|
|
*
|
|
* @param string $import import string
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function parse_css_import( $import ) {
|
|
$data = [
|
|
'base_url' => '',
|
|
'family' => '',
|
|
'weights' => [],
|
|
'query' => [],
|
|
];
|
|
$import = str_replace( array( '"', "'", '@import url(', ')', ';' ), '', $import );
|
|
|
|
$result = parse_url( $import );
|
|
if ( $result ) {
|
|
$data['base_url'] = ( isset( $result['host'] ) ? 'https://' . $result['host'] : '' ) . $result['path'];
|
|
|
|
if ( ! empty( $result['query'] ) ) {
|
|
parse_str( $result['query'], $query );
|
|
|
|
list( $family, $weights ) = explode( ':', $query['family'] );
|
|
unset( $query['family'] );
|
|
|
|
$data['family'] = $family;
|
|
/* hold weights as keys, so it's less expensive to get unique weights */
|
|
$data['weights'] = array_flip( array_filter( explode( ',', $weights ), function ( $weight ) {
|
|
/**
|
|
* Preserve italic weights
|
|
*/
|
|
if ( substr( $weight, - 1 ) === 'i' ) {
|
|
$weight = substr( $weight, 0, - 1 );
|
|
}
|
|
|
|
return filter_var( $weight, FILTER_VALIDATE_INT );
|
|
} ) );
|
|
$data['query'] = $query;
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Builds an @import CSS rule based on $font_data
|
|
*
|
|
* @param array $font_data array in the form returned by self::parse_css_import
|
|
* @param string $return_type Controls the output. Can be 'link'/'url' or 'import'
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function build_font_string( $font_data, $return_type = 'import' ) {
|
|
if ( empty( $font_data ) ) {
|
|
return '';
|
|
}
|
|
$font_data['query'] = array( 'family' => $font_data['family'] . ':' . implode( ',', array_keys( $font_data['weights'] ) ) ) + $font_data['query'];
|
|
|
|
/**
|
|
* https://web.dev/font-display/
|
|
* this ensures font is readable while external gfonts are loaded
|
|
*
|
|
*/
|
|
$font_data['query']['display'] = 'swap';
|
|
|
|
$result = $font_data['base_url'] . '?' . rawurldecode( http_build_query( $font_data['query'], '', '&' ) );
|
|
|
|
if ( $return_type === 'import' ) {
|
|
$result = '@import url("' . $result . '");';
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Create a rest nonce for our ajax requests
|
|
*
|
|
* @return mixed|void
|
|
*/
|
|
public static function create_nonce() {
|
|
return wp_create_nonce( 'wp_rest' );
|
|
}
|
|
|
|
/**
|
|
* Mark that we started processing custom CSS
|
|
*/
|
|
public static function before_custom_css_processing() {
|
|
$GLOBALS[ TVE_IS_PROCESSING_CUSTOM_CSS ] = true;
|
|
}
|
|
|
|
/**
|
|
* Mark that we finished processing custom CSS
|
|
*/
|
|
public static function after_custom_css_processing() {
|
|
$GLOBALS[ TVE_IS_PROCESSING_CUSTOM_CSS ] = false;
|
|
}
|
|
|
|
/**
|
|
* Check if we're currently processing CSS.
|
|
* Useful in shortcode handlers in case you want to see if the shortcode is called from CSS or HTML.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function is_processing_custom_css() {
|
|
return ! empty( $GLOBALS[ TVE_IS_PROCESSING_CUSTOM_CSS ] );
|
|
}
|
|
|
|
/**
|
|
* If we're in a debug environment, we're not minifying JS files.
|
|
* The constant should be defined in the wp-config.php file
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function get_js_suffix() {
|
|
return tve_dash_is_debug_on() ? '.js' : '.min.js';
|
|
}
|
|
|
|
/**
|
|
* Shortcut function that will output json encoded data or return it as it is based on the second parameter.
|
|
*
|
|
* @param mixed $data
|
|
* @param bool $output if true, it will use WordPress's wp_send_json to output data
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public static function maybe_send_json( $data, $output = true ) {
|
|
if ( $output ) {
|
|
wp_send_json( $data );
|
|
} else {
|
|
return $data;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Write file using wordpress functionality
|
|
*
|
|
* @param $file
|
|
* @param string $content
|
|
* @param int $mode
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function write_file( $file, $content = '', $mode = 0644 ) {
|
|
require_once( ABSPATH . 'wp-admin/includes/file.php' );
|
|
|
|
/* make sure that the FS_METHOD defaults to 'direct' so we use WP_Filesystem_direct in order to avoid the FTP implementations of put_contents */
|
|
defined( 'FS_METHOD' ) || define( 'FS_METHOD', 'direct' );
|
|
|
|
global $wp_filesystem;
|
|
|
|
return WP_Filesystem() && $wp_filesystem->put_contents( $file, $content, $mode );
|
|
}
|
|
|
|
/**
|
|
* Restore some fields of the $_POST data that have been previously replaced from javascript
|
|
* Wordfence blocks certain strings in POST - these are replaced from javascript before sending the ajax request to some equivalents
|
|
* Currently, this method handles:
|
|
* - <svg and </svg> ( these are replaced from javascript into <_wafsvg_ and </_wafsvg )
|
|
*/
|
|
public static function restore_post_waf_content() {
|
|
/**
|
|
* Filter the list of fields that should be processed
|
|
*
|
|
* @param array $field_list
|
|
*/
|
|
$field_list = apply_filters( 'tcb_waf_fields_restore', [
|
|
'template',
|
|
'template_content',
|
|
'tve_content',
|
|
'tve_stripped_content',
|
|
'symbol_content',
|
|
] );
|
|
/* map of search_string => replace_string */
|
|
$replace_map = [
|
|
'_wafsvg_' => 'svg',
|
|
];
|
|
$search = array_keys( $replace_map );
|
|
$replace = array_values( $replace_map );
|
|
|
|
foreach ( $field_list as $field ) {
|
|
if ( ! empty( $_POST[ $field ] ) && is_string( $_POST[ $field ] ) ) {
|
|
$_POST[ $field ] = str_replace( $search, $replace, $_POST[ $field ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return string[]
|
|
*/
|
|
public static function get_api_list_with_tag_support() {
|
|
$apis_that_support_tags = [ 'activecampaign', 'aweber', 'convertkit', 'drip', 'klicktipp', 'mailchimp', 'sendlane', 'zapier' ];
|
|
|
|
return apply_filters( 'tcb_lead_generation_apis_with_tag_support', $apis_that_support_tags );
|
|
}
|
|
|
|
/**
|
|
* Get some values from the queried object.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_filtered_queried_object() {
|
|
$queried_object = get_queried_object();
|
|
$qo = [];
|
|
|
|
if ( $queried_object ) {
|
|
/* when we're using demo content the $queried_object can get weird, so check stuff before using it */
|
|
if (
|
|
property_exists( $queried_object, 'data' )
|
|
&& property_exists( $queried_object->data, 'ID' )
|
|
&&
|
|
! empty( $queried_object->data->ID )
|
|
) {
|
|
$qo ['ID'] = $queried_object->data->ID;
|
|
} elseif ( property_exists( $queried_object, 'ID' ) && ! empty( $queried_object->ID ) ) {
|
|
$qo ['ID'] = $queried_object->ID;
|
|
}
|
|
|
|
/* only keep the values for the specified keys */
|
|
$qo = array_filter( (array) $queried_object, function ( $key ) {
|
|
return in_array( $key, [ 'post_author', 'taxonomy', 'term_id', 'ID' ] );
|
|
}, ARRAY_FILTER_USE_KEY );
|
|
}
|
|
|
|
/**
|
|
* Filters the queried object needed in the frontend localization (used in generating "Edit with TTB" links that will show the same content)
|
|
*
|
|
* @param array $qo associative array the should have at least an `ID` key
|
|
*/
|
|
return apply_filters( 'tcb_frontend_queried_object', $qo );
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public static function get_placeholder_url() {
|
|
return tve_editor_url( 'admin/assets/images/no-template-preview.jpg' );
|
|
}
|
|
|
|
/**
|
|
* Get placeholder information for the template preview
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_placeholder_data() {
|
|
return [
|
|
'url' => static::get_placeholder_url(),
|
|
/* hardcoded sizes taken from 'no-template-preview.jpg' */
|
|
'h' => '120',
|
|
'w' => '250',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Used to hide elements on certain post types, called in hide() method from element classes
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function should_hide_element_on_blacklisted_post_types() {
|
|
$blacklisted_post_types = static::get_banned_post_types();
|
|
|
|
$blacklisted_post_types = array_diff( $blacklisted_post_types, [ 'tcb_symbol' ] );
|
|
|
|
return in_array( get_post_type( get_the_ID() ), $blacklisted_post_types );
|
|
}
|
|
|
|
/**
|
|
* Get TVA_Order using product ID and user ID.
|
|
*
|
|
* @param int $product_id
|
|
* @param int $user_id
|
|
*
|
|
* @return TVA_Order|null
|
|
*/
|
|
public static function get_tva_order_by_product_and_user( $product_id, $user_id ) {
|
|
global $wpdb;
|
|
|
|
$query = $wpdb->prepare(
|
|
"SELECT id FROM {$wpdb->prefix}tva_orders
|
|
WHERE user_id = %d
|
|
AND ID IN (SELECT order_id FROM {$wpdb->prefix}tva_order_items WHERE product_id = %d)
|
|
AND status = 1",
|
|
$user_id, $product_id
|
|
);
|
|
|
|
$order_id = $wpdb->get_results( $query );
|
|
|
|
// Check if an order ID was found then return the TVA_Order object.
|
|
if ( ! empty( $order_id ) && ! empty( $order_id[0] ) ) {
|
|
return new TVA_Order( (int) $order_id[0]->id );
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|