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>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,191 @@
<?php
/**
* The class is responsible for adding widget in the WordPress admin area.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick\Admin;
use AdvancedAds\Utilities\WordPress;
use AdvancedAds\Modules\OneClick\Helpers;
use AdvancedAds\Modules\OneClick\Options;
use AdvancedAds\Framework\Interfaces\Integration_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Admin.
*/
class Admin implements Integration_Interface {
/**
* Hook into WordPress
*
* @return void
*/
public function hooks(): void {
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
add_action( 'advanced-ads-overview-widgets-after', [ $this, 'add_metabox' ] );
}
/**
* Enqueue scripts
*
* @param string $hook current page hook.
*
* @return void
*/
public function enqueue( $hook ): void {
if ( 'toplevel_page_advanced-ads' !== $hook ) {
return;
}
$config = Options::pubguru_config();
wp_advads()->registry->enqueue_script( 'oneclick-onboarding' );
wp_advads()->json->add(
'oneclick',
[
'security' => wp_create_nonce( 'pubguru_oneclick_security' ),
'isConnected' => false !== Options::pubguru_config(),
'btnCancel' => __( 'Cancel', 'advanced-ads' ),
'btnClose' => __( 'Close', 'advanced-ads' ),
'btnContinue' => __( 'Continue', 'advanced-ads' ),
'btnRetry' => __( 'Retry', 'advanced-ads' ),
'siteDomain' => WordPress::get_site_domain(),
'spinner' => ADVADS_BASE_URL . 'admin/assets/img/loader.gif',
'addonRow' => [
'icon' => ADVADS_BASE_URL . 'assets/img/add-ons/aa-addons-icons-m2pg.svg',
'title' => __( 'MonetizeMore & PubGuru Integration', 'advanced-ads' ),
'content' => __( 'Enables MonetizeMore users to link their settings with the PubGuru insights & analytics dashboard.', 'advanced-ads' ),
'connect' => __( 'Connect now', 'advanced-ads' ),
'disconnect' => __( 'Disconnect now', 'advanced-ads' ),
],
'metabox' => [
'title' => __( 'MonetizeMore & PubGuru Integration', 'advanced-ads' ),
'visitText' => __( 'Visit the MonetizeMore website to learn about PubGuru', 'advanced-ads' ),
'visitLink' => 'https://www.monetizemore.com/solutions/pubguru',
],
'step1' => [
'title' => __( 'Onboarding Step 1 of 3, Consent and Privacy Policy', 'advanced-ads' ),
'content' => sprintf(
wp_kses_post(
/* translators: %s link to privacy policy */
__( 'This form is designed exclusively for MonetizeMore customers who wish to integrate Advanced Ads with their PubGuru Dashboard. In alignment with our <a href="%s">Privacy Policy</a>, no information other than your domain name is exchanged, and Advanced Ads does not engage in any tracking activities.', 'advanced-ads' )
),
'https://wpadvancedads.com/privacy-policy/'
),
'agreeText' => __( 'I agree to share my domain name to facilitate the connection with my PubGuru account.', 'advanced-ads' ),
'btnAgree' => __( 'Connect with PubGuru', 'advanced-ads' ),
],
'step2' => [
'title' => __( 'Onboarding Step 2 of 3, Connecting to PubGuru', 'advanced-ads' ),
'loading' => __( 'Fetching your domain information from PubGuru, please wait...', 'advanced-ads' ),
'notRegistered' => __( 'The domain &ldquo;{0}&rdquo; is not registered with PubGuru', 'advanced-ads' ),
'content' => sprintf(
/* translators: %1$s is contact link, %2$s is email link */
__( 'If you are on a domain &ldquo;unknow&rdquo; to PubGuru, e.g., a staging site, please indicate the domain that you registered with PubGuru. If you need assistance, please <a href="%1$s">click here to contact PubGuru support</a> or <a href="%2$s">send an email to support@monetizemore.com</a>.', 'advanced-ads' ),
'https://www.monetizemore.com/contact/',
'mailto:support@monetizemore.com'
),
'inputLabel' => __( 'Registered domain', 'advanced-ads' ),
'serverError' => __( 'The onboarding process has encountered an error: &ldquo;{0}&rdquo;', 'advanced-ads' ),
'serverContent' => sprintf(
/* translators: %1$s is contact link, %2$s is email link */
__( 'Please wait a few minutes and try again. If you need assistance, please <a href="%1$s">click here to contact PubGuru support</a> or <a href="%2$s">send an email to support@monetizemore.com</a>.', 'advanced-ads' ),
'https://www.monetizemore.com/contact/',
'mailto:support@monetizemore.com'
),
],
'step3' => [
'title' => __( 'Onboarding Step 3 of 3, Test and Finalize Ad Unit Import', 'advanced-ads' ),
'yourDomain' => __( 'Your domain &ldquo;{0}&rdquo; is connected to PubGuru.', 'advanced-ads' ),
'btnImport' => __( 'Import PubGuru Ad Units', 'advanced-ads' ),
'importContent' => wp_kses_post(
join(
'',
[
'<p>' . __( 'This step is entirely optional. Your PubGuru configuration shows the following available ad units', 'advanced-ads' ) . '</p>',
'<ul class="list-disc ml-4">',
'<li>' . __( '3 In-Content Ads', 'advanced-ads' ) . '</li>',
'<li>' . __( '1 Leaderboard Ad', 'advanced-ads' ) . '</li>',
'</ul>',
'<p>' . __( 'You will be able to preview the ad units injections on a test page before and there is a rollback option after the import.', 'advanced-ads' ) . '</p>',
]
)
),
'previewContent' => __( 'You may preview or change the test page for the ad units&rsquo; injections, or finalize the PubGuru Ad Unit import.', 'advanced-ads' ),
'finalContent' => sprintf(
/* translators: %s rollback page link */
__( 'You have successfully imported your PubGuru Ad Units. If necessary, use the <a href="%s">Rollback Tool</a> to revert your ad setup to a previous state.', 'advanced-ads' ),
esc_url( admin_url( 'admin.php?page=advanced-ads-tools#import-history' ) )
),
],
'settings' => [
'title' => __( 'General Settings', 'advanced-ads' ),
'help' => sprintf(
/* translators: %1$s is contact link, %2$s is email link */
__( 'If you need assistance, please <a href="%1$s">click here to contact PubGuru support</a> or <a href="%2$s">send an email to support@monetizemore.com</a>.', 'advanced-ads' ),
'https://www.monetizemore.com/contact/',
'mailto:support@monetizemore.com'
),
'headerBidding' => __( 'Activate PubGuru Header Bidding', 'advanced-ads' ),
'activateTags' => __( 'Activate Tag Conversion', 'advanced-ads' ),
'trafficCop' => __( 'Activate Traffic Cop Invalid Traffic Protection', 'advanced-ads' ),
'trafficCopTrial' => __( '7 Days Trial', 'advanced-ads' ),
'adsTxt' => sprintf(
/* translators: %s is link to PubGuru */
__( 'Redirect ads.txt calls to the <a href="%s" target="_blank" rel="noreferrer">PubGuru platform</a>', 'advanced-ads' ),
'https://app.pubguru.com/ads-txt'
),
'scriptLocation' => __( 'Move the PubGuru Header Bidding script to the footer. <span class="muted">Keep this option disabled to maximize revenue. Only enable it if PageSpeed is your priority.</span>', 'advanced-ads' ),
'onlyPreview' => __( '(Only enabled on Preview Page)', 'advanced-ads' ),
],
'options' => [
'headerBidding' => Options::module( 'header_bidding' ),
'headerBiddingAtBody' => Options::module( 'header_bidding_at_body' ),
'adsTxt' => Options::module( 'ads_txt' ),
'trafficCop' => Options::module( 'traffic_cop' ),
'tagConversion' => Options::module( 'tag_conversion' ),
'connectedDomain' => $config['domain'] ?? '',
'selectedMethod' => $config['method'] ?? 'page',
'selectedPage' => $config['page'] ?? 0,
'selectedPageTitle' => isset( $config['page'] ) ? get_the_title( $config['page'] ) : '',
'hasTrafficCop' => Helpers::has_traffic_cop( $config ),
],
'modal' => [
'title' => __( 'Import PubGuru Ad Units', 'advanced-ads' ),
'btnSave' => __( 'Close and update preview', 'advanced-ads' ),
'btnFinal' => __( 'Finalize ad unit import', 'advanced-ads' ),
'btnUpdate' => __( 'Update preview', 'advanced-ads' ),
'btnGoto' => __( 'Go to the preview', 'advanced-ads' ),
'labelImport' => __( 'Import method', 'advanced-ads' ),
'labelSpecificPage' => __( 'Preview ad units on specific page', 'advanced-ads' ),
'labelFinalImport' => __( 'Finalize ad units import', 'advanced-ads' ),
'descFinalImport' => join(
'',
[
'<ul class="list-disc ml-2">',
'<li>' . __( 'Your existing ads and placements will be set to &lsquo;Draft&rsquo; mode', 'advanced-ads' ) . '</li>',
'<li>' . __( 'Your PubGuru ad units will be imported as suitable ads and placements, and published right away', 'advanced-ads' ) . '</li>',
'</ul>',
'<p>' . __( 'You can manually republish specific ads and placements or fully rollback at any time.', 'advanced-ads' ) . '</p>',
]
),
],
]
);
}
/**
* Add metabox
*
* @return void
*/
public function add_metabox(): void {
echo '<div id="advads-oneclick-app"></div>';
}
}

