version 4.13.0

This commit is contained in:
2021-12-07 11:08:05 +00:00
commit cb26d2c0c4
1285 changed files with 254735 additions and 0 deletions

View File

@ -0,0 +1,50 @@
<?php
/**
* Author Condition's logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Author Condition Trait
*/
trait AuthorCondition {
/**
* Processes "Author" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all condition settings.
*
* @return boolean Condition output.
*/
protected function _process_author_condition( $condition_settings ) {
// Only check for Posts.
if ( ! is_singular() ) {
return false;
}
$display_rule = isset( $condition_settings['authorDisplay'] ) ? $condition_settings['authorDisplay'] : '';
$authors_raw = isset( $condition_settings['authors'] ) ? $condition_settings['authors'] : [];
$authors_ids = array_map(
function( $item ) {
return $item['value'];
},
$authors_raw
);
$is_on_shop_page = class_exists( 'WooCommerce' ) && is_shop();
$queried_object_id = $is_on_shop_page ? wc_get_page_id( 'shop' ) : get_queried_object_id();
$current_post_author_id = get_post_field( 'post_author', (int) $queried_object_id );
$should_display = array_intersect( $authors_ids, (array) $current_post_author_id ) ? true : false;
return ( 'is' === $display_rule ) ? $should_display : ! $should_display;
}
}

View File

@ -0,0 +1,76 @@
<?php
/**
* Browser condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Browser Condition Trait.
*/
trait BrowserCondition {
/**
* Processes "Operating System" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_browser_condition( $condition_settings ) {
$display_rule = isset( $condition_settings['browserDisplay'] ) ? $condition_settings['browserDisplay'] : 'is';
$browsers_raw = isset( $condition_settings['browsers'] ) ? $condition_settings['browsers'] : '';
$browsers = explode( '|', $browsers_raw );
// phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- User Agent is not stored or displayed therefore XSS safe.
$useragent = ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) ? $_SERVER['HTTP_USER_AGENT'] : '';
$is_old_edge = preg_match( '/edge\//i', $useragent );
$is_checking_for_chrome = array_search( 'chrome', $browsers, true ) !== false;
$current_browser = $this->_get_browser( $useragent );
// Exception: When checking "Chrome" condition we should treat New Edge as Chrome.
if ( 'edge' === $current_browser && ! $is_old_edge && $is_checking_for_chrome ) {
$current_browser = 'chrome';
}
$should_display = array_intersect( $browsers, (array) $current_browser ) ? true : false;
return ( 'is' === $display_rule ) ? $should_display : ! $should_display;
}
/**
* Returns the Browser name based on user agent.
*
* @since 4.11.0
*
* @param string $useragent The useragent of the berowser.
*
* @return string Detected browser.
*/
protected function _get_browser( $useragent ) {
$browser = 'unknown';
$browser_array = array(
'/safari/i' => 'safari',
'/chrome|CriOS/i' => 'chrome',
'/firefox|FxiOS/i' => 'firefox',
'/msie|Trident/i' => 'ie',
'/edg/i' => 'edge',
'/opr|Opera|Presto/i' => 'opera',
'/maxthon/i' => 'maxthon',
'/ucbrowser/i' => 'ucbrowser',
);
foreach ( $browser_array as $regex => $value ) {
if ( preg_match( $regex, $useragent ) ) {
$browser = $value;
}
}
return $browser;
}
}

View File

@ -0,0 +1,79 @@
<?php
/**
* Cart Contents condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Cart Contents Condition Trait.
*/
trait CartContentsCondition {
/**
* Processes "Cart Contents" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_cart_contents_condition( $condition_settings ) {
if ( ! class_exists( 'WooCommerce' ) ) {
return false;
}
$display_rule = isset( $condition_settings['cartContentsDisplay'] ) ? $condition_settings['cartContentsDisplay'] : 'hasProducts';
$products_raw = isset( $condition_settings['products'] ) ? $condition_settings['products'] : [];
$products_ids = array_map(
function( $item ) {
return isset( $item['value'] ) ? $item['value'] : '';
},
$products_raw
);
$is_cart_empty = WC()->cart->is_empty();
switch ( $display_rule ) {
case 'hasProducts':
return ! $is_cart_empty;
case 'isEmpty':
return $is_cart_empty;
case 'hasSpecificProduct':
return $this->_has_specific_product_in_cart( $products_ids );
case 'doesNotHaveSpecificProduct':
return ! $this->_has_specific_product_in_cart( $products_ids );
default:
return false;
}
}
/**
* Checks presence of specified products in the Cart.
*
* @param Array $products_ids Array of products IDs to check against the Cart's products.
* @return boolean Indicating the presence of specified products in the Cart.
*/
protected function _has_specific_product_in_cart( $products_ids ) {
$has_specific_product = false;
if ( ! WC()->cart->is_empty() ) {
foreach ( WC()->cart->get_cart() as $cart_item ) {
$cart_item_ids = [ $cart_item['product_id'], $cart_item['variation_id'] ];
if ( array_intersect( $products_ids, $cart_item_ids ) ) {
$has_specific_product = true;
break;
}
}
}
return $has_specific_product;
}
}

View File

