Commit inicial - WordPress Análisis de Precios Unitarios

- 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>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,139 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Element_Abstract
*/
abstract class TCB_Cloud_Template_Element_Abstract extends TCB_Element_Abstract {
/**
* Whether or not this element has cloud templates
*
* @return bool
*/
public function has_cloud_templates() {
return true;
}
/**
* All these elements act as placeholders
*
* @return true
*/
public function is_placeholder() {
return true;
}
/**
* These elements do not have their own identifiers - they are built from base elements and inherit options from base elements
*
* @return string
*/
public function identifier() {
return '';
}
/**
* HTML layout of the element for when it's dragged in the canvas
*
* @return string
*/
protected function html() {
return $this->html_placeholder( sprintf( __( 'Insert %s', 'thrive-cb' ), $this->name() ) );
}
/**
* Returns the HTML placeholder for an element (contains a wrapper, and a button with icon + element name)
*
* @param string $title Optional. Defaults to the name of the current element
*
* @return string
*/
public function html_placeholder( $title = null ) {
if ( empty( $title ) ) {
$title = $this->name();
}
return tcb_template( 'elements/element-placeholder', array(
'icon' => $this->icon(),
'class' => 'tcb-ct-placeholder',
'title' => $title,
'extra_attr' => 'data-ct="' . $this->tag() . '-0" data-tcb-elem-type="' . $this->tag() . '" data-element-name="' . esc_attr( $this->name() ) . '"',
), true );
}
/**
* Fetches a list of cloud templates for an element
*
* @param array $args allows controlling aspects of the method:
* $nocache - do not use caching (transients)
*
* @return array|WP_Error
*/
public function get_cloud_templates( $args = [] ) {
if ( ! $this->has_cloud_templates() ) {
return new WP_Error( 'invalid_element', __( 'Element does not have cloud templates', 'thrive-cb' ) );
}
$type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : '';
/**
*Allows changing cloud template tag
*/
$tag = apply_filters( 'tcb_cloud_templates_replace_featured_tag', $this->get_template_tag(), $type );
return tve_get_cloud_content_templates( $tag, apply_filters( 'tcb_get_cloud_templates_default_args', $args ) );
}
/**
* Get information about a cloud template:
* html content
* css
* custom css
* etc
*
* If the template does not exist, download it from the cloud
*
* @param string $id Template id
* @param array $args allow modifying the behavior
*
* @return array|WP_Error
*/
public function get_cloud_template_data( $id, $args = [] ) {
if ( ! $this->has_cloud_templates() ) {
return new WP_Error( 'invalid_element', __( 'Element does not have cloud templates', 'thrive-cb' ) );
}
$args = wp_parse_args(
$args,
array(
'type' => $this->tag(),
)
);
return tve_get_cloud_template_data(
$this->get_template_tag(),
array(
'id' => $id,
'type' => $args['type'],
'post_id' => empty( $args['post_id'] ) ? '' : $args['post_id'],
)
);
}
/**
* Allows cloud templates to have a different tag than this element
*
* @return string
*/
public function get_template_tag() {
return $this->tag();
}
}

View File

