'disabled', 'cache-busting' => 'on', 'ad_label' => 'default', 'placement_position' => '', 'item_adblocker' => '', 'pro_minimum_length' => '0', 'words_between_repeats' => '0', 'previous_method' => null, 'previous_id' => null, 'wp_the_query' => array ( 'term_id' => '', 'taxonomy' => '', 'is_main_query' => true, 'is_rest_api' => false, 'page' => 1, 'numpages' => 1, 'is_archive' => false, 'is_search' => false, 'is_home' => false, 'is_404' => false, 'is_attachment' => false, 'is_singular' => true, 'is_front_page' => false, 'is_feed' => false, ), 'global_output' => true, ); /** * One argument in this array may belong to several AJAX requests. * * @var array */ private $ajax_queries_args = array(); private function __construct() { // Load options (and only execute when enabled). $options = Advanced_Ads_Pro::get_instance()->get_options(); if ( isset( $options['cache-busting'] ) ) { $this->options = $options['cache-busting']; } $this->cache_busting_module_enabled = isset( $this->options['enabled'] ) && $this->options['enabled']; if ( ! $this->should_init_cb() ) { return false; } $this->lazy_load_module_enabled = ! empty( $options['lazy-load']['enabled'] ); $this->lazy_load_module_offset = ! empty( $options['lazy-load']['offset'] ) ? absint( $options['lazy-load']['offset'] ) : 0; $this->is_ajax = ( defined( 'DOING_AJAX' ) && DOING_AJAX ) // An AJAX request but not to `/admin-ajax.php`. || ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && 'XMLHttpRequest' === $_SERVER['HTTP_X_REQUESTED_WITH'] ); if ( ! $this->is_ajax && ! is_admin() ) { add_action( 'wp', array( $this, 'init_fronend' ) ); // load Advads Tracking header scripts add_filter( 'advanced-ads-tracking-load-header-scripts', array( $this, 'load_tracking_scripts' ), 10, 1 ); } else { // only execute when enabled if ( $this->cache_busting_module_enabled ) { new Advanced_Ads_Pro_Module_Cache_Busting_Admin_UI(); } } $this->fallback_method = ( ! isset( $this->options['default_fallback_method'] ) || $this->options['default_fallback_method'] === 'ajax' ) ? 'ajax' : 'off'; if ( 'ajax' === $this->fallback_method ) { $this->server_info = new Advanced_Ads_Pro_Cache_Busting_Server_Info( $this, $this->options ); } add_filter( 'advanced-ads-ad-output-debug-content', array( $this, 'add_debug_content' ), 10, 2 ); add_filter( 'advanced-ads-ajax-ad-select-arguments', array( $this, 'add_default_ajax_arguments' ), 10, 2 ); } /** * Check if cache-busting should be initialized. * * Even when the module is disabled, we partially (i.e .conditions are not checked for every visitor of a cached page) * use cache-busting functionality to deliver Custom Position placements so that they do not appear in the footer when * selectors do not exist. * * @see self::add_simple_js_item */ private function should_init_cb() { if ( $this->cache_busting_module_enabled ) { return true; } $placements = Advanced_Ads::get_ad_placements_array(); foreach ( $placements as $placement ) { if ( isset( $placement['type'] ) && $placement['type'] === 'custom_position' && ! empty( $placement['item'] ) ) { return true; } } return false; } /** * Return an instance of this class. * * @return obj A single instance of this class. */ public static function get_instance() { // If the single instance hasn't been set, set it now. if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Init cache-busting frontend after the `parse_query` hook. * Not ajax, not admin. */ public function init_fronend() { global $wp_the_query; if ( apply_filters( 'advanced-ads-pro-cb-frontend-disable', false ) // Disable cache-busting on AMP pages. || ( function_exists( 'advads_is_amp' ) && advads_is_amp() ) || $wp_the_query->is_feed() ) { return; } add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); add_action( 'wp_head', array( $this, 'watch_wp_head'), PHP_INT_MAX ); add_filter( 'advanced-ads-ad-output', array( $this, 'watch_ad_output' ), 100, 2 ); add_filter( 'advanced-ads-group-output', array( $this, 'watch_group_output' ), 100, 2 ); // override output based on the Advanced_Ads_Ad object conditions add_filter( 'advanced-ads-ad-select-override-by-ad', array( $this, 'override_ad_select_by_ad' ), 10, 3 ); // override output based on the Advanced_Ads_Group object conditions add_filter( 'advanced-ads-ad-select-override-by-group', array( $this, 'override_ad_select_by_group' ), 10, 4 ); add_action( 'wp_footer', array( $this, 'passive_cache_busting_output' ), 21 ); add_filter( 'advanced-ads-can-display', array( $this, 'can_display_by_display_limit' ), 10, 3 ); if ( ! $this->cache_busting_module_enabled ) { return; } add_filter( 'advanced-ads-ad-select-args', array( $this, 'override_ad_select' ), 100 ); add_filter( 'advanced-ads-ad-select-args', array( $this, 'disable_global_output_passive' ), 101 ); add_action( 'advanced-ads-can-display-placement', array( $this, 'placement_can_display' ), 12, 2 ); } /** * Output passive cache-busting array */ public function passive_cache_busting_output() { // if ( true === WP_DEBUG ) { // echo '
' . htmlentities( print_r( $this->passive_cache_busting_placements, true ) ) . ''; // } $arrays = array( 'window.advads_placement_tests' => Advanced_Ads_Pro_Placement_Tests::get_instance()->get_placement_tests_js( false ), 'window.advads_passive_ads' => $this->passive_cache_busting_ads, 'window.advads_passive_groups' => $this->passive_cache_busting_groups, 'window.advads_passive_placements' => $this->passive_cache_busting_placements, 'window.advads_ajax_queries' => self::$ajax_queries, 'window.advads_has_ads' => $this->has_ads, 'window.advads_js_items' => $this->js_items, 'window.advads_ajax_queries_args' => $this->ajax_queries_args, ); $content = ''; foreach ( $arrays as $name => $array ) { if ( $array ) { $has_data = true; $content .= $name . ' = ' . json_encode( $array ) . ";\n"; } } if ( ! $content ) { return; } $content = ''; if ( class_exists( 'Advanced_Ads_Utils' ) && method_exists( 'Advanced_Ads_Utils', 'get_inline_asset' ) ) { $content = Advanced_Ads_Utils::get_inline_asset( $content ); } echo $content; } public function enqueue_scripts() { // Include in footer to prevent conflict when Autoptimize and NextGen Gallery are used at the same time. $uri_rel_path = AAP_BASE_URL . 'assets/js/'; $dependencies = array( 'jquery' ); // If the privacy module is active, add advanced-js as a dependency. if ( ! empty( Advanced_Ads_Privacy::get_instance()->options()['enabled'] ) ) { $dependencies[] = ADVADS_SLUG . '-advanced-js'; } if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) { wp_register_script( 'krux/postscribe', $uri_rel_path . 'postscribe.js', array(), '2.0.8', true ); wp_register_script( 'advanced-ads-pro/cache_busting', $uri_rel_path . 'base.js', array_merge( $dependencies, array( 'krux/postscribe' ) ), AAP_VERSION, true ); } else { // minified wp_register_script( 'advanced-ads-pro/cache_busting', $uri_rel_path . 'base.min.js', $dependencies, AAP_VERSION, true ); } $info = array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'lazy_load_module_enabled' => $this->lazy_load_module_enabled, 'lazy_load' => array( 'default_offset' => $this->lazy_load_module_offset, 'offsets' => apply_filters( 'advanced-ads-lazy-load-placement-offsets', array() ), ), 'moveintohidden' => defined( 'ADVANCED_ADS_PRO_CUSTOM_POSITION_MOVE_INTO_HIDDEN' ), 'wp_timezone_offset' => Advanced_Ads_Utils::get_wp_timezone()->getOffset(date_create()), ); if ( defined( 'ICL_SITEPRESS_VERSION' ) ) { $current_lang = apply_filters( 'wpml_current_language', null ); $info['ajax_url'] = add_query_arg( 'wpml_lang', $current_lang, $info['ajax_url'] ); } wp_localize_script( 'advanced-ads-pro/cache_busting', 'advanced_ads_pro_ajax_object', $info ); wp_enqueue_script( 'advanced-ads-pro/cache_busting' ); if ( is_admin_bar_showing() ) { // add loaded ads to admin bar wp_enqueue_script( 'advanced-ads-pro/cache_busting_admin_bar', $uri_rel_path . 'admin_bar.js', array( 'advanced-ads-pro/cache_busting' ), AAP_VERSION, true ); } } /** * Provide current_ad propery to client. * * @param string $content * @param Advanced_Ads_Ad $ad * * @return string */ public function watch_ad_output( $content, $ad = null ) { if ( isset( $ad ) && $ad instanceof Advanced_Ads_Ad ) { // build content (arguments are: id, method, title) if ( ! empty( $ad->global_output ) ) { $this->has_ads[] = array( "$ad->id", 'ad', null ); } if ( $this->collecting_js_items ) { $this->has_js_items[] = array( 'id' => $ad->id, 'type' => 'ad', 'title' => $ad->title, 'blog_id' => get_current_blog_id() ); } } return $content; } /** * Provide current group propery to client. * * @param string $content * @param Advanced_Ads_Group $group * * @return string */ public function watch_group_output( $content, Advanced_Ads_Group $group ) { if ( $this->collecting_js_items ) { $this->has_js_items[] = array( 'id' => $group->id, 'type' => 'group', 'title' => $group->id ); } return $content; } /** * Turn off head optimisation. */ public function watch_wp_head() { $this->isHead = false; } /** * Replace ad content with placeholder. * * @param array $arguments * * @return array */ public function override_ad_select( $arguments ) { // placements and not Feed only $not_feed = empty( $arguments['wp_the_query']['is_feed'] ); if ( $arguments['method'] === Advanced_Ads_Select::PLACEMENT && $not_feed ) { $placements = Advanced_Ads::get_ad_placements_array(); if ( empty( $placements[ $arguments['id'] ]['item'] ) || ! isset( $placements[ $arguments['id'] ]['type'] ) ) { // placement was created but no item was selected in dropdown unset( $arguments['override'] ); return $arguments; } $arguments['placement_type'] = $placements[ $arguments['id'] ]['type']; $options = isset( $placements[ $arguments['id'] ]['options'] ) ? (array) $placements[ $arguments['id'] ]['options'] : array(); foreach ( $options as $_k => $_v ) { if ( ! isset( $arguments[ $_k ] ) ) { $arguments[ $_k ] = $_v; } } $query = self::build_js_query( $arguments ); // allow to disable feature if ( $this->can_override( $query ) ) { $arguments['override'] = $this->get_override_content( $query ); } } return $arguments; } /** * Disable global output for passive cache-busting. * * @param array $arguments * @return array $arguments */ public function disable_global_output_passive( $arguments ) { $cb_auto = ( isset( $arguments['cache-busting'] ) && $arguments['cache-busting'] === self::OPTION_AUTO ); if ( $cb_auto && $this->is_passive_method_used() && ! isset( $arguments['global_output'] ) ) { $arguments['global_output'] = false; } return $arguments; } /** * return ad, prepared for js handler if the conditions are met * * @param string $overriden_ad ad content to override * @param obj $ad Advanced_Ads_Ad * @param array $args argument passed to the 'get_ad_by_id' function * @return string ad content prepared for js handler if the conditions are met */ public function override_ad_select_by_ad( $overriden_ad, Advanced_Ads_Ad $ad, $args ) { if ( ! $this->can_override_passive( $args ) ) { return $overriden_ad; } if ( $this->cache_busting_module_enabled ) { // Cache busting 'auto'. $overriden_ad = $this->cache_busting_auto_for_ad( $overriden_ad, $ad, $args ); } if ( false === $overriden_ad ) { // The cache-busting module is disabled or the 'off' fallback has been aplied. $overriden_ad = $this->get_simple_js_ad( $overriden_ad, $ad, $args ); } return $overriden_ad; } /** * return group, prepared for js handler if the conditions are met * * @param string $overriden_group group content to override * @param obj $adgroup Advanced_Ads_Group * @param array/null $ordered_ad_ids ordered ids of the ads that belong to the group * @param array $args argument passed to the 'get_ad_by_group' function * @return string/false group content prepared for js handler if the conditions are met */ public function override_ad_select_by_group( $overriden_group, Advanced_Ads_Group $adgroup, $ordered_ad_ids, $args ) { if ( ! $this->can_override_passive( $args ) ) { return $overriden_group; } if ( $this->cache_busting_module_enabled ) { // Cache busting 'auto'. $overriden_group = $this->cache_busting_auto_for_group( $overriden_group, $adgroup, $ordered_ad_ids, $args ); } if ( false === $overriden_group ) { // The cache-busting module is disabled or the 'off' fallback has been aplied. $overriden_group = $this->get_simple_js_group( $overriden_group, $adgroup, $ordered_ad_ids, $args ); } return $overriden_group; } public function cache_busting_auto_for_ad( $overriden_ad, Advanced_Ads_Ad $ad, $args ) { //if it was requested by placement; if cache-busting option does not exists yet, or exist and = 'auto' $cache_busting_auto = isset( $args['placement_type'] ) && ( ! isset( $args['cache-busting'] ) || $args['cache-busting'] === self::OPTION_AUTO ); $cache_busting_off = isset( $args['cache-busting'] ) && $args['cache-busting'] === self::OPTION_OFF; $prev_is_placement = isset( $args['previous_method'] ) && $args['previous_method'] === 'placement' && isset( $args['previous_id'] ); $test_id = isset( $args['test_id'] ) ? $args['test_id'] : null; $is_passive_all = ! empty( $this->options['passive_all'] ); if ( $cache_busting_auto && ! $this->is_passive_method_used() ) { // ajax method // ad was requested by group `placement->group->ad` or `group->ad` if ( isset( $args['previous_method'] ) && $args['previous_method'] === 'group' && isset( $args['previous_id'] ) ) { return $ad; } $ad->args['cache-busting'] = self::OPTION_ON; $ad->args['cache-busting-orig'] = self::OPTION_AUTO; $overriden_ad = $this->get_overridden_ajax_ad( $ad, $args ); if ( false === $overriden_ad ) { // static and not test if ( isset( $args['output']['placement_id'] ) ) { if ( ! $this->placement_can_display_not_passive( $args['output']['placement_id'] ) ) { return ''; } $this->add_placement_to_current_ads( $args['output']['placement_id'] ); } } return $overriden_ad; } elseif ( ! $cache_busting_off && ( $cache_busting_auto || $is_passive_all ) ) { // passive method // ad was requested by group `placement->group->ad` or `group->ad` if ( isset( $args['previous_method'] ) && $args['previous_method'] === 'group' && isset( $args['previous_id'] ) ) { return $ad; } $needs_backend = $this->ad_needs_backend_request( $ad ); // ad was requested by placement `placement->ad` or `ad` // check if ad can be delivered without any cache-busting if ( 'static' === $needs_backend && ! $is_passive_all && ! $test_id ) { $ad->args['cache-busting'] = self::OPTION_OFF; $ad->args['cache-busting-orig'] = self::OPTION_AUTO; $ad->global_output = true; if ( isset( $args['output']['placement_id'] ) ) { if ( ! $this->placement_can_display_not_passive( $args['output']['placement_id'] ) ) { return ''; } $this->add_placement_to_current_ads( $args['output']['placement_id'] ); } return $overriden_ad; } // check if ad cannot be delivered with passive cache-busting if ( 'off' === $needs_backend || 'ajax' === $needs_backend ) { $is_ajax_fallbback = 'ajax' === $needs_backend; if ( isset( $args['output']['placement_id'] ) && ! $this->placement_can_display_not_passive( $args['output']['placement_id'] ) ) { // prevent selection of this placement using JavaScript if ( $test_id ){ Advanced_Ads_Pro_Placement_Tests::get_instance()->no_cb_fallbacks[] = $args['previous_id']; } return ''; } if ( $is_ajax_fallbback && $cache_busting_auto ) { $ad->args['cache-busting'] = self::OPTION_ON; $ad->args['cache-busting-orig'] = self::OPTION_AUTO; return $this->get_overridden_ajax_ad( $ad, $args ); } // `No cache-busting` fallback if ( $test_id ) { if ( in_array( $args['previous_id'], Advanced_Ads_Pro_Placement_Tests::get_instance()->get_random_placements() ) ) { Advanced_Ads_Pro_Placement_Tests::get_instance()->delivered_tests[ $args['previous_id'] ] = $test_id; } else { // prevent selection of this placement using JavaScript Advanced_Ads_Pro_Placement_Tests::get_instance()->no_cb_fallbacks[] = $args['previous_id']; return ''; } } $ad->args['cache-busting'] = self::OPTION_OFF; $ad->args['cache-busting-orig'] = self::OPTION_AUTO; $ad->args['global_output'] = true; $ad->global_output = true; if ( isset( $args['output']['placement_id'] ) ) { if ( ! $this->placement_can_display_not_passive( $args['output']['placement_id'] ) ) { return ''; } $this->add_placement_to_current_ads( $args['output']['placement_id'] ); } return $overriden_ad; } if ( ! $ad->can_display( array( 'passive_cache_busting' => true ) ) ) { if ( $test_id && array_key_exists( $args['previous_id'], Advanced_Ads_Pro_Placement_Tests::get_instance()->delivered_tests ) ) { Advanced_Ads_Pro_Placement_Tests::get_instance()->delivered_tests[ $args['previous_id'] ] = $test_id; } return ''; } // deliver ad using passive cache-busting // add new info to the passive cache-busting array $overriden_ad = $this->get_passive_overriden_ad( $ad, $args ); } if ( $prev_is_placement && false === $overriden_ad && $test_id ) { Advanced_Ads_Pro_Placement_Tests::get_instance()->delivered_tests[ $args['previous_id'] ] = $test_id ; } return $overriden_ad; } public function cache_busting_auto_for_group( $overriden_group, Advanced_Ads_Group $adgroup, $ordered_ad_ids, $args ) { $prev_is_placement = isset( $args['previous_method'] ) && $args['previous_method'] === 'placement' && isset( $args['previous_id'] ); $cache_busting_auto = isset( $args['placement_type'] ) && ( ! isset( $args['cache-busting'] ) || $args['cache-busting'] === self::OPTION_AUTO ); $test_id = isset( $args['test_id'] ) ? $args['test_id'] : null; $is_passive_all = ! empty( $this->options['passive_all'] ); $cache_busting_off = isset( $args['cache-busting'] ) && $args['cache-busting'] === self::OPTION_OFF; if ( $cache_busting_auto && ! $this->is_passive_method_used() ) { // ajax method $group_ads = $this->request_passive_ads_of_group( $adgroup, $ordered_ad_ids, $args ); if ( $test_id || ! $this->group_ads_static( $group_ads, $adgroup ) ) { $adgroup->ad_args['cache-busting'] = self::OPTION_ON; $adgroup->ad_args['cache-busting-orig'] = self::OPTION_AUTO; $query = self::build_js_query( $args); $overriden_group = $this->get_override_content( $query ); } if ( false === $overriden_group ) { // Static and does not belong to a test. $adgroup->ad_args['cache-busting'] = self::OPTION_OFF; $adgroup->ad_args['cache-busting-orig'] = self::OPTION_AUTO; unset( $adgroup->ad_args['cache_busting_elementid'], $args['cache_busting_elementid'] ); $adgroup->ad_args['global_output'] = true; if ( isset( $args['output']['placement_id'] ) ) { if ( ! $this->placement_can_display_not_passive( $args['output']['placement_id'] ) ) { return ''; } $this->add_placement_to_current_ads( $args['output']['placement_id'] ); } } return $overriden_group; } elseif ( ! $cache_busting_off && ( $cache_busting_auto || $is_passive_all ) ) { // passive method if ( is_array( $ordered_ad_ids ) && count( $ordered_ad_ids ) > 0 ) { // add info about the group to the passive cache-busting array $uniq_key = ++self::$adOffset; $group_ads = $this->request_passive_ads_of_group( $adgroup, $ordered_ad_ids, $args ); foreach ( $group_ads as $ad ) { $needs_backend = $this->ad_needs_backend_request( $ad ); if ( 'off' === $needs_backend || 'ajax' === $needs_backend ) { $is_ajax_fallbback = 'ajax' === $needs_backend; // delete info from the passive cache-busting array $this->delete_passive_group( $adgroup, $args, $uniq_key ); if ( isset( $args['output']['placement_id'] ) && ! $this->placement_can_display_not_passive( $args['output']['placement_id'] ) ) { // prevent selection of this placement using JavaScript if ( $test_id ){ Advanced_Ads_Pro_Placement_Tests::get_instance()->no_cb_fallbacks[] = $args['previous_id']; } return ''; } if ( $is_ajax_fallbback && $cache_busting_auto ) { $adgroup->ad_args['cache-busting'] = self::OPTION_ON; $adgroup->ad_args['cache-busting-orig'] = self::OPTION_AUTO; $query = self::build_js_query( $args); return $this->get_override_content( $query ); } else { // `No cache-busting` fallback if ( $test_id ) { if ( in_array( $args['previous_id'], Advanced_Ads_Pro_Placement_Tests::get_instance()->get_random_placements() ) ) { Advanced_Ads_Pro_Placement_Tests::get_instance()->delivered_tests[ $args['previous_id'] ] = $test_id; } else { // prevent selection of this placement using JavaScript Advanced_Ads_Pro_Placement_Tests::get_instance()->no_cb_fallbacks[] = $args['previous_id']; return ''; } } $adgroup->ad_args['cache-busting'] = self::OPTION_OFF; $adgroup->ad_args['cache-busting-orig'] = self::OPTION_AUTO; unset( $adgroup->ad_args['cache_busting_elementid'], $args['cache_busting_elementid'] ); $adgroup->ad_args['global_output'] = true; if ( isset( $args['output']['placement_id'] ) ) { if ( ! $this->placement_can_display_not_passive( $args['output']['placement_id'] ) ) { return ''; } $this->add_placement_to_current_ads( $args['output']['placement_id'] ); } return $overriden_group; } } } if ( $this->group_ads_static( $group_ads, $adgroup ) && ! $is_passive_all && ! $test_id ) { $adgroup->ad_args['cache-busting'] = self::OPTION_OFF; $adgroup->ad_args['cache-busting-orig'] = self::OPTION_AUTO; unset( $adgroup->ad_args['cache_busting_elementid'], $args['cache_busting_elementid'] ); $adgroup->ad_args['global_output'] = true; if ( isset( $args['output']['placement_id'] ) ) { if ( ! $this->placement_can_display_not_passive( $args['output']['placement_id'] ) ) { return ''; } $this->add_placement_to_current_ads( $args['output']['placement_id'] ); } return $overriden_group; } $output_string = $this->get_passive_overriden_group( $adgroup, $ordered_ad_ids, $args, $uniq_key, $group_ads ); $overriden_group = $output_string; } } if ( $prev_is_placement && false === $overriden_group && $test_id ) { Advanced_Ads_Pro_Placement_Tests::get_instance()->delivered_tests[ $args['previous_id'] ] = $test_id; } return $overriden_group; } /** * Request passive ads of a group. * * @param obj $adgroup Advanced_Ads_Group * @param array/null $ordered_ad_ids ordered ids of the ads that belong to the group * @param array $args argument passed to the 'get_ad_by_group' function */ private function request_passive_ads_of_group( $adgroup, $ordered_ad_ids, $args ) { $args['global_output'] = false; $args['is_top_level'] = false; $args['ad_label'] = 'disabled'; $args['group_info'] = array ( 'passive_cb' => true, 'id' => $adgroup->id, 'name' => $adgroup->name, 'type' => $adgroup->type, 'refresh_enabled' => Advanced_Ads_Pro_Group_Refresh::is_enabled( $adgroup ), ); $ordered_ad_ids = is_array( $ordered_ad_ids ) ? $ordered_ad_ids : array(); $group_ads = array(); foreach ( $ordered_ad_ids as $_ad_id ) { // get result from the 'override_ad_select_by_ad' method $ad = Advanced_Ads_Select::get_instance()->get_ad_by_method( $_ad_id, Advanced_Ads_Select::AD, $args ); // Ignore ads that are hidden for all users. if ( ! $ad instanceof Advanced_Ads_Ad || ! $ad->can_display( array( 'passive_cache_busting' => true ) ) ) { continue; } $group_ads[] = $ad; } return $group_ads; } /** * Get simple js ad. * Conditions are not checked for every visitor of a cached page. */ public function get_simple_js_ad( $overriden_ad, Advanced_Ads_Ad $ad, $args ) { $cp_placement = isset( $args['placement_type'] ) && $args['placement_type'] === 'custom_position'; if ( ! $cp_placement // Check if collecting of simple ads has been started. || $this->collecting_js_items ) { return $overriden_ad; } $this->collecting_js_items = true; $elementid = $this->generate_elementid(); $args['cache_busting_elementid'] = $ad->args['cache_busting_elementid'] = $elementid; $overriden_ad = ''; if ( $ad->can_display() ) { // Disable global output because the ads will be tracked using an AJAX request. $ad->args['global_output'] = false; $ad->global_output = false; $l = count( $this->has_js_items ); $overriden_ad = $this->add_simple_js_item( $elementid, $ad->output(), $l, $args ); $ad->args['global_output'] = true; $ad->global_output = true; } $this->collecting_js_items = false; return $overriden_ad; } /** * Get simple js group. * Conditions are not checked for every visitor of a cached page. */ public function get_simple_js_group( $overriden_group, Advanced_Ads_Group $adgroup, $ordered_ad_ids, $args ) { $cp_placement = isset( $args['placement_type'] ) && $args['placement_type'] === 'custom_position'; if ( ! $cp_placement || $this->collecting_js_items ) { // Check if collecting of simple ads has been started. return $overriden_group; } $this->collecting_js_items = true; $elementid = $this->generate_elementid(); $args['cache_busting_elementid'] = $adgroup->ad_args['cache_busting_elementid'] = $elementid; // Disable global output because the ads will be tracked using an AJAX request. $adgroup->ad_args['global_output'] = false; $l = count( $this->has_js_items ); $overriden_group = $this->add_simple_js_item( $elementid, $adgroup->output( $ordered_ad_ids ), $l, $args ); $adgroup->ad_args['global_output'] = true; $this->collecting_js_items = false; return $overriden_group; } /** * Add simple js item. * * @param string $elementid Wrapper id. * @param string $output Ad/Group output. * @param int $l Number of existing simple js items. * @param array $args Placement options. * @return string Wrapper id. */ function add_simple_js_item( $elementid, $output, $l, $args ) { $js_item = array( 'output' => $output, 'elementid' => $elementid, 'args' => $args, 'has_js_items' => array_slice( $this->has_js_items, $l ), ); $js_item = apply_filters( 'advanced-ads-cache-busting-item', $js_item, array( 'method' => 'placement', 'args' => $args ) ); $this->js_items[] = $js_item; /** * Collect blog data before `restore_current_blog` is called */ if ( class_exists( 'Advanced_Ads_Tracking_Util', false ) && method_exists( 'Advanced_Ads_Tracking_Util', 'collect_blog_data' ) ) { $tracking_utils = Advanced_Ads_Tracking_Util::get_instance(); $tracking_utils->collect_blog_data(); } $placement_id = ! empty( $args['output']['placement_id'] ) ? $args['output']['placement_id'] : ''; return $this->create_wrapper( $elementid, $placement_id, $args ); } /** * add data related to ad and ad placement to js array * * @param obj $ad Advanced_Ads_Ad * @param array $args argument passed to the 'get_ad_by_id' function * @return string */ private function get_passive_overriden_ad( Advanced_Ads_Ad $ad, $args ) { $cache_busting_auto = isset( $args['placement_type'] ) && ( ! isset( $args['cache-busting'] ) || $args['cache-busting'] === self::OPTION_AUTO ); if ( $cache_busting_auto ) { $js_array = & $this->passive_cache_busting_placements; $id = $args['previous_id']; } else { $js_array = & $this->passive_cache_busting_ads; $id = $args['id']; } $uniq_key = $id . '_' . ++self::$adOffset; $not_head = ! $this->isHead || ( isset( $args['placement_type'] ) && $args['placement_type'] !== 'header' ); $elementid = $not_head ? $this->generate_elementid() : null; $args['cache_busting_elementid'] = $ad->args['cache_busting_elementid'] = $elementid; $placement_id = ! empty( $args['output']['placement_id'] ) ? $args['output']['placement_id'] : ''; $output_string = $not_head ? $this->create_wrapper( $elementid, $placement_id, $args ) : ''; $js_array[ $uniq_key ] = array( 'elementid' => array( $elementid ), 'ads' => array( $ad->id => $this->get_passive_cb_for_ad( $ad ) ), // only 1 ad ); if ( $cache_busting_auto ) { $placements = Advanced_Ads::get_ad_placements_array(); $test_id = isset( $args['test_id'] ) ? $args['test_id'] : null; $js_array[ $uniq_key ]['type'] = 'ad'; $js_array[ $uniq_key ]['id'] = $ad->id; $js_array[ $uniq_key ]['placement_info'] = $this->get_placement_info( $id ); $js_array[ $uniq_key ]['test_id'] = $test_id; if ( $ad_for_adblocker = Advanced_Ads_Pro_Module_Ads_For_Adblockers::get_ad_for_adblocker( $args ) ) { $js_array[ $uniq_key ]['ads_for_ab'] = array( $ad_for_adblocker->id => $this->get_passive_cb_for_ad( $ad_for_adblocker ) ); } if ( 'ajax' === $this->fallback_method ) { $ajax_info = $this->server_info->get_ajax_for_passive_placement( $ad, $args, $elementid ); if ( $ajax_info ) { $js_array[ $uniq_key ] = array_merge( $js_array[ $uniq_key ], $ajax_info ); } } } $js_array[ $uniq_key ] = apply_filters( 'advanced-ads-cache-busting-item', $js_array[ $uniq_key ], array( 'method' => $cache_busting_auto ? 'placement' : 'ad', 'args' => $args ) ); return $output_string; } /** * add data related to group and group placement to js array * * @param obj $adgroup Advanced_Ads_Group * @param array/null $ordered_ad_ids ordered ids of the ads that belong to the group * @param array $args argument passed to the 'get_ad_by_group' function * @param str $uniq_key Property name in JS array. * @param array $group_ads Group ads. * @return string */ private function get_passive_overriden_group( Advanced_Ads_Group $adgroup, $ordered_ad_ids, $args, $uniq_key, $group_ads ) { $cache_busting_auto = isset( $args['placement_type'] ) && ( ! isset( $args['cache-busting'] ) || $args['cache-busting'] === self::OPTION_AUTO ); if ( $cache_busting_auto ) { $js_array = & $this->passive_cache_busting_placements; $id = $args['previous_id']; } else { $js_array = & $this->passive_cache_busting_groups; $id = $args['id']; } $uniq_key = $id . '_' . $uniq_key; $not_head = ! $this->isHead || ( isset( $args['placement_type'] ) && $args['placement_type'] !== 'header' ); $elementid = $not_head ? $this->generate_elementid() : null; $args['cache_busting_elementid'] = $adgroup->ad_args['cache_busting_elementid'] = $elementid; $placement_id = ! empty( $args['output']['placement_id'] ) ? $args['output']['placement_id'] : ''; $output_string = $not_head ? $this->create_wrapper( $elementid, $placement_id, $args ) : ''; // remove ads with 0 ad weight $weights = $adgroup->get_ad_weights(); foreach ( $weights as $_ad_id => $_ad_weight ){ if ( $_ad_weight === 0 ){ unset( $weights[ $_ad_id ] ); } } if ( ( $ad_count = apply_filters( 'advanced-ads-group-ad-count', $adgroup->ad_count, $adgroup ) ) === 'all' ) { $ad_count = 999; } $passive_ads = array(); foreach ( $group_ads as $group_ad ) { $passive_ads[ $group_ad->id ] = $this->get_passive_cb_for_ad( $group_ad ); } $js_array[ $uniq_key ] = array ( 'type'=> 'group', 'id' => $adgroup->id, 'elementid' => array( $elementid ), 'ads' => $passive_ads, 'group_info' => array( 'id' => $adgroup->id, 'name' => $adgroup->name, 'weights' => $weights, 'type' => $adgroup->type, 'ordered_ad_ids' => $ordered_ad_ids, 'ad_count' => $ad_count, ), ); // deprecated after Advaned Ads Slider > 1.3.1 if ( 'slider' === $adgroup->type && defined( 'AAS_VERSION' ) && version_compare( AAS_VERSION, '1.3.1', '<=' ) ) { $slider_options = Advanced_Ads_Slider::get_slider_options( $adgroup ); $js_array[ $uniq_key ]['group_info']['slider_options'] = $slider_options; } if ( Advanced_Ads_Pro_Group_Refresh::is_enabled( $adgroup ) ) { $js_array[ $uniq_key ]['group_info']['refresh_enabled'] = true; $js_array[ $uniq_key ]['group_info']['refresh_interval_for_ads'] = Advanced_Ads_Pro_Group_Refresh::get_ad_intervals( $adgroup ); } $advads_plugin = Advanced_Ads::get_instance(); $label = ''; if ( method_exists( $advads_plugin, 'get_label' ) ) { $placement_state = isset( $args['ad_label'] ) ? $args['ad_label'] : 'default'; $label = Advanced_Ads::get_instance()->get_label( $placement_state ); } if ( $cache_busting_auto ) { $placements = Advanced_Ads::get_ad_placements_array(); $js_array[ $uniq_key ]['placement_info'] = $this->get_placement_info( $id ); $js_array[ $uniq_key ]['test_id'] = isset( $args['test_id'] ) ? $args['test_id'] : null; if ( $ad_for_adblocker = Advanced_Ads_Pro_Module_Ads_For_Adblockers::get_ad_for_adblocker( array_diff_key( $args, array( 'ad_label' => false ) ) ) ) { $js_array[ $uniq_key ]['ads_for_ab'] = array( $ad_for_adblocker->id => $this->get_passive_cb_for_ad( $ad_for_adblocker ) ); } if ( 'ajax' === $this->fallback_method ) { $ajax_info = $this->server_info->get_ajax_for_passive_placement( $group_ads, $args, $elementid ); if ( $ajax_info ) { $js_array[ $uniq_key ] = array_merge( $js_array[ $uniq_key ], $ajax_info ); } } } $js_array[ $uniq_key ] = apply_filters( 'advanced-ads-pro-passive-cb-group-data', $js_array[ $uniq_key ], $adgroup, $elementid ); // Add wrapper around group. if ( ( ! empty( $adgroup->wrapper ) || $label ) && is_array( $adgroup->wrapper ) && class_exists( 'Advanced_Ads_Utils' ) && method_exists( 'Advanced_Ads_Utils' , 'build_html_attributes' ) ) { $before = '