<?php
/**
 * Avada Builder Conditional Render Helper class.
 *
 * @package Avada-Builder
 * @since 3.3
 */

// Do not allow directly accessing this file.
if ( ! defined( 'ABSPATH' ) ) {
	exit( 'Direct script access denied.' );
}


/**
 * Avada Builder Conditional Render Helper class.
 *
 * @since 3.3
 */
class Fusion_Builder_Conditional_Render_Helper {

	protected static $custom_conditions;

	/**
	 * Class constructor.
	 *
	 * @since 3.3
	 * @access public
	 */
	public function __construct() {
	}

	/**
	 * Get conditional logic params.
	 *
	 * @since 3.3
	 * @access public
	 * @param array $args The placeholder arguments.
	 * @return array
	 */
	public static function get_params( $args ) {

		// Post Categories.
		$post_categories_field   = 'text';
		$post_categories_options = '';
		$post_categories_count   = wp_count_terms( 'category' );

		if ( 25 > $post_categories_count && 0 < $post_categories_count ) {
			$post_categories = [];
			$categories      = get_terms(
				'category',
				[
					'hide_empty' => false,
				]
			);
			if ( ! empty( $categories ) && ! is_wp_error( $categories ) ) {
				foreach ( $categories as $category ) {
					$post_categories[ $category->term_id ] = $category->name;
				}
			}

			$post_categories_field   = 'select';
			$post_categories_options = $post_categories;
		}

		// Post Tags.
		$post_tags_field   = 'text';
		$post_tags_options = '';
		$post_tag_count    = wp_count_terms( 'post_tag' );

		if ( 25 > $post_tag_count && 0 < $post_tag_count ) {
			$post_tags = [];
			$tags      = get_terms(
				'post_tag',
				[
					'hide_empty' => false,
				]
			);
			if ( ! empty( $tags ) && ! is_wp_error( $tags ) ) {
				foreach ( $tags as $tag ) {
					$post_tags[ $tag->term_id ] = $tag->name;
				}
			}

			$post_tags_field   = 'select';
			$post_tags_options = $post_tags;
		}

		$post_types      = get_post_types( [ 'public' => true  ], 'objects' );
		$post_type_array = [];
		if ( ! empty( $post_types ) && ! is_wp_error( $post_types ) ) {
			foreach( $post_types as $post_type ) {
				$post_type_array[ $post_type->name ] = isset( $post_type->labels->singular_name ) ? $post_type->labels->singular_name : $post_type->label;
			}
		}

		$params = [
			[
				'type'        => 'fusion_logics',
				'heading'     => esc_html__( 'Conditional Rendering', 'fusion-builder' ),
				'param_name'  => 'render_logics',
				'description' => __( 'Add conditional rendering logic for the element. The element will only be part of the post / page contents, if the set conditions are met. <strong>NOTE:</strong> Server cache can interfere with results.', 'fusion-builder' ),
				'group'       => esc_attr__( 'Extras', 'fusion-builder' ),
				'placeholder' => [
					'id'          => 'placeholder',
					'title'       => esc_html__( 'Select A Condition Type', 'fusion-builder' ),
					'type'        => 'text',
					'comparisons' => [
						'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
						'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					],
				],
				'choices'     => [
					[
						'id'          => 'device_type',
						'title'       => esc_html__( 'Device Type', 'fusion-builder' ),
						'type'        => 'select',
						'options'     => [
							'desktop'       => esc_html__( 'Desktop', 'fusion-builder' ),
							'mobile_tablet' => __( 'Mobile & Tablet', 'fusion-builder' ),
							'mobile'        => __( 'Mobile', 'fusion-builder' ),
							'tablet'        => __( 'Tablet', 'fusion-builder' ),
						],
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'get_var',
						'title'       => esc_html__( 'GET Variable', 'fusion-builder' ),
						'type'        => 'text',
						'additionals' => [
							'type'        => 'text',
							'title'       => esc_html__( 'GET', 'fusion-builder' ),
							'placeholder' => esc_html__( 'Variable Name', 'fusion-builder' ),
						],
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
							'contains'     => esc_attr__( 'Contains', 'fusion-builder' ),
							'not-contains' => esc_attr__( 'Does Not Contain', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'session_var',
						'title'       => esc_html__( 'SESSION Variable', 'fusion-builder' ),
						'type'        => 'text',
						'additionals' => [
							'type'        => 'text',
							'title'       => esc_html__( 'SESSION', 'fusion-builder' ),
							'placeholder' => esc_html__( 'Variable Name', 'fusion-builder' ),
						],
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
							'contains'     => esc_attr__( 'Contains', 'fusion-builder' ),
							'not-contains' => esc_attr__( 'Does Not Contain', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'user_agent',
						'title'       => esc_html__( 'User Agent', 'fusion-builder' ),
						'type'        => 'text',
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
							'contains'     => esc_attr__( 'Contains', 'fusion-builder' ),
							'not-contains' => esc_attr__( 'Does Not Contain', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'referrer',
						'title'       => esc_html__( 'Referrer', 'fusion-builder' ),
						'placeholder' => esc_attr__( 'Referrer URL', 'fusion-builder' ),
						'type'        => 'text',
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'contains'     => esc_attr__( 'Contains', 'fusion-builder' ),
							'not-contains' => esc_attr__( 'Does Not Contain', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'user_role',
						'title'       => esc_html__( 'User Role', 'fusion-builder' ),
						'type'        => 'select',
						'options'     => self::get_user_roles(),
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'user_state',
						'title'       => esc_html__( 'User State', 'fusion-builder' ),
						'type'        => 'select',
						'options'     => [
							'logged_in'  => esc_html__( 'Logged In', 'fusion-builder' ),
							'logged_out' => esc_html__( 'Logged Out', 'fusion-builder' ),
						],
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'user_meta',
						'title'       => esc_html__( 'User Meta', 'fusion-builder' ),
						'placeholder' => esc_attr__( 'Meta value', 'fusion-builder' ),
						'type'        => 'text',
						'additionals' => [
							'type'        => 'select',
							'title'       => esc_html__( 'Meta Data Key', 'fusion-builder' ),
							'options'     => awb_get_user_meta_data_fields(),
						],
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
							'contains'     => esc_attr__( 'Contains', 'fusion-builder' ),
							'not-contains' => esc_attr__( 'Does Not Contain', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'user_meta_custom',
						'title'       => esc_html__( 'User Meta Custom Key', 'fusion-builder' ),
						'placeholder' => esc_attr__( 'Meta value', 'fusion-builder' ),
						'type'        => 'text',
						'additionals' => [
							'type'        => 'text',
							'title'       => esc_html__( 'Custom Meta Data Key', 'fusion-builder' ),
							'placeholder' => esc_attr__( 'Meta data key', 'fusion-builder' ),
						],
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
							'contains'     => esc_attr__( 'Contains', 'fusion-builder' ),
							'not-contains' => esc_attr__( 'Does Not Contain', 'fusion-builder' ),
						],
					],					
					[
						'id'          => 'custom_field',
						'title'       => esc_html__( 'Custom Field', 'fusion-builder' ),
						'type'        => 'text',
						'additionals' => [
							'type'        => 'text',
							'title'       => esc_html__( 'Field Name', 'fusion-builder' ),
							'placeholder' => esc_html__( 'Field Name', 'fusion-builder' ),
						],
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
							'contains'     => esc_attr__( 'Contains', 'fusion-builder' ),
							'not-contains' => esc_attr__( 'Does Not Contain', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'current_date',
						'title'       => esc_html__( 'Current Date', 'fusion-builder' ),
						'type'        => 'text',
						'additionals' => [
							'type'        => 'text',
							'format'      => esc_html__( 'Date Format', 'fusion-builder' ),
							'placeholder' => esc_html__( 'Y-m-d H:i:s', 'fusion-builder' ),
						],
						'placeholder' => esc_attr__( 'Accepts same inputs as strtotime()', 'fusion-builder' ),
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'published_date',
						'title'       => esc_html__( 'Post Published Date', 'fusion-builder' ),
						'type'        => 'text',
						'additionals' => [
							'type'        => 'text',
							'format'      => esc_html__( 'Published Date Format', 'fusion-builder' ),
							'placeholder' => esc_html__( 'Y-m-d H:i:s', 'fusion-builder' ),
						],						
						'placeholder' => esc_attr__( 'Accepts same inputs as strtotime()', 'fusion-builder' ),
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'modified_date',
						'title'       => esc_html__( 'Post Modified Date', 'fusion-builder' ),
						'type'        => 'text',
						'additionals' => [
							'type'        => 'text',
							'format'      => esc_html__( 'Modified Date Format', 'fusion-builder' ),
							'placeholder' => esc_html__( 'Y-m-d H:i:s', 'fusion-builder' ),
						],
						'placeholder' => esc_attr__( 'Accepts same inputs as strtotime()', 'fusion-builder' ),
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'post_id',
						'title'       => esc_html__( 'Post ID', 'fusion-builder' ),
						'type'        => 'text',
						'placeholder' => esc_attr__( 'Post ID', 'fusion-builder' ),
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'post_type',
						'title'       => esc_html__( 'Post Type', 'fusion-builder' ),
						'type'        => 'select',
						'options'     => $post_type_array,
						'placeholder' => esc_attr__( 'Post Type', 'fusion-builder' ),
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'post_status',
						'title'       => esc_html__( 'Post Status', 'fusion-builder' ),
						'type'        => 'select',
						'options'     => [
							'publish'   => esc_html__( 'Published', 'fusion-builder' ),
							'pending'   => esc_html__( 'Pending', 'fusion-builder' ),
							'draft'     => esc_html__( 'Drafted', 'fusion-builder' ),
							'future'    => esc_html__( 'Planned (future)', 'fusion-builder' ),
							'private'   => esc_html__( 'Private', 'fusion-builder' ),
							'protected' => esc_html__( 'Password Protected', 'fusion-builder' ),
							'trash'     => esc_html__( 'Trashed', 'fusion-builder' ),
						],
						'placeholder' => esc_attr__( 'Post Status', 'fusion-builder' ),
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'post_status_special',
						'title'       => esc_html__( 'Post Special Status', 'fusion-builder' ),
						'type'        => 'select',
						'options'     => [
							'sticky'          => esc_html__( 'Sticky', 'fusion-builder' ),
							'featured'        => esc_html__( 'Featured', 'fusion-builder' ),
							'sticky_featured' => esc_html__( 'Sticky And Featured', 'fusion-builder' ),
						],
						'placeholder' => esc_attr__( 'Post Special Status', 'fusion-builder' ),
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],					
					[
						'id'          => 'post_category',
						'title'       => esc_html__( 'Post Category', 'fusion-builder' ),
						'type'        => $post_categories_field,
						'options'     => $post_categories_options,
						'placeholder' => esc_attr__( 'Category Name, Slug or ID', 'fusion-builder' ),
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'post_tag',
						'title'       => esc_html__( 'Post Tag', 'fusion-builder' ),
						'type'        => $post_tags_field,
						'options'     => $post_tags_options,
						'placeholder' => esc_attr__( 'Tag Name, Slug or ID', 'fusion-builder' ),
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'post_term',
						'title'       => esc_html__( 'Post Term', 'fusion-builder' ),
						'type'        => 'text',
						'placeholder' => esc_attr__( 'Term ID', 'fusion-builder' ),
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'post_count',
						'title'       => esc_html__( 'Post Count', 'fusion-builder' ),
						'type'        => 'text',
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'term_count',
						'title'       => esc_html__( 'Term Count', 'fusion-builder' ),
						'type'        => 'text',
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'is_term',
						'title'       => esc_html__( 'Term ID', 'fusion-builder' ),
						'type'        => 'text',
						'placeholder' => esc_attr__( 'Term ID', 'fusion-builder' ),
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'featured_images_count',
						'title'       => esc_html__( 'Featured Images Count', 'fusion-builder' ),
						'type'        => 'text',
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'comments_status',
						'title'       => esc_html__( 'Comments Status', 'fusion-builder' ),
						'type'        => 'select',
						'options'     => [
							'open'   => esc_html__( 'Open', 'fusion-builder' ),
							'closed' => esc_html__( 'Closed', 'fusion-builder' ),
						],
						'comparisons' => [
							'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'comments_count',
						'title'       => esc_html__( 'Comments Count', 'fusion-builder' ),
						'type'        => 'text',
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'heading_number',
						'title'       => esc_html__( 'Number Of Headings', 'fusion-builder' ),
						'type'        => 'text',
						'additionals' => [
							'type'        => 'select',
							'options'     => [
								'exclude' => esc_html__( 'Excluding Post Cards', 'fusion-builder' ),
								'include' => esc_html__( 'Including Post Cards', 'fusion-builder' ),
							],
						],
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
							'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
							'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'wp_conditional_tags',
						'title'       => esc_html__( 'WP Conditional Tags', 'fusion-builder' ),
						'placeholder' => esc_attr__( 'Conditional Tag', 'fusion-builder' ),
						'type'        => 'select',
						'options'     => [
							'true'  => esc_html__( 'True', 'fusion-builder' ),
							'false' => esc_html__( 'False', 'fusion-builder' ),
						],
						'additionals' => [
							[
								'type'        => 'select',
								'title'       => esc_html__( 'Conditional Tag', 'fusion-builder' ),
								'options'     => [
									'is_front_page'        => __( 'is_front_page()', 'fusion-builder' ),
									'is_home'              => __( 'is_home()', 'fusion-builder' ),
									'is_single'            => __( 'is_single()', 'fusion-builder' ),
									'is_singular'          => __( 'is_singular()', 'fusion-builder' ),
									'is_page'              => __( 'is_page()', 'fusion-builder' ),
									'is_archive'           => __( 'is_archive()', 'fusion-builder' ),
									'is_tag'               => __( 'is_tag()', 'fusion-builder' ),
									'is_tax'               => __( 'is_tax()', 'fusion-builder' ),
									'is_author'            => __( 'is_author()', 'fusion-builder' ),
									'is_search'            => __( 'is_search()', 'fusion-builder' ),
									'is_404'               => __( 'is_404()', 'fusion-builder' ),
									'is_sticky'            => __( 'is_sticky()', 'fusion-builder' ),
									'is_post_type_archive' => __( 'is_post_type_archive()', 'fusion-builder' ),
									'comments_open'        => __( 'comments_open()', 'fusion-builder' ),
									'is_rtl'               => __( 'is_rtl()', 'fusion-builder' ),
									'is_date'              => __( 'is_date()', 'fusion-builder' ),
									'is_year'              => __( 'is_year()', 'fusion-builder' ),
									'is_month'             => __( 'is_month()', 'fusion-builder' ),
									'is_day'               => __( 'is_day()', 'fusion-builder' ),
								],
							],
							[
								'type'        => 'text',
								'format'      => esc_html__( 'Param', 'fusion-builder' ),
								'placeholder' => esc_html__( 'Additional param to pass.', 'fusion-builder' ),
							],
						],
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
					[
						'id'          => 'active_language',
						'title'       => esc_html__( 'Active Language', 'fusion-builder' ),
						'placeholder' => esc_attr__( 'Conditional Tag', 'fusion-builder' ),
						'type'        => 'text',
						'comparisons' => [
							'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
							'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
						],
					],
				],
			],
		];

		$params = self::maybe_add_woo_options( $params );
		$params = self::maybe_add_ec_options( $params );
		$params = self::maybe_add_acf_options( $params );
		$params = self::maybe_add_custom_options( $params );

		// Override params.
		foreach ( $args as $key => $value ) {
			if ( 'fusion_remove_param' === $value && isset( $params[0][ $key ] ) ) {
				unset( $params[0][ $key ] );
				continue;
			}

			$params[0][ $key ] = $value;
		}

		return $params;
	}

	/**
	 * Returns all user roles.
	 *
	 * @since 3.3
	 * @return array states.
	 */
	public static function get_user_roles() {
		global $wp_roles;
		$roles = [];
		if ( is_array( $wp_roles->roles ) ) {
			foreach ( $wp_roles->roles as $key => $role ) {
				$roles[ $key ] = $role['name'];
			}
		}

		return $roles;
	}

	/**
	 * Adds WooCommerce Options.
	 *
	 * @since 3.3
	 * @param array $params The existing params.
	 * @return array.
	 */
	public static function maybe_add_woo_options( $params ) {
		if ( ! class_exists( 'WooCommerce' ) ) {
			return $params;
		}

		// Product categories.
		$product_categories_field   = 'text';
		$product_categories_options = '';
		$product_categories_count   = wp_count_terms( 'product_cat' );

		if ( 25 > $product_categories_count && 0 < $product_categories_count ) {
			$product_categories = [];
			$categories         = get_terms(
				'product_cat',
				[
					'hide_empty' => false,
				]
			);
			if ( ! empty( $categories ) && ! is_wp_error( $categories ) ) {
				foreach ( $categories as $category ) {
					$product_categories[ $category->term_id ] = $category->name;
				}
			}

			$product_categories_field   = 'select';
			$product_categories_options = $product_categories;
		}

		// Product tags.
		$product_tags_field   = 'text';
		$product_tags_options = '';
		$product_tags_count   = wp_count_terms( 'product_tag' );

		if ( 25 > $product_tags_count && 0 < $product_tags_count ) {
			$product_tags = [];
			$tags         = get_terms(
				'product_tag',
				[
					'hide_empty' => false,
				]
			);
			if ( ! empty( $tags ) && ! is_wp_error( $tags ) ) {
				foreach ( $tags as $tag ) {
					$product_tags[ $tag->term_id ] = $tag->name;
				}
			}

			$product_tags_field   = 'select';
			$product_tags_options = $product_tags;
		}

		// Order statuses.
		$statuses    = wc_get_order_statuses();
		$wc_statuses = [];
		foreach ( $statuses as $status_id => $status_name ) {
			$status_id                 = ( 'wc-' === substr( $status_id, 0, 3 ) ? substr( $status_id, 3 ) : $status_id );
			$wc_statuses[ $status_id ] = $status_name;
		}

		$woo_options = [
			[
				'id'          => 'woo_pages',
				'title'       => esc_html__( 'WooCommerce Pages', 'fusion-builder' ),
				'placeholder' => esc_attr__( 'WooCommerce Page', 'fusion-builder' ),
				'type'        => 'select',
				'options'     => [
					'true'  => esc_html__( 'True', 'fusion-builder' ),
					'false' => esc_html__( 'False', 'fusion-builder' ),
				],
				'additionals' => [
					'type'        => 'select',
					'title'       => esc_html__( 'WooCommerce Page', 'fusion-builder' ),
					'options'     => [
						'is_shop'                => __( 'Is Shop Page', 'fusion-builder' ),
						'is_cart'                => __( 'Is Cart Page', 'fusion-builder' ),
						'is_checkout'            => __( 'Is Checkout Page ', 'fusion-builder' ),
						'is_order_received_page' => __( 'Is Order Received Page', 'fusion-builder' ),
						'is_account_page'        => __( 'Is Account Page', 'fusion-builder' ),
					],
				],
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'cart_status',
				'title'       => esc_html__( 'Cart Status', 'fusion-builder' ),
				'type'        => 'select',
				'options'     => [
					'in'    => esc_html__( 'In', 'fusion-builder' ),
					'empty' => esc_html__( 'Empty', 'fusion-builder' ),
				],
				'comparisons' => [
					'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'sale_status',
				'title'       => esc_html__( 'Sale Status', 'fusion-builder' ),
				'type'        => 'select',
				'options'     => [
					'started' => esc_html__( 'Started', 'fusion-builder' ),
					'ended'   => esc_html__( 'Ended', 'fusion-builder' ),
				],
				'comparisons' => [
					'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'stock_quantity',
				'title'       => esc_html__( 'Stock Quantity', 'fusion-builder' ),
				'type'        => 'text',
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'stock_status',
				'title'       => esc_html__( 'Stock Status', 'fusion-builder' ),
				'type'        => 'select',
				'options'     => [
					'in'  => esc_html__( 'In Stock', 'fusion-builder' ),
					'out' => esc_html__( 'Out of Stock', 'fusion-builder' ),
				],
				'comparisons' => [
					'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'purchased_product',
				'title'       => esc_html__( 'Product Purchase Status', 'fusion-builder' ),
				'type'        => 'select',
				'options'     => [
					'purchased'     => esc_html__( 'Purchased', 'fusion-builder' ),
					'not_purchased' => esc_html__( 'Not Purchased', 'fusion-builder' ),
				],
				'additionals' => [
					'type'        => 'text',
					'title'       => esc_html__( 'Product ID', 'fusion-builder' ),
					'placeholder' => esc_html__( 'ID or empty for current product.', 'fusion-builder' ),
				],
				'comparisons' => [
					'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'product_type',
				'title'       => esc_html__( 'Product Type', 'fusion-builder' ),
				'type'        => 'select',
				'options'     => [
					'simple'   => esc_html__( 'Simple Product', 'fusion-builder' ),
					'grouped'  => esc_html__( 'Grouped Product', 'fusion-builder' ),
					'external' => esc_html__( 'External/Affiliate Product', 'fusion-builder' ),
					'variable' => esc_html__( 'Variable Product', 'fusion-builder' ),
				],
				'comparisons' => [
					'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'product_category',
				'title'       => esc_html__( 'Product Category', 'fusion-builder' ),
				'type'        => $product_categories_field,
				'options'     => $product_categories_options,
				'placeholder' => esc_html__( 'Category Name, Slug or ID', 'fusion-builder' ),
				'comparisons' => [
					'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'product_tag',
				'title'       => esc_html__( 'Product Tag', 'fusion-builder' ),
				'type'        => $product_tags_field,
				'options'     => $product_tags_options,
				'placeholder' => esc_html__( 'Tag Name, Slug or ID', 'fusion-builder' ),
				'comparisons' => [
					'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'woo_free_shipping_min_amount',
				'title'       => esc_html__( 'Free Shipping Min. Amount', 'fusion-builder' ),
				'type'        => 'text',
				'additionals' => [
					'type'        => 'select',
					'title'       => esc_html__( 'Check Type', 'fusion-builder' ),
					'options'     => [
						'full'       => esc_attr__( 'Full', 'fusion-builder' ),
						'missing'    => esc_attr__( 'Missing', 'fusion-builder' ),
						'percentage' => esc_attr__( 'Percentage', 'fusion-builder' ),
					]
				],
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'related_products_count',
				'title'       => esc_html__( 'Related Products', 'fusion-builder' ),
				'type'        => 'text',
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'up_sells_products_count',
				'title'       => esc_html__( 'Up-Sells Products', 'fusion-builder' ),
				'type'        => 'text',
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'cross_sells_products_count',
				'title'       => esc_html__( 'Cross-Sells Products', 'fusion-builder' ),
				'type'        => 'text',
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'product_variations',
				'title'       => esc_html__( 'Product Variations', 'fusion-builder' ),
				'type'        => 'text',
				'placeholder' => esc_html__( 'Attribute Name eg. color or size.', 'fusion-builder' ),
				'comparisons' => [
					'equal'     => esc_attr__( 'Has', 'fusion-builder' ),
					'not-equal' => esc_attr__( 'Has Not', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'order_received_status',
				'title'       => esc_html__( 'Order Received Status', 'fusion-builder' ),
				'type'        => 'select',
				'placeholder' => esc_html__( 'If the order received page (after user checks out), is successful (payment successful) or not (payment denied by bank for example).', 'fusion-builder' ),
				'options'     => $wc_statuses,
				'comparisons' => [
					'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'order_received_total_value',
				'title'       => esc_html__( 'Order Received Total Value', 'fusion-builder' ),
				'type'        => 'text',
				'placeholder' => esc_html__( 'The total value of the order. Works only on order received page (after user checks out).', 'fusion-builder' ),
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'order_received_downloads',
				'title'       => esc_html__( 'Order Received Download Count', 'fusion-builder' ),
				'type'        => 'text',
				'placeholder' => esc_html__( 'How many items can be downloaded on the order received page (after user checks out).', 'fusion-builder' ),
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
				],
			],

		];

		$params[0]['choices'] = array_merge( $params[0]['choices'], $woo_options );

		return $params;
	}

	/**
	 * Adds Event Calendar Options.
	 *
	 * @since 3.3
	 * @param array $params The existing params.
	 * @return array.
	 */
	public static function maybe_add_ec_options( $params ) {
		if ( ! class_exists( 'Tribe__Events__Main' ) ) {
			return $params;
		}

		$ec_options = [
			[
				'id'          => 'event_status',
				'title'       => esc_html__( 'Event Status', 'fusion-builder' ),
				'type'        => 'select',
				'options'     => [
					'started'      => esc_html__( 'Started', 'fusion-builder' ),
					'ended'        => esc_html__( 'Ended', 'fusion-builder' ),
					'scheduled'    => esc_html__( 'Scheduled', 'fusion-builder' ),
					'canceled'     => esc_html__( 'Canceled', 'fusion-builder' ),
					'postponed'    => esc_html__( 'Postponed', 'fusion-builder' ),
					'moved-online' => esc_html__( 'Moved Online', 'fusion-builder' ),
				],
				'comparisons' => [
					'equal'     => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal' => esc_attr__( 'Not Equal To', 'fusion-builder' ),
				],
			],
		];

		$params[0]['choices'] = array_merge( $params[0]['choices'], $ec_options );

		return $params;
	}

	/**
	 * Adds ACF Options.
	 *
	 * @since 3.5
	 * @param array $params The existing params.
	 * @return array.
	 */
	public static function maybe_add_acf_options( $params ) {
		if ( ! class_exists( 'ACF' ) ) {
			return $params;
		}

		$options = [
			[
				'id'          => 'acf_field',
				'title'       => esc_html__( 'ACF Field', 'fusion-builder' ),
				'type'        => 'text',
				'additionals' => [
					'type'        => 'text',
					'title'       => esc_html__( 'Field Name', 'fusion-builder' ),
					'placeholder' => esc_html__( 'Field Name', 'fusion-builder' ),
				],
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
					'contains'     => esc_attr__( 'Contains', 'fusion-builder' ),
					'not-contains' => esc_attr__( 'Does Not Contain', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'acf_repeater_count',
				'title'       => esc_html__( 'ACF Repeater Count', 'fusion-builder' ),
				'type'        => 'text',
				'additionals' => [
					'type'        => 'text',
					'title'       => esc_html__( 'Field Name', 'fusion-builder' ),
					'placeholder' => esc_html__( 'Field Name', 'fusion-builder' ),
				],
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'acf_repeater_single_value',
				'title'       => esc_html__( 'ACF Repeater Single Value', 'fusion-builder' ),
				'type'        => 'text',
				'additionals' => [
					'type'        => 'text',
					'title'       => esc_html__( 'Field', 'fusion-builder' ),
					'placeholder' => 'field[1][name]',
				],
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
					'contains'     => esc_attr__( 'Contains', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'acf_repeater_sub_field',
				'title'       => esc_html__( 'ACF Repeater Sub Field', 'fusion-builder' ),
				'description' => esc_html__( 'Enter repeater sub field name. This option only works on post cards within the ACF repeater loop.', 'fusion-builder' ),
				'type'        => 'text',
				'additionals' => [
					'type'        => 'text',
					'title'       => esc_html__( 'Sub Field name', 'fusion-builder' ),
					'placeholder' => esc_html__( 'Sub Field name', 'fusion-builder' ),
				],
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
					'contains'     => esc_attr__( 'Contains', 'fusion-builder' ),
					'not-contains' => esc_attr__( 'Does Not Contain', 'fusion-builder' ),
				],
			],
			[
				'id'          => 'acf_relationship_count',
				'title'       => esc_html__( 'ACF Relationship Count', 'fusion-builder' ),
				'type'        => 'text',
				'additionals' => [
					'type'        => 'text',
					'title'       => esc_html__( 'Field Name', 'fusion-builder' ),
					'placeholder' => esc_html__( 'Field Name', 'fusion-builder' ),
				],
				'comparisons' => [
					'equal'        => esc_attr__( 'Equal To', 'fusion-builder' ),
					'not-equal'    => esc_attr__( 'Not Equal To', 'fusion-builder' ),
					'greater-than' => esc_attr__( 'Greater Than', 'fusion-builder' ),
					'less-than'    => esc_attr__( 'Less Than', 'fusion-builder' ),
				],
			],
		];

		$params[0]['choices'] = array_merge( $params[0]['choices'], $options );

		return $params;
	}

	/**
	 * Get custom conditional rendering options.
	 *
	 * @access public
	 * @since 3.14.0
	 * @param array $params The existing params.
	 * @return array.
	 */
	public static function get_custom_options() {
		if ( null !== self::$custom_conditions ) {
			return self::$custom_conditions;
		}
		self::$custom_conditions = (array) apply_filters( 'awb_custom_rendering_conditions', [] );
		return self::$custom_conditions;
	}

	/**
	 * Add custom conditional rendering options.
	 *
	 * @access public
	 * @since 3.14.0
	 * @param array $params The existing params.
	 * @return array.
	 */
	public static function maybe_add_custom_options( $params ) {
		$custom_conditions = self::get_custom_options();
		if ( ! empty( $custom_conditions ) ) {
			foreach ( $custom_conditions as $condition ) {
				if ( isset( $condition['param'] ) && is_array( $condition['param'] ) ) {
					$params[0]['choices'][] = $condition['param'];
				}
			}
		}

		return $params;
	}

	/**
	 * Checks if element should render or not.
	 *
	 * @since 3.3
	 * @param array $atts The attributes.
	 * @return bool
	 */
	public static function should_render( $atts ) {
		$logics = [];
		if ( isset( $atts['conditional_logic'] ) ) {
			$logics = json_decode( base64_decode( $atts['conditional_logic'] ) );
		} else if ( isset( $atts['render_logics'] ) && '' !== $atts['render_logics'] ) {
			$logics = json_decode( base64_decode( $atts['render_logics'] ) );
		}

		$current_values = isset( $atts['current_values'] ) ? $atts['current_values'] : [];
		$checks         = [];

		if ( empty( $logics ) ) {
			return true;
		}

		foreach ( $logics as $logic ) {
			$check      = [];
			$operator   = isset( $logic->operator ) ? $logic->operator : '';
			$comparison = isset( $logic->comparison ) ? $logic->comparison : '';
			$field_name = isset( $logic->field ) && ! is_null( $logic->field ) ? str_replace( '[]', '', $logic->field ) : '';

			$desired_value    = isset( $logic->value ) ? $logic->value : '';
			$additionals      = isset( $logic->additionals ) ? $logic->additionals : '';
			$additionals_text = isset( $logic->additionals_text ) ? $logic->additionals_text : '';
			$current_value    = ! empty( $current_values ) && isset( $current_values[ $field_name ] ) ? $current_values[ $field_name ] : self::get_value( $field_name, $desired_value, $additionals, $additionals_text );

			if ( ! $field_name || ! $comparison ) {
				continue;
			}

			array_push( $check, $operator );
			array_push( $check, '' !== $current_value ? self::is_match( $current_value, $desired_value, $comparison, $field_name ) : false );
			array_push( $checks, $check );

			fusion_library()->conditional_loading[] = [
				'operator'      => $operator,
				'comparison'    => $comparison,
				'field_name'    => $field_name,
				'desired_value' => $desired_value,
				'additionals'   => $additionals,
				'current_value' => $current_value,
			];
		}

		if ( count( $checks ) ) {
			return self::match_conditions( $checks );
		}

		return true;
	}

	/**
	 * Gets value.
	 *
	 * @since 3.3
	 * @param string $name        The item name.
	 * @param string $value       The desired name.
	 * @param string $additionals The additional data.
	 * @param string $additionals_text The additional data stored in an additional text field.
	 * @return mixed.
	 */
	public static function get_value( $name, $value, $additionals, $additionals_text ) {
		$woo_options       = [ 'cart_status', 'sale_status', 'stock_quantity' ];
		$event_options     = [ 'event_status' ];
		$acf_options       = [ 'acf_field' ];
		$custom_conditions = self::get_custom_options();
		$post_id           = get_the_ID();

		if ( isset( $custom_conditions[ $name ]['callback'] ) ) {
			return call_user_func_array( $custom_conditions[ $name ]['callback'], [ $value, $additionals ] );
		}

		if ( in_array( $name, $woo_options, true ) && ! class_exists( 'WooCommerce' ) || in_array( $name, $event_options, true ) && ! class_exists( 'Tribe__Events__Main' ) || in_array( $name, $acf_options, true ) && ! class_exists( 'ACF' ) ) {
			return '';
		}

		switch ( $name ) {

			case 'user_state':
				return is_user_logged_in() ? 'logged_in' : 'logged_out';
				
			case 'user_meta':
			case 'user_meta_custom':

				// Defined in helpers.php.
				$meta_value = awb_get_user_meta_value( [ 'meta_key' => $additionals ] );
				return '' !== $meta_value ? $meta_value : null;

			case 'woo_pages':
				$page = isset( $additionals ) && ! empty( $additionals ) ? $additionals : 'is_shop';

				return call_user_func( $page ) ? 'true' : 'false';

			case 'cart_status':
				if ( 'in' === $value ) {
					$is_in_cart = false;
					$product_id = $post_id;
					$parent_id  = wp_get_post_parent_id( $product_id );
					$product_id = $parent_id > 0 ? $parent_id : $product_id;

					if ( is_object( WC()->cart ) ) {
						foreach ( WC()->cart->get_cart() as $cart_item ) {
							if ( $cart_item['product_id'] === $product_id ) {
								$is_in_cart = true;
							}
						}
					}

					return $is_in_cart ? 'in' : null;
				} else {
					return is_object( WC()->cart ) && 0 === WC()->cart->get_cart_contents_count() ? 'empty' : null;
				}

			case 'sale_status':
				$product = wc_get_product( $post_id );

				if ( false === $product ) {
					return '';
				}

				if ( 'started' === $value ) {
					return $product->is_on_sale() ? 'started' : null;
				} else {
					return ! $product->is_on_sale() ? 'ended' : null;
				}

			case 'stock_quantity':
				$product = wc_get_product( $post_id );

				if ( false === $product ) {
					return 0;
				}

				return $product->get_stock_quantity();

			case 'stock_status':
				$product = wc_get_product( $post_id );

				if ( false === $product ) {
					return 0;
				}

				return $product->is_in_stock() ? 'in' : 'out';

			case 'purchased_product':
				$product = isset( $additionals ) && ! empty( $additionals ) ? wc_get_product( $additionals ) : wc_get_product( get_the_ID() );

				if ( false === $product || ! is_user_logged_in() ) {
					return 0;
				}

				return wc_customer_bought_product( '', get_current_user_id(), $product->get_id() ) ? 'purchased' : 'not_purchased';

			case 'product_type':
				$product = wc_get_product( $post_id );

				if ( false === $product ) {
					return 0;
				}

				return $product->get_type();

			case 'product_category':
				return has_term( $value, 'product_cat' ) ? $value : null;
			case 'product_tag':
				return has_term( $value, 'product_tag' ) ? $value : null;
			case 'woo_free_shipping_min_amount':
				$type       = ! empty( $additionals ) ? $additionals : 'missing';
				$min_amount = Fusion_Dynamic_Data_Callbacks::woo_get_free_shipping_min_amount( [ 'display_type' => $type, 'no_html' => true ] );
				return $min_amount;
			case 'related_products_count':
				$product = wc_get_product( $post_id );

				if ( false === $product ) {
					return 0;
				}
				$related_products = wc_get_related_products( $post_id, intval( $value ) + 1 );
				return count( $related_products );
			case 'up_sells_products_count':
				$product = wc_get_product( $post_id );

				if ( false === $product ) {
					return 0;
				}
				return count( $product->get_upsell_ids() );
			case 'cross_sells_products_count':
				if ( is_cart() && is_object( WC()->cart ) ) {
					return count( WC()->cart->get_cross_sells() );
				}

				$product = wc_get_product( $post_id );

				if ( false === $product ) {
					return 0;
				}
				return count( $product->get_cross_sell_ids() );
			case 'product_variations':
				$product = wc_get_product( $post_id );

				if ( false === $product ) {
					return 0;
				}
				if ( ! $product->is_type( 'variable' ) ) {
					return 0;
				}

				$atts = $product->get_variation_attributes();
				return ! empty( $product->get_attributes() ) && is_array( $atts ) && array_key_exists( 'pa_' . strtolower( $value ), $atts ) ? $value : null;
			case 'current_date':
				$format = ! empty( $additionals ) ? $additionals : 'U';
				return wp_date( $format );
			case 'published_date':
				$format = ! empty( $additionals ) ? $additionals : 'U';
				return get_the_time( $format );
			case 'modified_date':
				$format = ! empty( $additionals ) ? $additionals : 'U';
				return get_the_modified_date( $format );
			case 'post_id':
				return $post_id;
			case 'post_type':
				return get_post_type( $post_id );
			case 'post_status':
				if ( post_password_required( $post_id ) || ! empty( get_post( $post_id )->post_password ) ) {
					return 'protected';
				}

				$post_status = str_replace( 'auto-', '', get_post_status( $post_id ) );

				return $post_status;

			case 'post_status_special':
				if ( is_sticky( $post_id )  ) {
					return 'sticky';
				}

				if ( class_exists( 'WooCommerce' ) && is_product() ) {
					$product = wc_get_product( $post_id );

					if ( $product && $product->is_featured() ) {
						return 'featured';
					}
				}

				if ( class_exists( 'Tribe__Events__Main' ) ) {
					$event_post  = get_post( $post_id );
					$is_sticky   = false;
					$is_featured = false;
					if ( $event_post && -1 === (int) $event_post->menu_order ) {
						$is_sticky = true;
					}

					if ( tribe( 'tec.featured_events' )->is_featured( $post_id ) ) {
						$is_featured = true;
					}

					if ( $is_sticky && $is_featured ) {
						return 'sticky_featured';
					} else if ( $is_featured ) {
						return 'featured';
					} else if ( $is_sticky ) {
						return 'sticky';
					}
				}

				return '';

			case 'post_category':
				return has_term( $value, 'category' ) ? $value : null;
			case 'post_tag':
				return has_term( $value, 'post_tag' ) ? $value : null;
			case 'post_count':
				$count = is_archive() || is_search() ? get_queried_object()->count : null;
				return $count;
			case 'term_count':
				if ( is_archive() || is_tax() ) {
					return count(
						get_terms(
							[
								'taxonomy' => get_queried_object()->taxonomy,
								'child_of' => get_queried_object()->term_id,
							]
						)
					);
				} else {
					return null;
				}
			case 'is_term':
				$queried_object = get_queried_object();
				if ( ( is_archive() || is_tax() ) && isset( $queried_object->term_id ) ) {
					return $queried_object->term_id;
				} else {
					return 0;
				}
			case 'featured_images_count':
				return function_exists( 'avada_number_of_featured_images' ) ? avada_number_of_featured_images( true ) : 0;
			case 'comments_status':
				return comments_open() ? 'open' : 'closed';
			case 'comments_count':
				return intval( get_comments_number() );
			case 'event_status':
				if ( ! tribe_is_event( $post_id ) ) {
					return '';
				}		

				if ( 'started' === $value || 'ended' === $value ) {
					$event      = tribe_events_get_event( $post_id );
					$end_date   = tribe_get_end_date( $event, true, 'U' );
					$start_date = tribe_get_start_date( $event, true, 'U' );

					if ( 'started' === $value ) {
						return time() < $end_date ? 'started' : null;
					} else {
						return time() > $end_date ? 'ended' : null;
					}
				} else {
					return get_post_meta( $post_id, '_tribe_events_status', true );	
				}

			case 'device_type':
				if ( fusion_library()->device_detection->is_mobile() && 'mobile_tablet' !== $value ) {
					return 'mobile';
				} elseif ( fusion_library()->device_detection->is_tablet() && 'mobile_tablet' !== $value ) {
					return 'tablet';
				} elseif ( ! wp_is_mobile() ) {
					return 'desktop';
				} elseif ( wp_is_mobile() ) {
					return 'mobile_tablet';
				}
				return '';

			case 'user_agent':
				return isset( $_SERVER['HTTP_USER_AGENT'] ) ? wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

			case 'referrer':
				return wp_get_referer();

			case 'user_role':
				$user = wp_get_current_user();
				return 0 !== $user->ID ? $user->roles : [];

			case 'get_var':
				if ( ! isset( $_GET[ $additionals ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
					return null;
				}
				if ( is_array( $_GET[ $additionals ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
					return array_map( 'sanitize_text_field', $_GET[ $additionals ] ); // phpcs:ignore WordPress.Security
				}

				return sanitize_text_field( wp_unslash( $_GET[ $additionals ] ) ); // phpcs:ignore WordPress.Security.NonceVerification

			case 'session_var':
				if ( ! isset( $_SESSION[ $additionals ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
					return null;
				}
				if ( is_array( $_SESSION[ $additionals ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
					return array_map( 'sanitize_text_field', $_SESSION[ $additionals ] ); // phpcs:ignore WordPress.Security
				}

				return sanitize_text_field( wp_unslash( $_SESSION[ $additionals ] ) ); // phpcs:ignore WordPress.Security.NonceVerification				
			case 'custom_field':
				$post_meta = get_post_meta( $post_id, $additionals, true );
				return ! empty( $post_meta ) ? $post_meta : null;

			case 'acf_field':
				if ( $op_field = Fusion_Dynamic_Data_Callbacks::get_acf_op_option( $additionals, 'true' ) ) {
					$acf_field    = $op_field['value'];
					$field_object = $op_field['object'];
				} else {
					$acf_field    = ! is_archive() ? get_field( $additionals ) : get_field( $additionals, get_queried_object() );
					$field_object = get_field_object( $additionals );
				}

				if ( isset( $field_object['type'] ) && 'true_false' === $field_object['type'] ) {
					if ( true === $acf_field ) {
						$acf_field = is_numeric( $value ) ? '1' : 'true';
					} else if ( false === $acf_field ) {
						$acf_field = is_numeric( $value ) ? '0' : 'false';
					}
				} else if ( empty( $acf_field ) ) {
					$acf_field = null;
				}

				return $acf_field;

			case 'acf_repeater_count':
				$count = 0;

				if ( class_exists( 'ACF' ) && $additionals ) {
					if ( 'awb_acfop_' === substr( $additionals, 0, 10 ) ) {
						$post_id = 'option';
						if ( 1 === preg_match( '/awb_acfop_.+__/', $additionals, $check ) ) {
							$post_id = trim( str_replace( 'awb_acfop_', '', $check[0] ), '__' );
						}

						$have_rows = have_rows( str_replace( 'awb_acfop_', '', $additionals ), $post_id );
					} else {
						$have_rows = have_rows( $additionals );
					}

					if ( $have_rows ) {
						if ( $op_field = Fusion_Dynamic_Data_Callbacks::get_acf_op_option( $additionals ) ) {
							$acf_field = $op_field;
						} else {
							$acf_field = ! is_archive() ? get_field( $additionals ) : get_field( $additionals, get_queried_object() );
						}

						$count = is_array( $acf_field ) ? count( $acf_field ) : $acf_field;
					}
				}

				return $count;

			case 'acf_repeater_single_value':
				if ( ! $additionals ) {
					return '';
				}
				preg_match( '/.+?(?=\[)/', $additionals, $field );
				$field = $field[0];

				preg_match_all( '/\[(.*?)\]/', $additionals, $keys );

				$keys  = $keys[1];
				$index = isset( $keys[0] ) ? $keys[0] : '';
				$key   = isset( $keys[1] ) ? $keys[1] : '';

				$value = Fusion_Dynamic_Data_Callbacks::acf_get_repeater_single_field(
					[
						'field' => $field,
						'index' => $index,
						'key'   => $key,
					]
				);

				return $value;

			case 'acf_repeater_sub_field':
				if ( ! $additionals ) {
					return '';
				}

				$value = Fusion_Dynamic_Data_Callbacks::acf_get_repeater_sub_field( [ 'sub_field' => $additionals ] );

				return $value;
			case 'acf_relationship_count':
				$count = 0;
				if ( class_exists( 'ACF' ) && $additionals && have_rows( $additionals ) ) {
					$count = count( get_field( $additionals, false, false ) );
				}
				return $count;
			case 'heading_number':
				return $additionals ? awb_get_approx_nr_of_headings( (int) $post_id, $additionals ) : awb_get_approx_nr_of_headings( (int) $post_id );

			case 'wp_conditional_tags':
				$result = $additionals_text ? call_user_func( $additionals, $additionals_text ) : call_user_func( $additionals );
 
				return $result ? 'true' : 'false';

			case 'active_language':
				return Fusion_Multilingual::get_active_language();

			case 'order_received_status':
				global $wp;

				if ( is_object( $wp ) && property_exists( $wp, 'query_vars' ) && isset( $wp->query_vars['order-received'] ) ) {
					$wc_order = wc_get_order( apply_filters( 'woocommerce_thankyou_order_id', absint( $wp->query_vars['order-received'] ) ) );
				} else {
					return '';
				}
				return $wc_order->get_status();

			case 'order_received_total_value':
				global $wp;

				if ( is_object( $wp ) && property_exists( $wp, 'query_vars' ) && isset( $wp->query_vars['order-received'] ) ) {
					$wc_order = wc_get_order( apply_filters( 'woocommerce_thankyou_order_id', absint( $wp->query_vars['order-received'] ) ) );
				} else {
					return false;
				}

				return $wc_order->get_total();

			case 'order_received_downloads':
				global $wp;

				if ( is_object( $wp ) && property_exists( $wp, 'query_vars' ) && isset( $wp->query_vars['order-received'] ) ) {
					$wc_order = wc_get_order( apply_filters( 'woocommerce_thankyou_order_id', absint( $wp->query_vars['order-received'] ) ) );
				} else {
					return false;
				}

				if ( $wc_order->has_downloadable_item() && $wc_order->is_download_permitted() ) {
					return count( $wc_order->get_downloadable_items() );
				}

				return false;

			case 'post_term':
				global $post;
				$taxonomy_ids = [];

				if ( ! $post ) {
					return $taxonomy_ids;
				}

				$post_taxonomies = get_object_taxonomies( $post, 'objects' );

				if ( ! is_array( $post_taxonomies ) ) {
					return $taxonomy_ids;
				}

				foreach ( $post_taxonomies as $taxonomy ) {
					$terms = get_the_terms( $post, $taxonomy->name );
					if ( ! is_array( $terms ) ) {
						continue;
					}

					foreach ( $terms as $term ) {
						array_push( $taxonomy_ids, $term->term_id );
					}
				}

				return $taxonomy_ids;

		}
	}

	/**
	 * Matches current and desired values.
	 *
	 * @since 3.3
	 * @param mixed  $current_value The current value.
	 * @param string $desired_value The desired value.
	 * @param string $comparison    The desired comparison.
	 * @param string $field_name    The field name.
	 * @return bool
	 */
	public static function is_match( $current_value, $desired_value, $comparison, $field_name ) {
		
		$current_value = self::format_string( $current_value, $field_name );
		$desired_value = self::format_string( $desired_value, $field_name );

		switch ( $comparison ) {
			case 'equal':
				return is_array( $current_value ) ? in_array( $desired_value, $current_value ) : $current_value === $desired_value; // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict

			case 'not-equal':
				return is_array( $current_value ) ? ! in_array( $desired_value, $current_value ) : $current_value !== $desired_value; // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict

			case 'greater-than':
				return floatval( $current_value ) > floatval( $desired_value );

			case 'less-than':
				return floatval( $current_value ) < floatval( $desired_value );

			case 'contains':
				return is_array( $current_value ) ? in_array( $desired_value, $current_value ) : false !== strpos( $current_value, $desired_value );

			case 'not-contains':
				return is_array( $current_value ) ? ! in_array( $desired_value, $current_value ) : false === strpos( $current_value, $desired_value );
		}

		return false;
	}

	/**
	 * Format variables to be lowercase strings.
	 *
	 * @static
	 * @since 3.11.3
	 * @access public
	 * @param mixed $value The current value.
	 * @param string $field_name    The field name.
	 * @return mixed The formatted value.
	 */
	public static function format_string( $value, $field_name = '' ) {
		if ( 'published_date' === $field_name || 'modified_date' === $field_name || 'current_date' === $field_name ) {
			$value = strtotime( $value );
		} else if ( is_array( $value ) ) {
			$value = array_map( [ 'Fusion_Builder_Conditional_Render_Helper', 'format_string' ], $value );
		} elseif ( is_null( $value ) || is_bool( $value ) || is_numeric( $value ) || is_string( $value ) ) {
			$value = strtolower( (string) $value );
		}

		return $value;
	}

	/**
	 * Matches conditions.
	 *
	 * @since 3.3
	 * @param array $checks An array of all the conditions.
	 * @return bool.
	 */
	public static function match_conditions( $checks ) {
		$is_match = null;
		$encoded  = wp_json_encode( $checks );

		// If all conditions are of OR type.
		if ( false === strpos( $encoded, 'and' ) ) {
			foreach ( $checks as $check ) {
				$is_match = null === $is_match ? $check[1] : $is_match;
				$is_match = $is_match || $check[1];
			}
			return $is_match;
		}

		// If all conditions are of AND type.
		if ( false === strpos( $encoded, 'or' ) ) {
			foreach ( $checks as $check ) {
				$is_match = null === $is_match ? $check[1] : $is_match;
				$is_match = $is_match && $check[1];
			}
			return $is_match;
		}

		if ( 'or' === fusion_library()->get_option( 'rendering_logic_binding' ) ) {
			return self::evaluate_conditions_split_on_or( $checks );
		} else {
			return self::match_mixed_conditions( $checks );
		}
	}

	/**
	 * Evaluates the mixed conditions, splitting at OR operators.
	 *
	 * @since 3.15.0
	 * @param array $checks An array of all the conditions.
	 * @return bool.
	 */	
	public static function evaluate_conditions_split_on_or( array $checks ): bool {
		$groups        = [];
		$current_group = [];

		foreach ( $checks as $check ) {
			[ $operator, $value ] = $check;

			// Add this condition's value to the current group first.
			$current_group[] = (bool) $value;

			// The operator on each condition is the gutter pointing OUTWARD toward the
			// next condition. An 'or' operator means "seal the current AND-group after me".
			if ( 'or' === $operator ) {
				$groups[]      = $current_group;
				$current_group = [];
			}
		}

		// Push the last group (conditions whose final gutter is AND, or the only group).
		if ( ! empty( $current_group ) ) {
			$groups[] = $current_group;
		}

		// Evaluate each AND-group; return true as soon as one passes (OR semantics).
		foreach ( $groups as $group ) {
			$and_result = true;

			foreach ( $group as $value ) {
				$and_result = $and_result && $value;
				if ( false === $and_result ) {
					break; // Short-circuit AND.
				}
			}

			// OR short-circuit: if this AND-group is true, the whole expression is true.
			if ( true === $and_result ) {
				return true;
			}
		}

		// No group passed.
		return false;
	}

	/**
	 * Matches mixed conditions.
	 *
	 * @since 3.3
	 * @param array $checks An array of all the conditions.
	 * @return bool.
	 */
	public static function match_mixed_conditions( $checks ) {
		$collected_conditions = [];
		$current_operation    = '';
		$size                 = count( $checks );
		$j                    = 0;
		$k                    = 0;

		// Combine conditions based on comparison operator change.
		for ( $i = 0; $i < $size; $i++ ) {

			if ( '' === $current_operation || $current_operation === $checks[ $i ][0] ) {
				$collected_conditions[ $j ][ $k ] = $checks[ $i ][1];
				$k++;
				$collected_conditions[ $j ][ $k ] = $checks[ $i ][0];
				$k++;
				$current_operation = $checks[ $i ][0];
			} else {
				$collected_conditions[ $j ][ $k ] = $checks[ $i ][1];
				$k++;
				$collected_conditions[ $j ][ $k ] = $checks[ $i ][0];
				$j++;
				$k                 = 0;
				$current_operation = '';
			}
		}

		// Process conditions.
		$final_conditions = [];
		$main_operator    = '';
		$temp_result      = '';
		$inner_operator   = '';
		$operand_first    = '';
		$operand_second   = '';

		foreach ( $collected_conditions as $condition ) {
			$size = count( $condition );
			if ( $size < 3 ) {
				$final_conditions[] = $condition[0];
				$final_conditions[] = $condition[1];
				continue;
			}

			for ( $i = 0; $i < $size - 1; $i++ ) {

				if ( '' === $temp_result ) {
					$operand_first  = $condition[ $i ];
					$operand_second = $condition[ $i + 2 ];
					$inner_operator = $condition[ $i + 1 ];
					$i              = $i + 2;

					$temp_result = 'or' === $inner_operator ? ( $operand_first || $operand_second ) : ( $operand_first && $operand_second );
				} else {
					$operand_first  = $temp_result;
					$operand_second = $condition[ $i + 1 ];
					$inner_operator = $condition[ $i ];

					$temp_result = 'or' === $inner_operator ? ( $operand_first || $operand_second ) : ( $operand_first && $operand_second );
					$i++;
				}

				if ( true !== $temp_result ) {
					$temp_result = false;
				}
			}
			$main_operator = $condition;

			$final_conditions[] = $temp_result;
			$final_conditions[] = $main_operator[ $size - 1 ];
			$temp_result        = '';
		}

		// Final comparisons.
		$temp_result    = '';
		$inner_operator = '';
		$operand_first  = '';
		$operand_second = '';
		$size           = count( $final_conditions );

		if ( 3 > $size ) {
			return $final_conditions[0];
		}

		for ( $i = 0; $i < $size - 1; $i++ ) {
			if ( '' === $temp_result ) {
				$operand_first  = $final_conditions[ $i ];
				$operand_second = $final_conditions[ $i + 2 ];
				$inner_operator = $final_conditions[ $i + 1 ];
				$i              = $i + 2;

				$temp_result = 'or' === $inner_operator ? ( $operand_first || $operand_second ) : ( $operand_first && $operand_second );
			} else {
				$operand_first  = $temp_result;
				$operand_second = $final_conditions[ $i + 1 ];
				$inner_operator = $final_conditions[ $i ];

				$temp_result = 'or' === $inner_operator ? ( $operand_first || $operand_second ) : ( $operand_first && $operand_second );
				$i++;
			}

			if ( true !== $temp_result ) {
				$temp_result = false;
			}
		}

		return $temp_result;
	}
}