@@ -0,0 +1,96 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Color_Manager
*
* @project : thrive-visual-editor
*/
class TCB_Color_Manager {
/**
* @var TCB_Color_Manager
*/
private static $instance;
/**
* @var boolean
*/
private $is_multisite = false;
/**
* Dynamically computed depending on the context
*
* Modified in Theme/Content/Landing Builder websites to suite our needs
*
* @var string
*/
private $option_name;
/**
* TCB_Color_Manager constructor.
*/
private function __construct() {
$this->is_multisite = apply_filters( 'tcb_allow_global_colors_multisite', false );
$this->option_name = apply_filters( 'tcb_global_colors_option_name', 'thrv_global_colours' );
}
/**
* @return TCB_Color_Manager
*/
public static function get_instance() {
if ( self::$instance === null ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Updates the color list with the provided color array
*
* @param array $colors
*/
public function update_list( $colors = [] ) {
if ( $this->is_multisite ) {
update_site_option( $this->option_name, $colors );
} else {
update_option( $this->option_name, $colors );
}
}
/**
* Returns the color list
*
* @return array
*/
public function get_list() {
if ( $this->is_multisite ) {
$colors = get_site_option( $this->option_name, [] );
} else {
$colors = get_option( $this->option_name, [] );
}
/**
* Allow other functionality to be injected here to append or modify the color list
*
* Used in ThriveTheme Builder Website
*
* @param array $colors
*/
return apply_filters( 'tcb_global_colors_list', $colors );
}
}
function tcb_color_manager() {
return TCB_Color_Manager::get_instance();
}

View File

@@ -0,0 +1,589 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Contact_Form
*/
class TCB_Contact_Form {
private $posted_data = [];
private $empty_posted_data = true;
private $invalid_fields = [];
private $types = [];
private $config_parsing_error;
private $blog_name;
/**
* The permalink the Contact Form is located in
*
* @var string
*/
private $permalink = '';
private $config;
/**
* The ID of the post the Contact Form is located in
*/
private $post_id;
/**
* An array containing security info for backend validation
*
* @var array
*/
private $security = [];
/**
* Used on Zapier CF element connection
*
* @var array
*/
private $_excluded_inputs = [
'zapier_send_ip',
'zapier_tags',
];
/**
* TCB_Contact_Form constructor.
*
* @param array $data
*/
public function __construct( $data = [] ) {
$data = $this->sanitize_posted_data( $data );
$has_config = $this->setup_config( $data );
if ( $has_config ) {
$this->setup_posted_data( $data );
$this->blog_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
$this->permalink = get_permalink( $this->post_id );
if ( tve_is_code_debug() ) {
add_action( 'wp_mail_failed', [ $this, 'mail_error' ] );
}
}
}
/**
* Setup the Posted Data
*
* @param array $data
*/
private function setup_posted_data( $data = [] ) {
$this->post_id = $data['post_id'];
$this->types = static::get_types();
foreach ( $data as $type => $value ) {
/**
* Filter the Post Data
*/
if ( isset( $this->types[ $type ] ) || in_array( (string) $type, $this->_excluded_inputs, true ) ) {
$this->posted_data[ $type ] = $value;
}
}
}
/**
* @param array $data
*
* @return bool
*/
private function setup_config( $data = [] ) {
if ( empty( $data['config'] ) ) {
$this->config_parsing_error = __( 'ERROR: Empty Config', 'thrive-cb' );
return false;
}
$this->config = base64_decode( $data['config'] );
if ( false !== $this->config ) {
$this->config = thrive_safe_unserialize( $this->config );
if ( is_array( $this->config ) ) {
/**
* Filter if a specific string can be found in content edited with thrive architect
*
* @param boolean $has_string
* @param string $string
* @param int $post_id
*
* @return boolean
*/
$valid_config = apply_filters( 'tcb_architect_content_has_string', false, $data['config'], (int) $data['post_id'] );
if ( ! $valid_config ) {
$this->config_parsing_error = __( 'ERROR: Invalid Config', 'thrive-cb' );
return false;
}
}
}
if ( empty( $this->config['to_email'] ) || empty( $this->config['submit'] ) ) {
$this->config_parsing_error = __( 'ERROR: Invalid Config', 'thrive-cb' );
return false;
}
$this->security = json_decode( wp_unslash( $data['security'] ), true );
if ( ! is_array( $this->security ) || (int) $this->security['check'] !== 1 ) {
$this->config_parsing_error = __( 'ERROR: Security Warning', 'thrive-cb' );
return false;
}
$this->config = wp_array_slice_assoc( $this->config, [ 'to_email', 'submit' ] );
return true;
}
/**
* Submit Form: Validate and Anti Spam Checks
*
* @return array
*/
public function submit() {
$return = [
'errors' => [],
'success' => 0,
];
// Form connected to Zapier
if ( ( isset( $this->posted_data['zapier_send_ip'] ) || isset( $this->posted_data['zapier_tags'] ) ) && class_exists( 'Thrive_Dash_List_Manager', false ) ) {
// API connection check
if ( ! array_key_exists( 'zapier', Thrive_Dash_List_Manager::available() ) ) {
$return['errors'][] = __( 'Please create a Zapier API connection', 'thrive-cb' );
return $return;
}
// Build params and call Zapier's contact form trigger
$arguments = $this->posted_data;
$arguments['optin_hook'] = 'cf-optin';
$zapier_instance = Thrive_Dash_List_Manager::connectionInstance( 'zapier' );
$zapier_subscribe = $zapier_instance->addSubscriber( '', $arguments );
$return['errors'][] = $zapier_subscribe;
if ( true === filter_var( $zapier_subscribe, FILTER_VALIDATE_BOOLEAN ) ) {
$return = [
'errors' => [],
'success' => 1,
];
}
return $return;
}
if ( ! empty( $this->config_parsing_error ) ) {
$return['errors'][] = $this->config_parsing_error;
return $return;
}
if ( ! $this->is_valid() ) {
if ( $this->empty_posted_data ) {
$return['errors'][] = __( 'The posted data is completely empty!', 'thrive-cb' );
}
foreach ( $this->invalid_fields as $invalid_field ) {
$return['errors'][] = $this->types[ $invalid_field ]['validation_error'];
}
} elseif ( $this->is_spam() ) {
$return['errors'][] = __( 'Invalid reCAPTCHA!', 'thrive-cb' );
} elseif ( $this->mail() ) {
$return['success'] = 1;
} else {
$return['errors'][] = __( 'Ups, we encountered some issues, please try again later!', 'thrive-cb' );
}
return $return;
}
/**
* Validates The Contact Form based on field type
*
* @return bool
*/
private function is_valid() {
if ( empty( $this->posted_data ) ) {
return false;
}
foreach ( $this->posted_data as $type => $value ) {
if ( empty( $value ) ) {
continue;
}
$this->empty_posted_data = false;
if ( 'email' === $type && ! is_email( $value ) ) {
$this->invalid_fields[] = $type;
}
if ( 'url' === $type && false === filter_var( ( strpos( $value, 'http' ) !== 0 ? 'http://' . $value : $value ), FILTER_VALIDATE_URL ) ) {
$this->invalid_fields[] = $type;
}
if ( 'phone' === $type && ! preg_match( '%^[+]?[0-9\(\)/ -]*$%', $value ) ) {
$this->invalid_fields[] = $type;
}
}
return empty( $this->invalid_fields ) && $this->empty_posted_data === false;
}
/**
* Ensures that the request is not SPAM
*
* @return bool
*/
private function is_spam() {
if ( $this->security['has_recaptcha'] ) {
if ( empty( $this->posted_data['g-recaptcha-response'] ) ) {
return true;
}
/**
* Google reCAPTCHA verification
*/
$captcha_api = Thrive_Dash_List_Manager::credentials( 'recaptcha' );
$_captcha_params = array(
'response' => $this->posted_data['g-recaptcha-response'],
'secret' => empty( $captcha_api['secret_key'] ) ? '' : $captcha_api['secret_key'],
'remoteip' => ! empty( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( $_SERVER['REMOTE_ADDR'] ) : '',
);
$request_captcha = tve_dash_api_remote_post( 'https://www.google.com/recaptcha/api/siteverify', [ 'body' => $_captcha_params ] );
$response = json_decode( wp_remote_retrieve_body( $request_captcha ) );
if ( empty( $response ) || false === $response->success ) {
return true;
}
}
return false;
}
/**
* Sends the actual mail
*
* @return bool
*/
private function mail() {
if ( $this->config['submit']['send_confirmation_email'] && ! empty( $this->posted_data['email'] ) ) {
/**
* We an email to the user that completed the contact form
*/
$user_email = array(
'to' => $this->posted_data['email'],
'subject' => ! empty( $this->config['submit']['confirmation_subject'] ) ? $this->config['submit']['confirmation_subject'] : __( '[%s] Contact Form submission confirmation', 'thrive-cb' ),
'message' => $this->get_user_email_message(),
'headers' => [ 'Content-Type: text/html; charset=UTF-8' ],
);
if ( $this->config['submit']['sender_personalized'] ) {
add_filter( 'wp_mail_from', [ $this, 'user_from_mail' ] );
add_filter( 'wp_mail_from_name', [ $this, 'user_from_mail_name' ] );
$user_email['headers'][] = 'reply-to: ' . $this->config['submit']['reply_to'];
}
wp_mail( $user_email['to'], sprintf( $user_email['subject'], $this->blog_name ), $user_email['message'], $user_email['headers'] );
remove_filter( 'wp_mail_from', [ $this, 'user_from_mail' ] );
remove_filter( 'wp_mail_from_name', [ $this, 'user_from_mail_name' ] );
/**
* Added action after the contact form is submitted to capture the user details that is being sent
*
* Useful for other functionality to be hooked here
*/
do_action( 'tcb_contact_form_user_mail_after_send', $this->posted_data );
}
/**
* We send an email to the admin informing him that the contact form has been submitted by a user
*/
$admin_email_data = $this->get_admin_email_data();
$admin_email = [
'to' => $this->config['to_email']['to'],
'subject' => $admin_email_data['subject'],
'message' => $admin_email_data['message'],
'headers' => [ 'Content-Type: text/html; charset=UTF-8' ],
];
if ( ! empty( $this->posted_data['email'] ) ) {
$admin_email['headers'][] = 'reply-to: ' . $this->posted_data['email'];
}
if ( ! empty( $this->config['to_email']['cc'] ) ) {
/**
* We strip the white spaces of the email list in case user inputs something like this "test1@thrive.com , test2@thrive.com"
*/
$admin_email['headers'][] = 'cc: ' . str_replace( ' ', '', $this->config['to_email']['cc'] );
}
if ( ! empty( $this->config['to_email']['bcc'] ) ) {
/**
* We strip the white spaces of the email list in case user inputs something like this "test1@thrive.com , test2@thrive.com"
*/
$admin_email['headers'][] = 'Bcc: ' . str_replace( ' ', '', $this->config['to_email']['bcc'] );
}
$admin_email = wp_unslash( $admin_email );
return wp_mail( $admin_email['to'], $admin_email['subject'], $admin_email['message'], $admin_email['headers'] );
}
/**
* Function used to display errors from wp_mail function
*
* @param WP_Error $wp_error
*/
public function mail_error( $wp_error ) {
echo '<pre>';
print_r( $wp_error );
echo '<pre>';
}
/**
* sanitize $_POST
*
* @param $value
*
* @return array|string
*/
private function sanitize_posted_data( $value ) {
if ( is_array( $value ) ) {
$value = array_map( [ $this, 'sanitize_posted_data' ], $value );
} elseif ( is_string( $value ) ) {
$value = wp_check_invalid_utf8( $value );
$value = wp_kses_no_null( $value );
}
return $value;
}
/**
* Returns the admin email text
*
* @return array
*/
private function get_admin_email_data() {
$email_data = '';
$subject = str_replace(
array(
'[form_url_slug]',
),
array(
trim( parse_url( $this->permalink, PHP_URL_PATH ), '/' ),
),
$this->config['to_email']['subject']
);
foreach ( $this->posted_data as $type => $value ) {
if ( in_array( $type, [ 'g-recaptcha-response' ] ) ) {
/**
* We have done this to ensure some info is left out of the admin email.
* Example: google reCaptcha code
*/
continue;
}
/**
* Build the table for admin mail
*/
$type_cell = '<td>' . $this->types[ $type ]['label'] . ':</td>';
$value_cell = '<td>' . $value . '</td>';
$email_data .= '<tr>' . $type_cell . $value_cell . '</tr>';
if ( empty( $this->types[ $type ]['shortcode'] ) ) {
continue;
}
/**
* Replace Subject Tags
*/
$subject = str_replace( $this->types[ $type ]['shortcode'], $value, $subject );
}
$posted_data = '<table>' . $email_data . '</table>';
$date_row = '<tr><td>' . __( 'Date', 'thrive-cb' ) . ':</td><td>' . date_i18n( 'F j, Y' ) . '</td></tr>';
$time_row = '<tr><td>' . __( 'Time', 'thrive-cb' ) . ':</td><td>' . date_i18n( 'g:i a' ) . '</td></tr>';
$date_info = '<table>' . $date_row . $time_row . '</table>';
$message = $posted_data . '<br>' . '----' . '<br>' . $date_info;
$message = nl2br( $message );
return [
'subject' => $subject,
'message' => $message,
];
}
/**
* Returns the user email message
*
* @return string
*/
private function get_user_email_message() {
$message = str_replace(
array(
'[wp_site_title]',
'[form_url_slug]',
),
array(
$this->blog_name,
trim( parse_url( $this->permalink, PHP_URL_PATH ), '/' ),
),
$this->config['submit']['confirmation_message']
);
foreach ( $this->posted_data as $type => $value ) {
if ( empty( $this->types[ $type ]['shortcode'] ) ) {
continue;
}
$message = str_replace( $this->types[ $type ]['shortcode'], $value, $message );
}
$message = nl2br( $message );
return $message;
}
/**
* Modifies the from email address
*
* @return string
*/
public function user_from_mail() {
return $this->config['submit']['from_email'];
}
/**
* Modifies the from email name
*
* @return string
*/
public function user_from_mail_name() {
return wp_specialchars_decode( $this->config['submit']['from_name'], ENT_QUOTES );
}
/**
* Returns Contact Form Field Types
*
* @return array
*/
public static function get_types() {
return array(
'first_name' => array(
'label' => __( 'First Name', 'thrive-cb' ),
'tag_name' => 'input',
'defaults' => array(
'label' => __( 'First Name', 'thrive-cb' ),
'placeholder' => __( 'John', 'thrive-cb' ),
),
'type' => 'text',
'shortcode' => '[first_name]',
'validation_error' => __( 'Invalid First Name', 'thrive-cb' ),
),
'last_name' => array(
'label' => __( 'Last Name', 'thrive-cb' ),
'tag_name' => 'input',
'type' => 'text',
'defaults' => array(
'label' => __( 'Last Name', 'thrive-cb' ),
'placeholder' => __( 'Doe', 'thrive-cb' ),
),
'shortcode' => '[last_name]',
'validation_error' => __( 'Invalid Last Name', 'thrive-cb' ),
),
'full_name' => array(
'label' => __( 'Full Name', 'thrive-cb' ),
'tag_name' => 'input',
'type' => 'text',
'defaults' => array(
'label' => __( 'Full Name', 'thrive-cb' ),
'placeholder' => __( 'John Doe', 'thrive-cb' ),
),
'shortcode' => '[full_name]',
'validation_error' => __( 'Invalid Full Name', 'thrive-cb' ),
),
'email' => array(
'label' => __( 'Email Address', 'thrive-cb' ),
'tag_name' => 'input',
'type' => 'email',
'defaults' => array(
'label' => __( 'Email Address', 'thrive-cb' ),
'placeholder' => __( 'j.doe@inbox.com', 'thrive-cb' ),
),
'shortcode' => '[user_email]',
'validation_error' => __( 'Invalid Email', 'thrive-cb' ),
),
'message' => array(
'label' => __( 'Message', 'thrive-cb' ),
'tag_name' => 'textarea',
'type' => '',
'defaults' => array(
'label' => __( 'Message', 'thrive-cb' ),
'placeholder' => __( 'Type your message here...', 'thrive-cb' ),
),
'validation_error' => __( 'Invalid Message', 'thrive-cb' ),
),
'phone' => array(
'label' => __( 'Phone Number', 'thrive-cb' ),
'tag_name' => 'input',
'type' => 'tel',
'defaults' => array(
'label' => __( 'Phone Number', 'thrive-cb' ),
'placeholder' => __( '+1 555 2368', 'thrive-cb' ),
),
'shortcode' => '[user_phone]',
'validation_error' => __( 'Invalid Phone', 'thrive-cb' ),
),
'url' => array(
'label' => __( 'Website', 'thrive-cb' ),
'tag_name' => 'input',
'type' => 'url',
'defaults' => array(
'label' => __( 'Website', 'thrive-cb' ),
'placeholder' => __( 'https://yourwebsite.com/', 'thrive-cb' ),
),
'shortcode' => '[user_url]',
'validation_error' => __( 'Invalid URL', 'thrive-cb' ),
),
'g-recaptcha-response' => array(
'label' => __( 'Recaptcha', 'thrive-cb' ),
'tag_name' => 'recaptcha',
'type' => 'g-recaptcha-response',
'defaults' => array(
'label' => __( 'ReCaptcha', 'thrive-cb' ),
'placeholder' => __( 'ReCaptcha', 'thrive-cb' ),
),
'shortcode' => '',//Google reCAPTCHA Should Not have a shortcode attached.
'validation_error' => __( 'Invalid reCAPTCHA', 'thrive-cb' ),
),
);
}
}

View File

@@ -0,0 +1,155 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
if ( ! class_exists( 'TCB_Landing_Page_Cloud_Templates_Api' ) ) {
require_once TVE_TCB_ROOT_PATH . 'landing-page/inc/TCB_Landing_Page_Transfer.php';
}
class TCB_Content_Handler extends TCB_Landing_Page_Transfer {
/**
* Zip data
*
* @var string
*/
protected $cfg_name = 'tve_content.json';
protected $html_file_name = 'tve_content.html';
protected $archive_prefix = 'tve-content-';
protected $thumbnail_prefix = 'content-';
/**
* hold a copy of the config array for the import process
*
* @var array
*/
private $import_config = [];
/**
* holds the current WP Page (or landing page)
*
* @var WP_Post
*/
private $current_page = null;
/**
* Whether or not LP vars should be replaced by their values on export
*/
protected $allow_lp_vars = true;
/**
* Whether or not we expect a LP to be imported
*
* @return bool
*/
protected function should_check_lp_page() {
return false;
}
public function get_cfg_name() {
return $this->cfg_name;
}
public function get_html_file_name() {
return $this->html_file_name;
}
public function import( $file, $page_id ) {
$this->importValidateFile( $file );
$zip = new ZipArchive();
if ( $zip->open( $file ) !== true ) {
throw new Exception( __( 'Could not open the archive file', 'thrive-cb' ) );
}
/* 1. read config & validate */
$config = $this->importReadConfig( $zip );
$this->import_config = $config;
$this->current_page = get_post( $page_id );
/* 2. import all the images (add them as attachments) and store the links in the config array */
$this->importImages( $config, $zip );
/* 3. import all lightboxes (create new posts with type tcb_lightbox) */
$lightbox_id_map = $this->importLightboxes( $config );
/* 4. replace images from config*/
$this->importParseImageLinks( $config );
/* 5. get content*/
$page_content = $zip->getFromName( $this->html_file_name );
/* 6. replace images & lightboxes from content*/
$this->importParseImageLinks( $page_content );
$this->importReplaceLightboxIds( $page_content, $lightbox_id_map );
$this->import_symbols( $config );
if ( ! empty( $config['lightbox'] ) ) {
foreach ( $config['lightbox'] as $old_id => $data ) {
$lb_content = $zip->getFromName( 'lightboxes/' . $old_id . '.html' );
$this->importReplaceLightboxIds( $lb_content, $lightbox_id_map );
$this->importParseImageLinks( $lb_content );
update_post_meta( $lightbox_id_map[ $old_id ], 'tve_updated_post', $lb_content );
}
}
$template_name = basename( $file, '.zip' );
$page_content = $this->replace_content_symbols_on_insert( $page_content );
$config['tve_custom_css'] = $this->replace_content_symbols_on_insert( $config['tve_custom_css'] );
/**
* Change imported content name before saving as template
*
*/
$template_name = apply_filters( 'tve_imported_content_name', $template_name );
$preview_data_url = $this->importThumbnail( $config, $zip );
$preview_data_path = str_replace( wp_upload_dir()['baseurl'], wp_upload_dir()['basedir'], $preview_data_url );
$new_template_data = [
'name' => $template_name,
'content' => $page_content,
'type' => '',
'thumb' => '',
'id_category' => \TCB\UserTemplates\Category::PAGE_TEMPLATE_IDENTIFIER,
'css' => $config['tve_user_custom_css'],
'media_css' => $config['tve_custom_css'],
];
$new_template_data = tve_update_image_size( $preview_data_path, $new_template_data, $preview_data_url );
$template_id = TCB\UserTemplates\Template::insert( $new_template_data );
update_post_meta( $template_id, 'tve_kit_imported', 1 );
return [
'content' => $page_content,
'inline_css' => $config['tve_custom_css'],
'custom_css' => $config['tve_user_custom_css'],
'template_id' => $template_id,
];
}
/**
* Get the generated preview of the LP(it's previously done on save)
*
* @param $page_id
* @param $zip
*
* @return false
*/
protected function exportGeneratedThumbnail( $page_id, $zip ) {
$upload = tve_filter_content_preview_location( wp_upload_dir() );
$path = $upload['path'] . '/' . $this->thumbnail_prefix . $page_id . '.png';
$zip->addEmptyDir( 'thumbnail' );
if ( is_file( $path ) && $zip->addFile( $path, 'thumbnail/' . $this->thumbnail_prefix . $page_id . '.png' ) === false ) {
$zip->deleteName( 'thumbnail' );
return false;
}
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
<?php
class TCB_Editor_Meta_Boxes {
const FLAG = 'tcb-only-meta-boxes';
public static function init() {
add_filter( 'redirect_post_location', [ __CLASS__, 'redirect_post_location' ], 10, 2 );
if ( isset( $_GET[ static::FLAG ] ) ) {
add_filter( 'replace_editor', '__return_true' );
add_action( 'admin_action_edit', [ __CLASS__, 'admin_action_edit' ] );
}
}
public static function admin_action_edit() {
global $hook_suffix, $post;
$post = get_post( $_GET['post'] );
$screen = get_current_screen();
wp_enqueue_media( [ 'post' => $post ] );
/* display all meta boxes */
add_filter( 'hidden_meta_boxes', '__return_empty_array' );
do_action( 'admin_enqueue_scripts', $hook_suffix );
require_once ABSPATH . 'wp-admin/includes/meta-boxes.php';
wp_enqueue_style( 'wp-edit-post' );
wp_enqueue_style( 'buttons' );
wp_enqueue_style( 'common' );
wp_enqueue_style( 'forms' );
wp_enqueue_style( 'edit' );
wp_enqueue_script( 'post' );
wp_print_scripts( [ 'jquery' ] );
wp_enqueue_style( 'tcb-editor-meta-boxes', tve_editor_css( 'editor-meta-boxes.css' ), [], TVE_VERSION );
register_and_do_post_meta_boxes( $post );
include TVE_TCB_ROOT_PATH . '/admin/includes/views/editor-meta-boxes.php';
}
public static function redirect_post_location( $location, $post_id ) {
if ( isset( $_POST['_wp_http_referer'] ) && strpos( $_POST['_wp_http_referer'], static::FLAG ) !== false ) {
$location = add_query_arg( static::FLAG, 1, $location );
}
return $location;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,563 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
require_once plugin_dir_path( __FILE__ ) . 'class-tcb-element-abstract.php';
require_once plugin_dir_path( __FILE__ ) . 'post-list/class-tcb-post-list-sub-element-abstract.php';
require_once plugin_dir_path( __FILE__ ) . 'class-tcb-menu-icon-element-abstract.php';
require_once plugin_dir_path( __FILE__ ) . 'class-tcb-cloud-template-element-abstract.php';
require_once plugin_dir_path( __FILE__ ) . 'elements/class-tcb-lead-generation-element.php';
require_once plugin_dir_path( __FILE__ ) . 'class-tcb-symbol-element-abstract.php';
/**
* Class TCB_Elements
*/
class TCB_Elements {
/**
* Elements instances
*
* @var TCB_Element_Abstract[]
*/
private $_instances = [];
public $pinned_category = 'Pinned';
/**
* @return array
*/
private function categories_order() {
$order = array(
0 => $this->pinned_category,
5 => TCB_Post_List::elements_group_label(),
10 => TCB_Element_Abstract::get_thrive_basic_label(),
20 => TCB_Element_Abstract::get_thrive_advanced_label(),
30 => TCB_Element_Abstract::get_thrive_integrations_label(),
90 => TCB_Element_Abstract::get_widgets_label(),
);
$order = apply_filters( 'tcb_categories_order', $order );
ksort( $order );
return $order;
}
/**
* Include and instantiate all the elements. If folders are encountered, do recursion over them.
*
* @param null $path
*/
private function set_elements( $path = null ) {
$root_path = plugin_dir_path( __FILE__ ) . 'elements/';
/* if there's no recursion, use the root path */
$path = ( $path === null ) ? $root_path : $path;
$items = array_diff( scandir( $path ), [ '.', '..' ] );
foreach ( $items as $item ) {
$item_path = $path . '/' . $item;
/* if the item is a folder, do recursion inside it */
if ( is_dir( $item_path ) ) {
$this->set_elements( $item_path );
}
/* if the item is a file, include it */
if ( is_file( $item_path ) && substr( $item_path, - 3 ) === 'php' ) {
$element = str_replace( [ 'class-tcb-', '-element.php' ], '', $item );
$element = static::capitalize_class_name( $element );
$class = 'TCB_' . $element . '_Element';
require_once $item_path;
if ( class_exists( $class ) ) {
$tag = strtolower( $element );
/** @var TCB_Element_Abstract $instance */
$instance = new $class( $tag );
if ( $instance->is_available() ) {
$this->_instances[ $tag ] = $instance;
}
}
}
}
}
/**
* Include element class and create and instance for that element
*/
private function set() {
$this->set_elements();
$this->_instances = apply_filters( 'tcb_element_instances', $this->_instances, '' );
$order_template = [
'text',
'image',
'button',
'columns',
'section',
'contentbox',
'ct',
'tweet',
'reveal',
'countdown',
'countdownevergreen_template',
'credit',
'html',
'menu',
'commentsdisqus',
'divider',
'commentsfacebook',
'fillcounter',
'gmap',
'icon',
'lead_generation',
'moretag',
'postgrid',
'progressbar',
'social',
'social_follow',
'rating',
'styledlist',
'table',
'toc',
'tabs',
'testimonial',
'toggle',
'responsivevideo',
'wordpress',
'post_title',
'post_thumbnail',
'post_content',
'post_read_more',
'post_author_name',
'post_author_picture',
'post_date',
'post_categories',
'post_tags',
];
$this->_instances = array_merge( array_flip( $order_template ), $this->_instances );
if ( apply_filters( 'tve_include_widgets_in_editor', false ) ) {
$this->load_widgets();
}
/* Allow plugins to remove TCB Elements */
$this->_instances = apply_filters( 'tcb_remove_instances', $this->_instances );
}
/**
* Get all the 3rd party widgets (without the default wordpress widgets).
*
* @return array
*/
public function get_external_widgets() {
global $wp_widget_factory;
$widgets = [];
/* these widgets are added by wordpress - we do not add these because the functionality already exists in TVE/TTB elements */
$blacklisted_widgets = [
'pages',
'calendar',
'archives',
'media_audio',
'media_image',
'media_gallery',
'media_video',
'meta',
'search',
'text',
'categories',
'recent-posts',
'recent-comments',
'rss',
'tag_cloud',
'nav_menu',
'custom_html',
];
foreach ( $wp_widget_factory->widgets as $wp_widget ) {
if ( ! in_array( $wp_widget->id_base, $blacklisted_widgets, true ) ) {
$widgets[] = $wp_widget;
}
}
/**
* Filter allowed widgets in the editor
*
* @param WP_Widget[] $widgets
*
* @return array
*/
return apply_filters( 'tcb_editor_widgets', $widgets );
}
/**
* Load widgets in the editor (at the moment, only inside the theme builder).
*/
private function load_widgets() {
require_once plugin_dir_path( __FILE__ ) . 'class-tcb-widget-element.php';
$widgets = $this->get_external_widgets();
if ( ! empty( $widgets ) ) {
foreach ( $widgets as $wp_widget ) {
try {
$widget = new TCB_Widget_Element( $wp_widget );
$this->_instances[ $widget->tag() ] = $widget;
} catch ( Exception $e ) {
//nothing for now.
}
}
/* stop The Events Calendar (https://wordpress.org/plugins/the-events-calendar/) from enqueueing scripts - something from there breaks the editor */
add_filter( 'tribe_events_assets_should_enqueue_admin', '__return_false' );
/* temporarily modify the current screen in order to pass widget checks (which verify if we're on .../wp-admin/widgets.php) */
global $current_screen, $pagenow;
$prev_screen = $current_screen;
$current_screen = WP_Screen::get( 'widgets.php' );
$pagenow = 'widgets.php';
/* do actions in order to enqueue scrips and styles from widgets inside the editor */
do_action( 'admin_enqueue_scripts', 'widgets.php' );
do_action( 'admin_print_styles-widgets.php' );
do_action( 'admin_print_scripts-widgets.php' );
do_action( 'admin_print_footer_scripts-widgets.php' );
do_action( 'admin_footer-widgets.php' );
$current_screen = $prev_screen;
$pagenow = $prev_screen === null ? 0 : $prev_screen->id;
}
}
/**
* Get elements to be displayed on sidebar, grouped in categories
*
* @return array
* @throws Exception
*/
public function get_for_front() {
$elements = $this->get();
$all = [];
$pinned_elements = get_user_option( 'tcb_pinned_elements' );
if ( empty( $pinned_elements ) ) {
$pinned_elements = [];
}
$order = $this->categories_order();
foreach ( $order as $category ) {
$all[ $category ] = [];
}
foreach ( $elements as $element ) {
if ( ! $element->hide() && ! $element->promoted() ) {
$element->pinned = in_array( $element->tag(), $pinned_elements );
$category = $element->pinned ? $this->pinned_category : $element->category();
$all[ $category ][] = $element;
}
}
return $all;
}
/**
* Returns all the promoted elements
*
* @return array
*/
public function get_promoted() {
$elements = $this->get();
$promoted = [];
foreach ( $elements as $element ) {
/* also check if the element is hidden ( there are cases where we don't want to display elements in the Symbols Dashboard, TU, TQB, etc */
if ( $element->promoted() && ! $element->hide() ) {
$promoted[] = $element;
}
}
return $promoted;
}
/**
* Get all elements available in TCB. Uses tcb_elements filter to allow extending
*
* @param $element string|null $element element to get.
*
* @return TCB_Element_Abstract[]|null
*/
public function get( $element = null ) {
if ( empty( $this->_instances ) ) {
$this->set();
}
/**
* Action filter
*
* Allows extending existing elements, or adding new functionality
*
* @param array $elements
*
* @since 2.0
*
*/
$elements = apply_filters( 'tcb_elements', $this->_instances );
if ( null === $element ) {
return $elements;
}
if ( ! isset( $elements[ $element ] ) ) {
return null;
}
/**
* Action filter
*
* Allows extending the configuration for a single element
*
* @param array $config element configuration
*
* @since 2.0
*
*/
return apply_filters( 'tcb_element_' . $element, $elements[ $element ] );
}
/**
* Outputs the html containing the menu components for all TCB elements
*
* @return void
*/
public function output_components() {
$menu_folder = TVE_TCB_ROOT_PATH . 'inc/menu/';
foreach ( $this->menu_components() as $component ) {
/**
* Action filter
*
* Allows insertion of custom Menu components in TCB.
*
* @param string $file default file path
*
* @since 2.0
*
*/
$file = apply_filters( 'tcb_menu_path_' . $component, $menu_folder . $component . '.php' );
if ( empty( $file ) || ! is_file( $file ) ) {
continue;
}
include $file;
}
do_action( 'tcb_output_components' );
}
/**
* Component options that apply to all elements
*
* @return array
*/
public function component_options() {
return array(
'animation' => tcb_event_manager_config(),
);
}
/**
* Resolves all menu components included in the elements config
*
* @return array
*/
public function menu_components() {
$components = [ 'general' ];
foreach ( $this->get() as $key => $element ) {
$c = $element->components();
if ( empty( $c ) || ! is_array( $c ) ) {
continue;
}
$components = array_merge( $components, array_keys( $c ) );
}
return array_unique( $components );
}
/**
* Return element static layout
*
* @return string
*/
public function layout() {
$layout = '';
foreach ( $this->get() as $key => $element ) {
$content = $element->layout();
if ( ! empty( $content ) ) {
$layout .= '<div data-elem="' . $key . '">' . $content . '</div>';
}
}
return $layout;
}
/**
* Displays custom sidebars needed by elements.
* Example: Table element - it has a custom sidebar layout for when editing the cells
*
* @return array
*/
public function custom_sidebars() {
$sidebars = array(
/**
* Default sidebar for EDIT-MODE - currently an empty div. if needed, create a template for it
*/
'edit-mode' => array(
'template' => '',
'title' => __( 'Edit Mode', 'thrive-cb' ),
),
);
foreach ( $this->get() as $element ) {
$sidebars = array_merge( $sidebars, $element->get_custom_sidebars() );
}
return $sidebars;
}
/**
* Prepares the elements config for javascript.
*
* @return array
* @throws Exception
*/
public function localize() {
$elements = [];
foreach ( $this->get() as $key => $element ) {
$elements[ $key ] = $element->config();
}
/**
* Allows filtering configuration for all elements
*
* @param array $elements configuration data
*
* @return array
*/
return apply_filters( 'tcb_elements_localize', $elements );
}
/**
* Gets the templates category for category autocomplete widget
*
* @return array
*/
public function user_templates_category() {
$categories = [];
foreach ( TCB\UserTemplates\Category::get_all() as $category ) {
$categories[] = (object) [
'id' => $category['id'],
'text' => $category['name'],
'value' => $category['name'],
];
}
return $categories;
}
/**
* Capitalize class name => transforms lead-generation into Lead_Generation
*
* @param $element_file_name
*
* @return string
*/
public static function capitalize_class_name( $element_file_name ) {
$chunks = explode( '-', $element_file_name );
$chunks = array_map( 'ucfirst', $chunks );
return implode( '_', $chunks );
}
/**
* Instantiate an element class identified by $element_type or return it if it already exists in the instances array
*
* @param string $element_type
*
* @return null|TCB_Element_Abstract
*/
public function element_factory( $element_type ) {
if ( isset( $this->_instances[ $element_type ] ) ) {
return $this->_instances[ $element_type ];
}
$instance = null;
/**
* Internal TCB elements
*/
$class_name = 'TCB_' . static::capitalize_class_name( $element_type ) . '_Element';
if ( ! class_exists( $class_name ) ) {
$file = plugin_dir_path( __FILE__ ) . 'elements/class-tcb-' . str_replace( '_', '-', $element_type ) . '-element.php';
if ( file_exists( $file ) ) {
include $file;
}
}
if ( class_exists( $class_name ) ) {
$instance = new $class_name( $element_type );
}
if ( ! isset( $instance ) ) {
/**
* Try out also possible external class instances
*/
$external_instances = apply_filters( 'tcb_element_instances', [], $element_type );
if ( isset( $external_instances[ $element_type ] ) ) {
$instance = $external_instances[ $element_type ];
}
}
return $instance;
}
}
global $tcb_elements;
/**
* Singleton instantiator for TCB_Elements
*
* @return TCB_Elements
*/
function tcb_elements() {
global $tcb_elements;
if ( ! isset( $tcb_elements ) ) {
$tcb_elements = new TCB_Elements();
}
return $tcb_elements;
}

View File

@@ -0,0 +1,244 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Main class for handling the editor page related stuff
*
* Class TCB_Editor_Page
*/
class TCB_Font_Manager {
/**
* Instance
*
* @var TCB_Font_Manager
*/
private static $instance;
/**
* Singleton instance method
*
* @return TCB_Font_Manager
*/
public static function instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Return all fonts needed for font manager
*
* @return array
*/
public function all_fonts() {
$fonts = array(
'google' => array(
'label' => __( 'Google Fonts', 'thrive-cb' ),
'fonts' => [],
'search_priority' => 99,
),
'safe' => array(
'label' => __( 'Web Safe Fonts', 'thrive-cb' ),
'fonts' => static::safe_fonts(),
'search_priority' => 1,
),
'custom' => array(
'label' => __( 'Custom Fonts', 'thrive-cb' ),
'fonts' => $this->custom_fonts(),
'search_priority' => 1,
),
);
/**
* Compatibility with the "Font Library" plugin
*/
if ( tve_font_library()::is_wordpress_version_supported() ) {
$fonts['library'] = array(
'label' => __( 'Font Library', 'thrive-cb' ),
'fonts' => static::font_library_fonts(),
'search_priority' => 1,
);
}
/**
* Compatibility with the "Custom Fonts" plugin
*/
if ( class_exists( 'Bsf_Custom_Fonts_Taxonomy' ) ) {
$bsf = [];
if ( version_compare( BSF_CUSTOM_FONTS_VER, '2.0.0', '<' ) === true ) {
foreach ( Bsf_Custom_Fonts_Taxonomy::get_fonts() as $font_face => $urls ) {
$bsf [ $font_face ] = [
'family' => $font_face,
'variants' => [],
'subsets' => '',
];
}
} else if ( version_compare( BSF_CUSTOM_FONTS_VER, '2.0.0', '>=' ) === true ) {
if ( class_exists( 'Bsf_Custom_Fonts_Render', false ) ) {
$custom_fonts = Bsf_Custom_Fonts_Render::get_instance()->get_existing_font_posts();
foreach ( $custom_fonts as $key => $font_id ) {
$font_face = get_the_title( $font_id );
$bsf [ $font_id ] = [
'family' => $font_face,
'variants' => [],
'subsets' => '',
];
}
}
}
if ( $bsf ) {
$fonts['custom_fonts_plugin'] = array(
'label' => __( 'Custom Fonts Plugin', 'thrive-cb' ),
'fonts' => $bsf,
'search_priority' => 1,
);
}
}
return $fonts;
}
/**
* Return array of fonts from font library
*
* @return array
*/
public static function font_library_fonts() {
$fonts = [];
$response = tve_font_library()->endpoint->get_fonts();
$fonts = $response->data ?? [];
//Sort array of font objects by the name key.
usort( $fonts, function ( $a, $b ) {
return strcmp( $a['name'], $b['name'] );
} );
// Move fontFamily key to family key for each item in the array.
// This is to maintain consistency with other font sources.
foreach ( $fonts as $key => $font ) {
$fonts[ $key ]['family'] = $font['fontFamily'];
unset( $fonts[ $key ]['fontFamily'] );
}
return $fonts;
}
/**
* Return array of custom fonts
*
* @return array
*/
public function custom_fonts() {
$custom_fonts = json_decode( get_option( 'thrive_font_manager_options' ), true );
$imported_fonts = Tve_Dash_Font_Import_Manager::getImportedFonts();
if ( ! is_array( $custom_fonts ) ) {
$custom_fonts = [];
}
$imported_keys = [];
foreach ( $imported_fonts as $imp_font ) {
$imported_keys[] = $imp_font['family'];
}
$return = [];
foreach ( $custom_fonts as $font ) {
$return[ $font['font_name'] ] = array(
'family' => $font['font_name'],
'regular_weight' => intval( $font['font_style'] ),
'class' => $font['font_class'],
);
}
return $return;
}
/**
* Return safe fonts array
*
* @return array
*/
public static function safe_fonts() {
return array(
array(
'family' => 'Georgia, serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Palatino Linotype, Book Antiqua, Palatino, serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Times New Roman, Times, serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Arial, Helvetica, sans-serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Arial Black, Gadget, sans-serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Comic Sans MS, cursive, sans-serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Impact, Charcoal, sans-serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Lucida Sans Unicode, Lucida Grande, sans-serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Tahoma, Geneva, sans-serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Trebuchet MS, Helvetica, sans-serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Verdana, Geneva, sans-serif',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Courier New, Courier, monospace',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
array(
'family' => 'Lucida Console, Monaco, monospace',
'variants' => [ 'regular', 'italic', '600' ],
'subsets' => [ 'latin' ],
),
);
}
}

View File

@@ -0,0 +1,106 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package TCB2.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class TCB_Icon_Manager
*
* Holds the whole logic of icons
* All types of icons
*/
class TCB_Icon_Manager {
/**
* Main entry point and executed at inclusion
*/
static public function init() {
self::init_hooks();
}
private static function init_hooks() {
/**
* enqueue icon pack for editor or
* if the post has in post meta flag set
*/
if ( is_editor_page() && tve_is_post_type_editable( get_post_type( get_the_ID() ) ) || tve_get_post_meta( get_the_ID(), 'thrive_icon_pack' ) ) {
add_action( 'wp_enqueue_scripts', [ 'TCB_Icon_Manager', 'enqueue_icon_pack' ] );
}
}
/**
* Get retina icons from dashboard and also if the imported page had retina icons too
*
* @param null $post_id - edited page id
*
* @return array
*/
public static function get_custom_icons( $post_id = null ) {
if ( empty( $post_id ) ) {
$post_id = get_the_ID();
}
$icon_data = get_option( 'thrive_icon_pack', [] );
if ( empty( $icon_data['icons'] ) ) {
$icon_data['icons'] = [];
}
$icon_data['icons'] = apply_filters( 'tcb_get_extra_icons', $icon_data['icons'], $post_id ); //
return [
'style' => 'icomoon',
'prefix' => 'icon',
'icons' => $icon_data['icons'],
];
}
/**
* Enqueue Fontawesome and Material icons css styles
* Needed for icon modal to use fonts instead of svgs
*/
public static function enqueue_fontawesome_styles() {
$license = 'use';
if ( get_option( 'tve_fa_kit', '' ) ) {
$license = 'pro';
}
tve_enqueue_style( 'tve_material', '//fonts.googleapis.com/css?family=Material+Icons+Two+Tone' );
tve_enqueue_style( 'tve_material_community', '//cdn.materialdesignicons.com/5.3.45/css/materialdesignicons.min.css' );
tve_enqueue_style( 'tve_fa', "//$license.fontawesome.com/releases/v6.7.1/css/all.css" );
}
/**
* Enqueue the CSS for the icon pack used by the user
*
* @return false|string url
*/
public static function enqueue_icon_pack() {
$handle = 'thrive_icon_pack';
if ( wp_style_is( $handle, 'enqueued' ) ) {
return false;
}
$icon_pack = get_option( 'thrive_icon_pack' );
if ( empty( $icon_pack['css'] ) ) {
return false;
}
$css_url = $icon_pack['css'];
$css_version = isset( $icon_pack['css_version'] ) ? $icon_pack['css_version'] : TVE_VERSION;
$_url = tve_url_no_protocol( $css_url );
wp_enqueue_style( $handle, $_url, [], $css_version );
return $_url . '?ver=' . $css_version;
}
}
add_action( 'wp', [ 'TCB_Icon_Manager', 'init' ] );

View File

@@ -0,0 +1,296 @@
<?php
/**
* Class TCB_Lightbox
*
* This file is only included when TCB is installed as a stand-alone plugin
*/
class TCB_Lightbox extends TCB_Post {
public function get_html() {
if ( ! $this->post || ( $this->post && $this->post->post_status === 'trash' ) ) {
return '';
}
$lightbox_id = $this->post->ID;
$lightbox_content = str_replace( ']]>', ']]&gt;', apply_filters( 'the_content', $this->post_content ) );
$config = $this->globals();
return sprintf(
'<div%s id="tve_thrive_lightbox_%s"><div class="tve_p_lb_overlay" data-style="%s" style="%s"%s></div>' .
'<div class="tve_p_lb_content bSe cnt%s tcb-lp-lb" style="%s"%s><div class="tve_p_lb_inner" id="tve-p-scroller" style="%s"><article>%s</article></div>' .
'<a href="javascript:void(0)" class="tve_p_lb_close%s" style="%s"%s title="Close">x</a></div></div>',
empty( $data['visible'] ) ? ' style="display: none"' : '',
$lightbox_id,
$config['overlay']['css'],
$config['overlay']['css'],
$config['overlay']['custom_color'],
$config['content']['class'],
$config['content']['css'],
$config['content']['custom_color'],
$config['inner']['css'],
$lightbox_content,
$config['close']['class'],
$config['close']['css'],
$config['close']['custom_color']
);
}
/**
* Reads the globals saved in TCB2 format
*
* @param array $config
*
* @return array
*/
public function globals_v2( $config ) {
return array(
'overlay' => array(
'css' => '',
'custom_color' => ! empty( $config['overlay_css'] ) ? ' data-css="' . $config['overlay_css'] . '"' : '',
),
'content' => array(
'css' => '',
'class' => '',
'custom_color' => ! empty( $config['content_css'] ) ? ' data-css="' . $config['content_css'] . '"' : '',
),
'close' => array(
'css' => '',
'class' => '',
'custom_color' => ! empty( $config['close_css'] ) ? ' data-css="' . $config['close_css'] . '"' : '',
),
'inner' => [
'css' => '',
],
);
}
/**
* Fetches Lightbox global settings
* Checks if this lightbox has content stored in TCB2
*
* @return array
*/
public function globals() {
$config = $this->meta( 'tve_globals' );
if ( isset( $config['content_css'] ) || isset( $config['close_css'] ) || isset( $config['overlay_css'] ) ) {
/* this is a tcb2-style lightbox */
return $this->globals_v2( $config );
}
$html = array(
'overlay' => array(
'css' => empty( $config['l_oo'] ) ? '' : 'opacity:' . $config['l_oo'],
'custom_color' => empty( $config['l_ob'] ) ? '' : ' data-tve-custom-colour="' . $config['l_ob'] . '"',
),
'content' => array(
'custom_color' => empty( $config['l_cb'] ) ? '' : ' data-tve-custom-colour="' . $config['l_cb'] . '"',
'class' => empty( $config['l_ccls'] ) ? '' : ' ' . $config['l_ccls'],
'css' => '',
),
'inner' => [
'css' => '',
],
'close' => [
'custom_color' => '',
'class' => '',
'css' => '',
],
);
if ( ! empty( $config['l_cimg'] ) ) { // background image
$html['content']['css'] .= "background-image:url('{$config['l_cimg']}');background-repeat:no-repeat;background-size:cover;";
} elseif ( ! empty( $config['l_cpat'] ) ) {
$html['content']['css'] .= "background-image:url('{$config['l_cpat']}');background-repeat:repeat;";
}
if ( ! empty( $config['l_cbs'] ) ) { // content border style
$html['content']['class'] .= ' ' . $config['l_cbs'];
$html['close']['class'] .= ' ' . $config['l_cbs'];
}
if ( ! empty( $config['l_cbw'] ) ) { // content border width
$html['content']['css'] .= "border-width:{$config['l_cbw']};";
$html['close']['css'] .= "border-width:{$config['l_cbw']};";
}
if ( ! empty( $config['l_cmw'] ) ) { // content max width
$html['content']['css'] .= "max-width:{$config['l_cmw']}";
}
// Close Custom Color settings
$html['close']['custom_color'] = empty( $config['l_ccc'] ) ? '' : ' data-tve-custom-colour="' . $config['l_ccc'] . '"';
return $html;
}
/**
* Outputs the editor / preview page for a Thrive Lightbox
*/
public function output_layout() {
if ( is_editor_page() ) {
tve_enqueue_style( 'tve_lightbox_post', tve_editor_css( 'editor_lightbox.css' ) );
}
/**
* Fix added by Paul McCarthy 16th October 2014 - added to solve THesis Child themes not loading CSS in Thrive lightboxes
* Thesis v 2.1.9 loads style sheets for their child themes with this:- add_filter('template_include', [$this, '_skin']);
* The filter isn't applied when the content builder lightbox is loaded because of our template_redirect filter
* This function checks if the theme is Thesis, if so it checks for the existance of the css.css file that all Thesis child themes should have
* If the file is found, it enqueuest the stylesheet in both editor and front end mode.
*/
if ( wp_get_theme() == 'Thesis' && defined( 'THESIS_USER_SKIN_URL' ) && file_exists( THESIS_USER_SKIN . '/css.css' ) ) {
wp_enqueue_style( 'tve_thesis_css', THESIS_USER_SKIN_URL . '/css.css' );
}
$landing_page_dir = plugin_dir_path( dirname( __DIR__ ) ) . 'landing-page';
if ( $for_landing_page = $this->meta( 'tve_lp_lightbox' ) ) {
if ( tve_is_cloud_template( $for_landing_page ) ) {
$config = tve_get_cloud_template_config( $for_landing_page, false );
$css_file = 'templates/css/' . $for_landing_page . '_lightbox.css';
/* only enqueue CSS for v < 2 */
if ( (int) $config['LP_VERSION'] !== 2 && is_file( tcb_get_cloud_base_path() . $css_file ) ) {
/* load up the lightbox style for this landing page */
tve_enqueue_style( 'thrive_landing_page_lightbox', tcb_get_cloud_base_url() . $css_file );
}
} else {
if ( is_file( $landing_page_dir . '/templates/css/' . $for_landing_page . '_lightbox.css' ) ) {
/* load up the lightbox style for this landing page */
tve_enqueue_style( 'thrive_landing_page_lightbox', TVE_LANDING_PAGE_TEMPLATE . '/css/' . $for_landing_page . '_lightbox.css' );
}
}
}
tcb_template( 'layouts/editor-lightbox', [
'lightbox' => $this,
] );
}
/**
* Generate and save a new Thrive Lightbox
*
* @param string $title lightbox title
* @param string $tcb_content
* @param array $tve_globals tve_globals array to save for the lightbox
* @param array $extra_meta_data array of key => value pairs, each will be saved in a meta field for the lightbox
*
* @return int the saved lightbox id
*/
public static function create( $title = '', $tcb_content = '', $tve_globals = [], $extra_meta_data = [] ) {
/* just to make sure that our content filter does not get applied when inserting a (possible) new lightbox */
$GLOBALS['TVE_CONTENT_SKIP_ONCE'] = true;
$lightbox_id = wp_insert_post( [
'post_content' => '',
'post_title' => $title,
'post_status' => 'publish',
'post_type' => 'tcb_lightbox',
] );
foreach ( $extra_meta_data as $meta_key => $meta_value ) {
update_post_meta( $lightbox_id, $meta_key, $meta_value );
}
update_post_meta( $lightbox_id, 'tve_updated_post', $tcb_content );
update_post_meta( $lightbox_id, 'tve_globals', $tve_globals );
unset( $GLOBALS['TVE_CONTENT_SKIP_ONCE'] );
return $lightbox_id;
}
/**
* Updates a Thrive Lightbox
*
* @param int $lightbox_id local lightbox post id
* @param string $title lightbox title
* @param string $tcb_content
* @param array $tve_globals tve_globals array to save for the lightbox
* @param array $extra_meta_data array of key => value pairs, each will be saved in a meta field for the lightbox
*
* @return int the saved lightbox id
*/
public static function update( $lightbox_id, $title = '', $tcb_content = '', $tve_globals = [], $extra_meta_data = [] ) {
/* just to make sure that our content filter does not get applied when inserting a (possible) new lightbox */
$GLOBALS['TVE_CONTENT_SKIP_ONCE'] = true;
$post_data = [
'post_content' => '',
'post_title' => $title,
'post_status' => 'publish',
'post_type' => 'tcb_lightbox',
'ID' => $lightbox_id,
];
wp_update_post( $post_data );
foreach ( $extra_meta_data as $meta_key => $meta_value ) {
update_post_meta( $lightbox_id, $meta_key, $meta_value );
}
update_post_meta( $lightbox_id, 'tve_updated_post', $tcb_content );
update_post_meta( $lightbox_id, 'tve_globals', $tve_globals );
unset( $GLOBALS['TVE_CONTENT_SKIP_ONCE'] );
return $lightbox_id;
}
}
/**
* Instantiates a new TCB_Lightbox helper class
*
* @param null|mixed $post_id
*
* @return TCB_Lightbox
*/
function tcb_lightbox( $post_id = null ) {
return new TCB_Lightbox( $post_id );
}
/**
* Registers the tcb_lightbox post type - only available when TCB is installed as a separate plugin
*/
function tcb_lightbox_init() {
register_post_type( 'tcb_lightbox', array(
'labels' => array(
'name' => __( 'Thrive Lightboxes', 'thrive-cb' ),
'singular_name' => __( 'Thrive Lightbox', 'thrive-cb' ),
'add_new_item' => __( 'Add New Thrive Lightbox', 'thrive-cb' ),
'edit_item' => __( 'Edit Thrive Lightbox', 'thrive-cb' ),
),
'exclude_from_search' => true,
'public' => true,
'has_archive' => false,
'rewrite' => false,
'show_in_nav_menus' => false,
'show_in_menu' => tve_in_architect() && TCB_Product::has_access(),
) );
}
/**
* Hide notices for the tcb_lightbox post type dashboard page
*
* @return void
*/
function tcb_lightbox_admin_footer() {
$screen = tve_get_current_screen_key();
if ( $screen && $screen === 'edit-tcb_lightbox' ) {
echo '<style type="text/css">
#message, .error, .notice, .update-nag, .sbi_notice, .update, .updated {
display: none !important;
}
:not(#_s):not(#_s) .tve-metrics-consent-notice {
display: flex !important;
margin: 0 0 25px 0;
}
</style>';
}
}
/**
* Registers the tcb_lightbox post type
*/
add_action( 'init', 'tcb_lightbox_init' );
add_action( 'admin_footer', 'tcb_lightbox_admin_footer' );

View File

@@ -0,0 +1,516 @@
<?php
/**
* Class TCB_Login_Element_Handler
*
* Handle Login element submit
*/
class TCB_Login_Element_Handler {
public function __construct() {
$this->hooks();
}
public function hooks() {
if ( wp_doing_ajax() ) {
add_action( 'wp_ajax_nopriv_tve_login_submit', [ $this, 'submit' ] );
add_action( 'wp_ajax_tve_login_submit', [ $this, 'submit' ] );
}
add_action( 'tcb_login_action_login', [ $this, 'action_login' ] );
add_action( 'tcb_login_action_register', [ $this, 'action_register' ] );
add_action( 'tcb_login_action_recover_password', [ $this, 'action_recover_password' ] );
add_filter( 'tcb_dynamiclink_data', [ $this, 'dynamiclink_data' ], 100 );
add_shortcode( 'thrive_login_form_shortcode', [ $this, 'login_form_shortcode' ] );
}
/**
* Remove actions and filters that might affect submit action
*/
private function _clear() {
global $WishListMemberInstance;
$is_wl = class_exists( 'WishListMember3', false ) && $WishListMemberInstance instanceof WishListMember3;
if ( true === $is_wl ) {
remove_action( 'template_redirect', [ $WishListMemberInstance, 'Process' ], 1 );
}
}
/**
* Handle Submit action
*/
public function submit() {
$this->_clear();
$data = $_POST;
if ( isset( $data['custom_action'] ) ) {
/**
* Fire a hook for each action of the Login Element
*/
do_action( 'tcb_login_action_' . $data['custom_action'], $data );
}
wp_send_json( [ 'error' => 'ERROR!! No handler provided for the request' ] );
}
/**
* Handle Login Action for Login Element
*
* @param array $data
* @param bool $json_output Whether or not to send the output as a json-encoded response to the browser
*
* @return mixed|void
*/
public function action_login( $data, $json_output = true ) {
$args['user_login'] = isset( $data['username'] ) ? sanitize_text_field( $data['username'] ) : '';
$args['user_password'] = isset( $data['password'] ) ? $data['password'] : '';
$args['remember'] = ! empty( $data['remember_me'] );
/**
* Do not send back the password
*/
unset( $data['password'] );
$user = wp_signon( $args );
$data['success'] = $user instanceof WP_User;
$data['errors'] = $user instanceof WP_Error ? $user->get_error_messages() : [];
/**
* Allow other plugins to manipulate the response
*
* @param array $data array of data to be sent back
*
* @return array
*/
$data = apply_filters( 'tcb_after_user_logged_in', $data );
if ( ! $json_output ) {
return $data;
}
wp_send_json( $data );
}
/**
* Handle Forgot Password Action for Login Element
*
* @param array $data
*/
public function action_recover_password( $data ) {
$response = [
'success' => true,
'errors' => [],
];
$user_login = sanitize_text_field( $data['login'] );
$result = retrieve_password( $user_login );
if ( is_wp_error( $result ) ) {
$response['success'] = false;
$response['errors'] = $result->get_error_messages();
}
wp_send_json( $response );
}
/**
* Registration form submission process
*
* @param array $data
*/
public function action_register( $data ) {
/**
* Handle the WordPress API Connection separately, because if this one fails, there is no point in processing further API connections
*/
add_filter( 'tcb_api_subscribe_connections', function ( $connections, $available, $post_data ) {
if ( ! isset( $connections['wordpress'], $available['wordpress'] ) ) {
$this->send_ajax_error( array(
'error' => __( 'Something went wrong. Please contact site owner', 'thrive-cb' ),
) );
}
/** @var Thrive_Dash_List_Connection_Wordpress $wordpress_api */
$wordpress_api = $available['wordpress'];
$wordpress_api->set_error_type( 'array' );
$submission_result = tve_api_add_subscriber( $available['wordpress'], $connections['wordpress'], $post_data );
if ( $submission_result !== true ) {
$this->send_ajax_error( $submission_result );
}
unset( $connections['wordpress'] );
return $connections;
}, 10, 3 );
$logged_in = false;
/**
* Use this detection method, because `is_user_logged_in()` function will not work in the same request as the login process
*/
add_action( 'wp_login', static function () use ( &$logged_in ) {
$logged_in = true;
} );
$result = tve_api_form_submit( false );
if ( ! is_array( $result ) ) {
wp_send_json( $result );
}
if ( ! empty( $result['error'] ) ) {
$this->send_ajax_error( $result );
}
/* This filter is incorrectly named. It should be renamed to something like "tcb_prepare_login_response". Kept to maintain backwards compat. */
$result = apply_filters( 'tcb_after_user_logged_in', $result + $data );
$result['success'] = true;
$result['logged_in'] = $logged_in;
/* WordPress API already successfully registered the user */
wp_send_json( [ 'wordpress' => true ] + $result );
}
/**
* Send a response containing an ajax error message
*
* @param mixed $data
* @param int $http_status_code
*/
public function send_ajax_error( $data, $http_status_code = 422 ) {
status_header( $http_status_code );
wp_send_json( $data );
}
/**
* @param string $data
*
* @return array
*/
public function get_user( $data ) {
$response = [];
$response['user'] = '';
$response['errors'] = [];
if ( empty( $data ) || ! is_string( $data ) ) {
$response['errors']['empty_username'] = __( 'Enter a username or email address.', 'thrive-cb' );
return $response;
}
$data = sanitize_text_field( $data );
$field = strpos( $data, '@' ) ? 'email' : 'login';
$user_data = get_user_by( $field, $data );
if ( ! $user_data instanceof WP_User ) {
$response['errors']['invalidcombo'] = __( 'Invalid username or email.', 'thrive-cb' );
}
$response['user'] = $user_data;
return $response;
}
/**
* Get available actions for Login element
*
* @return array
*/
public static function get_post_login_actions() {
$actions = array(
array(
'key' => 'refresh',
'label' => __( 'Refresh page', 'thrive_cb' ),
'icon' => 'autorenew',
'preview_icon' => 'autorenew',
),
array(
'key' => 'redirect',
'label' => __( 'Redirect to Custom URL', 'thrive_cb' ),
'icon' => 'url',
'preview_icon' => 'url',
),
array(
'key' => 'noRedirect', // noRedirect key kept for backwards compatibility
'label' => __( 'Switch to already logged in state', 'thrive_cb' ),
'icon' => 'change',
'preview_icon' => 'change',
),
);
/**
* Allows dynamically modifying post login actions.
*
* @param array $actions array of actions to be filtered
*
* @return array
*/
return apply_filters( 'tcb_post_login_actions', $actions );
}
/**
* Get available post-registration actions for Login element
*
* @return array
*/
public static function get_post_register_actions() {
$actions = array_filter(
static::get_post_login_actions(),
static function ( $action ) {
/* identical to post login actions, except for "Show already logged in state" */
return $action['key'] !== 'noRedirect';
}
);
/**
* Allows dynamically modifying post-registration actions.
*
* @param array $actions array of actions to be filtered
*
* @return array
*/
return apply_filters( 'tcb_post_register_actions', array_values( $actions ) );
}
/**
* @param array $data
*
* @return array
*/
public function dynamiclink_data( $data ) {
$data['Login Form'] = array(
'links' => array(
0 => array(
'bk_to_login' => [
'name' => 'Back to Login',
'url' => '',
'show' => 1,
'id' => 'bk_to_login',
'type' => 'login',
],
'pass_reset' => [
'name' => 'Password Reset',
'url' => '',
'show' => 1,
'id' => 'forgot_password',
'type' => 'login',
],
'logout' => array(
'name' => 'Logout',
'url' => wp_logout_url(),
'show' => 1,
'id' => 'logout',
'type' => [ 'login', 'register' ],
),
'login' => [
'name' => 'Log In',
'url' => '',
'show' => 1,
'id' => 'login',
'type' => 'login',
],
'register' => [
'name' => 'Register',
'url' => '',
'show' => 1,
'id' => 'register',
'type' => 'register',
],
),
),
'shortcode' => 'thrive_login_form_shortcode',
);
return $data;
}
/**
* @param $args
*
* @return string
*/
public function login_form_shortcode( $args ) {
if ( ! isset( $args['id'] ) ) {
return '';
}
$data = '#tcb-state--' . $args['id'];
switch ( $args['id'] ) {
case 'logout':
global $wp;
$data = wp_logout_url( home_url( add_query_arg( [], $wp->request ) ) );
break;
default;
break;
}
return $data;
}
/**
* Get a list of all available error messages for the registration form element
*
* @return array
*/
public static function get_registration_error_messages() {
return array(
'required_field' => __( 'This field is required', 'thrive-cb' ),
'file_size' => __( '{file} exceeds the maximum file size of {filelimit}', 'thrive-cb' ),
'file_extension' => __( 'Sorry, {fileextension} files are not allowed', 'thrive-cb' ),
'max_files' => __( 'Sorry, the maximum number of files is {maxfiles}', 'thrive-cb' ),
'passwordmismatch' => __( 'Password mismatch', 'thrive-cb' ),
);
}
public static function get_default_settings() {
return [
'submit_action' => 'refresh',
'redirect_url' => '',
'success_message' => 'Success',
'post_register_action' => 'refresh',
'post_register_action.success_message' => 'Success',
'post_register_action.redirect_url' => '',
];
}
public static function get_registration_form_default_settings() {
return [
'v' => 1,
'apis' => [
'wordpress' => 'subscriber',
],
'captcha' => 0,
];
}
/**
* Configuration for Group editing inside Login / Registration forms
*
* @return array
*/
public static function get_group_editing_options() {
return array(
'exit_label' => __( 'Exit Group Styling', 'thrive-cb' ),
'select_values' => array(
array(
'value' => 'all_form_items',
'selector' => '.tve-login-form-item',
'name' => __( 'Grouped Form Items', 'thrive-cb' ),
'singular' => __( '-- Form Item %s', 'thrive-cb' ),
),
array(
'value' => 'all_inputs',
'selector' => '.tve-login-form-input',
'name' => __( 'Grouped Inputs', 'thrive-cb' ),
'singular' => __( '-- Input %s', 'thrive-cb' ),
),
array(
'value' => 'all_labels',
'selector' => '.tve-login-form-item .tcb-label',
'name' => __( 'Grouped Labels', 'thrive-cb' ),
'singular' => __( '-- Label %s', 'thrive-cb' ),
),
array(
'value' => 'all_radio_elements',
'selector' => '.tve_lg_radio',
'name' => __( 'Grouped Radio', 'thrive-cb' ),
'singular' => __( '-- Radio %s', 'thrive-cb' ),
),
array(
'value' => 'all_checkbox_elements',
'selector' => '.tve_lg_checkbox:not(.tcb-lg-consent)',
'name' => __( 'Grouped Checkbox', 'thrive-cb' ),
'singular' => __( '-- Checkbox %s', 'thrive-cb' ),
),
array(
'value' => 'all_dropdown_elements',
'selector' => '.tve_lg_dropdown, .tve_lg_country, .tve_lg_state',
'name' => __( 'Grouped Dropdowns', 'thrive-cb' ),
'singular' => __( '-- Dropdown %s', 'thrive-cb' ),
),
array(
'value' => 'radio_options',
'selector' => '.tve_lg_radio_wrapper',
'name' => __( 'Grouped Radio Options', 'thrive-cb' ),
'singular' => __( '-- Option %s', 'thrive-cb' ),
),
array(
'value' => 'dropdown_options',
'selector' => '.tve-lg-dropdown-option',
'name' => __( 'Grouped Dropdown Options', 'thrive-cb' ),
'singular' => __( '-- Option %s', 'thrive-cb' ),
),
array(
'value' => 'checkbox_options',
'selector' => '.tve_lg_checkbox_wrapper:not(.tcb-lg-consent .tve_lg_checkbox_wrapper)',
'name' => __( 'Grouped Checkbox Options', 'thrive-cb' ),
'singular' => __( '-- Option %s', 'thrive-cb' ),
),
array(
'value' => 'all_form_link',
'selector' => '.tar-login-elem-link',
'name' => __( 'Form Links', 'thrive-cb' ),
'singular' => __( '-- Link %s', 'thrive-cb' ),
),
array(
'value' => 'all_form_link_text',
'selector' => '.tar-login-elem-link .tve-dynamic-link',
'name' => __( 'Form Links Texts', 'thrive-cb' ),
'singular' => __( '-- Text %s', 'thrive-cb' ),
),
array(
'value' => 'all_form_titles',
'selector' => '.thrv-form-title',
'name' => __( 'Form Title', 'thrive-cb' ),
'singular' => __( '-- Title %s', 'thrive-cb' ),
),
array(
'value' => 'all_form_info',
'selector' => '.thrv-form-info',
'name' => __( 'Form Texts', 'thrive-cb' ),
'singular' => __( '-- Text %s', 'thrive-cb' ),
),
array(
'value' => 'all_submit_buttons',
'selector' => '.tar-login-elem-button',
'name' => __( 'Submit Buttons', 'thrive-cb' ),
'singular' => __( '-- Label %s', 'thrive-cb' ),
),
array(
'value' => 'all_submit_texts',
'selector' => '.tar-login-submit .tcb-button-text',
'name' => __( 'Submit Button Text', 'thrive-cb' ),
'singular' => __( '-- Submit Text %s', 'thrive-cb' ),
),
array(
'value' => 'all_inputs_icons',
'selector' => '.tve-login-form-input .thrv_icon',
'name' => __( 'Input Icons', 'thrive-cb' ),
'singular' => __( '-- Input Icon %s', 'thrive-cb' ),
),
array(
'value' => 'all_states',
'selector' => '.tve-form-state',
'name' => __( 'Form States', 'thrive-cb' ),
'singular' => __( '-- Form State %s', 'thrive-cb' ),
),
),
);
}
}
new TCB_Login_Element_Handler();

View File

@@ -0,0 +1,59 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
if ( ! class_exists( '\TCB_Icon_Element', false ) ) {
require_once TVE_TCB_ROOT_PATH . 'inc/classes/elements/class-tcb-icon-element.php';
}
/**
* Class TCB_Menu_Icon_Element_Abstract
*
* inherited by TCB_Menu_Icon_Open_Element and TCB_Menu_Icon_Close_Element
*/
abstract class TCB_Menu_Icon_Element_Abstract extends TCB_Icon_Element {
/**
* @return bool
*/
public function hide() {
return true;
}
/**
* @return array
*/
public function own_components() {
$components = parent::own_components();
$components['icon']['disabled_controls'] = [ 'ToggleURL', 'link' ];
$components['layout']['disabled_controls'] = [
'Float',
'Width',
'Height',
'Display',
'Position',
'Overflow',
'Alignment',
'ScrollStyle',
];
$components['animation'] = [ 'hidden' => true ];
$components['scroll'] = [ 'hidden' => true ];
$components['responsive'] = [ 'hidden' => true ];
$components['styles-templates'] = [ 'hidden' => true ];
$components['icon']['config']['Slider']['important'] = true;
$components['icon']['config']['Slider']['css_prefix'] = tcb_selection_root() . ' ';
$components['icon']['config']['ColorPicker']['important'] = true;
return $components;
}
}

View File

@@ -0,0 +1,196 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TCB_Menu_Settings {
const POST_TYPE = 'tve_menu_settings';
/**
* @var WP_Post
*/
private $post;
public function __construct( $post ) {
if ( ! ( $post instanceof WP_Post ) ) {
$post = get_post( $post );
}
$this->post = $post;
}
public function update( $data ) {
$data = array_merge( [
'id' => '',
'config' => [],
'before' => 0,
'after' => 0,
], $data );
$this->update_meta( '_menu_id', $data['id'] );
$this->update_meta( '_config', $data['config'] );
$this->update_meta( '_before', $data['before'] );
$this->update_meta( '_after', $data['after'] );
}
/**
* @param $key
* @param $value
*
* @return void
*/
private function update_meta( $key, $value ) {
update_post_meta( $this->get_id(), $key, $value );
}
/**
* @param $key
*
* @return mixed
*/
private function get_meta( $key ) {
return get_post_meta( $this->get_id(), $key, true );
}
/**
* @return int
*/
public function get_id() {
return empty( $this->post ) ? 0 : $this->post->ID;
}
/**
* @return mixed
*/
public function get_config() {
return $this->get_meta( '_config' );
}
/**
* Get before/after html for the hamburger menu
*
* @param string $position
* @param boolean $raw
*
* @return mixed|string
*/
public function get_extra_html( $position, $raw = false ) {
$html = $this->get_meta( $position );
if ( ! $raw && is_numeric( $html ) ) {
$html = '';
}
return do_shortcode( $html );
}
/**
* @return boolean
*/
public function has_custom_content_saved() {
return ! is_numeric( $this->get_extra_html( '_before', true ) ) || ! is_numeric( $this->get_extra_html( '_after', true ) );
}
/**
* @param array $data
* @param int $post_id
*
* @return static
*/
public static function save( $data = [], $post_id = 0 ) {
$menu_settings = static::get_menu_settings_instance( $data['id'] ?? 0, $post_id );
if ( $menu_settings === null ) {
remove_all_filters( 'wp_insert_post_data' );
remove_all_actions( 'edit_post' );
remove_all_actions( 'save_post' );
remove_all_actions( 'wp_insert_post' );
$id = wp_insert_post( [
'post_type' => static::POST_TYPE,
'post_title' => "Settings for menu on $post_id",
'post_parent' => $post_id,
'post_status' => 'publish',
] );
$menu_settings = new static( $id );
}
$menu_settings->update( $data );
return $menu_settings;
}
/**
* @param $menu_id
* @param $post_id
*
* @return static
*/
public static function get_menu_settings_instance( $menu_id, $post_id ) {
$posts = get_posts( [
'post_type' => static::POST_TYPE,
'post_parent' => $post_id,
'meta_query' => [
[
'key' => '_menu_id',
'value' => $menu_id,
],
],
] );
return empty( $posts ) ? null : new static( $posts[0] );
}
public static function init() {
add_filter( 'tcb.content_pre_save', static function ( $response, $post_data ) {
$post_id = isset( $post_data['post_id'] ) ? (int) $post_data['post_id'] : 0;
$menu_ids = [];
if ( ! empty( $post_data['menus'] ) ) {
foreach ( $post_data['menus'] as $menu_data ) {
$menu_settings = static::save( $menu_data, $post_id );
$menu_ids[] = $menu_settings->get_id();
$response['menus'][ $menu_data['id'] ?? 0 ] = $menu_settings->get_id();
}
}
// Symbols don't send their ID so there is a risc of removing unwanted menus TODO: fix this
//static::remove_unused_menus( $post_id, $menu_ids );
return $response;
}, 10, 2 );
}
/**
* When saving a page, menus that were not sent have been removed from the page so we also remove them
*
* @param $post_id
* @param $saved_menus
*
* @return void
*/
public static function remove_unused_menus( $post_id, $saved_menus ) {
$menus = get_posts( [
'post_type' => static::POST_TYPE,
'exclude' => $saved_menus,
'post_parent' => $post_id,
'post_status' => 'publish',
'fields' => 'ids',
] );
foreach ( $menus as $menu_id ) {
wp_delete_post( $menu_id, true );
}
}
}

View File

@@ -0,0 +1,753 @@
<?php
/**
* Custom walker for the Menu element
*
* Class TCB_Menu_Walker
*/
class TCB_Menu_Walker extends Walker_Nav_Menu {
/**
* Menu descriptions for Mega Menus
*
* @var string
*/
public static $mega_description_template = '<div class="thrv_text_element tve-no-drop">%s</div>';
/**
* MegaMenu images - raw template
*
* @var string
*/
public static $mega_image_template = '<span class="tcb-mm-image menu-item-{ITEM_ID}-img tve_editable{CLS}" {DYNAMIC_ATTR} style=\'background-image:{IMG}\'></span>';
/**
* Regular Menu images - raw template
*
* @var string
*/
public static $menu_item_image_template = '<span class="tcb-menu-item-image menu-item-{ITEM_ID}-img tve_editable{CLS}" {DYNAMIC_ATTR} style=\'background-image:{IMG}\'></span>';
/**
* unlinked selector: <LI> element
*/
const UNLINKED_LI = '.menu-item-{ID}';
/**
* unlinked selector: <UL> element
*/
const UNLINKED_UL = '.menu-item-{ID}-ul';
/**
* unlinked identifier: <a> (megamenu item)
*/
const UNLINKED_A = '.menu-item-{ID}-a';
/**
* unlinked identifier: megamenu dropdown column
*/
const UNLINKED_COL = '.menu-item-{ID}.lvl-1';
/**
* unlinked identifier: megamenu dropdown
*/
const UNLINKED_DROP = '.menu-item-{ID}-drop';
/**
* unlinked identifier: megamenu image
*/
const UNLINKED_IMG = '.menu-item-{ID}-img';
/**
* CSS class to add to unlinked items
*/
const CLS_UNLINKED = 'tcb-excluded-from-group-item';
/**
* Active state for menu items
*/
const CLS_ACTIVE = 'tve-state-active';
/**
* flag indicating where or not this is a editor page
*
* @var boolean
*/
protected $is_editor_page;
/**
* @var WP_Post current menu item
*/
protected $current_item;
/**
* Stores icon data
*
* @var array
*/
protected $icons = [];
protected $positional_selectors = false;
/**
* Cached version of a placeholder HTML for an image
*
* @var string
*/
protected $image_placeholder = '';
/**
* Holds the index of the current item as rendered in the <ul> parent
*
* @var int
*/
protected $current_item_index = 0;
public function __construct() {
$icons = $this->get_config( 'icon', [] );
$this->positional_selectors = tcb_custom_menu_positional_selectors();
$template = tcb_template( 'elements/menu-item-icon.phtml', null, true, 'backbone' );
foreach ( (array) $icons as $k => $icon_id ) {
if ( $icon_id ) {
$this->icons[ $k ] = str_replace( '_ID_', $icon_id, $template );
}
}
}
/**
* Gets HTML for an icon corresponding to a <li>
*
* @param WP_Post $item
* @param int $current_level
*
* @return string
*/
protected function icon( $item, $current_level ) {
$parent_field = $this->db_fields['parent'];
/* unlinked id */
$id = '.menu-item-' . $item->ID;
if ( $this->positional_selectors && ! empty( $item->_tcb_pos_selector ) ) {
/* try unlinked positional selectors */
$id = $item->_tcb_pos_selector;
}
if ( isset( $this->icons[ $id ] ) ) {
return $this->icons[ $id ];
}
if ( $this->get_menu_type() === 'mega' && isset( $this->icons["{$id}-a"] ) ) {
return $this->icons["{$id}-a"];
}
/* check top level */
if ( empty( $item->$parent_field ) ) {
return isset( $this->icons['top'] ) ? $this->icons['top'] : '';
}
/* check for mega menu icons */
if ( $this->get_menu_type() === 'mega' && $current_level > 0 ) {
$key = 1 === $current_level ? 'mega_main' : 'mega_sub';
return isset( $this->icons[ $key ] ) ? $this->icons[ $key ] : '';
}
/**
* default : submenu item
*/
return isset( $this->icons['sub'] ) ? $this->icons['sub'] : '';
}
/**
* Starts the list before the elements are added.
*
* @param string $output Used to append additional content (passed by reference).
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
*
* @see Walker::start_lvl()
*
* @since 3.0.0
*
*/
public function start_lvl( &$output, $depth = 0, $args = [] ) {
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t = '';
$n = '';
} else {
$t = "\t";
$n = "\n";
}
$indent = str_repeat( $t, $depth );
// Default class.
$classes = $this->get_menu_type() === 'regular' ? [ 'sub-menu' ] : [];
/**
* Filters the CSS class(es) applied to a menu list element.
*
* @param array $classes The CSS classes that are applied to the menu `<ul>` element.
* @param stdClass $args An object of `wp_nav_menu()` arguments.
* @param int $depth Depth of menu item. Used for padding.
*
* @since 4.8.0
*
*/
$classes = apply_filters( 'nav_menu_submenu_css_class', $classes, $args, $depth );
$classes [] = 'menu-item-' . $this->current_item->ID . '-ul';
if ( $this->is_out_of_group_editing( $this->current_item->ID, self::UNLINKED_UL ) ) {
$classes [] = self::CLS_UNLINKED;
}
$wrap_start = '';
if ( 0 === $depth && $this->get_menu_type() === 'mega' ) {
$drop_classes = [
'tcb-mega-drop-inner',
'thrv_wrapper',
'menu-item-' . $this->current_item->ID . '-drop',
];
if ( $this->is_out_of_group_editing( $this->current_item->ID, self::UNLINKED_DROP ) ) {
$drop_classes [] = self::CLS_UNLINKED;
}
$wrap_start = '<div class="tcb-mega-drop"><div class="' . implode( ' ', $drop_classes ) . '">';
/* check if this dropdown has masonry */
/**
* masonry if:
* unlinked and specific masonry set on the unlinked config
* OR masonry specified on the default config
*/
if ( $this->get_config( 'layout/default' ) === 'masonry' && $this->get_config( "layout/drop-{$this->current_item->ID}" ) !== 'grid' ) {
$classes [] = 'tcb-masonry';
}
}
$class_names = ' class="' . esc_attr( join( ' ', $classes ) ) . '"';
$output .= "{$wrap_start}{$n}{$indent}<ul$class_names>{$n}";
}
public function end_lvl( &$output, $depth = 0, $args = [] ) {
parent::end_lvl( $output, $depth, $args );
if ( 0 === $depth && $this->get_menu_type() === 'mega' ) {
$output .= '</div></div>';
}
}
/**
*
* Checks if an element has been unlocked from group editing ( is edited separately )
* If item ID can't be retrieved, it is assumed to be linked
* Spec can be any of the self::UNLINKED_* constants
*
* @param WP_Post|string $item
* @param string $spec
*
* @return bool
* @see self::UNLINKED_* constants
*
*/
public function is_out_of_group_editing( $item, $spec ) {
if ( is_numeric( $item ) ) {
$item_id = $item;
} elseif ( ! empty( $item->ID ) ) {
$item_id = $item->ID;
} else {
return false;
}
if ( $this->positional_selectors && $spec === self::UNLINKED_LI && isset( $item->_tcb_pos_selector ) ) {
return $this->get_config( "unlinked/{$item->_tcb_pos_selector}" );
}
$unlinked_class = str_replace( '{ID}', $item_id, $spec );
return $this->get_config( "unlinked/{$unlinked_class}" ) !== null;
}
/**
* @inheritDoc
*/
public function start_el( &$output, $item, $depth = 0, $args = [], $id = 0 ) {
if ( $depth === 0 ) {
$this->current_item_index ++;
}
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t = '';
} else {
$t = "\t";
}
$menu_type = $this->get_menu_type();
/**
* Render the logo before rendering the menu item thats after it
*/
if ( $depth === 0 && $menu_type === 'regular' && ( $this->current_item_index === $this->get_logo_split_breakpoint() + 1 ) ) {
$output .= $this->get_logo_html();
}
$indent = ( $depth ) ? str_repeat( $t, $depth ) : '';
$classes = empty( $item->classes ) ? [] : (array) $item->classes;
$link_attr = [];
$link_classes = 'mega' === $menu_type && $depth > 0 ? [ "menu-item menu-item-{$item->ID} menu-item-{$item->ID}-a" ] : [];
if ( 0 !== $depth && 'mega' === $menu_type && $this->is_editor_page() ) {
$link_classes[] = 'thrv_wrapper';
}
if ( $this->is_out_of_group_editing( $item->ID, self::UNLINKED_A ) ) {
$link_classes [] = self::CLS_UNLINKED;
}
/* Add the responsive classes on the menu item */
$responsive_attributes = (array) $this->get_config( 'responsive_attributes', [] );
$parent_field = $this->db_fields['parent'];
$item_id = '.menu-item-' . $item->ID;
$itemKey = '';
/* Get the item key of this item */
if ( ! empty( $responsive_attributes[ $item_id ] ) ) {
$itemKey = $item_id;
} else if ( $menu_type === 'mega' && ! empty( $responsive_attributes["{$item_id}-a"] ) ) {
$itemKey = "{$item_id}-a";
} else if ( empty( $item->$parent_field ) ) {
$itemKey = 'top';
} else if ( $menu_type === 'mega' && $depth > 0 ) {
$itemKey = 1 === $depth ? 'mega_main' : 'mega_sub';
} else {
$itemKey = 'sub';
}
$responsive_attrs = '';
/* Build the responsive data attributes */
if ( ! empty( $responsive_attributes[ $itemKey ] ) ) {
$devices = [ 'desktop', 'tablet', 'mobile' ];
foreach ( $devices as $device ) {
if ( ! empty( $responsive_attributes[ $itemKey ][ $device ] ) ) {
$responsive_attrs .= 'data-item-display-' . $device . '="' . $responsive_attributes[ $itemKey ][ $device ] . '"';
}
}
}
/* handle link classes for menu images */
if ( 'mega' === $menu_type || 'regular' === $menu_type ) {
$item_image = $this->get_config( "images/{$item->ID}", [] );
$image_placeholder = (array) $this->get_config( 'img_settings', [] );
$container_class = 'mega' === $menu_type && 1 === $depth ? 'tcb-mm-container' : 'tcb-menu-item-container';
$place = $this->get_image_placement( $item, $depth );
if ( ! empty( $item_image ) ) {
$link_classes [] = $container_class;
$link_classes [] = isset( $item_image['o'] ) ? "tcb--{$item_image['o']}" : 'tcb--row';
} elseif ( 1 === $depth && 'mega' === $menu_type && ! empty( $image_placeholder['enabled'] ) ) {
$link_classes [] = $container_class . ' ' . ( isset( $image_placeholder['o'] ) ? "tcb--{$image_placeholder['o']}" : 'tcb--row' );
$item_image = array(
'placeholder' => true,
'o' => isset( $image_placeholder['o'] ) ? $image_placeholder['o'] : '',
);
} elseif ( ! empty( $image_placeholder[ $place ] ) && isset( $image_placeholder[ $place ]['enabled'] ) && $image_placeholder[ $place ]['enabled'] ) {
$link_classes [] = $container_class . ' ' . ( isset( $image_placeholder[ $place ]['o'] ) ? "tcb--{$image_placeholder[ $place ]['o']}" : 'tcb--row' );
$item_image = array(
'placeholder' => true,
'o' => isset( $image_placeholder[ $place ]['o'] ) ? $image_placeholder[ $place ]['o'] : '',
);
}
}
/**
* Filters the arguments for a single nav menu item.
*
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
*
* @since 4.4.0
*
*/
$args = apply_filters( 'nav_menu_item_args', $args, $item, $depth );
/**
* Filters the CSS class(es) applied to a menu item's list item element.
*
* @param array $classes The CSS classes that are applied to the menu item's `<li>` element.
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*
* @since 3.0.0
* @since 4.1.0 The `$depth` parameter was added.
*
*/
$classes = apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth );
// make sure these are always included
$classes[] = 'menu-item-' . $item->ID;
$classes[] = 'lvl-' . $depth;
if ( ! empty( $GLOBALS['tve_menu_font_class'] ) ) {
$classes[] = $GLOBALS['tve_menu_font_class'];
}
if ( $this->is_editor_page() && ( 0 === $depth || $menu_type === 'regular' ) ) {
$classes[] = 'thrv_wrapper';
}
if ( $this->is_out_of_group_editing( $item, self::UNLINKED_LI ) || $this->is_out_of_group_editing( $item->ID, self::UNLINKED_COL ) ) {
$classes [] = self::CLS_UNLINKED;
}
$top_cls = (array) $this->get_config( 'top_cls', [] );
if ( ! empty( $top_cls ) ) {
$unlinked_key = ! empty( $item->_tcb_pos_selector ) ? $item->_tcb_pos_selector : '.menu-item-' . $item->ID;
$is_unlinked = ! empty( $this->get_config( "unlinked/$unlinked_key", [] ) );
if ( isset( $top_cls[ $unlinked_key ] ) && $is_unlinked ) {
$classes [] = $top_cls[ $unlinked_key ];
} elseif ( ! empty( $top_cls['main'] ) ) {
$classes [] = $top_cls['main'];
}
}
if ( ! $this->is_editor_page() && in_array( 'current-menu-item', $classes ) ) {
$classes [] = self::CLS_ACTIVE;
$link_classes [] = self::CLS_ACTIVE;
}
/* event actions */
$events = $this->get_config( "actions/{$item->ID}" );
if ( empty( $events ) ) {
$events = ! empty( $item->thrive_events ) ? $item->thrive_events : '';
}
if ( $events ) {
$link_classes [] = 'tve_evt_manager_listen tve_et_click';
}
$class_names = ' class="' . esc_attr( join( ' ', $classes ) ) . '"';
/**
* Filters the ID applied to a menu item's list item element.
*
* @param string $menu_id The ID that is applied to the menu item's `<li>` element.
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*
* @since 3.0.1
* @since 4.1.0 The `$depth` parameter was added.
*
*/
$id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args, $depth );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
$output .= $indent . '<li' . $id . $class_names . ' data-id="' . $item->ID . '" ' . $responsive_attrs . ' >';
$link_attr['title'] = ! empty( $item->attr_title ) ? $item->attr_title : '';
$link_attr['target'] = ! empty( $item->target ) ? $item->target : '';
$link_attr['rel'] = ! empty( $item->xfn ) ? $item->xfn : '';
$link_attr['href'] = ! empty( $item->url ) ? $item->url : '';
if ( 0 !== $depth && $menu_type !== 'regular' && $this->is_editor_page() ) {
$link_classes[] = 'thrv_wrapper';
}
if ( $this->is_out_of_group_editing( $item->ID, self::UNLINKED_A ) ) {
$link_classes [] = self::CLS_UNLINKED;
}
/**
* Filters the HTML attributes applied to a menu item's anchor element.
*
* @param array $link_attr {
* The HTML attributes applied to the menu item's `<a>` element, empty strings are ignored.
*
* @type string $title Title attribute.
* @type string $target Target attribute.
* @type string $rel The rel attribute.
* @type string $href The href attribute.
* }
*
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*
* @since 3.6.0
* @since 4.1.0 The `$depth` parameter was added.
*
*/
$link_attr = apply_filters( 'nav_menu_link_attributes', $link_attr, $item, $args, $depth );
$link_attr['class'] = isset( $link_attr['class'] ) ? $link_attr['class'] : '';
$link_attr['class'] .= ( $link_attr['class'] ? ' ' : '' ) . implode( ' ', $link_classes );
if ( $events ) {
$link_attr['data-tcb-events'] = $events;
}
$attributes = '';
foreach ( $link_attr as $attr => $value ) {
if ( ! empty( $value ) ) {
$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
if ( $depth > 0 && $menu_type === 'mega' ) {
$attributes .= ' ' . $responsive_attrs . ' ';
}
/** This filter is documented in wp-includes/post-template.php */
$title = apply_filters( 'the_title', $item->title, $item->ID );
/**
* Filters a menu item's title.
*
* @param string $title The menu item's title.
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*
* @since 4.4.0
*
*/
$title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
$item_output = $args->before . '<a' . $attributes . '>';
if ( ! empty( $item_image ) ) {
$item_output .= $this->build_image( $item_image, $item, $depth );
if ( 1 === $depth && 'mega' === $menu_type ) {
$item_output .= '<span class="tcb-mm-text">';
}
$args->link_after = $args->link_after . '</span>';
}
$item_output .= $this->icon( $item, $depth );
$item_output .= $args->link_before . $title . $args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
/**
* Append megamenu descriptions stored in config
*/
if ( 1 === $depth && $menu_type === 'mega' ) {
$mega_description = $this->get_config( 'mega_desc' );
if ( $mega_description ) {
$mega_description = json_decode( base64_decode( $mega_description ), true );
$mega_description = isset( $mega_description[ $item->ID ] ) ? $mega_description[ $item->ID ] : '';
$item_output .= ! empty( $mega_description ) ? sprintf( static::$mega_description_template, $mega_description ) : '';
}
}
/**
* Filters a menu item's starting output.
*
* The menu item's starting output only includes `$args->before`, the opening `<a>`,
* the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is
* no filter for modifying the opening and closing `<li>` for a menu item.
*
* @param string $item_output The menu item's starting HTML output.
* @param WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
*
* @since 3.0.0
*
*/
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
/* keep a reference to the current menu itemID */
$this->current_item = $item;
}
/**
* Checks if the current page is the editor page
* Also handles the case where the CM is rendered via ajax
*
* @return boolean
*/
protected function is_editor_page() {
if ( ! isset( $this->is_editor_page ) ) {
$this->is_editor_page = ( ( wp_doing_ajax() && ! empty( $_REQUEST['action'] ) && 'tcb_editor_ajax' === $_REQUEST['action'] ) || is_editor_page() );
}
return $this->is_editor_page;
}
/**
* Get the menu type. empty means regular WP menu
*
* @return string
*/
protected function get_menu_type() {
return $this->get_config( 'type', 'regular' );
}
/**
* @param string $key allows "/" to split fields
* @param null $default
*
* @return mixed
*/
protected function get_config( $key, $default = null ) {
$fields = explode( '/', $key );
$target = $GLOBALS['tcb_wp_menu'];
while ( $fields ) {
/* make sure this is always an array */
$target = (array) $target;
$field = array_shift( $fields );
if ( ! isset( $target[ $field ] ) ) {
return $default;
}
$target = $target[ $field ];
}
return $target;
}
/**
* Get a group configuration value ( "default" is stored for all linked items, $spec is stored for unlinked items )
* Example specification:
* ".img-{ID}
*
* @param string $key
* @param WP_Post|string|int $item
* @param mixed $default
*
* @return mixed
*/
protected function get_group_config( $key, $item, $default = null ) {
if ( is_object( $item ) && $item->ID ) {
$item = $item->ID;
}
return $this->get_config( "{$key}/{$item}", $this->get_config( "{$key}/default", $default ) );
}
/**
* Output the selected image for a menu item
*
* @param array $image
* @param WP_Post $item
*
* @return string
*/
protected function build_image( $image, $item, $depth ) {
if ( empty( $image ) ) {
return '';
}
$dynamic_attr = '';
/* If the image is dynamic, we change the url accordingly */
if ( ! empty( $image['d'] ) ) {
switch ( $image['d'] ) {
case 'user':
$image['i'] = 'url("' . tcb_dynamic_user_image_instance( get_current_user_id() )->user_avatar() . '")';
break;
case 'author':
$image['i'] = 'url("' . TCB_Post_List_Author_Image::author_avatar() . '")';
TCB_Post_List_Author_Image::author_avatar();
break;
case 'featured':
/* In editor we add the placeholder, in front-end we leave the link empty*/
$featured_img = get_the_post_thumbnail_url( get_the_ID() );
if ( empty( $featured_img ) && is_editor_page() ) {
$featured_img = TCB_Post_List_Featured_Image::get_default_url( get_the_ID() );
}
$image['i'] = 'url("' . $featured_img . '")';
break;
default:
break;
}
$dynamic_attr = 'data-d-f="' . $image['d'] . '"';
}
$menu_type = $this->get_menu_type();
$template = 'mega' === $menu_type && 1 === $depth ? static::$mega_image_template : static::$menu_item_image_template;
$containter_class = 'mega' === $menu_type && 1 === $depth ? 'tcb-mm-image' : 'tcb-menu-item-image';
$template = empty( $image['placeholder'] ) ? $template : $this->get_image_placeholder();
$classes = $this->is_out_of_group_editing( $item->ID, self::UNLINKED_IMG ) ? ' ' . self::CLS_UNLINKED : '';
$background = str_replace( "'", '"', isset( $image['i'] ) ? $image['i'] : '' );
if ( ! empty( $image['cfVariable'] ) ) {
$background .= '; --tcb-background-custom-field:' . str_replace( "'", '"', $image['cfVariable'] );
}
if ( ! empty( $image['d'] ) ) {
$classes .= ' tcb-dynamic-field-source';
}
if ( ! empty( $image['cf'] ) ) {
$classes .= ' tcb-custom-field-source';
$dynamic_attr .= ' data-c-f-id="' . $image['d'] . '"';
}
if ( ! empty( $image['cfAttr'] ) ) {
foreach ( $image['cfAttr'] as $attr => $value ) {
if ( ! empty( $value ) ) {
$dynamic_attr .= 'data-' . $attr . '="' . $value . '"';
}
}
}
return str_replace(
array( '{ITEM_ID}', '{CLS}', '{IMG}', '{ITEM_TYPE_CLS}', '{DYNAMIC_ATTR}' ),
array( $item->ID, $classes, stripslashes( $background ), $containter_class, $dynamic_attr ),
$template
);
}
/**
* Get the image placeholder for a megamenu item
*
* @return string
*/
protected function get_image_placeholder() {
if ( ! $this->image_placeholder ) {
$this->image_placeholder = tcb_template( 'elements/menu-image-placeholder.phtml', null, true, 'backbone' );
}
return $this->image_placeholder;
}
/**
* Render the menu-logo-split, if configured
*
* @return string
*/
public function get_logo_html() {
$html = '';
$logo = $this->get_config( 'logo' );
if ( $logo && is_array( $logo ) ) {
$html = sprintf(
'<li class="tcb-menu-logo-wrap %s tcb-selector-no_highlight menu-item--1" data-id="-1">%s</li>',
static::CLS_UNLINKED,
TCB_Logo::render_logo( $logo )
);
}
return $html;
}
/**
* Get the split-point (index after the logo item should be rendered in case of Split Logo functionality
*
* @return false|float
*/
public function get_logo_split_breakpoint() {
return (int) floor( $GLOBALS['tcb_wp_menu']['top_level_count'] / 2 );
}
public function get_image_placement( $item, $current_level ) {
$parent_field = $this->db_fields['parent'];
$key = '';
/* check top level */
if ( empty( $item->$parent_field ) ) {
$key = 'top';
} else if ( $this->get_menu_type() === 'regular' ) {
$key = 'sub';
}
/* check for mega menu */
if ( $this->get_menu_type() === 'mega' && $current_level > 0 ) {
$key = $current_level === 1 ? 'mega_main' : 'mega_sub';
}
return $key;
}
}

View File

@@ -0,0 +1,434 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 5/29/2017
* Time: 9:39 AM
*/
class TCB_Post_Grid {
private $_template = 'sc-post-grid.php';
private $_cfg_code = '__CONFIG_post_grid__';
/**
* Defines rules that remove from Post Grid content specific elements
*
* @var array
*/
private $_content_to_remove = array(
'#<a href="javascript:(.+?)</a>#',
'#<span class="tve_s_cnt">(.+?)</span> shares#',
'#__CONFIG_group_edit__(.+?)__CONFIG_group_edit__#',
'#__CONFIG_local_colors__(.+?)__CONFIG_local_colors__#',
/* some "custom" custom menus are saved without the __CONFIG_widget_menu key (in symbols, this is a problem) - we need to get rid of all json-encoded string from the content */
'#{"menu_id"(.+)(true|false|null|"|\'|\d|]|})}#',
/* Custom menu - encoded json version */
'@{&#8220;menu_id&#8221;(.+)(true|false|null|&#8221;|\d|]|})}@',
);
/**
* When set to false, the shortcode config DIV wont be rendered
*
* @var bool
*/
public $output_shortcode_config = true;
/**
* PostGrid constructor.
*
* @param $config
*/
public function __construct( $config = [] ) {
$config = stripslashes_deep( $config );
$defaults = array(
'display' => 'grid',
'grid_layout' => 'horizontal',
'columns' => '3',
'text_type' => 'summary',
'read-more-text' => __( 'Read More', 'thrive-cb' ),
'image-height' => '',
'font-size' => '', //Backwards Compatibility: Title Font Size
'text-line-height' => '', //Backwards Compatibility: Title Line Height
'teaser_layout' => [
'featured_image' => 'true',
'title' => 'true',
'text' => 'true',
'read_more' => 'true',
],
'layout' => [
'featured_image',
'title',
'text',
'read_more',
],
'orderby' => 'date',
'order' => 'DESC',
'recent_days' => '0',
'posts_start' => '0',
'posts_per_page' => '6',
'content_types' => [ 'post' ],
'filters' => [
'category' => [],
'tag' => [],
'tax' => [],
'author' => [],
'posts' => [],
],
);
/**
* Backwards compatible $config['post_types'].
* This can be removed after users update a while when users update their post grids and the post_types variable is removed from the config array
*/
if ( ! empty( $config['post_types'] ) && is_array( $config['post_types'] ) && empty( $config['content_types'] ) ) {
$config['content_types'] = [];
foreach ( $config['post_types'] as $type => $checked ) {
if ( $checked === 'true' ) {
$config['content_types'][] = $type;
}
}
}
$this->_config = array_merge( $defaults, $config );
}
/**
* Render Functions
* Goes through all posts and builds the HTML code
*
* @return string
*/
public function render() {
$posts = $this->_get_post_grid_posts();
$count = count( $posts );
$index = 1;
$extra_classes = 'tve_post_grid_' . $this->_config['display'];
if ( $this->_config['grid_layout'] === 'vertical' ) {
$extra_classes .= ' tve_post_grid_vertical';
}
$html = '';
if ( $this->output_shortcode_config ) {
$html .= $this->_get_shortcode_config();
}
$html .= '<div class="tve_post_grid_wrapper tve_clearfix thrive-shortcode-html ' . $extra_classes . '">';
if ( $count === 0 ) {
$html .= __( 'No results have been returned for your Query. Please edit the query for content to display.', 'thrive-cb' );
}
foreach ( $posts as $key => $post ) {
$html .= tcb_template( $this->_template, [ 'cls' => $this, 'index' => $index, 'post' => $post, 'count' => $count ], true );
$index ++;
}
$html .= '</div>';
return $html;
}
/**
* Outputs the config shortcode.
*
* @return string
*/
private function _get_shortcode_config() {
$encoded_config = tve_json_utf8_unslashit( json_encode( $this->_config ) );
return '<div class="thrive-shortcode-config" style="display: none !important">' . $this->_cfg_code . $encoded_config . $this->_cfg_code . '</div>';
}
/**
* Applies the settings and returns an array with all posts with the corresponding settings
*
* @return array
*/
private function _get_post_grid_posts() {
if ( empty( $this->_config['exclude'] ) ) {
$this->_config['exclude'] = 0;
}
$types = empty( $this->_config['content_types'] ) ? 'any' : $this->_config['content_types'];
$args = array(
'post_type' => $types,
'offset' => $this->_config['posts_start'],
'posts_per_page' => intval( $this->_config['posts_per_page'] ) == 0 ? - 1 : $this->_config['posts_per_page'],
'order' => $this->_config['order'],
'orderby' => $this->_config['orderby'],
'post_status' => 'publish',
'post__not_in' => [ $this->_config['exclude'] ],
);
if ( ! empty( $this->_config['filters']['category'] ) ) {
//Backwards compatibility:
if ( is_string( $this->_config['filters']['category'] ) ) {
$this->_config['filters']['category'] = explode( ',', $this->_config['filters']['category'] );
}
$args['tax_query'] = array(
'relation' => 'AND',
array(
'relation' => 'OR',
array(
'taxonomy' => 'category',
'field' => 'name',
'terms' => $this->_config['filters']['category'],
'operator' => 'IN',
),
array(
'taxonomy' => 'apprentice',
'field' => 'name',
'terms' => $this->_config['filters']['category'],
'operator' => 'IN',
),
),
);
}
if ( ! empty( $this->_config['filters']['tag'] ) ) {
//Backwards compatibility:
if ( is_string( $this->_config['filters']['tag'] ) ) {
$tags = explode( ',', trim( $this->_config['filters']['tag'], ',' ) );
$tags = empty( $tags ) ? [] : $tags;
$this->_config['filters']['tag'] = array_unique( $tags );
}
$query_tags = array(
'relation' => 'OR',
array(
'taxonomy' => 'post_tag',
'field' => 'name',
'terms' => $this->_config['filters']['tag'],
'operator' => 'IN',
),
array(
'taxonomy' => 'apprentice-tag',
'field' => 'name',
'terms' => $this->_config['filters']['tag'],
'operator' => 'IN',
),
);
if ( ! empty( $this->_config['filters']['category'] ) ) {
$args['tax_query'][] = $query_tags;
} else {
$args['tax_query'] = [
'relation' => 'AND',
$query_tags,
];
}
}
if ( ! empty( $this->_config['filters']['tax'] ) ) {
//Backwards compatibility:
if ( is_string( $this->_config['filters']['tax'] ) ) {
$tax_parts = explode( ',', trim( $this->_config['filters']['tax'], ',' ) );
$tax_parts = empty( $tax_parts ) ? [] : $tax_parts;
$this->_config['filters']['tax'] = array_unique( $tax_parts );
}
$tax_names = $this->_config['filters']['tax']; //array_unique( $tax_names );
$tax_query = [];
//foreach taxonomy name get all its terms and build tax_query for it
foreach ( $tax_names as $tax_name ) {
$terms_obj = get_terms( $tax_name );
if ( empty( $terms_obj ) || $terms_obj instanceof WP_Error ) {
continue;
}
$tax_terms = [];
foreach ( $terms_obj as $term ) {
$tax_terms[] = $term->slug;
}
$tax_query[] = [
'taxonomy' => $tax_name,
'field' => 'slug',
'terms' => $tax_terms,
];
}
if ( ! empty( $tax_query ) ) {
$tax_query['relation'] = 'OR';
$args['tax_query'] = $tax_query;
}
}
if ( ! empty( $this->_config['filters']['author'] ) ) {
//Backwards compatibility:
if ( is_string( $this->_config['filters']['author'] ) ) {
$this->_config['filters']['author'] = array_unique( explode( ',', trim( $this->_config['filters']['author'], ',' ) ) );
}
$author_names = $this->_config['filters']['author']; //array_unique( $author_names );
$author_ids = [];
foreach ( $author_names as $name ) {
$author = get_user_by( 'slug', $name );
if ( $author ) {
$author_ids[] = $author->ID;
}
}
if ( ! empty( $author_ids ) ) {
$args['author'] = implode( ',', $author_ids );
}
}
if ( ! empty( $this->_config['filters']['posts'] ) ) {
if ( is_string( $this->_config['filters']['posts'] ) ) { //Backwards Compatibility
$post_ids = array_unique( explode( ',', $this->_config['filters']['posts'] ) );
} else {
$post_ids = wp_list_pluck( array_filter( $this->_config['filters']['posts'] ), 'id' ); //array_unique( $post_ids );
}
$args['post__in'] = $post_ids;
}
if ( ! empty( $this->_config['recent_days'] ) ) {
$args['date_query'] = array(
'after' => date( 'Y-m-d', strtotime( '-' . intval( $this->_config['recent_days'] ) . ' days', strtotime( date( 'Y-m-d' ) ) ) ),
);
}
$args['ignore_sticky_posts'] = 1;
remove_filter( 'pre_get_posts', 'thrive_exclude_category' );
$results = new WP_Query( $args );
return $results->posts;
}
/**
* Returns the post content by checking if post option to be displayed exists: featured image, text, read more, title
*
* @param $post
*
* @return string
*/
public function get_post_content( $post ) {
$html = '';
if ( ! in_array( 'read_more', $this->_config['layout'] ) ) {
$this->_config['layout'][] = 'read_more';
}
foreach ( $this->_config['layout'] as $layout ) {
if ( ! empty( $this->_config['teaser_layout'][ $layout ] ) && $this->_config['teaser_layout'][ $layout ] === 'true' ) {
$function_name = '_display_post_' . $layout;
$html .= call_user_func( [ $this, $function_name ], $post );
}
}
return $html;
}
/**
* Displays the post featured image
* Used in get_post_content method
*
* @param $post
*
* @return string
*/
private function _display_post_featured_image( $post ) {
if ( ! has_post_thumbnail( $post->ID ) ) {
return '';
}
$src = wp_get_attachment_url( get_post_thumbnail_id( $post->ID ) );
$height = ! empty( $this->_config['image-height'] ) ? "height: {$this->_config['image-height']}px" : '';
return '<a href="' . get_permalink( $post ) . '"><div class="tve_post_grid_image_wrapper" style="background-image: url(' . $src . ' ); ' . $height . '"><div class="tve_pg_img_overlay"><span class="thrv-icon thrv-icon-forward"></span></div></div></a>';
}
/**
* Display the post text
* Used in get_post_content method
*
* @param $post
*
* @return string
*/
private function _display_post_text( $post ) {
//get whole the content
$content = empty( $post->post_content ) ? $post->tve_updated_post : $post->post_content;
//strip all the shortcodes from the content
$content = strip_shortcodes( $content );
if ( $this->_config['text_type'] === 'summary' ) {
$content = $this->_get_summary_text( $content );
} elseif ( $this->_config['text_type'] === 'excerpt' ) {
$content = empty( $post->post_excerpt ) ? $this->_get_summary_text( $content ) : $post->post_excerpt;
} elseif ( $this->_config['text_type'] === 'fulltext' ) {
$content = $this->_filter_content( $content );
$content = strip_tags( $content, '<p><h1><h2><h3><h4><h5><h6><a><strong><b>' );
// Remove breaks (new line characters)
$content = trim( preg_replace( '/[\r\n\t ]+/', ' ', $content ) );
}
if ( empty( $content ) ) {
return '';
}
return '<div class="tve-post-grid-text">' . $content . '</div>';
}
/**
* Displays post title
* Used in get_post_content method
*
* @param $post
*
* @return string
*/
private function _display_post_title( $post ) {
$title_font_size = ! empty( $this->_config['font-size'] ) ? 'font-size: ' . $this->_config['font-size'] . 'px;' : '';
$title_line_height = ! empty( $this->_config['text-line-height'] ) ? 'line-height: ' . $this->_config['text-line-height'] . ';' : '';
$title_style = '';
if ( ! empty( $title_font_size ) || ! empty( $title_line_height ) ) {
$title_style = 'style="' . $title_font_size . $title_line_height . '"';
}
return '<span class="tve-post-grid-title" ' . $title_style . '><a href="' . get_permalink( $post ) . '" aria-label="' . get_the_title( $post->ID ) . '" >' . get_the_title( $post->ID ) . '</a></span>';
}
/**
* Displays post read more text
* Used in get_post_content method
*
* @param $post
*
* @return string
*/
private function _display_post_read_more( $post ) {
return '<div class="tve_pg_more"><a href="' . get_permalink( $post ) . '" aria-label="' . $this->_config['read-more-text'] . '">' . $this->_config['read-more-text'] . '</a>&nbsp;<span class="thrv-icon thrv-icon-uniE602"></span></div>';
}
private function _get_summary_text( $text ) {
$text = $this->_filter_content( $text );
$text = wp_strip_all_tags( $text, true );
$text = wp_trim_words( $text, 20, '&#91;...&#93;' );
return $text;
}
/**
* Filters the content by removing specific elements
*
* @param string $content
*
* @return string
*/
private function _filter_content( $content = '' ) {
foreach ( $this->_content_to_remove as $pattern ) {
$content = preg_replace( $pattern, '', $content );
}
return $content;
}
}

View File

@@ -0,0 +1,321 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
if ( ! class_exists( 'TCB_Post' ) ) {
/**
* Class TCB_Post
*
* @property $tcb_content
* @property $post_content
* @property $ID
*/
class TCB_Post {
/**
* @var WP_Post
*/
public $post;
public function __construct( $post_id = null ) {
global $tve_post;
if ( empty( $post_id ) && ! empty( $tve_post ) ) {
$post_id = $tve_post->ID;
}
$this->post = get_post( $post_id );
}
/**
* Setter or getter for a post_meta field
*
* @param string $key
* @param null|mixed $value if $value is null, the function acts as a getter
* @param bool $use_lp_key whether or not to get / set the value in the LandingPage meta space
* @param mixed $default default value to return if meta value is empty
*
* @return mixed|TCB_Post
*/
public function meta( $key, $value = null, $use_lp_key = false, $default = null ) {
if ( ! $this->post ) {
return null;
}
if ( null === $value ) {
$fn = $use_lp_key ? 'tve_get_post_meta' : 'get_post_meta';
$value = $fn( $this->post->ID, $key, true );
if ( empty( $value ) && null !== $default ) {
$value = $default;
}
return $value;
}
$fn = $use_lp_key ? 'tve_update_post_meta' : 'update_post_meta';
$fn( $this->post->ID, $key, $value );
return $this;
}
/**
* Deletes post meta field
*
* @param string $key
*/
public function meta_delete( $key ) {
delete_post_meta( $this->post->ID, $key );
return $this;
}
/**
* @param $name
*
* @return mixed|null
*/
public function __get( $name ) {
switch ( $name ) {
case 'tcb_content':
return $this->meta( 'tve_updated_post', null, true );
}
return $this->post ? $this->post->{$name} : null;
}
/**
* Get the HTML for a single WP content element containing everything from the post_content field
*/
public function get_wp_element() {
$html = '';
$wp_content = wpautop( $this->post->post_content );
$wp_content = shortcode_unautop( $wp_content );
if ( trim( $wp_content ) ) {
$html = '<div class="thrv_wrapper tve_wp_shortcode"><div class="tve_shortcode_raw" style="display: none">___TVE_SHORTCODE_RAW__' . htmlentities( $wp_content ) . '__TVE_SHORTCODE_RAW___</div></div>';
}
return $html;
}
/**
* Migrates the post to TCB2
*
* @param boolean $update_plain_text whether or not to also update the plain text version of the post content
*/
public function migrate( $update_plain_text = true ) {
$wp_content = $this->post->post_content;
$tcb_content = $this->tcb_content;
if ( ! empty( $wp_content ) ) {
$tcb_content .= $this->get_wp_element();
}
$this->meta( 'tve_updated_post', $tcb_content, true )
->meta( 'tcb2_ready', 1 )
->meta( 'tcb_editor_enabled', 1 )
->meta_delete( 'tcb_editor_disabled' );
if ( $update_plain_text ) {
$this->update_plain_text_content( $tcb_content );
}
}
/**
* Generates the text version of a TCB-saved post
*
* @param string $tcb_content
*
* @return TCB_Post
*/
public function update_plain_text_content( $tcb_content = null ) {
if ( ! $this->editor_enabled() ) {
return $this;
}
if ( null === $tcb_content ) {
$tcb_content = $this->tcb_content;
}
$tcb_content = tcb_clean_frontend_content( $tcb_content );
/* Make sure WP shortcode element is decoded before saving it */
$tcb_content = preg_replace_callback( '#___TVE_SHORTCODE_RAW__(.+?)__TVE_SHORTCODE_RAW___#s', [ $this, 'plain_text_decode_content' ], $tcb_content );
$tcb_content = wp_unslash( $tcb_content );
$tcb_content = tve_thrive_shortcodes( $tcb_content );
do_action( 'tcb_plain_content_do_shortcode_before' );
$tcb_content = do_shortcode( $tcb_content );
do_action( 'tcb_plain_content_do_shortcode_after' );
$tcb_content = preg_replace( '/<script(.*?)>(.*?)<\/script>/is', '', $tcb_content );
$tcb_content = preg_replace( '/<style(.*?)>(.*?)<\/style>/is', '', $tcb_content );
/**
* replace html comment tags so we preserve gutenberg block on strip tags
*/
$tcb_content = preg_replace( '/<!--/is', '{!--', $tcb_content );
$tcb_content = preg_replace( '/-->/is', '--}', $tcb_content );
$tcb_content = strip_tags( $tcb_content, '<h1><h2><h3><h4><h5><h6><p><ul><ol><li><span><a><img><strong><b><u><em><sup><sub><blockquote><address><table><tbody><thead><tr><th><td>' );
$tcb_content = preg_replace( '/{!--/is', '<!--', $tcb_content );
$tcb_content = preg_replace( '/--}/is', '-->', $tcb_content );
$tcb_content = str_replace( [ "\n", "\r", "\t" ], '', $tcb_content );
/* re-add the <!--more--> tag to the text, if it was present before */
$tcb_content = str_replace( 'TCB_WP_MORE_TAG', '<!--more-->', $tcb_content );
$tcb_content = preg_replace( '/(\s+)?class="([^"]*)?"/is', '', $tcb_content );
$tcb_content = preg_replace( '/(\s+)?data-css="([^"]+)"/is', '', $tcb_content );
$tcb_content = preg_replace( '/(\s+)?data-tcb-events="__TCB_EVENT_(.+?)_TNEVE_BCT__"/is', '', $tcb_content );
wp_update_post( [
'ID' => $this->post->ID,
'post_content' => $tcb_content,
] );
return $this;
}
/**
* Decode html entities inside WP Content elemnt
*
* @param array $matches
*
* @return string
*/
public function plain_text_decode_content( $matches ) {
$html = html_entity_decode( $matches[1] );
/* replace the MORE tag from WP with a placeholder so it does not get stripped by strip_tags */
if ( preg_match( '#<!--more(.*?)?-->#', $html, $m ) ) {
$html = str_replace( $m[0], 'TCB_WP_MORE_TAG', $html );
}
return $html;
}
/**
* Enables the TCB-only editor for this post
*
* @return TCB_Post
*/
public function enable_editor() {
if ( ! $this->post || ! $this->meta( 'tcb2_ready' ) ) {
return $this;
}
return $this->meta_delete( 'tcb_editor_disabled' )
->meta( 'tcb_editor_enabled', 1 );
}
/**
* Disables the TCB-only editor for this post
*
* @return TCB_Post
*/
public function disable_editor() {
if ( ! $this->post || ! $this->meta( 'tcb2_ready' ) ) {
return $this;
}
return $this->meta_delete( 'tcb_editor_enabled' )
->meta( 'tcb_editor_disabled', 1 );
}
/**
* Checks if this post has the TCB-only editor enabled ( version 2.0 ).
*/
public function editor_enabled() {
if ( ! $this->post ) {
return false;
}
if ( ! $this->meta( 'tcb2_ready' ) ) {
return false;
}
return (int) $this->meta( 'tcb_editor_enabled' );
}
/**
* Check if the TCB editor is specifically disabled for this post
*/
public function editor_disabled() {
if ( ! $this->post ) {
return false;
}
if ( ! $this->meta( 'tcb2_ready' ) ) {
/* acts as previously */
return false;
}
return (int) $this->meta( 'tcb_editor_disabled' );
}
/**
* Check if the conditions are met to auto-migrate the post to TCB2.0, and enable TCB-editor only mode.
* This can only happen if there is no WP editor content in the post, and also, the post has tcb-content
*
* @param boolean $update_plain_text whether or not to update the plain text content
*
* @return TCB_Post allows chained calls
*/
public function maybe_auto_migrate( $update_plain_text = true ) {
if ( ! $this->post ) {
return $this;
}
if ( $this->meta( 'tcb2_ready' ) ) {
return $this;
}
$wp_content = trim( $this->post->post_content );
if ( empty( $wp_content ) && $this->meta( 'tve_globals', null, true ) ) {
$this->migrate( $update_plain_text );
}
return $this;
}
/**
* Checks whether or not this page is a landing page
*
* @return false|string The name of the template if this is a landing page, boolean false otherwise
*/
public function is_landing_page() {
$is_landing_page = $this->post instanceof WP_Post;
$is_landing_page = $is_landing_page && apply_filters( 'tve_allowed_post_type', true, $this->post->post_type );
if ( $is_landing_page ) {
$is_landing_page = $this->meta( 'tve_landing_page' );
}
return $is_landing_page;
}
/**
* Checks if the current post is a Thrive Lightbox
*/
public function is_lightbox() {
return $this->post && $this->post->post_type === 'tcb_lightbox';
}
}
/**
* Instantiates a new TCB_Post helper class
*
* @param null|mixed $post_id
*
* @return TCB_Post
*/
function tcb_post( $post_id = null ) {
return new TCB_Post( $post_id );
}
}

View File

@@ -0,0 +1,138 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-theme
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class Tcb_Scripts
*/
class Tcb_Scripts {
const HEAD_SCRIPT = 'head';
const BODY_SCRIPT = 'body';
const FOOTER_SCRIPT = 'footer';
/**
* All types of scripts that can be saved for a post
*/
const ALL = [ self::HEAD_SCRIPT, self::BODY_SCRIPT, self::FOOTER_SCRIPT ];
/**
* Option name where we are saving the scripts ( the same as the one from TAR )
*/
const OPTION_NAME = 'tve_global_scripts';
/**
* @var TCB_Post
*/
private $post;
/**
* @var null instance
*/
protected static $_instance;
/**
* General singleton implementation for class instance that also requires an id
*
* @param int $id
*
* @return null
*/
public static function instance_with_id( $id = 0 ) {
/* if we don't have any instance or when we send an id that it's not the same as the previous one, we create a new instance */
if ( empty( static::$_instance ) || is_wp_error( $id ) || ( ! empty( $id ) && static::$_instance->ID !== $id ) ) {
static::$_instance = new self( $id );
}
return static::$_instance;
}
/**
* Tcb_Scripts constructor.
*
* @param int $id
*/
public function __construct( $id = 0 ) {
$this->post = new TCB_Post( $id );
}
/**
* Add actions in order to insert the scripts properly
*/
public function hooks() {
add_action( 'wp_head', function () {
echo $this->get_all( self::HEAD_SCRIPT ); // phpcs:ignore;
} );
add_action( 'theme_after_body_open', function () {
echo $this->get_all( self::BODY_SCRIPT ); // phpcs:ignore;
} );
add_action( 'theme_before_body_close', function () {
echo $this->get_all( self::FOOTER_SCRIPT ); // phpcs:ignore;
} );
}
/**
* Get the posts global scripts
*
* @param string $type
*
* @return array|mixed|string
*/
public function get_all( $type = '' ) {
$scripts = $this->post->meta( static::OPTION_NAME );
$all = [];
foreach ( static::ALL as $value ) {
$all[ $value ] = isset( $scripts[ $value ] ) ? $scripts[ $value ] : '';
}
if ( empty( $type ) ) {
$scripts = $all;
} else {
$scripts = isset( $all[ $type ] ) ? $all[ $type ] : '';
}
return $scripts;
}
/**
* Save scripts
*
* @param $data
*/
public function save( $data ) {
$scripts = [];
foreach ( static::ALL as $value ) {
$key = "thrive_{$value}_scripts";
$scripts[ $value ] = isset( $data[ $key ] ) ? $data[ $key ] : '';
}
if ( ! empty( $scripts ) ) {
$this->post->meta( static::OPTION_NAME, $scripts );
}
}
}
if ( ! function_exists( 'tcb_scripts' ) ) {
/**
* Return Thrive_Post instance
*
* @param int id - post id
*
* @return Tcb_Scripts
*/
function tcb_scripts( $id = 0 ) {
return Tcb_Scripts::instance_with_id( $id );
}
}

View File

@@ -0,0 +1,161 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Search_Form
*/
class TCB_Search_Form {
private $shortcode_tag = 'tcb_search_form';
/**
* Default values for search post types
*
* @var array
*/
public static $default_post_types = [ 'post' => 'Post', 'page' => 'Page' ];
/**
* TCB_Search_Form constructor.
*/
public function __construct() {
add_action( 'init', [ $this, 'init_shortcode' ] );
add_filter( 'tcb_content_allowed_shortcodes', [ $this, 'tcb_content_allowed_shortcodes' ] );
add_action( 'pre_get_posts', [ $this, 'filter_post_types' ] );
}
/**
* Add the logo shortcode.
*/
public function init_shortcode() {
add_shortcode( $this->shortcode_tag, static function ( $attr ) {
/**
* Type validation
*/
if ( ! is_array( $attr ) ) {
$attr = [];
}
if ( ! empty( $attr['wrapper-events'] ) && is_string( $attr['wrapper-events'] ) ) {
$attr['wrapper-events'] = '__TCB_EVENT_[' . $attr['wrapper-events'] . ']_TNEVE_BCT__';
}
if ( ! empty( $attr['post-types'] ) && is_string( $attr['post-types'] ) ) {
$attr['post-types'] = json_decode( $attr['post-types'], true );
}
$attr = array_merge( static::default_attrs(), $attr );
$id = $attr['wrapper-id'];
$classes = 'thrv_wrapper thrv-search-form ' . $attr['wrapper-class'];
$content = static::render( $attr );
$wrapper_attr = [
'data-css' => esc_attr( $attr['data-css-form'] ),
'data-tcb-events' => esc_html( $attr['wrapper-events'] ),
'data-ct-name' => esc_attr( $attr['data-ct-name'] ),
'data-ct' => esc_attr( $attr['data-ct'] ),
'data-list' => isset( $attr['data-list'] ) ? esc_attr( $attr['data-list'] ) : '',
'data-display-d' => esc_attr( $attr['data-display-d'] ),
'data-position-d' => esc_attr( $attr['data-position-d'] ),
];
$additional_attrs = [ 'data-display-t', 'data-position-t', 'data-display-m', 'data-position-m', 'data-editor-preview' ];
foreach ( $additional_attrs as $additional_attr ) {
if ( isset( $attr[ $additional_attr ] ) ) {
$wrapper_attr[ $additional_attr ] = esc_attr( $attr[ $additional_attr ] );
}
}
return TCB_Utils::wrap_content( $content, 'div', $id, $classes, $wrapper_attr );
} );
}
/**
* Modify WP_Query before it asks the database what data to retrieve
*
* @param WP_Query $query
*
* @return void
*/
public function filter_post_types( $query ) {
// Don't run on admin
if ( $query->is_admin ) {
return;
}
// IF main query and search page
if ( $query->is_main_query() && $query->is_search() && isset( $_GET['tcb_sf_post_type'] ) ) {
$post_types = map_deep( $_GET['tcb_sf_post_type'], 'sanitize_text_field' );
/**
* Type validation
*/
if ( ! is_array( $post_types ) || empty( $post_types ) ) {
$post_types = static::$default_post_types;
}
$query->set( 'post_type', $post_types );
}
}
public function tcb_content_allowed_shortcodes( $shortcodes = [] ) {
if ( is_editor_page_raw( true ) ) {
$shortcodes = array_merge( $shortcodes, [ $this->shortcode_tag ] );
}
return $shortcodes;
}
/**
* Returns the default shortcode attributes
*
* @return array
*/
public static function default_attrs() {
return array(
'wrapper-id' => '',
'wrapper-class' => '',
'wrapper-events' => '',
'data-css-form' => '',
'data-ct' => 'search_form-56234',
'data-ct-name' => 'Default Template',
'data-css-input' => '',
'data-css-submit' => '',
'data-css-icon' => '',
'data-display-d' => 'none',
'data-position-d' => 'left',
'button-icon' => '<svg class="tcb-icon" viewBox="0 0 512 512" data-id="icon-search-regular"><path d="M508.5 468.9L387.1 347.5c-2.3-2.3-5.3-3.5-8.5-3.5h-13.2c31.5-36.5 50.6-84 50.6-136C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c52 0 99.5-19.1 136-50.6v13.2c0 3.2 1.3 6.2 3.5 8.5l121.4 121.4c4.7 4.7 12.3 4.7 17 0l22.6-22.6c4.7-4.7 4.7-12.3 0-17zM208 368c-88.4 0-160-71.6-160-160S119.6 48 208 48s160 71.6 160 160-71.6 160-160 160z"></path></svg>',
'button-layout' => 'icon_text',
'button-label' => __( 'Search', 'thrive-cb' ),
'input-placeholder' => esc_attr__( 'Search', 'thrive-cb' ),
'post-types' => static::$default_post_types,
);
}
/**
* Render shortcode
*
* @param array $attr
*
* @return string|null
*/
public static function render( $attr = [] ) {
return trim( tcb_template( 'search-form/shortcode', $attr, true ) );
}
}
new TCB_Search_Form();

View File

@@ -0,0 +1,172 @@
<?php
/**
* Class TCB_Show_When_Menu_Option
* - adds show when dropdown to each menu item in any menu
*/
class TCB_Show_When_Menu_Option {
/**
* @var TCB_Show_When_Menu_Option
*/
protected static $instance;
public $settings = [];
private function __construct() {
add_action( 'wp_nav_menu_item_custom_fields', [ $this, 'add_show_when_dropdown_to_menu_item' ], 10, 4 );
add_filter( 'wp_setup_nav_menu_item', [ $this, 'add_show_when_to_menu_item' ] );
add_action( 'wp_update_nav_menu_item', [ $this, 'wp_update_nav_menu_item' ], 10, 2 );
add_filter( 'wp_nav_menu_objects', [ $this, 'remove_specific_menu_items' ], 9 ); //before TA and TL
}
public function add_show_when_dropdown_to_menu_item( $item_id, $item ) {
echo tcb_template( 'show-when-dropdown.phtml', [ 'item' => $item, 'item_id' => $item_id ], true ); //phpcs:ignore
}
/**
* Adds the show when option to post meta
*
* @param int $menu_id
* @param int $menu_item_id
*/
public function wp_update_nav_menu_item( $menu_id, $menu_item_id ) {
$value = get_post_meta( $menu_item_id, '_menu_item_tcb_show_when', true );
if ( ! empty( $_REQUEST['tcb_show_when'][ $menu_item_id ] ) ) {
$value = sanitize_text_field( $_REQUEST['tcb_show_when'][ $menu_item_id ] );
}
if ( empty( $value ) ) {
$value = 'always';
}
update_post_meta( $menu_item_id, '_menu_item_tcb_show_when', $value );
}
/**
* @return TCB_Show_When_Menu_Option
*/
public static function get_instance() {
if ( ! static::$instance ) {
static::$instance = new static();
}
return static::$instance;
}
/**
* Adds the show when option from post meta to the menu item
*
* @param WP_Post $menu_item
*
* @return WP_Post
*/
public function add_show_when_to_menu_item( $menu_item ) {
$menu_item->tcb_show_when = get_post_meta( $menu_item->ID, '_menu_item_tcb_show_when', true );
return $menu_item;
}
/**
* Cuts menu items that shouldn't appear in the menu based on the 'Show when' option value
*
* @param array $sorted_menu_items indexing starts from 1
*
* @return array of nav menu items
*/
public function remove_specific_menu_items( $sorted_menu_items ) {
/**
* shift elements to left so that the elements start from 0 and not 1
*/
array_splice( $sorted_menu_items, 0, 0 );
$length = count( $sorted_menu_items );
$index = 0;
while ( $index < $length ) {
$show_when = $sorted_menu_items[ $index ]->tcb_show_when;
$shouldUnset = false;
switch ( $show_when ) {
case 'loggedin':
if ( ! is_user_logged_in() ) {
$shouldUnset = true;
}
break;
case 'loggedout':
if ( is_user_logged_in() ) {
$shouldUnset = true;
}
break;
}
if ( $shouldUnset ) {
$currentID = $sorted_menu_items[ $index ]->ID;
$currentElParent = $sorted_menu_items[ $index ]->menu_item_parent;
$i = $index + 1;
$previousElID = ! empty( $sorted_menu_items[ $index - 1 ] ) ? $sorted_menu_items[ $index - 1 ]->ID : null;
$previousElParent = ! empty( $sorted_menu_items[ $index - 1 ] ) ? $sorted_menu_items[ $index - 1 ]->menu_item_parent : '0';
/**
* iterate over every child menu item if it was a direct child then change child parent to current parent
*/
while ( $i < $length && $sorted_menu_items[ $i ]->menu_item_parent !== $previousElParent && $sorted_menu_items[ $i ]->menu_item_parent !== '0' ) {
if ( $sorted_menu_items[ $i ]->menu_item_parent == $currentID ) {
$sorted_menu_items[ $i ]->menu_item_parent = $currentElParent;
}
$i ++;
}
/**
* if it was the last child of an element then remove the has child class, so that the item won't indicate that it has children
*/
if ( $i == $index + 1 && $previousElID == $currentElParent ) {
$key = array_search( 'menu-item-has-children', $sorted_menu_items[ $index - 1 ]->classes );
if ( $key !== false ) {
unset( $sorted_menu_items[ $index - 1 ]->classes[ $key ] );
}
}
/**
* Remove the item from the array and thus the keys are reindexed
*/
array_splice( $sorted_menu_items, $index, 1 );
$index -= 1;
$length -= 1;
}
$index += 1;
}
//reset top level count once the elements are hidden
$GLOBALS['tcb_wp_menu']['top_level_count'] = count( array_filter( $sorted_menu_items, function ( $item ) {
return empty( $item->menu_item_parent );
} ) );
return $sorted_menu_items;
}
}
global $tcb_show_when;
/**
* Method wrapper for singleton
*
* @return TCB_Show_When_Menu_Option
*/
function tcb_show_when_menu_option() {
global $tcb_show_when;
$tcb_show_when = TCB_Show_When_Menu_Option::get_instance();
return $tcb_show_when;
}
add_action( 'after_setup_theme', 'tcb_show_when_menu_option' );

View File

@@ -0,0 +1,246 @@
<?php
/**
* Default TAr style class. Extend this to modify default style functionality
*
* Class TCB_Style_Provider
*/
class TCB_Style_Provider {
/**
* Get an array of default style specifications
*
* @return array
*/
protected function defaults() {
$defaults = array(
'link' => array(
/* needs to be quite specific. some 3rd party themes are really specific */
/* also need to make the selector from _typography.scss */
'selector' => ':not(.inc) .thrv_text_element a:not(.tcb-button-link), :not(.inc) .tcb-styled-list a, :not(.inc) .tcb-numbered-list a, .tve-input-option-text a',
'lp_selector' => '#tcb_landing_page .thrv_text_element a:not(.tcb-button-link), #tcb_landing_page .tcb-styled-list a, #tcb_landing_page .tcb-numbered-list a, #tcb_landing_page .tve-input-option-text a',
),
'p_link' => array(
'selector' => ':not(.inc) .thrv_text_element p a:not(.tcb-button-link):not(.thrv-typography-link-text)',
'lp_selector' => '#tcb_landing_page .thrv_text_element p a:not(.tcb-button-link)',
),
'heading_link' => array(
'selector' => ':not(#tve) :not(.inc) .thrv_text_element h1 a:not(.tcb-button-link), :not(#tve) :not(.inc) .thrv_text_element h2 a:not(.tcb-button-link), :not(#tve) :not(.inc) .thrv_text_element h3 a:not(.tcb-button-link), :not(#tve) :not(.inc) .thrv_text_element h4 a:not(.tcb-button-link), :not(#tve) :not(.inc) .thrv_text_element h5 a:not(.tcb-button-link), :not(#tve) :not(.inc) .thrv_text_element h6 a:not(.tcb-button-link)',
'lp_selector' => ':not(.inc) #tcb_landing_page h1 a:not(.tcb-button-link), :not(.inc) #tcb_landing_page h2 a:not(.tcb-button-link), :not(.inc) #tcb_landing_page h3 a:not(.tcb-button-link), :not(.inc) #tcb_landing_page h4 a:not(.tcb-button-link), :not(.inc) #tcb_landing_page h5 a:not(.tcb-button-link), :not(.inc) #tcb_landing_page h6 a:not(.tcb-button-link)',
),
'li_link' => array(
'selector' => ':not(.inc) .tcb-styled-list a, :not(.inc) .tcb-numbered-list a',
'lp_selector' => '#tcb_landing_page .tcb-styled-list a, :not(.inc) .tcb-numbered-list a',
),
'plaintext_link' => array(
'selector' => ':not(.inc) .tcb-plain-text a:not(.tcb-button-link)',
'lp_selector' => '#tcb_landing_page .tve_lp .tcb-plain-text a:not(.tcb-button-link)',
),
'p' => [
'selector' => '.tcb-style-wrap p',
'lp_selector' => '#tcb_landing_page p',
],
'ul' => array(
'selector' => '.tcb-style-wrap ul:not([class*="menu"]), .tcb-style-wrap ol',
'lp_selector' => '#tcb_landing_page ul:not([class*="menu"]), #tcb_landing_page ol',
),
'li' => array(
'selector' => '.tcb-style-wrap li:not([class*="menu"])',
'lp_selector' => '#tcb_landing_page li:not([class*="menu"])',
),
'pre' => [
'selector' => '.tcb-style-wrap pre',
'lp_selector' => '#tcb_landing_page pre',
],
'blockquote' => [
'selector' => '.tcb-style-wrap blockquote',
'lp_selector' => '#tcb_landing_page blockquote',
],
'plaintext' => [
'selector' => '.tcb-plain-text',
'lp_selector' => '.tve_lp .tcb-plain-text',
],
);
foreach ( range( 1, 6 ) as $level ) {
$defaults[ 'h' . $level ] = [
'selector' => '.tcb-style-wrap h' . $level,
'lp_selector' => '#tcb_landing_page h' . $level,
];
}
/**
* When the Typography is inherited from TTB, we need to update the selectors and make them stronger
*/
return apply_filters( 'tcb_typography_inherit', $defaults );
}
/**
* Get list of default TAr styles
*
* @return array
*/
public function get_styles() {
return $this->prepare_styles( $this->read_styles() );
}
/**
* Prepares the list of styles taken out of the DB, making sure it's valid, it contains all needed selectors etc
*
* @param array $styles
*
* @return array
*/
protected function prepare_styles( $styles ) {
$styles = (array) $styles;
/* ensure backwards compatibility -> @import rules are now stored in a single array key instead of scattered for each type */
$imports = isset( $styles['@imports'] ) ? $styles['@imports'] : [];
foreach ( $styles as $style_type => &$style_data ) {
if ( isset( $style_data['@imports'] ) ) {
$imports = array_merge( $imports, $style_data['@imports'] );
unset( $style_data['@imports'] );
$found = true;
}
}
if ( isset( $found ) ) {
$styles['@imports'] = TCB_Utils::merge_google_fonts( $imports );
$this->save_styles( $styles );
}
/* end backwards compat */
$defaults = $this->defaults();
$styles = array_intersect_key( $styles, $defaults ); // cleanup anything unnecessary
$styles['@imports'] = $imports;
foreach ( $defaults as $type => $style ) {
$styles[ $type ]['selector'] = $style['selector'];
$styles[ $type ]['lp_selector'] = $style['lp_selector'];
}
return (array) $styles;
}
/**
* Read styles from data source.
* Default: read them from wp_options
*
* When extending the class, this method should be overridden
*
* @return array formatted list of styles
*/
protected function read_styles() {
$styles = get_option( 'tve_default_styles', [] );
/* li gets the same styles as <p> at first, but it's stylable individually in some places */
if ( empty( $styles['li'] ) ) {
$styles['li'] = isset( $styles['p'] ) ? $styles['p'] : [];
}
/* For the new links we need to set the styles previously added on the Link element */
if ( empty( $styles['p_link'] ) ) {
$styles['p_link'] = isset( $styles['link'] ) ? $styles['link'] : [];
}
if ( empty( $styles['li_link'] ) ) {
$styles['li_link'] = isset( $styles['link'] ) ? $styles['link'] : [];
}
if ( empty( $styles['plaintext_link'] ) ) {
$styles['plaintext_link'] = isset( $styles['link'] ) ? $styles['link'] : [];
}
return $styles;
}
/**
* Saves styles to the database
*
* @param array $styles
*/
public function save_styles( $styles ) {
update_option( 'tve_default_styles', $styles );
}
/**
* Process raw styles, building and replacing selectors
*
* @param array $raw_styles raw styles collected from DB
* @param string $return Can be one of 'string', 'object' used to control how to return the results
* @param bool $include_fonts Whether or not to include @import rules in the output
*
* @return array|string array with @imports and media keys, each of them a string
* or a string containing all CSS
*/
public function get_processed_styles( $raw_styles = null, $return = 'object', $include_fonts = true ) {
$raw_styles = $this->prepare_styles( isset( $raw_styles ) ? $raw_styles : $this->read_styles() );
$data = array(
'@imports' => isset( $raw_styles['@imports'] ) ? $raw_styles['@imports'] : [],
'media' => [],
);
unset( $raw_styles['@imports'] );
foreach ( $raw_styles as $element_type => $style_data ) {
$selector = $style_data['selector'];
$suffix_selector = str_replace( ', ', '%suffix%, ', $selector ) . '%suffix%';
unset( $style_data['selector'], $style_data['@imports'], $style_data['lp_selector'] );
foreach ( $style_data as $media_key => $css_rules ) {
$css_rules = implode( '', $css_rules );
/**
* Default styles should NEVER generate !important. (This was added by :hover for links from typography)
*/
$css_rules = str_replace( [ ' !important', '!important' ], '', $css_rules );
/* make sure suffix selectors are built correctly */
$css_rules = preg_replace_callback( '#__el__([^{]{2,}?){#m', function ( $matches ) use ( $suffix_selector ) {
return str_replace( '%suffix%', rtrim( $matches[1] ), $suffix_selector ) . ' {';
}, $css_rules );
$data['media'][ $media_key ] = ( isset( $data['media'][ $media_key ] ) ? $data['media'][ $media_key ] : '' ) . str_replace( '__el__', $selector, $css_rules );
}
}
if ( tve_dash_is_google_fonts_blocked() ) {
$data['@imports'] = [];
}
$media_query_order = array_flip( array(
'(min-width: 300px)',
'(max-width: 1023px)',
'(max-width: 767px)',
) );
/* Make sure the media queries are in the correct order */
uksort( $data['media'], static function ( $key1, $key2 ) use ( $media_query_order ) {
if ( ! isset( $media_query_order[ $key2 ] ) ) {
return 1;
}
if ( ! isset( $media_query_order[ $key1 ] ) ) {
return - 1;
}
return $media_query_order[ $key1 ] - $media_query_order[ $key2 ];
} );
if ( $return === 'string' ) {
$css = $include_fonts ? implode( "", $data['@imports'] ) : '';
foreach ( $data['media'] as $media => $css_str ) {
$css .= "@media {$media} { $css_str }";
}
return $css;
}
return $data;
}
/**
* @return array
*/
public function get_css_imports() {
$styles = $this->read_styles();
return isset( $styles['@imports'] ) ? $styles['@imports'] : [];
}
}

View File

@@ -0,0 +1,579 @@
<?php
/**
* FileName class-tcb-symbol-element-abstract.php.
*
* @project : thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Symbol_Element_Abstract
*/
abstract class TCB_Symbol_Element_Abstract extends TCB_Cloud_Template_Element_Abstract {
/**
* Config for symbol
*
* @var string
*/
public $_cfg_code = '__CONFIG_post_symbol__';
/**
* This is only a placeholder element
*
* @return bool
*/
public function is_placeholder() {
return true;
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
return [];
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return static::get_thrive_basic_label();
}
/**
* HTML layout of the element for when it's dragged in the canvas
*
* @return string
*/
public function html() {
return $this->html_placeholder( sprintf( __( 'Insert %s', 'thrive-cb' ), $this->name() ) );
}
/**
* Returns the HTML placeholder for an element (contains a wrapper, and a button with icon + element name)
*
* @param string $title Optional. Defaults to the name of the current element
*
* @return string
*/
public function html_placeholder( $title = null ) {
if ( empty( $title ) ) {
$title = $this->name();
}
return tcb_template( 'elements/section-placeholder', array(
'icon' => $this->icon(),
'id' => 'thrive-' . $this->tag(),
'class' => 'thrv_symbol ' . 'thrv_' . $this->tag(),
'title' => $title,
'extra_attr' => 'data-shortcode=thrive_' . $this->tag() . ' data-selector="' . '.thrv_symbol' . '.thrv_' . $this->tag() . '" data-tcb-elem-type="' . $this->tag() . '" data-element-name="' . esc_attr( $this->name() ) . '"',
), true );
}
/**
* Make sure that a symbol title is provided and it's unique
*
* @param array $args
*
* @return bool|WP_Error
*/
public function ensure_title( $args ) {
/* If the title is not set, just throw the error */
if ( ! isset( $args['post_title'] ) ) {
return new WP_Error( 'rest_cannot_create_post', __( 'Sorry, you are not allowed to create symbols without title' ), [ 'status' => 409 ] );
}
$post = tve_get_page_by_title( $args['post_title'], TCB_Symbols_Post_Type::SYMBOL_POST_TYPE );
if ( $post && $post->post_status !== 'trash' ) {
return new WP_Error( 'rest_cannot_create_post', __( 'Sorry, you are not allowed to create global elements with the same title' ), [ 'status' => 409 ] );
}
return true;
}
/**
* Get all symbols
*/
public function get_all( $args, $is_localize = false ) {
$result = [];
$defaults = [
'post_type' => TCB_Symbols_Post_Type::SYMBOL_POST_TYPE,
'posts_per_page' => - 1,
'post_status' => 'publish',
];
//get symbols from a specific category
if ( isset( $args['category_name'] ) ) {
$args['tax_query'] = array(
array(
'taxonomy' => TCB_Symbols_Taxonomy::SYMBOLS_TAXONOMY,
'field' => 'slug',
'terms' => $args['category_name'],
),
);
unset( $args['category_name'] );
}
//exclude symbols from categories
if ( isset( $args['category__not_in'] ) ) {
$args['tax_query'] = array(
array(
'taxonomy' => TCB_Symbols_Taxonomy::SYMBOLS_TAXONOMY,
'field' => 'term_id',
'terms' => $args['category__not_in'],
'operator' => 'NOT IN',
),
);
unset( $args['category__not_in'] );
}
$args = wp_parse_args( $args, $defaults );
/**
* Add the possibility for other plugins to change the arguments for getting the symbols
*
* @param array $args
*/
$args = apply_filters( 'tcb_get_symbols_args', $args );
$symbols = get_posts( $args );
if ( is_wp_error( $symbols ) ) {
return new WP_Error( 'query_error', __( 'Error when retrieving symbols', 'thrive-cb' ) );
}
ob_start(); // some plugins echo output through shortcodes causing the ajax request to be misshaped
foreach ( $symbols as $symbol ) {
$result['local'][ $symbol->ID ] = $this->prepare_symbol( $symbol, $is_localize ) + [ 'is_local' => 1 ];
}
ob_end_clean();
//if we have templates in the cloud get them
//else just return the local results
if ( $this->has_cloud_templates() ) {
//get the templates from the cloud
$cloud_items = $this->get_cloud_templates();
if ( is_wp_error( $cloud_items ) ) {
return $cloud_items;
}
$result['cloud'] = $cloud_items;
} else {
$result = isset( $result['local'] ) ? $result['local'] : $result;
}
/**
* Change the symbols array returned
*
* @param array $result
*/
$result = apply_filters( 'tcb_get_symbols_response', $result );
return $result;
}
/**
* Prepare symbol before listing in TAR
*
* @param WP_Post $symbol
* @param bool $is_localize
*
* @return array
*/
public function prepare_symbol( $symbol, $is_localize = false ) {
$symbol_data = [];
if ( $symbol instanceof WP_Post && $symbol->post_status === 'publish' ) {
$globals = get_post_meta( $symbol->ID, 'tve_globals', true );
if ( empty( $globals ) ) {
$globals = [];
}
$symbol_data = [
'id' => $symbol->ID,
'post_title' => $symbol->post_title,
'config' => $this->_get_symbol_config( $symbol ),
'thumb' => TCB_Utils::get_thumb_data( $symbol->ID, TCB_Symbols_Post_Type::SYMBOL_THUMBS_FOLDER, TCB_Utils::get_placeholder_data() ),
'tve_globals' => $globals,
];
if ( ! $is_localize ) {
$symbol_data = array_merge(
$symbol_data,
[
'content' => TCB_Symbol_Template::render_content( [ 'id' => $symbol->ID ] ),
'css' => $this->get_symbol_css( $symbol->ID ),
]
);
}
}
/**
* Change symbol data before showing it in the list
*
* @param array $symbol_data
*/
return apply_filters( 'tcb_symbol_data_before_return', $symbol_data );
}
/**
* Get css for a certain symbol
*
* @param int $id
*
* @return mixed
*/
public function get_symbol_css( $id ) {
$custom_css = get_post_meta( $id, 'tve_custom_css', true );
/* If we want to change the symbol css just before is being inserted in the page */
$custom_css = apply_filters( 'tcb_symbol_css_before', $custom_css, $id );
return $custom_css;
}
/**
* Get config for symbol
*
* @param WP_Post $symbol
*
* @return string
*/
private function _get_symbol_config( $symbol ) {
$encoded_config = tve_json_utf8_unslashit( json_encode( array( 'id' => ( string ) $symbol->ID ) ) );
return $this->_cfg_code . $encoded_config . $this->_cfg_code;
}
/**
* Save a symbol changed from within the editor page
*
* @param array $symbol_data
*
* @return array|WP_Error
*/
public function edit_symbol( $symbol_data ) {
if ( ! isset( $symbol_data['id'] ) ) {
return new WP_Error( 'id_is_not_set', __( 'Missing symbol id', 'thrive-cb' ), [ 'status' => 500 ] );
}
/**
* Added some defaults
*/
$symbol_data = array_merge( [
'has_icons' => 0,
'class' => '',
], $symbol_data );
/**
* update CSS text to reflect new symbol id ( replace cloud id placeholder with local id in css text)
*/
$symbol_data['css'] = str_replace( '|TEMPLATE_ID|', $symbol_data['id'], $symbol_data['css'] );
update_post_meta( $symbol_data['id'], 'tve_updated_post', $symbol_data['content'] );
update_post_meta( $symbol_data['id'], 'tve_custom_css', $symbol_data['css'] );
update_post_meta( $symbol_data['id'], 'tve_globals', $symbol_data['tve_globals'] );
update_post_meta( $symbol_data['id'], 'thrive_icon_pack', $symbol_data['has_icons'] );
update_post_meta( $symbol_data['id'], 'tve_extra_class', $symbol_data['class'] );
$symbol = get_post( $symbol_data['id'] );
return [ 'symbol' => $symbol ];
}
/**
* Create symbol from content elements
*
* @param array $symbol_data
*
* @return array|int|WP_Error
*/
public function create_symbol( $symbol_data ) {
$create_symbol_defaults = [
'post_type' => TCB_Symbols_Post_Type::SYMBOL_POST_TYPE,
'post_status' => 'publish',
];
$post_title = str_replace( '\\', '', $symbol_data['symbol_title'] );
$create_symbol_args = wp_parse_args( [ 'post_title' => $post_title ], $create_symbol_defaults );
/**
* Add the possibility for other plugins to change the arguments for creating a symbol
*
* @param array $args
*/
$create_symbol_args = apply_filters( 'tcb_create_symbol_args', $create_symbol_args );
/* Ensure that the title exists and it's unique */
$check_title = $this->ensure_title( $create_symbol_args );
if ( is_wp_error( $check_title ) ) {
return $check_title;
}
$post_id = wp_insert_post( $create_symbol_args, true );
//if something went wrong at insert, just return the error
if ( is_wp_error( $post_id ) ) {
return $post_id;
}
/**
* After save actions: add to category and update meta ( html and css )
*/
$this->after_save( $post_id, $symbol_data );
//return the newly created symbol for later use, if needed
$symbol = get_post( $post_id );
//prepare the symbol to be inserted in the page after a successful save
return $this->prepare_symbol( $symbol );
}
/**
* Actions taken if a symbols is successfully created
*
* @param int $post_id
* @param array $symbol_data
*/
public function after_save( $post_id, $symbol_data ) {
/**
* Added some defaults
*/
$symbol_data = array_merge( [
'has_icons' => 0,
], $symbol_data );
//if we are sending the category than assign the symbol to it
$terms = isset( $symbol_data['term_id'] ) ? [ $symbol_data['term_id'] ] : [];
wp_set_post_terms( $post_id, $terms, TCB_Symbols_Taxonomy::SYMBOLS_TAXONOMY );
/**
* update CSS text to reflect new symbol id ( replace cloud id placeholder with local id in css text)
*/
$symbol_data['css'] = isset( $symbol_data['css'] ) ? str_replace( '|TEMPLATE_ID|', $post_id, $symbol_data['css'] ) : '';
$upload_dir = wp_upload_dir();
/** If created from an existing symbol, replace the old ID with the new ID */
if ( ! empty( $symbol_data['from_existing_id'] ) ) {
$symbol_data['css'] = str_replace( 'symbol_' . $symbol_data['from_existing_id'], 'symbol_' . $post_id, $symbol_data['css'] );
/**
* Copy the thumbnail from the original symbol to the new one.
*/
if ( empty( $upload_dir['error'] ) ) {
$thumb_data = TCB_Utils::get_thumbnail_data_from_id( $symbol_data['from_existing_id'] );
$thumb_path = trailingslashit( $upload_dir['basedir'] ) . TCB_Symbols_Post_Type::SYMBOL_THUMBS_FOLDER . '/' . $symbol_data['from_existing_id'] . '.png';
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
if ( $thumb_data && @is_readable( $thumb_path ) ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
$copied = @copy( $thumb_path, dirname( $thumb_path ) . '/' . $post_id . '.png' );
if ( $copied ) {
$thumb_data['url'] = str_replace( $symbol_data['from_existing_id'], $post_id, $thumb_data['url'] );
TCB_Utils::save_thumbnail_data( $post_id, $thumb_data );
}
}
}
} elseif ( ! empty( $symbol_data['thumb'] ) ) {
/* We also need to copy the thumbnail if the symbol was created base on a cloud template */
$thumb_data = $symbol_data['thumb'];
if ( ! empty( $thumb_data['url'] ) ) {
$thumb_path = $thumb_data['url'];
if ( strpos( $thumb_path, 'http' ) === false ) {
$thumb_path = 'http:' . $thumb_path;
}
$destination = TCB_Symbols_Post_Type::SYMBOL_THUMBS_FOLDER . '/' . $post_id . '.png';
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
$copied = @copy( $thumb_path, trailingslashit( $upload_dir['basedir'] ) . $destination );
if ( $copied ) {
$thumb_data['url'] = trailingslashit( $upload_dir['baseurl'] ) . $destination;
TCB_Utils::save_thumbnail_data( $post_id, $thumb_data );
}
}
}
//if the insert was ok, update the meta attributes for the symbol
update_post_meta( $post_id, 'tve_updated_post', $symbol_data['content'] );
update_post_meta( $post_id, 'tve_custom_css', $symbol_data['css'] );
update_post_meta( $post_id, 'tve_globals', $symbol_data['tve_globals'] );
update_post_meta( $post_id, 'thrive_icon_pack', $symbol_data['has_icons'] );
update_post_meta( $post_id, 'tve_extra_class', $symbol_data['class'] );
\TCB\Lightspeed\Main::handle_optimize_saves( $post_id, $symbol_data );
}
/**
* Save css for elements with extra css. i.e call to action
* The css selectors are updated with proper thrv_symbol selectors
*
* @param array $data
*
* @return array|WP_Error
*/
public function save_extra_css( $data ) {
if ( ! isset( $data['id'] ) ) {
return new WP_Error( 'id_is_not_set', __( 'Missing symbol id', 'thrive-cb' ), [ 'status' => 500 ] );
}
update_post_meta( $data['id'], 'tve_custom_css', $data['css'] );
$symbol = get_post( $data['id'] );
return [ 'symbol' => $symbol ];
}
/**
* Generate preview for the symbol
*
* @param int $post_id
* @param string $element_type
*
* @return array|WP_Error
*/
public function generate_preview( $post_id, $element_type = 'symbol' ) {
add_filter( 'upload_dir', [ $this, 'upload_dir' ] );
$preview_file = ! empty( $_FILES['preview_file'] ) ? $_FILES['preview_file'] : []; // phpcs:ignore
$moved_file = wp_handle_upload( $preview_file, [
'action' => TCB_Editor_Ajax::ACTION,
'unique_filename_callback' => [ $this, 'get_preview_filename' ],
] );
remove_filter( 'upload_dir', [ $this, 'upload_dir' ] );
if ( empty( $moved_file['url'] ) ) {
return new WP_Error( 'file_not_saved', __( 'The file could not be saved', 'thrive-cb' ), [ 'status' => 500 ] );
}
$new_width = in_array( $element_type, [ 'header', 'footer' ] ) ? 600 : 300;
$preview = wp_get_image_editor( $moved_file['file'] );
if ( ! is_wp_error( $preview ) ) {
$preview->resize( $new_width, null );
$preview->save( $moved_file['file'] );
}
$editor = wp_get_image_editor( $moved_file['file'] );
$editor->save( $moved_file['file'] );
$dimensions = $editor->get_size();
$thumb = [
'url' => $moved_file['url'],
'h' => $dimensions['height'],
'w' => $dimensions['width'],
];
TCB_Utils::save_thumbnail_data( $post_id, $thumb );
return $thumb;
}
/**
* Get the name for the thumbnail
* Prevent wordpress for creating a new file when it already exists in the uploads folder
*
* @param string $dir
* @param string $name
* @param string $ext
*
* @return mixed
*/
public function get_preview_filename( $dir, $name, $ext ) {
return $name;
}
/**
* Get the upload directory where the file will be kept
*
* @param array $upload
*
* @return mixed
*/
public static function upload_dir( $upload ) {
$sub_dir = '/' . TCB_Symbols_Post_Type::SYMBOL_THUMBS_FOLDER;
$upload['path'] = $upload['basedir'] . $sub_dir;
$upload['url'] = $upload['baseurl'] . $sub_dir;
$upload['subdir'] = $sub_dir;
return $upload;
}
/**
* @param array $args
*
* @return array|WP_Error
*/
public function get_cloud_templates( $args = [] ) {
$result = [];
$cloud_templates = parent::get_cloud_templates( $args );
if ( is_wp_error( $cloud_templates ) ) {
return $cloud_templates;
}
$included_cloud_fields = isset( $args['included_cloud_fields'] ) ? $args['included_cloud_fields'] : [];
//see how the cloud templates are returned when you have elements of that type or when you don't
if ( ! empty( $cloud_templates ) ) {
foreach ( (array) $cloud_templates as $cloud_template ) {
$result[ $cloud_template['id'] ] = array(
'id' => $cloud_template['id'],
'post_title' => $cloud_template['name'],
'thumb' => array(
'url' => $cloud_template['thumb'],
'w' => isset( $cloud_template['thumb_size'] ) ? $cloud_template['thumb_size']['w'] : '',
'h' => isset( $cloud_template['thumb_size'] ) ? $cloud_template['thumb_size']['h'] : '',
),
'from_cloud' => 1,
);
foreach ( $included_cloud_fields as $field ) {
if ( isset( $cloud_template[ $field ] ) ) {
$result[ $cloud_template['id'] ][ $field ] = $cloud_template[ $field ];
}
}
}
}
return $result;
}
/**
* Get path for symbol thumbnail
*
* @param int $old_path
* @param int $new_id
*
* @return bool
*/
public function copy_thumb( $old_path, $new_id ) {
if ( strpos( $old_path, 'http' ) === false ) {
$old_path = 'http:' . $old_path;
}
$upload_dir = wp_upload_dir();
$new_path = trailingslashit( $upload_dir['basedir'] ) . TCB_Symbols_Post_Type::SYMBOL_THUMBS_FOLDER . '/' . $new_id . '.png';
return copy( $old_path, $new_path );
}
}

View File

@@ -0,0 +1,356 @@
<?php
class TCB_User_Profile_Handler {
const DEFAULT_FIELDS = [
'user_email',
'username',
'nickname',
'first_name',
'last_name',
'display_name',
'website',
'user_bio',
'pass1',
'pass2',
];
/**
* Config attribute separator
*/
const SEP = '__TCB_UP__';
const SHORTCODE = 'tve_user_profile';
const NONCE = 'tve-user-profile-nonce';
public static function init() {
static::hooks();
}
public static function hooks() {
add_shortcode( static::SHORTCODE, [ __CLASS__, 'render_shortcode' ] );
add_action( 'wp_ajax_tve_user_profile_update', [ __CLASS__, 'handle_update_data' ] );
add_filter( 'tve_thrive_shortcodes', [ __CLASS__, 'thrive_shortcodes' ], 10, 2 );
add_filter( 'tcb.content_pre_save', [ __CLASS__, 'handle_content_pre_save' ], 10, 2 );
add_filter( 'tcb_content_allowed_shortcodes', [ __CLASS__, 'content_allowed_shortcodes_filter' ] );
add_filter( 'tve_frontend_options_data', [ __CLASS__, 'frontend_options_data' ], 10, 2 );
}
/**
* On frontend contexts, always remove the config
*/
public static function thrive_shortcodes( $content, $is_editor_page ) {
if ( ! ( $is_editor_page || strpos( $content, static::SEP ) === false ) ) {
return preg_replace( static::pattern( true ), '', $content );
}
return $content;
}
/**
* Add nonce to frontend options
*
* @param array $data The frontend options data
*
* @return array The updated frontend options data with nonce added
*/
public static function frontend_options_data( $data ) {
$data['user_profile_nonce'] = wp_create_nonce( static::NONCE );
return $data;
}
/**
* Handle the ajax request and validate fields
*/
public static function handle_update_data() {
if ( ! wp_verify_nonce( $_REQUEST['form-nonce'], static::NONCE ) ) {
wp_send_json(
[
'errors' => __( 'Unauthorized access.', 'thrive-cb' ),
'success' => false,
]
);
}
if ( current_user_can( 'manage_options' ) ) {
wp_send_json(
[
'errors' => __( "Admins can't update profile data using the profile element.", 'thrive-cb' ),
'success' => false,
]
);
}
$data = [];
$response = [ 'success' => true ];
/**
* Check whether or not the form settings exist
*/
if ( empty( $_POST['form_id'] ) || ! $config = get_option( sanitize_text_field( $_POST['form_id'] ) ) ) {
$response['errors'] = __( 'Form settings validation failed', 'thrive-cb' );
} else {
$config = json_decode( wp_unslash( $config ) );
if ( ! empty( $config->fields ) ) {
foreach ( static::DEFAULT_FIELDS as $field ) {
if ( ! empty( $_POST[ $field ] ) && in_array( $field, $config->fields ) ) {
if ( $field === 'user_bio' ) {
$data[ $field ] = sanitize_textarea_field( $_POST[ $field ] );
} else {
$data[ $field ] = sanitize_text_field( $_POST[ $field ] );
}
}
}
}
}
if ( empty( $data ) ) {
$response['success'] = false;
} else {
$required_fields_fulfilled = true;
/**
* Double-check for required fields
*/
if ( ! empty( $config ) && ! empty( $config->required ) ) {
foreach ( $config->required as $field ) {
if ( empty( $data[ $field ] ) ) {
$required_fields_fulfilled = false;
}
}
}
if ( $required_fields_fulfilled ) {
$update_response = static::update( $data );
if ( is_wp_error( $update_response ) ) {
$response['success'] = false;
$response['errors'] = $update_response;
}
} else {
$response['success'] = false;
$response['errors'] = __( 'Missing required fields', 'thrive-cb' );
}
}
wp_send_json( $response );
}
/**
* Update data function
* Based on wp function edit_user
*
* @param $data
*
* @return int|mixed|string|WP_Error
*/
public static function update( $data ) {
$current_user = wp_get_current_user();
if ( empty( $current_user->data ) || empty( $current_user->data->ID ) ) {
return '';
}
$user_id = (int) $current_user->data->ID;
$user = new stdClass();
$user->ID = $user_id;
$userdata = get_userdata( $user_id );
$user->user_login = wp_slash( $userdata->user_login );
$pass1 = '';
if ( isset( $data['pass1'] ) ) {
$pass1 = trim( $data['pass1'] );
}
if ( isset( $data['pass2'] ) ) {
$pass2 = trim( $data['pass2'] );
}
if ( isset( $data['user_email'] ) ) {
$user->user_email = $data['user_email'];
}
if ( isset( $data['website'] ) ) {
if ( empty( $data['website'] ) || 'http://' === $data['website'] ) {
$user->user_url = '';
} else {
$user->user_url = esc_url_raw( $data['website'] );
$protocols = implode( '|', array_map( 'preg_quote', wp_allowed_protocols() ) );
$user->user_url = preg_match( '/^(' . $protocols . '):/is', $user->user_url ) ? $user->user_url : 'http://' . $user->user_url;
}
}
if ( isset( $data['first_name'] ) ) {
$user->first_name = $data['first_name'];
}
if ( isset( $data['last_name'] ) ) {
$user->last_name = $data['last_name'];
}
if ( isset( $data['nickname'] ) ) {
$user->nickname = $data['nickname'];
}
if ( isset( $data['display_name'] ) ) {
$user->display_name = $data['display_name'];
}
if ( isset( $data['user_bio'] ) ) {
$user->description = trim( $data['user_bio'] );
}
$errors = new WP_Error();
/**
* Fires before the password and confirm password fields are checked for congruity.
*
* @param string $user_login The username.
* @param string $pass1 The password (passed by reference).
* @param string $pass2 The confirmed password (passed by reference).
*
* @since 1.5.1
*/
do_action_ref_array( 'check_passwords', [ $user->user_login, &$pass1, &$pass2 ] );
// Check for "\" in password.
if ( false !== strpos( wp_unslash( $pass1 ), '\\' ) ) {
$errors->add( 'pass_slash', __( '<strong>Error</strong>: Passwords may not contain the character "\\".', 'thrive-cb' ), [ 'form-field' => 'pass1' ] );
}
if ( ! empty( $pass1 ) ) {
$user->user_pass = $pass1;
$score = tve_score_password( $pass1 );
if ( $score <= 30 ) {
$errors->add( 'password_score', __( 'Please choose a stronger password. Try including numbers, symbols, and a mix of upper and lowercase letters and remove common words.', 'thrive-cb' ), [ 'form-field' => 'pass1' ] );
}
// Checking the password has been typed twice the same.
if ( ! empty( $pass2 ) && $pass1 != $pass2 ) {
$errors->add( 'passwordmismatch', __( "Passwords don't match. Please enter the same password in both password fields." ), [ 'form-field' => 'pass1' ] );
}
}
/* checking email address */
if ( ! empty( $user->user_email ) ) {
if ( ! is_email( $user->user_email ) ) {
$errors->add( 'invalid_email', __( "The email address isn't correct.", 'thrive-cb' ), [ 'form-field' => 'email' ] );
} else {
$owner_id = email_exists( $user->user_email );
if ( $owner_id && ( $owner_id != $user->ID ) ) {
$errors->add( 'email_exists', __( 'This email is already registered. Please choose another one.', 'thrive-cb' ), [ 'form-field' => 'email' ] );
}
}
}
/**
* Fires before user profile update errors are returned.
*
* @param WP_Error $errors WP_Error object (passed by reference).
* @param bool $update Whether this is a user update.
* @param stdClass $user User object (passed by reference).
*
* @since 2.8.0
*/
do_action_ref_array( 'user_profile_update_errors', [ &$errors, true, &$user ] );
if ( $errors->has_errors() ) {
return $errors;
}
return wp_update_user( $user );
}
/**
* Build the regex pattern for matching form json configuration
*
* @param bool $with_attribute whether or not to also match the `data-form-settings` attribute
*
* @return string
*/
public static function pattern( $with_attribute = false ) {
$regex = static::SEP . '(.+?)' . static::SEP;
if ( $with_attribute ) {
$regex = ' data-config="' . $regex . '"';
}
return "#{$regex}#s";
}
/**
* Only render the shortcode if the user logged
*
* @param $attr
* @param $content
* @param $tag
*
* @return string
*/
public static function render_shortcode( $attr, $content ) {
$html = '';
if ( is_user_logged_in() ) {
$html = TCB_Utils::wrap_content( $content, 'div', '', 'thrv_wrapper tve-user-profile tcb-local-vars-root', $attr );
}
return $html;
}
/**
* Allow the shortcode to be rendered in the editor
*
* @param $shortcodes
*
* @return array
*/
public static function content_allowed_shortcodes_filter( $shortcodes ) {
if ( is_editor_page_raw( true ) ) {
$shortcodes[] = static::SHORTCODE;
}
return $shortcodes;
}
/**
* Handle user profile settings and store them as options
*
* @param $response
* @param $post_data
*
* @return mixed
*/
public static function handle_content_pre_save( $response, $post_data ) {
if ( ! empty( $post_data['user_profile_forms'] ) ) {
foreach ( $post_data['user_profile_forms'] as $form_id => $settings ) {
if ( strncmp( $form_id, 'tve-up-', 7 ) === 0 ) {
update_option( $form_id, $settings );
}
}
}
if ( ! empty( $post_data['user_profile_deleted_forms'] ) ) {
foreach ( $post_data['user_profile_deleted_forms'] as $form_id ) {
if ( strncmp( $form_id, 'tve-up-', 7 ) === 0 ) {
delete_option( $form_id );
}
}
}
// delete existing lead gen forms data.
if ( ! empty( $post_data['post_id'] ) ) {
global $wpdb;
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->prefix}postmeta
WHERE meta_key LIKE '_tve_lead_gen_form\_%' AND post_id = %d",
$post_data['post_id']
)
);
}
return $response;
}
}
TCB_User_Profile_Handler::init();

View File

@@ -0,0 +1,942 @@
<?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;
}
}