@ -0,0 +1,85 @@
<?php
/**
* Categories condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Categories Condition Trait.
*/
trait CategoriesCondition {
/**
* Processes "Categories" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all condition settings.
*
* @return boolean Condition output.
*/
protected function _process_categories_condition( $condition_settings ) {
// Only check for Posts.
if ( ! is_singular() ) {
return false;
}
// Get condition's settings.
$display_rule = isset( $condition_settings['categoriesDisplay'] ) ? $condition_settings['categoriesDisplay'] : 'is';
$categories_raw = isset( $condition_settings['categories'] ) ? $condition_settings['categories'] : [];
$categories = array_map(
function( $item ) {
return (object) [
'id' => $item['value'],
'taxonomy_slug' => $item['groupSlug'],
];
},
$categories_raw
);
$current_queried_id = get_queried_object_id();
$has_post_specified_term = false;
$tax_slugs_of_catch_all_items = [];
$is_any_catch_all_selected = false;
$has_post_specified_taxonomy = false;
// Logic evaluation.
foreach ( $categories_raw as $item ) {
if ( true === $item['isCatchAll'] ) {
$tax_slugs_of_catch_all_items[] = $item['groupSlug'];
$is_any_catch_all_selected = true;
}
}
foreach ( $categories as $cat ) {
if ( has_term( $cat->id, $cat->taxonomy_slug, $current_queried_id ) ) {
$has_post_specified_term = true;
break;
}
}
$is_displayable = $has_post_specified_term ? true : false;
if ( ! $is_displayable && $is_any_catch_all_selected ) {
foreach ( $tax_slugs_of_catch_all_items as $tax_slug ) {
$has_post_specified_taxonomy = has_term( '', $tax_slug, $current_queried_id );
if ( $has_post_specified_taxonomy ) {
break;
}
}
$is_displayable = $has_post_specified_taxonomy ? true : false;
}
// Evaluation output.
return ( 'is' === $display_rule ) ? $is_displayable : ! $is_displayable;
}
}

View File