View File

@@ -0,0 +1,261 @@
<?php
/**
* The class is responsible for ajax functionality.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick\Admin;
use WP_Error;
use AdvancedAds\Utilities\WordPress;
use AdvancedAds\Modules\OneClick\Helpers;
use AdvancedAds\Modules\OneClick\Options;
use AdvancedAds\Framework\Utilities\Params;
use AdvancedAds\Modules\OneClick\AdsTxt\Detector;
use AdvancedAds\Framework\Interfaces\Integration_Interface;
use AdvancedAds\Importers\Api_Ads;
defined( 'ABSPATH' ) || exit;
/**
* Ajax.
*/
class Ajax implements Integration_Interface {
/**
* API URL
*
* Production: https://app.pubguru.com
* Development: https://new-stagingtools5.pubguru.com
*
* @var string
*/
const API_URL = 'https://app.pubguru.com/';
/**
* Hook into WordPress
*
* @return void
*/
public function hooks(): void {
add_action( 'init', [ $this, 'init' ] );
add_action( 'wp_ajax_search_posts', [ $this, 'search_posts' ] );
add_action( 'wp_ajax_pubguru_connect', [ $this, 'pubguru_connect' ] );
add_action( 'wp_ajax_pubguru_disconnect', [ $this, 'pubguru_disconnect' ] );
add_action( 'wp_ajax_pubguru_module_change', [ $this, 'module_status_changed' ] );
add_action( 'wp_ajax_pubguru_backup_ads_txt', [ $this, 'backup_ads_txt' ] );
add_action( 'wp_ajax_update_oneclick_preview', [ $this, 'update_oneclick_preview' ] );
}
/**
* Init hook
*
* @return void
*/
public function init(): void {
if ( Params::get( 'refresh_ads', false, FILTER_VALIDATE_BOOLEAN ) ) {
$config = $this->pubguru_api_connect();
if ( is_wp_error( $config ) ) {
wp_die(
$config->get_error_message(), // phpcs:ignore
esc_html__( 'Refreshing PubGuru Ads', 'advanced-ads' ),
$config->get_error_data() // phpcs:ignore
);
}
}
}
/**
* PubGuru Connect
*
* @return void
*/
public function pubguru_connect(): void {
check_ajax_referer( 'pubguru_oneclick_security', 'nonce' );
$config = $this->pubguru_api_connect();
if ( is_wp_error( $config ) ) {
wp_send_json(
[
'success' => false,
'code' => $config->get_error_code(),
'message' => $config->get_error_message(),
],
$config->get_error_data()
);
}
// Default module enabled.
Options::module( 'header_bidding', true );
wp_send_json_success(
[
'message' => esc_html__( 'We have successfully migrated your MonetizeMore PubGuru Ad Units to your WordPress site. The existing placements and ads have been paused.', 'advanced-ads' ),
'hasTrafficCop' => Helpers::has_traffic_cop( $config ),
]
);
}
/**
* PubGuru Disconnect
*
* @return void
*/
public function pubguru_disconnect(): void {
check_ajax_referer( 'pubguru_oneclick_security', 'nonce' );
Options::pubguru_config( 'delete' );
wp_send_json_success(
[
'message' => esc_html__( 'PubGuru successfully disconnected.', 'advanced-ads' ),
]
);
}
/**
* Handle module status changes
*
* @return void
*/
public function module_status_changed(): void {
check_ajax_referer( 'pubguru_oneclick_security', 'security' );
$module = Params::post( 'module', [] );
$status = Params::post( 'status', false, FILTER_VALIDATE_BOOLEAN );
Options::module( $module, $status );
$data = apply_filters( 'pubguru_module_status_changed', [], $module, $status );
wp_send_json_success( $data );
}
/**
* Handle module status changes
*
* @return void
*/
public function backup_ads_txt(): void {
check_ajax_referer( 'pubguru_oneclick_security', 'security' );
$result = ( new Detector() )->backup_file();
if ( false === $result ) {
$notice = sprintf(
'<div class="flex items-center">'
/* translators: 1 is the opening link to the Advanced Ads website, 2 the closing link */
. __( 'The backup of your ads.txt file has failed. Please ensure that a manual backup is created You can find detailed instructions on how to manually back up your ads.txt file in the manual. %1$sManual%2$s', 'advanced-ads' ) // phpcs:ignore
. '</div>',
'<a href="https://wpadvancedads.com/manual/ads-txt/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-ads-txt-oci#Manual_backup_of_the_adstxt_file" target="_blank" class="button button-link ml-auto mr-2">',
'</a>'
);
wp_send_json_error( $notice );
}
$notice = sprintf(
'<div class="flex items-center">%s</div>',
esc_html__( 'File successfully backed up.', 'advanced-ads' )
);
wp_send_json_success( $notice );
}
/**
* Search posts
*
* @return void
*/
public function search_posts(): void {
global $wpdb;
check_ajax_referer( 'pubguru_oneclick_security', 'security' );
$search = Params::get( 'q', '' );
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT ID, post_title FROM {$wpdb->posts}
WHERE post_title LIKE %s
AND post_status = 'publish'
AND post_type IN ('post', 'page')",
'%' . $wpdb->esc_like( $search ) . '%'
)
);
$posts = [];
foreach ( $results as $result ) {
$posts[] = [
'id' => $result->ID,
'text' => $result->post_title,
];
}
wp_send_json( $posts );
}
/**
* Update OneClick preview
*
* @return void
*/
public function update_oneclick_preview(): void {
check_ajax_referer( 'pubguru_oneclick_security', 'security' );
$method = Params::post( 'method', 'page' );
$page = Params::post( 'page', 0, FILTER_VALIDATE_INT );
$config = Options::pubguru_config();
$config['method'] = $method;
$config['page'] = $page;
Options::pubguru_config( $config );
// Importer.
$importer = new Api_Ads();
$importer->import();
wp_send_json_success();
}
/**
* Fetch config from PubGuru api
*
* @return WP_Error|array
*/
private function pubguru_api_connect() {
$domain = Params::post( 'testDomain' ) ? Params::post( 'testDomain' ) : WordPress::get_site_domain();
$domain = str_replace( 'www.', '', $domain );
$response = wp_remote_get(
self::API_URL . 'domain_configs/?domain=' . $domain,
[
'timeout' => 30,
'sslverify' => false,
]
);
$response_code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $response_code ) {
return new WP_Error(
'connect_error',
esc_html__( 'An error has occurred please try again.', 'advanced-ads' ),
$response_code
);
}
$config = json_decode( wp_remote_retrieve_body( $response ), true );
if ( 'error' === $config['status'] ) {
return new WP_Error(
'domain_not_found',
'Connection with PubGuru & MonetizeMore was unsuccessful. Please <a href="https://www.monetizemore.com/contact/">click here</a> to contact MonetizeMore Support or email us at <a href="mailto:support@monetizemore.com">support@monetizemore.com</a>',
201
);
}
$config['domain'] = $domain;
Options::pubguru_config( $config );
return $config;
}
}

