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,81 @@
(function () {
'use strict';
// eslint-disable-next-line camelcase,no-undef
if (!window.advanced_ads_pro || !window.advads_pro_utils) {
return;
}
const date = new Date();
/**
* JS version of WP's PHP zeroise (with threshold fixed to 2)
*
* @param {string|number} num the number
* @return {string} number string with at most one leading zero
*/
const zeroise = function (num) {
num = typeof num !== 'string' ? num.toString() : num;
return num.length < 2 ? `0${num}` : num;
};
// add start and end time into passive CB ad info.
document.addEventListener('advanced-ads-passive-cb-ad-info', function (ev) {
if (typeof ev.detail.adInfo.by_hours === 'undefined') {
return;
}
const hours = ev.detail.adInfo.by_hours.split('_');
ev.detail.ad.by_hours = { start: hours[0], end: hours[1] };
});
// can display check.
document.addEventListener(
'advanced-ads-passive-cb-can-display',
function (ev) {
if (!ev.detail.adInfo.by_hours || !ev.detail.canDisplay.display) {
// no specific hours or already hidden by another check.
return;
}
const now = parseInt(
zeroise(date.getHours()) + zeroise(date.getMinutes()),
10
);
const start = parseInt(ev.detail.adInfo.by_hours.start, 10);
const end = parseInt(ev.detail.adInfo.by_hours.end, 10);
const canDisplay = {
show:
start < end
? now > start && now < end
: now > start || now < end,
};
// allow filtering of canDisplay for passive cb.
document.dispatchEvent(
new CustomEvent('advanced-ads-can-display-ads-by-hours', {
detail: {
canDisplay,
},
})
);
ev.detail.canDisplay.display = canDisplay.show;
if (!canDisplay.show) {
// eslint-disable-next-line camelcase,no-undef
advads_pro_utils.log(
'passive ad id',
ev.detail.adInfo.id,
'cannot be displayed: by_hours'
);
}
}
);
// Edit the ajax cb call payload
document.addEventListener('advanced-ads-ajax-cb-payload', function (ev) {
ev.detail.payload.browserTime = `${zeroise(date.getHours())}:${zeroise(
date.getMinutes()
)}`;
});
})();

View File

@@ -0,0 +1,13 @@
<?php
/**
* Main module class
*
* @package AdvancedAds\Pro
* @author Advanced Ads <info@wpadvancedads.com>
*/
namespace Advanced_Ads_Pro\Ads_By_Hours;
const BASE_DIR = __DIR__;
const BASE_FILE = __FILE__;
Module::get_instance();

View File

