load_textdomain(); // Load config and modules. $options = $this->get_options(); Advanced_Ads_ModuleLoader::loadModules( AAP_PATH . '/modules/', isset( $options['modules'] ) ? $options['modules'] : array() ); // Load admin on demand. if ( is_admin() ) { new Advanced_Ads_Pro_Admin(); // Run after the internal Advanced Ads version has been updated by the `Advanced_Ads_Upgrades`, because. // The `Advanced_Ads_Admin_Notices` can update this version, and the `Advanced_Ads_Upgrades` will not be called. add_action( 'init', array( $this, 'maybe_update_capabilities' ) ); add_filter( 'advanced-ads-notices', array( $this, 'add_notices' ) ); add_filter( 'advanced-ads-add-ons', array( $this, 'register_auto_updater' ), 10 ); } else { // Force advanced js file to be attached. add_filter( 'advanced-ads-activate-advanced-js', '__return_true' ); // Check autoptimize. if ( method_exists( 'Advanced_Ads_Checks', 'requires_noptimize_wrapping' ) && Advanced_Ads_Checks::requires_noptimize_wrapping() && ! isset( $options['autoptimize-support-disabled'] ) ) { add_filter( 'advanced-ads-output-inside-wrapper', array( $this, 'autoptimize_support' ) ); } } new Advanced_Ads_Pro_Compatibility(); // Override shortcodes. remove_shortcode( 'the_ad' ); remove_shortcode( 'the_ad_group' ); remove_shortcode( 'the_ad_placement' ); add_shortcode( 'the_ad', array( $this, 'shortcode_display_ad' ) ); add_shortcode( 'the_ad_group', array( $this, 'shortcode_display_ad_group' ) ); add_shortcode( 'the_ad_placement', array( $this, 'shortcode_display_ad_placement' ) ); add_filter( 'advanced-ads-can-display', array( $this, 'can_display_by_display_limit' ), 10, 3 ); add_filter( 'advanced-ads-ad-output', array( $this, 'add_custom_code' ), 30, 2 ); add_filter( 'advanced-ads-output-final', array( $this, 'encode_ad_custom_code' ), 20, 2 ); add_filter( 'advanced-ads-placement-content-offsets', array( $this, 'placement_content_offsets' ), 10, 6 ); add_action( 'wp_head', array( $this, 'wp_head' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ) ); } /** * Enqueue front end script. */ public function wp_enqueue_scripts() { // Do not enqueue on AMP pages. if ( function_exists( 'advads_is_amp' ) && advads_is_amp() ) { return; } wp_enqueue_script( 'advanced-ads-pro/front', sprintf( '%sassets/js/advanced-ads-pro%s.js', AAP_BASE_URL, defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min' ), array( 'jquery', ADVADS_SLUG . '-advanced-js' ), AAP_VERSION, true ); } /** * Front end header script. */ public function wp_head() { // Do not enqueue on AMP pages. if ( function_exists( 'advads_is_amp' ) && advads_is_amp() ) { return; } ?> get_col( "SELECT blog_id FROM {$wpdb->blogs}" ); $original_blog_id = $wpdb->blogid; foreach ( $blog_ids as $blog_id ) { switch_to_blog( $blog_id ); self::single_activate(); } switch_to_blog( $original_blog_id ); } else { self::single_activate(); } } else { self::single_activate(); } } /** * Fired when the plugin is deactivated.boolean $network_wide True if WPMU superadmin uses"Network Activate" action, false ifWPMU is disabled or plugin isactivated on an individual blog. * * @param boolean $network_wide True if WPMU superadmin uses * "Network Activate" action, false if * WPMU is disabled or plugin is * activated on an individual blog. * * @since 1.2.5 */ public static function deactivate( $network_wide ) { if ( function_exists( 'is_multisite' ) && is_multisite() ) { if ( $network_wide ) { // Get all blog ids. global $wpdb; $blog_ids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs}" ); $original_blog_id = $wpdb->blogid; foreach ( $blog_ids as $blog_id ) { switch_to_blog( $blog_id ); self::single_deactivate(); } switch_to_blog( $original_blog_id ); } else { self::single_deactivate(); } } else { self::single_deactivate(); } } /** * Fired when a new site is activated with a WPMU environment. * * @param int $blog_id ID of the new blog. */ public static function activate_new_site( $blog_id ) { if ( 1 !== did_action( 'wpmu_new_blog' ) ) { return; } switch_to_blog( $blog_id ); self::single_activate(); restore_current_blog(); } /** * Perform when Advanced Ads Pro is enabled on a single site */ public static function single_activate() { // Create new user roles. add_role( 'advanced_ads_admin', __( 'Ad Admin', 'advanced-ads-pro' ), array( 'read' => true, 'advanced_ads_manage_options' => true, 'advanced_ads_see_interface' => true, 'advanced_ads_edit_ads' => true, 'advanced_ads_manage_placements' => true, 'advanced_ads_place_ads' => true, 'upload_files' => true, 'unfiltered_html' => true, ) ); add_role( 'advanced_ads_manager', __( 'Ad Manager', 'advanced-ads-pro' ), array( 'read' => true, 'advanced_ads_see_interface' => true, 'advanced_ads_edit_ads' => true, 'advanced_ads_manage_placements' => true, 'advanced_ads_place_ads' => true, 'upload_files' => true, 'unfiltered_html' => true, ) ); add_role( 'advanced_ads_user', __( 'Ad User', 'advanced-ads-pro' ), array( 'read' => true, 'advanced_ads_place_ads' => true, ) ); self::enable_placement_test_emails(); } /** * Perform when Advanced Ads Pro is deactivated on a single site. */ public static function single_deactivate() { // Remove user roles. remove_role( 'advanced_ads_admin' ); remove_role( 'advanced_ads_manager' ); remove_role( 'advanced_ads_user' ); self::disable_placement_test_emails(); } /** * Show warning if Advanced Ads js is not activated */ public function missing_plugin_notice() { echo '