View File

@@ -0,0 +1,161 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Widget_Element
*/
class TCB_Widget_Element extends TCB_Element_Abstract {
/**
* @var WP_Widget
*/
private $widget;
/**
* TCB_Widget_Element constructor.
*
* @param $widget WP_Widget
*
* @throws Exception
*/
public function __construct( $widget ) {
if ( $widget instanceof WP_Widget ) {
$tag = 'widget_' . $widget->id_base;
$this->widget = $widget;
if ( method_exists( $widget, 'enqueue_admin_scripts' ) ) {
$widget->enqueue_admin_scripts();
}
if ( method_exists( $widget, 'render_control_template_scripts' ) ) {
$widget->render_control_template_scripts();
}
parent::__construct( $tag );
} else {
throw new Exception( 'Constructor argument should be a WP_Widget instance' );
}
}
/**
* Name of the element
*
* @return string
*/
public function name() {
$name = $this->widget->name;
/* some widgets already have 'Widget' at the end of their name */
if ( strpos( $name, 'Widget' ) === false ) {
$name .= ' ' . __( 'Widget', 'thrive-cb' );
}
return $name;
}
/**
* Set alternate for widget so we can better find him with search
*
* @return mixed|string|string[]|null
*/
public function alternate() {
return $this->widget->id_base;
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
/**
* Filter widget icon in case we want something special
*
* @param string $icon by default it's the wordpress icon
* @param WP_Widget $widget the current widget
*
* @return string
*/
return apply_filters( 'tcb_widget_element_icon', 'wordpress', $this->widget );
}
/**
* Button element identifier
*
* @return string
*/
public function identifier() {
return '.thrv_' . $this->widget->id_base;
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
/**
* Filter widget category label in case we want to group widgets differently
*
* @param string $icon by default we have 'Widgets'
* @param WP_Widget $widget the current widget
*
* @return string
*/
return apply_filters( 'tcb_widget_element_category', static::get_widgets_label(), $this->widget );
}
/**
* HTML of the current widget
*
* @return string
*/
public function html() {
return '<div class="thrv_wrapper thrv_widget thrv_' . $this->widget->id_base . ' tcb-empty-widget tcb-elem-placeholder">
<span class="tcb-inline-placeholder-action with-icon">' . tcb_icon( 'wordpress', true, 'editor' ) . $this->name() . '</span>
</div>';
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
return array(
'widget' => [
'config' => [],
],
'styles-templates' => [ 'hidden' => true ],
'typography' => [ 'hidden' => true ],
'animation' => array(
'disabled_controls' =>
array( '.btn-inline.anim-link', '.btn-inline.anim-popup' ),
),
'layout' => [
'disabled_controls' => [],
],
'borders' => [
'config' => [
'Borders' => [
'important' => true,
],
'Corners' => [
'important' => true,
],
],
],
);
}
}