@@ -0,0 +1,152 @@
<?php
/**
* Backend helper
*
* @package AdvancedAds\Pro
* @author Advanced Ads <info@wpadvancedads.com>
*/
namespace Advanced_Ads_Pro\Ads_By_Hours;
use Advanced_Ads_Utils;
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Constants;
use DateTime;
/**
* Dashboard class
*/
class Admin {
/**
* Ads by hours module class
*
* @var Module
*/
private $module;
/**
* Constructor
*
* @param Module $module main module class.
*/
public function __construct( $module ) {
$this->module = $module;
if ( ! wp_doing_ajax() ) {
add_action( 'post_submitbox_misc_actions', [ $this, 'publish_metabox_markup' ], 20 );
add_filter( 'advanced-ads-ad-pre-save', [ $this, 'on_save' ], 10, 2 );
}
}
/**
* Save ad options.
*
* @param Ad $ad Ad instance.
* @param array $post_data Post data array.
*
* @return void
*/
public function on_save( $ad, $post_data ) {
$options['enabled'] = ! empty( $post_data['ads_by_hours']['enabled'] );
$posted = wp_unslash( $post_data['ads_by_hours'] ?? [] );
if ( ! isset( $options['start_hour'], $options['start_min'], $options['end_hour'], $options['end_min'] ) ) {
return;
}
$options['start_hour'] = in_array( $posted['start_hour'], $this->module->get_hours(), true ) ? sanitize_key( $posted['start_hour'] ) : '00';
$options['start_min'] = in_array( $posted['start_min'], $this->module->get_minutes(), true ) ? sanitize_key( $posted['start_min'] ) : '00';
$options['end_hour'] = in_array( $posted['end_hour'], $this->module->get_hours(), true ) ? sanitize_key( $posted['end_hour'] ) : '00';
$options['end_min'] = in_array( $posted['end_min'], $this->module->get_minutes(), true ) ? sanitize_key( $posted['end_min'] ) : '00';
$ad->set_prop( 'ads_by_hours', $options );
}
/**
* Get the warning about cache plugin
*
* @return string
*/
public function get_cache_plugin_warning() {
return __( "A cache plugin has been detected. It is recommended to enable Cache Busting and check the visitor's time when displaying the ad on the frontend.", 'advanced-ads-pro' );
}
/**
* Get the message for when CB is not detected
*
* @return string
*/
public function get_cb_warning_message() {
return __( "Showing ads depending on the visitor's time requires enabling Cache Busting.", 'advanced-ads-pro' );
}
/**
* Get localized hour to use in the publish metabox
*
* @param string $hour hour (00 to 23) to be localized.
*
* @return string
*/
public function get_localized_hour( $hour ) {
// From the saved WP tme format, replace all constants that are not hour nor timezone, preserve white spaces.
return ( new DateTime( "today $hour:00" ) )->format( preg_replace( '/[^gGhHaAeIOPTZ ]/', '', self::get_time_format() ) );
}
/**
* Get localized hour interval for the ad planning column
*
* @param Ad $ad Ad instance.
*
* @return array
*/
public function get_localized_intervals( $ad ) {
$interval = $ad->get_prop( 'ads_by_hours', [] );
if ( empty( $interval ) ) {
return [];
}
return [
'start' => ( new DateTime( "today {$interval['start_hour']}:{$interval['start_min']}" ) )->format( self::get_time_format() ),
'end' => ( new DateTime( "today {$interval['end_hour']}:{$interval['end_min']}" ) )->format( self::get_time_format() ),
];
}
/**
* Show ads by hours inputs on the publish metabox
*
* @return void
*/
public function publish_metabox_markup() {
if ( get_post_type() !== Constants::POST_TYPE_AD ) {
return;
}
$post = get_post();
$ad = wp_advads_get_ad( $post->ID );
$options = $this->module->get_ad_by_hour_options( $ad );
$addon_options = \Advanced_Ads_Pro::get_instance()->get_options();
require_once BASE_DIR . '/views/publish-metabox-inputs.php';
}
/**
* Get timezone used for the front end checks.
*
* @return string
*/
public function get_time_zone_string() {
return $this->module->use_browser_time() ? __( 'viewer time zone', 'advanced-ads-pro' ) : Advanced_Ads_Utils::get_timezone_name();
}
/**
* Get the WP time format option
*
* @return string
*/
public static function get_time_format() {
static $time_format;
if ( is_null( $time_format ) ) {
$time_format = get_option( 'time_format' );
}
return $time_format;
}
}

View File

