Files
roi-theme/wp-content/plugins/advanced-ads/modules/gadsense/includes/class-mapi.php
root a22573bf0b Commit inicial - WordPress Análisis de Precios Unitarios
- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:04:30 -06:00

1763 lines
53 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php // phpcs:ignoreFile
use AdvancedAds\Utilities\Conditional;
use AdvancedAds\Framework\Utilities\Params;
/**
* AdSense Management API class.
*/
class Advanced_Ads_AdSense_MAPI {
/**
* The Adsense MAPI settings in the database.
*
* @var string
*/
const OPTION_KEY = 'advanced-ads-adsense-mapi';
/**
* The URL for retrieving alerts from the Google AdSense API.
*
* @var string
*/
const ALERTS_URL = 'https://adsense.googleapis.com/v2/accounts/PUBID/alerts';
/**
* Google Adsense Client ID.
*
* @var string
*/
const CID = '400595147946-3ot506jh20qld7bqmg1l87ms4vn2uok5.apps.googleusercontent.com';
/**
* Google AdSense Client Secret.
*
* @var string
*/
const CS = 'WKX8ghwUbxdrBcVmZ9WXOKph';
/**
* The redirect URI for the Google AdSense API authentication.
*
* @var string
*/
const REDIRECT_URI = 'https://c.wpadvancedads.com/oauth.php';
/**
* The maximum number of API calls allowed per 24 hours.
*
* @var int
*/
const CALL_PER_24H = 20;
/**
* Class Mapi
*
* @var Advanced_Ads_AdSense_MAPI
*/
private static $instance = null;
/**
* Default options.
*
* @var array
*/
private static $default_options = [];
/**
* Default account options.
*
* @var array
*/
private static $empty_account_data = [
'default_app' => [
'access_token' => '',
'refresh_token' => '',
'expires' => 0,
'token_type' => '',
],
'user_app' => [
'access_token' => '',
'refresh_token' => '',
'expires' => 0,
'token_type' => '',
],
'ad_units' => [],
'details' => [],
'alerts' => [],
];
/**
* Instance constructor
*/
private function __construct() {
add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts' ] );
add_action( 'wp_ajax_advads_gadsense_mapi_confirm_code', [ $this, 'ajax_confirm_code' ] );
add_action( 'wp_ajax_advads_gadsense_mapi_get_details', [ $this, 'ajax_get_account_details' ] );
add_action( 'wp_ajax_advads_gadsense_mapi_select_account', [ $this, 'ajax_account_selected' ] );
add_action( 'wp_ajax_advads_mapi_get_adCode', [ $this, 'ajax_get_ad_code' ] );
add_action( 'wp_ajax_advads-mapi-reconstructed-code', [ $this, 'ajax_save_reconstructed_code' ] );
add_action( 'wp_ajax_advads-mapi-save-manual-code', [ $this, 'ajax_save_manual_code' ] );
add_action( 'wp_ajax_advads-mapi-revoke-token', [ $this, 'ajax_revoke_tokken' ] );
add_action( 'wp_ajax_advads-mapi-get-alerts', [ $this, 'ajax_get_account_alerts' ] );
add_action( 'wp_ajax_advads-mapi-dismiss-alert', [ $this, 'ajax_dismiss_alert' ] );
add_action( 'wp_ajax_advads_adsense_report_refresh', [ 'Advanced_Ads_Overview_Widgets_Callbacks', 'ajax_gadsense_dashboard' ] );
add_action( 'admin_footer', [ $this, 'admin_footer' ] );
self::$default_options = [
'accounts' => [],
'ad_codes' => [],
'unsupported_units' => [],
'quota' => [
'count' => self::CALL_PER_24H,
'ts' => 0,
],
'connect_error' => [],
];
add_action( 'wp_loaded', [ $this, 'update_ad_health_notices' ] );
add_filter( 'advanced-ads-support-messages', [ 'Advanced_Ads_AdSense_MAPI', 'adsense_warnings_check' ] );
}
/**
* Update all MAPI related notices.
*/
public function update_ad_health_notices() {
$mapi_options = self::get_option();
$connection_error_messages = self::get_connect_error_messages();
$health_class = Advanced_Ads_Ad_Health_Notices::get_instance();
// Last connection failed.
if ( isset( $mapi_options['connect_error'] ) && ! empty( $mapi_options['connect_error'] ) ) {
if ( isset( $connection_error_messages[ $mapi_options['connect_error']['reason'] ] ) ) {
$health_class->add( 'adsense_connect_' . $mapi_options['connect_error']['reason'] );
} else {
$health_class->add(
'adsense_connect_' . $mapi_options['connect_error']['reason'],
[
'text' => esc_html__( 'Last AdSense account connection attempt failed.', 'advanced-ads' ) . ' ' . $mapi_options['connect_error']['message'],
'type' => 'problem',
]
);
}
foreach ( $health_class->notices as $key => $value ) {
// There was already a connection error but the user tried again and obtained another error.
if ( false !== stripos( $key, 'adsense_connect_' ) && 'adsense_connect_' . $mapi_options['connect_error']['reason'] !== $key ) {
$health_class->remove( $key );
}
}
} else {
// Once a connection has been established (or a the warning has been discarded on the AA settings page), remove connection related notices.
foreach ( $health_class->notices as $key => $value ) {
if ( false !== stripos( $key, 'adsense_connect_' ) ) {
$health_class->remove( $key );
}
}
}
$gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
$adsense_id = $gadsense_data->get_adsense_id();
$alerts = self::get_stored_account_alerts( $adsense_id );
// AdSense account alerts (can not happens simultaneously with the connection error).
if ( is_array( $alerts ) && isset( $alerts['items'] ) && is_array( $alerts['items'] ) && $alerts['items'] ) {
$item_ids = [];
$alerts_advads_messages = Advanced_Ads_Adsense_MAPI::get_adsense_alert_messages();
foreach ( $alerts['items'] as $internal_id => $item ) {
$item_id = isset( $item['id'] ) ? $item['id'] : str_replace( '-', '_', strtoupper( $item['type'] ) );
$item_ids[] = $item_id;
if ( isset( $alerts_advads_messages[ $item_id ] ) ) {
$health_class->add( 'adsense_alert_' . $item_id );
} else {
$health_class->add(
'adsense_alert_' . $item_id,
[
'text' => $item['message'] . ' ' . self::get_adsense_error_link( $item_id ),
'type' => 'problem',
]
);
}
}
// Remove notices that no more exist in the AdSense account (or have been dismissed).
$_remove_ids = [];
foreach ( $health_class->notices as $key => $value ) {
if ( false !== stripos( $key, 'adsense_alert_' ) ) {
$alert_id = substr( $key, strlen( 'adsense_alert_' ) );
if ( ! in_array( $alert_id, $item_ids, true ) ) {
$_remove_ids[] = $key;
}
}
}
foreach ( $_remove_ids as $id ) {
$health_class->remove( $id );
}
} else {
// No more alerts.
foreach ( $health_class->notices as $key => $value ) {
if ( false !== stripos( $key, 'adsense_alert_' ) ) {
$health_class->remove( $key );
}
}
}
}
/**
* Get available quota and eventual message about remaining call
*/
public function get_quota() {
// Early bail!!
if ( self::use_user_app() ) {
return [ 'count' => PHP_INT_MAX ];
}
$now = time();
$options = $this->get_option();
if ( $now > $options['quota']['ts'] + ( 24 * 3600 ) ) {
return [
'count' => self::CALL_PER_24H,
];
}
return [
'count' => $options['quota']['count'],
'msg' => $this->get_quota_msg(),
];
}
/**
* Get the readable quota
*/
public function get_quota_msg() {
$options = $this->get_option();
$now = time();
$secs = $options['quota']['ts'] + ( 24 * 3600 ) - $now;
$hours = floor( $secs / 3600 );
$mins = ceil( ( $secs - ( $hours * 3600 ) ) / 60 );
if ( 60 === $mins ) {
++$hours;
$mins = 0;
}
if ( 0 === (int) $options['quota']['count'] ) {
$msg = sprintf(
'No API call left before %1$s %2$s.',
sprintf( '%s hours', $hours ),
sprintf( '%s minutes', $mins )
);
if ( 0 === $hours ) {
$msg = 'No API call left before.';
}
if ( 0 === $mins ) {
$msg = 'No API call left.';
}
} else {
$msg = sprintf(
'%1$s for the next %2$s %3$s',
sprintf( '%s API calls remaining', $options['quota']['count'] ),
sprintf( '%s hours', $hours ),
sprintf( '%s minutes', $mins )
);
if ( 0 === $hours ) {
$msg = sprintf( '%s API calls remaining.', $options['quota']['count'] );
}
if ( 0 === $mins ) {
$msg = sprintf(
'%1$s for the next %2$s',
sprintf( '%s API calls remaining', $options['quota']['count'] ),
sprintf( '%s hours', $hours )
);
}
}
return $msg;
}
/**
* Decrement quota by 1, and return message about remaining call
*/
public function decrement_quota() {
$options = $this->get_option();
if ( 0 < $options['quota']['count'] ) {
--$options['quota']['count'];
$now = time();
if ( $now > $options['quota']['ts'] + ( 24 * 3600 ) ) {
$options['quota']['ts'] = $now;
}
update_option( self::OPTION_KEY, $options );
return $this->get_quota_msg();
}
}
/**
* Get ad code from Google fpr a given ad unit
*
* @param string $ad_unit the ad unit to get the ad code for.
*
* @return array response to send back to the browser.
*/
public function get_ad_code( $ad_unit ) {
$options = self::get_option();
$gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
$adsense_id = $gadsense_data->get_adsense_id();
$unit_id = explode( ':', $ad_unit )[1];
$url = 'https://adsense.googleapis.com/v2/accounts/' . $adsense_id . '/adclients/ca-' . $adsense_id . '/adunits/' . $unit_id . '/adcode';
$access_token = self::get_access_token( $adsense_id );
foreach ( Advanced_Ads_Network_Adsense::get_instance()->get_external_ad_units() as $unit ) {
if (
isset( $unit->raw )
&& in_array( $unit->raw['contentAdsSettings']['type'], [ 'ARTICLE', 'FEED', 'MATCHED_CONTENT' ], true )
&& $ad_unit === $unit->id
&& ! array_key_exists( $ad_unit, $options['ad_codes'] )
) {
$options['unsupported_units'][ $ad_unit ] = 1;
update_option( self::OPTION_KEY, $options );
return [
'status' => false,
'msg' => 'doesNotSupportAdUnitType',
];
}
}
if ( ! isset( $access_token['msg'] ) ) {
$headers = [ 'Authorization' => 'Bearer ' . $access_token ];
$response = wp_remote_get( $url, [ 'headers' => $headers ] );
self::log( 'Get ad code for ad Unit [' . $ad_unit . ']' );
if ( is_wp_error( $response ) ) {
return [
'status' => false,
/* translators: %s: ad unit ID. */
'msg' => sprintf( esc_html__( 'Error while retrieving ad code for "%s".', 'advanced-ads' ), $ad_unit ),
'raw' => $response->get_error_message(),
];
}
$ad_code = json_decode( $response['body'], true );
if ( null === $ad_code || ! isset( $ad_code['adCode'] ) ) {
if ( $ad_code['error'] &&
$ad_code['error']['errors'] &&
isset( $ad_code['error']['errors'][0]['reason'] ) &&
'doesNotSupportAdUnitType' === $ad_code['error']['errors'][0]['reason']
) {
if ( array_key_exists( $ad_unit, $options['ad_codes'] ) && array_key_exists( $ad_unit, $options['unsupported_units'] ) ) {
unset( $options['unsupported_units'][ $ad_unit ] );
} else {
$options['unsupported_units'][ $ad_unit ] = 1;
}
update_option( self::OPTION_KEY, $options );
return [
'status' => false,
'msg' => 'doesNotSupportAdUnitType',
];
}
return [
'status' => false,
/* translators: %s: ad unit ID. */
'msg' => sprintf( esc_html__( 'Invalid response while retrieving ad code for "%s".', 'advanced-ads' ), $ad_unit ),
'raw' => $response['body'],
];
}
$options['ad_codes'][ $ad_unit ] = $ad_code['adCode'];
if ( isset( $options['unsupported_units'][ $ad_unit ] ) ) {
unset( $options['unsupported_units'][ $ad_unit ] );
}
update_option( self::OPTION_KEY, $options );
return $ad_code['adCode'];
}
// return the original error info.
return $access_token;
}
/**
* Convert ad unit data to v1.4 format to match the current UI and logics
*
* @param array $ad_unit ad unit in MAPI v2 format.
*
* @return array the ad unit in MAPI v1.4 format.
*/
public static function convert_ad_unit_format( $ad_unit ) {
$chunks = explode( '/', $ad_unit['name'] );
return [
'name' => $ad_unit['displayName'],
'nameV2' => $ad_unit['name'],
'id' => $ad_unit['reportingDimensionId'],
'code' => $chunks[ count( $chunks ) - 1 ],
'status' => $ad_unit['state'],
'contentAdsSettings' => $ad_unit['contentAdsSettings'],
'reportingDimensionId' => $ad_unit['reportingDimensionId'],
];
}
/**
* Get/Update ad unit list for a given client
*
* @param string $account publisher ID.
*
* @return array
*/
public static function get_ad_units( $account ) {
$url = 'https://adsense.googleapis.com/v2/accounts/' . $account . '/adclients/ca-' . $account . '/adunits?pageSize=350';
$access_token = self::get_access_token( $account );
if ( isset( $access_token['msg'] ) ) {
// Return the token related message.
return $access_token;
}
$response = wp_remote_get( $url, [ 'headers' => [ 'Authorization' => 'Bearer ' . $access_token ] ] );
self::log( 'Get ad units list for ca-' . $account );
if ( is_wp_error( $response ) ) {
return [
'status' => false,
/* translators: %s is the publisher ID. */
'msg' => sprintf( esc_html__( 'Error while retrieving ad unit list for "%s".', 'advanced-ads' ), $account ),
'raw' => $response->get_error_message(),
];
}
if ( trim( $response['body'] ) === '{}' ) {
// Empty account.
return [
'status' => false,
'msg' => sprintf(
/* translators: %1$s is the AdSense publisher ID; %2$s a starting a tag to the AdSense ad unit list and %3$s the closing link. */
esc_html__( 'The account "%1$s" does not seem to have any ad units. Please create some %2$shere%3$s.', 'advanced-ads' ),
$account,
'<a href="https://www.google.com/adsense/new/u/0/' . $account . '/myads/units" target="_blank">',
'</a>'
),
'raw' => $response['body'],
];
}
$response_body = json_decode( trim( $response['body'] ), true );
if ( null === $response_body || ! isset( $response_body['adUnits'] ) ) {
/* translators: %s is the publisher ID. */
$error_message = sprintf( esc_html__( 'Invalid response while retrieving ad unit list for "%s".', 'advanced-ads' ), $account );
// check the response for errors and display them for better problem-solving.
if ( ! empty( $response_body['error']['errors'] ) ) {
foreach ( $response_body['error']['errors'] as $err ) {
$hint = self::get_adsense_error_hint( $err['reason'] );
if ( $hint ) {
$error_message .= '<p class="description">' . $hint . '</p>';
}
$error_message .= sprintf(
'<p class="description">%1$s %2$s<br>%3$s %4$s</p>',
_x( 'Reason:', 'Reason of the API call error', 'advanced-ads' ),
$err['reason'],
_x( 'Message:', 'Error message from Google', 'advanced-ads' ),
$err['message']
);
}
}
return [
'status' => false,
'msg' => $error_message,
'raw' => trim( $response['body'] ),
];
}
$options = self::get_option();
if ( ! isset( $response_body['nextPageToken'] ) ) {
// Results fit into a single page (of 350 items).
$new_ad_units = [];
foreach ( $response_body['adUnits'] as $item ) {
$item = self::convert_ad_unit_format( $item );
$new_ad_units[ $item['id'] ] = $item;
}
$options['accounts'][ $account ]['ad_units'] = $new_ad_units;
update_option( self::OPTION_KEY, $options );
return [ 'done' => true ];
}
// There are more than 350 items in the account.
$page_token = $response_body['nextPageToken'];
$new_ad_units = [];
foreach ( $response_body['adUnits'] as $item ) {
$item = self::convert_ad_unit_format( $item );
$new_ad_units[ $item['id'] ] = $item;
}
$page = 1;
// While there is a next page of results do . . .
while ( $page_token ) {
$access_token = self::get_access_token( $account );
if ( isset( $access_token['msg'] ) ) {
// return the original error info.
return $access_token;
}
$next_url = $url . '&pageToken=' . urlencode( $page_token );
$headers = [
'Authorization' => 'Bearer ' . $access_token,
];
$response = wp_remote_get( $next_url, [ 'headers' => $headers ] );
self::log( 'Get ad unit list for ca-' . $account . ' page ' . $page );
++$page;
if ( is_wp_error( $response ) ) {
return [
'status' => false,
/* translators: %s is the publisher ID. */
'msg' => sprintf( esc_html__( 'Error while retrieving ad unit list for "%s".', 'advanced-ads' ), $account ),
'raw' => $response->get_error_message(),
];
}
$response_body = json_decode( $response['body'], true );
// Update page token if there are ad units left.
$page_token = isset( $response_body['nextPageToken'] ) ? $response_body['nextPageToken'] : false;
// Add items from this page into the final result.
foreach ( $response_body['adUnits'] as $item ) {
$item = self::convert_ad_unit_format( $item );
$new_ad_units[ $item['id'] ] = $item;
}
}
$options['accounts'][ $account ]['ad_units'] = $new_ad_units;
update_option( self::OPTION_KEY, $options );
return [ 'done' => true ];
}
/**
* Get the appropriate access token (default one or from user's Google app). Update it if needed.
*
* @param string $account publisher ID.
*
* @return array|string the access token on success, error info (as array) if an error occurred.
*/
public static function get_access_token( $account ) {
$options = self::get_option();
if ( isset( $options['accounts'][ $account ] ) ) {
if ( self::use_user_app() ) {
if ( time() > $options['accounts'][ $account ]['user_app']['expires'] ) {
$new_tokens = self::renew_access_token( $account );
if ( $new_tokens['status'] ) {
return $new_tokens['access_token'];
} else {
return $new_tokens;
}
} else {
return $options['accounts'][ $account ]['user_app']['access_token'];
}
} else {
if ( time() > $options['accounts'][ $account ]['default_app']['expires'] ) {
$new_tokens = self::renew_access_token( $account );
if ( $new_tokens['status'] ) {
return $new_tokens['access_token'];
} else {
// return all error info [arr].
return $new_tokens;
}
} else {
return $options['accounts'][ $account ]['default_app']['access_token'];
}
}
} else {
// Account does not exist.
if ( ! empty( $options['accounts'] ) ) {
// There is another account connected.
return [
'status' => false,
'msg' => esc_html__( 'It seems that some changes have been made in the Advanced Ads settings. Please refresh this page.', 'advanced-ads' ),
'reload' => true,
];
} else {
// No account at all.
return [
'status' => false,
/* translators: %s account id */
'msg' => wp_kses( sprintf( __( 'Advanced Ads does not have access to your account (<code>%s</code>) anymore.', 'advanced-ads' ), $account ), [ 'code' => true ] ),
'reload' => true,
];
}
}
}
/**
* Renew the current access token.
*
* @param array $account AdSense account ID.
*/
public static function renew_access_token( $account ) {
$cid = self::CID;
$cs = self::CS;
$options = self::get_option();
$access_token = $options['accounts'][ $account ]['default_app']['access_token'];
$refresh_token = $options['accounts'][ $account ]['default_app']['refresh_token'];
if ( self::use_user_app() ) {
$gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
$_options = $gadsense_data->get_options();
$cid = ADVANCED_ADS_MAPI_CID;
$cs = ADVANCED_ADS_MAPI_CIS;
$access_token = $options['accounts'][ $account ]['user_app']['access_token'];
$refresh_token = $options['accounts'][ $account ]['user_app']['refresh_token'];
}
$url = 'https://www.googleapis.com/oauth2/v4/token';
$args = [
'body' => [
'refresh_token' => $refresh_token,
'client_id' => $cid,
'client_secret' => $cs,
'grant_type' => 'refresh_token',
],
];
$response = wp_remote_post( $url, $args );
self::log( 'Refresh access token' );
if ( is_wp_error( $response ) ) {
return [
'status' => false,
/* translators: %s account id */
'msg' => sprintf( esc_html__( 'error while renewing access token for "%s"', 'advanced-ads' ), $account ),
'raw' => $response->get_error_message(),
];
} else {
$tokens = json_decode( $response['body'], true );
// checking for the $tokens is not enough. it can be empty.
// monitored this, when the access token is revoked from the outside
// this can happen, when the user connects from another domain.
if ( null !== $tokens && isset( $tokens['expires_in'] ) ) {
$expires = time() + absint( $tokens['expires_in'] );
if ( self::use_user_app() ) {
$options['accounts'][ $account ]['user_app']['access_token'] = $tokens['access_token'];
$options['accounts'][ $account ]['user_app']['expires'] = $expires;
} else {
$options['accounts'][ $account ]['default_app']['access_token'] = $tokens['access_token'];
$options['accounts'][ $account ]['default_app']['expires'] = $expires;
}
update_option( self::OPTION_KEY, $options );
return [
'status' => true,
'access_token' => $tokens['access_token'],
];
} else {
return [
'status' => false,
'msg' => sprintf(
/* translators: %s AdSense account ID */
esc_html__( 'invalid response received while renewing access token for "%s"', 'advanced-ads' ),
$account
) . ' ' . __( 'You could try to connect again under Advanced Ads > Settings > AdSense.', 'advanced-ads' ),
'raw' => $response['body'],
];
}
}
}
/**
* Recoke a refresh token
*/
public function ajax_revoke_tokken() {
$nonce = Params::post( 'nonce', '' );
if ( ! Conditional::user_can( 'advanced_ads_manage_options' ) ) {
die;
}
if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
$adsense_id = stripslashes( Params::post( 'adsenseId', '' ) );
$options = self::get_option();
if ( self::use_user_app() ) {
$token = $options['accounts'][ $adsense_id ]['user_app']['refresh_token'];
} else {
$token = $options['accounts'][ $adsense_id ]['default_app']['refresh_token'];
}
$url = 'https://accounts.google.com/o/oauth2/revoke?token=' . $token;
$args = [
'timeout' => 5,
'header' => [ 'Content-type' => 'application/x-www-form-urlencoded' ],
];
$response = wp_remote_post( $url, $args );
self::log( 'Revoke API access for ca-' . $adsense_id );
if ( is_wp_error( $response ) ) {
echo wp_json_encode( [ 'status' => false ] );
} else {
global $wpdb;
$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'advanced_ads_adsense_report_%';" );
delete_option( 'advanced-ads-adsense-dashboard-filter' );
header( 'Content-Type: application/json' );
unset( $options['accounts'][ $adsense_id ] );
update_option( self::OPTION_KEY, $options );
echo wp_json_encode( [ 'status' => true ] );
}
}
die;
}
/**
* When a user manually adds an ad code, save it
*/
public function ajax_save_manual_code() {
if ( ! Conditional::user_can( 'advanced_ads_edit_ads' ) ) {
die();
}
if ( ! wp_verify_nonce( Params::request( 'nonce', '' ), 'advads-mapi' ) ) {
die();
}
$publisher_id = sanitize_text_field( wp_unslash( isset( $_POST['parsed_code']['pubId'] ) ? $_POST['parsed_code']['pubId'] : '' ) );
if ( ! $this->check_valid_publisher( $publisher_id ) ) {
wp_send_json_error(
[
'message' => __( 'This ad code is from a different AdSense Account', 'advanced-ads' ),
],
400
);
}
if ( empty( $_POST['parsed_code']['slotId'] ) || empty( $_POST['raw_code'] ) ) {
die();
}
static $options;
if ( is_null( $options ) ) {
$options = self::get_option();
}
$slot_id = 'ca-' . $publisher_id . ':' . sanitize_text_field( wp_unslash( $_POST['parsed_code']['slotId'] ) );
// phpcs:disable WordPress.Security
$options['ad_codes'][ $slot_id ] = urldecode( Params::post( 'raw_code', '' ) );
// phpcs:enable
if ( array_key_exists( $slot_id, $options['unsupported_units'] ) ) {
unset( $options['unsupported_units'][ $slot_id ] );
}
wp_send_json_success( [ 'updated' => update_option( self::OPTION_KEY, $options ) ] );
}
/**
* Check if the provided AdSense Publisher ID matches the saved ID
*
* @param string $pub AdSense Publisher ID.
*
* @return bool
*/
protected function check_valid_publisher( $pub ) {
return Advanced_Ads_AdSense_Data::get_instance()->get_adsense_id() === $pub;
}
/**
* Save ad code reconstructed from ad parameters
*/
public function ajax_save_reconstructed_code() {
$nonce = Params::post( 'nonce', '' );
if ( ! Conditional::user_can( 'advanced_ads_edit_ads' ) ) {
die;
}
if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
$code = stripslashes( Params::post( 'code', '' ) );
$slot = stripslashes( Params::post( 'slot', '' ) );
$gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
$adsense_id = $gadsense_data->get_adsense_id();
$options = self::get_option();
$options['ad_codes'][ 'ca-' . $adsense_id . ':' . $slot ] = $code;
update_option( self::OPTION_KEY, $options );
header( 'Content-Type: application/json' );
echo wp_json_encode( [ 'status' => true ] );
}
die;
}
/**
* Get ad code for a given unit
*/
public function ajax_get_ad_code() {
if ( ! Conditional::user_can( 'advanced_ads_edit_ads' ) ) {
wp_send_json_error( 'Unauthorized', 401 );
}
$post_data = wp_unslash( $_POST );
$nonce = isset( $post_data['nonce'] ) ? $post_data['nonce'] : '';
if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
$unit = stripslashes( $post_data['unit'] );
if ( ! self::use_user_app() ) {
$quota = $this->get_quota();
// No more quota left.
if ( $quota['count'] < 1 ) {
header( 'Content-Type: application/json' );
$quota_msg = $this->get_quota_msg();
echo wp_json_encode(
[
'quota' => 0,
'quotaMsg' => $quota_msg,
]
);
die;
}
}
$code = $this->get_ad_code( $unit );
/**
* Ad code is returned as string. Otherwise it's an error
*/
if ( is_string( $code ) ) {
$ad_units = array_filter(
Advanced_Ads_Network_Adsense::get_instance()->get_external_ad_units(),
function ( Advanced_Ads_Ad_Network_Ad_Unit $ad_unit ) use ( $unit ) {
return $ad_unit->id === $unit;
}
);
$ad_unit = reset( $ad_units );
$response = [
'code' => $code,
'type' => self::format_ad_data( $ad_unit, 'type' ),
];
/**
* Add quota info for default API creds
*/
if ( ! self::use_user_app() ) {
$quota = $this->get_quota();
$quota_msg = $this->get_quota_msg();
$response['quota'] = $quota['count'];
$response['quotaMsg'] = $quota_msg;
}
header( 'Content-Type: application/json' );
echo wp_json_encode( $response );
} else {
// return info about the error.
header( 'Content-Type: application/json' );
echo wp_json_encode( $code );
}
}
die;
}
/**
* Dismiss an account alert
*/
public function ajax_dismiss_alert() {
if ( ! Conditional::user_can( 'advanced_ads_manage_options' ) ) {
die;
}
$nonce = Params::post( 'nonce', '' );
if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
$account = stripslashes( Params::post( 'account', '' ) );
$id = stripslashes( Params::post( 'id', '' ) );
$options = self::get_option();
$items = [];
// the account exists.
if ( isset( $options['accounts'][ $account ] ) ) {
// the alert exists.
if ( isset( $options['accounts'][ $account ]['alerts']['items'][ $id ] ) ) {
unset( $options['accounts'][ $account ]['alerts']['items'][ $id ] );
update_option( self::OPTION_KEY, $options );
$items = $options['accounts'][ $account ]['alerts']['items'];
}
}
wp_send_json(
[
'status' => true,
'alerts' => $items,
'length' => count( $items ),
]
);
}
die;
}
/**
* Get / Update the list of alerts on an AdSense account.
*/
public function ajax_get_account_alerts() {
if ( ! Conditional::user_can( 'advanced_ads_manage_options' ) ) {
die;
}
$nonce = Params::post( 'nonce', '' );
if ( false !== wp_verify_nonce( $nonce, 'mapi-alerts' ) ) {
$account = stripslashes( Params::post( 'account', '' ) );
$options = self::get_option();
// the account exists.
if ( isset( $options['accounts'][ $account ] ) && self::has_token( $account ) ) {
$access_token = self::get_access_token( $account );
$url = str_replace( 'PUBID', $account, self::ALERTS_URL );
if ( isset( $_POST['inlineAttempt'] ) ) {
if ( ! is_array( $options['accounts'][ $account ]['alerts'] ) ) {
$options['accounts'][ $account ]['alerts'] = [];
}
$options['accounts'][ $account ]['alerts']['inlineAttempt'] = time();
update_option( self::OPTION_KEY, $options );
}
// the token is valid.
if ( ! isset( $access_token['msg'] ) ) {
$headers = [
'Authorization' => 'Bearer ' . $access_token,
];
$response = wp_remote_get( $url, [ 'headers' => $headers ] );
$this->log( 'Get AdSense alerts for ' . $account );
// the HTTP response is not an error.
if ( ! is_wp_error( $response ) ) {
$alerts = json_decode( $response['body'], true );
// the response body is valid.
if ( is_array( $alerts ) && isset( $alerts['alerts'] ) ) {
$items = [];
foreach ( $alerts['alerts'] as $item ) {
// Do not store alerts of type "INFO".
if ( strcasecmp( $item['severity'], 'INFO' ) !== 0 ) {
$items[ wp_generate_password( 6, false ) ] = $item;
}
}
// filter alerts that are not relevant to the user.
$items = self::filter_account_alerts( $items );
$alerts_array = [
'items' => $items,
'lastCheck' => time(),
];
$options['accounts'][ $account ]['alerts'] = $alerts_array;
update_option( self::OPTION_KEY, $options );
$results = [
'status' => true,
'alerts' => $items,
'length' => count( $items ),
];
header( 'Content-Type:application/json' );
echo wp_json_encode( $results );
} else {
$results = [
'status' => false,
'msg' => esc_html__( 'Invalid response body while retrieving account alerts', 'advanced-ads' ),
];
header( 'Content-Type:application/json' );
echo wp_json_encode( $results );
}
} else {
$results = [
'status' => false,
'msg' => esc_html__( 'error while retrieving account alerts', 'advanced-ads' ),
'raw' => $response->get_error_message(),
];
header( 'Content-Type:application/json' );
echo wp_json_encode( $results );
}
} else {
// return the original error info.
return $access_token;
}
} else {
header( 'Content-Type:application/json' );
echo wp_json_encode( [ 'status' => false ] );
}
}
die;
}
/**
* Get / Update the ad unit list for a given ad client. The corresponding <select /> input used in the ad selector is passed as a fied of an array
*/
public function ajax_get_adUnits() {
if ( ! Conditional::user_can( 'advanced_ads_edit_ads' ) ) {
die;
}
$post_vars = wp_unslash( $_POST );
$nonce = isset( $post_vars['nonce'] ) ? wp_strip_all_tags( $post_vars['nonce'] ) : '';
if ( wp_verify_nonce( $nonce, 'advads-mapi' ) && isset( $post_vars['account'] ) ) {
$account = wp_strip_all_tags( stripslashes( $post_vars['account'] ) );
$units = self::get_ad_units( $account );
if ( isset( $units['done'] ) && true === $units['done'] ) {
ob_start();
Advanced_Ads_AdSense_Admin::get_mapi_ad_selector();
$ad_selector = ob_get_clean();
$response = [
'status' => true,
'html' => $ad_selector,
];
/**
* Add quota info for default API creds
*/
if ( ! self::use_user_app() ) {
$quota = $this->get_quota();
$quota_msg = $this->get_quota_msg();
$response['quota'] = $quota['count'];
$response['quotaMsg'] = $quota_msg;
}
} else {
// Return the error info array.
$response = $units;
}
header( 'Content-Type: application/json' );
echo wp_json_encode( $response );
}
die;
}
/**
* Save account and token after account selection MCN.
*/
public function ajax_account_selected() {
if ( ! Conditional::user_can( 'advanced_ads_manage_options' ) ) {
die;
}
$post_data = wp_unslash( $_POST );
$nonce = $post_data['nonce'] ?? '';
if ( ! wp_verify_nonce( $nonce, 'advads-mapi' ) && ! check_ajax_referer( 'advanced_ads_wizard', 'nonce' ) ) {
wp_send_json_error( 'Not Authorized', 401 );
}
$token_data = wp_unslash( $post_data['token_data'] );
$account = wp_unslash( $post_data['account'] );
if ( $token_data && $account ) {
self::save_token_from_data( $token_data, $account );
wp_send_json_success(
[
'status' => true,
'account' => $account,
],
200
);
}
$error = 'Token data missing';
if ( $token_data ) {
$error = 'No account provided';
}
wp_send_json_success(
[
'status' => false,
'error_msg' => $error,
],
200
);
}
/**
* Get AdSense account details from a new access token.
*/
public function ajax_get_account_details() {
if ( ! Conditional::user_can( 'advanced_ads_manage_options' ) ) {
wp_send_json_error( 'Unauthorized', 401 );
}
$post_data = wp_unslash( $_POST );
$nonce = $post_data['nonce'] ?? '';
if ( ! wp_verify_nonce( $nonce, 'advads-mapi' ) && ! check_ajax_referer( 'advanced_ads_wizard', 'nonce' ) ) {
wp_send_json_error( 'Not Authorized', 401 );
}
$url = 'https://adsense.googleapis.com/v2/accounts';
$list_child_url = 'https://adsense.googleapis.com/v2/accounts/%pubid%:listChildAccounts';
$token_data = wp_unslash( $post_data['token_data'] );
if ( ! is_array( $token_data ) ) {
wp_send_json(
[
'status' => false,
'error_msg' => esc_html__( 'No token provided. Token data needed to get account details.', 'advanced-ads' ),
]
);
}
$headers = [ 'Authorization' => 'Bearer ' . $token_data['access_token'] ];
$response = wp_remote_get( $url, [ 'headers' => $headers ] );
self::log( 'Get account details from new access token' );
if ( is_wp_error( $response ) ) {
wp_send_json(
[
'status' => false,
'error_msg' => $response->get_error_message(),
]
);
}
if ( trim( $response['body'] ) === '{}' ) {
// No AdSense account.
$options = self::get_option();
$options['connect_error'] = [
'message' => esc_html__( 'No AdSense account data found.', 'advanced-ads' ),
'reason' => 'noAdsenseData',
];
update_option( self::OPTION_KEY, $options );
wp_send_json_error( [ 'error' => esc_html__( 'No AdSense account data found.', 'advanced-ads' ) ], 404 );
}
$accounts = json_decode( trim( $response['body'] ), true );
if ( isset( $accounts['accounts'] ) ) {
$pub_id = explode( '/', $accounts['accounts'][0]['name'] )[1];
$child_accounts = wp_remote_get( str_replace( '%pubid%', $pub_id, $list_child_url ), [ 'headers' => $headers ] );
if ( is_wp_error( $child_accounts ) ) {
wp_send_json_error( $child_accounts, 500 );
}
$accounts_list = json_decode( trim( $child_accounts['body'] ), true );
if ( trim( $child_accounts['body'] ) === '{}' ) {
// Standard AdSense account.
self::save_token_from_data( $token_data, $accounts['accounts'][0] );
wp_send_json_success(
[
'reload' => true,
'account' => self::get_account_details( $accounts['accounts'][0] ),
]
);
}
if ( null !== $accounts_list ) {
// Network account.
$details = [];
$html = '';
$details[ $pub_id ] = [
'id' => $pub_id,
'name' => $accounts['accounts'][0]['displayName'],
];
$html .= sprintf( '<option value="%1$s">%2$s [%3$s]</option>', esc_attr( $pub_id ), esc_html( $accounts['accounts'][0]['displayName'] ), esc_html( $pub_id ) );
foreach ( $accounts_list['accounts'] as $item ) {
$account_id = explode( '/', $item['name'] )[1];
$details[ $account_id ] = [
'id' => $account_id,
'name' => $item['displayName'],
];
$html .= sprintf( '<option value="%1$s">%2$s [%3$s]</option>', esc_attr( $account_id ), esc_html( $item['displayName'] ), esc_html( $account_id ) );
}
wp_send_json_success(
[
'details' => $details,
'html' => $html,
'token_data' => $token_data,
]
);
}
wp_send_json_error( [ 'message' => 'unexpected response - get child accounts' ], 400 );
}
}
/**
* Submit Google API confirmation code. Save the token and update ad client list.
*/
public function ajax_confirm_code() {
if ( ! Conditional::user_can( 'advanced_ads_manage_options' ) ) {
die;
}
$nonce = wp_unslash( Params::post( 'nonce' ) ) ?? '';
if ( ! wp_verify_nonce( $nonce, 'advads-mapi' ) && ! check_ajax_referer( 'advanced_ads_wizard', 'nonce' ) ) {
wp_send_json_error( 'Not Authorized', 401 );
}
$code = urldecode( wp_unslash( Params::post( 'code' ) ) );
$cid = self::CID;
$cs = self::CS;
$use_user_app = self::use_user_app();
if ( $use_user_app ) {
$cid = ADVANCED_ADS_MAPI_CID;
$cs = ADVANCED_ADS_MAPI_CIS;
}
$code_url = 'https://www.googleapis.com/oauth2/v4/token';
$redirect_uri = self::REDIRECT_URI;
$grant_type = 'authorization_code';
$args = [
'timeout' => 10,
'body' => [
'code' => $code,
'client_id' => $cid,
'client_secret' => $cs,
'redirect_uri' => $redirect_uri,
'grant_type' => $grant_type,
],
];
$response = wp_remote_post( $code_url, $args );
self::log( 'Confirm authorization code' );
if ( is_wp_error( $response ) ) {
wp_send_json_error(
[
'status' => false,
'msg' => 'error while submitting code',
'raw' => $response->get_error_message(),
],
$response->get_error_code()
);
}
$token = json_decode( $response['body'], true );
if ( null !== $token && isset( $token['refresh_token'] ) ) {
$expires = time() + absint( $token['expires_in'] );
$token['expires'] = $expires;
wp_send_json_success(
[
'status' => true,
'token_data' => $token,
],
200
);
}
wp_send_json_error(
[
'status' => false,
'response_body' => $response['body'],
],
400
);
}
/**
* Enqueue admin scripts
*
* @param string $hook current page hook.
*/
public function admin_scripts( $hook ) {
if ( 'advanced-ads_page_advanced-ads-settings' === $hook ) {
wp_enqueue_script( 'gasense/mapi/settings', GADSENSE_BASE_URL . 'admin/assets/js/mapi-settings.js', [ 'jquery', 'wp-util' ], ADVADS_VERSION );
}
}
/**
* Print alert data in admin footer
*/
public function admin_footer() {
$data = Advanced_Ads_AdSense_Data::get_instance();
$adsense_id = $data->get_adsense_id();
$has_token = self::has_token( $adsense_id );
$alerts = self::get_stored_account_alerts( $adsense_id );
$refresh_alerts = false;
// default value, never checked for alerts.
if ( [] === $alerts && $has_token ) {
$refresh_alerts = true;
}
if ( $has_token && is_array( $alerts ) ) {
// Check weekly for alerts.
if ( isset( $alerts['lastCheck'] ) && time() > absint( $alerts['lastCheck'] ) + DAY_IN_SECONDS * 7 ) {
$refresh_alerts = true;
}
// Only try to get the alerts in the background once a day.
if ( isset( $alerts['inlineAttempt'] ) && time() < $alerts['inlineAttempt'] + DAY_IN_SECONDS ) {
$refresh_alerts = false;
}
}
if ( $refresh_alerts ) {
$nonce = wp_create_nonce( 'mapi-alerts' );
?>
<input type="hidden" id="advads-mapi-refresh-alerts" />
<script type="text/javascript">
;(function($) {
$( '#mapi-alerts-overlay' ).css( 'display', 'block' );
var pubId = $( '#adsense-id' ).val();
$.ajax({
url: ajaxurl,
type: 'post',
data: {
action: 'advads-mapi-get-alerts',
account: '<?php echo esc_html( $adsense_id ); ?>',
nonce: '<?php echo esc_html( $nonce ); ?>',
inlineAttempt: 1,
},
success:function(response, status, XHR) {
if ( 'undefined' != typeof response.alerts ) {
$( '#advads-mapi-refresh-alerts' ).trigger( 'advadsMapiRefreshAlerts', [response] );
}
$( '#mapi-alerts-overlay' ).css( 'display', 'none' );
},
error:function(request, status, error) {
$( '#mapi-alerts-overlay' ).css( 'display', 'none' );
},
});
})(window.jQuery);
</script>
<?php
}
}
/**
* Logs a task to a file if ADVANCED_ADS_LOG_ADSENSE_API constant is defined and true.
*
* @param string $task The task to be logged. Default is 'No task provided'.
*
* @return void
*/
public static function log( $task = 'No task provided' ): void {
if ( ! defined( 'ADVANCED_ADS_LOG_ADSENSE_API' ) || ! ADVANCED_ADS_LOG_ADSENSE_API ) {
return;
}
$message = date_i18n( '[Y-m-d H:i:s]' ) . ' ' . $task . "\n";
error_log( $message, 3, WP_CONTENT_DIR . '/advanced-ads-google-api-requests.log' );
}
/**
* Sort ad units list alphabetically
*
* @param array $adunits The array of ad units to be sorted.
*
* @return array The sorted array of ad units.
*/
public static function get_sorted_adunits( $adunits ): array {
$units_sorted_by_name = [];
$units_by_id = [];
foreach ( $adunits as $unit ) {
$units_sorted_by_name[ $unit['name'] ] = $unit['id'];
$units_by_id[ $unit['id'] ] = $unit;
}
ksort( $units_sorted_by_name );
$units_sorted_by_name = array_flip( $units_sorted_by_name );
$results = [];
foreach ( $units_sorted_by_name as $id => $name ) {
$results[ $name ] = $units_by_id[ $id ];
}
return $results;
}
/**
* Format ad type and size strings from Google for display
*
* @param Advanced_Ads_Ad_Network_Ad_Unit $ad_unit the ad unit for which to format the details.
* @param string $format takes either type or size.
*
* @return string
*/
public static function format_ad_data( Advanced_Ads_Ad_Network_Ad_Unit $ad_unit, $format = 'type' ) {
if ( 'type' === $format ) {
$str = $ad_unit->display_type;
$options = self::get_option();
if ( array_key_exists( $ad_unit->id, $options['ad_codes'] ) ) {
preg_match_all( '/data-ad-format="(?<format>.+?)"|data-ad-layout="(?<layout>.+?)"/', $options['ad_codes'][ $ad_unit->id ], $matches );
$format = array_filter( $matches['format'] );
$layout = array_filter( $matches['layout'] );
$format = reset( $format );
$layout = reset( $layout );
if ( empty( $format ) ) {
$format = '';
}
if ( empty( $layout ) ) {
$layout = '';
}
if ( 'autorelaxed' === $format ) {
$str = _x( 'Multiplex', 'AdSense ad type', 'advanced-ads' );
} elseif ( 'fluid' === $format ) {
if ( 'in-article' === $layout ) {
$str = _x( 'In-article', 'AdSense ad type', 'advanced-ads' );
} else {
$str = _x( 'In-feed', 'AdSense ad type', 'advanced-ads' );
}
}
}
switch ( $str ) {
case 'DISPLAY':
$str = _x( 'Display', 'AdSense ad type', 'advanced-ads' );
break;
case 'LINK':
$str = _x( 'Link', 'AdSense ad type', 'advanced-ads' );
break;
case 'MATCHED_CONTENT':
$str = _x( 'Multiplex', 'AdSense ad type', 'advanced-ads' );
break;
case 'ARTICLE':
$str = _x( 'In-article', 'AdSense ad type', 'advanced-ads' );
break;
case 'FEED':
$str = _x( 'In-feed', 'AdSense ad type', 'advanced-ads' );
break;
case 'TYPE_UNSPECIFIED':
default:
}
} elseif ( 'size' === $format ) {
// size.
$str = '1x3' === $ad_unit->display_size
? 'Responsive' : $ad_unit->display_size;
if ( strpos( $str, 'SIZE_' ) === 0 ) {
$str = str_replace( '_', 'x', substr( $str, 5 ) );
}
$str = ucfirst( strtolower( $str ) );
} else {
$str = '';
}
return $str;
}
/**
* Check if the credential are the default ones or from user's app
*/
public static function use_user_app() {
if (
( defined( 'ADVANCED_ADS_MAPI_CID' ) && '' !== ADVANCED_ADS_MAPI_CID ) &&
( defined( 'ADVANCED_ADS_MAPI_CIS' ) && '' !== ADVANCED_ADS_MAPI_CIS )
) {
return true;
}
return false;
}
/**
* Checks if a Google AdSense token exists for the specified AdSense ID.
*
* @param string $adsense_id The AdSense ID to check for.
*
* @return bool Returns true if a token exists, false otherwise.
*/
public static function has_token( $adsense_id = '' ): bool {
if ( empty( $adsense_id ) ) {
return false;
}
$options = self::get_option();
$look_for = self::use_user_app() ? 'user_app' : 'default_app';
if (
isset( $options['accounts'][ $adsense_id ] ) &&
! empty( $options['accounts'][ $adsense_id ][ $look_for ]['refresh_token'] )
) {
return true;
}
return false;
}
/**
* Save token obtained from confirmation code
*
* @param string $token access token data.
* @param array $details selected account details.
*/
public static function save_token_from_data( $token, $details ) {
$options = self::get_option();
$adsense_id = isset( $details['id'] ) ? $details['id'] : explode( '/', $details['name'] )[1];
if ( ! isset( $options['accounts'][ $adsense_id ] ) ) {
$options['accounts'][ $adsense_id ] = self::$empty_account_data;
}
if ( self::use_user_app() ) {
$options['accounts'][ $adsense_id ]['user_app'] = [
'access_token' => $token['access_token'],
'refresh_token' => $token['refresh_token'],
'expires' => $token['expires'],
'token_type' => $token['token_type'],
];
} else {
$options['accounts'][ $adsense_id ]['default_app'] = [
'access_token' => $token['access_token'],
'refresh_token' => $token['refresh_token'],
'expires' => $token['expires'],
'token_type' => $token['token_type'],
];
}
$options['accounts'][ $adsense_id ]['details'] = [
'id' => $adsense_id,
'name' => isset( $details['displayName'] ) ? $details['displayName'] : $details['name'],
];
$options['connect_error'] = [];
update_option( self::OPTION_KEY, $options );
$gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
$gadsense_options = $gadsense_data->get_options();
$gadsense_options['adsense-id'] = $adsense_id;
update_option( GADSENSE_OPT_NAME, $gadsense_options );
}
/**
* Get a list of stored alerts for a given AdSense account.
*
* @param string $pub_id the publisher account.
* @return array $alerts
*/
public static function get_stored_account_alerts( $pub_id = '' ) {
if ( empty( $pub_id ) ) {
return false;
}
$options = self::get_option();
if ( isset( $options['accounts'][ $pub_id ] ) ) {
$account = [];
if ( isset( $options['accounts'][ $pub_id ]['alerts'] ) && is_array( $options['accounts'][ $pub_id ]['alerts'] ) ) {
$alerts = $options['accounts'][ $pub_id ]['alerts'];
$account = self::filter_stored_account_alerts( $alerts );
}
return $account;
}
return false;
}
/**
* We filter out specific alerts from the AdSense account when they are
* - duplicates
* - irrelevant when placing ads in the frontend
*
* @param array $alert_items alerts.
* @param null|array $disabled_alerts additional disabled alerts.
* @return array filtered alert items.
*/
public static function filter_account_alerts( array $alert_items, $disabled_alerts = null ) {
if ( empty( $alert_items ) || ! is_array( $alert_items ) ) {
return $alert_items;
}
// the message IDs we dont even import from AdSense.
$disabled_adsense_alerts = [
'SELLERS_JSON_CONSENT', // AdSense message: We encourage you to publish your seller information in the Google sellers.json file. Visit the account settings page to review your current visibility status.
'REPORTING_HORIZON_LEGACY_DATA_NOTICE', // AdSense message: Data older than three years is no longer available in Reporting. This data can be downloaded for a limited time.
];
// additional messages to disable. Useful if the function is used in different situations.
if ( ! empty( $disabled_alerts ) && is_array( $disabled_alerts ) ) {
$disabled_adsense_alerts = array_merge( $disabled_adsense_alerts, $disabled_alerts );
}
// remove alerts based on specific IDs.
foreach ( $alert_items as $internal_id => $item ) {
if (
( isset( $item['id'] ) && in_array( $item['id'], $disabled_adsense_alerts, true ) )
|| ( isset( $item['type'] ) && in_array( str_replace( '-', '_', strtoupper( $item['type'] ) ), $disabled_adsense_alerts, true ) )
) {
unset( $alert_items[ $internal_id ] );
}
}
return $alert_items;
}
/**
* Remove alerts dynamically when showing them.
* only applies to stored alerts and not when they are loaded directly from AdSense
*
* @param array $alerts Alert options.
* @return array $alerts Modified alert options.
*/
public static function filter_stored_account_alerts( array $alerts ) {
if ( empty( $alerts['items'] ) || ! is_array( $alerts['items'] ) ) {
return $alerts;
}
$disabled_alerts = [];
/**
* Asside from the basic filter, we also filter out some messages only from showing up while we still import them
* This allows us to show them only under related conditions
*/
// Remove `ads.txt` related alerts if the file is displayed to visitors.
if ( Advanced_Ads_Ads_Txt_Admin::is_displayed() ) {
$disabled_alerts = [ 'ALERT_TYPE_ADS_TXT_UNAUTHORIZED', 'ADS_TXT_MISSING', 'ADS_TXT_ISSUES' ];
}
$alerts['items'] = self::filter_account_alerts( $alerts['items'], $disabled_alerts );
return $alerts;
}
/**
* Checks if there is any AdSense warning for the currently connected AdSense account.
*
* @param array $messages The array of messages.
*
* @return array The modified array.
*/
public static function adsense_warnings_check( $messages ) {
$data = Advanced_Ads_AdSense_Data::get_instance();
$adsense_id = $data->get_adsense_id();
$alerts = self::get_stored_account_alerts( $adsense_id );
if ( ! is_array( $messages ) ) {
$messages = [];
}
if ( ! empty( $alerts ) && ! empty( $alerts['items'] ) ) {
$messages[] = sprintf(
wp_kses(
/* translators: %s admin setting page link */
__( 'There are one or more warnings about the currently linked AdSense account. You can view them <a href="%s">here</a>', 'advanced-ads' ),
[ 'a' => [ 'href' => true ] ]
),
esc_url( admin_url( 'admin.php?page=advanced-ads-settings#top#adsense' ) )
);
}
return $messages;
}
/**
* Get the class's option
*/
public static function get_option() {
$options = get_option( self::OPTION_KEY, [] );
if ( ! is_array( $options ) ) {
$options = [];
}
return $options + self::$default_options;
}
/**
* Get the URL to the AdSense error page
*
* @param string $code Add the error code to the URL.
*
* @return string The entire text with the url.
*/
public static function get_adsense_error_link( $code = '' ) {
if ( ! empty( $code ) ) {
$code = '-' . $code;
}
return sprintf(
/* translators: %1$s is an anchor (link) opening tag, %2$s is the closing tag. */
esc_attr__( 'Learn more about AdSense account issues %1$shere%2$s.', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/adsense-errors/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adsense-error' . $code . '" target="_blank">',
'</a>'
);
}
/**
* Get custom account connection error message list.
*/
public static function get_connect_error_messages() {
$messages = [];
$health_class = Advanced_Ads_Ad_Health_Notices::get_instance();
foreach ( $health_class->default_notices as $key => $value ) {
if ( 0 === strpos( $key, 'adsense_connect_' ) ) {
$messages[ substr( $key, strlen( 'adsense_connect_' ) ) ] = $value['text'];
}
}
return $messages;
}
/**
* Get custom messages for AdSense alerts.
*/
public static function get_adsense_alert_messages() {
$messages = [];
$health_class = Advanced_Ads_Ad_Health_Notices::get_instance();
foreach ( $health_class->default_notices as $key => $value ) {
if ( 0 === strpos( $key, 'adsense_alert_' ) ) {
$messages[ substr( $key, strlen( 'adsense_alert_' ) ) ] = $value['text'];
}
}
return $messages;
}
/**
* Get class instance
*
* @return Advanced_Ads_AdSense_MAPI
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Extract basic account info from the data sent by Google
*
* @param array $account account data from Google.
*
* @return array
*/
private static function get_account_details( $account ) {
return [
'id' => str_replace( 'accounts/', '', $account['name'] ),
'name' => $account['displayName'],
];
}
/**
* Get a hint for an error object that was received from AdSense
*
* @param string $reason The reason from the response's error.
*
* @return string|bool if there is a hint for this reason, a string containing the hint will be returned.
*/
final public static function get_adsense_error_hint( $reason ) {
if ( 'authError' === $reason ) {
return sprintf(
/* translators: 1: A link to the settings page 2: The name of an ad network */
__( 'Please try to <a href="%1$s" target="_blank">reconnect to your %2$s account</a>.', 'advanced-ads' ),
admin_url( 'admin.php?page=advanced-ads-settings#top#adsense' ),
'AdSense'
);
}
return false;
}
}