View File

@@ -0,0 +1,132 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay;
use TCB\ConditionalDisplay\Traits\Item;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
abstract class Condition {
use Item;
private $value;
private $operator;
private $um;
private $extra;
public function __construct( $data ) {
$this->prepare_data( $data );
}
public function prepare_data( $data ) {
$this->value = empty( $data['value'] ) ? '' : $data['value'];
if ( ! empty( $data['operator'] ) ) {
$this->operator = $data['operator'];
}
if ( ! empty( $data['extra'] ) ) {
$this->extra = $data['extra'];
}
if ( ! empty( $data['um'] ) ) {
$this->um = $data['um'];
}
}
public function get_value() {
return $this->value;
}
public function get_operator() {
return $this->operator;
}
public function get_um() {
return $this->um;
}
public function get_extra() {
return $this->extra;
}
/**
* @return string
*/
abstract public static function get_key();
abstract public static function get_label();
abstract public function apply( $data );
/**
* Function that should be implemented individually - for situations where the filter has multiple operators, get a list of them
*/
abstract public static function get_operators();
/**
* Allows adding extra operators, for conditions on multiple rows
*
* @return array
*/
public static function get_extra_operators() {
return [];
}
public static function get_control_type() {
return 'input';
}
/**
* This determines whether the select for the operator is shown or not.
*
* @return bool
*/
public static function is_hidden() {
return false;
}
public static function get_display_size() {
return 'small';
}
/**
* @return array
*/
public static function get_data_to_localize() {
$operators = static::get_operators();
return [
'label' => static::get_label(),
'operators' => $operators,
'extra_operators' => static::get_extra_operators(),
'is_hidden' => static::is_hidden(),
'control_type' => static::get_control_type(),
'display_size' => static::get_display_size(),
'validation_data' => static::get_validation_data(),
'is_single_operator' => count( $operators ) === 1,
'has_options_to_preload' => static::has_options_to_preload(),
];
}
/**
* @return array
*/
public static function get_validation_data() {
return [
'min' => 0,
'max' => PHP_INT_MAX,
];
}
public static function has_options_to_preload() {
return false;
}
}