' . sprintf( wp_kses( // Translators: %s is the plugin’s name. __( '%s requires the Advanced Ads plugin to be installed and activated on your site.', 'advanced-ads-pro' ), array( 'strong' => array(), 'a' => array( 'href' => array(), 'target' => array(), ), ) ), 'Advanced Ads Pro' ) . ' '; $plugins = get_plugins(); if ( isset( $plugins['advanced-ads/advanced-ads.php'] ) ) { // Is installed, but not active. echo '' . esc_html__( 'Activate Now', 'advanced-ads-pro' ) . ''; } else { echo '' . esc_html__( 'Install Now', 'advanced-ads-pro' ) . ''; } echo '

'; } /** * Return Advanced Ads Pro options * * @return array */ public function get_options() { if ( ! isset( $this->options ) ) { $default_options = array(); $this->options = get_option( self::OPTION_KEY, $default_options ); // Handle previous option key. if ( $this->options === array() ) { $old_options = get_option( self::OPTION_KEY . '-modules', false ); if ( $old_options ) { // Update old options. $this->update_options( $old_options ); delete_option( self::OPTION_KEY . '-modules' ); } } } return $this->options; } /** * Set a specific option. * * @param string $key key to identify the option. * @param mixed $value value of the option. */ public function set_option( $key, $value ) { $options = $this->get_options(); $options[ $key ] = $value; $this->update_options( $options ); } /** * Update all Advanced Ads Pro options. * * @param array $options */ public function update_options( array $options ) { $updated = update_option( self::OPTION_KEY, $options ); if ( $updated ) { $this->options = $options; } } /** * Load the plugin’s text domain. */ public function load_textdomain() { load_plugin_textdomain( AAP_SLUG, false, AAP_BASE_DIR . '/languages' ); } /** * Register plugin for the auto updater in the base plugin * * @param array $plugins plugin that are already registered for auto updates. * @return array $plugins */ public function register_auto_updater( array $plugins = array() ) { $plugins['pro'] = array( 'name' => AAP_PLUGIN_NAME, 'version' => AAP_VERSION, 'path' => AAP_BASE_PATH . 'advanced-ads-pro.php', 'options_slug' => self::OPTION_KEY, ); return $plugins; } /** * Add autoptimize support * * @param string $ad_content ad content. * @return string output that should not be changed by Autoptimize. */ public function autoptimize_support( $ad_content = '' ) { return '' . $ad_content . ''; } /** * Return internal plugin options, these are options set by the plugin * * @param bool $set_defaults true if we set default options. * @return array $options */ public function internal_options( $set_defaults = true ) { if ( ! $set_defaults ) { return get_option( AAP_PLUGIN_NAME . '-internal', array() ); } if ( ! isset( $this->internal_options ) ) { $defaults = array( 'version' => AAP_VERSION, ); $this->internal_options = get_option( AAP_PLUGIN_NAME . '-internal', array() ); // Save defaults. if ( $this->internal_options === array() ) { $this->internal_options = $defaults; $this->update_internal_options( $this->internal_options ); } } return $this->internal_options; } /** * Update internal plugin options * * @param array $options new internal options. */ public function update_internal_options( array $options ) { $this->internal_options = $options; update_option( AAP_PLUGIN_NAME . '-internal', $options ); } /** * Update capabilities and warn user if needed */ public function maybe_update_capabilities() { $internal_options = $this->internal_options( false ); if ( ! isset( $internal_options['version'] ) ) { $roles = array( 'advanced_ads_admin', 'advanced_ads_manager' ); // Add notice if there is at least 1 user with that role. foreach ( $roles as $role ) { $users_query = new WP_User_Query( array( 'fields' => 'ID', 'number' => 1, 'role' => $role, ) ); if ( count( $users_query->get_results() ) ) { Advanced_Ads_Admin_Notices::get_instance()->add_to_queue( 'pro_changed_caps' ); break; } } $admin_role = get_role( 'advanced_ads_admin' ); if ( $admin_role ) { $admin_role->add_cap( 'upload_files' ); $admin_role->add_cap( 'unfiltered_html' ); } $manager_role = get_role( 'advanced_ads_manager' ); if ( $manager_role ) { $manager_role->add_cap( 'upload_files' ); $manager_role->add_cap( 'unfiltered_html' ); } // Save new version. $this->internal_options(); } } /** * Add potential warning to global array of notices. * * @param array $notices existing notices. * * @return mixed */ public function add_notices( $notices ) { $notices['pro_changed_caps'] = array( 'type' => 'update', 'text' => __( 'Please note, the “Ad Admin“ and the “Ad Manager“ roles have the “upload_files“ and the “unfiltered_html“ capabilities', 'advanced-ads-pro' ), 'global' => true, ); return $notices; } /** * Check if the ad can be displayed based on display limit * * @param bool $can_display existing value. * @param Advanced_Ads_Ad $ad Advanced_Ads_Ad object. * @param array $check_options tbd. * @return bool true if limit is not reached, false otherwise */ public function can_display_by_display_limit( $can_display, Advanced_Ads_Ad $ad, $check_options ) { if ( ! $can_display ) { return false; } $output_options = $ad->options( 'output' ); if ( empty( $check_options['passive_cache_busting'] ) && ! empty( $output_options['once_per_page'] ) ) { $current_ads = Advanced_Ads::get_instance()->current_ads; foreach ( $current_ads as $item ) { if ( $item['type'] === 'ad' && absint( $item['id'] ) === $ad->id ) { return false; } } } return true; } /** * Get offsets for Content placement. * * @param array $offsets Existing Offsets. * @param array $options Injection options. * @param array $placement_opts Placement options. * @param object $xpath DOMXpath object. * @param array $items Selected items. * @param object $dom DOMDocument object. * @return array $offsets New offsets. */ public function placement_content_offsets( $offsets, $options, $placement_opts, $xpath = null, $items = null, $dom = null ) { if ( ! isset( $options['paragraph_count'] ) ) { return $offsets; } if ( isset( $placement_opts['placement']['type'] ) ) { if ( 'post_content_random' === $placement_opts['placement']['type'] ) { $max = absint( $options['paragraph_count'] - 1 ); // Skip if have only one paragraph since `wp_rand( 0, 0)` generates large number. if ( $max > 0 ) { $rand = wp_rand( 0, $max ); $offsets = array( $rand ); } } if ( 'post_content_middle' === $placement_opts['placement']['type'] ) { $middle = absint( ( $options['paragraph_count'] - 1 ) / 2 ); $offsets = array( $middle ); } } // "Content" placement, repeat position. if ( ! empty( $placement_opts['repeat'] ) && isset( $options['paragraph_id'] ) && isset( $options['paragraph_select_from_bottom'] ) ) { $offsets = array(); for ( $i = $options['paragraph_id'] - 1; $i < $options['paragraph_count']; $i++ ) { // Select every X number. if ( ( $i + 1 ) % $options['paragraph_id'] === 0 ) { $offsets[] = $options['paragraph_select_from_bottom'] ? $options['paragraph_count'] - 1 - $i : $i; } } } if ( ! empty( $placement_opts['words_between_repeats'] ) && $xpath && $items && $dom ) { $options['words_between_repeats'] = absint( $placement_opts['words_between_repeats'] ); $offset_shifter = new Advanced_Ads_Pro_Offset_Shifter( $dom, $xpath, $options ); $offsets = $offset_shifter->calc_offsets( $offsets, $items ); } return $offsets; } /** * Add custom code after the ad. * * Note: this won’t work for the Background ad placement. There is a custom solution for that in Advanced_Ads_Pro_Module_Background_Ads:ad_output * * @param string $ad_content Ad content. * @param Advanced_Ads_Ad $ad ad object. * @return string $ad_content Ad content. */ public function add_custom_code( $ad_content, Advanced_Ads_Ad $ad ) { $custom_code = $this->get_custom_code($ad); if ( ! empty( $custom_code ) ) { return $ad_content . $custom_code; } return $ad_content; } /** * If this ad has custom code, encode the output. * * @param string $output The output string. * @param Advanced_Ads_Ad $ad The ad object. * * @return string */ public function encode_ad_custom_code( $output, Advanced_Ads_Ad $ad ) { $privacy = Advanced_Ads_Privacy::get_instance(); if ( // don't encode if AMP. ( function_exists( 'advads_is_amp' ) && advads_is_amp() ) // privacy module is either not enabled, or shows all ads without consent. || ( empty( $privacy->options()['enabled'] ) ) // Ad is already encoded. || ( ! method_exists( $privacy, 'is_ad_output_encoded' ) || $privacy->is_ad_output_encoded( $output ) ) // Consent is overridden, and this is not an AdSense ad, don't encode it. || ( $ad->type !== 'adsense' && isset( $ad->options()['privacy']['ignore-consent'] ) ) ) { return $output; } // If we have custom code, encode the ad. if ( ! empty( $this->get_custom_code( $ad ) ) ) { $output = $privacy->encode_ad( $output, $ad ); } return $output; } /** * Get the custom code for this ad. * * @param Advanced_Ads_Ad $ad The ad object. * * @return string */ public function get_custom_code( Advanced_Ads_Ad $ad ) { $options = $ad->options( 'output' ); $custom_code = isset( $options['custom-code'] ) ? $options['custom-code'] : ''; return (string) apply_filters( 'advanced_ads_pro_output_custom_code', $custom_code, $ad ); } /** * Enable placement test emails */ public static function enable_placement_test_emails() { // Only schedule if not yet scheduled. if ( ! wp_next_scheduled( 'advanced-ads-placement-tests-emails' ) ) { wp_schedule_event( time(), 'daily', 'advanced-ads-placement-tests-emails' ); } } /** * Disable placement test emails */ public static function disable_placement_test_emails() { wp_clear_scheduled_hook( 'advanced-ads-placement-tests-emails' ); } /** * Shortcode to include ad in frontend * * @param array $atts shortcode attributes. * @return string content as generated by the shortcode. */ public function shortcode_display_ad( $atts ) { return $this->do_shortcode( $atts, 'shortcode_display_ad' ); } /** * Shortcode to include ad from an ad group in frontend * * @param array $atts shortcode attributes. * @return string content as generated by the shortcode. */ public function shortcode_display_ad_group( $atts ) { return $this->do_shortcode( $atts, 'shortcode_display_ad_group' ); } /** * Shortcode to display content of an ad placement in frontend * * @param array $atts shortcode attributes. * @return string content as generated by the shortcode. */ public function shortcode_display_ad_placement( $atts ) { return $this->do_shortcode( $atts, 'shortcode_display_ad_placement' ); } /** * Create shortcode output. * * @param array $atts shortcode attributes. * @param string $function_name function to be executed by the shortcode. * * @return string content as generated by the shortcode. */ private function do_shortcode( $atts, $function_name ) { $blog_id = isset( $atts['blog_id'] ) ? absint( $atts['blog_id'] ) : 0; if ( $blog_id && $blog_id !== get_current_blog_id() && is_multisite() ) { // Prevent database error. if ( ! Advanced_Ads_Pro_Utils::blog_exists( $blog_id ) ) { return ''; } if ( method_exists( Advanced_Ads::get_instance(), 'switch_to_blog' ) ) { Advanced_Ads::get_instance()->switch_to_blog( $blog_id ); } // Use the public available function here. $result = call_user_func( array( Advanced_Ads_Plugin::get_instance(), $function_name ), $atts ); if ( method_exists( Advanced_Ads::get_instance(), 'restore_current_blog' ) ) { Advanced_Ads::get_instance()->restore_current_blog(); } return $result; } // Use the public available function here. return call_user_func( array( Advanced_Ads_Plugin::get_instance(), $function_name ), $atts ); } }