Exemple #1
0
 function et_pb_add_builder_page_js_css()
 {
     global $typenow, $post;
     if (et_is_yoast_seo_plugin_active()) {
         // Get list of shortcodes that causes issue if being triggered in admin
         $conflicting_shortcodes = et_pb_admin_excluded_shortcodes();
         if (!empty($conflicting_shortcodes)) {
             foreach ($conflicting_shortcodes as $shortcode) {
                 remove_shortcode($shortcode);
             }
         }
         // save the original content of $post variable
         $post_original = $post;
         // get the content for yoast
         $post_content_processed = do_shortcode($post->post_content);
         // set the $post to the original content to make sure it wasn't changed by do_shortcode()
         $post = $post_original;
     }
     // we need some post data when editing saved templates.
     if ('et_pb_layout' === $typenow) {
         $template_scope = wp_get_object_terms(get_the_ID(), 'scope');
         $is_global_template = !empty($template_scope[0]) ? $template_scope[0]->slug : 'regular';
         $post_id = get_the_ID();
         // Check whether it's a Global item's page and display wp error if Global items disabled for current user
         if (!et_pb_is_allowed('edit_global_library') && 'global' === $is_global_template) {
             wp_die(esc_html__("you don't have sufficient permissions to access this page", 'et_builder'));
         }
         $built_for_post_type = get_post_meta(get_the_ID(), '_et_pb_built_for_post_type', true);
         $built_for_post_type = '' !== $built_for_post_type ? $built_for_post_type : 'page';
         $post_type = apply_filters('et_pb_built_for_post_type', $built_for_post_type, get_the_ID());
     } else {
         $is_global_template = '';
         $post_id = '';
         $post_type = $typenow;
     }
     // we need this data to create the filter when adding saved modules
     $layout_categories = get_terms('layout_category');
     $layout_cat_data = array();
     $layout_cat_data_json = '';
     if (is_array($layout_categories) && !empty($layout_categories)) {
         foreach ($layout_categories as $category) {
             $layout_cat_data[] = array('slug' => $category->slug, 'name' => $category->name);
         }
     }
     if (!empty($layout_cat_data)) {
         $layout_cat_data_json = json_encode($layout_cat_data);
     }
     // Set fixed protocol for preview URL to prevent cross origin issue
     $preview_scheme = is_ssl() ? 'https' : 'http';
     $preview_url = esc_url(home_url('/'));
     if ('https' === $preview_scheme && !strpos($preview_url, 'https://')) {
         $preview_url = str_replace('http://', 'https://', $preview_url);
     }
     // force update cache if need to regenerate MailChimp or AWeber Lists or if et_pb_clear_templates_cache option is set to on
     if ('on' === et_get_option('divi_regenerate_mailchimp_lists', 'false') || 'on' === et_get_option('divi_regenerate_aweber_lists', 'false') || 'on' === et_get_option('et_pb_clear_templates_cache', 'off')) {
         $force_cache_value = true;
     } else {
         $force_cache_value = false;
     }
     $force_cache_update = false !== $force_cache_value ? $force_cache_value : ET_BUILDER_FORCE_CACHE_PURGE;
     // delete et_pb_clear_templates_cache option it's not needed anymore
     et_delete_option('et_pb_clear_templates_cache');
     wp_enqueue_script('jquery-ui-core');
     wp_enqueue_script('underscore');
     wp_enqueue_script('backbone');
     wp_enqueue_script('google-maps-api', esc_url(add_query_arg(array('v' => 3, 'sensor' => 'false'), is_ssl() ? 'https://maps-api-ssl.google.com/maps/api/js' : 'http://maps.google.com/maps/api/js')), array(), '3', true);
     wp_enqueue_script('wp-color-picker');
     wp_enqueue_style('wp-color-picker');
     wp_enqueue_script('wp-color-picker-alpha', ET_BUILDER_URI . '/scripts/ext/wp-color-picker-alpha.min.js', array('jquery', 'wp-color-picker'), ET_BUILDER_VERSION, true);
     wp_register_script('chart', ET_BUILDER_URI . '/scripts/ext/chart.min.js', array(), ET_BUILDER_VERSION, true);
     wp_register_script('jquery-tablesorter', ET_BUILDER_URI . '/scripts/ext/jquery.tablesorter.min.js', array('jquery'), ET_BUILDER_VERSION, true);
     // load 1.10.4 versions of jQuery-ui scripts if WP version is less than 4.5, load 1.11.4 version otherwise
     if (et_pb_is_wp_old_version()) {
         wp_enqueue_script('et_pb_admin_date_js', ET_BUILDER_URI . '/scripts/ext/jquery-ui-1.10.4.custom.min.js', array('jquery'), ET_BUILDER_VERSION, true);
     } else {
         wp_enqueue_script('et_pb_admin_date_js', ET_BUILDER_URI . '/scripts/ext/jquery-ui-1.11.4.custom.min.js', array('jquery'), ET_BUILDER_VERSION, true);
     }
     wp_enqueue_script('et_pb_admin_date_addon_js', ET_BUILDER_URI . '/scripts/ext/jquery-ui-timepicker-addon.js', array('et_pb_admin_date_js'), ET_BUILDER_VERSION, true);
     wp_enqueue_script('validation', ET_BUILDER_URI . '/scripts/ext/jquery.validate.js', array('jquery'), ET_BUILDER_VERSION, true);
     wp_enqueue_script('minicolors', ET_BUILDER_URI . '/scripts/ext/jquery.minicolors.js', array('jquery'), ET_BUILDER_VERSION, true);
     wp_enqueue_script('et_pb_cache_notice_js', ET_BUILDER_URI . '/scripts/cache_notice.js', array('jquery', 'et_pb_admin_js', 'et_pb_admin_global_js'), ET_BUILDER_VERSION, true);
     wp_localize_script('et_pb_cache_notice_js', 'et_pb_notice_options', apply_filters('et_pb_notice_options_builder', array('product_version' => ET_BUILDER_PRODUCT_VERSION)));
     wp_enqueue_script('et_pb_admin_js', ET_BUILDER_URI . '/scripts/builder.js', array('jquery', 'jquery-ui-core', 'underscore', 'backbone', 'chart', 'jquery-tablesorter', 'et_pb_admin_global_js'), ET_BUILDER_VERSION, true);
     wp_localize_script('et_pb_admin_js', 'et_pb_options', apply_filters('et_pb_options_builder', array('debug' => true, 'ajaxurl' => admin_url('admin-ajax.php'), 'home_url' => home_url(), 'preview_url' => add_query_arg('et_pb_preview', 'true', $preview_url), 'et_admin_load_nonce' => wp_create_nonce('et_admin_load_nonce'), 'images_uri' => ET_BUILDER_URI . '/images', 'post_type' => $post_type, 'et_builder_module_parent_shortcodes' => ET_Builder_Element::get_parent_shortcodes($post_type), 'et_builder_module_child_shortcodes' => ET_Builder_Element::get_child_shortcodes($post_type), 'et_builder_module_raw_content_shortcodes' => ET_Builder_Element::get_raw_content_shortcodes($post_type), 'et_builder_modules' => ET_Builder_Element::get_modules_js_array($post_type), 'et_builder_modules_count' => ET_Builder_Element::get_modules_count($post_type), 'et_builder_modules_with_children' => ET_Builder_Element::get_shortcodes_with_children($post_type), 'et_builder_templates_amount' => ET_BUILDER_AJAX_TEMPLATES_AMOUNT, 'default_initial_column_type' => apply_filters('et_builder_default_initial_column_type', '4_4'), 'default_initial_text_module' => apply_filters('et_builder_default_initial_text_module', 'et_pb_text'), 'section_only_row_dragged_away' => esc_html__('The section should have at least one row.', 'et_builder'), 'fullwidth_module_dragged_away' => esc_html__('Fullwidth module can\'t be used outside of the Fullwidth Section.', 'et_builder'), 'stop_dropping_3_col_row' => esc_html__('3 column row can\'t be used in this column.', 'et_builder'), 'preview_image' => esc_html__('Preview', 'et_builder'), 'empty_admin_label' => esc_html__('Module', 'et_builder'), 'video_module_image_error' => esc_html__('Still images cannot be generated from this video service and/or this video format', 'et_builder'), 'geocode_error' => esc_html__('Geocode was not successful for the following reason', 'et_builder'), 'geocode_error_2' => esc_html__('Geocoder failed due to', 'et_builder'), 'no_results' => esc_html__('No results found', 'et_builder'), 'all_tab_options_hidden' => esc_html__('No available options for this configuration.', 'et_builder'), 'update_global_module' => esc_html__('You\'re about to update global module. This change will be applied to all pages where you use this module. Press OK if you want to update this module', 'et_builder'), 'global_row_alert' => esc_html__('You cannot add global rows into global sections', 'et_builder'), 'global_module_alert' => esc_html__('You cannot add global modules into global sections or rows', 'et_builder'), 'all_cat_text' => esc_html__('All Categories', 'et_builder'), 'is_global_template' => $is_global_template, 'template_post_id' => $post_id, 'layout_categories' => $layout_cat_data_json, 'map_pin_address_error' => esc_html__('Map Pin Address cannot be empty', 'et_builder'), 'map_pin_address_invalid' => esc_html__('Invalid Pin and address data. Please try again.', 'et_builder'), 'locked_section_permission_alert' => esc_html__('You do not have permission to unlock this section.', 'et_builder'), 'locked_row_permission_alert' => esc_html__('You do not have permission to unlock this row.', 'et_builder'), 'locked_module_permission_alert' => esc_html__('You do not have permission to unlock this module.', 'et_builder'), 'locked_item_permission_alert' => esc_html__('You do not have permission to perform this task.', 'et_builder'), 'localstorage_unavailability_alert' => esc_html__('Unable to perform copy/paste process due to inavailability of localStorage feature in your browser. Please use latest modern browser (Chrome, Firefox, or Safari) to perform copy/paste process', 'et_builder'), 'invalid_color' => esc_html__('Invalid Color', 'et_builder'), 'et_pb_preview_nonce' => wp_create_nonce('et_pb_preview_nonce'), 'is_divi_library' => 'et_pb_layout' === $typenow ? 1 : 0, 'layout_type' => 'et_pb_layout' === $typenow ? et_pb_get_layout_type(get_the_ID()) : 0, 'is_plugin_used' => et_is_builder_plugin_active(), 'yoast_content' => et_is_yoast_seo_plugin_active() ? $post_content_processed : '', 'ab_db_status' => true === et_pb_db_status_up_to_date() ? 'exists' : 'not_exists', 'ab_testing_builder_nonce' => wp_create_nonce('ab_testing_builder_nonce'), 'page_color_palette' => get_post_meta(get_the_ID(), '_et_pb_color_palette', true), 'default_color_palette' => implode('|', et_pb_get_default_color_palette()), 'page_section_bg_color' => get_post_meta(get_the_ID(), '_et_pb_section_background_color', true), 'page_gutter_width' => '' !== ($saved_gutter_width = get_post_meta(get_the_ID(), '_et_pb_gutter_width', true)) ? $saved_gutter_width : et_get_option('gutter_width', 3), 'product_version' => ET_BUILDER_VERSION, 'verb' => array('did' => esc_html__('Did', 'et_builder'), 'added' => esc_html__('Added', 'et_builder'), 'edited' => esc_html__('Edited', 'et_builder'), 'removed' => esc_html__('Removed', 'et_builder'), 'moved' => esc_html__('Moved', 'et_builder'), 'expanded' => esc_html__('Expanded', 'et_builder'), 'collapsed' => esc_html__('Collapsed', 'et_builder'), 'locked' => esc_html__('Locked', 'et_builder'), 'unlocked' => esc_html__('Unlocked', 'et_builder'), 'cloned' => esc_html__('Cloned', 'et_builder'), 'cleared' => esc_html__('Cleared', 'et_builder'), 'enabled' => esc_html__('Enabled', 'et_builder'), 'disabled' => esc_html__('Disabled', 'et_builder'), 'copied' => esc_html__('Copied', 'et_builder'), 'renamed' => esc_html__('Renamed', 'et_builder'), 'loaded' => esc_html__('Loaded', 'et_builder'), 'turnon' => esc_html__('Turned On', 'et_builder'), 'turnoff' => esc_html__('Turned Off', 'et_builder')), 'noun' => array('section' => esc_html__('Section', 'et_builder'), 'saved_section' => esc_html__('Saved Section', 'et_builder'), 'fullwidth_section' => esc_html__('Fullwidth Section', 'et_builder'), 'specialty_section' => esc_html__('Specialty Section', 'et_builder'), 'column' => esc_html__('Column', 'et_builder'), 'row' => esc_html__('Row', 'et_builder'), 'saved_row' => esc_html__('Saved Row', 'et_builder'), 'module' => esc_html__('Module', 'et_builder'), 'saved_module' => esc_html__('Saved Module', 'et_builder'), 'page' => esc_html__('Page', 'et_builder'), 'layout' => esc_html__('Layout', 'et_builder'), 'abtesting' => esc_html__('Split Testing', 'et_builder')), 'addition' => array('phone' => esc_html__('on Phone', 'et_builder'), 'tablet' => esc_html__('on Tablet', 'et_builder'), 'desktop' => esc_html__('on Desktop', 'et_builder')), 'invalid_color' => esc_html__('Invalid Color', 'et_builder'), 'et_pb_preview_nonce' => wp_create_nonce('et_pb_preview_nonce'), 'is_divi_library' => 'et_pb_layout' === $typenow ? 1 : 0, 'layout_type' => 'et_pb_layout' === $typenow ? et_pb_get_layout_type(get_the_ID()) : 0, 'is_plugin_used' => et_is_builder_plugin_active(), 'yoast_content' => et_is_yoast_seo_plugin_active() ? $post_content_processed : '', 'product_version' => ET_BUILDER_PRODUCT_VERSION, 'force_cache_purge' => (int) $force_cache_update, 'memory_limit_increased' => esc_html__('Your memory limit has been increased', 'et_builder'), 'memory_limit_not_increased' => esc_html__("Your memory limit can't be changed automatically", 'et_builder'))));
     wp_localize_script('et_pb_admin_js', 'et_pb_ab_js_options', apply_filters('et_pb_ab_js_options', array('test_id' => $post->ID, 'has_report' => et_pb_ab_has_report($post->ID), 'has_permission' => et_pb_is_allowed('ab_testing'), 'refresh_interval_duration' => et_pb_ab_get_refresh_interval_duration($post->ID), 'refresh_interval_durations' => et_pb_ab_refresh_interval_durations(), 'analysis_formula' => et_pb_ab_get_analysis_formulas(), 'have_conversions' => et_pb_ab_get_modules_have_conversions(), 'sales_title' => esc_html__('Sales', 'et_builder'), 'force_cache_purge' => (int) $force_cache_update, 'total_title' => esc_html__('Total', 'et_builder'), 'subjects_rank' => 'on' === get_post_meta($post->ID, '_et_pb_use_builder', true) ? et_pb_ab_get_saved_subjects_ranks($post->ID) : false, 'subjects_rank_color' => et_pb_ab_get_subject_rank_colors(), 'has_no_permission' => array('title' => esc_html__('Unauthorized Action', 'et_builder'), 'desc' => esc_html__('You do not have permission to edit the module, row or section in this split test.', 'et_builder')), 'select_ab_testing_subject' => array('title' => esc_html__('Select Split Testing Subject', 'et_builder'), 'desc' => esc_html__('You have activated the Divi Leads Split Testing System. Using split testing, you can create different element variations on your page to find out which variation most positively affects the conversion rate of your desired goal. After closing this window, please click on the section, row or module that you would like to split test.', 'et_builder')), 'select_ab_testing_goal' => array('title' => esc_html__('Select Your Goal', 'et_builder'), 'desc' => esc_html__('Congratulations, you have selected a split testing subject! Next you need to select your goal. After closing this window, please click the section, row or module that you want to use as your goal. Depending on the element you choose, Divi will track relevant conversion rates for clicks, reads or sales. For example, if you select a Call To Action module as your goal, then Divi will track how variations in your test subjects affect how often visitors read and click the button in your Call To Action module. The test subject itself can also be selected as your goal.', 'et_builder')), 'configure_ab_testing_alternative' => array('title' => esc_html__('Configure Subject Variations', 'et_builder'), 'desc' => esc_html__('Congratulations, your split test is ready to go! You will notice that your split testing subject has been duplicated. Each split testing variation will be displayed to your visitors and statistics will be collected to figure out which variation results in the highest goal conversion rate. Your test will begin when you save this page.', 'et_builder')), 'select_ab_testing_winner_first' => array('title' => esc_html__('Select Split Testing Winner', 'et_builder'), 'desc' => esc_html__('Before ending your split test, you must choose which split testing variation to keep. Please select your favorite or highest converting subject. Alternative split testing subjects will be removed.', 'et_builder')), 'select_ab_testing_subject_first' => array('title' => esc_html__('Select Split Testing Subject', 'et_builder'), 'desc' => esc_html__('You need to select a split testing subject first.', 'et_builder')), 'select_ab_testing_goal_first' => array('title' => esc_html__('Select Split Testing Goal', 'et_builder'), 'desc' => esc_html__('You need to select a split testing goal first. ', 'et_builder')), 'cannot_select_subject_parent_as_goal' => array('title' => esc_html__('Select A Different Goal', 'et_builder'), 'desc' => esc_html__('This element cannot be used as a your split testing goal. Please select a different module, or section.', 'et_builder')), 'cannot_save_app_layout_has_ab_testing' => array('title' => esc_html__('Can\'t Save Layout', 'et_builder'), 'desc' => esc_html__('You cannot save layout while a split test is running. Please end your split test and then try again.', 'et_builder')), 'cannot_save_section_layout_has_ab_testing' => array('title' => esc_html__('Can\'t Save Section', 'et_builder'), 'desc' => esc_html__('You cannot save this section while a split test is running. Please end your split test and then try again.', 'et_builder')), 'cannot_save_row_layout_has_ab_testing' => array('title' => esc_html__('Can\'t Save Row', 'et_builder'), 'desc' => esc_html__('You cannot save this row while a split test is running. Please end your split test and then try again.', 'et_builder')), 'cannot_save_row_inner_layout_has_ab_testing' => array('title' => esc_html__('Can\'t Save Row', 'et_builder'), 'desc' => esc_html__('You cannot save this row while a split test is running. Please end your split test and then try again.', 'et_builder')), 'cannot_save_module_layout_has_ab_testing' => array('title' => esc_html__('Can\'t Save Module', 'et_builder'), 'desc' => esc_html__('You cannot save this module while a split test is running. Please end your split test and then try again.', 'et_builder')), 'cannot_load_layout_has_ab_testing' => array('title' => esc_html__('Can\'t Load Layout', 'et_builder'), 'desc' => esc_html__('You cannot load a new layout while a split test is running. Please end your split test and then try again.', 'et_builder')), 'cannot_clear_layout_has_ab_testing' => array('title' => esc_html__('Can\'t Clear Layout', 'et_builder'), 'desc' => esc_html__('You cannot clear your layout while a split testing is running. Please end your split test before clearing your layout.', 'et_builder')), 'cannot_import_export_layout_has_ab_testing' => array('title' => esc_html__("Can't Import/Export Layout", 'et_builder'), 'desc' => esc_html__('You cannot import or export a layout while a split test is running. Please end your split test and then try again.', 'et_builder')), 'cannot_move_module_goal_out_from_subject' => array('title' => esc_html__('Can\'t Move Goal', 'et_builder'), 'desc' => esc_html__('Once set, a goal that has been placed inside a split testing subject cannot be moved outside the split testing subject. You can end your split test and start a new one if you would like to make this change.', 'et_builder')), 'cannot_move_row_goal_out_from_subject' => array('title' => esc_html__('Can\'t Move Goal', 'et_builder'), 'desc' => esc_html__('Once set, a goal that has been placed inside a split testing subject cannot be moved outside the split testing subject. You can end your split test and start a new one if you would like to make this change.', 'et_builder')), 'cannot_move_goal_into_subject' => array('title' => esc_html__('Can\'t Move Goal', 'et_builder'), 'desc' => esc_html__('A split testing goal cannot be moved inside of a split testing subject. To perform this action you must first end your split test.', 'et_builder')), 'cannot_move_subject_into_goal' => array('title' => esc_html__('Can\'t Move Subject', 'et_builder'), 'desc' => esc_html__('A split testing subject cannot be moved inside of a split testing goal. To perform this action you must first end your split test.', 'et_builder')), 'cannot_clone_section_has_goal' => array('title' => esc_html__('Can\'t Clone Section', 'et_builder'), 'desc' => esc_html__('This section cannot be duplicated because it contains a split testing goal. Goals cannot be duplicated. You must first end your split test before performing this action.', 'et_builder')), 'cannot_clone_row_has_goal' => array('title' => esc_html__('Can\'t Clone Row', 'et_builder'), 'desc' => esc_html__('This row cannot be duplicated because it contains a split testing goal. Goals cannot be duplicated. You must first end your split test before performing this action.', 'et_builder')), 'cannot_remove_section_has_goal' => array('title' => esc_html__('Can\'t Remove Section', 'et_builder'), 'desc' => esc_html__('This section cannot be removed because it contains a split testing goal. Goals cannot be deleted. You must first end your split test before performing this action.', 'et_builder')), 'cannot_remove_row_has_goal' => array('title' => esc_html__('Can\'t Remove Row', 'et_builder'), 'desc' => esc_html__('This row cannot be removed because it contains a split testing goal. Goals cannot be deleted. You must first end your split test before performing this action.', 'et_builder')), 'cannot_remove_section_has_unremovable_subject' => array('title' => esc_html__('Can\'t Remove Section', 'et_builder'), 'desc' => esc_html__('Split testing requires at least 2 subject variations. This variation cannot be removed until additional variations have been added.', 'et_builder')), 'cannot_remove_row_has_unremovable_subject' => array('title' => esc_html__('Can\'t Remove Row', 'et_builder'), 'desc' => esc_html__('Split testing requires at least 2 subject variations. This variation cannot be removed until additional variations have been added', 'et_builder')), 'view_stats_thead_titles' => array('clicks' => array(esc_html__('ID', 'et_builder'), esc_html__('Subject', 'et_builder'), esc_html__('Impressions', 'et_builder'), esc_html__('Clicks', 'et_builder'), esc_html__('Clickthrough Rate', 'et_builder')), 'reads' => array(esc_html__('ID', 'et_builder'), esc_html__('Subject', 'et_builder'), esc_html__('Impressions', 'et_builder'), esc_html__('Reads', 'et_builder'), esc_html__('Reading Rate', 'et_builder')), 'bounces' => array(esc_html__('ID', 'et_builder'), esc_html__('Subject', 'et_builder'), esc_html__('Impressions', 'et_builder'), esc_html__('Stays', 'et_builder'), esc_html__('Bounce Rate', 'et_builder')), 'engagements' => array(esc_html__('ID', 'et_builder'), esc_html__('Subject', 'et_builder'), esc_html__('Goal Views', 'et_builder'), esc_html__('Goal Reads', 'et_builder'), esc_html__('Engagement Rate', 'et_builder')), 'conversions' => array(esc_html__('ID', 'et_builder'), esc_html__('Subject', 'et_builder'), esc_html__('Impressions', 'et_builder'), esc_html__('Conversion Goals', 'et_builder'), esc_html__('Conversion Rate', 'et_builder')), 'shortcode_conversions' => array(esc_html__('ID', 'et_builder'), esc_html__('Subject', 'et_builder'), esc_html__('Impressions', 'et_builder'), esc_html__('Shortcode Conversions', 'et_builder'), esc_html__('Conversion Rate', 'et_builder'))))));
     wp_enqueue_style('et_pb_admin_css', ET_BUILDER_URI . '/styles/style.css', array(), ET_BUILDER_VERSION);
     wp_enqueue_style('et_pb_admin_date_css', ET_BUILDER_URI . '/styles/jquery-ui-1.10.4.custom.css', array(), ET_BUILDER_VERSION);
     wp_add_inline_style('et_pb_admin_css', et_pb_ab_get_subject_rank_colors_style());
 }