View File

@@ -0,0 +1,130 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay;
use TCB\ConditionalDisplay\Traits\Item;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
abstract class Entity {
use Item;
protected $data;
protected static $fields = [];
/**
* @return array
*/
public static function get_fields() {
$entity_key = static::get_key();
if ( empty( static::$fields[ $entity_key ] ) ) {
foreach ( Field::get( true ) as $field ) {
if ( $field::get_entity() === $entity_key ) {
static::$fields[ $entity_key ][] = $field::get_key();
}
}
}
return static::$fields[ $entity_key ];
}
/**
* @return string
*/
abstract public static function get_key();
/**
* Create an entity from the data provided
*
* @param array $extra_data
*/
public function __construct( $extra_data = [] ) {
$this->data = $this->create_object( $extra_data );
}
/**
* @param $param
*
* @return mixed
*/
abstract public function create_object( $param );
/**
* @param $field_key
*
* @return string
*/
public function get_field_value( $field_key ) {
$value = '';
$field_object = $this->get_field( $field_key );
if ( ! empty( $field_object ) ) {
$value = $field_object->get_value( $this->data );
}
return $value;
}
/**
* @param $field_key
*
* @return Field
*/
public function get_field( $field_key ) {
$field_object = null;
if ( static::validate_field( $field_key ) ) {
$field_object = Field::get_instance( $field_key );
} else {
trigger_error( 'Field ' . $field_key . ' must be an allowed field of ' . static::class );
}
return $field_object;
}
/**
* @param $field
*
* @return bool
*/
public static function validate_field( $field ) {
return in_array( $field, static::get_fields() );
}
/**
* @return array
*/
public static function get_data_to_localize() {
$data = [];
$entities = static::get( true );
foreach ( $entities as $key => $class ) {
$data[ $key ] = [
'label' => $class::get_label(),
];
}
return $data;
}
/**
* Determines the display order in the modal entity select
*
* @return int
*/
public static function get_display_order() {
/* 'User' is 0, other entities are multipliers of 5, everything else that doesn't overwrite this is 100 */
return 100;
}
}

View File

@@ -0,0 +1,111 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay;
use TCB\ConditionalDisplay\Traits\Item;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
abstract class Field {
use Item;
/**
* @return string
*/
abstract public static function get_entity();
abstract public function get_value( $object );
/**
* @return string
*/
abstract public static function get_key();
/**
* @return string
*/
abstract public static function get_label();
/**
* @return array
*/
abstract public static function get_conditions();
/**
* @param array $selected_values
* @param string $search
*
* @return array
*/
public static function get_options( $selected_values = [], $search = '' ) {
return [];
}
public static function filter_options( $id, $label, $selected_values = [], $searched_keyword = '' ) {
return
( empty( $selected_values ) || in_array( $id, $selected_values ) ) && /* if there are pre-selected values, only return the options for those */
( empty( $searched_keyword ) || stripos( $label, $searched_keyword ) !== false ); /* if there is a searched keyword, only return the options that match it */
}
/**
* @return array
*/
public static function get_data_to_localize() {
return [
'label' => static::get_label(),
'is_boolean' => static::is_boolean(),
'autocomplete_placeholder' => static::get_autocomplete_placeholder(), //todo will delete after removing the implementation from the other plugins
'placeholder_text' => static::get_placeholder_text(),
'validation_data' => static::get_validation_data(),
];
}
/**
* Boolean fields can return the condition value directly ( is_logged_in, is_logged_out )
*
* @return bool
*/
public static function is_boolean() {
return false;
}
/**
* @return string
*/
public static function get_autocomplete_placeholder() {
return static::get_placeholder_text();
}
/**
* @return string
*/
public static function get_placeholder_text() {
return '';
}
/**
* @return array
*/
public static function get_validation_data() {
return [
'min' => 0,
'max' => 1000,
];
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 100;
}
}

View File

@@ -0,0 +1,274 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay;
use TCB\ConditionalDisplay\PostTypes\Conditional_Display_Group;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Hooks {
public static function add_filters() {
add_filter( 'tcb_content_allowed_shortcodes', [ __CLASS__, 'allowed_shortcodes' ] );
add_filter( 'tcb_lazy_load_data', [ __CLASS__, 'load_display_groups' ], 10, 3 );
add_filter( 'tve_frontend_options_data', [ __CLASS__, 'tve_frontend_data' ] );
add_filter( 'tve_dash_frontend_ajax_response', [ __CLASS__, 'lazy_load_response' ] );
add_filter( 'tve_update_symbol_html', [ __CLASS__, 'tve_update_symbol_html' ], 10, 2 );
}
public static function add_actions() {
add_action( 'tcb_ajax_save_post', [ __CLASS__, 'save_post' ] );
add_action( 'tcb_ajax_before', [ __CLASS__, 'save_post' ] );
add_action( 'rest_api_init', [ __CLASS__, 'register_routes' ] );
add_action( 'wp_ajax_nopriv_tcb_conditional_display', [ __CLASS__, 'lazy_load_display_groups' ] );
add_action( 'wp_ajax_tcb_conditional_display', [ __CLASS__, 'lazy_load_display_groups' ] );
add_action( 'wp_ajax_dismiss_conditional_tooltip', [ __CLASS__, 'dismiss_conditional_tooltip' ] );
add_action( 'wp_print_footer_scripts', [ __CLASS__, 'wp_print_footer_scripts' ] );
add_action( 'admin_bar_menu', [ __CLASS__, 'admin_bar_menu' ], 1000 );
add_action( 'after_thrive_clone_item', [ __CLASS__, 'after_thrive_clone_item' ], 10, 3 );
}
/**
* On request for lazy loading other products content we add the conditional display data
*
* @param $response
*
* @return mixed
*/
public static function lazy_load_response( $response ) {
if ( Shortcode::is_preview() && isset( $GLOBALS['conditional_display_preview'] ) ) {
$response['lazy_load_conditional_preview'] = array_values( $GLOBALS['conditional_display_preview'] );
}
return $response;
}
/**
* @param $allowed_shortcodes
*
* @return mixed
*/
public static function allowed_shortcodes( $allowed_shortcodes ) {
if ( is_editor_page_raw( true ) ) {
$allowed_shortcodes[] = Shortcode::NAME;
}
return $allowed_shortcodes;
}
/**
* Lazy load localize display groups inside the editor
*
* @param array $data
*
* @return mixed
*/
public static function load_display_groups( $data ) {
if ( isset( $_POST['conditional-display-groups'] ) && is_array( $_POST['conditional-display-groups'] ) ) {
foreach ( $_POST['conditional-display-groups'] as $display_group_key ) {
$display_group = Conditional_Display_Group::get_instance( $display_group_key );
if ( $display_group !== null ) {
$display_group->localize( false, true );
}
}
$data['conditional-display-groups'] = array_values( $GLOBALS['conditional_display_preview'] );
}
return $data;
}
/**
* Load displays to be displayed in frontend
*
* @return void
*/
public static function lazy_load_display_groups() {
$groups = [];
$external_resources = [
'js' => [],
'css' => [],
];
if ( isset( $_GET['query_vars'] ) ) {
tve_set_query_vars_data( $_GET['query_vars'] );
}
if ( is_array( $_GET['groups'] ) ) {
foreach ( $_GET['groups'] as $display_group_key ) {
$display_group = Conditional_Display_Group::get_instance( $display_group_key );
if ( $display_group !== null ) {
foreach ( $display_group->get_displays() as $display ) {
if ( Shortcode::verify_conditions( $display ) ) {
if ( empty( $display['hide'] ) ) {
$content = Shortcode::parse_content( $display['html'], false );
if ( ! empty( $content ) ) {
$groups[ $display_group_key ] = [
'content' => $content,
];
$external_resources = Conditional_Display_Group::get_external_resources_for_content( $external_resources, $content );
}
}
break;
}
}
}
}
}
ob_start();
/* retrieve animations and actions events and maybe lightboxes if needed */
tve_print_footer_events();
$footer_scripts = ob_get_clean();
wp_send_json( [
'groups' => $groups,
'footer_scripts' => $footer_scripts,
'external_resources' => $external_resources,
]
);
}
public static function dismiss_conditional_tooltip() {
$dismissed_tooltips = (array) get_user_meta( wp_get_current_user()->ID, 'tcb_dismissed_tooltips' );
$dismissed_tooltips[] = 'conditional-display-tooltip';
update_user_meta( wp_get_current_user()->ID, 'tcb_dismissed_tooltips', $dismissed_tooltips );
}
/**
* Save conditional displays
*/
public static function save_post() {
if ( isset( $_REQUEST['conditional-displays'] ) ) {
Conditional_Display_Group::save_groups( $_REQUEST['conditional-displays'] );
}
}
public static function register_routes() {
RestApi\General_Data::register_routes();
RestApi\Global_Sets::register_routes();
}
public static function wp_print_footer_scripts() {
/**
* Make sure that is printed only on initial load not while plugins do lazy load
*/
if ( Shortcode::is_preview() && ! wp_doing_ajax() ) {
if ( empty( $GLOBALS['conditional_display_preview'] ) ) {
$GLOBALS['conditional_display_preview'] = [];
}
echo \TCB_Utils::wrap_content( "var tcb_condition_sets=JSON.parse('" . addslashes( json_encode( array_values( $GLOBALS['conditional_display_preview'] ) ) ) . "');", 'script', '', '', [ 'type' => 'text/javascript' ] ); // phpcs:ignore
}
}
/**
* Add some data to the frontend localized object
*
* @param $data
*
* @return mixed
*/
public static function tve_frontend_data( $data ) {
$dismissed_tooltips = (array) get_user_meta( wp_get_current_user()->ID, 'tcb_dismissed_tooltips', true );
$data['conditional_display'] = [
'is_tooltip_dismissed' => in_array( 'conditional-display-tooltip', $dismissed_tooltips, true ),
];
return $data;
}
/**
* @param \WP_Admin_Bar $wp_admin_bar
*/
public static function admin_bar_menu( $wp_admin_bar ) {
if ( ! Shortcode::is_preview() ) {
return;
}
wp_enqueue_style( 'tve-logged-in-style', tve_editor_css( 'logged-in.css' ), false, TVE_VERSION );
$wp_admin_bar->add_node( [
'id' => 'tve-preview-conditions',
'title' => '<span class="tve-preview-conditions-icon admin-bar"></span>',
'parent' => 'top-secondary',
'meta' => [ 'class' => 'tcb-preview-hidden' ],
] );
$wp_admin_bar->add_node( [
'id' => 'tve-conditions-title',
'title' => '<span class="tve-preview-conditions-icon"></span>' .
'<span class="tve-preview-conditions-title">Preview conditions</span>' .
'<div class="tve-preview-conditions-info">
<div class="tve-preview-conditions-tooltip">
This page contains conditional displays on some content . You can preview how the page looks for users that match different conditions by selecting them below.
<a class="tve-preview-conditions-tooltip-link" target="_blank" href="https://help.thrivethemes.com/en/articles/5814058-how-to-use-the-conditional-display-option">Learn more </a>
</div>
</div> ' .
'<button class="tve-preview-conditions-close"></button> ',
'parent' => 'tve-preview-conditions',
] );
$wp_admin_bar->add_node( [
'id' => 'tve-conditions-tooltip',
'title' => '<div class="tve-preview-conditions-tooltip-text">This page contains conditional displays.</div><div class="tve-preview-conditions-tooltip-text">Click here to change your preview settings.</div> ',
'parent' => 'tve-preview-conditions',
] );
}
/**
* Replace conditional display groups inside the cloned item
*
* @param int $new_post_id
* @param int $original_post_id
* @param array $css_id_map
*
* @return void
*/
public static function after_thrive_clone_item( $new_post_id, $original_post_id, $css_id_map ) {
$content = tve_get_post_meta( $new_post_id, 'tve_updated_post' );
$cloned_result = Conditional_Display_Group::clone_conditional_groups_in_content( $content, $css_id_map );
$content = $cloned_result['content'];
tve_update_post_meta( $new_post_id, 'tve_updated_post', $content );
}
/**
* Conditionals ids for duplicated symbols needs to be regenerated
*
* @param $meta_key
* @param $meta_value
*/
public static function tve_update_symbol_html( $meta_key, $meta_value ) {
/* For the Conditional Display we need to regenerate the ids of the added conditions */
if ( $meta_key === 'tve_updated_post' ) {
$cloned_result = Conditional_Display_Group::clone_conditional_groups_in_content( $meta_value );
$meta_value = $cloned_result['content'];
}
return $meta_value;
}
}

View File

@@ -0,0 +1,118 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay;
use TCB\ConditionalDisplay\PostTypes\Conditional_Display_Group;
use TCB\ConditionalDisplay\PostTypes\Global_Conditional_Set;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Main {
const ABSTRACT_PATH = __DIR__ . '/abstract';
const TRAIT_PATH = __DIR__ . '/traits';
public static $entities = [];
public static function init() {
static::includes();
Conditional_Display_Group::register();
Global_Conditional_Set::register();
Hooks::add_filters();
Hooks::add_actions();
Shortcode::add();
do_action( 'tcb_conditional_display_register' );
}
public static function includes() {
require_once __DIR__ . '/post-types/class-conditional-display-group.php';
require_once __DIR__ . '/post-types/class-global-conditional-set.php';
require_once __DIR__ . '/class-shortcode.php';
require_once __DIR__ . '/class-hooks.php';
require_once __DIR__ . '/rest-api/class-general-data.php';
require_once __DIR__ . '/rest-api/class-global-sets.php';
require_once static::TRAIT_PATH . '/class-item.php';
require_once static::ABSTRACT_PATH . '/class-entity.php';
require_once static::ABSTRACT_PATH . '/class-field.php';
require_once static::ABSTRACT_PATH . '/class-condition.php';
require_once __DIR__ . '/tve-conditional-display-global.php';
static::load_files_from_path( 'entities', Entity::class );
foreach ( [ 'user', 'time', 'request', 'referral' ] as $field_group ) {
static::load_files_from_path( 'fields/' . $field_group, Field::class );
}
static::load_files_from_path( 'conditions', Condition::class );
}
/**
* @param $path
* @param $type_class
*/
public static function load_files_from_path( $path, $type_class ) {
$full_path = __DIR__ . '/' . $path;
/* convert path to namespace: '/fields/user' -> '\\Fields\\User' */
$namespace = implode( '/', array_map( 'ucfirst', explode( '/', $path ) ) );
$namespace = str_replace( '/', '\\', $namespace );
static::include_classes_from_folder_recursive( $full_path, $namespace, $type_class );
}
/**
* @param $path
* @param $namespace
* @param $type_class
*/
public static function include_classes_from_folder_recursive( $path, $namespace, $type_class ) {
$items = array_diff( scandir( $path ), [ '.', '..' ] );
foreach ( $items as $item ) {
$item_path = $path . '/' . $item;
/* if the item is a folder, enter it and do recursion */
if ( is_dir( $item_path ) ) {
static::include_classes_from_folder_recursive( $item_path, $namespace, $type_class );
}
/* if the item is a file, include it */
if ( is_file( $item_path ) && substr( $item_path, - 3 ) === 'php' ) {
require_once $item_path;
/* for each file, dynamically call the init function of the class */
if ( preg_match( '/class-(.*).php/m', $item, $m ) && ! empty( $m[1] ) ) {
$class_name = \TCB_ELEMENTS::capitalize_class_name( $m[1] );
$class = __NAMESPACE__ . '\\' . $namespace . '\\' . $class_name;
$type_class::register( $class );
}
}
}
}
/**
* Get all the data that we want to localize for Conditional Display - the rest is fetched on demand through REST
*
* @return array
*/
public static function get_localized_data() {
return [
'entities' => Entity::get_data_to_localize(),
];
}
}

View File