View File

@@ -0,0 +1,4 @@
<?php
/**
* Silence is golden.
*/

View File

@@ -0,0 +1,220 @@
<?php
/**
* Helpers.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick;
use AdvancedAds\Utilities\WordPress;
use AdvancedAds\Framework\Utilities\Str;
defined( 'ABSPATH' ) || exit;
/**
* Helpers.
*/
class Helpers {
/**
* Check if config has traffic cop subscription
*
* @param array $config Config instance.
*
* @return bool
*/
public static function has_traffic_cop( $config = null ): bool {
if ( null === $config ) {
$config = Options::pubguru_config();
}
if (
isset( $config['params'] ) &&
( isset( $config['params']['trafficCopIvtAction'] ) && 'block' === $config['params']['trafficCopIvtAction'] ) &&
( isset( $config['params']['trafficCopTestPercent'] ) && $config['params']['trafficCopTestPercent'] > 0.01 )
) {
return true;
}
return false;
}
/**
* Get config file
*
* Cases
* 1. For auto_created
* 2. For mobile prefix
* 3. For desktop prefix
* 4. If none of the prefix is found than go with the first one
* 5. No configuration found => pg.{domain}.js
*
* @return bool|string
*/
public static function get_config_file() {
static $pubguru_config_name;
if ( null !== $pubguru_config_name ) {
return $pubguru_config_name;
}
$pubguru_config_name = false;
$configs = Options::pubguru_config();
// 1. For auto_created => pg.{domain}_auto_created.js
foreach ( $configs['configs'] as $config ) {
if ( isset( $config['auto_created'] ) && $config['auto_created'] ) {
$pubguru_config_name = $config['name'];
return $pubguru_config_name;
}
}
// 5. No configuration found => pg.{domain}.js
if ( ! isset( $configs['configs'] ) || empty( $configs['configs'] ) ) {
$domain = WordPress::get_site_domain( 'name' );
return "pg.{$domain}.js";
}
$pubguru_config_name = wp_is_mobile()
// 2. For mobile prefix
? self::config_contains( 'mobile' )
// 3. For desktop prefix
: self::config_contains( 'desktop' );
$pubguru_config_name = false !== $pubguru_config_name
? $pubguru_config_name
// 4. If none of the prefix is found than go with the first one
: $configs['configs'][0]['name'];
return $pubguru_config_name;
}
/**
* Find config name by needle
*
* @param string $needle Needle to look into config name.
*
* @return bool|string
*/
private static function config_contains( $needle ) {
$configs = Options::pubguru_config();
foreach ( $configs['configs'] as $config ) {
if ( Str::contains( $needle, $config['name'] ) ) {
return $config['name'];
}
}
return false;
}
/**
* Get ads from saved config.
*
* In this order
* 1. Get ads from auto_created = true
* 2. Get ads from first config
* 3. Get ads from default config
*
* @return bool|array
*/
public static function get_ads_from_config() {
static $pubguru_config_ads;
$config = Options::pubguru_config();
if ( null !== $pubguru_config_ads ) {
return $pubguru_config_ads;
}
$pubguru_config_ads = false;
// 1. Get ads from auto_created = true or name contains auto_created
foreach ( $config['configs'] as $config ) {
if (
( isset( $config['auto_created'] ) && $config['auto_created'] ) ||
Str::contains( 'auto_created', $config['name'] )
) {
$pubguru_config_ads = $config['ad_units'];
return $pubguru_config_ads;
}
}
// 2. Get ads from first config
if ( isset( $config['configs'][0]['ad_units'] ) && ! empty( $config['configs'][0]['ad_units'] ) ) {
$pubguru_config_ads = $config['configs'][0]['ad_units'];
} else {
// 3. Get ads from default config
$domain = WordPress::get_site_domain();
$pubguru_config_ads = [
$domain . '_leaderboard' => [
'ad_unit' => $domain . '_leaderboard',
'slot' => $domain . '_leaderboard',
'device' => 'all',
'advanced_placement' => [
'placement' => 'beforeContent',
'inContentRule' => [
'position' => 'before',
'positionCount' => 1,
'positionElement' => 'paragraph',
'positionRepeat' => false,
],
],
],
$domain . '_in_content_1' => [
'ad_unit' => $domain . '_in_content_1',
'slot' => $domain . '_in_content_1',
'device' => 'all',
'advanced_placement' => [
'placement' => 'beforeContent',
'inContentRule' => [
'position' => 'before',
'positionCount' => 1,
'positionElement' => 'paragraph',
'positionRepeat' => false,
],
],
],
$domain . '_in_content_2' => [
'ad_unit' => $domain . '_in_content_2',
'slot' => $domain . '_in_content_2',
'device' => 'all',
'advanced_placement' => [
'placement' => 'inContent',
'inContentRule' => [
'position' => 'after',
'positionCount' => 3,
'positionElement' => 'paragraph',
'positionRepeat' => true,
],
],
],
];
}
return $pubguru_config_ads;
}
/**
* Is ad disabled on page
*
* @param int $post_id Post id to check for.
*
* @return bool
*/
public static function is_ad_disabled( $post_id = 0 ): bool {
global $post;
if ( ! $post ) {
return false;
}
if ( ! $post_id ) {
$post_id = $post->ID;
}
$settings = get_post_meta( $post_id, '_advads_ad_settings', true );
return is_singular() ? ! empty( $settings['disable_ads'] ) : false;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* Options.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick;
defined( 'ABSPATH' ) || exit;
/**
* Options.
*/
class Options {
const CONFIG_KEY = '_advads_pubguru_connect_config';
/**
* Read and Write pubguru config
*
* @param array $data Array of pubguru configuration.
*
* @return bool|array
*/
public static function pubguru_config( $data = null ) {
if ( null === $data ) {
return get_option( self::CONFIG_KEY );
}
if ( 'delete' === $data ) {
return delete_option( self::CONFIG_KEY );
}
return update_option( self::CONFIG_KEY, $data );
}
/**
* Read and Write pubguru module status
*
* @param string $module Module name.
* @param bool $status Module status.
*
* @return bool
*/
public static function module( $module, $status = null ): bool {
$option_key = 'pubguru_module_' . $module;
if ( null === $status ) {
return boolval( get_option( $option_key, false ) );
}
update_option( $option_key, $status );
return $status;
}
}

View File

@@ -0,0 +1,139 @@
<?php
/**
* Modules TrafficCop Page Parser.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick;
use AdvancedAds\Framework\Interfaces\Integration_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Modules TrafficCop Page Parser.
*
* phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
*/
class Page_Parser implements Integration_Interface {
/**
* Hold page.
*
* @var string
*/
private $page = '';
/**
* Get Parser Instance
*
* @return Page_Parser
*/
public static function get_instance() {
static $instance;
if ( null === $instance ) {
$instance = new Page_Parser();
$instance->hooks();
}
return $instance;
}
/**
* Hook into WordPress.
*
* @return void
*/
public function hooks(): void {
add_action( 'template_redirect', [ $this, 'start_buffer' ], -9999 );
add_action( 'wp_footer', [ $this, 'flush_page' ], 9999 );
}
/**
* Get page
*
* @return string
*/
public function get_page() {
return $this->page;
}
/**
* Start of buffer.
*
* @return void
*/
public function start_buffer() {
ob_start( [ $this, 'parse' ] );
}
/**
* Parse page for script tag
*
* @param string $buffer Page buffer.
*
* @return string
*/
public function parse( $buffer ): string {
$this->page = $buffer;
$this->loop_script_tags();
$this->page = apply_filters( 'pubguru_current_page', $this->page ); // phpcs:ignore
return $this->page;
}
/**
* Flush page after footer
*
* @return void
*/
public function flush_page() {
$buffer_status = ob_get_status();
if (
! empty( $buffer_status ) &&
1 === $buffer_status['type'] &&
get_class( $this ) . '::parse' === $buffer_status['name']
) {
ob_end_flush();
}
}
/**
* Loop through script tags.
*
* @return void
*/
public function loop_script_tags() {
// Early bail!!
if ( ! has_filter( 'pubguru_page_script_tag' ) ) {
return;
}
$scripts = $this->get_script_tags();
foreach ( $scripts as $script ) {
$find = $script;
$replace = apply_filters( 'pubguru_page_script_tag', $script );
if ( false !== $replace ) {
$this->page = str_replace( $find, $replace, $this->page );
}
}
}
/**
* Get script tags only.
*
* @return array
*/
private function get_script_tags() {
$matches = [];
preg_match_all( '/<script[\s\S]*?>[\s\S]*?<\/script>/i', $this->page, $matches );
return isset( $matches[0] ) ? $matches[0] : [];
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* OneClick Connect module
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
use AdvancedAds\Modules\OneClick\Admin\Admin;
use AdvancedAds\Modules\OneClick\Admin\Ajax;
use AdvancedAds\Modules\OneClick\Workflow;
// Common.
( new Workflow() )->hooks();
// Admin.
if ( is_admin() ) {
( new Ajax() )->hooks();
( new Admin() )->hooks();
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* The class is responsible to redirect ads.txt to centralized location.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick\AdsTxt;
use AdvancedAds\Utilities\WordPress;
use AdvancedAds\Framework\Interfaces\Integration_Interface;
use AdvancedAds\Framework\Utilities\Params;
use AdvancedAds\Framework\Utilities\Str;
defined( 'ABSPATH' ) || exit;
/**
* AdsTxt.
*/
class AdsTxt implements Integration_Interface {
/**
* Hook into WordPress
*
* @return void
*/
public function hooks(): void {
remove_action( 'advanced-ads-plugin-loaded', 'advanced_ads_ads_txt_init' );
add_action( 'template_redirect', [ $this, 'handle_redirect' ] );
add_filter( 'allowed_redirect_hosts', [ $this, 'allowed_redirect_hosts' ] );
}
/**
* Handle redirect
*
* @return void
*/
public function handle_redirect(): void {
if (
'ads-txt' !== get_query_var( 'name' ) ||
Str::contains( Params::server( 'REQUEST_URI' ), 'ads.txt' )
) {
return;
}
$redirect = sprintf( 'https://adstxt.pubguru.net/pg/%s/ads.txt', WordPress::get_site_domain() );
wp_safe_redirect( $redirect, 301 );
exit;
}
/**
* Allowed redirect hosts
*
* @param array $hosts Array to hold allowed hosts.
*
* @return array
*/
public function allowed_redirect_hosts( $hosts ): array {
$hosts[] = 'adstxt.pubguru.net';
return $hosts;
}
}

View File

@@ -0,0 +1,136 @@
<?php
/**
* The class is responsible to detect ads.txt.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick\AdsTxt;
use AdvancedAds\Modules\OneClick\Admin\Admin;
use AdvancedAds\Framework\Interfaces\Integration_Interface;
use AdvancedAds\Utilities\Conditional;
defined( 'ABSPATH' ) || exit;
/**
* Detector.
*/
class Detector implements Integration_Interface {
/**
* Hook into WordPress
*
* @return void
*/
public function hooks(): void {
add_action( 'current_screen', [ $this, 'conditional_loading' ] );
}
/**
* Detect ads.txt physical file
*
* @return void
*/
public function conditional_loading(): void {
if ( ! Conditional::is_screen_advanced_ads() ) {
return;
}
if ( $this->detect_files() ) {
add_action( 'all_admin_notices', [ $this, 'show_notice' ] );
}
}
/**
* Detect file exists
*
* @param string $file file name.
*
* @return bool
*/
public function detect_files( $file = 'ads.txt' ): bool {
$wp_filesystem = $this->get_filesystem();
if ( null === $wp_filesystem ) {
return false;
}
return $wp_filesystem->exists( ABSPATH . '/' . $file );
}
/**
* Backup file
*
* @return bool
*/
public function backup_file(): bool {
$source = ABSPATH . '/ads.txt';
$destination = $source . '.bak';
return $this->move_file( $source, $destination );
}
/**
* Revert file
*
* @return bool
*/
public function revert_file(): bool {
$source = ABSPATH . '/ads.txt.bak';
$destination = ABSPATH . 'ads.txt';
return $this->move_file( $source, $destination );
}
/**
* Show notice that physical file exists
*
* @return void
*/
public function show_notice(): void {
?>
<div class="notice notice-error flex items-center p-4">
<div>
<strong><?php esc_html_e( 'File alert!', 'advanced-ads' ); ?></strong> <?php esc_html_e( 'Physical ads.txt found. In order to use PubGuru service you need to delete it or back it up.', 'advanced-ads' ); ?>
</div>
<button class="!ml-auto button button-primary js-btn-backup-adstxt" data-text="<?php esc_attr_e( 'Backup the File', 'advanced-ads' ); ?>" data-loading="<?php esc_attr_e( 'Backing Up', 'advanced-ads' ); ?>" data-done="<?php esc_attr_e( 'Backed Up', 'advanced-ads' ); ?>" data-security="<?php echo wp_create_nonce( 'pubguru_oneclick_security' ); // phpcs:ignore ?>">
<?php esc_html_e( 'Backup the File', 'advanced-ads' ); ?>
</button>
</div>
<?php
}
/**
* Instantiates the WordPress filesystem for use
*
* @return object
*/
private function get_filesystem() {
global $wp_filesystem;
if ( empty( $wp_filesystem ) ) {
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem();
}
return $wp_filesystem;
}
/**
* Handle file operations (backup or revert)
*
* @param string $source Source file path.
* @param string $destination Destination file path.
*
* @return bool
*/
private function move_file( string $source, string $destination ): bool {
$wp_filesystem = $this->get_filesystem();
if ( null === $wp_filesystem || ! $wp_filesystem->is_writable( $source ) ) {
return false;
}
return $wp_filesystem->move( $source, $destination );
}
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* The class is responsible to inject header bidding tags.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick;
use AdvancedAds\Framework\Utilities\Str;
use AdvancedAds\Framework\Interfaces\Integration_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Header bidding tags.
*/
class Header_Bidding implements Integration_Interface {
/**
* Hook into WordPress
*
* @return void
*/
public function hooks(): void {
add_filter( 'pubguru_page_script_tag', [ $this, 'remove_tags' ] );
add_filter( 'pubguru_current_page', [ $this, 'add_tags' ] );
}
/**
* Add TrafficCop tags
*
* @param string $page Page html.
*
* @return string
*/
public function add_tags( $page ): string {
$page = $this->add_script_tag( $page );
return $page;
}
/**
* Remove script tag
*
* @param string $script Scrip tag.
*
* @return string
*/
public function remove_tags( $script ): string {
if ( Str::contains( '/gpt.js', $script ) ) {
$script = '';
}
if ( Str::contains( '//m2d.m2.ai/', $script ) || Str::contains( '//c.pubguru.net/', $script ) ) {
$script = '';
}
if ( Str::contains( 'window.pg.atq = window.pg.atq || [];', $script ) ) {
$script = '';
}
return $script;
}
/**
* Guard the page from getting JS errors
*
* @param string $page Page html.
*
* @return string
*/
private function add_script_tag( $page ): string {
$name = Helpers::get_config_file();
$at_body = Options::module( 'header_bidding_at_body' );
if ( $name ) {
$script = [];
if ( ! $at_body ) {
$script[] = '<head>';
}
$script[] = '<script src="https://securepubads.g.doubleclick.net/tag/js/gpt.js" async></script>'; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
$script[] = '<script type="text/javascript">window.googletag=window.googletag||{};window.googletag.cmd=window.googletag.cmd||[];';
$script[] = 'window.googletag.cmd.push(function(){window.__onpageGptEmbed=(new Date()).getTime()})</script>';
$script[] = sprintf( '<script src="//c.pubguru.net/%s" async> </script>', $name ); // phpcs:ignore
if ( Options::module( 'traffic_cop' ) && Helpers::has_traffic_cop() ) {
$script[] = '<script>window.pg = window.pg || {};window.pg.atq = window.pg.atq || [];</script>';
}
if ( $at_body ) {
$page = $page . join( "\n", $script );
} else {
$page = str_replace(
'<head>',
join( "\n", $script ),
$page
);
}
}
return $page;
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* The class is responsible to convert ad tags to pubguru tag.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick;
use AdvancedAds\Modules\OneClick\Helpers;
use AdvancedAds\Framework\Interfaces\Integration_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Ad tags conversion.
*/
class Tags_Conversion implements Integration_Interface {
/**
* Hook into WordPress
*
* @return void
*/
public function hooks(): void {
add_filter( 'pubguru_current_page', [ $this, 'convert_tags' ], 20 );
}
/**
* Convert tags
*
* @param string $page Page html.
*
* @return string
*/
public function convert_tags( $page ): string {
$page = $this->convert_ad_by_config( $page );
return $page;
}
/**
* Convert ad divs to pubguru tags
*
* @param string $page Page html.
*
* @return string
*/
private function convert_ad_by_config( $page ): string {
$slots = $this->get_ad_slots();
if ( false === $slots ) {
return $page;
}
$divs = $this->get_ad_divs( $page, $slots );
foreach ( $divs as $div ) {
$replace = str_replace(
[ '<div', '</div>' ],
[ '<pubguru', '</pubguru>' ],
$div
);
$page = str_replace( $div, $replace, $page );
}
return $page;
}
/**
* Get ad divs only
*
* @param string $page Page html.
* @param array $slots Ad slots ids.
*
* @return array
*/
private function get_ad_divs( $page, $slots ): array {
$matches = [];
$slot_ids = [];
foreach ( $slots as $slot ) {
$slot_ids[] = preg_quote( $slot, '/' );
}
$slot_ids = join( '|', $slot_ids );
preg_match_all( '/<div id="(' . $slot_ids . ')"[^>]*>(.*?)<\/div>/mis', $page, $matches );
return isset( $matches[0] ) ? $matches[0] : [];
}
/**
* Get slots from config
*
* @return bool|array
*/
private function get_ad_slots() {
$ads = Helpers::get_ads_from_config();
if ( false === $ads ) {
return false;
}
$slots = [];
foreach ( $ads as $ad ) {
$slots[] = $ad['slot'];
}
return $slots;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* The class is responsible to wrap the google tags into traffic cop wrappers.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick;
use AdvancedAds\Framework\Utilities\Str;
use AdvancedAds\Framework\Interfaces\Integration_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Traffic Cop.
*/
class Traffic_Cop implements Integration_Interface {
/**
* Hook into WordPress
*
* @return void
*/
public function hooks(): void {
add_filter( 'pubguru_page_script_tag', [ $this, 'modify_script_tag' ], 30 );
}
/**
* Modify scrip if google tag found
*
* @param mixed $content Scrip tag.
*
* @return bool|string
*/
public function modify_script_tag( $content ) {
// Early bail!!
if ( ! Str::contains( 'googletag.display', $content ) ) {
return false;
}
$content = str_replace( '<script>', '<script>pg.atq.push(function() {', $content );
$content = str_replace( '</script>', '});</script>', $content );
return $content;
}
}

View File

@@ -0,0 +1,180 @@
<?php
/**
* The class is responsible for the one-click module workflow.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Modules\OneClick;
use AdvancedAds\Modules\OneClick\Helpers;
use AdvancedAds\Modules\OneClick\Options;
use AdvancedAds\Framework\Utilities\Params;
use AdvancedAds\Modules\OneClick\Traffic_Cop;
use AdvancedAds\Modules\OneClick\AdsTxt\AdsTxt;
use AdvancedAds\Modules\OneClick\AdsTxt\Detector;
use AdvancedAds\Framework\Interfaces\Integration_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Workflow.
*/
class Workflow implements Integration_Interface {
/**
* Flush rules option key.
*
* @var string
*/
const FLUSH_KEY = 'pubguru_flush_rewrite_rules';
/**
* Hook into WordPress
*
* @return void
*/
public function hooks(): void {
add_action( 'init', [ $this, 'flush_rewrite_rules' ], 999 );
add_filter( 'pubguru_module_status_changed', [ $this, 'module_status_changed' ], 10, 3 );
if ( false !== Options::pubguru_config() && ! is_admin() ) {
add_action( 'wp', [ $this, 'init' ] );
if ( Options::module( 'ads_txt' ) ) {
( new AdsTxt() )->hooks();
}
if ( ! function_exists( 'wp_advads_pro' ) ) {
add_filter( 'advanced-ads-placement-content-offsets', [ $this, 'placement_content_offsets' ], 10, 3 );
}
}
if ( Options::module( 'ads_txt' ) ) {
if ( is_admin() ) {
( new Detector() )->hooks();
}
remove_action( 'advanced-ads-plugin-loaded', 'advanced_ads_ads_txt_init' );
}
}
/**
* Init workflow
*
* @return void
*/
public function init(): void {
// Early bail!!
$is_debugging = Params::get( 'aa-debug', false, FILTER_VALIDATE_BOOLEAN );
if ( ! $is_debugging && Helpers::is_ad_disabled() ) {
return;
}
Page_Parser::get_instance();
if ( $is_debugging || Options::module( 'header_bidding' ) ) {
$config = Options::pubguru_config();
$config['method'] = $config['method'] ?? 'page';
if ( 'page' === $config['method'] && isset( $config['page'] ) && is_page( absint( $config['page'] ) ) ) {
( new Header_Bidding() )->hooks();
}
if ( 'final' === $config['method'] ) {
( new Header_Bidding() )->hooks();
}
}
if ( $is_debugging || Options::module( 'tag_conversion' ) ) {
( new Tags_Conversion() )->hooks();
}
if ( Options::module( 'traffic_cop' ) && Helpers::has_traffic_cop() ) {
if ( ! Options::module( 'header_bidding' ) ) {
( new Header_Bidding() )->hooks();
}
( new Traffic_Cop() )->hooks();
}
}
/**
* Handle module status change
*
* @param array $data Data to send back to ajax request.
* @param string $module Module name.
* @param bool $status Module status.
*
* @return array
*/
public function module_status_changed( $data, $module, $status ): array {
if ( 'ads_txt' === $module ) {
$detector = new Detector();
if ( $status && $detector->detect_files() ) {
$data['notice'] = join(
'',
[
'<strong>' . esc_html__( 'File alert!', 'advanced-ads' ) . '</strong>',
' ',
esc_html__( 'Physical ads.txt found. In order to use PubGuru service you need to delete it or back it up.', 'advanced-ads' ),
]
);
$data['action'] = esc_html__( 'Backup the File', 'advanced-ads' );
}
if ( ! $status && $detector->detect_files( 'ads.txt.bak' ) ) {
$detector->revert_file();
}
update_option( self::FLUSH_KEY, 1 );
}
return $data;
}
/**
* Flush the rewrite rules once if the pubguru_flush_rewrite_rules option is set
*
* @return void
*/
public function flush_rewrite_rules(): void {
if ( get_option( self::FLUSH_KEY ) ) {
flush_rewrite_rules();
delete_option( self::FLUSH_KEY );
}
}
/**
* Get offsets for Content placement.
*
* @param array $offsets Existing Offsets.
* @param array $options Injection options.
* @param array $placement_opts Placement options.
*
* @return array $offsets New offsets.
*/
public function placement_content_offsets( $offsets, $options, $placement_opts ) {
if ( ! isset( $options['paragraph_count'] ) ) {
return $offsets;
}
// "Content" placement, repeat position.
if (
( ! empty( $placement_opts['repeat'] ) || ! empty( $options['repeat'] ) ) &&
isset( $options['paragraph_id'] ) &&
isset( $options['paragraph_select_from_bottom'] )
) {
$offsets = [];
for ( $i = $options['paragraph_id'] - 1; $i < $options['paragraph_count']; $i++ ) {
// Select every X number.
if ( 0 === ( $i + 1 ) % $options['paragraph_id'] ) {
$offsets[] = $options['paragraph_select_from_bottom'] ? $options['paragraph_count'] - 1 - $i : $i;
}
}
}
return $offsets;
}
}