@ -0,0 +1,73 @@
<?php
/**
* Category Page condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Category Page Condition Trait.
*/
trait CategoryPageCondition {
/**
* Processes "Category Page" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_category_page_condition( $condition_settings ) {
// Only check for Archive pages.
if ( ! is_archive() ) {
return false;
}
// Get condition's settings.
$display_rule = isset( $condition_settings['categoryPageDisplay'] ) ? $condition_settings['categoryPageDisplay'] : 'is';
$categories_raw = isset( $condition_settings['categories'] ) ? $condition_settings['categories'] : [];
$queried_object = get_queried_object();
$is_queried_object_valid = $queried_object instanceof \WP_Term && property_exists( $queried_object, 'taxonomy' );
if ( ! $is_queried_object_valid ) {
return false;
}
$queried_taxonomy = $queried_object->taxonomy;
$categories_ids = array_map(
function( $item ) {
return $item['value'];
},
$categories_raw
);
$tax_slugs_of_catch_all_items = [];
$is_any_catch_all_selected = false;
foreach ( $categories_raw as $item ) {
if ( true === $item['isCatchAll'] ) {
$tax_slugs_of_catch_all_items[] = $item['groupSlug'];
$is_any_catch_all_selected = true;
}
}
// Logic evaluation.
$current_category_id = get_queried_object_id();
$is_displayable = array_intersect( $categories_ids, (array) $current_category_id ) ? true : false;
if ( ! $is_displayable && $is_any_catch_all_selected ) {
$is_displayable = array_intersect( $tax_slugs_of_catch_all_items, (array) $queried_taxonomy ) ? true : false;
}
// Evaluation output.
return ( 'is' === $display_rule ) ? $is_displayable : ! $is_displayable;
}
}

View File

@ -0,0 +1,52 @@
<?php
/**
* Cookie condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Cookie Condition Trait.
*/
trait CookieCondition {
/**
* Processes "Cookie" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_cookie_condition( $condition_settings ) {
$display_rule = isset( $condition_settings['cookieDisplay'] ) ? $condition_settings['cookieDisplay'] : 'cookieExists';
$cookie_name = isset( $condition_settings['cookieName'] ) ? $condition_settings['cookieName'] : '';
$cookie_value = isset( $condition_settings['cookieValue'] ) ? $condition_settings['cookieValue'] : '';
$is_cookie_set = ( isset( $_COOKIE[ $cookie_name ] ) ) ? true : false;
$is_cookie_value_equals = ( isset( $_COOKIE[ $cookie_name ] ) ) ? $cookie_value === $_COOKIE[ $cookie_name ] : false;
switch ( $display_rule ) {
case 'cookieExists':
return $is_cookie_set;
case 'cookieDoesNotExist':
return ! $is_cookie_set;
case 'cookieValueEquals':
return $is_cookie_value_equals;
case 'cookieValueDoesNotEqual':
return ! $is_cookie_value_equals;
default:
return false;
}
}
}

View File

@ -0,0 +1,57 @@
<?php
/**
* Date Archive condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
use DateTimeImmutable;
/**
* Date Archive Condition Trait.
*/
trait DateArchiveCondition {
/**
* Processes "Date Archive" condition.
*
* @since 4.11.0
*
* @param array $all_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_date_archive_condition( $all_settings ) {
if ( ! is_date() ) {
return false;
}
$display_rule = isset( $all_settings['dateArchiveDisplay'] ) ? $all_settings['dateArchiveDisplay'] : 'isAfter';
$date = isset( $all_settings['dateArchive'] ) ? $all_settings['dateArchive'] : '';
$year = get_query_var( 'year' );
$monthnum = get_query_var( 'monthnum' ) === 0 ? 1 : get_query_var( 'monthnum' );
$day = get_query_var( 'day' ) === 0 ? 1 : get_query_var( 'day' );
$archive_date = sprintf( '%s-%s-%s', $year, $monthnum, $day );
$target_date = new DateTimeImmutable( $date, wp_timezone() );
$current_arhive_date = new DateTimeImmutable( $archive_date, wp_timezone() );
switch ( $display_rule ) {
case 'isAfter':
return ( $current_arhive_date > $target_date );
case 'isBefore':
return ( $current_arhive_date < $target_date );
default:
return ( $current_arhive_date > $target_date );
}
}
}

View File

@ -0,0 +1,251 @@
<?php
/**
* Date Time condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
use DateTimeImmutable;
/**
* Date Time Condition Trait.
*/
trait DateTimeCondition {
/**
* Processes "Date & Time" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_date_time_condition( $condition_settings ) {
$display_rule = isset( $condition_settings['dateTimeDisplay'] ) ? $condition_settings['dateTimeDisplay'] : 'isAfter';
$date = isset( $condition_settings['date'] ) ? $condition_settings['date'] : '';
$time = isset( $condition_settings['time'] ) ? $condition_settings['time'] : '';
$all_day = isset( $condition_settings['allDay'] ) ? $condition_settings['allDay'] : '';
$from_time = isset( $condition_settings['fromTime'] ) ? $condition_settings['fromTime'] : '';
$until_time = isset( $condition_settings['untilTime'] ) ? $condition_settings['untilTime'] : '';
$weekdays = isset( $condition_settings['weekdays'] ) ? array_filter( explode( '|', $condition_settings['weekdays'] ) ) : array();
$repeat_frequency = isset( $condition_settings['repeatFrequency'] ) ? $condition_settings['repeatFrequency'] : '';
$repeat_frequency_specific_days = isset( $condition_settings['repeatFrequencySpecificDays'] ) ? $condition_settings['repeatFrequencySpecificDays'] : '';
$date_from_time = $date . ' ' . $from_time;
$date_until_time = $date . ' ' . $until_time;
$date_time = $date . ' ' . $time;
$target_date = new DateTimeImmutable( $date, wp_timezone() );
$target_datetime = new DateTimeImmutable( $date_time, wp_timezone() );
$target_from_datetime = new DateTimeImmutable( $date_from_time, wp_timezone() );
$target_until_datetime = new DateTimeImmutable( $date_until_time, wp_timezone() );
$current_datetime = ! empty( $this->_custom_current_date ) ? $this->_custom_current_date : current_datetime();
$current_datetime_from = $current_datetime->modify( $from_time );
$current_datetime_until = $current_datetime->modify( $until_time );
switch ( $display_rule ) {
case 'isAfter':
return ( $current_datetime > $target_datetime );
case 'isBefore':
return ( $current_datetime < $target_datetime );
case 'isOnSpecificDate':
$has_reached_target_datetime = $current_datetime >= $target_date;
$has_time_until_tomorrow = $current_datetime < $target_date->modify( 'tomorrow' );
if ( 'off' === $all_day ) {
$has_reached_target_datetime = $current_datetime >= $target_from_datetime;
$has_time_until_tomorrow = $current_datetime < $target_until_datetime;
}
$is_on_specific_date = ( $has_reached_target_datetime && $has_time_until_tomorrow );
$is_repeated = $this->_is_datetime_condition_repeated( $condition_settings, $is_on_specific_date, $current_datetime, $target_datetime );
return ( $is_on_specific_date || $is_repeated );
case 'isNotOnSpecificDate':
$has_reached_target_datetime = $current_datetime >= $target_date;
$has_time_until_tomorrow = $current_datetime < $target_date->modify( 'tomorrow' );
if ( 'off' === $all_day ) {
$has_reached_target_datetime = $current_datetime >= $target_from_datetime;
$has_time_until_tomorrow = $current_datetime < $target_until_datetime;
}
return ! ( $has_reached_target_datetime && $has_time_until_tomorrow );
case 'isOnSpecificDays':
$current_day = strtolower( $current_datetime->format( 'l' ) );
$is_on_selected_day = array_intersect( (array) $current_day, $weekdays ) ? true : false;
$has_reached_target_datetime = true;
$has_time_until_tomorrow = true;
if ( 'off' === $all_day ) {
$has_reached_target_datetime = $current_datetime >= $current_datetime_from;
$has_time_until_tomorrow = $current_datetime < $current_datetime_until;
}
$is_repeated = $this->_is_datetime_condition_repeated( $condition_settings, $is_on_selected_day, $current_datetime, $target_datetime );
$is_on_specific_days = $is_on_selected_day && $has_reached_target_datetime && $has_time_until_tomorrow;
return ( 'weekly' === $repeat_frequency_specific_days ) ? $is_on_specific_days : $is_repeated;
case 'isFirstDayOfMonth':
$is_first_day_of_month = $current_datetime->format( 'd' ) === '01';
$has_reached_target_datetime = true;
$has_time_until_tomorrow = true;
if ( 'off' === $all_day ) {
$has_reached_target_datetime = $current_datetime >= $current_datetime_from;
$has_time_until_tomorrow = $current_datetime < $current_datetime_until;
}
return ( $is_first_day_of_month && $has_reached_target_datetime && $has_time_until_tomorrow );
case 'isLastDayOfMonth':
$last_day_of_month = new DateTimeImmutable( 'last day of this month', wp_timezone() );
$is_last_day_of_month = $current_datetime->format( 'd' ) === $last_day_of_month->format( 'd' );
$has_reached_target_datetime = true;
$has_time_until_tomorrow = true;
if ( 'off' === $all_day ) {
$has_reached_target_datetime = $current_datetime >= $current_datetime_from;
$has_time_until_tomorrow = $current_datetime < $current_datetime_until;
}
return ( $is_last_day_of_month && $has_reached_target_datetime && $has_time_until_tomorrow );
default:
return ( $current_datetime >= $target_datetime );
}
}
/**
* Checks whether a condition should be repeated or not.
*
* @since 4.11.0
*
* @param array $condition_settings Contains all settings of the condition.
* @param boolean $is_on_specific_date Specifies if "Is On Specific Date" condition has already
* reached that specific date or not.
* Useful to avoid repetition checking if condition is already
* true and also for "Every Other" repeat frequency.
* @param DateTimeImmutable $current_datetime The current date and time to use.
* @param DateTimeImmutable $target_datetime To detect Monthly/Annually repetition and "After Number of times".
*
* @return boolean Condition repetition result.
*/
protected function _is_datetime_condition_repeated( $condition_settings, $is_on_specific_date, $current_datetime, $target_datetime ) {
$repeat = isset( $condition_settings['repeat'] ) ? $condition_settings['repeat'] : '';
$repeat_frequency = isset( $condition_settings['repeatFrequency'] ) ? $condition_settings['repeatFrequency'] : '';
$repeat_frequency_specific_days = isset( $condition_settings['repeatFrequencySpecificDays'] ) ? $condition_settings['repeatFrequencySpecificDays'] : '';
$repeat_end = isset( $condition_settings['repeatEnd'] ) ? $condition_settings['repeatEnd'] : '';
$repeat_until = isset( $condition_settings['repeatUntilDate'] ) ? $condition_settings['repeatUntilDate'] : '';
$repeat_times = isset( $condition_settings['repeatTimes'] ) ? $condition_settings['repeatTimes'] : '';
$all_day = isset( $condition_settings['allDay'] ) ? $condition_settings['allDay'] : '';
$from_time = isset( $condition_settings['fromTime'] ) ? $condition_settings['fromTime'] : '';
$until_time = isset( $condition_settings['untilTime'] ) ? $condition_settings['untilTime'] : '';
$is_repeated = false;
$is_on_specific_days = 'isOnSpecificDays' === $condition_settings['dateTimeDisplay'];
if ( $is_on_specific_days || ( 'on' === $repeat && ! $is_on_specific_date ) ) {
if ( $is_on_specific_days ) {
$is_day_repeated = $this->_is_day_repeated( $repeat_frequency_specific_days, $is_on_specific_date, $current_datetime, $target_datetime );
} else {
$is_day_repeated = $this->_is_day_repeated( $repeat_frequency, $is_on_specific_date, $current_datetime, $target_datetime );
}
$is_repeat_valid = false;
switch ( $repeat_end ) {
case 'untilDate':
$is_repeat_valid = $current_datetime <= new DateTimeImmutable( $repeat_until, wp_timezone() );
break;
case 'afterNumberOfTimes':
$target_date_after_number_of_times = $target_datetime->modify( '+' . $repeat_times . ' month' );
if ( 'annually' === $repeat_frequency ) {
$target_date_after_number_of_times = $target_datetime->modify( '+' . $repeat_times . ' year' );
}
if ( 'off' === $all_day ) {
$target_date_after_number_of_times = $target_date_after_number_of_times->modify( $until_time );
}
$is_repeat_valid = $current_datetime <= $target_date_after_number_of_times;
break;
case 'never':
$is_repeat_valid = true;
break;
default:
$is_repeat_valid = true;
break;
}
// We assume "All Day" switch is "On".
$has_reached_from_time = $is_day_repeated;
$has_reached_until_time = $current_datetime < $current_datetime->modify( 'tomorrow' );
// Calculate from time/until time if "All Day" switch is "Off".
if ( 'off' === $all_day ) {
$has_reached_from_time = $current_datetime >= $current_datetime->modify( $from_time );
$has_reached_until_time = $current_datetime < $current_datetime->modify( $until_time );
}
$is_repeated = $is_day_repeated && $has_reached_from_time && $has_reached_until_time && $is_repeat_valid;
}
return $is_repeated;
}
/**
* Checks whether a day is repeated or not.
*
* @since 4.11.0
*
* @param string $repeat_frequency Frequency of repeat Ex. monthly, annually, everyOther...
* @param boolean $is_on_specific_date Useful for "Every Other" repeat frequency.
* @param DateTimeImmutable $current_datetime The current date and time to use.
* @param DateTimeImmutable $target_datetime Checks monthly/annually repetition against this Date and Time.
*
* @return boolean Day repetition result.
*/
protected function _is_day_repeated( $repeat_frequency, $is_on_specific_date, $current_datetime, $target_datetime ) {
switch ( $repeat_frequency ) {
case 'monthly':
return ( $current_datetime->format( 'd' ) === $target_datetime->format( 'd' ) );
case 'annually':
return ( $current_datetime->format( 'm d' ) === $target_datetime->format( 'm d' ) );
case 'everyOther':
return ! $is_on_specific_date;
case 'firstInstanceOfMonth':
return ( $current_datetime->format( 'Y-m-d' ) === $current_datetime->modify( 'first ' . $current_datetime->format( 'l' ) . ' of this month' )->format( 'Y-m-d' ) );
case 'lastInstanceOfMonth':
return ( $current_datetime->format( 'Y-m-d' ) === $current_datetime->modify( 'last ' . $current_datetime->format( 'l' ) . ' of this month' )->format( 'Y-m-d' ) );
default:
return false;
}
}
/**
* Checks date and time for possible conflicts.
*
* @since 4.11.0
*
* @param string $current_display_rule Value of currently processing condition's display rule Ex. is,isNot...
* @param string $prev_display_rule Value of previously processed condition's display rule Ex. is,isNot...
* @param array $conflicting_display_rule_vals Array of values containing the conflicting display rules as defined in $this->conflicts.
*
* @return boolean Conflict evaluation result.
*/
protected function _is_date_time_conflicted( $current_display_rule, $prev_display_rule, $conflicting_display_rule_vals ) {
$is_current_display_rule_conflicted = $this->_in_array_conflict( $current_display_rule, $conflicting_display_rule_vals );
$is_prev_display_rule_conflicted = $this->_in_array_conflict( $prev_display_rule, $conflicting_display_rule_vals );
$is_from_same_group = $is_current_display_rule_conflicted['index'] === $is_prev_display_rule_conflicted['index'];
if ( $is_current_display_rule_conflicted['value'] && $is_prev_display_rule_conflicted['value'] && ! $is_from_same_group ) {
return true;
}
return false;
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* Dynamic Posts Condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Dynamic Posts Condition Trait.
*/
trait DynamicPostsCondition {
/**
* Processes "Dynamic Posts" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_dynamic_posts_condition( $condition_settings ) {
// Only check for Posts.
if ( ! is_singular() ) {
return false;
}
$display_rule = isset( $condition_settings['dynamicPostsDisplay'] ) ? $condition_settings['dynamicPostsDisplay'] : '';
$dynamic_posts_raw = isset( $condition_settings['dynamicPosts'] ) ? $condition_settings['dynamicPosts'] : [];
$dynamic_posts_ids = array_map(
function( $item ) {
return isset( $item['value'] ) ? $item['value'] : '';
},
$dynamic_posts_raw
);
$is_on_shop_page = class_exists( 'WooCommerce' ) && is_shop();
$current_page_id = $is_on_shop_page ? wc_get_page_id( 'shop' ) : get_queried_object_id();
$should_display = array_intersect( $dynamic_posts_ids, (array) $current_page_id ) ? true : false;
return ( 'is' === $display_rule ) ? $should_display : ! $should_display;
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* Logged In Status Condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Logged In Status Condition Trait.
*/
trait LoggedInStatusCondition {
/**
* Processes "Logged In Status" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_logged_in_status_condition( $condition_settings ) {
$logged_in_status = isset( $condition_settings['loggedInStatus'] ) ? $condition_settings['loggedInStatus'] : 'loggedIn';
$should_display = ( is_user_logged_in() ) ? true : false;
return ( 'loggedIn' === $logged_in_status ) ? $should_display : ! $should_display;
}
/**
* Checks logged in status for possible conflicts.
*
* @param string $current_value Curent setting value.
* @param string $prev_value Previous setting value.
* @param array $conflicting_value Defined conflicting value.
* @return boolean
*/
protected function _is_logged_in_status_conflicted( $current_value, $prev_value, $conflicting_value ) {
$is_current_value_conflicted = in_array( $current_value, $conflicting_value, true );
$is_prev_value_conflicted = in_array( $prev_value, $conflicting_value, true );
if ( $is_current_value_conflicted && $is_prev_value_conflicted ) {
return true;
}
return false;
}
}

View File

@ -0,0 +1,79 @@
<?php
/**
* Number of Views condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Number of Views Condition Trait.
*/
trait NumberOfViewsCondition {
/**
* Processes "Number of Views" condition.
*
* @since 4.11.0
*
* @param array $condition_id Condition ID.
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_number_of_views_condition( $condition_id, $condition_settings ) {
if ( ! isset( $_COOKIE['divi_module_views'] ) ) {
return true;
}
// Get condition's settings.
$number_of_views = isset( $condition_settings['numberOfViews'] ) ? $condition_settings['numberOfViews'] : '0';
$cookie_array = [];
$visit_count = 0;
$current_datetime = current_datetime();
$cookie_array = json_decode( base64_decode( $_COOKIE['divi_module_views'] ), true ); // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput, WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode -- Cookie is not stored or displayed therefore XSS safe, The returned data is an array and necessary validation checks are performed.
if ( ! is_array( $cookie_array ) ) {
return true;
}
// Logic evaluation.
$col = array_column( $cookie_array, 'id' );
$is_condition_set_in_cookie = array_search( $condition_id, $col, true ) !== false;
if ( ! $is_condition_set_in_cookie ) {
// Display module if condition is not set in Cookie yet.
return true;
}
$is_reset_after_duration_on = 'on' === $condition_settings['resetAfterDuration'] ? true : false;
if ( $is_reset_after_duration_on ) {
$first_visit_timestamp = $cookie_array[ $condition_id ]['first_visit_timestamp'];
$display_again_after = $condition_settings['displayAgainAfter'] . ' ' . $condition_settings['displayAgainAfterUnit'];
$first_visit_datetime = $current_datetime->setTimestamp( $first_visit_timestamp );
$display_again_datetime = $first_visit_datetime->modify( $display_again_after );
if ( $current_datetime > $display_again_datetime ) {
return true;
}
}
$visit_count = $cookie_array[ $condition_id ]['visit_count'];
if ( (int) $visit_count >= (int) $number_of_views ) {
$is_displayable = false;
} else {
$is_displayable = true;
}
// Evaluation output.
return $is_displayable;
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* Operating System Condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Operating System Condition Trait.
*/
trait OperatingSystemCondition {
/**
* Processes "Operating System" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_operating_system_condition( $condition_settings ) {
$display_rule = isset( $condition_settings['operatingSystemDisplay'] ) ? $condition_settings['operatingSystemDisplay'] : 'is';
$operating_systems_raw = isset( $condition_settings['operatingSystems'] ) ? $condition_settings['operatingSystems'] : '';
$operating_systems = explode( '|', $operating_systems_raw );
$current_os = $this->_get_os();
$should_display = array_intersect( $operating_systems, (array) $current_os ) ? true : false;
return ( 'is' === $display_rule ) ? $should_display : ! $should_display;
}
/**
* Returns the Operating System name based on user agent.
*
* @since 4.11.0
*
* @return string
*/
protected function _get_os() {
$os_platform = 'unknown';
// phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- User Agent is not stored or displayed therefore XSS safe.
$user_agent = $_SERVER['HTTP_USER_AGENT'];
$os_array = array(
'/windows nt/i' => 'windows',
'/macintosh|mac os x/i' => 'macos',
'/linux/i' => 'linux',
'/android/i' => 'android',
'/iphone/i' => 'iphone',
'/ipad/i' => 'ipad',
'/ipod/i' => 'ipod',
'/appletv/i' => 'appletv',
'/playstation/i' => 'playstation',
'/xbox/i' => 'xbox',
'/nintendo/i' => 'nintendo',
'/webos|hpwOS/i' => 'webos',
);
foreach ( $os_array as $regex => $value ) {
if ( preg_match( $regex, $user_agent ) ) {
$os_platform = $value;
}
}
return $os_platform;
}
}

View File

@ -0,0 +1,51 @@
<?php
/**
* Page Visit Condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Page Visit Condition Trait.
*/
trait PageVisitCondition {
/**
* Processes "Page Visit" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_page_visit_condition( $condition_settings ) {
$display_rule = isset( $condition_settings['pageVisitDisplay'] ) ? $condition_settings['pageVisitDisplay'] : 'hasVisitedSpecificPage';
$pages_raw = isset( $condition_settings['pages'] ) ? $condition_settings['pages'] : [];
$pages_ids = array_map(
function( $item ) {
return isset( $item['value'] ) ? (int) $item['value'] : '';
},
$pages_raw
);
$has_visited_specific_page = false;
if ( isset( $_COOKIE['divi_post_visit'] ) ) {
// phpcs:ignore ET.Sniffs.ValidatedSanitizedInput, WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode -- Cookie is not stored or displayed therefore XSS safe, base64_decode returned data is an array and necessary validation checks are performed.
$cookie = json_decode( base64_decode( $_COOKIE['divi_post_visit'] ), true );
$col = array_column( $cookie, 'id' );
$has_visited_specific_page = array_intersect( $pages_ids, $col ) ? true : false;
}
$should_display = $has_visited_specific_page;
return ( 'hasVisitedSpecificPage' === $display_rule ) ? $should_display : ! $should_display;
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* Page Type Condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Post Type Condition Trait.
*/
trait PostTypeCondition {
/**
* Processes "Post Types" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_post_type_condition( $condition_settings ) {
// Only check for Posts.
if ( ! is_singular() ) {
return false;
}
$display_rule = isset( $condition_settings['postTypeDisplay'] ) ? $condition_settings['postTypeDisplay'] : '';
$post_types_raw = isset( $condition_settings['postTypes'] ) ? $condition_settings['postTypes'] : [];
$post_types_values = array_map(
function( $item ) {
return $item['value'];
},
$post_types_raw
);
$is_on_shop_page = class_exists( 'WooCommerce' ) && is_shop();
$current_queried_id = $is_on_shop_page ? wc_get_page_id( 'shop' ) : get_queried_object_id();
$post_type = get_post_type( $current_queried_id );
$should_display = array_intersect( $post_types_values, (array) $post_type ) ? true : false;
return ( 'is' === $display_rule ) ? $should_display : ! $should_display;
}
}

View File

@ -0,0 +1,109 @@
<?php
/**
* Product Purchase Condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Product Purchase Condition Trait.
*/
trait ProductPurchaseCondition {
/**
* Processes "Product Purchase" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_product_purchase_condition( $condition_settings ) {
if ( ! class_exists( 'WooCommerce' ) || ! is_user_logged_in() ) {
return false;
}
$display_rule = isset( $condition_settings['productPurchaseDisplay'] ) ? $condition_settings['productPurchaseDisplay'] : 'hasBoughtProduct';
$products_raw = isset( $condition_settings['products'] ) ? $condition_settings['products'] : [];
$current_user = wp_get_current_user();
$products_ids = array_map(
function( $item ) {
return isset( $item['value'] ) ? $item['value'] : '';
},
$products_raw
);
switch ( $display_rule ) {
case 'hasBoughtProduct':
$has_bought_product = $this->_has_user_bought_any_product( $current_user->ID );
return $has_bought_product;
case 'hasNotBoughtProduct':
$has_bought_product = $this->_has_user_bought_any_product( $current_user->ID );
return ! $has_bought_product;
case 'hasBoughtSpecificProduct':
return $this->_has_user_bought_specific_product( $current_user, $products_ids );
case 'hasNotBoughtSpecificProduct':
return ! $this->_has_user_bought_specific_product( $current_user, $products_ids );
default:
return false;
}
}
/**
* Checks whether `$current_user` has bought any specified products.
*
* @param WP_User $current_user Current user object.
* @param array $products_ids List of specefied product IDs.
*
* @return boolean Returns true if `$current_user` has bought any specified products, False otherwise.
*/
protected function _has_user_bought_specific_product( $current_user, $products_ids ) {
$has_bought_specific_product = false;
foreach ( $products_ids as $product_id ) {
$has_bought_specific_product = wc_customer_bought_product( $current_user->user_email, $current_user->ID, $product_id );
if ( $has_bought_specific_product ) {
break;
}
}
return $has_bought_specific_product;
}
/**
* Checks if `$user_id` has bought any product in WooCommerce.
*
* @param integer $user_id WordPress User ID.
*
* @return boolean Returns true if `$user_id` has any paid order, False otherwise.
*/
protected function _has_user_bought_any_product( $user_id = 0 ) {
if ( ! class_exists( 'WooCommerce' ) || ! $user_id || ! is_numeric( $user_id ) ) {
return false;
}
$paid_statuses = wc_get_is_paid_statuses();
$orders = wc_get_orders(
[
'limit' => 1,
'status' => $paid_statuses,
'customer_id' => (int) $user_id,
'return' => 'ids',
]
);
return count( $orders ) > 0 ? true : false;
}
}

View File

@ -0,0 +1,68 @@
<?php
/**
* Search Results Condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Search Results Condition Trait.
*/
trait SearchResultsCondition {
/**
* Processes "Search Results" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_search_results_condition( $condition_settings ) {
// Only check for Search.
if ( ! is_search() ) {
return false;
}
$display_rule = isset( $condition_settings['searchResultsDisplay'] ) ? $condition_settings['searchResultsDisplay'] : 'is';
$specific_search_queries_raw = isset( $condition_settings['specificSearchQueries'] ) ? $condition_settings['specificSearchQueries'] : '';
$excluded_search_queries_raw = isset( $condition_settings['excludedSearchQueries'] ) ? $condition_settings['excludedSearchQueries'] : '';
$specific_search_queries = explode( ',', $specific_search_queries_raw );
$excluded_search_queries = explode( ',', $excluded_search_queries_raw );
switch ( $display_rule ) {
case 'specificSearchQueries':
return $this->_is_specific_search_query( $specific_search_queries );
case 'excludedSearchQueries':
return ! $this->_is_specific_search_query( $excluded_search_queries );
default:
return false;
}
}
/**
* "is specirfic serach query" Condition logic.
*
* @param array $specific_search_queries Array of search queries.
* @return boolean Indicating whether "is specirfic serach query" Condition is true or false.
*/
protected function _is_specific_search_query( $specific_search_queries ) {
$is_specific_search_query = false;
foreach ( $specific_search_queries as $search_query ) {
$is_specific_search_query = get_search_query() === $search_query;
if ( $is_specific_search_query ) {
break;
}
}
return $is_specific_search_query;
}
}

View File

@ -0,0 +1,73 @@
<?php
/**
* Tag Page condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Tag Page Condition Trait.
*/
trait TagPageCondition {
/**
* Processes "Tag Page" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_tag_page_condition( $condition_settings ) {
// Only check for Archive pages.
if ( ! is_archive() ) {
return false;
}
// Get condition's settings.
$display_rule = isset( $condition_settings['tagPageDisplay'] ) ? $condition_settings['tagPageDisplay'] : 'is';
$tags_raw = isset( $condition_settings['tags'] ) ? $condition_settings['tags'] : [];
$queried_object = get_queried_object();
$is_queried_object_valid = $queried_object instanceof \WP_Term && property_exists( $queried_object, 'taxonomy' );
if ( ! $is_queried_object_valid ) {
return false;
}
$queried_taxonomy = $queried_object->taxonomy;
$tags_raw_ids = array_map(
function( $item ) {
return $item['value'];
},
$tags_raw
);
$tax_slugs_of_catch_all_items = [];
$is_any_catch_all_selected = false;
foreach ( $tags_raw as $item ) {
if ( true === $item['isCatchAll'] ) {
$tax_slugs_of_catch_all_items[] = $item['groupSlug'];
$is_any_catch_all_selected = true;
}
}
// Logic evaluation.
$current_tag_id = get_queried_object_id();
$is_displayable = array_intersect( $tags_raw_ids, (array) $current_tag_id ) ? true : false;
if ( ! $is_displayable && $is_any_catch_all_selected ) {
$is_displayable = array_intersect( $tax_slugs_of_catch_all_items, (array) $queried_taxonomy ) ? true : false;
}
// Evaluation output.
return ( 'is' === $display_rule ) ? $is_displayable : ! $is_displayable;
}
}

View File

@ -0,0 +1,85 @@
<?php
/**
* Tags Condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* Tags Condition Trait.
*/
trait TagsCondition {
/**
* Processes "Tags" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_tags_condition( $condition_settings ) {
// Only check for Posts.
if ( ! is_singular() ) {
return false;
}
// Get condition's settings.
$display_rule = isset( $condition_settings['tagsDisplay'] ) ? $condition_settings['tagsDisplay'] : 'is';
$tags_raw = isset( $condition_settings['tags'] ) ? $condition_settings['tags'] : [];
$tags = array_map(
function( $item ) {
return (object) [
'id' => $item['value'],
'taxonomy_slug' => $item['groupSlug'],
];
},
$tags_raw
);
$current_queried_id = get_queried_object_id();
$has_post_specified_term = false;
$tax_slugs_of_catch_all_items = [];
$is_any_catch_all_selected = false;
$has_post_specified_taxonomy = false;
// Logic evaluation.
foreach ( $tags_raw as $item ) {
if ( true === $item['isCatchAll'] ) {
$tax_slugs_of_catch_all_items[] = $item['groupSlug'];
$is_any_catch_all_selected = true;
}
}
foreach ( $tags as $tag ) {
if ( has_term( $tag->id, $tag->taxonomy_slug, $current_queried_id ) ) {
$has_post_specified_term = true;
break;
}
}
$is_displayable = $has_post_specified_term ? true : false;
if ( ! $is_displayable && $is_any_catch_all_selected ) {
foreach ( $tax_slugs_of_catch_all_items as $tax_slug ) {
$has_post_specified_taxonomy = has_term( '', $tax_slug, $current_queried_id );
if ( $has_post_specified_taxonomy ) {
break;
}
}
$is_displayable = $has_post_specified_taxonomy ? true : false;
}
// Evaluation output.
return ( 'is' === $display_rule ) ? $is_displayable : ! $is_displayable;
}
}

View File

@ -0,0 +1,74 @@
<?php
/**
* User Role Condition logic swiftly crafted.
*
* @since 4.11.0
*
* @package Divi
* @sub-package Builder
*/
namespace Module\Field\DisplayConditions;
/**
* User Role Condition Trait.
*/
trait UserRoleCondition {
/**
* Processes "User Role" condition.
*
* @since 4.11.0
*
* @param array $condition_settings Containing all settings of the condition.
*
* @return boolean Condition output.
*/
protected function _process_user_role_condition( $condition_settings ) {
$display_rule = isset( $condition_settings['userRoleDisplay'] ) ? $condition_settings['userRoleDisplay'] : 'is';
$roles_raw = isset( $condition_settings['userRoles'] ) ? $condition_settings['userRoles'] : [];
$ids_raw = isset( $condition_settings['userIds'] ) ? $condition_settings['userIds'] : '';
$roles = array_map(
function( $item ) {
return $item['value'];
},
$roles_raw
);
$ids = isset( $ids_raw ) ? array_map( 'trim', array_filter( explode( ',', $ids_raw ) ) ) : array();
$user = wp_get_current_user();
$should_display_based_on_roles = array_intersect( $roles, (array) $user->roles ) ? true : false;
$should_display_based_on_ids = array_intersect( $ids, (array) $user->ID ) ? true : false;
$should_display = ( $should_display_based_on_roles || $should_display_based_on_ids );
return ( 'is' === $display_rule ) ? $should_display : ! $should_display;
}
/**
* Checks user role for possible conflicts.
*
* @since 4.11.0
*
* @param string $current_value Currently processing condition's conflicting value.
* @param string $prev_value Previously processed condition's conflicting value.
* @param array $conflicting_value Array of values containing the conflicting values as defined in $this->conflicts.
* @param string $current_display_rule Currently processing condition's display rule Ex. is,isNot...
* @param string $prev_display_rule Previously processed condition's display rule Ex. is,isNot...
* @param array $conflicting_display_rule_vals Array of values containing the conflicting display rules as defined in $this->conflicts.
*
* @return boolean Conflict evaluation result.
*/
protected function _is_user_role_conflicted( $current_value, $prev_value, $conflicting_value, $current_display_rule, $prev_display_rule, $conflicting_display_rule_vals ) {
$current_value = explode( '|', $current_value );
$prev_value = explode( '|', $prev_value );
$is_current_value_conflicted = ! empty( array_intersect( $current_value, $conflicting_value ) );
$is_prev_value_conflicted = ! empty( array_intersect( $prev_value, $conflicting_value ) );
$is_current_display_rule_conflicted = in_array( $current_display_rule, $conflicting_display_rule_vals, true );
$is_prev_display_rule_conflicted = in_array( $prev_display_rule, $conflicting_display_rule_vals, true );
if ( $is_current_value_conflicted && $is_prev_value_conflicted && $is_current_display_rule_conflicted && $is_prev_display_rule_conflicted ) {
return true;
}
return false;
}
}