t = array(); /** * Prepare attributes by converting strings to multi-dimensional array * Example: [ 'output__margin__top' => 1 ] => ['output']['margin']['top'] = 1 */ if ( ! defined( 'ADVANCED_ADS_DISABLE_CHANGE' ) || ! ADVANCED_ADS_DISABLE_CHANGE ) { foreach ( $atts as $attr => $data ) { $levels = explode( '__', $attr ); $last = array_pop( $levels ); $cur_lvl = &$result; foreach ( $levels as $lvl ) { if ( ! isset( $cur_lvl[ $lvl ] ) ) { $cur_lvl[ $lvl ] = array(); } $cur_lvl = &$cur_lvl[ $lvl ]; } $cur_lvl[ $last ] = $data; } $result = array_diff_key( $result, array( 'id' => false, 'blog_id' => false, 'ad_args' => false, ) ); } // Ad type: 'content' and a shortcode inside. if ( isset( $atts['ad_args'] ) ) { $result = array_merge( $result, json_decode( urldecode( $atts['ad_args'] ), true ) ); } return $result; } /** * Return plugin options * these are the options updated by the user * * @return array $options */ public function options() { // we can’t store options if WPML String Translations is enabled, or it would not translate the "Ad Label" option. if ( ! isset( $this->options ) || class_exists( 'WPML_ST_String' ) ) { $this->options = get_option( ADVADS_SLUG, array() ); } // allow to change options dynamically $this->options = apply_filters( 'advanced-ads-options', $this->options ); return $this->options; } /** * Update plugin options (not for settings page, but if automatic options are needed) * * @param array $options new options. */ public function update_options( array $options ) { // do not allow to clear options. if ( array() === $options ) { return; } $this->options = $options; update_option( ADVADS_SLUG, $options ); } /** * Return internal plugin options * these are options set by the plugin * * @return array $options */ public function internal_options() { if ( ! isset( $this->internal_options ) ) { $defaults = array( 'version' => ADVADS_VERSION, 'installed' => time(), // when was this installed. ); $this->internal_options = get_option( ADVADS_SLUG . '-internal', array() ); // save defaults. if ( array() === $this->internal_options ) { $this->internal_options = $defaults; $this->update_internal_options( $this->internal_options ); self::get_instance()->create_capabilities(); } // for versions installed prior to 1.5.3 set installed date for now. if ( ! isset( $this->internal_options['installed'] ) ) { $this->internal_options['installed'] = time(); $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 ) { // do not allow to clear options. if ( array() === $options ) { return; } $this->internal_options = $options; update_option( ADVADS_SLUG . '-internal', $options ); } /** * Get prefix used for frontend elements */ public function get_frontend_prefix() { if ( ! $this->frontend_prefix ) { $options = $this->options(); if ( ! isset( $options['front-prefix'] ) ) { if ( isset( $options['id-prefix'] ) ) { // deprecated: keeps widgets working that previously received an id based on the front-prefix. $frontend_prefix = esc_attr( $options['id-prefix'] ); } else { $host = parse_url( get_home_url(), PHP_URL_HOST ); $frontend_prefix = preg_match( '/[A-Za-z][A-Za-z0-9_]{4}/', $host, $result ) ? $result[0] . '-' : self::DEFAULT_FRONTEND_PREFIX; } } else { $frontend_prefix = esc_attr( $options['front-prefix'] ); } /** * Applying the filter here makes sure that it is the same frontend prefix for all * calls on this page impression */ $this->frontend_prefix = apply_filters( 'advanced-ads-frontend-prefix', $frontend_prefix ); } return $this->frontend_prefix; } /** * Get priority used for injection inside content */ public function get_content_injection_priority() { $options = $this->options(); return isset( $options['content-injection-priority'] ) ? (int) $options['content-injection-priority'] : 100; } /** * Returns the capability needed to perform an action * * @param string $capability a capability to check, can be internal to Advanced Ads. * * @return string $capability a valid WordPress capability. */ public static function user_cap( $capability = 'manage_options' ) { global $advanced_ads_capabilities; // admins can do everything. // is also a fallback if no option or more specific capability is given. if ( current_user_can( 'manage_options' ) ) { return 'manage_options'; } return apply_filters( 'advanced-ads-capability', $capability ); } /** * Create roles and capabilities */ public function create_capabilities() { if ( $role = get_role( 'administrator' ) ) { $role->add_cap( 'advanced_ads_manage_options' ); $role->add_cap( 'advanced_ads_see_interface' ); $role->add_cap( 'advanced_ads_edit_ads' ); $role->add_cap( 'advanced_ads_manage_placements' ); $role->add_cap( 'advanced_ads_place_ads' ); } } /** * Remove roles and capabilities */ public function remove_capabilities() { if ( $role = get_role( 'administrator' ) ) { $role->remove_cap( 'advanced_ads_manage_options' ); $role->remove_cap( 'advanced_ads_see_interface' ); $role->remove_cap( 'advanced_ads_edit_ads' ); $role->remove_cap( 'advanced_ads_manage_placements' ); $role->remove_cap( 'advanced_ads_place_ads' ); } } /** * Fired when the plugin is uninstalled. */ public static function uninstall() { $advads_options = Advanced_Ads::get_instance()->options(); if ( ! empty( $advads_options['uninstall-delete-data'] ) ) { global $wpdb; $main_blog_id = $wpdb->blogid; Advanced_Ads::get_instance()->create_post_types(); if ( ! is_multisite() ) { self::get_instance()->uninstall_single(); } else { $blog_ids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs}" ); foreach ( $blog_ids as $blog_id ) { switch_to_blog( $blog_id ); self::get_instance()->uninstall_single(); } switch_to_blog( $main_blog_id ); } // Delete assets (main blog). Advanced_Ads_Ad_Blocker_Admin::get_instance()->clear_assets(); } } /** * Fired for each blog when the plugin is uninstalled. */ protected function uninstall_single() { global $wpdb; // Ads. $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s", Advanced_Ads::POST_TYPE_SLUG ) ); if ( $post_ids ) { $wpdb->delete( $wpdb->posts, array( 'post_type' => Advanced_Ads::POST_TYPE_SLUG ), array( '%s' ) ); $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE post_id IN( %s )", implode( ',', $post_ids ) ) ); } // Groups. $term_ids = $wpdb->get_col( $wpdb->prepare( "SELECT t.term_id FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s", Advanced_Ads::AD_GROUP_TAXONOMY ) ); foreach ( $term_ids as $term_id ) { wp_delete_term( $term_id, Advanced_Ads::AD_GROUP_TAXONOMY ); } delete_option( 'advads-ad-groups' ); delete_option( Advanced_Ads::AD_GROUP_TAXONOMY . '_children' ); delete_option( 'advads-ad-weights' ); // Placements. delete_option( 'advads-ads-placements' ); // User metadata. delete_metadata( 'user', null, 'advanced-ads-hide-wizard', '', true ); delete_metadata( 'user', null, 'advanced-ads-subscribed', '', true ); // Post metadata. delete_metadata( 'post', null, '_advads_ad_settings', '', true ); // Transients. delete_transient( ADVADS_SLUG . '_add-on-updates-checked' ); delete_option( GADSENSE_OPT_NAME ); delete_option( ADVADS_SLUG ); delete_option( ADVADS_SLUG . '-internal' ); delete_option( ADVADS_SLUG . '-notices' ); // Widget. $base_widget_id = Advanced_Ads_Widget::get_base_id(); delete_option( 'widget_' . $base_widget_id ); // Ad blocker disquise. delete_option( ADVADS_AB_SLUG ); do_action( 'advanced-ads-uninstall' ); wp_cache_flush(); } /** * Check if any add-on is activated * * @return bool true if there is any add-on activated */ public static function any_activated_add_on() { return ( defined( 'AAP_VERSION' ) // Advanced Ads Pro. || defined( 'AAGAM_VERSION' ) // Google Ad Manager. || defined( 'AASA_VERSION' ) // Selling Ads. || defined( 'AAT_VERSION' ) // Tracking. || defined( 'AASADS_VERSION' ) // Sticky Ads. || defined( 'AAR_VERSION' ) // Responsive Ads. || defined( 'AAPLDS_VERSION' ) // PopUp and Layer Ads. || defined( 'AAGT_SLUG' ) // Geo-Targeting. ); } /** * Get the correct support URL: wp.org for free users and website for those with any add-on installed * * @param string $utm add UTM parameter to the link leading to https://wpadvancedads.com, if given. * * @return string URL. */ public static function support_url( $utm = '' ) { $utm = empty( $utm ) ? '#utm_source=advanced-ads&utm_medium=link&utm_campaign=support' : $utm; if ( self::any_activated_add_on() ) { $url = ADVADS_URL . 'support/' . $utm . '-with-addons'; } else { $url = ADVADS_URL . 'support/' . $utm . '-free-user'; } return $url; } /** * Create a random group * * @param string $url optional parameter. * @param string $ex group. * * @return bool */ public static function get_group_by_url( $url = '', $ex = 'a' ) { $url = self::get_short_url( $url ); $code = intval( substr( md5( $url ), - 1 ), 16 ); switch ( $ex ) { case 'b': return ( $code & 2 ) >> 1; // returns 1 or 0. case 'c': return ( $code & 4 ) >> 2; // returns 1 or 0. case 'd': return ( $code & 8 ) >> 3; // returns 1 or 0. default: return $code & 1; // returns 1 or 0. } } /** * Check if user started after a given date * * @param integer $timestamp time stamp. * * @return bool true if user is added after timestamp. */ public static function is_new_user( $timestamp = 0 ) { // allow admins to see version for new users in any case. if ( current_user_can( self::user_cap( 'advanced_ads_manage_options' ) ) && isset( $_REQUEST['advads-ignore-timestamp'] ) ) { return true; } $timestamp = absint( $timestamp ); $options = self::get_instance()->internal_options(); $installed = isset( $options['installed'] ) ? $options['installed'] : 0; return ( $installed >= $timestamp ); } /** * Show stuff to new users only. * * @param integer $timestamp time after which to show whatever. * @param string $group optional group. * * @return bool true if user enabled after given timestamp. */ public static function show_to_new_users( $timestamp, $group = 'a' ) { return ( self::get_group_by_url( null, $group ) && self::is_new_user( $timestamp ) ); } /** * Get short version of home_url() * remove protocol and www * remove slash * * @param string $url URL to be shortened. * * @return string */ public static function get_short_url( $url = '' ) { $url = empty( $url ) ? home_url() : $url; // strip protocols. if ( preg_match( '/^(\w[\w\d]*:\/\/)?(www\.)?(.*)$/', trim( $url ), $matches ) ) { $url = $matches[3]; } // strip slashes. $url = trim( $url, '/' ); return $url; } /** * Return Advanced Ads logo in base64 format for use in WP Admin menu. * * @return string */ public static function get_icon_svg() { return 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE4LjEuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJFYmVuZV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDY0Ljk5MyA2NS4wMjQiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDY0Ljk5MyA2NS4wMjQ7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxwYXRoIHN0eWxlPSJmaWxsOiNFNEU0RTQ7IiBkPSJNNDYuNTcxLDI3LjY0MXYyMy4xMzNIMTQuMjVWMTguNDUzaDIzLjExOGMtMC45NTYtMi4xODMtMS40OTQtNC41OS0xLjQ5NC03LjEyNg0KCWMwLTIuNTM1LDAuNTM4LTQuOTQyLDEuNDk0LTcuMTI0aC02Ljk1N0gwdjQ5LjQ5M2wxLjYxOCwxLjYxOEwwLDUzLjY5NmMwLDYuMjU2LDUuMDY4LDExLjMyNiwxMS4zMjQsMTEuMzI4djBoMTkuMDg3aDMwLjQxMlYyNy42MTENCgljLTIuMTkxLDAuOTY0LTQuNjA5LDEuNTA5LTcuMTU3LDEuNTA5QzUxLjE0MiwyOS4xMiw0OC43NDYsMjguNTg4LDQ2LjU3MSwyNy42NDF6Ii8+DQo8Y2lyY2xlIHN0eWxlPSJmaWxsOiM5ODk4OTg7IiBjeD0iNTMuNjY2IiBjeT0iMTEuMzI4IiByPSIxMS4zMjgiLz4NCjwvc3ZnPg0K'; } /** * Fires when a post is transitioned from one status to another. * * @param string $new_status New post status. * @param string $old_status Old post status. * @param WP_Post $post Post object. */ public function transition_ad_status( $new_status, $old_status, $post ) { if ( ! isset( $post->post_type ) || Advanced_Ads::POST_TYPE_SLUG !== $post->post_type || ! isset( $post->ID ) ) { return; } $ad = new Advanced_Ads_Ad( $post->ID ); if ( $old_status !== $new_status ) { /** * Fires when an ad has transitioned from one status to another. * * @param Advanced_Ads_Ad $ad Ad object. */ do_action( "advanced-ads-ad-status-{$old_status}-to-{$new_status}", $ad ); } if ( 'publish' === $new_status && 'publish' !== $old_status ) { /** * Fires when an ad has transitioned from any other status to `publish`. * * @param Advanced_Ads_Ad $ad Ad object. */ do_action( 'advanced-ads-ad-status-published', $ad ); } if ( 'publish' === $old_status && 'publish' !== $new_status ) { /** * Fires when an ad has transitioned from `publish` to any other status. * * @param Advanced_Ads_Ad $ad Ad object. */ do_action( 'advanced-ads-ad-status-unpublished', $ad ); } } }