@@ -0,0 +1,228 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay;
use TCB\ConditionalDisplay\PostTypes\Conditional_Display_Group;
use TCB\ConditionalDisplay\PostTypes\Global_Conditional_Set;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Shortcode {
const NAME = 'tve_conditional_display';
public static function add() {
add_shortcode( static::NAME, [ __CLASS__, 'render' ] );
}
/**
* @param $attr
*
* @return string
*/
public static function render( $attr ) {
$group_key = empty( $attr['group'] ) ? null : $attr['group'];
$is_editor_page = is_editor_page_raw() || isset( $_REQUEST['tar_editor_page'] );
/* check for admin just so we won't show displays to unwanted users */
$during_optimization = \TCB\Lightspeed\Main::is_optimizing() && current_user_can( 'manage_options' );
$display_group = Conditional_Display_Group::get_instance( $group_key );
$content = '';
$all_displays = '';
if ( $display_group !== null ) {
/* We should not localize the groups during optimization or during post list / symbol render */
if ( ! $during_optimization && static::should_localize() ) {
/* Basically localize the data related to conditional display */
$display_group->localize( static::is_preview(), $is_editor_page );
}
if ( ! $during_optimization && ( ! ( $is_editor_page || wp_doing_ajax() ) && $display_group->has_lazy_load() ) ) {
$content = $display_group->lazy_load_placeholder();
} else {
foreach ( $display_group->get_displays( true, $is_editor_page ) as $display ) {
if ( $during_optimization || static::verify_conditions( $display ) ) {
$content = empty( $display['hide'] ) || $is_editor_page ? $display['html'] : '';
/* If we are in preview, and we have a hide content we add a placeholder */
if ( empty( $content ) && static::is_preview() ) {
$content = \TCB_Utils::wrap_content( '', 'span', '', '', [ 'data-display-group' => $group_key ] );
}
$content = static::parse_content( $content, $is_editor_page );
if ( $during_optimization ) {
$all_displays .= $content;
} else {
break;
}
}
}
}
}
return $during_optimization ? $all_displays : $content;
}
/**
* There are cases when we do not want to localize the displays, such as post list render or symbol render during lazy load.
* @return bool
*/
public static function should_localize() {
$should_localize = \TCB_Post_List::is_outside_post_list_render();
if ( wp_doing_ajax() ) {
$should_localize = $should_localize && \TCB_Symbol_Template::is_outside_symbol_render();
}
return $should_localize;
}
/**
* Parse shortcode content - do shortcode, read events, and so on
*
* @param $content
* @param $is_editor_page
*
* @return string
*/
public static function parse_content( $content, $is_editor_page = true ) {
$content = tve_do_wp_shortcodes( $content, $is_editor_page );
$content = tve_thrive_shortcodes( $content, $is_editor_page );
$content = do_shortcode( $content );
if ( ! $is_editor_page ) {
$content = tve_restore_script_tags( $content );
tve_parse_events( $content );
$global_styles = tve_get_shared_styles( $content, '', false, false );
$content = $global_styles . $content;
}
return $content;
}
/**
* Verify conditions for a specific display
*
* @param $display
*
* @return bool
*/
public static function verify_conditions( $display ) {
$is_verified = $display['key'] === 'default';
if ( ! $is_verified && ! empty( $display['conditions'] ) ) {
$conditions = static::parse_condition_config( $display['conditions'] );
/**
* condition = set1 || set2 || set3
* set1 = rule1 && rule2 && rule3
*/
foreach ( $conditions as $set ) {
if ( static::verify_set( $set ) ) {
$is_verified = true;
/* if we have a verified set, we can stop checking the other sets */
break;
}
}
}
return $is_verified;
}
/**
* replace single quotes with double quotes and json_decode
*
* @param $conditions
*
* @return mixed
*/
public static function parse_condition_config( $conditions ) {
$conditions = str_replace( "'", '"', html_entity_decode( $conditions, ENT_QUOTES ) );
return json_decode( $conditions, true );
}
public static function is_preview() {
$is_editor = is_editor_page_raw();
$is_ajax = wp_doing_ajax();
$ajax_action = empty( $GLOBALS['tve_dash_frontend_ajax_load'] ) ? false : $GLOBALS['tve_dash_frontend_ajax_load'];
return current_user_can( 'edit_posts' ) && ! $is_editor && ( ! $is_ajax || ( $is_ajax && $ajax_action ) );
}
/**
* Verify rules from a set
*
* @param $set
*
* @return bool
*/
public static function verify_set( $set ) {
if ( empty( $set['ID'] ) ) {
$rules = $set['rules'];
} else {
$global_set = Global_Conditional_Set::get_instance( $set['ID'] );
$rules = $global_set === null || empty( $global_set->get_post() ) ? [] : $global_set->get_rules();
}
foreach ( $rules as $rule ) {
$is_rule_verified = static::verify_rule( $rule );
$is_set_verified = isset( $is_set_verified ) ? $is_set_verified && $is_rule_verified : $is_rule_verified;
}
return isset( $is_set_verified ) ? $is_set_verified : false;
}
/**
* Check if the rule is valid or not
*
* @param $config
*
* @return boolean
*/
public static function verify_rule( $config ) {
$is_verified = false;
if ( ! empty( $config['entity'] ) && ! empty( $config['field'] ) ) {
$entity = Entity::get_instance( $config['entity'] );
if ( ! empty( $entity ) ) {
$field_value = $entity->get_field_value( $config['field'] );
if ( empty( $config['condition']['key'] ) ) {
$field = Field::get_instance( $config['field'] );
if ( $field::is_boolean() ) {
$is_verified = $field_value;
}
} else {
$condition = Condition::get_instance( $config['condition']['key'], $config['condition'] );
$is_verified = $condition->apply( [ 'field_value' => $field_value ] );
}
}
}
return $is_verified;
}
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
if ( ! class_exists( 'Autocomplete', false ) ) {
require_once __DIR__ . '/class-autocomplete.php';
}
/**
* This is used by Product_Access in Apprentice
* Because the field name there is called 'Has access to Apprentice Product(s)', it doesn't make sense to have the condition visible, so we hide it.
*/
class Autocomplete_Hidden extends Autocomplete {
/**
* @return string
*/
public static function get_key() {
return 'autocomplete_hidden';
}
public function apply( $data ) {
$field_values = $data['field_value'];
$haystack = $this->get_value();
if ( is_array( $field_values ) ) {
$result = ! empty( array_intersect( $field_values, $haystack ) );
} else {
$result = in_array( $field_values, $haystack, true );
}
return $result;
}
public static function get_operators() {
return [
'autocomplete' => [
'label' => 'is',
],
];
}
public static function is_hidden() {
return true;
}
public static function get_control_type() {
return Autocomplete::get_key(); /* use the 'autocomplete' control because the functionality is the same */
}
}

View File

@@ -0,0 +1,65 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Autocomplete extends Condition {
/**
* @return string
*/
public static function get_key() {
return 'autocomplete';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'Autocomplete', 'thrive-cb' );
}
public static function get_display_size() {
return 'full';
}
public function apply( $data ) {
$result = false;
$compared_values = $this->get_value();
if ( ! empty( $compared_values ) ) {
$field_values = $data['field_value'];
if ( is_array( $field_values ) ) {
$result = ! empty( array_intersect( $field_values, $compared_values ) );
} else {
$result = in_array( $field_values, $compared_values );
}
}
return $this->get_operator() === 'autocomplete' ? $result : ! $result;
}
public static function get_operators() {
return [
'autocomplete' => [
'label' => 'is',
],
'autocomplete_exclude' => [
'label' => 'is not',
],
];
}
public static function get_control_type() {
return static::get_key();
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Checkbox extends Condition {
/**
* @return string
*/
public static function get_key() {
return 'checkbox';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'Checkbox', 'thrive-cb' );
}
public function apply( $data ) {
$field_values = $data['field_value'];
$haystack = $this->get_value();
if ( is_array( $field_values ) ) {
$result = ! empty( array_intersect( $field_values, $haystack ) );
} else {
$result = in_array( $field_values, $haystack );
}
return $this->get_operator() === 'contains' ? $result : ! $result;
}
public static function get_operators() {
return [
'contains' => [
'label' => esc_html__( 'is', 'thrive-cb' ),
],
'not_contains' => [
'label' => esc_html__( 'is not', 'thrive-cb' ),
],
];
}
public static function get_control_type() {
return static::get_key();
}
public static function get_display_size() {
return 'full';
}
public static function has_options_to_preload() {
return true;
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Date_And_Time_Picker extends Condition {
/**
* @return string
*/
public static function get_key() {
return 'date_and_time';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'Date and time comparison', 'thrive-cb' );
}
public function apply( $data ) {
$formatted_field_value = strtotime( $data['field_value'] );
$formatted_compared_value = strtotime( $this->get_value() );
switch ( $this->get_operator() ) {
case 'before':
$result = $formatted_field_value < $formatted_compared_value;
break;
case 'after':
$result = $formatted_field_value > $formatted_compared_value;
break;
case 'equals':
$result = strtotime( date( 'Y/m/d', $formatted_field_value ) ) === strtotime( date( 'Y/m/d', $formatted_compared_value ) );
break;
default:
$result = false;
}
return $result;
}
public static function get_operators() {
return [
'equals' => [
'label' => 'equals',
],
'before' => [
'label' => 'before',
],
'after' => [
'label' => 'after',
],
];
}
public static function get_control_type() {
return 'date-and-time';
}
public static function get_display_size() {
return 'medium';
}
/**
* @return array
*/
public static function get_validation_data() {
return [
'min_minutes' => 0,
'max_minutes' => 59,
'min_hours' => 0,
'max_hours' => 23,
];
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Date_And_Time_With_Intervals extends Date_And_Time_Picker {
/**
* @return string
*/
public static function get_key() {
return 'date_and_time_with_intervals';
}
public function apply( $data ) {
$result = false;
if ( ! empty( $data['field_value'] ) ) {
$now = current_time( 'timestamp' );
switch ( $this->get_operator() ) {
case 'more':
$result = $now > strtotime( $data['field_value'] ) + $this->get_added_time();
break;
case 'less':
$result = strtotime( $data['field_value'] ) > $now - $this->get_added_time();
break;
default:
$result = parent::apply( $data );
}
}
return $result;
}
public static function get_operators() {
return array_merge(
[
'more' => [
'label' => 'more than',
],
'less' => [
'label' => 'less than',
],
],
parent::get_operators()
);
}
private function get_added_time() {
$um = $this->get_um();
$value = (int) $this->get_value();
switch ( $um ) {
case 'days':
$result = $value * DAY_IN_SECONDS;
break;
case 'hours':
$result = $value * HOUR_IN_SECONDS;
break;
case 'minutes':
$result = $value * MINUTE_IN_SECONDS;
break;
case 'months':
$result = $value * MONTH_IN_SECONDS;
break;
case 'years':
$result = $value * YEAR_IN_SECONDS;
break;
default:
$result = 0;
}
return $result;
}
/**
* @return array
*/
public static function get_validation_data() {
return array_merge( parent::get_validation_data(), [
'min_interval' => 1,
'max_interval' => 1000,
] );
}
}

View File

@@ -0,0 +1,79 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Date extends Date_And_Time_Picker {
/**
* @return string
*/
public static function get_key() {
return 'date';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'Date comparison', 'thrive-cb' );
}
public function apply( $data ) {
$result = false;
$field_value = $data['field_value'];
if ( ! empty( $field_value ) ) {
$formatted_field_value = strtotime( $data['field_value'] );
$formatted_compared_value = strtotime( $this->get_value() );
switch ( $this->get_operator() ) {
case 'equals':
$result = strtotime( date( 'Y/m/d', $formatted_field_value ) )
===
strtotime( date( 'Y/m/d', $formatted_compared_value ) );
break;
case 'between':
/* reduce the format to date-only */
$formatted_start_interval = strtotime( date( 'Y/m/d', $formatted_compared_value ) );
$formatted_end_interval = strtotime( date( 'Y/m/d', strtotime( $this->get_extra() ) ) );
$formatted_field_value = strtotime( date( 'Y/m/d', $formatted_field_value ) );
$result = $formatted_field_value >= $formatted_start_interval &&
$formatted_field_value <= $formatted_end_interval;
break;
default:
$result = parent::apply( $data );
}
}
return $result;
}
public static function get_operators() {
return array_merge( parent::get_operators(), [
'between' => [
'label' => 'between',
],
] );
}
public static function get_control_type() {
return static::get_key();
}
/**
* @return array
*/
public static function get_validation_data() {
return [];
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Dropdown extends Condition {
/**
* @return string
*/
public static function get_key() {
return 'dropdown';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'Dropdown', 'thrive-cb' );
}
public function apply( $data ) {
$field_value = $data['field_value'];
$compared_value = $this->get_value();
if ( is_numeric( $field_value ) ) {
$compared_value = (int) $compared_value;
}
return $field_value === $compared_value;
}
public static function get_operators() {
return [
'equals' => [
'label' => '=',
],
];
}
public static function get_control_type() {
return static::get_key();
}
public static function is_hidden() {
return true;
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Number_Comparison extends Condition {
/**
* @return string
*/
public static function get_key() {
return 'number_comparison';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'Number comparison', 'thrive-cb' );
}
public function apply( $data ) {
$field_number = (float) $data['field_value'];
$compared_number = (float) $this->get_value();
switch ( $this->get_operator() ) {
case 'less_than':
$result = $field_number < $compared_number;
break;
case 'more_than':
$result = $field_number > $compared_number;
break;
case 'equal':
$result = $field_number == $compared_number;
break;
default:
$result = false;
}
return $result;
}
public static function get_operators() {
return [
'less_than' => [
'label' => 'is less than',
],
'more_than' => [
'label' => 'is more than',
],
'equal' => [
'label' => 'is equal to',
],
];
}
public static function get_control_type() {
return 'input-number';
}
public static function get_display_size() {
return 'medium';
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Number_Equals extends Condition {
/**
* @return string
*/
public static function get_key() {
return 'number_equals';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'Number equals', 'thrive-cb' );
}
public function apply( $data ) {
$a = (int) $data['field_value'];
$b = (int) $this->get_value();
return $a === $b;
}
public static function get_operators() {
return [
'equals' => [
'label' => '=',
],
];
}
public static function get_control_type() {
return 'input-number';
}
public static function is_hidden() {
return true;
}
}

View File

@@ -0,0 +1,102 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class String_Comparison extends Condition {
/**
* @return string
*/
public static function get_key() {
return 'string_comparison';
}
public static function get_control_type() {
return 'string-comparison';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'String comparison', 'thrive-cb' );
}
public function apply( $data ) {
$string_data = $this->get_value();
$string_name = $string_data['string_name'];
$string_operator = $string_data['string_operator'];
$string_value = $string_data['string_value'];
$field_string = isset( $data['field_value'] ) && isset( $data['field_value'][ $string_name ] ) ? sanitize_text_field( urldecode( $data['field_value'][ $string_name ] ) ) : '';
switch ( $string_operator ) {
case 'equals':
$result = $field_string === $string_value;
break;
case 'contains':
$result = strpos( $field_string, $string_value ) !== false;
break;
case 'not_contains':
$result = strpos( $field_string, $string_value ) === false;
break;
case 'exists':
$result = ! empty( $field_string );
break;
default:
$result = false;
}
return $result;
}
public static function get_operators() {
/* The operators are added dynamically, but we keep an array with one element so this will be considered a singular condition */
return [
[
'value' => 'equals',
'label' => 'Equals',
],
];
}
public static function get_extra_operators() {
return [
[
'value' => 'equals',
'label' => __( 'Equals' ),
],
[
'value' => 'contains',
'label' => __( 'Contains' ),
],
[
'value' => 'not_contains',
'label' => __( 'Does not Contain' ),
],
[
'value' => 'exists',
'label' => __( 'Exists' ),
],
];
}
public static function get_display_size() {
return 'medium';
}
public static function is_hidden() {
return true;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class String_Contains extends Condition {
/**
* @return string
*/
public static function get_key() {
return 'string_contains';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'String contains', 'thrive-cb' );
}
public function apply( $data ) {
$haystack = $data['field_value'];
$needle = $this->get_value();
return strpos( $haystack, $needle ) !== false;
}
public static function get_operators() {
return [
'contains' => [
'label' => '=',
],
];
}
public static function is_hidden() {
return true;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class String_Equals extends Condition {
/**
* @return string
*/
public static function get_key() {
return 'string_equals';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'String equals', 'thrive-cb' );
}
public function apply( $data ) {
$a = $data['field_value'];
$b = $this->get_value();
return strcmp( $a, $b ) === 0;
}
public static function get_operators() {
return [
'equals' => [
'label' => '=',
],
];
}
public static function is_hidden() {
return true;
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Time extends Date_And_Time_Picker {
/**
* @return string
*/
public static function get_key() {
return 'time';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'Time comparison', 'thrive-cb' );
}
public function apply( $data ) {
$compared_value = $this->get_value();
$formatted_field_value = strtotime( $data['field_value'] );
$formatted_compared_value = strtotime( $compared_value['hours'] . ':' . $compared_value['minutes'] );
switch ( $this->get_operator() ) {
case 'before':
$result = $formatted_field_value <= $formatted_compared_value;
break;
case 'after':
$result = $formatted_field_value >= $formatted_compared_value;
break;
case 'between':
$formatted_start_interval = $formatted_compared_value;
$formatted_end_interval = strtotime( $this->get_extra()['hours'] . ':' . $this->get_extra()['minutes'] );
$result = $formatted_field_value >= $formatted_start_interval &&
$formatted_field_value <= $formatted_end_interval;
break;
default:
$result = false;
}
return $result;
}
public static function get_control_type() {
return static::get_key();
}
public static function get_operators() {
return [
'before' => [
'label' => 'before',
],
'after' => [
'label' => 'after',
],
'between' => [
'label' => 'between',
],
];
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Conditions;
use TCB\ConditionalDisplay\Condition;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class URL_Comparison extends Condition {
/**
* @return string
*/
public static function get_key() {
return 'url_comparison';
}
/**
* @return string
*/
public static function get_label() {
return esc_html__( 'URL comparison', 'thrive-cb' );
}
public function apply( $data ) {
$field_value = $data['field_value'];
$compared_value = $this->get_value();
if ( strpos( $compared_value, '*' ) === false ) {
$result = strcmp( $field_value, $compared_value ) === 0;
} else {
/* if a wildcard '*' is found, convert it into the regex format then run a preg_match */
$compared_value = str_replace( '\*', '.*', preg_quote( $compared_value, '/' ) );
preg_match_all( '/' . $compared_value . '/m', $field_value, $matches, PREG_SET_ORDER );
$result = ! empty( $matches );
}
return $result;
}
public static function get_operators() {
return [
'equals' => [
'label' => '=',
],
];
}
public static function is_hidden() {
return true;
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Entities;
use TCB\ConditionalDisplay\Entity;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Referral extends Entity {
/**
* @return string
*/
public static function get_key() {
return 'referral_data';
}
public static function get_label() {
return esc_html__( 'Referral', 'thrive-cb' );
}
/**
* The referrer is normally taken from $_SERVER['HTTP_REFERER'].
* When it's not available ( this happens during ajax requests ), it is sent as a parameter from there.
*
* @param $param
*
* @return array|mixed
*/
public function create_object( $param ) {
$referrer_data = [];
if ( wp_doing_ajax() && ! empty( $_REQUEST['referrer'] ) ) {
$url = $_REQUEST['referrer'];
} else if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
$url = $_SERVER['HTTP_REFERER'];
}
if ( ! empty( $url ) ) {
$referrer_data['url'] = $url;
/* if the URL is from this site, store the post data */
if ( strpos( $url, home_url() ) !== false ) {
$referrer_data['post'] = get_post( url_to_postid( $url ) );
}
}
return $referrer_data;
}
/**
* Determines the display order in the modal entity select
*
* @return int
*/
public static function get_display_order() {
return 25;
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Entities;
use TCB\ConditionalDisplay\Entity;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Request extends Entity {
/**
* @return string
*/
public static function get_key() {
return 'request_data';
}
public static function get_label() {
return esc_html__( 'Request data', 'thrive-cb' );
}
public function create_object( $param ) {
return '';
}
/**
* Determines the display order in the modal entity select
*
* @return int
*/
public static function get_display_order() {
return 20;
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Entities;
use TCB\ConditionalDisplay\Entity;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Time extends Entity {
/**
* @return string
*/
public static function get_key() {
return 'time_data';
}
public static function get_label() {
return esc_html__( 'Time and date', 'thrive-cb' );
}
public function create_object( $param ) {
return '';
}
/**
* Determines the display order in the modal entity select
*
* @return int
*/
public static function get_display_order() {
return 15;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Entities;
use TCB\ConditionalDisplay\Entity;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class User extends Entity {
/**
* @return string
*/
public static function get_key() {
return 'user_data';
}
public static function get_label() {
return esc_html__( 'User', 'thrive-cb' );
}
public function create_object( $param ) {
$user_id = get_current_user_id();
return get_userdata( $user_id );
}
/**
* Determines the display order in the modal entity select
*
* @return int
*/
public static function get_display_order() {
return 0;
}
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Referral;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Category extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'referral_data';
}
/**
* @return string
*/
public static function get_key() {
return 'referral_category_id';
}
public static function get_label() {
return esc_html__( 'Category', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'autocomplete' ];
}
public function get_value( $referral_data ) {
$categories = [];
if ( ! empty( $referral_data['post'] ) ) {
foreach ( get_the_category( $referral_data['post'] ) as $category ) {
$categories[] = $category->term_id;
}
}
return $categories;
}
public static function get_options( $selected_values = [], $searched_keyword = '' ) {
$categories = [];
foreach ( get_categories() as $category ) {
if ( static::filter_options( $category->term_id, $category->name, $selected_values, $searched_keyword ) ) {
$categories[] = [
'value' => (string) $category->term_id,
'label' => $category->name,
];
}
}
return $categories;
}
/**
* @return string
*/
public static function get_placeholder_text() {
return esc_html__( 'Search categories', 'thrive-cb' );
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 20;
}
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Referral;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Domain extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'referral_data';
}
/**
* @return string
*/
public static function get_key() {
return 'referral_domain';
}
public static function get_label() {
return esc_html__( 'Domain', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'string_contains' ];
}
public function get_value( $referral_data ) {
return empty( $referral_data['url'] ) ? '' : parse_url( $referral_data['url'], PHP_URL_HOST );
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 5;
}
/**
* @return string
*/
public static function get_placeholder_text() {
return esc_html__( 'Enter a domain URL', 'thrive-cb' );
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Referral;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
if ( ! class_exists( 'Referral_Post', false ) ) {
require_once __DIR__ . '/class-post.php';
}
class Page extends Post {
/**
* @return string
*/
public static function get_key() {
return 'referral_page_id';
}
public static function get_label() {
return esc_html__( 'Page', 'thrive-cb' );
}
public static function get_post_type() {
return 'page';
}
/**
* @return string
*/
public static function get_placeholder_text() {
return esc_html__( 'Search pages', 'thrive-cb' );
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 15;
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Referral;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Post extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'referral_data';
}
/**
* @return string
*/
public static function get_key() {
return 'referral_post_id';
}
public static function get_label() {
return esc_html__( 'Post', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'autocomplete' ];
}
public function get_value( $referral_data ) {
return empty( $referral_data['post'] ) ? '' : $referral_data['post']->ID;
}
public static function get_options( $selected_values = [], $searched_keyword = '' ) {
$query = [
'posts_per_page' => empty( $selected_values ) ? min( 100, max( 20, strlen( $searched_keyword ) * 3 ) ) : - 1,
'post_type' => static::get_post_type(),
'orderby' => 'title',
'order' => 'ASC',
];
if ( ! empty( $searched_keyword ) ) {
$query['s'] = $searched_keyword;
}
if ( ! empty( $selected_values ) ) {
$query['include'] = $selected_values;
}
$posts = [];
foreach ( get_posts( $query ) as $post ) {
if ( static::filter_options( $post->ID, $post->post_title, $selected_values, $searched_keyword ) ) {
$posts[] = [
'value' => (string) $post->ID,
'label' => $post->post_title,
];
}
}
return $posts;
}
public static function get_post_type() {
return 'post';
}
/**
* @return string
*/
public static function get_placeholder_text() {
return esc_html__( 'Search posts', 'thrive-cb' );
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 10;
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Referral;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Tag extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'referral_data';
}
/**
* @return string
*/
public static function get_key() {
return 'referral_tag_id';
}
public static function get_label() {
return esc_html__( 'Tag', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'autocomplete' ];
}
public function get_value( $referral_data ) {
$tags = [];
if ( ! empty( $referral_data['post'] ) ) {
$post_tags = get_the_tags( $referral_data['post'] );
if ( ! empty( $post_tags ) ) {
foreach ( $post_tags as $tag ) {
$tags[] = $tag->term_id;
}
}
}
return $tags;
}
public static function get_options( $selected_values = [], $searched_keyword = '' ) {
$tags = [];
foreach ( get_tags() as $tag ) {
if ( static::filter_options( $tag->term_id, $tag->name, $selected_values, $searched_keyword ) ) {
$tags[] = [
'value' => (string) $tag->term_id,
'label' => $tag->name,
];
}
}
return $tags;
}
/**
* @return string
*/
public static function get_placeholder_text() {
return esc_html__( 'Search tags', 'thrive-cb' );
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 25;
}
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Referral;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Url extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'referral_data';
}
/**
* @return string
*/
public static function get_key() {
return 'referral_url';
}
public static function get_label() {
return esc_html__( 'URL', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'url_comparison' ];
}
public function get_value( $referral_data ) {
return empty( $referral_data['url'] ) ? '' : $referral_data['url'];
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 0;
}
/**
* @return string
*/
public static function get_placeholder_text() {
return esc_html__( 'Enter a URL. Use an asterisk as a wildcard', 'thrive-cb' );
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Request;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Cookie extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'request_data';
}
/**
* @return string
*/
public static function get_key() {
return 'cookie';
}
public static function get_label() {
return esc_html__( 'Cookie', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'string_comparison' ];
}
public function get_value( $request_data ) {
return $_COOKIE;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Request;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Post_Variable extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'request_data';
}
/**
* @return string
*/
public static function get_key() {
return 'post_variable';
}
public static function get_label() {
return esc_html__( 'POST variable ', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'string_comparison' ];
}
public function get_value( $request_data ) {
return wp_doing_ajax() && isset( $_GET['post_variables'] ) ? $_GET['post_variables'] : $_POST;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Request;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Url_Query_String extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'request_data';
}
/**
* @return string
*/
public static function get_key() {
return 'url_query_string';
}
public static function get_label() {
return esc_html__( 'URL Query String', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'string_comparison' ];
}
public function get_value( $request_data ) {
return wp_doing_ajax() && isset( $_GET['query_strings'] ) ? $_GET['query_strings'] : $_GET;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Time;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Current_Date extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'time_data';
}
/**
* @return string
*/
public static function get_key() {
return 'current_date';
}
public static function get_label() {
return esc_html__( 'Date', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'date' ];
}
public function get_value( $data ) {
return current_time( 'Y/m/d H:i' );
}
/**
* @return int
*/
public static function get_display_order() {
return 0;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Time;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Current_Time extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'time_data';
}
/**
* @return string
*/
public static function get_key() {
return 'current_time';
}
public static function get_label() {
return esc_html__( 'Time', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'time' ];
}
public function get_value( $data ) {
return current_time( 'H:i' );
}
/**
* @return int
*/
public static function get_display_order() {
return 5;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Time;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Day_Of_Month extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'time_data';
}
/**
* @return string
*/
public static function get_key() {
return 'day_of_month';
}
public static function get_label() {
return esc_html__( 'Day of month', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'number_equals' ];
}
public function get_value( $data ) {
return (int) date( 'd' );
}
/**
* @return array
*/
public static function get_validation_data() {
return [
'min' => 1,
'max' => 31,
];
}
/**
* @return int
*/
public static function get_display_order() {
return 15;
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Time;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Day_Of_Week extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'time_data';
}
/**
* @return string
*/
public static function get_key() {
return 'day_of_week';
}
public static function get_label() {
return esc_html__( 'Day of week', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'checkbox' ];
}
public function get_value( $data ) {
return strtolower( date( 'l' ) );
}
public static function get_options( $selected_values = [], $search = '' ) {
return [
[
'value' => 'monday',
'label' => __( 'Monday' ),
],
[
'value' => 'tuesday',
'label' => __( 'Tuesday' ),
],
[
'value' => 'wednesday',
'label' => __( 'Wednesday' ),
],
[
'value' => 'thursday',
'label' => __( 'Thursday' ),
],
[
'value' => 'friday',
'label' => __( 'Friday' ),
],
[
'value' => 'saturday',
'label' => __( 'Saturday' ),
],
[
'value' => 'sunday',
'label' => __( 'Sunday' ),
],
];
}
/**
* @return int
*/
public static function get_display_order() {
return 10;
}
}

View File

@@ -0,0 +1,102 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\Time;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Month extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'time_data';
}
/**
* @return string
*/
public static function get_key() {
return 'month';
}
public static function get_label() {
return esc_html__( 'Month', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'checkbox' ];
}
public function get_value( $data ) {
return (int) date( 'n' );
}
public static function get_options( $selected_values = [], $search = '' ) {
return [
[
'value' => '1',
'label' => __( 'January' ),
],
[
'value' => '2',
'label' => __( 'February' ),
],
[
'value' => '3',
'label' => __( 'March' ),
],
[
'value' => '4',
'label' => __( 'April' ),
],
[
'value' => '5',
'label' => __( 'May' ),
],
[
'value' => '6',
'label' => __( 'June' ),
],
[
'value' => '7',
'label' => __( 'July' ),
],
[
'value' => '8',
'label' => __( 'August' ),
],
[
'value' => '9',
'label' => __( 'September' ),
],
[
'value' => '10',
'label' => __( 'October' ),
],
[
'value' => '11',
'label' => __( 'November' ),
],
[
'value' => '12',
'label' => __( 'December' ),
],
];
}
/**
* @return int
*/
public static function get_display_order() {
return 20;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\User;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Last_Logged_In extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'user_data';
}
/**
* @return string
*/
public static function get_key() {
return 'last_logged_in';
}
public static function get_label() {
return esc_html__( 'Last logged in', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'date_and_time_with_intervals' ];
}
public function get_value( $user_data ) {
$last_logged_in = '';
if ( $user_data ) {
$user_meta = get_user_meta( $user_data->ID );
if ( isset( $user_meta['tve_last_login'] ) && is_array( $user_meta['tve_last_login'] ) ) {
$last_logged_in = date( 'Y-m-d H:i:s', (int) $user_meta['tve_last_login'][0] );
}
}
return $last_logged_in;
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 10;
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\User;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Number_Of_Comments extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'user_data';
}
/**
* @return string
*/
public static function get_key() {
return 'number_of_comments';
}
public static function get_label() {
return esc_html__( 'Number of comments', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'number_comparison' ];
}
public function get_value( $user_data ) {
$comments_count = 0;
if ( ! empty( $user_data ) ) {
$args = [
'author_email' => $user_data->user_email,
'no_found_rows' => false,
'number' => 10,
'status' => 'all,spam,trash',
];
$query = new \WP_Comment_Query;
$query->query( $args );
$comments_count = (int) $query->found_comments;
}
return $comments_count;
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 25;
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\User;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class User_Id extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'user_data';
}
/**
* @return string
*/
public static function get_key() {
return 'user_id';
}
public static function get_label() {
return esc_html__( 'Username', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'autocomplete' ];
}
public function get_value( $user_data ) {
return empty( $user_data ) ? '' : $user_data->ID;
}
public static function get_options( $selected_values = [], $searched_keyword = '' ) {
$users = [];
foreach ( get_users() as $user ) {
if ( static::filter_options( $user->ID, $user->data->user_login, $selected_values, $searched_keyword ) ) {
$users[] = [
'value' => (string) $user->ID,
'label' => $user->data->user_login,
];
}
}
return $users;
}
/**
* @return string
*/
public static function get_placeholder_text() {
return esc_html__( 'Search users', 'thrive-cb' );
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 20;
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\User;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class User_Is_Logged_In extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'user_data';
}
/**
* @return string
*/
public static function get_key() {
return 'is_logged_in';
}
public static function get_label() {
return esc_html__( 'Is logged in', 'thrive-cb' );
}
public static function get_conditions() {
return [];
}
public function get_value( $user_data ) {
return ! empty( $user_data );
}
public static function is_boolean() {
return true;
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 0;
}
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\User;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class User_Is_Not_Logged_In extends User_Is_Logged_In {
/**
* @return string
*/
public static function get_entity() {
return 'user_data';
}
/**
* @return string
*/
public static function get_key() {
return 'is_not_logged_in';
}
public static function get_label() {
return esc_html__( 'Is not logged in', 'thrive-cb' );
}
public function get_value( $user_data ) {
return empty( $user_data );
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 1;
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\User;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class User_Registration_Date extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'user_data';
}
/**
* @return string
*/
public static function get_key() {
return 'user_registration_date';
}
public static function get_label() {
return esc_html__( 'Registration date', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'date_and_time_with_intervals' ];
}
public function get_value( $user_data ) {
return empty( $user_data ) ? '' : $user_data->user_registered;
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 15;
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Fields\User;
use TCB\ConditionalDisplay\Field;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class User_Role extends Field {
/**
* @return string
*/
public static function get_entity() {
return 'user_data';
}
/**
* @return string
*/
public static function get_key() {
return 'user_role';
}
public static function get_label() {
return esc_html__( 'Role', 'thrive-cb' );
}
public static function get_conditions() {
return [ 'checkbox' ];
}
public function get_value( $user_data ) {
return empty( $user_data ) ? '' : $user_data->roles;
}
public static function get_options( $selected_values = [], $search = '' ) {
$roles = [];
if ( ! function_exists( 'get_editable_roles' ) ) {
require_once ABSPATH . '/wp-admin/includes/user.php';
}
foreach ( get_editable_roles() as $key => $role ) {
$roles[ $key ] = [
'label' => $role['name'],
'value' => $key,
];
}
return $roles;
}
/**
* Determines the display order in the modal field select
*
* @return int
*/
public static function get_display_order() {
return 5;
}
}

View File

@@ -0,0 +1,473 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\PostTypes;
use TCB\ConditionalDisplay\Shortcode;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Conditional_Display_Group {
const NAME = 'tve_cond_display';
const DISPLAYS_META_KEY = '_tve_conditional_displays';
const LAZY_LOAD_META_KEY = '_tve_lazy_load';
const UNIFORM_HEIGHT_META_KEY = '_tve_uniform_height';
const DISPLAY_HEIGHTS_META_KEY = '_tve_display_heights';
const PLACEHOLDER_CSS_META_KEY = '_tve_placeholder_css';
const PLACEHOLDER_HTML_META_KEY = '_tve_placeholder_html';
const INHERIT_BACKGROUND_META_KEY = '_tve_inherit_background';
/** @var \WP_Post */
private $post;
/** @var string|null */
private $key;
/** @var array|null */
private $displays;
public static function title() {
return __( 'Conditional display group', 'thrive-cb' );
}
public static function register() {
register_post_type(
static::NAME,
[
'public' => isset( $_GET[ TVE_EDITOR_FLAG ] ),
'publicly_queryable' => is_user_logged_in(),
'query_var' => false,
'exclude_from_search' => true,
'rewrite' => false,
'_edit_link' => 'post.php?post=%d',
'map_meta_cap' => true,
'label' => static::title(),
'capabilities' => [
'edit_others_posts' => 'tve-edit-cpt',
'edit_published_posts' => 'tve-edit-cpt',
],
'show_in_nav_menus' => false,
'show_in_menu' => false,
'show_in_rest' => true,
'has_archive' => false,
] );
}
/**
* @param null $key
*
* @return Conditional_Display_Group|null
*/
public static function get_instance( $key = null ) {
if ( $key === null ) {
return null;
}
$posts = get_posts( [
'post_type' => static::NAME,
'meta_query' => [
[
'key' => 'key',
'value' => $key,
],
],
] );
if ( empty( $posts ) ) {
$post = null;
} else {
$post = $posts[0];
}
return new self( $post, $key );
}
private function __construct( $post = null, $key = null ) {
$this->post = $post;
$this->key = $key;
}
public function create() {
$post_id = wp_insert_post( [
'post_title' => static::title(),
'post_type' => static::NAME,
'post_status' => 'publish',
'meta_input' => [
'key' => $this->key,
],
] );
$this->post = get_post( $post_id );
}
public function update( $data ) {
if ( $this->post === null ) {
$this->create();
}
foreach ( static::get_data_attributes() as $key => $meta_key ) {
if ( isset( $data[ $key ] ) ) {
$this->update_meta_key( $meta_key, $data[ $key ] );
}
}
}
/**
* @return string
*/
public function get_key() {
return $this->key;
}
/**
* @param $meta_key
* @param $default
*
* @return mixed|null
*/
public function get_meta_value( $meta_key, $default = null ) {
return $this->post === null ? $default : get_post_meta( $this->post->ID, $meta_key, true );
}
/**
* @param $meta_key
* @param $meta_value
*
* @return void
*/
public function update_meta_key( $meta_key, $meta_value ) {
update_post_meta( $this->post->ID, $meta_key, $meta_value );
}
/**
* Clone group and displays and return the new type
*
* @return Conditional_Display_Group
*/
public function clone_group( $css_id_map = [] ) {
$new_group_key = uniqid( 'tve-dg', false );
$new_group = new Conditional_Display_Group( null, $new_group_key );
$new_group->create();
$old_group_key = $this->get_key();
foreach ( static::get_data_attributes() as $meta_key ) {
$meta_value = $this->get_meta_value( $meta_key );
if ( $meta_key === static::DISPLAYS_META_KEY && is_array( $meta_value ) ) {
/* generate new keys for each display */
foreach ( $meta_value as $index => $display ) {
if ( $display['key'] !== 'default' ) {
$old_display_key = $display['key'];
$new_display_key = uniqid( '', false );
$display['key'] = $new_display_key;
/* replace old display key with the new one */
$display['html'] = str_replace( $old_display_key, $new_display_key, $display['html'] );
}
/* replace old group key with the new one */
$display['html'] = str_replace( $old_group_key, $new_group_key, $display['html'] );
/* replace css ids with newly generated ones */
$display['html'] = str_replace( array_keys( $css_id_map ), array_values( $css_id_map ), $display['html'] );
/* replace other groups inside the display */
$cloned_content = static::clone_conditional_groups_in_content( $display['html'], $css_id_map );
$display['html'] = $cloned_content['content'];
$meta_value[ $index ] = $display;
}
} elseif ( \is_string( $meta_value ) ) {
/* just replace the group key in every string */
$meta_value = str_replace( $old_group_key, $new_group_key, $meta_value );
/* also replace css ids */
$meta_value = str_replace( array_keys( $css_id_map ), array_values( $css_id_map ), $meta_value );
}
$new_group->update_meta_key( $meta_key, $meta_value );
}
return $new_group;
}
/**
* Data attributes
*
* @return string[]
*/
public static function get_data_attributes() {
return [
'displays' => static::DISPLAYS_META_KEY,
'lazy-load' => static::LAZY_LOAD_META_KEY,
'uniform-heights' => static::UNIFORM_HEIGHT_META_KEY,
'display-heights' => static::DISPLAY_HEIGHTS_META_KEY,
'placeholder-css' => static::PLACEHOLDER_CSS_META_KEY,
'placeholder-html' => static::PLACEHOLDER_HTML_META_KEY,
'inherit-bg' => static::INHERIT_BACKGROUND_META_KEY,
];
}
/**
* Return an array of displays from the group
*
* @param boolean $ordered
* @param boolean $is_editor_page
*
* @return array|mixed
*/
public function get_displays( $ordered = true, $is_editor_page = false ) {
if ( empty( $this->post ) ) {
$displays = [];
} else {
$displays = $this->get_meta_value( static::DISPLAYS_META_KEY );
if ( empty( $displays ) ) {
$displays = [];
} elseif ( $ordered ) {
$default_display_index = array_search( 'default', array_column( $displays, 'key' ), true );
$displays[ $default_display_index ]['order'] = $is_editor_page ? - 1 : PHP_INT_MAX;
uasort( $displays, static function ( $a, $b ) {
return (int) $a['order'] - (int) $b['order'];
} );
/* re-index after sorting */
$displays = array_values( $displays );
}
}
return $displays;
}
/**
* Localize display group data
*
* @param $for_preview boolean for preview we need more data
*
* @return array
*/
public function localize( $for_preview = false, $is_editor_page = false ) {
if ( empty( $GLOBALS['conditional_display_preview'] ) ) {
$GLOBALS['conditional_display_preview'] = [];
}
if ( ! isset( $GLOBALS['conditional_display_preview'][ $this->key ] ) ) {
$group_data = [
'key' => $this->key,
'lazy' => $this->has_lazy_load() ? 1 : 0,
'displays' => [],
'uniform-heights' => $this->has_uniformed_heights() ? 1 : 0,
'display-heights' => $this->get_display_heights(),
'inherit-bg' => $this->get_inherit_background(),
];
$external_resources = [
'js' => [],
'css' => [],
];
foreach ( $this->get_displays() as $display ) {
$display['html'] = Shortcode::parse_content( $display['html'], $is_editor_page );
$external_resources = static::get_external_resources_for_content( $external_resources, $display['html'] );
if ( $for_preview ) {
$display['sets'] = [];
$conditions = Shortcode::parse_condition_config( $display['conditions'] );
if ( ! empty( $conditions ) ) {
foreach ( $conditions as $set ) {
if ( empty( $set['ID'] ) ) {
$name = $set['label'];
} else {
$global_set = Global_Conditional_Set::get_instance( $set['ID'] );
$name = $global_set === null ? '' : $global_set->get_label();
}
$is_valid = Shortcode::verify_set( $set );
$display['sets'][] = [
'is_default' => false,
'is_checked' => $is_valid,
'is_global' => empty( $set['ID'] ) ? false : $set['ID'],
'name' => $name,
];
}
} elseif ( $display['key'] === 'default' ) {
$display['sets'][] = [ 'is_default' => true ];
}
}
$group_data['displays'][] = $display;
}
static::enqueue_external_resources( $external_resources );
$GLOBALS['conditional_display_preview'][ $this->key ] = $group_data;
}
return $GLOBALS['conditional_display_preview'][ $this->key ];
}
/**
* Check if we should load external resources for this content
*
* @param array $external_resources
* @param string $content
*
* @return array
*/
public static function get_external_resources_for_content( $external_resources, $content ) {
return apply_filters( 'tcb_external_resources_for_content', $external_resources, $content );
}
/**
* @param array $resources
*/
public static function enqueue_external_resources( $resources ) {
foreach ( $resources['js'] as $id => $script ) {
if ( ! wp_script_is( $id ) ) {
tve_enqueue_script( $id, $script['url'], $script['dependencies'], false, true );
}
}
foreach ( $resources['css'] as $id => $style ) {
if ( ! wp_style_is( $id ) ) {
tve_enqueue_style( $id, $style );
}
}
}
/**
* Check if the display group uses lazy load or not
*
* @return bool
*/
public function has_lazy_load() {
return $this->get_meta_value( static::LAZY_LOAD_META_KEY ) === '1';
}
/**
* @return bool
*/
public function has_uniformed_heights() {
return $this->get_meta_value( static::UNIFORM_HEIGHT_META_KEY ) === '1';
}
/**
* @return mixed|null
*/
public function get_display_heights() {
return $this->get_meta_value( static::DISPLAY_HEIGHTS_META_KEY, [] );
}
/**
* @return mixed|null
*/
public function get_inherit_background() {
return $this->get_meta_value( static::INHERIT_BACKGROUND_META_KEY, '' );
}
/**
* Check if the display group uses lazy load or not
*
* @return bool
*/
public function get_placeholder_css() {
$css = '';
if ( $this->post ) {
$css = $this->get_meta_value( static::PLACEHOLDER_CSS_META_KEY );
}
if ( ! empty( $css ) ) {
$css = \TCB_Utils::wrap_content( $css, 'style', '', 'tve-cd-placeholder-css-' . $this->key );
}
return $css;
}
public function lazy_load_placeholder() {
$placeholder_css = $this->get_placeholder_css();
$placeholder_html = $this->get_meta_value( static::PLACEHOLDER_HTML_META_KEY );
return empty( $placeholder_html ) ? '<div class="tcb-conditional-display-placeholder" data-group="' . $this->key . '">' . $placeholder_css . '</div>' : ( $placeholder_css . $placeholder_html );
}
/**
* @param array|string $groups
*
* @return void
*/
public static function save_groups( $groups = [] ) {
/* content templates save the groups in the JSON format, so we must decode first */
if ( ! empty( $groups ) && ! is_array( $groups ) ) {
$groups = json_decode( stripslashes( $groups ), true );
}
if ( is_array( $groups ) ) {
foreach ( $groups as $group ) {
if ( isset( $group['key'] ) ) {
$display_group = static::get_instance( (string) $group['key'] );
if ( $display_group !== null ) {
$display_group->update( $group );
}
}
}
}
}
/**
* Clone conditional groups from content and replace them with new ids
*
* @param string $content
* @param array $css_id_map
*
* @return array
*/
public static function clone_conditional_groups_in_content( $content, $css_id_map = [] ) {
$display_group_keys = [];
/* match display group key */
preg_match_all( '/\[' . Shortcode::NAME . " group='([^']*)'/m", $content, $matches );
if ( $matches !== null ) {
foreach ( $matches[1] as $display_group_key ) {
$display_group = static::get_instance( $display_group_key );
if ( $display_group !== null ) {
$new_display_group = $display_group->clone_group( $css_id_map );
$content = str_replace( $display_group_key, $new_display_group->get_key(), $content );
/* Store the mapping of old key to new key */
$display_group_keys[ $display_group_key ] = $new_display_group->get_key();
}
}
}
return [
'content' => $content,
'display_group_keys' => $display_group_keys,
];
}
}

View File

@@ -0,0 +1,130 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\PostTypes;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class Global_Conditional_Set {
const NAME = 'tve_global_cond_set';
/** @var \WP_Post */
private $post;
public static function title() {
return __( 'Global condition set', 'thrive-cb' );
}
public static function register() {
register_post_type( static::NAME, [
'public' => isset( $_GET[ TVE_EDITOR_FLAG ] ),
'publicly_queryable' => is_user_logged_in(),
'query_var' => false,
'exclude_from_search' => true,
'rewrite' => false,
'_edit_link' => 'post.php?post=%d',
'map_meta_cap' => true,
'label' => static::title(),
'capabilities' => [
'edit_others_posts' => 'tve-edit-cpt',
'edit_published_posts' => 'tve-edit-cpt',
],
'show_in_nav_menus' => false,
'show_in_menu' => false,
'show_in_rest' => true,
'has_archive' => false,
] );
}
/**
* @param $post_id
*
* @return Global_Conditional_Set|null
*/
public static function get_instance( $post_id = null ) {
if ( ! empty( $post_id ) ) {
$post = get_post( $post_id );
}
if ( empty( $post ) ) {
$post = null;
}
return new self( $post );
}
private function __construct( $post = null ) {
$this->post = $post;
}
public function get_post() {
return $this->post;
}
public function create( $rules, $label ) {
$post_id = wp_insert_post( [
'post_title' => static::title(),
'post_type' => static::NAME,
'post_status' => 'publish',
'meta_input' => [
'rules' => $rules,
'label' => $label,
],
]
);
$this->post = get_post( $post_id );
return $post_id;
}
public function update( $rules, $label ) {
update_post_meta( $this->post->ID, 'rules', $rules );
update_post_meta( $this->post->ID, 'label', $label );
}
public function remove() {
wp_delete_post( $this->post->ID, true );
}
public function get_rules() {
return get_post_meta( $this->post->ID, 'rules', true );
}
public function get_label() {
return empty( $this->post ) ? '' : get_post_meta( $this->post->ID, 'label', true );
}
/**
* @param string $searched_keyword
* @param bool $strict
*
* @return array[]
*/
public static function get_sets_by_name( $searched_keyword, $strict = false ) {
$posts = get_posts( [
'post_type' => static::NAME,
'posts_per_page' => 20,
'meta_query' => [
[
'key' => 'label',
'value' => $searched_keyword,
'compare' => $strict ? '=' : 'LIKE',
],
],
] );
return array_map( function ( $item ) {
return [
'value' => $item->ID,
'label' => get_post_meta( $item->ID, 'label' ),
];
}, $posts );
}
}

View File

@@ -0,0 +1,198 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\RestApi;
use TCB\ConditionalDisplay\Condition;
use TCB\ConditionalDisplay\Entity;
use TCB\ConditionalDisplay\Field;
use TCB\ConditionalDisplay\PostTypes\Conditional_Display_Group;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class General_Data
*
* @package TCB\ConditionalDisplay\RestApi
*/
class General_Data {
const REST_NAMESPACE = 'tcb/v1';
const REST_ROUTE = 'conditional-display/';
public static function register_routes() {
register_rest_route( static::REST_NAMESPACE, static::REST_ROUTE . 'groups', [
[
'methods' => \WP_REST_Server::READABLE,
'callback' => [ __CLASS__, 'get_groups' ],
'permission_callback' => [ __CLASS__, 'route_permission' ],
'args' => [
'groups' => [
'type' => 'array',
'required' => true,
],
],
],
] );
register_rest_route( static::REST_NAMESPACE, static::REST_ROUTE . 'fields', [
[
'methods' => \WP_REST_Server::READABLE,
'callback' => [ __CLASS__, 'get_fields' ],
'permission_callback' => [ __CLASS__, 'route_permission' ],
'args' => [
'entity' => [
'type' => 'string',
'required' => true,
],
],
],
] );
register_rest_route( static::REST_NAMESPACE, static::REST_ROUTE . 'conditions', [
[
'methods' => \WP_REST_Server::READABLE,
'callback' => [ __CLASS__, 'get_conditions' ],
'permission_callback' => [ __CLASS__, 'route_permission' ],
'args' => [
'field' => [
'type' => 'string',
'required' => true,
],
],
],
] );
register_rest_route( static::REST_NAMESPACE, static::REST_ROUTE . 'field-options', [
[
'methods' => \WP_REST_Server::READABLE,
'callback' => [ __CLASS__, 'get_field_options' ],
'permission_callback' => [ __CLASS__, 'route_permission' ],
'args' => [
'field' => [
'type' => 'string',
'required' => true,
],
],
],
] );
}
/**
* @param $request \WP_REST_Request
*
* @return array
*/
public static function get_groups( $request ) {
$group_keys = $request->get_param( 'groups' );
$query_vars = $request->get_param( 'query_vars' );
if ( ! empty( $query_vars ) ) {
tve_set_query_vars_data( $query_vars );
}
if ( is_array( $group_keys ) ) {
foreach ( $group_keys as $display_group_key ) {
$display_group = Conditional_Display_Group::get_instance( $display_group_key );
if ( $display_group !== null ) {
$display_group->localize( false, true );
}
}
$groups = array_values( $GLOBALS['conditional_display_preview'] );
} else {
$groups = [];
}
return $groups;
}
/**
* @param $request \WP_REST_Request
*
* @return \WP_REST_Response
*/
public static function get_fields( $request ) {
$entity_key = $request->get_param( 'entity' );
$field_data = [];
$entity = Entity::get();
$fields = $entity[ $entity_key ]::get_fields();
if ( ! empty( $fields ) ) {
foreach ( $fields as $field_key ) {
$field_class = Field::get()[ $field_key ];
$field_data[ $field_key ] = $field_class::get_data_to_localize();
}
}
return new \WP_REST_Response( $field_data );
}
/**
* @param \WP_REST_Request
*
* @return \WP_REST_Response
*/
public static function get_conditions( $request ) {
$field_key = $request->get_param( 'field' );
$condition_data = [];
$field = Field::get();
if ( ! empty( $field[ $field_key ] ) ) {
$conditions = $field[ $field_key ]::get_conditions();
if ( ! empty( $conditions ) ) {
foreach ( $conditions as $condition_key ) {
$condition_class = Condition::get()[ $condition_key ];
$condition_data[ $condition_key ] = $condition_class::get_data_to_localize();
}
}
}
return new \WP_REST_Response( $condition_data );
}
/**
* @param \WP_REST_Request
*
* @return \WP_REST_Response
*/
public static function get_field_options( $request ) {
$options = [];
$field_key = $request->get_param( 'field' );
if ( ! empty( Field::get()[ $field_key ] ) ) {
$selected_values = $request->get_param( 'values' );
$search = $request->get_param( 'search' );
$field = Field::get();
$options = $field[ $field_key ]::get_options( $selected_values, $search );
}
return new \WP_REST_Response( $options );
}
/**
* Check if a given request has access to route
*
* @return \WP_Error|bool
*/
public static function route_permission() {
$post_id = isset( $_REQUEST['post_id'] ) ? $_REQUEST['post_id'] : null;
return \TCB_Product::has_external_access( $post_id );
}
}

View File

@@ -0,0 +1,182 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\RestApi;
use TCB\ConditionalDisplay\PostTypes\Global_Conditional_Set;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class Global_Sets
*
* @package TCB\ConditionalDisplay\RestApi
*/
class Global_Sets {
const REST_NAMESPACE = 'tcb/v1';
const REST_ROUTE = 'conditional-display/global-set';
public static function register_routes() {
register_rest_route( static::REST_NAMESPACE, static::REST_ROUTE, [
[
'methods' => \WP_REST_Server::CREATABLE,
'callback' => [ __CLASS__, 'update_global_set' ],
'permission_callback' => [ __CLASS__, 'route_permission' ],
'args' => [
'label' => [
'type' => 'string',
'required' => true,
],
'rules' => [
'type' => 'array',
'required' => true,
],
],
],
] );
register_rest_route( static::REST_NAMESPACE, static::REST_ROUTE . '/(?P<id>[\d]+)', [
[
'methods' => \WP_REST_Server::READABLE,
'callback' => [ __CLASS__, 'get_global_set_data' ],
'permission_callback' => [ __CLASS__, 'route_permission' ],
],
[
'methods' => \WP_REST_Server::EDITABLE,
'callback' => [ __CLASS__, 'update_global_set' ],
'permission_callback' => [ __CLASS__, 'route_permission' ],
'args' => [
'label' => [
'type' => 'string',
'required' => true,
],
'rules' => [
'type' => 'array',
'required' => true,
],
],
],
[
'methods' => \WP_REST_Server::DELETABLE,
'callback' => [ __CLASS__, 'remove_global_set' ],
'permission_callback' => [ __CLASS__, 'route_permission' ],
],
] );
register_rest_route( static::REST_NAMESPACE, static::REST_ROUTE . '/get-all', [
[
'methods' => \WP_REST_Server::READABLE,
'callback' => [ __CLASS__, 'get_global_sets' ],
'permission_callback' => [ __CLASS__, 'route_permission' ],
'args' => [
'search' => [
'type' => 'string',
'required' => false,
],
],
],
] );
}
/**
* @param \WP_REST_Request
*
* @return \WP_REST_Response
*/
public static function get_global_set_data( $request ) {
$data = [];
$post_id = $request->get_param( 'id' );
$global_set = Global_Conditional_Set::get_instance( $post_id );
if ( ! empty( $global_set->get_post() ) ) {
$data = [
'id' => $post_id,
'rules' => $global_set->get_rules(),
'label' => $global_set->get_label(),
];
}
return new \WP_REST_Response( $data );
}
/**
* @param \WP_REST_Request
*
* @return \WP_REST_Response
*/
public static function get_global_sets( $request ) {
$searched_keyword = $request->get_param( 'search' );
$global_sets = Global_Conditional_Set::get_sets_by_name( $searched_keyword );
return new \WP_REST_Response( $global_sets );
}
/**
* @param \WP_REST_Request
*
* @return \WP_REST_Response|\WP_Error
*/
public static function update_global_set( $request ) {
$post_id = $request->get_param( 'id' );
$label = $request->get_param( 'label' );
$sets_with_this_label = Global_Conditional_Set::get_sets_by_name( $label, true );
if (
! empty( $sets_with_this_label ) &&
(
empty( $post_id ) || /* case 1: no post ID means we're adding a new global set and the label already exists */
count( $sets_with_this_label ) > 1 /* case 2: if there is a post ID: the only global set found for this label should be the current one */
)
) {
return new \WP_Error( 'tcb_error', __( 'A global set with this name already exists!', 'thrive-cb' ), [ 'status' => 409 ] );
}
$rules = $request->get_param( 'rules' );
if ( empty( $post_id ) ) {
$global_set = Global_Conditional_Set::get_instance();
$post_id = $global_set->create( $rules, $label );
} else {
$global_set = Global_Conditional_Set::get_instance( $post_id );
$global_set->update( $rules, $label );
}
return new \WP_REST_Response( $post_id );
}
/**
*
* @param \WP_REST_Request
*
* @return \WP_REST_Response
*/
public static function remove_global_set( $request ) {
$post_id = $request->get_param( 'id' );
$global_set = Global_Conditional_Set::get_instance( $post_id );
$global_set->remove();
return new \WP_REST_Response( $post_id );
}
/**
* Check if a given request has access to route
*
* @return \WP_Error|bool
*/
public static function route_permission() {
$post_id = isset( $_REQUEST['post_id'] ) ? $_REQUEST['post_id'] : null;
return \TCB_Product::has_external_access( $post_id );
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
namespace TCB\ConditionalDisplay\Traits;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
trait Item {
protected static $registered_items = [];
/**
* Get a list of all the registered items
*
* @param bool $sort_by_order
*
* @return static[]
*/
public static function get( $sort_by_order = false ) {
$items = static::$registered_items;
if ( $sort_by_order ) {
uasort( $items, static function ( $item1, $item2 ) {
/* @var Item $item1 , $item2 */
return $item1::get_display_order() - $item2::get_display_order();
} );
}
return $items;
}
/**
* @param $item
*/
public static function register( $item ) {
if ( is_subclass_of( $item, static::class ) ) {
if ( ! empty( $item::get_key() ) ) {
static::$registered_items[ $item::get_key() ] = $item;
} else {
trigger_error( $item . ' does not have an ID.' );
}
} else {
trigger_error( 'Argument ' . $item . ' must be a subclass of ' . static::class );
}
}
/**
* @param string $key
* @param array $extra_data
*
* @return mixed
*/
public static function get_instance( $key = '', $extra_data = [] ) {
$items = static::get();
$instance = null;
if ( isset( $items[ $key ] ) ) {
$instance = new $items[ $key ]( $extra_data );
}
return $instance;
}
/**
* @return string
*/
public function __toString() {
return __CLASS__;
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Register a new condition entity
*
* @param \TCB\ConditionalDisplay\Entity|string $entity
*/
function tve_register_condition_entity( $entity ) {
TCB\ConditionalDisplay\Entity::register( $entity );
}
/**
* Register a new condition field
*
* @param \TCB\ConditionalDisplay\Field|string $field
*/
function tve_register_condition_field( $field ) {
TCB\ConditionalDisplay\Field::register( $field );
}
/**
* Register a new condition
*
* @param \TCB\ConditionalDisplay\Condition|string $condition
*/
function tve_register_condition( $condition ) {
TCB\ConditionalDisplay\Condition::register( $condition );
}

View File

@@ -0,0 +1,388 @@
<?php
if ( ! class_exists( 'TCB_Landing_Page_Cloud_Templates_Api' ) ) {
require_once TVE_TCB_ROOT_PATH . 'landing-page/inc/TCB_Landing_Page_Transfer.php';
}
class TCB_Content_Templates_Api extends TCB_Landing_Page_Cloud_Templates_Api {
/**
* Needed to support extending the parent singleton
*
* @return TCB_Content_Templates_Api
*/
public static function getInstance() {
return new TCB_Content_Templates_Api();
}
/**
* Called from wp-includes/kses.php
*
* Adds extra css into a list of allowed style css.
* That list is used to filter the inline style attributes and removes disallowed rules from content
*
* @param array $allowed_style_css
*
* @return array
*/
public function add_extra_allowed_style_css( $allowed_style_css = [] ) {
if ( ! in_array( 'display', $allowed_style_css ) ) {
$allowed_style_css[] = 'display';
}
return $allowed_style_css;
}
/**
*
* Fetches all Content Templates of a type from landingpages.thrivethemes.com
*
* @param string $type
* @param array $args
*
* @return array
*
* @throws Exception
*/
public function get_all( $type = null, $args = [] ) {
$params = wp_parse_args(
$args,
array(
'route' => 'getAll',
'tar_version' => defined( 'TCB_CLOUD_DEBUG' ) && TCB_CLOUD_DEBUG ? '10' : TVE_VERSION,
'type' => $type,
'ct' => md5( time() ),
)
);
$response = $this->_request( $params );
$data = json_decode( $response, true );
if ( empty( $data ) ) {
throw new Exception( 'Got response: ' . $response );
}
if ( empty( $data['success'] ) ) {
throw new Exception( $data['error_message'] );
}
if ( ! isset( $data['data'] ) ) {
throw new Exception( 'Could not fetch templates.' );
}
$this->_validateReceivedHeader( $data );
$templates = apply_filters( 'tcb_cloud_templates', $data['data'], $type );
return $templates;
}
/**
* Just forward the call to get_all()
*
* Should not be used
*
* @param string $type
*
* @return array
*/
public function getTemplateList() {
$args = func_get_args();
if ( ! count( $args ) ) {
$args = [ 'testimonial' ];
}
return $this->get_all( array_shift( $args ) );
}
/**
* Get a post associated with a cloud content template
*
* @param string $id
*
* @return WP_Post|null
*/
public function get_post_for_content_template( $id ) {
$maybe = get_posts( [
'post_type' => TCB_CT_POST_TYPE,
'meta_key' => 'tcb_ct_id',
'meta_value' => $id,
'posts_per_page' => 1,
] );
return $maybe ? $maybe[0] : null;
}
/**
* get content template data
*
* @param $id
* @param bool $do_shortcode whether or not to execute `do_shortcode` on the content
*
* @return null|array
*/
public function get_content_template( $id, $do_shortcode = true ) {
$post = $this->get_post_for_content_template( $id );
if ( ! $post ) {
return null;
}
$meta = get_post_meta( $post->ID, 'tcb_ct_meta', true );
/**
* Change post data for a content template
*
* @param WP_Post $post
* @param array $meta
*
*/
do_action( 'tcb_before_get_content_template', $post, $meta );
$content = $do_shortcode ? do_shortcode( $post->post_content ) : $post->post_content;
$head_css = $do_shortcode ? do_shortcode( $meta['head_css'] ) : $meta['head_css'];
$data = array(
'id' => $id,
'type' => $meta['type'],
'name' => $post->post_title,
'content' => $content,
'head_css' => $head_css,
'custom_css' => $meta['custom_css'],
'v' => (int) ( isset( $meta['v'] ) ? $meta['v'] : 0 ),
'config' => isset( $meta['config'] ) ? $meta['config'] : [],
'tve_globals' => isset( $meta['tve_globals'] ) ? $meta['tve_globals'] : [],
'thumb' => isset( $meta['thumb'] ) ? $meta['thumb'] : [],
);
return apply_filters( 'tcb_alter_cloud_template_meta', $data, $meta, $do_shortcode );
}
/**
* Get data for a content template, or download it if it's not available locally
*
* @param string|int $id
* @param array $args
* @param bool $do_shortcode
*
* @return array|WP_Error|null
* @throws Exception
*
*/
public function download( $id, $args = [], $do_shortcode = true ) {
/**
* This needs to always be a string
*/
$id = (string) $id;
$type = (string) $args['type'];
$post_type = get_post_type( $args['post_id'] );
/**
* first make sure we can save the downloaded template
*/
$upload = wp_upload_dir();
if ( ! empty( $upload['error'] ) ) {
throw new Exception( $upload['error'] );
}
$base = trailingslashit( $upload['basedir'] ) . TVE_CLOUD_TEMPLATES_FOLDER . '/';
if ( false === wp_mkdir_p( $base . 'images' ) ) {
throw new Exception( 'Could not create the templates folder' );
}
$params = array(
'route' => 'download',
'type' => $type,
'post_type' => $post_type,
'tar_version' => TVE_VERSION,
'ct' => md5( time() ),
'id' => $id,
);
$params = apply_filters( 'tcb_download_template', $params );
$body = $this->_request( $params );
$control = [
'auth' => $this->request['headers']['X-Thrive-Authenticate'],
'id' => $id,
];
/**
* this means an error -> error message is json_encoded
*/
if ( empty( $this->received_auth_header ) || strpos( $body, '{"success' ) === 0 ) {
$data = json_decode( $body, true );
throw new Exception( isset( $data['error_message'] ) ? $data['error_message'] : ( 'Invalid response: ' . $body ) );
}
$this->_validateReceivedHeader( $control );
if ( $id === 'default' && ! empty( $this->response['headers']['X-Thrive-Template-Id'] ) ) {
$id = $this->response['headers']['X-Thrive-Template-Id'];
}
/**
* at this point, $body holds the contents of the zip file
*/
$zip_path = trailingslashit( $upload['basedir'] ) . TVE_CLOUD_TEMPLATES_FOLDER . '/ct-' . $id . '.zip';
tve_wp_upload_bits( $zip_path, $body );
$template_data = $this->process_zip( $zip_path );
$post = $this->get_post_for_content_template( $id );
$data = [
'post_title' => $template_data['name'],
'post_content' => $template_data['content'],
'post_type' => TCB_CT_POST_TYPE,
'post_status' => 'publish',
];
add_filter( 'safe_style_css', [ $this, 'add_extra_allowed_style_css' ] );
/*
* This filter causes serious issues on some of our header / footer templates, for which the html
* is a bit more than WordPress can handle - especially in cases where we have html code inside element attributes
*/
remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
if ( ! $post ) {
$post_id = wp_insert_post( $data );
} else {
$data['ID'] = $post->ID;
wp_update_post( $data );
$post_id = $post->ID;
}
remove_filter( 'safe_style_css', [ $this, 'add_extra_allowed_style_css' ] );
update_post_meta( $post_id, 'tcb_ct_id', $id );
update_post_meta( $post_id, 'tcb_ct_meta', apply_filters( 'tcb_alter_cloud_template_meta', array(
'v' => isset( $template_data['v'] ) ? $template_data['v'] : '0',
'type' => $template_data['type'],
'head_css' => $template_data['head_css'],
'custom_css' => $template_data['custom_css'],
'config' => isset( $template_data['config'] ) ? $template_data['config'] : [],
'tve_globals' => isset( $template_data['tve_globals'] ) ? $template_data['tve_globals'] : [],
'thumb' => isset( $template_data['thumb'] ) ? $template_data['thumb'] : [],
), $template_data, $do_shortcode ) );
return $id;
}
/**
* Extract the content template data from the archive located at $path
*
* @param string $path
*
* @throws Exception
*
*/
public function process_zip( $zip_file_path ) {
$old_umask = umask( 0 );
defined( 'FS_METHOD' ) || define( 'FS_METHOD', 'direct' );
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once( ABSPATH . 'wp-admin/includes/file.php' );
}
/** @var $wp_filesystem WP_Filesystem_Base */
global $wp_filesystem;
$upload = wp_upload_dir();
$wp_uploads_dir = $upload['basedir'];
if ( FS_METHOD !== 'direct' ) {
WP_Filesystem( array(
'hostname' => defined( 'FTP_HOST' ) ? FTP_HOST : '',
'username' => defined( 'FTP_USER' ) ? FTP_USER : '',
'password' => defined( 'FTP_PASS' ) ? FTP_PASS : '',
) );
if ( FS_METHOD !== 'ssh2' ) {
$wp_uploads_dir = str_replace( ABSPATH, '', $wp_uploads_dir );
}
} else {
WP_Filesystem();
}
if ( ! $wp_filesystem->connect() && $wp_filesystem->errors instanceof WP_Error ) {
throw new Exception( $wp_filesystem->errors->get_error_message() );
}
$folder = trailingslashit( $wp_uploads_dir ) . TVE_CLOUD_TEMPLATES_FOLDER . '/';
//$folder = trailingslashit( $upload['basedir'] ) . TVE_CLOUD_TEMPLATES_FOLDER . '/';
/* this means the template archive is coming directly from the Thrive Template Cloud, we can trust it */
$result = unzip_file( $zip_file_path, $folder );
if ( $result instanceof WP_Error ) {
umask( $old_umask );
throw new Exception( __( 'Could not extract the archive file', 'thrive-cb' ) );
}
if ( ! $wp_filesystem->is_readable( $folder . 'data.json' ) ) {
throw new Exception( __( 'Invalid archive contents', 'thrive-cb' ) );
}
@unlink( $zip_file_path );
$config = json_decode( $wp_filesystem->get_contents( $folder . 'data.json' ), true );
$type = empty( $config['type'] ) ? '' : $config['type'] . '/';
$baseurl = str_replace(
array(
'http://',
'https://',
),
'//',
$upload['baseurl']
);
$upload_url = trailingslashit( $baseurl ) . TVE_CLOUD_TEMPLATES_FOLDER . '/' . $type;
$images_uri = $upload_url . 'images/';
$this->replace_images( $config['head_css'], $config['image_map'], $images_uri );
$this->replace_images( $config['content'], $config['image_map'], $images_uri );
@unlink( $folder . 'data.json' );
if ( ! empty( $config['thumb']['url'] ) ) {
$config['thumb']['url'] = $upload_url . 'thumbnails/' . $config['thumb']['url'];
}
return $config;
}
/**
* Modified string, replaces md5 image codes with image URLs
*
* @param string $string
* @param array $image_map
* @param string $uri
*/
protected function replace_images( &$string, $image_map, $uri ) {
foreach ( $image_map as $key => $name ) {
$string = str_replace( "{{img={$key}}}", $uri . $name, $string );
}
}
}
/**
* @var TCB_Content_Templates_Api
*/
global $tcb_content_templates_api;
function tcb_content_templates_api() {
global $tcb_content_templates_api;
if ( ! isset( $tcb_content_templates_api ) ) {
$tcb_content_templates_api = TCB_Content_Templates_Api::getInstance();
}
return $tcb_content_templates_api;
}

View File

@@ -0,0 +1,91 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Article_Element
*/
class TCB_Article_Element extends TCB_Post_List_Sub_Element_Abstract {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Article', 'thrive-cb' );
}
/**
* WordPress element identifier
*
* @return string
*/
public function identifier() {
return '.' . TCB_POST_WRAPPER_CLASS;
}
/**
* Hide this.
*
* @return bool
*/
public function hide() {
return true;
}
/**
* This element has a selector
*
* @return bool
*/
public function has_selector() {
return true;
}
/**
* Check if this element behaves like a shortcode.
*
* @return bool
*/
public function is_shortcode() {
return false;
}
/**
* Whether or not this element can be edited while under :hover state
*
* @return bool
*/
public function has_hover_state() {
return true;
}
/**
* @return array
*/
public function own_components() {
$components = parent::own_components();
$components['responsive']['hidden'] = true;
$components['typography']['hidden'] = true;
$components['animation']['disabled_controls'] = [ '.anim-popup', '.anim-link' ];
$components['layout']['disabled_controls'] =
[
'margin-right',
'margin-bottom',
'margin-left',
'.tve-advanced-controls',
'MaxWidth',
'Alignment',
'hr',
'Display',
];
return $components;
}
}

View File

@@ -0,0 +1,116 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Audio_Element
*/
class TCB_Audio_Element extends TCB_Element_Abstract {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Audio', 'thrive-cb' );
}
/**
* Get element alternate
*
* @return string
*/
public function alternate() {
return 'audio';
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
return 'audio';
}
/**
* Element identifier
*
* @return string
*/
public function identifier() {
return '.thrv_audio,.tve_audio_container';
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
return [
'audio' => [
'config' => [
'ExternalFields' => [
'config' => [
'key' => 'audio',
'shortcode_element' => 'audio.tcb-audio',
],
'extends' => 'CustomFields',
],
],
],
'typography' => [ 'hidden' => true ],
'background' => [ 'hidden' => true ],
'shadow' => [
'config' => [
'disabled_controls' => [ 'inner', 'text' ],
],
],
'animation' => [ 'hidden' => true ],
'layout' => [
'config' => [
'Width' => [
'important' => true,
],
'Height' => [
'css_suffix' => [ ' iframe', ' > :first-child' ],
],
],
'disabled_controls' => [ 'Overflow', 'ScrollStyle' ],
],
];
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return static::get_thrive_advanced_label();
}
/**
* Element info
*
* @return string|string[][]
*/
public function info() {
return [
'instructions' => [
'type' => 'help',
'url' => 'audio_element',
'link' => 'https://help.thrivethemes.com/en/articles/4425842-how-to-use-the-audio-element',
],
];
}
}

View File

@@ -0,0 +1,195 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Avatar_Picker_Element
*/
class TCB_Avatar_Picker_Element extends TCB_Element_Abstract {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Avatar Picker', 'thrive-cb' );
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
return 'text';
}
public function hide() {
return true;
}
/**
* Element identifier
*
* @return string
*/
public function identifier() {
return '.tve-avatar-picker-element';
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return static::get_thrive_integrations_label();
}
public function has_hover_state() {
return true;
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
$avatar_image_selector = ' .tve-avatar-picker-image';
$has_google_connection = ! empty( tvd_get_google_api_key() );
$has_facebook_connection = ! empty( tvd_get_facebook_app_id() );
return [
'avatar_picker' => [
'config' => [
'GoogleApi' => [
'config' => [
'name' => '',
'label' => __( 'Enable Google', 'thrive-cb' ),
'default' => false,
'info' => ! $has_google_connection,
'info_hover' => ! $has_google_connection,
],
'extends' => 'Switch',
],
'FacebookApi' => [
'config' => [
'name' => '',
'label' => __( 'Enable Facebook', 'thrive-cb' ),
'default' => false,
'info' => ! $has_facebook_connection,
'info_hover' => ! $has_facebook_connection,
],
'extends' => 'Switch',
],
'Gravatar' => [
'config' => [
'name' => '',
'label' => __( 'Enable Gravatar', 'thrive-cb' ),
'default' => true,
],
'extends' => 'Switch',
],
'CustomUrl' => [
'config' => [
'name' => '',
'label' => __( 'Custom url', 'thrive-cb' ),
'default' => false,
],
'extends' => 'Switch',
],
'ImagePicker' => [
'config' => [
'label' => __( 'Default avatar', 'thrive-cb' ),
],
],
'ImageSize' => [
'config' => [
'default' => '240',
'min' => '50',
'max' => '1024',
'label' => __( 'Image size', 'thrive-cb' ),
'um' => [ 'px' ],
],
],
'ButtonType' => [
'config' => [
'name' => __( 'Edit button type', 'thrive-cb' ),
'options' => [
// 'button' => __( 'Button', 'thrive-cb' ),
'icon' => __( 'Icon', 'thrive-cb' ),
'overlay' => __( 'Overlay', 'thrive-cb' ),
],
],
'extends' => 'Select',
],
'ButtonPosition' => [
'config' => [
'name' => __( 'Button position', 'thrive-cb' ),
'options' => [
'top' => __( 'Top', 'thrive-cb' ),
'bottom' => __( 'Bottom', 'thrive-cb' ),
],
],
'extends' => 'Select',
],
'IconPosition' => [
'config' => [
'name' => __( 'Icon position', 'thrive-cb' ),
'options' => [
'top-left' => __( 'Left', 'thrive-cb' ),
'top-right' => __( 'Right', 'thrive-cb' ),
],
],
'extends' => 'Select',
],
],
],
'typography' => [
'hidden' => true,
],
'shadow' => [
'config' => [
'disabled_controls' => [ 'text' ],
'default_shadow' => 'none',
'css_suffix' => $avatar_image_selector,
],
],
'background' => [
'hidden' => true,
],
'styles-templates' => [
'hidden' => true,
],
'responsive' => [
'hidden' => true,
],
'animation' => [
'hidden' => true,
],
'layout' => [
'disabled_controls' => [ '[data-label="Width"]', '[data-label="Height"]', '[data-view="Display"]', '.tve-advanced-controls' ],
],
'borders' => [
'config' => [
'Borders' => [
'css_suffix' => $avatar_image_selector,
],
'Corners' => [
'css_suffix' => $avatar_image_selector,
],
],
],
];
}
}

View File

@@ -0,0 +1,91 @@
<?php
require_once plugin_dir_path( __FILE__ ) . 'class-tcb-section-element.php';
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Section_Element
*/
class TCB_Block_Element extends TCB_Section_Element {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Block', 'thrive-cb' );
}
/**
* Section element identifier
*
* @return string
*/
public function identifier() {
return '.thrv-lp-block.thrv-page-section';
}
/**
* @return bool
*/
public function promoted() {
return true;
}
/**
* @return bool
*/
public function is_placeholder() {
return false;
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return static::get_thrive_advanced_label();
}
/**
* HTML layout of the element for when it's dragged in the canvas
*
* @return string
*/
protected function html() {
return tcb_template( 'elements/' . $this->tag() . '.php', $this, true );
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
$components = parent::own_components();
$components = array_merge( [ 'block' => $components['section'] ], $components );
unset( $components['section'] );
unset( $components['shared-styles'] );
return array_merge( $components, $this->group_component() );
}
/**
* Element info
*
* @return string|string[][]
*/
public function info() {
return [
'instructions' => [
'type' => 'help',
'url' => 'block',
'link' => 'https://help.thrivethemes.com/en/articles/4425843-how-to-use-the-block-element',
],
];
}
}

View File

@@ -0,0 +1,347 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Button_Element
*/
class TCB_Button_Element extends TCB_Cloud_Template_Element_Abstract {
/**
* Get element alternate
*
* @return string
*/
public function alternate() {
return 'button';
}
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Button', 'thrive-cb' );
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
return 'button';
}
/**
* Button element identifier
*
* @return string
*/
public function identifier() {
return '.thrv-button, .thrv_button_shortcode';
}
/**
* This element is not a placeholder
*
* @return bool|true
*/
public function is_placeholder() {
return false;
}
/**
* Allow this element to be also styled for active state
*
* The active state class is .tcb-active-state
*
* @return string
*/
public function active_state_config() {
return apply_filters( 'tcb_button_active_state', false );
}
/**
* HTML layout of the element for when it's dragged in the canvas
*
* @return string
*/
protected function html() {
return tcb_template( 'elements/' . $this->tag() . '.php', $this, true );
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
$button = array(
'button' => array(
'config' => array(
'ButtonPalettes' => [
'config' => [],
'extends' => 'Palettes',
],
'icon_side' => array(
'config' => array(
'name' => __( 'Icon side', 'thrive-cb' ),
'buttons' => array(
array( 'value' => 'left', 'text' => __( 'Left', 'thrive-cb' ), 'default' => true ),
array( 'value' => 'right', 'text' => __( 'Right', 'thrive-cb' ) ),
),
),
),
'ButtonIcon' => array(
'config' => array(
'name' => '',
'label' => __( 'Add icon', 'thrive-cb' ),
'default' => false,
),
'extends' => 'Switch',
),
'MasterColor' => array(
'config' => array(
'default' => '000',
'label' => __( 'Master Color', 'thrive-cb' ),
'important' => true,
'affected_components' => [ 'shadow', 'background', 'borders' ],
'options' => [
'showGlobals' => false,
],
),
),
'SecondaryText' => array(
'config' => array(
'name' => '',
'label' => __( 'Secondary button text', 'thrive-cb' ),
'default' => false,
),
'to' => '.tcb-button-texts',
'extends' => 'Switch',
),
'ButtonSize' => array(
'css_prefix' => tcb_selection_root() . ' ',
'config' => array(
'name' => __( 'Size and alignment', 'thrive-cb' ),
'full-width' => true,
'buttons' => array(
array(
'value' => 's',
'properties' => [
'padding' => '12px 15px',
'font-size' => '18px',
'line-height' => '1.2em',
],
'text' => 'S',
'default' => true,
),
array(
'value' => 'm',
'properties' => [
'padding' => '14px 22px',
'font-size' => '24px',
'line-height' => '1.2em',
],
'text' => 'M',
),
array(
'value' => 'l',
'properties' => [
'padding' => '18px 30px',
'font-size' => '32px',
'line-height' => '1.2em',
],
'text' => 'L',
),
array(
'value' => 'xl',
'properties' => [
'padding' => '22px 40px',
'font-size' => '38px',
'line-height' => '1.1em',
],
'text' => 'XL',
),
array(
'value' => 'xxl',
'properties' => [
'padding' => '32px 50px',
'font-size' => '52px',
'line-height' => '1.1em',
],
'text' => 'XXL',
),
),
),
),
'Align' => array(
'config' => array(
'buttons' => array(
array(
'icon' => 'a_left',
'value' => 'left',
'tooltip' => __( 'Align Left', 'thrive-cb' ),
),
array(
'icon' => 'a_center',
'value' => 'center',
'default' => true,
'tooltip' => __( 'Align Center', 'thrive-cb' ),
),
array(
'icon' => 'a_right',
'value' => 'right',
'tooltip' => __( 'Align Right', 'thrive-cb' ),
),
array(
'text' => 'FULL',
'value' => 'full',
'tooltip' => __( 'Full Width', 'thrive-cb' ),
),
),
),
),
'ButtonWidth' => array(
'config' => array(
'default' => '0',
'min' => '10',
'max' => '1080',
'label' => __( 'Button width', 'thrive-cb' ),
'um' => [ '%', 'px' ],
'css' => 'max-width',
),
'extends' => 'Slider',
),
'style' => array(
'css_suffix' => ' .tcb-button-link',
'config' => array(
'label' => __( 'Button Styles', 'thrive-cb' ),
'items' => [],
'default_label' => __( 'Template Button', 'thrive-cb' ),
'default' => 'default',
),
),
),
),
'animation' => [
'config' => [
'to' => '.tcb-button-link',
],
],
'background' => [
'config' => [
'css_suffix' => ' .tcb-button-link',
],
],
'borders' => [
'config' => [
'css_suffix' => ' .tcb-button-link',
],
],
'typography' => [
'config' => [
'css_suffix' => ' .tcb-button-link',
'FontColor' => [
'css_suffix' => ' .tcb-button-link span',
],
'FontSize' => [
'css_suffix' => ' .tcb-button-link',
'important' => true,
],
'TextStyle' => [
'css_suffix' => ' .tcb-button-link span',
],
'LineHeight' => [
'css_suffix' => ' .tcb-button-link',
],
'FontFace' => [
'css_suffix' => ' .tcb-button-link',
],
'TextTransform' => [
'css_suffix' => ' .tcb-button-link span',
],
'LetterSpacing' => [
'css_suffix' => ' .tcb-button-link',
],
],
],
'shadow' => [
'config' => [
'css_suffix' => ' .tcb-button-link',
'default_shadow' => 'none',
],
],
'layout' => [
'config' => [
'MarginAndPadding' => [
'padding_suffix' => ' .tcb-button-link',
],
'Height' => [
'css_suffix' => ' .tcb-button-link',
],
],
'disabled_controls' => [
'Display',
'Alignment',
'Overflow',
'ScrollStyle',
],
],
'scroll' => [
'hidden' => false,
],
);
return array_merge( $button, $this->shared_styles_component() );
}
/**
* @return bool
*/
public function has_hover_state() {
return true;
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return static::get_thrive_basic_label();
}
/**
* Get default button templates from the cloud
*
* @return array|mixed|WP_Error
*/
public function get_default_templates() {
return tve_get_cloud_content_templates( $this->get_template_tag() );
}
/**
* Element info
*
* @return string|string[][]
*/
public function info() {
return [
'instructions' => [
'type' => 'help',
'url' => 'button',
'link' => 'https://help.thrivethemes.com/en/articles/4425768-how-to-use-the-button-element',
],
];
}
}

View File

@@ -0,0 +1,65 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 6/29/2018
* Time: 10:01 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
class TCB_Button_Group_Element extends TCB_Element_Abstract {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Button Group', 'thrive-cb' );
}
/**
* Hide Element From Sidebar Menu
*
* @return bool
*/
public function hide() {
return true;
}
/**
* When element is selected in editor this identifier
* establishes element _type
*
* @return string
* @see TVE.main.element_selected() TVE._type()
*
*/
public function identifier() {
return '.thrv-button-group';
}
/**
* Components that apply only to this
*
* @return array
*/
public function own_components() {
return [
'button_group' => [
'config' => [],
],
'typography' => [ 'hidden' => true ],
'animation' => [ 'hidden' => true ],
'shadow' => [
'config' => [
'disabled_controls' => [ 'text' ],
],
],
];
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 7/5/2018
* Time: 4:44 PM
*/
require_once 'class-tcb-button-group-item-element.php';
/**
* Class TCB_Button_Group_Item_Element
*/
class TCB_Button_Group_Item_Element extends TCB_Button_Element {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Button Group Item', 'thrive-cb' );
}
/**
* Hide Element From Sidebar Menu
*
* @return bool
*/
public function hide() {
return true;
}
/**
* Allow this element to be also styled for active state
*
* The active state class is .tcb-active-state
*
* @return string
*/
public function active_state_config() {
return true;
}
/**
* Button element identifier
*
* @return string
*/
public function identifier() {
return '.thrv-button-group-item';
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
$components = parent::own_components();
$components['button']['disabled_controls'] = [
'.tve-control[data-key="style"]',
'.tcb-button-link-container',
];
$components['animation'] = [
'hidden' => true,
];
$components['shared-styles'] = [
'hidden' => true,
];
$components['layout']['disabled_controls'] = [
'Alignment',
'.tve-advanced-controls',
'hr',
];
$components['borders']['config']['Borders']['important'] = true;
$components['borders']['config']['Corners']['important'] = true;
$components['scroll'] = [ 'hidden' => true ];
return $components;
}
}

View File

@@ -0,0 +1,77 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Callaction_Element
*/
class TCB_Callaction_Element extends TCB_Cloud_Template_Element_Abstract {
/**
* Get element alternate
*
* @return string
*/
public function alternate() {
return 'box, template, button, content';
}
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Call to Action', 'thrive-cb' );
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
return 'call_2_action';
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
return [];
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return static::get_thrive_advanced_label();
}
/**
* Element info
*
* @return string|string[][]
*/
public function info() {
return [
'instructions' => [
'type' => 'help',
'url' => 'call_to_action',
'link' => 'https://help.thrivethemes.com/en/articles/4425745-adding-a-call-to-action-element-with-thrive-architect',
],
];
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
if ( ! class_exists( '\TCB_Icon_Element', false ) ) {
require_once TVE_TCB_ROOT_PATH . 'inc/classes/elements/class-tcb-icon-element.php';
}
/**
* Class TCB_Carousel_Arrows_Element
*/
class TCB_Carousel_Arrows_Element extends TCB_Icon_Element {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Arrows', 'thrive-cb' );
}
/**
* Element identifier
*
* @return string
*/
public function identifier() {
return '.thrv_icon.tcb-carousel-arrow';
}
/**
* Hide Element From Sidebar Menu
*
* @return bool
*/
public function hide() {
return true;
}
/**
* @return array
*/
public function own_components() {
$components = parent::own_components();
$components['icon']['disabled_controls'] = [ 'ToggleURL', 'link', 'RotateIcon' ];
$components['layout']['disabled_controls'] = [
'margin-bottom',
'Width',
'Height',
'Display',
'Overflow',
'ScrollStyle',
'Alignment',
'Position',
'Float',
];
$components['icon']['config']['Slider']['css_prefix'] = tcb_selection_root() . ' .tcb-carousel-arrow';
$components['scroll'] = [ 'hidden' => true ];
$components['animation'] = [ 'hidden' => false ];
$components['carousel_arrows'] = $components['icon'];
unset( $components['icon'] );
return $components;
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
if ( ! class_exists( '\TCB_Icon_Element', false ) ) {
require_once TVE_TCB_ROOT_PATH . 'inc/classes/elements/class-tcb-icon-element.php';
}
/**
* Class TCB_Carousel_Dots_Element
*/
class TCB_Carousel_Dots_Element extends TCB_Icon_Element {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Dots', 'thrive-cb' );
}
/**
* Element identifier
*
* @return string
*/
public function identifier() {
return '.tcb-carousel-dots,.slick-dots';
}
/**
* Hide Element From Sidebar Menu
*
* @return bool
*/
public function hide() {
return true;
}
/**
* @return array
*/
public function own_components() {
$components = parent::own_components();
$components['icon']['disabled_controls'] = [ 'ToggleURL', 'link', 'RotateIcon' ];
$components['layout']['disabled_controls'] = [
'Width',
'Height',
'Display',
'Overflow',
'ScrollStyle',
'Alignment',
'Position',
'Float',
];
$components['scroll'] = [ 'hidden' => true ];
$components['animation'] = [ 'hidden' => true ];
$components['styles-templates'] = [ 'hidden' => true ];
$components['carousel_dots'] = $components['icon'];
$components['carousel_dots']['config']['ColorPicker']['important'] = true;
$components['carousel_dots']['config']['HorizontalSpace'] = array(
'config' => array(
'min' => '0',
'max' => '100',
'label' => __( 'Horizontal space', 'thrive-cb' ),
'um' => [ 'px', '%' ],
),
'extends' => 'Slider',
);
$components['layout']['config']['MarginAndPadding']['important'] = true;
unset( $components['icon'] );
return $components;
}
}

View File

@@ -0,0 +1,134 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Cell_Element
*
* Table cell editing
*/
class TCB_Cell_Element extends TCB_Element_Abstract {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Table Cell', 'thrive-cb' );
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
return 'none';
}
/**
* Element identifier
*
* @return string
*/
public function identifier() {
return '.tve_table th, .tve_table td';
}
/**
* Table cells are not visible in the side menu
*
* @return bool
*/
public function hide() {
return true;
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
return array(
'cell' => array(
'config' => array(
'width' => array(
'config' => array(
'min' => 50,
'max' => 500,
'label' => __( 'Column Width', 'thrive-cb' ),
'um' => [ 'px' ],
),
'extends' => 'Slider',
),
'height' => array(
'config' => array(
'min' => 10,
'max' => 200,
'label' => __( 'Row Height', 'thrive-cb' ),
'um' => [ 'px' ],
),
'extends' => 'Slider',
),
'valign' => array(
'config' => array(
'name' => __( 'Vertical Align', 'thrive-cb' ),
'buttons' => [
[
'icon' => 'none',
'default' => true,
'value' => '',
],
[
'icon' => 'top',
'value' => 'top',
],
[
'icon' => 'vertical',
'value' => 'middle',
],
[
'icon' => 'bot',
'value' => 'bottom',
],
],
),
'extends' => 'ButtonGroup',
),
),
),
'borders' => [
'hidden' => true,
],
'animation' => [
'hidden' => true,
],
'layout' => [
'hidden' => true,
],
'typography' => [
'hidden' => true,
],
'shadow' => [
'config' => [
'disabled_controls' => [ 'text' ],
],
],
'responsive' => [
'hidden' => true,
],
'styles-templates' => [
'hidden' => true,
],
);
}
}

View File

@@ -0,0 +1,152 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Column_Element
*/
class TCB_Column_Element extends TCB_Element_Abstract {
/**
* Not directly available from the menu
*
* @return bool
*/
public function hide() {
return true;
}
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Column', 'thrive-cb' );
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
return 'column';
}
/**
* Text element identifier
*
* @return string
*/
public function identifier() {
return 'div.tcb-col';
}
/**
* @return string
*/
protected function html() {
return '';
}
/**
* @return array
*/
public function own_components() {
return array(
'column' => array(
'config' => array(
'VerticalPosition' => array(
'config' => array(
'name' => __( 'Vertical position', 'thrive-cb' ),
'important' => true,
'buttons' => [
[
'icon' => 'none',
'default' => true,
'value' => '',
],
[
'icon' => 'top',
'value' => 'flex-start',
],
[
'icon' => 'vertical',
'value' => 'center',
],
[
'icon' => 'bot',
'value' => 'flex-end',
],
],
),
'extends' => 'ButtonGroup',
),
'FixedWidth' => array(
'config' => array(
'name' => '',
'label' => __( 'Enable fixed width', 'thrive-cb' ),
'default' => true,
'info' => true,
),
'extends' => 'Switch',
),
'FullHeight' => array(
'config' => array(
'name' => '',
'label' => __( 'Enable full height', 'thrive-cb' ),
'default' => true,
'info' => true,
),
'extends' => 'Switch',
),
'ColumnWidth' => array(
'config' => array(
'default' => '100',
'min' => '30',
'max' => '1500',
'label' => __( 'Width', 'thrive-cb' ),
'um' => [ 'px', '%', ],
'um_disabled' => true,
),
'extends' => 'Slider',
),
),
),
'responsive' => [ 'hidden' => true ],
'styles-templates' => [ 'hidden' => true ],
'layout' => [
'disabled_controls' => [
'.tve-advanced-controls',
'Width',
'Height',
'Alignment',
'Display',
],
],
'borders' => [
'config' => [
'Borders' => [
'important' => true,
],
],
],
'conditional-display' => [ 'hidden' => false ],
);
}
/**
* @return bool
*/
public function has_hover_state() {
return true;
}
}

View File

@@ -0,0 +1,205 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Columns_Element
*/
class TCB_Columns_Element extends TCB_Element_Abstract {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Columns', 'thrive-cb' );
}
/**
* Get element alternate
*
* @return string
*/
public function alternate() {
return 'container,box,content';
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
return 'column';
}
/**
* Text element identifier
*
* @return string
*/
public function identifier() {
return '.thrv-columns:not(.thrv-testimonial), .thrv_columns';
}
protected function html() {
return '';
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
return array(
'columns' => array(
'config' => array(
'GutterWidth' => array(
'config' => array(
'default' => '15',
'min' => '0',
'max' => '200',
'label' => __( 'Gutter width', 'thrive-cb' ),
'um' => [ 'px' ],
),
'to' => '> .tcb-flex-row',
'css_suffix' => ' > .tcb-flex-col',
'extends' => 'Slider',
),
'ColumnsOrder' => array(
'config' => array(
'name' => '',
'label' => __( 'Reverse column order', 'thrive-cb' ),
'default' => false,
),
'to' => ' > .tcb-flex-row',
'extends' => 'Switch',
),
'VerticalPosition' => array(
'config' => array(
'name' => __( 'Vertical position', 'thrive-cb' ),
'buttons' => [
[
'icon' => 'top',
'default' => true,
'value' => 'flex-start',
],
[
'icon' => 'vertical',
'value' => 'center',
],
[
'icon' => 'bot',
'value' => 'flex-end',
],
],
'info' => true,
),
'to' => ' > .tcb-flex-row',
'extends' => 'ButtonGroup',
),
'Wrap' => array(
'config' => array(
'name' => '',
'label' => __( 'Wrap columns', 'thrive-cb' ),
'default' => true,
),
'to' => ' > .tcb-flex-row',
'extends' => 'Switch',
),
'ColumnWidth' => array(
'config' => array(
'default' => '250',
'min' => '40',
'max' => '700',
'label' => __( 'Column breakpoint', 'thrive-cb' ),
'info' => true,
'info_hover' => true,
'um' => [ 'PX' ],
),
'to' => ' > .tcb-flex-row',
'extends' => 'Slider',
),
'FullWidth' => array(
'config' => array(
'name' => '',
'label' => __( 'Stretch to fit screen width', 'thrive-cb' ),
'default' => true,
),
'extends' => 'Switch',
),
'MinHeight' => array(
'config' => array(
'default' => '1024',
'min' => '1',
'max' => '1000',
'label' => __( 'Minimum height', 'thrive-cb' ),
'um' => [ 'px', 'vh' ],
'css' => 'min-height',
),
'to' => ' > .tcb-flex-row',
'css_suffix' => ' > .tcb-flex-col > .tcb-col',
'extends' => 'Slider',
),
),
),
'layout' => [
'config' => [
'MarginAndPadding' => [
'margin_to' => '',
'padding_to' => ' > .tcb-flex-row',
],
'Height' => [
'to' => ' > .tcb-flex-row',
'css_suffix' => ' > .tcb-flex-col > .tcb-col',
],
],
'disabled_controls' => [],
],
'typography' => [
'disabled_controls' => [],
'config' => [
'ParagraphStyle' => [ 'hidden' => false ],
],
],
'animation' => [ 'hidden' => true ],
'scroll' => [
'hidden' => false,
],
);
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return static::get_thrive_basic_label();
}
/**
* Element info
*
* @return string|string[][]
*/
public function info() {
return [
'instructions' => [
'type' => 'help',
'url' => 'columns',
'link' => 'https://help.thrivethemes.com/en/articles/4425769-how-to-use-the-columns-element',
],
];
}
}

View File

@@ -0,0 +1,118 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 5/3/2017
* Time: 1:42 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Commentsdisqus_Element
*/
class TCB_Commentsdisqus_Element extends TCB_Element_Abstract {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Disqus Comments', 'thrive-cb' );
}
/**
* Get element alternate
*
* @return string
*/
public function alternate() {
return 'social';
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
return 'disqus_comments';
}
/**
* Disqus Comments element identifier
*
* @return string
*/
public function identifier() {
return '.thrv_disqus_comments'; // Compatibility with TCB 1.5
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
return array(
'commentsdisqus' => array(
'config' => array(
'ForumName' => array(
'config' => array(
'full-width' => true,
'label' => __( 'Forum Name', 'thrive-cb' ),
),
'extends' => 'LabelInput',
),
'URL' => array(
'config' => array(
'full-width' => true,
'label' => __( 'URL', 'thrive-cb' ),
'placeholder' => __( 'http://', 'thrive-cb' ),
),
'extends' => 'LabelInput',
),
),
),
'typography' => [ 'hidden' => true ],
'animation' => [ 'hidden' => true ],
'background' => [ 'hidden' => true ],
'shadow' => [ 'hidden' => true ],
'layout' => [
'disabled_controls' => [
'.tve-advanced-controls',
'Width',
'Height',
'Alignment',
],
],
);
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return static::get_thrive_advanced_label();
}
/**
* Element info
*
* @return string|string[][]
*/
public function info() {
return [
'instructions' => [
'type' => 'help',
'url' => 'disqus_comments',
'link' => 'https://help.thrivethemes.com/en/articles/4425808-how-to-add-facebook-disqus-comments-in-thrive-architect',
],
];
}
}

View File

@@ -0,0 +1,160 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 5/4/2017
* Time: 11:56 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Commentsfacebook_Element
*/
class TCB_Commentsfacebook_Element extends TCB_Element_Abstract {
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Facebook Comments', 'thrive-cb' );
}
/**
* Get element alternate
*
* @return string
*/
public function alternate() {
return 'social';
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
return 'facebook_comments';
}
/**
* Facebook Comments element identifier
*
* @return string
*/
public function identifier() {
return '.thrv_facebook_comments'; // Compatibility with TCB 1.5
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
return array(
'commentsfacebook' => array(
'config' => array(
'moderators' => array(
'config' => array(
'top_text' => __( 'Add Facebook user ID for the people that you will like to moderate the comments.', 'thrive-cb' ),
'add_button_text' => __( 'Add New Moderator', 'thrive-cb' ),
'list_label' => 'ID',
'remove_title' => __( 'Remove Moderator', 'thrive-cb' ),
'list_items' => [],
),
'extends' => 'InputMultiple',
),
'URL' => array(
'config' => array(
'full-width' => true,
'label' => __( 'URL', 'thrive-cb' ),
'placeholder' => 'http://',
),
'extends' => 'LabelInput',
),
'nr_of_comments' => array(
'config' => array(
'default' => '20',
'min' => '1',
'max' => '200',
'label' => __( 'Number of comments', 'thrive-cb' ),
'um' => [],
),
'extends' => 'Slider',
),
'color_scheme' => array(
'config' => array(
'name' => __( 'Color Scheme', 'thrive-cb' ),
'options' => [
[
'value' => 'light',
'name' => 'Light',
],
[
'value' => 'dark',
'name' => 'Dark',
],
],
),
'extends' => 'Select',
),
'order_by' => array(
'config' => array(
'name' => __( 'Order By', 'thrive-cb' ),
'options' => [
[
'value' => 'social',
'name' => 'Social Popularity',
],
[
'value' => 'time',
'name' => 'Oldest First',
],
[
'value' => 'reverse_time',
'name' => 'Newest first',
],
],
),
'extends' => 'Select',
),
),
),
'typography' => [ 'hidden' => true ],
'animation' => [ 'hidden' => true ],
'background' => [ 'hidden' => true ],
'shadow' => [ 'hidden' => true ],
'layout' => [ 'disabled_controls' => [ 'Height', 'Width', 'Alignment', 'Overflow', 'ScrollStyle' ] ],
);
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return static::get_thrive_advanced_label();
}
/**
* Element info
*
* @return string|string[][]
*/
public function info() {
return [
'instructions' => [
'type' => 'help',
'url' => 'facebook_comments',
'link' => 'https://help.thrivethemes.com/en/articles/4425808-how-to-add-facebook-disqus-comments-in-thrive-architect',
],
];
}
}

View File

@@ -0,0 +1,211 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-visual-editor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Contact_Form_Element
*
* Element class
*/
class TCB_Contact_Form_Element extends TCB_Cloud_Template_Element_Abstract {
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return static::get_thrive_advanced_label();
}
public function hide() {
return true;
}
/**
* Name of the Element in sidebar
*
* @return string
*/
public function name() {
return __( 'Contact Form (Old)', 'thrive-cb' );
}
/**
* Which svg symbol id to use
*
* @return string
*/
public function icon() {
return 'contact_form';
}
/**
* When element is selected in editor this identifier
* establishes element _type
*
* @return string
* @see TVE.main.element_selected() TVE._type()
*
*/
public function identifier() {
return '.thrv-contact-form';
}
protected function html() {
return tcb_template( 'elements/' . $this->tag() . '.php', $this, true );
}
/**
* Filters the Contact Form Input Types
*
* @return array
*/
public function get_types() {
require_once dirname( dirname( __FILE__ ) ) . '/class-tcb-contact-form.php';
$types = TCB_Contact_Form::get_types();
foreach ( $types as $key => $value ) {
if ( ! empty( $value['validation_error'] ) ) {
unset( $types[ $key ]['validation_error'] );
}
}
return $types;
}
public function own_components() {
$contact_form = array(
'contact_form' => array(
'config' => array(
'FieldsControl' => array(
'config' => array(
'sortable' => true,
'settings_icon' => 'edit',
'types' => $this->get_types(),
),
),
'AddRemoveLabels' => array(
'config' => array(
'name' => '',
'label' => __( 'Labels', 'thrive-cb' ),
'default' => true,
),
'css_suffix' => ' label',
'css_prefix' => '',
'extends' => 'Switch',
),
'AddRemoveRequiredMarks' => array(
'config' => array(
'name' => '',
'label' => __( 'Required Marks', 'thrive-cb' ),
'default' => true,
),
'extends' => 'Switch',
),
'ZapierConnection' => array(
'config' => array(
'name' => '',
'label' => __( 'Connect to Zapier', 'thrive-cb' ),
'icon' => 'zapier-logo',
'default' => false,
),
'extends' => 'Switch',
),
'ZapierTags' => array(
'config' => array(
'label' => __( 'Tags', 'thrive-cb' ),
),
),
'ZapierIp' => array(
'config' => array(
'label' => __( 'Send IP Address', 'thrive-cb' ),
),
),
),
),
'typography' => [
'hidden' => true,
],
'animation' => [
'hidden' => true,
],
'layout' => [
'config' => [
'Width' => [
'important' => true,
],
],
'disabled_controls' => [
'Overflow',
'ScrollStyle',
],
],
);
return array_merge( $contact_form, $this->group_component() );
}
/**
* Group Edit Properties
*
* @return array|bool
*/
public function has_group_editing() {
return array(
'select_values' => array(
array(
'value' => 'all_cf_items',
'selector' => '.tve-cf-item',
'name' => __( 'Grouped Form Items', 'thrive-cb' ),
'singular' => __( '-- Form Item %s', 'thrive-cb' ),
),
array(
'value' => 'all_inputs',
'selector' => '.tve-cf-input',
'name' => __( 'Grouped Inputs', 'thrive-cb' ),
'singular' => __( '-- Input %s', 'thrive-cb' ),
),
array(
'value' => 'all_labels',
'selector' => '.tve-cf-item label',
'name' => __( 'Grouped Labels', 'thrive-cb' ),
'singular' => __( '-- Label %s', 'thrive-cb' ),
),
),
);
}
public function is_placeholder() {
return false;
}
/**
* Element info
*
* @return string|string[][]
*/
public function info() {
return [
'instructions' => [
'type' => 'help',
'url' => 'contact_form',
'link' => 'https://help.thrivethemes.com/en/articles/4430139-how-to-use-the-contact-form-element',
],
];
}
}

View File

@@ -0,0 +1,137 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 5/22/2018
* Time: 8:45 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class TCB_Contact_Form_Input_Element extends TCB_Element_Abstract {
/**
* Name of the Element
*
* @return string
*/
public function name() {
return __( 'Contact Form Input', 'thrive-cb' );
}
/**
* Section element identifier
*
* @return string
*/
public function identifier() {
return '.tve-cf-input';
}
/**
* Enables Hover States on Form Input
*
* @return bool
*/
public function has_hover_state() {
return true;
}
/**
* There is no need for HTML for this element since we need it only for control filter
*
* @return string
*/
protected function html() {
return '';
}
/**
* Hide Element From Sidebar Menu
*
* @return bool
*/
public function hide() {
return true;
}
/**
* Component and control configda
*
* @return array
*/
public function own_components() {
$prefix_config = tcb_selection_root();
$controls_default_config = [
'css_suffix' => [
' input',
' input::placeholder',
' textarea',
' textarea::placeholder',
],
];
$tag_default_config = [
'css_suffix' => [
' input',
' textarea',
],
];
return array(
'typography' => [
'config' => [
'FontSize' => $controls_default_config,
'FontColor' => $controls_default_config,
'TextAlign' => $controls_default_config,
'TextStyle' => $controls_default_config,
'TextTransform' => $controls_default_config,
'FontFace' => $controls_default_config,
'LineHeight' => $controls_default_config,
'LetterSpacing' => $controls_default_config,
],
],
'layout' => [
'disabled_controls' => [
'Width',
'Height',
'Alignment',
'Display',
'.tve-advanced-controls',
],
'config' => [
'MarginAndPadding' => $tag_default_config,
],
],
'borders' => array(
'config' => array(
'Borders' => array_merge( [ 'css_prefix' => $prefix_config . ' ' ], $tag_default_config ),
'Corners' => array_merge( [ 'css_prefix' => $prefix_config . ' ' ], $tag_default_config ),
),
),
'animation' => [
'hidden' => true,
],
'background' => [
'config' => [
'ColorPicker' => $tag_default_config,
'PreviewList' => $tag_default_config,
],
],
'shadow' => [
'config' => $tag_default_config,
],
'responsive' => [
'hidden' => true,
],
'styles-templates' => [
'hidden' => true,
],
);
}
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package TCB2.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class TCB_Contact_Form_Item_Element extends TCB_Element_Abstract {
public function name() {
return __( 'Contact Form Item', 'thrive-cb' );
}
public function identifier() {
return '.tve-cf-item';
}
/**
* Hide Element From Sidebar Menu
*
* @return bool
*/
public function hide() {
return true;
}
public function own_components() {
return [
'typography' => [
'hidden' => true,
],
'layout' => [
'disabled_controls' => [
'Width',
'Height',
'Alignment',
'Display',
'.tve-advanced-controls',
],
],
'animation' => [
'hidden' => true,
],
'responsive' => [
'hidden' => true,
],
'styles-templates' => [
'hidden' => true,
],
];
}
}

View File

@@ -0,0 +1,105 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 5/21/2018
* Time: 4:55 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class TCB_Contact_Form_Label_Element extends TCB_Element_Abstract {
/**
* Name of the Element
*
* @return string
*/
public function name() {
return __( 'Contact Form Label', 'thrive-cb' );
}
/**
* Section element identifier
*
* @return string
*/
public function identifier() {
return '.tve-cf-item label';
}
/**
* There is no need for HTML for this element since we need it only for control filter
*
* @return string
*/
protected function html() {
return '';
}
/**
* Hide Element From Sidebar Menu
*
* @return bool
*/
public function hide() {
return true;
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
return [
'typography' => [
'disabled_controls' => [ 'TextAlign', '.tve-advanced-controls' ],
'config' => [
'css_suffix' => '',
'FontSize' => [
'css_suffix' => '',
'important' => true,
],
'FontColor' => [
'css_suffix' => '',
'important' => true,
],
'LineHeight' => [
'css_suffix' => '',
'important' => true,
],
'LetterSpacing' => [
'css_suffix' => '',
'important' => true,
],
'FontFace' => [
'css_suffix' => '',
'important' => true,
],
'TextStyle' => [
'css_suffix' => '',
'important' => true,
],
'TextTransform' => [
'css_suffix' => '',
'important' => true,
],
],
],
'animation' => [
'hidden' => true,
],
'responsive' => [
'hidden' => true,
],
'styles-templates' => [
'hidden' => true,
],
];
}
}

View File

@@ -0,0 +1,156 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package TCB2.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class TCB_Contact_Form_Submit_Element extends TCB_Element_Abstract {
public function name() {
return __( 'Contact Form Submit', 'thrive-cb' );
}
public function identifier() {
return '.tve-cf-submit';
}
public function has_hover_state() {
return true;
}
public function hide() {
return true;
}
public function own_components() {
$prefix = tcb_selection_root( false ) . ' ';
$controls_default_config = [
'css_suffix' => ' button',
'css_prefix' => $prefix,
];
$submit = array(
'contact_form_submit' => array(
'config' => array(
'icon_side' => array(
'css_suffix' => ' .thrv_icon',
'css_prefix' => $prefix,
'config' => array(
'name' => __( 'Icon Side', 'thrive-cb' ),
'buttons' => array(
array(
'value' => 'left',
'text' => __( 'Left', 'thrive-cb' ),
),
array(
'value' => 'right',
'text' => __( 'Right', 'thrive-cb' ),
),
),
),
),
'ButtonWidth' => array(
'css_prefix' => $prefix,
'config' => array(
'default' => '100',
'min' => '10',
'max' => '100',
'label' => __( 'Button width', 'thrive-cb' ),
'um' => [ '%' ],
'css' => 'width',
),
'extends' => 'Slider',
),
'ButtonAlign' => array(
'config' => array(
'name' => __( 'Button Align', 'thrive-cb' ),
'buttons' => [
[
'icon' => 'a_left',
'text' => '',
'value' => 'left',
'default' => true,
],
[
'icon' => 'a_center',
'text' => '',
'value' => 'center',
],
[
'icon' => 'a_right',
'text' => '',
'value' => 'right',
],
[
'icon' => 'a_full-width',
'text' => '',
'value' => 'justify',
],
],
),
'extends' => 'ButtonGroup',
),
),
),
'typography' => [
'config' => [
'FontSize' => $controls_default_config,
'FontColor' => $controls_default_config,
'TextAlign' => $controls_default_config,
'TextStyle' => $controls_default_config,
'TextTransform' => $controls_default_config,
'FontFace' => $controls_default_config,
'LineHeight' => $controls_default_config,
'LetterSpacing' => $controls_default_config,
],
],
'layout' => [
'disabled_controls' => [
'Width',
'Height',
'Alignment',
'.tve-advanced-controls',
],
'config' => [
'MarginAndPadding' => $controls_default_config,
],
],
'borders' => [
'config' => [
'Borders' => $controls_default_config,
'Corners' => $controls_default_config,
],
],
'animation' => [
'hidden' => true,
],
'responsive' => [
'hidden' => true,
],
'background' => [
'config' => [
'ColorPicker' => $controls_default_config,
'PreviewList' => $controls_default_config,
],
],
'shadow' => [
'config' => $controls_default_config,
],
// 'styles-templates' => [
// 'config' => [
// 'to' => 'button',
// ],
// ],
);
return $submit;
// return array_merge( $submit, $this->shared_styles_component() );
}
}

View File

@@ -0,0 +1,350 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 2/7/2019
* Time: 9:40 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Class TCB_Contentblock_Element
*
* Element Class
*/
class TCB_Contentblock_Element extends TCB_Cloud_Template_Element_Abstract {
/**
* TCB_Contentblock_Element constructor.
*
* @param string $tag
*/
public function __construct( $tag = '' ) {
parent::__construct( $tag );
add_filter( 'tcb_alter_cloud_template_meta', [ $this, 'alter_tpl_meta' ], 10, 2 );
add_filter( 'tcb_filter_cloud_template_data', [ $this, 'filter_tpl_data' ], 10, 2 );
}
/**
* Either to display or not the element in the sidebar menu
*
* @return bool
*/
public function hide() {
return true;
}
/**
* Modifies the template meta for the content block element
*
* Works both in storing the meta values inside DB or outputing the values to the user
*
* Used in inc/classes/content-templates/class-tcb-content-templates-api.php
*
* @param array $return
* @param array $template_data
*
* @return array
*/
public function alter_tpl_meta( $return = [], $template_data = [] ) {
if ( $template_data['type'] === $this->_tag ) {
$return['pack'] = $template_data['pack'];
}
return $return;
}
/**
* Filters the data that comes from the user database for content block element
*
* Returns only the templates and ignores the packs and categories
*
* @param array $return
* @param string $tag
*
* @return array
*/
public function filter_tpl_data( $return = [], $tag = '' ) {
if ( $tag === $this->_tag ) {
$return = $return['tpls'];
}
return $return;
}
/**
* Returns the landing page cloud content blocks
*
* @param array $args
*
* @return array|WP_Error
*/
public function get_lp_cloud_templates( $args = [] ) {
$args = wp_parse_args( $args, [
'nocache' => false,
] );
$return = [];
if ( empty( $args['lp_set'] ) ) {
return $return;
}
$pack = sanitize_title( 'lp-set-' . (string) $args['lp_set'] );
$do_not_use_cache = ( defined( 'TCB_TEMPLATE_DEBUG' ) && TCB_TEMPLATE_DEBUG ) || $args['nocache'];
$transient_tpls = 'tcb_cloud_templates_' . $this->tag() . '_tpls_from_lp_set_' . $pack;
$transient_packs = 'tcb_cloud_templates_' . $this->tag() . '_packs_from_lp_set_' . $pack;
$transient_categories = 'tcb_cloud_templates_' . $this->tag() . '_categories_from_lp_set_' . $pack;
$return['tpls'] = get_transient( $transient_tpls );
$return['packs'] = get_transient( $transient_packs );
$return['categories'] = get_transient( $transient_categories );
if ( $do_not_use_cache || empty( $return['tpls'] ) || empty( $return['packs'] ) || empty( $return['categories'] ) ) {
require_once plugin_dir_path( __DIR__ ) . 'content-templates/class-tcb-content-templates-api.php';
try {
$return = tcb_content_templates_api()->get_all( $this->tag(), [ 'pack' => $pack ] );
if ( is_wp_error( $return ) ) {
return new WP_Error( 'tcb_error', $return->getMessage(), 501 );
}
if ( is_array( $return ) && ! empty( $return['tpls'] ) && ! empty( $return['packs'] ) && ! empty( $return['categories'] ) ) {
set_transient( $transient_tpls, $return['tpls'], 8 * HOUR_IN_SECONDS );
set_transient( $transient_packs, $return['packs'], 8 * HOUR_IN_SECONDS );
set_transient( $transient_categories, $return['categories'], 8 * HOUR_IN_SECONDS );
}
} catch ( Exception $e ) {
return new WP_Error( 'tcb_error', $e->getMessage(), 501 );
}
}
return $return;
}
/**
* Return all combined blocks
*
* @param bool $nocache
*
* @return array
*/
public function get_blocks( $nocache = false ) {
$blocks = [
'packs' => [],
'tpls' => [],
];
$special_block_set = apply_filters( 'tcb_get_special_blocks_set', '' );
if ( ! empty( $special_block_set ) ) {
$special_blocks = $this->get_lp_cloud_templates( [
'nocache' => $nocache,
'lp_set' => $special_block_set,
] );
if ( ! empty( $special_blocks ) && is_array( $special_blocks ) && ! empty( $special_blocks['packs'] ) && ! empty( $special_blocks['tpls'] ) ) {
$blocks['packs'] = array_merge( $blocks['packs'], $special_blocks['packs'] );
$blocks['tpls'] = array_merge( $blocks['tpls'], $special_blocks['tpls'] );
}
}
$content_blocks = $this->get_all_contentblocks_templates( [
'nocache' => $nocache,
] );
if ( is_wp_error( $content_blocks ) ) {
return new WP_Error( 'tcb_api_error', $content_blocks->get_error_message() );
}
$blocks['tpls'] = array_merge( $blocks['tpls'], $content_blocks );
if ( empty( $blocks['packs'] ) ) {
$blocks['packs'][] = [ 'name' => 'Content Blocks' ];
}
return $blocks;
}
/**
* Returns all contentblocks templates
* Used for improved LP BLocks + Content Templates Lightbox
*
* @param array $args
*
* @return array|WP_Error
*/
public function get_all_contentblocks_templates( $args = [] ) {
$args = wp_parse_args( $args, [
'nocache' => false,
] );
$do_not_use_cache = ( defined( 'TCB_TEMPLATE_DEBUG' ) && TCB_TEMPLATE_DEBUG ) || $args['nocache'];
$templates_transient = 'tcb_cloud_templates_' . $this->tag() . '_all_templates';
$templates = get_transient( $templates_transient );
if ( $do_not_use_cache || empty( $templates ) ) {
require_once plugin_dir_path( __DIR__ ) . 'content-templates/class-tcb-content-templates-api.php';
try {
$templates = tcb_content_templates_api()->get_all( $this->tag(), [ 'pack' => 'tcb.get.all.c.blocks.templates' ] );
set_transient( $templates_transient, $templates, 8 * HOUR_IN_SECONDS );
} catch ( Exception $exception ) {
return new WP_Error( 'tcb_error', $exception->getMessage(), 501 );
}
}
return $templates;
}
/**
* Fetches a list of cloud templates for an element
*
* @param array $args allows controlling aspects of the method:
* $nocache - do not use caching (transients)
*
* @return array|WP_Error
* @deprecated available only for backwards compatible: people who have content blocks saved in the content
*/
public function get_cloud_templates( $args = [] ) {
$args = wp_parse_args( $args, [
'nocache' => false,
] );
$pack_id = isset( $_GET['pack'] ) ? sanitize_text_field( $_GET['pack'] ) : '';
$return = [];
$do_not_use_cache = ( defined( 'TCB_TEMPLATE_DEBUG' ) && TCB_TEMPLATE_DEBUG ) || $args['nocache'];
$transient_tpls = 'tcb_cloud_templates_' . $this->tag() . '_tpls_from_pack_' . ( ! empty( $pack_id ) ? $pack_id : '' );
$transient_packs = 'tcb_cloud_templates_' . $this->tag() . '_packs';
$transient_categories = 'tcb_cloud_templates_' . $this->tag() . '_categories';
$return['tpls'] = get_transient( $transient_tpls );
$return['packs'] = get_transient( $transient_packs );
$return['categories'] = get_transient( $transient_categories );
if ( $do_not_use_cache || empty( $return['tpls'] ) || empty( $return['packs'] ) || empty( $return['categories'] ) || empty( $pack_id ) ) {
require_once plugin_dir_path( __DIR__ ) . 'content-templates/class-tcb-content-templates-api.php';
try {
$return = tcb_content_templates_api()->get_all( $this->tag(), [ 'pack' => $pack_id ] );
if ( empty( $pack_id ) ) {
$transient_tpls .= $return['from_pack'];
$pack_id = $return['from_pack'];
}
set_transient( $transient_tpls, $return['tpls'], 8 * HOUR_IN_SECONDS );
set_transient( $transient_packs, $return['packs'], 8 * HOUR_IN_SECONDS );
set_transient( $transient_categories, $return['categories'], 8 * HOUR_IN_SECONDS );
} catch ( Exception $e ) {
return new WP_Error( 'tcb_error', $e->getMessage(), 501 );
}
}
/**
* Favorites Blocks
*/
$favorites = get_option( 'thrv_fav_content_blocks', [] );
foreach ( $return['tpls'] as $index => $tpl ) {
$return['tpls'][ $index ]['fav'] = (int) ( ! empty( $favorites[ $pack_id ] ) && is_array( $favorites[ $pack_id ] ) && in_array( $tpl['id'], $favorites[ $pack_id ] ) );
}
return $return;
}
/**
* Name of the element
*
* @return string
*/
public function name() {
return __( 'Content Block', 'thrive-cb' );
}
/**
* Get element alternate
*
* @return string
*/
public function alternate() {
return 'content block';
}
/**
* Return icon class needed for display in menu
*
* @return string
*/
public function icon() {
return 'content_block';
}
/**
* Element identifier
*
* @return string
*/
public function identifier() {
return '.thrv-content-block';
}
/**
* Element category that will be displayed in the sidebar
*
* @return string
*/
public function category() {
return self::get_thrive_advanced_label();
}
/**
* HTML layout of the element for when it's dragged in the canvas
*
* @return string
*/
protected function html() {
return tcb_template( 'elements/' . $this->tag() . '.php', $this, true );
}
/**
* Component and control config
*
* @return array
*/
public function own_components() {
$contentblock = array(
'contentblock' => array(
'config' => array(
'ModalPicker' => array(
'config' => array(
'label' => __( 'Template', 'thrive-cb' ),
),
),
),
),
);
return array_merge( $contentblock, $this->group_component() );
}
public function is_placeholder() {
return false;
}
}

Some files were not shown because too many files have changed in this diff Show More