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,546 @@
<?php // phpcs:ignoreFile
use AdvancedAds\Widget;
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Framework\Utilities\Params;
/**
*
* NOTE: can not rely actively on base plugin without prior test for existence (only after plugins_loaded hook)
*/
class Advanced_Ads_Pro_Admin {
/**
* Link to plugin page
*
* @since 1.1
* @const
*/
const PLUGIN_LINK = 'https://wpadvancedads.com/add-ons/advanced-ads-pro/';
/**
* Field name of the user role
*
* @since 1.2.5
* @const
*/
const ROLE_FIELD_NAME = 'advanced-ads-role';
/**
* Advanced Ads user roles array.
*
* @var array
*/
private $roles;
/**
* Initialize the plugin
*
* @since 1.0.0
*/
public function __construct() {
$this->roles = [
'advanced_ads_admin' => __( 'Ad Admin', 'advanced-ads-pro' ),
'advanced_ads_manager' => __( 'Ad Manager', 'advanced-ads-pro' ),
'advanced_ads_user' => __( 'Ad User', 'advanced-ads-pro' ),
'' => __( '--no role--', 'advanced-ads-pro' ),
];
// Add add-on settings to plugin settings page.
add_action( 'advanced-ads-settings-init', [ $this, 'settings_init' ], 9 );
add_filter( 'advanced-ads-setting-tabs', [ $this, 'setting_tabs' ] );
// Add user role selection to users page.
add_action( 'show_user_profile', [ $this, 'add_user_role_fields' ] );
add_action( 'edit_user_profile', [ $this, 'add_user_role_fields' ] );
add_action( 'profile_update', [ $this, 'save_user_role' ] );
// Display warning if advanced visitor conditions are not active.
add_action( 'advanced-ads-visitor-conditions-after', [ $this, 'show_condition_notice' ], 10, 0 );
// Display "once per page" field.
add_action( 'advanced-ads-output-metabox-after', [ $this, 'render_ad_output_options' ] );
// Load admin style sheet.
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_styles' ] );
// Render repeat option for Content placement.
add_action( 'advanced-ads-placement-post-content-position', [ $this, 'render_placement_repeat_option' ], 10, 2 );
add_filter( 'pre_update_option_advanced-ads', [ $this, 'pre_update_advanced_ads_options' ], 10, 2 );
// Show/hide warnings for privacy module based on Pro state.
add_filter( 'advanced-ads-privacy-custom-show-warning', [ $this, 'show_custom_privacy_warning' ] );
add_filter( 'advanced-ads-privacy-tcf-show-warning', '__return_false' );
add_filter( 'advanced-ads-privacy-custom-link-attributes', [ $this, 'privacy_link_attributes' ] );
add_filter( 'advanced-ads-ad-privacy-hide-ignore-consent', [ $this, 'hide_ignore_consent_checkbox' ], 10, 3 );
// Show a warning if cache-busting is enabled, but no placement is used for a widget.
add_action( 'in_widget_form', [ $this, 'show_no_placement_in_widget_warning' ], 10, 3 );
add_action( 'advanced-ads-export-options', [ $this, 'export_options' ] );
// Suggest a text for the WP Privacy Policy
add_action( 'admin_init', [ $this, 'add_privacy_policy_content' ] );
// Trim custom code on save.
add_action( 'advanced-ads-ad-pre-save', [$this, 'trim_custom_code_on_save'], 10, 2 );
}
/**
* Trim whitespaces in custom code when saving an ad
*
* @param Ad $ad the ad.
* @param array $post_data sanitized content of $_POST.
*
* @return void
*/
public function trim_custom_code_on_save( $ad, $post_data ) {
if ( isset( $post_data['custom-code'] ) ) {
$ad->set_prop_temp( 'custom-code', trim( (string) $post_data['custom-code'] ) );
}
}
/**
* Add settings to settings page
*
* @param string $hook settings page hook.
* @since 1.0.0
*/
public function settings_init( $hook ) {
register_setting( Advanced_Ads_Pro::OPTION_KEY, Advanced_Ads_Pro::OPTION_KEY );
/**
* Allow Ad Admin to save pro options.
*
* @param array $settings Array with allowed options.
*
* @return array
*/
add_filter( 'advanced-ads-ad-admin-options', function( $options ) {
$options[] = Advanced_Ads_Pro::OPTION_KEY;
return $options;
} );
// Add new section.
add_settings_section(
Advanced_Ads_Pro::OPTION_KEY . '_modules-enable',
'',
[ $this, 'render_modules_enable' ],
Advanced_Ads_Pro::OPTION_KEY . '-settings'
);
// Add new section.
add_settings_section(
'advanced_ads_pro_settings_section',
'',
[ $this, 'render_other_settings' ],
Advanced_Ads_Pro::OPTION_KEY . '-settings'
);
// Setting for Autoptimize support.
$has_optimizer_installed = Advanced_Ads_Checks::active_autoptimize();
if ( ! $has_optimizer_installed && method_exists( 'Advanced_Ads_Checks', 'active_wp_rocket' ) ) {
$has_optimizer_installed = Advanced_Ads_Checks::active_wp_rocket();
}
if ( $has_optimizer_installed ) {
add_settings_field(
'autoptimize-support',
__( 'Allow optimizers to modify ad codes', 'advanced-ads-pro' ),
[ $this, 'render_settings_autoptimize' ],
Advanced_Ads_Pro::OPTION_KEY . '-settings',
'advanced_ads_pro_settings_section'
);
}
add_settings_field(
'placement-positioning',
__( 'Placement positioning', 'advanced-ads-pro' ),
[ $this, 'render_settings_output_buffering' ],
Advanced_Ads_Pro::OPTION_KEY . '-settings',
'advanced_ads_pro_settings_section'
);
add_settings_field(
'disable-by-post-types',
__( 'Disable ads for post types', 'advanced-ads-pro' ),
[ $this, 'render_settings_disable_post_types' ],
$hook,
'advanced_ads_setting_section_disable_ads'
);
}
/**
* Copy settings from `general` tab in order to prevent it from being cleaned
* when Pro is deactivated.
*
* @param mixed $options Advanced Ads options.
* @return mixed options
*/
public function pre_update_advanced_ads_options( $options ) {
$pro = Advanced_Ads_Pro::get_instance()->get_options();
if ( isset( $options['pro']['general']['disable-by-post-types'] ) && is_array( $options['pro']['general']['disable-by-post-types'] ) ) {
$pro['general']['disable-by-post-types'] = $options['pro']['general']['disable-by-post-types'];
} else {
$pro['general']['disable-by-post-types'] = [];
}
Advanced_Ads_Pro::get_instance()->update_options( $pro );
return $options;
}
/**
* Render content of module enable option
*/
public function render_modules_enable() {
}
/**
* Render additional pro settings
*
* @since 1.1
*/
public function render_other_settings() {
// Save options when the user is on the "Pro" tab.
$selected = $this->get_disable_by_post_type_options();
foreach ( $selected as $item ) { ?>
<input type="hidden" name="<?php echo esc_attr( AAP_SLUG ); ?>[general][disable-by-post-types][]" value="<?php echo esc_html( $item ); ?>">
<?php
}
}
/**
* Render Autoptimize settings field.
*
* @since 1.2.3
*/
public function render_settings_autoptimize() {
$options = Advanced_Ads_Pro::get_instance()->get_options();
$autoptimize_support_disabled = $options['autoptimize-support-disabled'] ?? false;
require AA_PRO_ABSPATH . '/views/setting_autoptimize.php';
}
/**
* Render output buffering settings field.
*/
public function render_settings_output_buffering() {
$placement_positioning = Advanced_Ads_Pro::get_instance()->get_options()['placement-positioning'] === 'js' ? 'js' : 'php';
$allowed_types = [
'post_above_headline',
'custom_position',
];
$allowed_types_names = [];
foreach ( $allowed_types as $allowed_type ) {
$allowed_type = wp_advads_get_placement_type( $allowed_type );
if ( $allowed_type && '' !== $allowed_type->get_title() ) {
$allowed_types_names[] = $allowed_type->get_title();
}
}
require AA_PRO_ABSPATH . '/views/setting-placement-positioning.php';
}
/**
* Render settings to disable ads by post types.
*/
public function render_settings_disable_post_types() {
$selected = $this->get_disable_by_post_type_options();
$post_types = get_post_types(
[
'public' => true,
'publicly_queryable' => true,
],
'objects',
'or'
);
$type_label_counts = array_count_values( wp_list_pluck( $post_types, 'label' ) );
require AA_PRO_ABSPATH . '/views/setting_disable_post_types.php';
}
/**
* Get "Disabled by post type" Pro options.
*/
private function get_disable_by_post_type_options() {
$options = Advanced_Ads_Pro::get_instance()->get_options();
if ( isset( $options['general']['disable-by-post-types'] ) && is_array( $options['general']['disable-by-post-types'] ) ) {
$selected = $options['general']['disable-by-post-types'];
} else {
$selected = [];
}
return $selected;
}
/**
* Add tracking settings tab
*
* @since 1.2.0
* @param array $tabs existing setting tabs.
* @return array $tabs setting tabs with AdSense tab attached.
*/
public function setting_tabs( array $tabs ) {
$tabs['pro'] = [
// TODO abstract string.
'page' => Advanced_Ads_Pro::OPTION_KEY . '-settings',
'group' => Advanced_Ads_Pro::OPTION_KEY,
'tabid' => 'pro',
'title' => 'Pro',
];
return $tabs;
}
/**
* Form field for user role selection
*
* @param array $user user data.
*/
public function add_user_role_fields( $user ) {
if ( ! current_user_can( 'edit_users' ) ) {
return;
}
$role = get_user_meta( $user->ID, self::ROLE_FIELD_NAME, true );
?>
<h3><?php esc_html_e( 'Advanced Ads User Role', 'advanced-ads-pro' ); ?></h3>
<table class="form-table">
<tr>
<th><label for="advads_pro_role"><?php esc_html_e( 'Ad User Role', 'advanced-ads-pro' ); ?></label></th>
<td><select name="<?php echo esc_attr( self::ROLE_FIELD_NAME ); ?>" id="advads_pro_role">
<?php
foreach ( $this->roles as $_slug => $_name ) :
?>
<option value="<?php echo esc_attr( $_slug ); ?>" <?php selected( $role, $_slug ); ?>><?php echo esc_html( $_name ); ?></option>
<?php
endforeach;
?>
</select>
<p class="description"><?php esc_html_e( 'Please note, with the last update, the “Ad Admin“ and “Ad Manager“ roles have the “upload_files“ and the “unfiltered_html“ capabilities.', 'advanced-ads-pro' ); ?></p>
</td>
</tr>
</table>
<?php
}
/**
* Update the user role
*
* @param int $user_id ID of the user.
*/
public function save_user_role( $user_id) {
if (
! array_key_exists( self::ROLE_FIELD_NAME, $_POST )
|| ! current_user_can( 'edit_users' )
|| ! wp_verify_nonce( Params::post( '_wpnonce' ), 'update-user_' . $user_id)
) {
return;
}
// check if this is a valid user role.
$user_role = sanitize_text_field( Params::post( self::ROLE_FIELD_NAME ) );
if ( ! array_key_exists( $user_role, $this->roles ) ) {
return;
}
// Get user object.
$user = new WP_User( $user_id );
// Remove previous role.
$prev_role = get_user_meta( $user_id, self::ROLE_FIELD_NAME, true );
$user->remove_role( $prev_role );
// Save new role as user meta.
update_user_meta( $user_id, self::ROLE_FIELD_NAME, $user_role );
if ( $user_role ) {
// Add role.
$user->add_role( $user_role );
}
}
/**
* Show a notice if advanced visitor conditions are disabled. Maybe some users are looking for it
*/
public function show_condition_notice() {
$options = Advanced_Ads_Pro::get_instance()->get_options();
if ( ! isset( $options['advanced-visitor-conditions']['enabled'] ) ) {
echo '<p>' . sprintf(
wp_kses(
/* translators: %s: URL to the settings page */
__( 'Enable the Advanced Visitor Conditions <a href="%s" target="_blank">in the settings</a>.', 'advanced-ads-pro' ),
[
'a' => [
'href' => [],
'target' => [],
],
]
),
esc_url( admin_url( 'admin.php?page=advanced-ads-settings#top#pro' ) )
) . '</p>';
}
}
/**
* Add output options to ad edit page
*
* @param Ad $ad Ad instance.
*/
public function render_ad_output_options( Ad $ad ) {
$once_per_page = $ad->get_prop( 'once_per_page' ) ? 1 : 0;
require AA_PRO_ABSPATH . '/views/setting_output_once.php';
// Get CodeMirror setting for Custom code textarea.
$settings = $this->get_code_editor_settings();
$custom_code = ! empty( $ad->get_prop( 'custom-code' ) ) ? esc_textarea( $ad->get_prop( 'custom-code' ) ) : '';
$privacy_options = Advanced_Ads_Privacy::get_instance()->options();
require AA_PRO_ABSPATH . '/views/setting_custom_code.php';
}
/**
* Render repeat option for Content placement.
*
* @param string $placement_slug Placement id.
* @param Placement $placement Placement instance.
*/
public function render_placement_repeat_option( $placement_slug, $placement ) {
$data = $placement->get_data();
$words_between_repeats = ! empty( $data['words_between_repeats'] ) ? absint( $data['words_between_repeats'] ) : 0;
require AA_PRO_ABSPATH . '/views/setting_repeat.php';
}
/**
* Get CodeMirror settings.
*/
public function get_code_editor_settings() {
global $wp_version;
if ( 'advanced_ads' !== get_current_screen()->id
|| defined( 'ADVANCED_ADS_DISABLE_CODE_HIGHLIGHTING' )
|| -1 === version_compare( $wp_version, '4.9' ) ) {
return false;
}
// Enqueue code editor and settings for manipulating HTML.
$settings = wp_enqueue_code_editor( [ 'type' => 'text/html' ] );
if ( ! $settings ) {
$settings = false;
}
return $settings;
}
/**
* Register and enqueue admin-specific style sheet.
*/
public function enqueue_admin_styles() {
wp_enqueue_style( AAP_SLUG . '-admin-styles', AAP_BASE_URL . 'assets/admin.css', [], AAP_VERSION );
}
/**
* Only show privacy warning if cache-busting module not enabled.
*
* @param bool $show Whether to show warning.
*
* @return bool
*/
public function show_custom_privacy_warning( $show ) {
if ( ! $show ) {
return $show;
}
$options = Advanced_Ads_Pro::get_instance()->get_options();
return ! isset( $options['cache-busting']['enabled'] );
}
/**
* Update Link in Privacy settings ot settings page instead of external plugin page.
*
* @return array
*/
public function privacy_link_attributes() {
return [
'href' => esc_url( admin_url( 'admin.php?page=advanced-ads-settings#top#pro' ) ),
];
}
/**
* Show the ignore-consent checkbox if this ad has custom code and type is image or dummy.
* The filter is called `advanced-ads-ad-privacy-hide-ignore-consent`, so the return needs to be !$hide to show.
*
* @param bool $hide Whether to show ignore-consent checkbox.
* @param Ad $ad Ad instance.
*
* @return bool
*/
public function hide_ignore_consent_checkbox( $hide, Ad $ad ) {
if ( ! $hide || ! $ad->is_type( [ 'image', 'dummy' ] ) ) {
return $hide;
}
return empty( Advanced_Ads_Pro::get_instance()->get_custom_code( $ad ) );
}
/**
* Show a warning below the form of Advanced Ads widgets if cache-busting is enabled
* but the widget does not use a placement or "Force passive cache-busting" is enabled
*
* Uses the in_widget_form action hook
*
* @param WP_Widget $widget The widget instance (passed by reference).
* @param null $return Return null if new fields are added.
* @param array $instance An array of the widget's settings.
*/
public function show_no_placement_in_widget_warning( $widget, $return, $instance ) {
// bail if this is not the Advanced Ads widget
if ( ! is_a( $widget, Widget::class ) ) {
return;
}
// bail if cache-busting is not enabled or if Force passive cache-busting is enabled
$options = Advanced_Ads_Pro::get_instance()->get_options();
if ( empty( $options['cache-busting']['enabled'] ) || isset( $options['cache-busting']['passive_all'] ) ) {
return;
}
// check item ID and show warning if it is given but does not contain a placement
if ( ! empty( $instance['item_id'] ) && 0 !== strpos( $instance['item_id'], 'placement_' ) ) {
?>
<p class="advads-notice-inline advads-error">
<?php esc_html_e( 'Select a Sidebar placement to enable cache-busting.', 'advanced-ads-pro' ); ?>
<a href="https://wpadvancedads.com/manual/cache-busting/#Cache-Busting_in_Widgets" target="_blank">
<?php esc_html_e( 'Learn more', 'advanced-ads-pro' ); ?>
</a>
</p>
<?php
}
}
/**
* Add Pro options to the list of options to be exported.
*
* @param $options Array of option data keyed by option keys.
* @return $options Array of option data keyed by option keys.
*/
public function export_options( $options ) {
$options[ Advanced_Ads_Pro::OPTION_KEY ] = get_option( Advanced_Ads_Pro::OPTION_KEY );
return $options;
}
/**
* Adds a privacy policy statement under Settings > Privacy > Policy Guide
* which customers can use as a basic templace.
*/
public function add_privacy_policy_content() {
if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) {
return;
}
ob_start();
include AA_PRO_ABSPATH . 'views/privacy-policy-content.php';
wp_add_privacy_policy_content( 'Advanced Ads Pro', wp_kses_post( wpautop( ob_get_clean(), false ) ) );
}
}