Exemple #2
0
/**
 * Get formatted stats data that is used by builder's Split testing stats
 *
 * @param int    post ID
 * @param string day|week|month|all duration of stats
 * @param string has to be in Y-m-d H:i:s format
 * @return array stats data
 */
function et_pb_ab_get_stats_data($post_id, $duration = 'week', $time = false, $force_update = false)
{
    global $wpdb;
    $post_id = intval($post_id);
    $goal_slug = et_pb_ab_get_goal_module($post_id);
    $rank_metrics = in_array($goal_slug, et_pb_ab_get_modules_have_conversions()) ? 'conversions' : 'clicks';
    // Get subjects
    $subjects = et_pb_ab_get_subjects($post_id, 'array', 'subject_');
    $subjects_id = et_pb_ab_get_subjects($post_id, 'array');
    // Get cached data
    $cached_data = get_transient('et_pb_ab_' . $post_id . '_stats_' . $duration);
    // Get rank coloring scheme
    $subject_rank_colors = et_pb_ab_get_subject_rank_colors();
    // return cached logs if exist and if force_update == false
    if ($cached_data && !$force_update) {
        // Remove inactive subjects
        if (isset($cached_data['subjects_id']) && !empty($cached_data['subjects_id'])) {
            foreach ($cached_data['subjects_id'] as $subject_id_key => $subject_id_value) {
                if (!in_array($subject_id_value, $subjects_id)) {
                    unset($cached_data['subjects_id'][$subject_id_key]);
                }
            }
        }
        if (isset($cached_data['subjects_logs']) && !empty($cached_data['subjects_logs'])) {
            foreach ($cached_data['subjects_logs'] as $subject_log_id => $subject_logs) {
                if (!in_array($subject_log_id, $subjects)) {
                    unset($cached_data['subjects_logs'][$subject_log_id]);
                }
            }
        }
        if (isset($cached_data['subjects_analysis']) && !empty($cached_data['subjects_analysis'])) {
            foreach ($cached_data['subjects_analysis'] as $subject_analysis_id => $subject_analysis) {
                if (!in_array($subject_analysis_id, $subjects)) {
                    unset($cached_data['subjects_analysis'][$subject_analysis_id]);
                }
            }
        }
        if (isset($cached_data['subjects_totals']) && !empty($cached_data['subjects_totals'])) {
            $subject_totals_index = 0;
            foreach ($cached_data['subjects_totals'] as $subject_total_id => $subject_totals) {
                if (!in_array($subject_total_id, $subjects)) {
                    unset($cached_data['subjects_totals'][$subject_total_id]);
                    continue;
                }
            }
            // Rank by engagement
            $cached_subjects_ranks = wp_list_pluck($cached_data['subjects_totals'], $rank_metrics);
            $cached_subjects_ranks_index = 0;
            // Sort from high to low, mantain keys
            arsort($cached_subjects_ranks);
            // Push color data
            foreach ($cached_subjects_ranks as $subject_rank_id => $subject_rank_value) {
                $cached_data['subjects_totals'][$subject_rank_id]['color'] = isset($subject_rank_colors[$cached_subjects_ranks_index]) ? $subject_rank_colors[$cached_subjects_ranks_index] : '#7E0000';
                $cached_subjects_ranks_index++;
            }
        }
        return $cached_data;
    }
    $table_name = $wpdb->prefix . 'et_divi_ab_testing_stats';
    // do nothing if no stats table exists in current WP
    if (!$wpdb->get_var("SHOW TABLES LIKE '{$table_name}'") == $table_name) {
        return false;
    }
    // Main placeholder
    $event_types = et_pb_ab_get_event_types();
    $analysis_types = et_pb_ab_get_analysis_types();
    $analysis_formulas = et_pb_ab_get_analysis_formulas();
    $time = $time ? $time : date('Y-m-d H:i:s', current_time('timestamp'));
    $stats = array('subjects_id' => $subjects_id, 'subjects_logs' => array(), 'subjects_analysis' => array(), 'subjects_totals' => array(), 'events_totals' => array(), 'dates' => array());
    // Get all logs in test
    switch ($duration) {
        case 'all':
            $date_range_interval = 'week';
            $query = $wpdb->prepare("SELECT subject_id, event, YEARWEEK(record_date) AS 'date', COUNT(id) AS 'count' FROM {$table_name} WHERE test_id = %d GROUP BY subject_id, YEARWEEK(record_date), event", $post_id);
            break;
        case 'month':
            $date_range_interval = 'day';
            $query = $wpdb->prepare("SELECT subject_id, event, DATE(record_date) AS 'date', COUNT(id) AS 'count' FROM {$table_name} WHERE test_id = %d AND record_date <= %s AND record_date > DATE_SUB( %s, INTERVAL 1 MONTH ) GROUP BY subject_id, DAYOFMONTH(record_date), event", $post_id, $time, $time);
            break;
        case 'day':
            $date_range_interval = 'hour';
            $query = $wpdb->prepare("SELECT subject_id, event, DATE_FORMAT(record_date, %s) AS 'date', COUNT(id) AS 'count' FROM {$table_name} WHERE test_id = %d AND record_date <= %s AND record_date > DATE_SUB( %s, INTERVAL 1 DAY ) GROUP BY subject_id, HOUR(record_date), event", '%Y-%m-%d %H:00', $post_id, $time, $time);
            break;
        default:
            $date_range_interval = 'day';
            $query = $wpdb->prepare("SELECT subject_id, event, DATE(record_date) AS 'date', COUNT(id) AS 'count' FROM {$table_name} WHERE test_id = %d AND record_date <= %s AND record_date > DATE_SUB( %s, INTERVAL 1 WEEK ) GROUP BY subject_id, DAYOFMONTH(record_date), event", $post_id, $time, $time);
            break;
    }
    $results = $wpdb->get_results($query);
    if (!empty($results)) {
        // Get min and max timestamp based on query result
        $min_max_date = et_pb_ab_get_min_max_timestamp($results, $date_range_interval);
        // Create default list
        $date_list = et_pb_ab_get_date_range($min_max_date['min'], $min_max_date['max'], $date_range_interval);
        // Insert date list to main placeholder
        $stats['dates'] = $date_list;
        // Format YYYYWW format on all-time stats into human-readable format (M jS)
        foreach ($stats['dates'] as $date_key => $date_time) {
            if ('all' === $duration) {
                $stats['dates'][$date_key] = date('M jS', strtotime(substr($date_time, 0, 4) . 'W' . substr($date_time, 4, 2)));
            } else {
                if ('day' === $duration) {
                    $stats['dates'][$date_key] = date('H:i', strtotime($date_time));
                } else {
                    $stats['dates'][$date_key] = date('M jS', strtotime($date_time));
                }
            }
        }
        // Fill subject logs placeholder with proper default
        $stats['subjects_logs'] = array_fill_keys($subjects, array_fill_keys($event_types, array_fill_keys($date_list, 0)));
        // Loop query result and place into placeholder
        foreach ($results as $log) {
            if (!in_array($log->subject_id, $subjects_id)) {
                continue;
            }
            $stats['subjects_logs']["subject_{$log->subject_id}"][$log->event][$log->date] = $log->count;
        }
        // Determine logs' totals and run analysis
        foreach ($stats['subjects_logs'] as $subject_log_id => $subject_log) {
            // Push stats total data
            foreach ($subject_log as $log_type => $logs) {
                $stats['subjects_totals'][$subject_log_id][$log_type] = array_sum($logs);
            }
            // Run analysis for stats' total data
            foreach ($analysis_types as $analysis_type) {
                $numerator_event = $analysis_formulas[$analysis_type]['numerator'];
                $denominator_event = $analysis_formulas[$analysis_type]['denominator'];
                $numerator = isset($stats['subjects_totals'][$subject_log_id][$numerator_event]) ? $stats['subjects_totals'][$subject_log_id][$numerator_event] : 0;
                $denominator = isset($stats['subjects_totals'][$subject_log_id][$denominator_event]) ? $stats['subjects_totals'][$subject_log_id][$denominator_event] : 0;
                $analysis = $denominator === 0 ? 0 : floatval(number_format($numerator / $denominator * 100, 2));
                if ($analysis_formulas[$analysis_type]['inverse']) {
                    $analysis = 100 - $analysis;
                }
                $stats['subjects_totals'][$subject_log_id][$analysis_type] = $analysis;
            }
            // Run analysis for each log date
            foreach ($date_list as $log_date) {
                // Run analysis per analysis type
                foreach ($analysis_types as $analysis_type) {
                    $numerator_event = $analysis_formulas[$analysis_type]['numerator'];
                    $denominator_event = $analysis_formulas[$analysis_type]['denominator'];
                    $numerator = isset($stats['subjects_logs'][$subject_log_id][$numerator_event][$log_date]) ? intval($stats['subjects_logs'][$subject_log_id][$numerator_event][$log_date]) : 0;
                    $denominator = isset($stats['subjects_logs'][$subject_log_id][$denominator_event][$log_date]) ? intval($stats['subjects_logs'][$subject_log_id][$denominator_event][$log_date]) : 0;
                    $analysis = $denominator === 0 ? 0 : floatval(number_format($numerator / $denominator * 100, 2));
                    if ($analysis_formulas[$analysis_type]['inverse']) {
                        $analysis = 100 - $analysis;
                    }
                    $stats['subjects_analysis'][$subject_log_id][$analysis_type][$log_date] = $analysis;
                }
            }
        }
        // Push total events data
        foreach ($event_types as $event_type) {
            $stats['events_totals'][$event_type] = array_sum(wp_list_pluck($stats['subjects_totals'], $event_type));
        }
        foreach ($analysis_types as $analysis_type) {
            $analysis_data = wp_list_pluck($stats['subjects_totals'], $analysis_type);
            $analysis_count = count($analysis_data);
            $stats['events_totals'][$analysis_type] = floatval(number_format(array_sum($analysis_data) / $analysis_count, 2));
        }
        // Rank by engagement
        $subjects_ranks = wp_list_pluck($stats['subjects_totals'], $rank_metrics);
        $subjects_ranks_index = 0;
        // Sort from high to low, mantain keys
        arsort($subjects_ranks);
        // Push color data
        foreach ($subjects_ranks as $subject_rank_id => $subject_rank_value) {
            $stats['subjects_totals'][$subject_rank_id]['color'] = isset($subject_rank_colors[$subjects_ranks_index]) ? $subject_rank_colors[$subjects_ranks_index] : '#7E0000';
            $subjects_ranks_index++;
        }
        // update cache
        set_transient('et_pb_ab_' . $post_id . '_stats_' . $duration, $stats, DAY_IN_SECONDS);
    } else {
        // remove the cache if no logs found
        delete_transient('et_pb_ab_' . $post_id . '_stats_' . $duration);
        return false;
    }
    return $stats;
}