@@ -0,0 +1,248 @@
<?php // phpcs:ignoreFile
/**
* Ads by hours main class
*
* @package AdvancedAds\Pro
* @author Advanced Ads <info@wpadvancedads.com>
*/
namespace Advanced_Ads_Pro\Ads_By_Hours;
use DateTimeImmutable;
use Advanced_Ads_Utils;
use AdvancedAds\Abstracts\Ad;
/**
* Main module class
*/
class Module {
const TIME_COOKIE = 'advanced_ads_browser_time';
/**
* The singleton
*
* @var Module
*/
private static $instance;
/**
* Whether to use client side time
*
* @var bool
*/
private $use_browser_time = false;
/**
* Dashboard helper class
*
* @var Admin
*/
private $admin;
/**
* Private constructor
*/
private function __construct() {
if ( is_admin() ) {
$this->admin = new Admin( $this );
}
add_filter( 'advanced-ads-can-display-ad', [ $this, 'can_display_by_hours' ], 10, 2 );
$this->use_browser_time = defined( 'ADVANCED_ADS_ADS_BY_BROWSER_HOUR' ) && ADVANCED_ADS_ADS_BY_BROWSER_HOUR;
if ( $this->use_browser_time ) {
add_filter( 'advanced-ads-pro-ad-needs-backend-request', [ $this, 'force_cb' ], 10, 2 );
add_filter( 'advanced-ads-pro-passive-cb-for-ad', [ $this, 'add_passive_cb_info' ], 10, 2 );
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
}
}
/**
* Adds info about hours to passive CB ad
*
* @param array $passive_cb_info information used by passive cb to decide whether the ad can be displayed.
* @param Ad $ad the ad.
*
* @return array
*/
public function add_passive_cb_info( $passive_cb_info, $ad ) {
$options = $this->get_ad_by_hour_options( $ad );
if ( empty( $options['enabled'] ) ) {
return $passive_cb_info;
}
if ( $options['start_hour'] . $options['start_min'] === $options['end_hour'] . $options['end_min'] ) {
return $passive_cb_info;
}
$passive_cb_info['by_hours'] = "{$options['start_hour']}{$options['start_min']}_{$options['end_hour']}{$options['end_min']}";
return $passive_cb_info;
}
/**
* @param string $cb_mode
* @param Ad $ad
*
* @return string
*/
public function force_cb( $cb_mode, $ad ) {
return $ad->get_prop( 'ads_by_hours.enabled' ) && 'static' === $cb_mode ? 'passive' : $cb_mode;
}
/**
* Get the admin helper
*
* @return Admin
*/
public function admin() {
return $this->admin;
}
/**
* Getter for `use_browserçtime`
*
* @return bool
*/
public function use_browser_time() {
return $this->use_browser_time;
}
/**
* Enqueue scripts on the frontend
*
* @return void
*/
public function enqueue_scripts() {
wp_enqueue_script(
'AdvancedAds\Pro\ads-by-hours',
trailingslashit( plugin_dir_url( BASE_FILE ) ) . 'assets/frontend.js',
[ 'advanced-ads-pro/cache_busting' ],
AAP_VERSION,
false
);
}
/**
* Should an ad be displayed given current DateTime
*
* @param bool $can_display current value of $can_display.
* @param Ad $ad current ad.
*
* @return bool|mixed
* @throws \Exception Can't create date object.
*/
public function can_display_by_hours( $can_display, $ad ) {
if ( ! $can_display ) {
return false;
}
$module_options = $this->get_ad_by_hour_options( $ad );
if ( empty( $module_options['enabled'] ) ) {
return true;
}
if ( $module_options['start_hour'] . $module_options['start_min'] === $module_options['end_hour'] . $module_options['end_min'] ) {
return true;
}
if ( wp_doing_ajax() ) {
// AJAX CB.
// phpcs:disable WordPress.Security.NonceVerification.Missing
$post_vars = wp_unslash( $_POST );
if ( 'advads_ad_select' === sanitize_key( $post_vars['action'] ) && ! empty( $post_vars['browserTime'] ) ) {
$browser_time = explode( ':', sanitize_text_field( $post_vars['browserTime'] ) );
$now = (int) zeroise( $browser_time[0], 2 ) . zeroise( $browser_time[1], 2 );
$start = (int) $module_options['start_hour'] . $module_options['start_min'];
$end = (int) $module_options['end_hour'] . $module_options['end_min'];
// Show if $now is between $start and $end.
$can_display = $now > $start && $now < $end;
if ( $start > $end ) {
// In case of overnight, show if $now is after $start OR before $end.
$can_display = $now > $start || $now < $end;
}
return apply_filters( 'advanced-ads-can-display-ads-by-hours', $can_display, $ad, $this );
}
// phpcs:enable
}
if ( $this->use_browser_time ) {
$pro_options = \Advanced_Ads_Pro::get_instance()->get_options();
if ( ! ( isset( $pro_options['cache-busting']['enabled'] ) && $pro_options['cache-busting']['enabled'] ) ) {
// Use browser time but cache busting not enabled - abort.
return apply_filters( 'advanced-ads-can-display-ads-by-hours', false, $ad, $this );
}
if ( 'off' === $ad->get_prop( 'cache-busting' ) ) {
return apply_filters( 'advanced-ads-can-display-ads-by-hours', false, $ad, $this );
}
// otherwise let CB handle it.
return apply_filters( 'advanced-ads-can-display-ads-by-hours', true, $ad, $this );
}
$now = (int) ( new DateTimeImmutable( 'now', Advanced_Ads_Utils::get_wp_timezone() ) )->format( 'U' );
$start = (int) ( new DateTimeImmutable( "today {$module_options['start_hour']}:{$module_options['start_min']}", Advanced_Ads_Utils::get_wp_timezone() ) )->format( 'U' );
$end = (int) ( new DateTimeImmutable( "today {$module_options['end_hour']}:{$module_options['end_min']}", Advanced_Ads_Utils::get_wp_timezone() ) )->format( 'U' );
$can_display = $start < $end ? $now > $start && $now < $end : $now > $start || $now < $end;
return apply_filters( 'advanced-ads-can-display-ads-by-hours', $can_display, $ad, $this );
}
/**
* Get minutes intervals
*
* @return string[]
*/
public function get_minutes() {
return [ '00', '15', '30', '45' ];
}
/**
* Get ads by hour option for a given ad, fall back to default value if not existing
*
* @param Ad $ad current ad.
*
* @return array
*/
public function get_ad_by_hour_options( $ad ) {
return $ad->get_prop( 'ads_by_hours' ) ?? [
'enabled' => false,
'start_hour' => '00',
'start_min' => '00',
'end_hour' => '00',
'end_min' => '00',
];
}
/**
* Get list of hours, from 00 to 23
*
* @return array
*/
public function get_hours() {
$hours = [];
for ( $i = 0; $i <= 23; $i++ ) {
$hours [] = zeroise( $i, 2 );
}
return $hours;
}
/**
* Returns the singleton
*
* @return Module the singleton.
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
}

View File

@@ -0,0 +1,74 @@
<?php
/***
* Markup for ads by hours inputs
*
* @package AdvancedAds\Pro
* @author Advanced Ads <info@wpadvancedads.com>
*
* @var array $addon_options pro add-on options.
* @var array $options ads by hour module options.
* @var Advanced_Ads_Pro\Ads_By_Hours\admin $this dashboard class.
*/
use AdvancedAds\Utilities\Conditional;
$cache_busting_enabled = isset( $addon_options['cache-busting']['enabled'] ) && $addon_options['cache-busting']['enabled'];
?>
<div id="advanced-ads-ads-by-hours-inputs" class="misc-pub-section">
<label onclick="advads_toggle_box( '#advanced-ads-ads-by-hours-enabled', '#advanced-ads-ads-by-hours-inputs .inner' )">
<input type="checkbox" value="1" name="advanced_ad[ads_by_hours][enabled]" id="advanced-ads-ads-by-hours-enabled" <?php checked( ! empty( $options['enabled'] ) ); ?>>
<?php esc_html_e( 'Set specific hours', 'advanced-ads-pro' ); ?>
</label>
<?php if ( $this->module->use_browser_time() && ! $cache_busting_enabled ) : ?>
<div class="notice advads-notice inline" style="margin:5px 1px 7px">
<p><?php echo esc_html( $this->get_cb_warning_message() ); ?></p>
</div>
<?php endif; ?>
<?php if ( ! $this->module->use_browser_time() && Conditional::has_cache_plugins() && ! $cache_busting_enabled ) : ?>
<div class="notice advads-notice inline" style="margin:5px 1px 7px">
<p><?php echo esc_html( $this->get_cache_plugin_warning() ); ?></p>
</div>
<?php endif; ?>
<div class="inner" style="<?php echo ! empty( $options['enabled'] ) ? '' : 'display:none;'; ?>font-size:.9em;">
<div>
<p style="font-weight: 500;"><?php esc_html_e( 'From', 'advanced-ads-pro' ); ?></p>
<fieldset class="advads-timestamp">
<label>
<select name="advanced_ad[ads_by_hours][start_hour]">
<?php foreach ( $this->module->get_hours() as $hour ) : ?>
<option value="<?php echo esc_attr( $hour ); ?>" <?php selected( $hour, $options['start_hour'] ); ?>><?php echo esc_html( $this->get_localized_hour( $hour ) ); ?></option>
<?php endforeach; ?>
</select>
</label>:
<label>
<select name="advanced_ad[ads_by_hours][start_min]">
<?php foreach ( $this->module->get_minutes() as $min ) : ?>
<option value="<?php echo esc_attr( $min ); ?>" <?php selected( $min, $options['start_min'] ); ?>><?php echo esc_html( $min ); ?></option>
<?php endforeach; ?>
</select>
</label>
</fieldset>
</div>
<div>
<p style="font-weight: 500;"><?php esc_html_e( 'To', 'advanced-ads-pro' ); ?></p>
<fieldset class="advads-timestamp">
<label>
<select name="advanced_ad[ads_by_hours][end_hour]">
<?php foreach ( $this->module->get_hours() as $hour ) : ?>
<option value="<?php echo esc_attr( $hour ); ?>" <?php selected( $hour, $options['end_hour'] ); ?>><?php echo esc_html( $this->get_localized_hour( $hour ) ); ?></option>
<?php endforeach; ?>
</select>
</label>:
<label>
<select name="advanced_ad[ads_by_hours][end_min]">
<?php foreach ( $this->module->get_minutes() as $min ) : ?>
<option value="<?php echo esc_attr( $min ); ?>" <?php selected( $min, $options['end_min'] ); ?>><?php echo esc_html( $min ); ?></option>
<?php endforeach; ?>
</select>
</label>
</fieldset>
</div>
<p class="description">(<?php echo esc_html( $this->get_time_zone_string() ); ?>)</p>
</div>
</div>