ad = $ad; $this->group_id = $group_id; $this->wo_meta = new WOMeta( AdCommander::ns() ); $this->meta = $this->wo_meta->get_post_meta( $ad->ID, AdPostMeta::post_meta_keys() ); $this->ad_type = $this->wo_meta->get_value( $this->meta, 'adtype', false ); /** * Initiate AdType class for this ad. */ switch ( $this->ad_type ) { case 'bannerad': $this->ad_type_instance = new AdTypeBanner( $this->ad, $this->meta, $this->wo_meta ); break; case 'textcode': case 'richcontent': $this->ad_type_instance = new AdTypeContent( $this->ad, $this->meta, $this->wo_meta, $this->ad_type ); break; case 'adsense': $this->ad_type_instance = new AdTypeAdSense( $this->ad, $this->meta, $this->wo_meta ); break; default: break; } } /** * Check if the current ad is valid. * * @return bool */ private function has_valid_ad() { return Util::has_valid_ad( $this->ad_type, $this->meta, $this->wo_meta, $this->ad->ID ); } /** * Do we need consent to display? * * @return bool */ private function needs_consent() { if ( $this->needs_consent === null ) { if ( $this->wo_meta->get_value( $this->meta, 'disable_consent', false ) ) { $this->needs_consent = false; return $this->needs_consent; } $global_needs_consent = Consent::instance()->global_needs_consent( $this->force_no_consent_check ); $this->needs_consent = $global_needs_consent; } return $this->needs_consent; } /** * Do we need to lazy load this ad? * * @return bool */ private function is_lazy() { if ( $this->is_lazy === null ) { if ( $this->group_id || $this->force_no_lazy === true ) { $this->is_lazy = false; } elseif ( ProBridge::instance()->pro_feature_check( 'lazyload' ) ) { $this->is_lazy = LazyPro::instance()->is_lazy_load_enabled(); } else { $this->is_lazy = false; } } return $this->is_lazy; } /** * Determine if we should use ajax loading for this ad. * * @return bool */ public function should_ajax() { /** * If part of a group, never load over ajax. The group will load over ajax. */ if ( $this->group_id || ! ProBridge::instance()->is_pro_loaded() || $this->is_amp ) { return false; } $render = Util::render_method(); /** * If render method is Ajax, load over ajax. */ if ( $render === 'clientside' ) { return true; } /** * If render method is serverside, never load over ajax. */ if ( $render === 'serverside' ) { return false; } /** * 'Smart' render method. */ /** * Use consent * Always use client-side if there's a consent cookie, because page caching would cause false positives. */ if ( Consent::instance()->requires_consent() || $this->is_lazy() || $this->is_click_fraud_enabled() ) { return true; } /* * If max_clicks or max_impressions are set, load over ajax because otherwise expirations won't work. */ $max_clicks = $this->wo_meta->get_value( $this->meta, 'expire_clicks', false ); $max_impressions = $this->wo_meta->get_value( $this->meta, 'expire_impressions', false ); if ( $max_clicks || $max_impressions ) { return true; } $visitor_conditions = $this->wo_meta->get_value( $this->meta, 'visitor_conditions', false ); return ( ( $visitor_conditions && ! empty( $visitor_conditions ) ) ); } /** * Determine if this ad has reached its max views during this view. * * @return bool */ private function has_max_displays() { if ( ! ProBridge::instance()->pro_feature_check( 'adviewhandler' ) ) { return false; } $max_displays = $this->wo_meta->get_value( $this->meta, 'max_displays_per_view', false ); if ( ! $max_displays || $max_displays <= 0 ) { return false; } return AdViewHandler::instance()->has_max_views( $this->ad->ID, $max_displays ); } private function is_ad_click_fraud_disabled() { return Util::truthy( $this->wo_meta->get_value( $this->meta, 'clickfraud_disable', false ) ); } private function is_click_fraud_enabled() { if ( ! ProBridge::instance()->pro_feature_check( 'clickfraud' ) ) { return false; } return ClickFraud::instance()->is_enabled(); } private function is_click_fraud() { if ( ! ProBridge::instance()->pro_feature_check( 'clickfraud' ) ) { return false; } if ( $this->is_ad_click_fraud_disabled() ) { return false; } return ClickFraud::instance()->is_blocked(); } /** * Track this ad display for the current view. */ private function mark_displayed() { if ( ProBridge::instance()->pro_feature_check( 'adviewhandler' ) ) { AdViewHandler::instance()->mark_ad_displayed( $this->ad->ID ); } } /** * Set campaign IDs for this ad. */ private function set_campaign_ids() { /** * Only set campaign IDs if this ad is in a group. */ if ( $this->group_id && ProBridge::instance()->pro_feature_check( 'campaigns' ) ) { $this->campaign_ids = Query::campaigns_by_ad_id( $this->ad->ID ); } } /** * Determine if this ad has max tracking and expire the ad if they're reached. * * @return bool */ private function check_max_tracking() { if ( ProBridge::instance()->is_pro_loaded() ) { $max_clicks = $this->wo_meta->get_value( $this->meta, 'expire_clicks', false ); $max_impressions = $this->wo_meta->get_value( $this->meta, 'expire_impressions', false ); return apply_filters( 'adcmdr_pro_check_max_tracking', false, $this->ad, $max_clicks, $max_impressions ); } return false; } /** * Potentially block a bot from seeing the ad. * * @return bool */ private function should_block_bot() { /** * Already checked when the group started. */ if ( $this->group_id ) { return false; } if ( ! Options::instance()->get( 'bots_disable_ads', 'general', true ) ) { return false; } return Bots::is_bot(); } /** * Check if ads are disabled in global settings. * * @return bool */ private function ads_disabled() { /** * Already checked when the group started. */ if ( $this->group_id ) { return false; } if ( Targeting::ads_disabled_all() ) { return true; } if ( TargetingVisitor::ads_disabled_user_role() ) { return true; } return false; } /** * Determine if tracking is disabled for this individual ad. * * @param string $type Impressoin or Click tracking (i or c). * * @return bool */ private function ad_tracking_disabled( $type ) { return Util::truthy( $this->wo_meta->get_value( $this->meta, 'donottrack_' . $type, false ) ); } /** * Determine if we should set banners in this ad to responsive width and height. * * @return bool */ private function responsive_ad_images() { return ! $this->group_id && Util::truthy_or_site_default( $this->wo_meta->get_value( $this->meta, 'responsive_banners', 'site_default' ), 'responsive_banners', 'general' ); } /** * Create list of classes for this ad. * * @param mixed $classes Classes that should be included in this ad. * * @return string */ private function ad_classes( $classes ) { $classes = Util::arrayify( $classes ); $classes[] = Util::prefixed( 'ad' ); $classes[] = Util::prefixed( 'ad-' . $this->ad->ID ); if ( $this->responsive_ad_images() ) { $classes[] = Util::prefixed( 'ad-resp' ); } if ( $this->is_amp ) { $classes[] = Util::prefixed( 'amp-ad' ); } if ( $this->is_ad_click_fraud_disabled() ) { $classes[] = Util::prefixed( 'cf-disabled' ); } $custom_classes = $this->wo_meta->get_value( $this->meta, 'custom_classes' ); if ( $custom_classes ) { $classes[] = $custom_classes; } /** * Filter: adcmdr_ad_start_class_list * Filter the list of classes for an individual ad, before they are converted into a string. */ $classes = array_unique( apply_filters( 'adcmdr_ad_start_class_list', $classes, $this->ad ) ); return implode( ' ', $classes ); } /** * Create HTML data attributes for ad tracking and identification on the front-end. * * @return string */ private function ad_data_attributes() { $data_attributes = ' data-t-id="' . esc_attr( $this->ad->ID ) . '" data-t-title="' . esc_attr( wp_strip_all_tags( $this->ad->post_title ) ) . '"'; if ( $this->ad_tracking_disabled( 'i' ) ) { $data_attributes .= ' data-ti-disabled="true"'; } if ( $this->ad_tracking_disabled( 'c' ) ) { $data_attributes .= ' data-tc-disabled="true"'; } if ( $this->campaign_ids ) { $data_attributes .= ' data-cid="' . esc_attr( implode( ',', $this->campaign_ids ) ) . '"'; } return $data_attributes; } /** * Create an inline style for manually-set margins. * * @return string */ private function ad_inline_styles() { return Util::inline_styles( array( 'margin-top' => $this->wo_meta->get_value( $this->meta, 'margin_top', false ), 'margin-right' => $this->wo_meta->get_value( $this->meta, 'margin_right', false ), 'margin-bottom' => $this->wo_meta->get_value( $this->meta, 'margin_bottom', false ), 'margin-left' => $this->wo_meta->get_value( $this->meta, 'margin_left', false ), ) ); } /** * If ad is set to float and is not part of a group, create the float wrapper. * * @return string */ private function ad_float_wrapper() { $html = ''; if ( ! $this->disable_wrappers && ! $this->group_id ) { $float = $this->wo_meta->get_value( $this->meta, 'float', false ); if ( $float && ( $float === 'l' || $float === 'r' ) ) { $this->has_float = true; $float_class = Util::prefixed( 'f' . $float ); $html = '