File "spectra-pro-popup-builder.php"
Full path: C:/Inetpub/vhosts/drshti.com/httpdocs/wp-content/plugins/spectra-pro/includes/extensions/popup-builder/spectra-pro-popup-builder.php
File
size: 38.75 B (38.75 KB bytes)
MIME-type: text/x-php
Charset: utf-8
Download Open Edit Advanced Editor &nnbsp; Back
<?php
namespace SpectraPro\Includes\Extensions\PopupBuilder;
/**
* Pro Popup Builder Class.
*
* @package SpectraPro
*
* @since 1.0.0
*/
class Spectra_Pro_Popup_Builder {
/**
* Initializator.
*
* @return void
*
* @since 1.0.0
*/
public static function init() {
$self = new self();
add_action( 'register_spectra_pro_popup_meta', array( $self, 'register_pro_meta' ), 10, 0 );
add_action( 'spectra_pro_popup_dashboard', array( $self, 'add_pro_admin_scripts_and_ajax' ), 10, 0 );
add_filter( 'spectra_pro_admin_popup_list_titles', array( $self, 'add_pro_admin_list_titles' ), 10, 1 );
add_action( 'spectra_pro_admin_popup_list_content', array( $self, 'add_pro_admin_list_content' ), 10, 2 );
add_filter( 'spectra_pro_popup_frontend_js', array( $self, 'upgrade_frontend_js' ), 10, 5 );
add_filter( 'spectra_pro_popup_display_filters', array( $self, 'render_shortcode_conditionally' ), 10, 2 );
add_action( 'wp_ajax_spectra_popup_builder_get_posts_by_query', array( $self, 'spectra_popup_builder_get_posts_by_query' ) );
}
/**
* Get location selection options.
*
* @return array
*
* @since 1.0.0
*/
public static function get_location_selections() {
$args = array(
'public' => true,
'_builtin' => true,
);
/**
* Post Types will always be of type WP_Post_Type[] instead of string[].
* Since we're passing param 2 as 'objects' instead of 'names'.
*
* @var \WP_Post_Type[] $post_types An array of all Inbuilt Post Types.
*/
$post_types = get_post_types( $args, 'objects' );
unset( $post_types['attachment'] );
$args['_builtin'] = false;
/**
* Post Types will always be of type WP_Post_Type[] instead of string[].
* Since we're passing param 2 as 'objects' instead of 'names'.
*
* @var \WP_Post_Type[] $custom_post_type An array of all Custom Post Types.
*/
$custom_post_type = get_post_types( $args, 'objects' );
$post_types = array_merge( $post_types, $custom_post_type );
$special_pages = array(
'special-404' => __( '404 Page', 'spectra-pro' ),
'special-search' => __( 'Search Page', 'spectra-pro' ),
'special-blog' => __( 'Blog / Posts Page', 'spectra-pro' ),
'special-front' => __( 'Front Page', 'spectra-pro' ),
'special-date' => __( 'Date Archive', 'spectra-pro' ),
'special-author' => __( 'Author Archive', 'spectra-pro' ),
);
if ( class_exists( 'WooCommerce' ) ) {
$special_pages['special-woo-shop'] = __( 'WooCommerce Shop Page', 'spectra-pro' );
}
$selection_options = array(
'basic' => array(
'label' => __( 'Basic', 'spectra-pro' ),
'value' => array(
'basic-singulars' => __( 'All Singulars', 'spectra-pro' ),
'basic-archives' => __( 'All Archives', 'spectra-pro' ),
),
),
'special-pages' => array(
'label' => __( 'Special Pages', 'spectra-pro' ),
'value' => $special_pages,
),
);
$args = array(
'public' => true,
);
/**
* Taxonomies will always be of type WP_Taxonomy[] instead of string[].
* Since we're passing param 2 as 'objects' instead of 'names'.
*
* @var \WP_Taxonomy[] $taxonomies An array of all taxonomies.
*/
$taxonomies = get_taxonomies( $args, 'objects' );
if ( ! empty( $taxonomies ) ) {
foreach ( $taxonomies as $taxonomy ) {
// skip post format taxonomy.
if ( 'post_format' === $taxonomy->name ) {
continue;
}
foreach ( $post_types as $post_type ) {
$post_opt = self::get_post_target_rule_options( $post_type, $taxonomy );
if ( isset( $selection_options[ $post_opt['post_key'] ] ) ) {
if ( ! empty( $post_opt['value'] ) && is_array( $post_opt['value'] ) ) {
foreach ( $post_opt['value'] as $key => $value ) {
if ( ! in_array( $value, $selection_options[ $post_opt['post_key'] ]['value'], true ) ) {
$selection_options[ $post_opt['post_key'] ]['value'][ $key ] = $value;
}
}
}
} else {
$selection_options[ $post_opt['post_key'] ] = array(
'label' => $post_opt['label'],
'value' => $post_opt['value'],
);
}
}//end foreach
}//end foreach
}//end if
$selection_options['specific-target'] = array(
'label' => __( 'Specific Target', 'spectra-pro' ),
'value' => array(
'specifics' => __( 'Specific Pages / Posts / CPTs', 'spectra-pro' ),
),
);
return $selection_options;
}
/**
* Get target rules for generating the markup for rule selector.
*
* @param \WP_Post_Type $post_type Post type parameter.
* @param \WP_Taxonomy $taxonomy Taxonomy for creating the target rule markup.
* @return array The post output.
*
* @since 1.0.0
*/
public static function get_post_target_rule_options( $post_type, $taxonomy ) {
$post_key = str_replace( ' ', '-', strtolower( $post_type->label ) );
$post_label = ucwords( $post_type->label );
$post_name = $post_type->name;
$post_option = array();
/* translators: %s post label */
$all_posts = sprintf( __( 'All %s', 'spectra-pro' ), $post_label );
$post_option[ $post_name . '|all' ] = $all_posts;
if ( 'pages' !== $post_key ) {
/* translators: %s post label */
$all_archive = sprintf( __( 'All %s Archive', 'spectra-pro' ), $post_label );
$post_option[ $post_name . '|all|archive' ] = $all_archive;
}
if ( in_array( $post_type->name, $taxonomy->object_type, true ) ) {
$tax_label = ucwords( $taxonomy->label );
$tax_name = $taxonomy->name;
/* translators: %s taxonomy label */
$tax_archive = sprintf( __( 'All %s Archive', 'spectra-pro' ), $tax_label );
$post_option[ $post_name . '|all|taxarchive|' . $tax_name ] = $tax_archive;
}
$post_output['post_key'] = $post_key;
$post_output['label'] = $post_label;
$post_output['value'] = $post_option;
return $post_output;
}
/**
* Register the Pro Meta Tags for the Spectra Popup Post Type.
*
* @return void
*
* @since 1.0.0
*/
public function register_pro_meta() {
$meta_args_popup_trigger = array(
'single' => true,
'type' => 'string',
'default' => 'load',
'auth_callback' => '__return_true',
'show_in_rest' => true,
);
$meta_args_popup_trigger_delay = array(
'single' => true,
'type' => 'integer',
'default' => 0,
'auth_callback' => '__return_true',
'show_in_rest' => true,
);
$meta_args_popup_display_inclusions = array(
'single' => true,
'type' => 'object',
'default' => array(
'rule' => array(),
'specific' => array(),
'specificText' => array(),
),
'auth_callback' => '__return_true',
'show_in_rest' => array(
'schema' => array(
'type' => 'object',
'properties' => array(
'rule' => array(
'type' => 'array',
),
'specific' => array(
'type' => 'array',
),
'specificText' => array(
'type' => 'array',
),
),
),
),
);
$meta_args_popup_display_exclusions = array(
'single' => true,
'type' => 'object',
'default' => array(
'rule' => array(),
'specific' => array(),
'specificText' => array(),
),
'auth_callback' => '__return_true',
'show_in_rest' => array(
'schema' => array(
'type' => 'object',
'properties' => array(
'rule' => array(
'type' => 'array',
),
'specific' => array(
'type' => 'array',
),
'specificText' => array(
'type' => 'array',
),
),
),
),
);
register_post_meta( 'spectra-popup', 'spectra-popup-trigger', $meta_args_popup_trigger );
register_post_meta( 'spectra-popup', 'spectra-popup-trigger-delay', $meta_args_popup_trigger_delay );
register_post_meta( 'spectra-popup', 'spectra-popup-display-inclusions', $meta_args_popup_display_inclusions );
register_post_meta( 'spectra-popup', 'spectra-popup-display-exclusions', $meta_args_popup_display_exclusions );
}
/**
* Add the Pro Popup Admin Scripts and Ajax only if the current page is the Popup Admin Page.
*
* @since 1.0.2
* @return void
*/
public function add_pro_admin_scripts_and_ajax() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_pro_admin_scripts' ) );
add_action( 'admin_footer', array( $this, 'add_pro_admin_footer_scripts' ) );
add_action( 'wp_ajax_uag_trigger_popup_quickview', array( $this, 'get_quickview_details' ) );
}
/**
* Check if the current page is the Popup Admin Page.
*
* @since 1.0.2
* @return boolean
*/
private function is_this_the_popup_admin() {
global $pagenow;
$screen = get_current_screen();
// If the current screen exists, return the result of the comparison, else return false.
return $screen ? ( 'spectra-popup' === $screen->post_type && 'edit.php' === $pagenow ) : false;
}
/**
* Enqueue the Pro Popup Admin Scripts.
*
* @since 1.0.2
* @return void
*/
public function enqueue_pro_admin_scripts() {
if ( ! $this->is_this_the_popup_admin() ) {
return;
}
$extension = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
wp_register_script(
'spectra-pro-popup-builder-admin-js',
SPECTRA_PRO_URL . 'assets/js/spectra-pro-popup-builder-admin' . $extension . '.js',
array(),
SPECTRA_PRO_VER,
false
);
wp_register_style(
'spectra-pro-popup-builder-admin',
SPECTRA_PRO_URL . 'assets/css/spectra-pro-popup-builder-admin' . $extension . '.css',
array(),
SPECTRA_PRO_VER
);
wp_localize_script(
'spectra-pro-popup-builder-admin-js',
'spectra_pro_popup_builder_admin',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'spectra_pro_popup_builder_admin_nonce' => wp_create_nonce( 'spectra_pro_popup_builder_admin_nonce' ),
)
);
wp_enqueue_script( 'spectra-pro-popup-builder-admin-js' );
wp_enqueue_style( 'spectra-pro-popup-builder-admin' );
}
/**
* Get the current Popup's QuickView Details from the Admin Table.
*
* @since 1.0.2
* @return void
*/
public function get_quickview_details() {
check_ajax_referer( 'spectra_pro_popup_builder_admin_nonce', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error();
}
if ( ! isset( $_POST['popup_id'] ) ) {
wp_send_json_error();
}
// Format the Popup's ID.
$formatted_post_id = absint( $_POST['popup_id'] );
// Get the Popup's Type and Display Rules.
$popup_type = get_post_meta( $formatted_post_id, 'spectra-popup-type', true );
$popup_inclusion_ruleset = get_post_meta( $formatted_post_id, 'spectra-popup-display-inclusions', true );
$popup_exclusion_ruleset = get_post_meta( $formatted_post_id, 'spectra-popup-display-exclusions', true );
// If the inclusion or exclusion rules are not set, set them to an empty array.
if ( ! is_array( $popup_inclusion_ruleset ) ) {
$popup_inclusion_ruleset = array();
}
if ( ! is_array( $popup_exclusion_ruleset ) ) {
$popup_exclusion_ruleset = array();
}
// Get the Popup's Edit Label.
switch ( $popup_type ) {
case 'banner':
$edit_label = __( 'Edit Info Bar', 'spectra-pro' );
break;
case 'popup':
$edit_label = __( 'Edit Popup', 'spectra-pro' );
break;
default:
$edit_label = __( 'Edit', 'spectra-pro' );
}
// Set the required data.
$required_data = array(
'name' => get_the_title( $formatted_post_id ),
'type' => $popup_type,
'inclusions' => $this->get_display_condition_ruleset_labels( $popup_inclusion_ruleset ),
'exclusions' => $this->get_display_condition_ruleset_labels( $popup_exclusion_ruleset ),
'status' => get_post_status( $formatted_post_id ),
'date' => get_the_date( 'F j, Y', $formatted_post_id ),
'edit' => get_edit_post_link( $formatted_post_id ),
'editLabel' => $edit_label,
);
wp_send_json_success( $required_data );
}
/**
* Enqueue the Pro Popup Admin Footer Scripts.
*
* @since 1.0.2
* @return void
*/
public function add_pro_admin_footer_scripts() {
if ( ! $this->is_this_the_popup_admin() ) {
return;
}
// Add the popup builder admin modal.
?>
<div class="spectra-popup-builder__modal--overlay" data-popup-id="0">
<div class="spectra-popup-builder__modal">
<div class="spectra-popup-builder__modal--header spectra-popup-builder__modal--padded">
<h2 class="spectra-popup-builder__modal--title"></h2>
<div class="spectra-popup-builder__modal--type"></div>
</div>
<div class="spectra-popup-builder__modal--body">
<div class="spectra-popup-builder__modal--padded"><?php echo esc_html__( 'Display On:', 'spectra-pro' ); ?></div>
<div class="spectra-popup-builder__modal--body-inclusions spectra-popup-builder__modal--padded"></div>
<div class="spectra-popup-builder__modal--padded"><?php echo esc_html__( 'Do Not Display On:', 'spectra-pro' ); ?></div>
<div class="spectra-popup-builder__modal--body-exclusions spectra-popup-builder__modal--padded"></div>
</div>
<div class="spectra-popup-builder__modal--footer spectra-popup-builder__modal--padded">
<div class="spectra-popup-builder__modal--footer-details">
<b><?php echo esc_html__( 'Status:', 'spectra-pro' ); ?></b> <span class="spectra-popup-builder__modal--status"></span><b> | <?php echo esc_html__( 'Created:', 'spectra-pro' ); ?></b> <span class="spectra-popup-builder__modal--date"></span>
</div>
<a href="javascript:void(0)" class="spectra-popup-builder__modal--edit button button-primary">
<?php echo esc_html__( 'Edit', 'spectra-pro' ); ?>
</a>
</div>
<button class="spectra-popup-builder__modal--close">
<span class="dashicons dashicons-no-alt"></span>
</button>
</div>
</div>
<?php
}
/**
* Get the Popup's Display Condition Labels.
*
* @param array $display_condition The Current Display Condition.
* @since 1.0.2
* @return array The Display Condition Labels, if any.
*/
private function get_display_condition_ruleset_labels( $display_condition ) {
// If the display condition is not an array, return an empty array.
if ( ! is_array( $display_condition['rule'] ) ) {
return array();
}
$display_condition_labels = array();
// Loop through the display condition rules and add the labels to the array.
foreach ( $display_condition['rule'] as $rule ) {
if ( ! empty( $rule['label'] ) && 'specifics' !== $rule['value'] ) {
array_push( $display_condition_labels, $rule['label'] );
}
}
// If the display condition specifics is not an array, return the existing labels.
if ( ! is_array( $display_condition['specificText'] ) ) {
return $display_condition_labels;
}
// Loop through the display condition specifics and add the labels to the array.
foreach ( $display_condition['specificText'] as $specific ) {
if ( ! empty( $specific['label'] ) ) {
array_push( $display_condition_labels, $specific['label'] );
}
}
return $display_condition_labels;
}
/**
* Add Pro Columns to the Popup Builder Admin Post List.
*
* @param array $columns The current popup list columns.
* @return array The updated columns.
*
* @since 1.0.0
*/
public function add_pro_admin_list_titles( $columns ) {
if ( is_array( $columns ) ) {
$columns['spectra_popup_trigger'] = __( 'Trigger', 'spectra-pro' );
unset( $columns['spectra_popup_type'] );
$columns['spectra_popup_details'] = __( 'Quick View', 'spectra-pro' );
}
return $columns;
}
/**
* Add Pro Column Content to the Popup Builder Admin Post List.
*
* @param string $column Name of the current column.
* @param int $post_id Current Post ID.
* @return void
*
* @since 1.0.0
*/
public function add_pro_admin_list_content( $column, $post_id ) {
if ( ! is_int( $post_id ) ) {
return;
}
switch ( $column ) {
case 'spectra_popup_trigger':
$trigger = get_post_meta( $post_id, 'spectra-popup-trigger', true );
if ( ! is_string( $trigger ) ) {
break;
}
switch ( $trigger ) {
case 'load':
$trigger_delay = get_post_meta( $post_id, 'spectra-popup-trigger-delay', true );
if ( is_numeric( $trigger_delay ) && $trigger_delay > 0 ) {
echo sprintf(
/* translators: %1$s break tag and opening emphasis tag, %2$s number of seconds, %3$s singular or plural form of second, %4%s closing emphasis tag */
esc_html__( 'On Load%1$sAfter %2$s %3$s%4$s', 'spectra-pro' ),
'<br/><em>',
esc_attr( strval( $trigger_delay ) ),
esc_html( _n( 'Second', 'Seconds', intval( $trigger_delay ), 'spectra-pro' ) ),
'</em>'
);
} else {
echo esc_html__( 'On Load', 'spectra-pro' );
}
break;
case 'exit':
echo esc_html__( 'Exit Intent', 'spectra-pro' );
break;
case 'element':
echo esc_html__( 'Custom Element', 'spectra-pro' );
echo '<br/><em>spectra-popup-trigger-' . esc_attr( strval( $post_id ) ) . '</em>';
break;
}//end switch
break;
case 'spectra_popup_details':
echo '<button class="spectra-popup-builder__button" data-popup_id="' . esc_attr( strval( $post_id ) ) . '"><span class="dashicons dashicons-visibility"></span></button>';
break;
default:
break;
}//end switch
}
/**
* Check whether to render this popup or not based on Pro Display Conditions.
*
* Note:
* Popups can be included in a general post type AND be excluded specifically.
*
* @param bool $render_status The current render status of this popup based on whether it is enabled.
* @param int $post_id The current post ID to render this popup on.
* @return bool Whether to render this popup on this post or not.
*
* @since 1.0.0
*/
public function render_shortcode_conditionally( $render_status, $post_id ) {
// If this popup is not enabled, exit directly.
if ( ! $render_status ) {
return $render_status;
}
// Return early if unable to get the popup ID.
$popup_id = get_the_ID();
if ( false === $popup_id ) {
return $render_status;
}
// Get the display inclusion meta, return if it's not defined.
$include_on = get_post_meta( $popup_id, 'spectra-popup-display-inclusions', true );
if ( ! is_array( $include_on ) ) {
return $render_status;
}
// Get the display exclusion meta, return if it's not defined.
$exclude_on = get_post_meta( $popup_id, 'spectra-popup-display-exclusions', true );
if ( ! is_array( $exclude_on ) ) {
return $render_status;
}
// Parse the exclusion rules to check if this popup is excluded from the current post (generally or specifically).
$is_excluded = $this->parse_popup_display_condition( $post_id, $exclude_on );
// Exit Early - Don't render this popup if it's excluded.
if ( $is_excluded ) {
return false;
}
// Parse the inclusion rules to check if this popup is included on the current post (generally or specifically).
$is_included = $this->parse_popup_display_condition( $post_id, $include_on );
if ( $is_included ) {
return true;
}
// If this popup had implicit include rules, don't render it - else render it.
return empty( $include_on['rule'] );
}
/**
* Parse the generic / specific rules for exclusion / inclusion of this popup.
*
* @param int $post_id The current post ID to render this popup on.
* @param array $rules Array of rules for the inclusion / exclusion meta.
* @return boolean Whether or not the current meta rules match for the current page and popup.
*
* @since 1.0.0
*/
public function parse_popup_display_condition( $post_id, $rules ) {
if ( empty( $rules['rule'] ) ) {
return false;
}
$is_in_rule = false;
$current_post_type = get_post_type( $post_id );
foreach ( $rules['rule'] as $key => $rule ) {
if ( empty( $rule ) ) {
continue;
}
if ( is_array( $rule ) && isset( $rule['value'] ) ) {
$rule = $rule['value'];
}
$rule_case = ( strrpos( $rule, 'all' ) !== false ) ? 'all' : $rule;
switch ( $rule_case ) {
// If 'Basic --> All Singulars' is selected.
case 'basic-singulars':
if ( is_singular() ) {
$is_in_rule = true;
}
break;
// If 'Basic --> All Archives' is selected.
case 'basic-archives':
if ( is_archive() ) {
$is_in_rule = true;
}
break;
// If 'Special Pages --> 404 Page' is selected.
case 'special-404':
if ( is_404() ) {
$is_in_rule = true;
}
break;
// If 'Special Pages --> Search Page' is selected.
case 'special-search':
if ( is_search() ) {
$is_in_rule = true;
}
break;
// If 'Special Pages --> Blog / Post Page' is selected.
case 'special-blog':
if ( is_home() ) {
$is_in_rule = true;
}
break;
// If 'Special Pages --> Front Page' is selected.
case 'special-front':
if ( is_front_page() ) {
$is_in_rule = true;
}
break;
// If 'Special Pages --> Date Archive' is selected.
case 'special-date':
if ( is_date() ) {
$is_in_rule = true;
}
break;
// If 'Special Pages --> Author Archive' is selected.
case 'special-author':
if ( is_author() ) {
$is_in_rule = true;
}
break;
// If 'Special Pages --> WooCommerce Shop Page' is selected.
case 'special-woo-shop':
if ( function_exists( 'is_shop' ) && is_shop() ) {
$is_in_rule = true;
}
break;
// If '[postTypes] --> All [postTypes|taxonomy|archive|etc]' is selected.
case 'all':
// First split apart the rule to determine the depth of this rule.
$rule_data = explode( '|', $rule );
// Then set the depth to check if this page needs this popup.
// The depth is as follows: postType | 'all' | archiveType | taxonomy.
$rule_post_type = isset( $rule_data[0] ) ? $rule_data[0] : false;
$rule_archive_type = isset( $rule_data[2] ) ? $rule_data[2] : false;
$rule_taxonomy = isset( $rule_data[3] ) ? $rule_data[3] : false;
// Check if this rule was not for an archive type.
if ( false === $rule_archive_type ) {
// Since this is not an archive type, check if the post ID is valid and the rule matches the current post type.
if ( $post_id && $current_post_type === $rule_post_type ) {
$is_in_rule = true;
}
break;
}
// Check if the current page is not an archive.
if ( is_archive() ) {
break;
}
// Since this is an archive, get the post type without an ID.
$current_post_type = get_post_type();
// Check if the current post type is not the post type in the rule.
if ( $current_post_type !== $rule_post_type ) {
break;
}
// Check what kind of archive this is.
switch ( $rule_archive_type ) {
case 'archive':
$is_in_rule = true;
break;
case 'taxarchive':
$current_query_obj = get_queried_object();
if ( null === $current_query_obj || ! isset( $current_query_obj->taxonomy ) ) {
break;
}
$current_taxonomy = $current_query_obj->taxonomy;
if ( $current_taxonomy === $rule_taxonomy ) {
$is_in_rule = true;
}
break;
}
break;
// If 'Specific Target --> Specific Pages / Posts / Taxonomies' is selected.
case 'specifics':
// Continue only if this rule has a list of speficic targets.
if ( ! isset( $rules['specific'] ) || ! is_array( $rules['specific'] ) ) {
break;
}
foreach ( $rules['specific'] as $specific_page ) {
$specific_data = explode( '-', $specific_page );
$specific_post_type = isset( $specific_data[0] ) ? $specific_data[0] : false;
$specific_post_id = isset( $specific_data[1] ) ? (int) $specific_data[1] : 0;
$specific_single = isset( $specific_data[2] ) ? $specific_data[2] : false;
// Check what kind of post this is.
switch ( $specific_post_type ) {
case 'post':
if ( $specific_post_id === $post_id ) {
$is_in_rule = true;
}
break;
case 'tax':
if ( 'single' === $specific_single && is_singular() ) {
$term_details = get_term( $specific_post_id );
if ( isset( $term_details->taxonomy ) ) {
$has_term = has_term( $specific_post_id, $term_details->taxonomy, $post_id );
if ( $has_term ) {
$is_in_rule = true;
}
}
} else {
$tax_id = get_queried_object_id();
if ( $specific_post_id === $tax_id ) {
$is_in_rule = true;
}
}
break;
}//end switch
}//end foreach
break;
}//end switch
if ( $is_in_rule ) {
break;
}
}//end foreach
return $is_in_rule;
}
/**
* Ajax handeler to return the posts based on the search query.
*
* @return void
*
* @since 1.0.0
*/
public function spectra_popup_builder_get_posts_by_query() {
check_ajax_referer( 'spectra_pro_ajax_nonce', 'nonce' );
$search_string = isset( $_POST['search'] ) ? sanitize_text_field( $_POST['search'] ) : '';
$data = array();
$result = array();
$args = array(
'public' => true,
'_builtin' => false,
);
$post_types = get_post_types( $args );
$post_types['Posts'] = 'post';
$post_types['Pages'] = 'page';
foreach ( $post_types as $key => $post_type ) {
$data = array();
add_filter( 'posts_search', array( $this, 'search_only_titles' ), 10, 2 );
$query = new \WP_Query(
array(
's' => $search_string,
'post_type' => $post_type,
'posts_per_page' => -1,
)
);
while ( $query->have_posts() ) :
$query->the_post();
$title = get_the_title();
$title .= ( $query->post && ( 0 !== $query->post->post_parent ) ) ? ' (' . get_the_title( $query->post->post_parent ) . ')' : '';
$id = get_the_id();
array_push(
$data,
array(
'id' => 'post-' . $id,
'title' => $title,
)
);
endwhile;
if ( ! empty( $data ) ) {
array_push(
$result,
array(
'title' => $key,
'children' => $data,
)
);
}
}//end foreach
// return the result in json.
wp_send_json_success( $result );
}
/**
* Return search results only by post title.
*
* @param string $search Search SQL for WHERE clause.
* @param \WP_Query $wp_query The current WP_Query object.
* @return string The Modified Search SQL for WHERE clause.
*
* @since 1.0.0
*/
public function search_only_titles( $search, $wp_query ) {
if ( empty( $search ) || empty( $wp_query->query_vars['search_terms'] ) ) {
return $search;
}
global $wpdb;
$query_vars = $wp_query->query_vars;
if ( ! is_array( $query_vars ) ) {
return $search;
}
$match_helper = empty( $query_vars['exact'] ) ? '%' : '';
$search = array();
foreach ( $query_vars['search_terms'] as $term ) {
$search[] = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $match_helper . $wpdb->esc_like( $term ) . $match_helper );
}
$search = ' AND ' . implode( ' AND ', $search );
return $search;
}
/**
* Add Pro Meta Based Conditions to JS Popup Builder Block.
*
* @param string $js The current block JS script.
* @param int $id The current block ID.
* @param array $attr The current block attributes.
* @param bool $is_push_banner A boolean stating if this is a push banner or not.
* @param int $popup_timer The timer of the current popup based on if it's a push banner.
* @return string The upgraded JS script or the Default JS Script.
*
* @since 1.0.0
*/
public function upgrade_frontend_js( $js, $id, $attr, $is_push_banner, $popup_timer ) {
$popup_id = get_the_ID();
if ( ! $popup_id ) {
return $js;
}
$trigger = get_post_meta( $popup_id, 'spectra-popup-trigger', true );
if ( ! is_string( $trigger ) ) {
return $js;
}
$trigger_delay = get_post_meta( $popup_id, 'spectra-popup-trigger-delay', true );
if ( ! $trigger_delay ) {
$trigger_delay = 0;
}
// Convert the Seconds to Milliseconds.
$trigger_delay *= 1000;
ob_start();
switch ( $trigger ) {
case 'load':
?>
window.addEventListener( 'DOMContentLoaded', () => {
const blockScope = document.querySelector( '.uagb-block-<?php echo esc_attr( strval( $id ) ); ?>' );
if ( ! blockScope ) {
return;
}
<?php
// The front-end JS common responsive code snippet cannot be escaped.
echo $this->frontend_js_responsive_snippet(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
<?php
// The front-end JS common repetition code snippet cannot be escaped.
echo $this->frontend_js_repetition_snippet( $popup_id ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
const theBody = document.querySelector( 'body' );
setTimeout( () => {
blockScope.style.display = 'flex';
}, <?php echo intval( $trigger_delay ); ?> );
setTimeout( () => {
<?php
// The front-end JS common load code snippet cannot be escaped.
echo $this->frontend_js_load_snippet( $attr, $is_push_banner ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
}, <?php echo intval( $trigger_delay ) + 100; ?> );
<?php
// The front-end JS common close code snippet cannot be escaped.
echo $this->frontend_js_close_snippet( $attr, $popup_id, true, $is_push_banner, $popup_timer, $trigger_delay ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
} );
<?php
break;
case 'exit':
?>
window.addEventListener( 'DOMContentLoaded', () => {
const exitIntent = ( event ) => {
if ( ! event.toElement && ! event.relatedTarget ) {
document.removeEventListener( 'mouseout', exitIntent );
const blockScope = document.querySelector( '.uagb-block-<?php echo esc_attr( strval( $id ) ); ?>' );
if ( ! blockScope ) {
return;
}
<?php
// The front-end JS common responsive code snippet cannot be escaped.
echo $this->frontend_js_responsive_snippet(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
<?php
// The front-end JS common repetition code snippet cannot be escaped.
echo $this->frontend_js_repetition_snippet( $popup_id ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
const theBody = document.querySelector( 'body' );
blockScope.style.display = 'flex';
setTimeout( () => {
<?php
// The front-end JS common load code snippet cannot be escaped.
echo $this->frontend_js_load_snippet( $attr, $is_push_banner ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
}, 100 );
<?php
// The front-end JS common close code snippet cannot be escaped.
echo $this->frontend_js_close_snippet( $attr, $popup_id, true, $is_push_banner, $popup_timer, 0 ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
}
}
document.addEventListener( 'mouseout', exitIntent );
} );
<?php
break;
case 'element':
?>
window.addEventListener( 'DOMContentLoaded', () => {
const popupTriggers = document.querySelectorAll( '.spectra-popup-trigger-<?php echo esc_attr( strval( $popup_id ) ); ?>' );
for ( let i = 0; i < popupTriggers.length; i++ ) {
popupTriggers[ i ].style.cursor = 'pointer';
popupTriggers[ i ].addEventListener( 'click', () => {
const blockScope = document.querySelector( '.uagb-block-<?php echo esc_attr( strval( $id ) ); ?>' );
if ( ! blockScope ) {
return;
}
<?php
// The front-end JS common responsive code snippet cannot be escaped.
echo $this->frontend_js_responsive_snippet(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
const theBody = document.querySelector( 'body' );
blockScope.style.display = 'flex';
setTimeout( () => {
<?php
// The front-end JS common load code snippet cannot be escaped.
echo $this->frontend_js_load_snippet( $attr, $is_push_banner ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
}, 100 );
<?php
// The front-end JS common close code snippet cannot be escaped.
echo $this->frontend_js_close_snippet( $attr, $popup_id, false, $is_push_banner, $popup_timer, 0 ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
} );
}
} );
<?php
break;
default:
// The block of JS code sent to this acction cannot be escaped.
echo $js; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
break;
}//end switch
$updated_js = ob_get_clean();
return is_string( $updated_js ) ? $updated_js : $js;
}
/**
* Snippet of the responsive handling for all pro JS renders.
*
* @return string The output buffer.
*
* @since 1.0.0
*/
private function frontend_js_responsive_snippet() {
ob_start();
?>
const deviceWidth = ( window.innerWidth > 0 ) ? window.innerWidth : screen.width;
if ( blockScope.classList.contains( 'uag-hide-desktop' ) && deviceWidth > 1024 ) {
blockScope.remove();
return;
} else if ( blockScope.classList.contains( 'uag-hide-tab' ) && ( deviceWidth <= 1024 && deviceWidth > 768 ) ) {
blockScope.remove();
return;
} else if ( blockScope.classList.contains( 'uag-hide-mob' ) && deviceWidth <= 768 ) {
blockScope.remove();
return;
}
<?php
$output = ob_get_clean();
return is_string( $output ) ? $output : '';
}
/**
* Snippet of common repetition JS code.
*
* @param int $popup_id The popup ID.
* @return string The output buffer.
*
* @since 1.0.0
*/
private function frontend_js_repetition_snippet( $popup_id ) {
// Either check if the localStorage has been set before - If not, create it.
// Or if this popup has an updated repetition number, reset the localStorage.
$repetition = get_post_meta( $popup_id, 'spectra-popup-repetition', true );
if ( ! is_numeric( $repetition ) ) {
return '';
}
ob_start();
?>
let popupSesh = JSON.parse( localStorage.getItem( 'spectraPopup<?php echo esc_attr( strval( $popup_id ) ); ?>' ) );
const repetition = <?php echo intval( $repetition ); ?>;
if ( null === popupSesh || repetition !== popupSesh[1] ) {
<?php // [0] is the updating repetition number, [1] is the original repetition number. ?>
const repetitionArray = [
repetition,
repetition,
];
localStorage.setItem( 'spectraPopup<?php echo esc_attr( strval( $popup_id ) ); ?>', JSON.stringify( repetitionArray ) );
popupSesh = JSON.parse( localStorage.getItem( 'spectraPopup<?php echo esc_attr( strval( $popup_id ) ); ?>' ) );
}
if ( 0 === popupSesh[0] ) {
blockScope.remove();
return;
}
<?php
$output = ob_get_clean();
return is_string( $output ) ? $output : '';
}
/**
* Snippet of common close JS function and calls required for all popups.
*
* @param array $attr The array of block attributes.
* @param int $popup_id The popup ID.
* @param bool $delete Determines whether or not the popup should be deleted when closed.
* @param bool $is_push_banner A boolean stating if this is a push banner or not.
* @param int $popup_timer The timer of the current popup based on if it's a push banner.
* @param int $trigger_delay The delay for on load popups, or zero for other popups.
* @return string The output buffer.
*
* @since 1.0.0
*/
private function frontend_js_close_snippet( $attr, $popup_id, $delete, $is_push_banner, $popup_timer, $trigger_delay ) {
ob_start();
// If this is a banner with push, Add the unset bezier curve after animating.
if ( $is_push_banner ) :
?>
setTimeout( () => {
blockScope.style.transition = 'max-height 0.5s cubic-bezier(0, 1, 0, 1)';
}, <?php echo intval( $trigger_delay ) + 600; ?> );
<?php endif; ?>
const closePopup = ( event = null ) => {
if ( event && blockScope !== event.target ) {
return;
}
<?php
// If this is a banner with push, render the required animation instead of opacity.
if ( $is_push_banner ) :
?>
blockScope.style.maxHeight = '';
<?php else : ?>
blockScope.style.opacity = 0;
<?php endif; ?>
setTimeout( () => {
<?php
// If this is a banner with push, remove the unset bezier curve.
if ( $is_push_banner ) :
?>
blockScope.style.transition = '';
<?php endif; ?>
<?php if ( $delete ) : ?>
if ( popupSesh[0] > 0 ) {
popupSesh[0] -= 1;
localStorage.setItem( 'spectraPopup<?php echo esc_attr( strval( $popup_id ) ); ?>', JSON.stringify( popupSesh ) );
}
blockScope.remove();
<?php else : ?>
blockScope.style.display = 'none';
blockScope.classList.remove( 'spectra-popup--open' );
<?php endif; ?>
const allActivePopups = document.querySelectorAll( '.uagb-popup-builder.spectra-popup--open' );
if ( 0 === allActivePopups.length ) {
theBody.classList.remove( 'uagb-popup-builder__body--overflow-hidden' );
}
}, <?php echo intval( $popup_timer ); ?> );
};
<?php
if ( $attr['isDismissable'] ) :
if ( $attr['hasOverlay'] && $attr['closeOverlayClick'] ) :
?>
blockScope.addEventListener( 'click', ( event ) => closePopup( event ) );
<?php
endif;
if ( $attr['closeIcon'] ) :
?>
const closeButton = blockScope.querySelector( '.uagb-popup-builder__close' );
closeButton.style.cursor = 'pointer';
closeButton.addEventListener( 'click', () => closePopup() );
<?php
endif;
endif;
?>
const closingElements = blockScope.querySelectorAll( '.spectra-popup-close-<?php echo esc_attr( strval( $popup_id ) ); ?>' );
for ( let i = 0; i < closingElements.length; i++ ) {
closingElements[ i ].style.cursor = 'pointer';
closingElements[ i ].addEventListener( 'click', () => closePopup() );
}
<?php
$output = ob_get_clean();
return is_string( $output ) ? $output : '';
}
/**
* Snippet of common scrollbar hide and push banner JS code on load.
*
* @param array $attr The array of block attributes.
* @param bool $is_push_banner A boolean stating if this is a push banner or not.
* @since 1.0.1
* @return string The output buffer.
*/
private function frontend_js_load_snippet( $attr, $is_push_banner ) {
ob_start();
// If this is a banner with push, render the max height instead of opacity on timeout.
if ( $is_push_banner ) {
?>
blockScope.style.maxHeight = '100vh';
<?php
} else {
// If this is a popup which prevent background interaction, hide the scrollbar.
if ( 'popup' === $attr['variantType'] && $attr['haltBackgroundInteraction'] ) :
?>
theBody.classList.add( 'uagb-popup-builder__body--overflow-hidden' );
blockScope.classList.add( 'spectra-popup--open' );
<?php endif; ?>
blockScope.style.opacity = 1;
<?php
}
$output = ob_get_clean();
return is_string( $output ) ? $output : '';
}
}