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,65 @@
<?php
/**
* This class is responsible to model content ads.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads;
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Interfaces\Ad_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Content ad.
*/
class Ad_Content extends Ad implements Ad_Interface {
/**
* Prepare output for frontend.
*
* @return string
*/
public function prepare_frontend_output(): string {
$output = $this->get_content();
if ( isset( $GLOBALS['wp_embed'] ) ) {
$old_post = $GLOBALS['post'];
$GLOBALS['post'] = $this->get_id(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$output = $GLOBALS['wp_embed']->run_shortcode( $output );
$output = $GLOBALS['wp_embed']->autoembed( $output );
$GLOBALS['post'] = $old_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
}
$output = wptexturize( $output );
$output = convert_smilies( $output );
$output = convert_chars( $output );
$output = wpautop( $output );
$output = shortcode_unautop( $output );
$output = $this->do_shortcode( $output );
if ( defined( 'ADVADS_DISABLE_RESPONSIVE_IMAGES' ) && ADVADS_DISABLE_RESPONSIVE_IMAGES ) {
return $output;
}
// Make included images responsive, since WordPress 4.4, before WordPress 5.5.
if ( function_exists( 'wp_make_content_images_responsive' ) && ! function_exists( 'wp_filter_content_tags' ) ) {
return function_exists( 'wp_filter_content_tags' )
? wp_filter_content_tags( $output )
: wp_make_content_images_responsive( $output ); // phpcs:ignore WordPress.WP.DeprecatedFunctions.wp_make_content_images_responsiveFound
}
// Function wp_make_content_images_responsive has been deprecated with WordPress 5.5.
if ( function_exists( 'wp_filter_content_tags' ) ) {
return wp_filter_content_tags( $output );
}
return $output;
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* This class is responsible to model dummy ads.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads;
use Advanced_Ads;
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Utilities\WordPress;
use AdvancedAds\Interfaces\Ad_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Dummy ad.
*/
class Ad_Dummy extends Ad implements Ad_Interface {
/**
* Prepare output for frontend.
*
* @return string
*/
public function prepare_frontend_output(): string {
$style = '';
if ( strpos( $this->get_position(), 'center' ) === 0 ) {
$style .= 'display: inline-block;';
}
$style = '' !== $style ? 'style="' . $style . '"' : '';
$img = sprintf(
'<img src="%s" width="300" height="250" %s />',
esc_url( ADVADS_BASE_URL . 'public/assets/img/dummy.jpg' ),
$style
);
$url = $this->get_url();
if ( ! defined( 'AAT_VERSION' ) && $url ) {
$options = Advanced_Ads::get_instance()->options();
$target_blank = ! empty( $options['target-blank'] ) ? ' target="_blank"' : '';
$img = sprintf( '<a href="%s"%s aria-label="dummy">%s</a>', esc_url( $url ), $target_blank, $img );
}
// Add 'loading' attribute if applicable, available from WP 5.5.
if ( function_exists( 'wp_lazy_loading_enabled' ) && wp_lazy_loading_enabled( 'img', 'the_content' ) ) {
// Optimize image HTML tag with loading attributes based on WordPress filter context.
$img = WordPress::img_tag_add_loading_attr( $img, 'the_content' );
}
return $img;
}
}

View File

@@ -0,0 +1,120 @@
<?php
/**
* The ad factory.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads;
use Exception;
use AdvancedAds\Constants;
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Abstracts\Factory;
defined( 'ABSPATH' ) || exit;
/**
* Ads Factory.
*/
class Ad_Factory extends Factory {
/**
* Create an empty ad object
*
* @param string $type Type of ad to create.
*
* @return Ad|bool Ad object or false if the ad type not found.
*/
public function create_ad( $type = 'dummy' ) {
$ad_type = wp_advads_get_ad_type( $type );
if ( ! $ad_type ) {
return false;
}
$classname = $ad_type->get_classname();
// Create ad.
$ad = new $classname( 0 );
$ad->set_type( $ad_type->get_id() );
return $ad;
}
/**
* Get the ad object.
*
* @param Ad|WP_Post|int|bool $ad_id Ad instance, post instance, numeric or false to use global $post.
* @param string $new_type Change type of ad.
*
* @return Ad|bool Ad object or false if the ad cannot be loaded.
*/
public function get_ad( $ad_id, $new_type = '' ) {
$ad_id = $this->get_ad_id( $ad_id );
if ( ! $ad_id ) {
return false;
}
$ad_type = '' !== $new_type ? $new_type : $this->get_ad_type( $ad_id );
$classname = $this->get_classname( wp_advads_get_ad_type_manager(), $ad_type, 'dummy' );
try {
return new $classname( $ad_id );
} catch ( Exception $e ) {
return false;
}
return new Ad_Content();
}
/**
* Get the type of the ad.
*
* @param int $ad_id Ad ID.
*
* @return string The type of the ad.
*/
private function get_ad_type( $ad_id ): string {
// Allow the overriding of the lookup in this function. Return the ad type here.
$override = apply_filters( 'advanced-ads-ad-type', false, $ad_id );
if ( $override ) {
return $override;
}
$options = get_post_meta( $ad_id, Ad_Repository::OPTION_METAKEY, true );
return $options['type'] ?? 'dummy';
}
/**
* Get the ad ID depending on what was passed.
*
* @param Ad|WP_Post|int|bool $ad Ad instance, post instance, numeric or false to use global $post.
*
* @return int|bool false on failure
*/
private function get_ad_id( $ad ) {
global $post;
if ( false === $ad && isset( $post, $post->ID ) && Constants::POST_TYPE_AD === get_post_type( $post->ID ) ) {
return absint( $post->ID );
}
if ( is_numeric( $ad ) ) {
return $ad;
}
if ( is_an_ad( $ad ) ) {
return $ad->get_id();
}
if ( ! empty( $ad->ID ) ) {
return $ad->ID;
}
return false;
}
}

View File

@@ -0,0 +1,114 @@
<?php
/**
* Manage ad and group relationship.
*
* @since 2.0.7
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
*/
namespace AdvancedAds\Ads;
use AdvancedAds\Constants;
defined( 'ABSPATH' ) || exit;
/**
* Ad group relation class.
*/
class Ad_Group_Relation {
/**
* Hold groups.
*
* @var array
*/
private $groups = [];
/**
* Create ad group relation.
*
* @param Ad $ad Ad object.
*
* @return void
*/
public function relate( $ad ): void {
$old_groups = get_post_meta( $ad->get_id(), Constants::AD_META_GROUP_IDS, true );
$new_groups = wp_get_object_terms( $ad->get_id(), Constants::TAXONOMY_GROUP, [ 'fields' => 'ids' ] );
if ( empty( $old_groups ) || ! is_array( $old_groups ) ) {
$old_groups = [];
}
$removed_terms = array_diff( $old_groups, $new_groups );
$added_terms = array_diff( $new_groups, $old_groups );
$this->handle_removed_terms( $removed_terms, $ad->get_id() );
$this->handle_added_terms( $added_terms, $ad->get_id() );
update_post_meta( $ad->get_id(), Constants::AD_META_GROUP_IDS, $new_groups );
}
/**
* Handles the removed terms for an ad.
*
* @param array $removed_terms An array of term IDs that have been removed.
* @param int $ad_id The ID of the ad.
*
* @return void
*/
private function handle_removed_terms( $removed_terms, $ad_id ): void {
foreach ( $removed_terms as $group_id ) {
$group = $this->get_group( $group_id );
if ( ! $group ) {
continue;
}
$weights = $group->get_ad_weights();
if ( isset( $weights[ $ad_id ] ) ) {
unset( $weights[ $ad_id ] );
$group->set_ad_weights( $weights );
$group->save();
}
}
}
/**
* Handles the added terms for an ad.
*
* @param array $added_terms An array of term IDs that have been added.
* @param int $ad_id The ID of the ad.
*
* @return void
*/
private function handle_added_terms( $added_terms, $ad_id ): void {
foreach ( $added_terms as $group_id ) {
$group = $this->get_group( $group_id );
if ( ! $group ) {
continue;
}
$weights = $group->get_ad_weights();
if ( ! isset( $weights[ $ad_id ] ) ) {
$weights[ $ad_id ] = Constants::GROUP_AD_DEFAULT_WEIGHT;
$group->set_ad_weights( $weights );
$group->save();
}
}
}
/**
* Get group by id and cache them.
*
* @param int $group_id Group id.
*
* @return Group|bool Group object or false if the group cannot be loaded.
*/
private function get_group( $group_id ) {
if ( ! isset( $this->groups[ $group_id ] ) ) {
$this->groups[ $group_id ] = wp_advads_get_group( $group_id );
}
return $this->groups[ $group_id ];
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* This class is responsible to model group ads.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads;
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Interfaces\Ad_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Group ad.
*/
class Ad_Group extends Ad implements Ad_Interface {
/**
* Get the group id for the ad.
*
* @param string $context What the value is for. Valid values are view and edit.
*
* @return int
*/
public function get_group_id( $context = 'view' ): int {
return $this->get_prop( 'group_id', $context ) ?? 0;
}
/**
* Prepare output for frontend.
*
* @return string
*/
public function prepare_frontend_output(): string {
if ( ! $this->get_group_id() ) {
return '';
}
// Disable the ad label for the ad group wrapper itself to avoid duplicate labels.
$ad_args = $this->get_prop( 'ad_args' ) ?? [];
$ad_args['ad_label'] = 'disabled';
return get_the_group( $this->get_group_id(), '', $ad_args );
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* This class is responsible to model image ads.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads;
use Advanced_Ads;
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Interfaces\Ad_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Image ad.
*/
class Ad_Image extends Ad implements Ad_Interface {
/**
* Get the image id for the ad.
*
* @param string $context What the value is for. Valid values are view and edit.
*
* @return int
*/
public function get_image_id( $context = 'view' ): int {
return $this->get_prop( 'image_id', $context ) ?? 0;
}
/**
* Set the image id.
*
* @param int|string $image_id Image id for ad.
*/
public function set_image_id( $image_id ) {
$this->set_prop( 'image_id', absint( $image_id ) );
}
/**
* Prepare output for frontend.
*
* @return string
*/
public function prepare_frontend_output(): string {
$url = $this->get_url();
$image_id = $this->get_image_id();
ob_start();
$this->get_type_object()->create_image_tag( $image_id, $this );
$img = ob_get_clean();
if ( ! defined( 'AAT_VERSION' ) && $url ) {
$alt = trim( esc_textarea( get_post_meta( $image_id, '_wp_attachment_image_alt', true ) ) );
$aria_label = ! empty( $alt ) ? $alt : wp_basename( get_the_title( $image_id ) );
$options = Advanced_Ads::get_instance()->options();
$target_blank = ! empty( $options['target-blank'] ) ? ' target="_blank"' : '';
$img = sprintf( '<a href="%s"%s aria-label="%s">%s</a>', esc_url( $url ), $target_blank, $aria_label, $img );
}
return $img;
}
/**
* Pre save
*
* @param array $post_data Post data.
*
* @return void
*/
public function pre_save( $post_data ): void {
$image_id = absint( $post_data['image_id'] ?? 0 );
if ( $image_id ) {
$attachment = get_post( $image_id );
if ( $attachment && 0 === $attachment->post_parent ) {
wp_update_post(
[
'ID' => $image_id,
'post_parent' => $this->get_id(),
]
);
}
}
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* This class is responsible to model plain ads.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads;
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Utilities\WordPress;
use AdvancedAds\Utilities\Conditional;
use AdvancedAds\Interfaces\Ad_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Plain ad.
*/
class Ad_Plain extends Ad implements Ad_Interface {
/**
* Prepare output for frontend.
*
* @return string
*/
public function prepare_frontend_output(): string {
$content = $this->get_content();
// Evaluate the code as PHP if setting was never saved or is allowed.
if ( $this->is_php_allowed() && Conditional::is_php_allowed() ) {
ob_start();
// phpcs:ignore Squiz.PHP.Eval.Discouraged -- this is specifically eval'd so allow eval here.
eval( '?>' . $content );
$content = ob_get_clean();
}
if ( ! is_string( $content ) ) {
return '';
}
/**
* Apply do_blocks if the content has block code
* works with WP 5.0.0 and later
*/
if ( function_exists( 'has_blocks' ) && has_blocks( $content ) ) {
$content = do_blocks( $content );
}
if ( $this->is_shortcode_allowed() ) {
$content = $this->do_shortcode( $content );
}
// Add 'loading' attribute if applicable, available from WP 5.5.
if (
function_exists( 'wp_lazy_loading_enabled' )
&& wp_lazy_loading_enabled( 'img', 'the_content' )
&& preg_match_all( '/<img\s[^>]+>/', $content, $matches )
) {
foreach ( $matches[0] as $image ) {
if ( strpos( $image, 'loading=' ) !== false ) {
continue;
}
// Optimize image HTML tag with loading attributes based on WordPress filter context.
$content = str_replace( $image, WordPress::img_tag_add_loading_attr( $image, 'the_content' ), $content );
}
}
return (
(
( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) ||
! Conditional::can_author_unfiltered_html( (int) get_post_field( 'post_author', $this->get_id() ) )
)
&& version_compare( $this->get_prop( 'last_save_version' ) ?? '0', '1.35.0', 'ge' )
)
? wp_kses_post( $content )
: $content;
}
}

View File

@@ -0,0 +1,502 @@
<?php
/**
* Ad Repository.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads;
use WP_Query;
use Exception;
use AdvancedAds\Constants;
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Admin\Metabox_Ad;
use AdvancedAds\Utilities\WordPress;
use AdvancedAds\Framework\Utilities\Arr;
use AdvancedAds\Framework\Utilities\Params;
use AdvancedAds\Framework\Utilities\Formatting;
defined( 'ABSPATH' ) || exit;
/**
* Ad Repository.
*
* phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.Found -- remove it later
*/
class Ad_Repository {
/**
* Ad options metakey
*
* @var string
*/
const OPTION_METAKEY = 'advanced_ads_ad_options';
/* CRUD Methods ------------------- */
/**
* Create a new ad in the database.
*
* @param Ad $ad Ad object.
*
* @return Ad
*/
public function create( &$ad ): Ad {
$id = wp_insert_post(
apply_filters(
'advanced-ads-new-ad-data',
[
'post_type' => Constants::POST_TYPE_AD,
'post_status' => $ad->get_status() ? $ad->get_status() : 'publish',
'post_author' => ! empty( $ad->get_author_id() ) ? $ad->get_author_id() : get_current_user_id(),
'post_title' => $ad->get_title() ? $ad->get_title() : __( 'New Ad', 'advanced-ads' ),
'post_content' => $ad->get_content() ? $ad->get_content() : __( 'New ad content goes here', 'advanced-ads' ),
'comment_status' => 'closed',
'ping_status' => 'closed',
],
$ad
),
true
);
if ( $id && ! is_wp_error( $id ) ) {
$ad->set_id( $id );
$this->update_post_meta( $ad );
$this->update_post_term( $ad );
$this->update_version( $ad );
$ad->apply_changes();
}
return $ad;
}
/**
* Read an ad from the database.
*
* @param Ad $ad Ad object.
* @throws Exception If invalid ad.
*
* @return void
*/
public function read( &$ad ): void {
$ad->set_defaults();
$post_object = get_post( $ad->get_id() );
if ( ! $ad->get_id() || ! $post_object || Constants::POST_TYPE_AD !== $post_object->post_type ) {
throw new Exception( esc_html__( 'Invalid ad.', 'advanced-ads' ) );
}
$ad->set_props(
[
'title' => $post_object->post_title,
'status' => $post_object->post_status,
'slug' => $post_object->post_name,
'content' => $post_object->post_content,
'author_id' => $post_object->post_author,
]
);
$this->read_ad_data( $ad );
$ad->set_object_read( true );
}
/**
* Update an existing ad in the database.
*
* @param Ad $ad Ad object.
*
* @return void
*/
public function update( &$ad ): void {
global $wpdb;
$changes = $ad->get_changes();
// Only update the post when the post data changes.
if ( array_intersect( [ 'title', 'status', 'content' ], array_keys( $changes ) ) ) {
$is_text_ad = $ad->is_type( [ 'plain', 'content' ] );
$post_data = [
'post_title' => $ad->get_title( 'edit' ),
'post_status' => $ad->get_status( 'edit' ) ? $ad->get_status( 'edit' ) : 'publish',
'post_type' => Constants::POST_TYPE_AD,
'post_content' => apply_filters(
'advanced-ads-pre-ad-save-' . $ad->get_type(),
$is_text_ad
? wp_unslash( $ad->get_content( 'edit' ) )
: apply_filters( 'content_save_pre', wp_unslash( $ad->get_content( 'edit' ) ) )
),
];
/**
* When updating this object, to prevent infinite loops, use $wpdb
* to update data, since wp_update_post spawns more calls to the
* save_post action.
*
* This ensures hooks are fired by either WP itself (admin screen save), or an update purely from CRUD.
*
* Use direct DB update for user-input ads to preserve literal content.
* Use wp_update_post for other ad types to maintain WordPress security standards.
*/
if ( doing_action( 'save_post' ) || $is_text_ad ) {
$GLOBALS['wpdb']->update( $GLOBALS['wpdb']->posts, $post_data, [ 'ID' => $ad->get_id() ] );
clean_post_cache( $ad->get_id() );
} else {
wp_update_post( array_merge( [ 'ID' => $ad->get_id() ], $post_data ) );
}
} else { // Only update post modified time to record this save event.
$wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
$wpdb->posts,
[
'post_modified' => current_time( 'mysql' ),
'post_modified_gmt' => current_time( 'mysql', 1 ),
],
[
'ID' => $ad->get_id(),
]
);
clean_post_cache( $ad->get_id() );
}
$this->update_post_meta( $ad );
$this->update_post_term( $ad );
$ad->apply_changes();
}
/**
* Delete an ad from the database.
*
* @param Ad $ad Ad object or Ad id.
* @param bool $force_delete Whether to bypass Trash and force deletion. Default false.
*
* @return void
*/
public function delete( &$ad, $force_delete = false ): void {
// Early bail!!
if ( ! $ad || ! $ad->get_id() ) {
return;
}
if ( $force_delete ) {
wp_delete_post( $ad->get_id(), true );
$ad->set_id( 0 );
} else {
wp_trash_post( $ad->get_id() );
$ad->set_status( 'trash' );
}
}
/* Finder Methods ------------------- */
/**
* Get an ad by its ID.
*
* @param int $id The ID of the ad to retrieve.
*
* @return Ad|null
*/
public function get_ad_by_id( $id ) {
return wp_advads_get_ad( $id );
}
/**
* Get ads belonging to a specific group.
*
* @param int $group_id The ID of the group.
*
* @return Ad[]
*/
public function get_ads_by_group_id( $group_id ): array {
$group = wp_advads_get_group( $group_id );
return $group->get_ads();
}
/**
* Get ads associated with a specific placement.
*
* @param int $placement_id The ID of the placement.
*
* @return array
*/
public function get_ads_by_placement_id( $placement_id ): array {
$placement = wp_advads_get_placement( $placement_id );
$item = $placement->get_item_object();
if ( is_a_group( $item ) ) {
return $item->get_ads();
}
if ( is_an_ad( $item ) ) {
return [ $item ];
}
return [];
}
/**
* Get ads of a specific type.
*
* @param string $type The type of ads to retrieve.
*
* @return array
*/
public function get_ads_by_type( $type ): array {
return [];
}
/**
* Get all ads object.
*
* @return array
*/
public function get_all_ads(): array {
static $advads_all_ads;
if ( isset( $advads_all_ads ) ) {
return $advads_all_ads;
}
$advads_all_ads = [];
foreach ( $this->get_ads_dropdown() as $post_id => $name ) {
$advads_all_ads[ $post_id ] = wp_advads_get_ad( $post_id );
}
return $advads_all_ads;
}
/**
* Get all ads as dropdown.
*
* @return array
*/
public function get_ads_dropdown(): array {
$query = $this->query(
[
'orderby' => 'title',
'order' => 'ASC',
],
true
);
return $query->have_posts() ? wp_list_pluck( $query->posts, 'post_title', 'ID' ) : [];
}
/**
* Query ads based on the provided arguments.
*
* @param array $args The arguments to customize the query.
* @param bool $improve_query Whether to improve the query speed.
*
* @return WP_Query The WP_Query object containing the results of the query.
*/
public function query( $args, $improve_query = false ): WP_Query {
$args = wp_parse_args(
$args,
[
'posts_per_page' => -1,
'post_status' => [ 'publish', 'future', 'draft' ],
]
);
// Strict mode.
$args['post_type'] = Constants::POST_TYPE_AD;
if ( $improve_query ) {
$args = WordPress::improve_wp_query( $args );
}
return new WP_Query( $args );
}
/* Additional Methods ------------------- */
/**
* Read ad data. Can be overridden by child classes to load other props.
*
* @param Ad $ad Ad object.
*
* @return void
*/
private function read_ad_data( &$ad ): void {
$post_meta_values = get_post_meta( $ad->get_id(), self::OPTION_METAKEY, true );
if ( empty( $post_meta_values ) || ! is_array( $post_meta_values ) ) {
$post_meta_values = [];
}
$post_meta_values = $this->migrate_values( $post_meta_values );
$display_conditions = $post_meta_values['conditions'] ?? [];
$visitor_conditions = $post_meta_values['visitors'] ?? [];
if ( ! Arr::accessible( $display_conditions ) ) {
$display_conditions = [];
}
if ( ! Arr::accessible( $visitor_conditions ) ) {
$visitor_conditions = [];
}
$ad->set_props( $post_meta_values );
$ad->set_props(
[
'display_conditions' => $display_conditions,
'visitor_conditions' => $visitor_conditions,
'has_weekdays' => $post_meta_values['weekdays']['enabled'] ?? false,
'weekdays' => $post_meta_values['weekdays']['day_indexes'] ?? [],
]
);
}
/**
* Update ad data. Can be overridden by child classes to load other props.
*
* @param Ad $ad Ad object.
*
* @return void
*/
private function update_post_meta( &$ad ): void {
$post_data = Metabox_Ad::get_post_data();
$ad->set_prop( 'last_save_version', ADVADS_VERSION );
// Pre save.
if ( method_exists( $ad, 'pre_save' ) ) {
$ad->pre_save( $post_data );
}
// Filters to manipulate options or add more to be saved.
do_action( 'advanced-ads-ad-pre-save', $ad, $post_data );
$meta_keys = $ad->get_data_keys();
$meta_keys = array_combine( $meta_keys, $meta_keys );
$meta_values = [];
foreach ( $meta_keys as $meta_key => $prop ) {
$value = method_exists( $ad, "get_$prop" )
? $ad->{"get_$prop"}( 'edit' )
: $ad->get_prop( $prop, 'edit' );
$value = is_string( $value ) ? wp_slash( $value ) : $value;
switch ( $prop ) {
case 'clearfix':
case 'allow_php':
case 'has_weekdays':
case 'reserve_space':
case 'allow_shortcodes':
$value = Formatting::bool_to_string( $value );
break;
case 'description':
$value = esc_textarea( $value );
break;
case 'display_conditions':
case 'visitor_conditions':
$value = WordPress::sanitize_conditions( $value );
if (
'editpost' === Params::post( 'originalaction' ) &&
! isset( $post_data[ $meta_key ] )
) {
$value = [];
}
break;
}
$meta_values[ $meta_key ] = $value;
}
// Convert values to array.
$meta_values['weekdays'] = [
'enabled' => $meta_values['has_weekdays'],
'day_indexes' => $meta_values['weekdays'],
];
unset( $meta_values['has_weekdays'] );
update_post_meta( $ad->get_id(), self::OPTION_METAKEY, $meta_values );
}
/**
* Update ad groups.
*
* @param Ad $ad Ad object.
*
* @return void
*/
private function update_post_term( &$ad ): void {
( new Ad_Group_Relation() )->relate( $ad );
}
/**
* Make sure we store the ad version (to track data changes).
*
* @param Ad $ad Ad object.
*
* @return void
*/
private function update_version( &$ad ): void {
if ( ! metadata_exists( 'post', $ad->get_id(), '_ad_version' ) ) {
update_post_meta( $ad->get_id(), '_ad_version', ADVADS_VERSION );
}
}
/**
* Migrate values to new version
*
* @param array $values Values to migrate.
*
* @return array
*/
private function migrate_values( $values ): array {
$output = wp_parse_args(
$values['output'] ?? [],
[
'position' => 'none',
'clearfix' => false,
'add_wrapper_sizes' => false,
'margin' => [
'top' => 0,
'left' => 0,
'bottom' => 0,
'right' => 0,
],
]
);
foreach ( $output as $key => $value ) {
if ( isset( $values[ $key ] ) ) {
continue;
}
$values[ $key ] = $value;
}
$values['reserve_space'] = $values['reserve_space'] ?? $output['add_wrapper_sizes'];
// Typecast the margin values.
$values['margin'] = array_map( 'intval', $values['margin'] );
// Old values are left, center and right, if none of these we've already migrated.
if ( ! in_array( $values['position'], [ 'left', 'center', 'right' ], true ) ) {
// Ensure we get an array with min two elements.
$position = explode( '_', $values['position'] . '_' );
// Explicitly set clearfix option.
$values['clearfix'] = 'center' !== $position[0] && 'nofloat' === $position[1];
} elseif ( 'center' === $values['position'] ) {
$values['position'] = 'center_nofloat';
} else {
$values['position'] .= $values['clearfix'] ? '_nofloat' : '_float';
}
if ( isset( $values['visitor'] ) && ! isset( $values['visitors'] ) ) {
$values['visitors'] = $values['visitor'];
}
unset( $values['visitor'], $values['output'] );
return $values;
}
}

View File

@@ -0,0 +1,65 @@
<?php
/**
* Ad types manager.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads;
use AdvancedAds\Ads\Types\AMP;
use AdvancedAds\Ads\Types\GAM;
use AdvancedAds\Abstracts\Types;
use AdvancedAds\Ads\Types\Dummy;
use AdvancedAds\Ads\Types\Group;
use AdvancedAds\Ads\Types\Image;
use AdvancedAds\Ads\Types\Plain;
use AdvancedAds\Ads\Types\Content;
use AdvancedAds\Ads\Types\Unknown;
use AdvancedAds\Interfaces\Ad_Type;
defined( 'ABSPATH' ) || exit;
/**
* Ad Types.
*/
class Ad_Types extends Types {
/**
* Hook to filter types.
*
* @var string
*/
protected $hook = 'advanced-ads-ad-types';
/**
* Class for unknown type.
*
* @var string
*/
protected $type_unknown = Unknown::class;
/**
* Type interface to check.
*
* @var string
*/
protected $type_interface = Ad_Type::class;
/**
* Register default types.
*
* @return void
*/
protected function register_default_types(): void {
$this->register_type( Plain::class );
$this->register_type( Dummy::class );
$this->register_type( Content::class );
$this->register_type( Image::class );
$this->register_type( Group::class );
$this->register_type( GAM::class );
$this->register_type( AMP::class );
}
}

View File

@@ -0,0 +1,54 @@
<?php
/**
* This class is responsible to hold all the Ads functionality.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads;
use AdvancedAds\Framework\Interfaces\Initializer_Interface;
defined( 'ABSPATH' ) || exit;
/**
* Ads Ads.
*/
class Ads implements Initializer_Interface {
/**
* Hold factory instance
*
* @var Ad_Factory
*/
public $factory = null;
/**
* Hold repository instance
*
* @var Ad_Repository
*/
public $repository = null;
/**
* Hold types manager
*
* @var Ad_Types
*/
public $types = null;
/**
* Runs this initializer.
*
* @return void
*/
public function initialize(): void {
$this->factory = new Ad_Factory();
$this->types = new Ad_Types();
$this->repository = new Ad_Repository();
$this->types->hooks();
}
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* This class represents the "AMP" ad type.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.2
*/
namespace AdvancedAds\Ads\Types;
use AdvancedAds\Ads\Ad_Dummy;
use AdvancedAds\Interfaces\Ad_Type;
defined( 'ABSPATH' ) || exit;
/**
* Type AMP.
*/
class AMP implements Ad_Type {
/**
* Get the unique identifier (ID) of the ad type.
*
* @return string The unique ID of the ad type.
*/
public function get_id(): string {
return 'amp';
}
/**
* Get the class name of the object as a string.
*
* @return string
*/
public function get_classname(): string {
return Ad_Dummy::class;
}
/**
* Get the title or name of the ad type.
*
* @return string The title of the ad type.
*/
public function get_title(): string {
return __( 'AMP', 'advanced-ads' );
}
/**
* Get a description of the ad type.
*
* @return string The description of the ad type.
*/
public function get_description(): string {
return __( 'Ads that are visible on Accelerated Mobile Pages.', 'advanced-ads' );
}
/**
* Check if this ad type requires premium.
*
* @return bool True if premium is required; otherwise, false.
*/
public function is_premium(): bool {
return true;
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_upgrade_url(): string {
return 'https://wpadvancedads.com/add-ons/responsive-ads/';
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_image(): string {
return ADVADS_BASE_URL . 'assets/img/ad-types/amp.svg';
}
/**
* Check if this ad type has size parameters.
*
* @return bool True if has size parameters; otherwise, false.
*/
public function has_size(): bool {
return true;
}
}

View File

@@ -0,0 +1,161 @@
<?php
/**
* This class represents the "Content" ad type.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads\Types;
use AdvancedAds\Ads\Ad_Content;
use AdvancedAds\Interfaces\Ad_Type;
defined( 'ABSPATH' ) || exit;
/**
* Type Content.
*/
class Content implements Ad_Type {
/**
* Get the unique identifier (ID) of the ad type.
*
* @return string The unique ID of the ad type.
*/
public function get_id(): string {
return 'content';
}
/**
* Get the class name of the object as a string.
*
* @return string
*/
public function get_classname(): string {
return Ad_Content::class;
}
/**
* Get the title or name of the ad type.
*
* @return string The title of the ad type.
*/
public function get_title(): string {
return __( 'Rich Content', 'advanced-ads' );
}
/**
* Get a description of the ad type.
*
* @return string The description of the ad type.
*/
public function get_description(): string {
return __( 'The full content editor from WordPress with all features like shortcodes, image upload or styling, but also simple text/html mode for scripts and code.', 'advanced-ads' );
}
/**
* Check if this ad type requires premium.
*
* @return bool True if premium is required; otherwise, false.
*/
public function is_premium(): bool {
return false;
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_upgrade_url(): string {
return '';
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_image(): string {
return ADVADS_BASE_URL . 'assets/img/ad-types/content.svg';
}
/**
* Check if this ad type has size parameters.
*
* @return bool True if has size parameters; otherwise, false.
*/
public function has_size(): bool {
return true;
}
/**
* Output for the ad parameters metabox
*
* @param Ad_Content $ad Ad instance.
*
* @return void
*/
public function render_parameters( $ad ): void {
$content = $ad->get_content() ?? '';
/**
* Build the tinymc editor
*
* @link http://codex.wordpress.org/Function_Reference/wp_editor
*
* Don't build it when ajax is used; display message and buttons instead
*/
if ( wp_doing_ajax() ) :
// IMPORTANT: Keep textarea on a single line to prevent whitespace from being added to the content.
?>
<textarea id="advads-ad-content-plain" style="display:none;" cols="40" rows="10" name="advanced_ad[content]"><?php echo esc_textarea( $content ); ?></textarea>
<?php
else :
if ( ! user_can_richedit() ) {
$content = esc_textarea( $content );
}
add_filter( 'tiny_mce_before_init', [ $this, 'tiny_mce_before_init' ], 10, 2 );
$args = [
'textarea_name' => 'advanced_ad[content]',
'textarea_rows' => 10,
'drag_drop_upload' => true,
];
wp_editor( $content, 'advanced-ad-parameters-content', $args );
endif;
?>
<br class="clear"/>
<input type="hidden" name="advanced_ad[output][allow_shortcodes]" value="1" />
<?php
include ADVADS_ABSPATH . 'views/admin/metaboxes/ads/ad-info-after-textarea.php';
}
/**
* Add JS into tinyMCE
*
* @param array $init_array TinyMCE arguments.
* @param string $editor_id Editor id.
*
* @return array
*/
public function tiny_mce_before_init( array $init_array, $editor_id ): array {
if ( 'advanced-ad-parameters-content' !== $editor_id ) {
return $init_array;
}
// Add a JS listener to trigger an `input` event for the rich text textarea.
$init_array['setup'] = <<<'JS'
[editor => {
const textarea = document.getElementById('advanced-ad-parameters-content');
editor.on('Dirty', event => {
textarea.value = editor.getContent();
textarea.dispatchEvent(new Event('input'));
});
}][0]
JS;
return $init_array;
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* This class represents the "Dummy" ad type.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads\Types;
use AdvancedAds\Ads\Ad_Dummy;
use AdvancedAds\Interfaces\Ad_Type;
defined( 'ABSPATH' ) || exit;
/**
* Type Dummy.
*/
class Dummy implements Ad_Type {
/**
* Get the unique identifier (ID) of the ad type.
*
* @return string The unique ID of the ad type.
*/
public function get_id(): string {
return 'dummy';
}
/**
* Get the class name of the object as a string.
*
* @return string
*/
public function get_classname(): string {
return Ad_Dummy::class;
}
/**
* Get the title or name of the ad type.
*
* @return string The title of the ad type.
*/
public function get_title(): string {
return __( 'Dummy', 'advanced-ads' );
}
/**
* Get a description of the ad type.
*
* @return string The description of the ad type.
*/
public function get_description(): string {
return __( 'Uses a simple placeholder ad for quick testing.', 'advanced-ads' );
}
/**
* Check if this ad type requires premium.
*
* @return bool True if premium is required; otherwise, false.
*/
public function is_premium(): bool {
return false;
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_upgrade_url(): string {
return '';
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_image(): string {
return ADVADS_BASE_URL . 'assets/img/ad-types/dummy.svg';
}
/**
* Check if this ad type has size parameters.
*
* @return bool True if has size parameters; otherwise, false.
*/
public function has_size(): bool {
return false;
}
/**
* Output for the ad parameters metabox
*
* @param Ad_Dummy $ad Ad instance.
*
* @return void
*/
public function render_parameters( $ad ): void {
if ( ! defined( 'AAT_VERSION' ) ) :
$url = $ad->get_url() ?? home_url();
?>
<span class="label"><?php esc_html_e( 'URL', 'advanced-ads' ); ?></span>
<div>
<input type="text" name="advanced_ad[url]" id="advads-url" class="advads-ad-url" value="<?php echo esc_url( $url ); ?>" />
</div>
<hr/>
<?php
endif;
?>
<img src="<?php echo esc_url( ADVADS_BASE_URL ) . 'public/assets/img/dummy.jpg'; ?>" alt="" width="300" height="250" />
<input type="hidden" name="advanced_ad[width]" value="300" />
<input type="hidden" name="advanced_ad[height]" value="250" />
<?php
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* This class represents the "GAM" ad type.
*
* @package AdvancedAds\GAM
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.2
*/
namespace AdvancedAds\Ads\Types;
use AdvancedAds\Ads\Ad_Dummy;
use AdvancedAds\Interfaces\Ad_Type;
defined( 'ABSPATH' ) || exit;
/**
* Type GAM.
*/
class GAM implements Ad_Type {
/**
* Get the unique identifier (ID) of the ad type.
*
* @return string The unique ID of the ad type.
*/
public function get_id(): string {
return 'gam';
}
/**
* Get the class name of the object as a string.
*
* @return string
*/
public function get_classname(): string {
return Ad_Dummy::class;
}
/**
* Get the title or name of the ad type.
*
* @return string The title of the ad type.
*/
public function get_title(): string {
return __( 'Google Ad Manager', 'advanced-ads' );
}
/**
* Get a description of the ad type.
*
* @return string The description of the ad type.
*/
public function get_description(): string {
return __( 'Load ad units directly from your Google Ad Manager account.', 'advanced-ads' );
}
/**
* Check if this ad type requires premium.
*
* @return bool True if premium is required; otherwise, false.
*/
public function is_premium(): bool {
return true;
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_upgrade_url(): string {
return 'https://wpadvancedads.com/add-ons/google-ad-manager/';
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_image(): string {
return ADVADS_BASE_URL . 'assets/img/ad-types/gam.svg';
}
/**
* Check if this ad type has size parameters.
*
* @return bool True if has size parameters; otherwise, false.
*/
public function has_size(): bool {
return true;
}
}

View File

@@ -0,0 +1,125 @@
<?php
/**
* This class represents the "Group" ad type.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads\Types;
use AdvancedAds\Constants;
use AdvancedAds\Ads\Ad_Group;
use AdvancedAds\Interfaces\Ad_Type;
defined( 'ABSPATH' ) || exit;
/**
* Type Group.
*/
class Group implements Ad_Type {
/**
* Get the unique identifier (ID) of the ad type.
*
* @return string The unique ID of the ad type.
*/
public function get_id(): string {
return 'group';
}
/**
* Get the class name of the object as a string.
*
* @return string
*/
public function get_classname(): string {
return Ad_Group::class;
}
/**
* Get the title or name of the ad type.
*
* @return string The title of the ad type.
*/
public function get_title(): string {
return __( 'Ad Group', 'advanced-ads' );
}
/**
* Get a description of the ad type.
*
* @return string The description of the ad type.
*/
public function get_description(): string {
return __( 'Choose an existing ad group. Use this type when you want to assign the same display and visitor conditions to all ads in that group.', 'advanced-ads' );
}
/**
* Check if this ad type requires premium.
*
* @return bool True if premium is required; otherwise, false.
*/
public function is_premium(): bool {
return false;
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_upgrade_url(): string {
return '';
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_image(): string {
return ADVADS_BASE_URL . 'assets/img/ad-types/group.svg';
}
/**
* Check if this ad type has size parameters.
*
* @return bool True if has size parameters; otherwise, false.
*/
public function has_size(): bool {
return true;
}
/**
* Output for the ad parameters metabox
*
* @param Ad_Group $ad Ad instance.
*
* @return void
*/
public function render_parameters( $ad ): void {
?>
<label for="advads-group-id" class="label">
<?php esc_html_e( 'Ad Group', 'advanced-ads' ); ?>
</label>
<div>
<?php
wp_dropdown_categories(
[
'name' => 'advanced_ad[output][group_id]',
'id' => 'advads-group-id',
'selected' => $ad->get_group_id() ?? '',
'taxonomy' => Constants::TAXONOMY_GROUP,
'hide_empty' => false,
'show_option_none' => esc_html__( 'Select a group', 'advanced-ads' ),
]
);
?>
</div>
<hr/>
<?php
}
}

View File

@@ -0,0 +1,292 @@
<?php
/**
* This class represents the "Image" ad type.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads\Types;
use AdvancedAds\Ads\Ad_Image;
use AdvancedAds\Interfaces\Ad_Type;
use AdvancedAds\Utilities\WordPress;
defined( 'ABSPATH' ) || exit;
/**
* Type Image.
*/
class Image implements Ad_Type {
/**
* Get the unique identifier (ID) of the ad type.
*
* @return string The unique ID of the ad type.
*/
public function get_id(): string {
return 'image';
}
/**
* Get the class name of the object as a string.
*
* @return string
*/
public function get_classname(): string {
return Ad_Image::class;
}
/**
* Get the title or name of the ad type.
*
* @return string The title of the ad type.
*/
public function get_title(): string {
return __( 'Image Ad', 'advanced-ads' );
}
/**
* Get a description of the ad type.
*
* @return string The description of the ad type.
*/
public function get_description(): string {
return __( 'Ads in various image formats.', 'advanced-ads' );
}
/**
* Check if this ad type requires premium.
*
* @return bool True if premium is required; otherwise, false.
*/
public function is_premium(): bool {
return false;
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_upgrade_url(): string {
return '';
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_image(): string {
return ADVADS_BASE_URL . 'assets/img/ad-types/image.svg';
}
/**
* Check if this ad type has size parameters.
*
* @return bool True if has size parameters; otherwise, false.
*/
public function has_size(): bool {
return true;
}
/**
* Render preview on the ad overview list
*
* @param Ad_Image $ad Ad instance.
*
* @TODO: refactor and test
*
* @return void
*/
public function render_preview( Ad_Image $ad ): void {
if ( empty( $ad->get_image_id() ) ) {
return;
}
list( $src, $width, $height ) = wp_get_attachment_image_src( $ad->get_image_id(), 'medium', true );
$preview_size_small = 50;
$preview_size_large = 200;
// Scale down width or height for the preview.
if ( $width > $height ) {
$preview_height = ceil( $height / ( $width / $preview_size_small ) );
$preview_width = $preview_size_small;
$tooltip_height = ceil( $height / ( $width / $preview_size_large ) );
$tooltip_width = $preview_size_large;
} else {
$preview_width = ceil( $width / ( $height / $preview_size_small ) );
$preview_height = $preview_size_small;
$tooltip_width = ceil( $width / ( $height / $preview_size_large ) );
$tooltip_height = $preview_size_large;
}
$preview_hwstring = image_hwstring( $preview_width, $preview_height );
$tooltip_hwstring = image_hwstring( $tooltip_width, $tooltip_height );
$alt = wp_strip_all_tags( get_post_meta( $ad->get_image_id(), '_wp_attachment_image_alt', true ) );
include ADVADS_ABSPATH . 'admin/views/ad-list/preview-image.php';
}
/**
* Output for the ad parameters metabox
*
* @param Ad_Image $ad Ad instance.
*
* @return void
*/
public function render_parameters( $ad ): void {
$id = $ad->get_image_id() ?? '';
$url = $ad->get_url() ?? '';
$edit_link = $id ? get_edit_post_link( $id ) : '';
?><span class="label">
<button href="#" class="advads_image_upload button advads-button-secondary" type="button"
data-uploader-title="<?php esc_attr_e( 'Insert File', 'advanced-ads' ); ?>"
data-uploader-button-text="<?php esc_attr_e( 'Insert', 'advanced-ads' ); ?>"
onclick="return false;">
<?php esc_html_e( 'Select image', 'advanced-ads' ); ?>
</button>
</span>
<div>
<input type="hidden" name="advanced_ad[output][image_id]" value="<?php echo absint( $id ); ?>" id="advads-image-id"/>
<div id="advads-image-preview">
<?php $this->create_image_tag( $id, $ad ); ?>
</div>
<a id="advads-image-edit-link" class="<?php echo ! $edit_link ? 'hidden' : ''; ?>" href="<?php echo esc_url( $edit_link ); ?>"><span class="dashicons dashicons-edit"></span></a>
</div>
<hr/>
<?php
if ( ! defined( 'AAT_VERSION' ) ) :
?>
<label for="advads-url" class="label"><?php esc_html_e( 'URL', 'advanced-ads' ); ?></label>
<div>
<input type="url" name="advanced_ad[url]" id="advads-url" class="advads-ad-url" value="<?php echo esc_url( $url ); ?>" placeholder="https://www.example.com/"/>
<p class="description">
<?php esc_html_e( 'Link to target site including http(s)', 'advanced-ads' ); ?>
</p>
</div>
<hr/>
<?php
endif;
}
/**
* Generate a string with the original image size for output in the backend
* Only show, if different from entered image sizes
*
* @param Ad_Image $ad Ad instance.
*
* @return string empty, if the entered size is the same as the original size
*/
public function show_original_image_size( Ad_Image $ad ) {
$attachment_id = $ad->get_image_id() ?? '';
$attachment = wp_get_attachment_image_src( $attachment_id, 'full' );
if ( $attachment ) {
list( $src, $width, $height ) = $attachment;
?>
<p class="description">
<?php
if ( $ad->get_width() !== $width || $ad->get_height() !== $height ) :
printf(
/* translators: $s is a size string like "728 x 90". */
esc_attr__( 'Original size: %s', 'advanced-ads' ),
esc_html( $width ) . '&nbsp;x&nbsp;' . esc_html( $height )
);
?>
</p>
<?php
endif;
}
return '';
}
/**
* Render image tag
*
* @param int $attachment_id Attachment id.
* @param Ad_Image $ad Ad instance.
*
* @return void
*/
public function create_image_tag( $attachment_id, $ad ): void {
global $wp_current_filter;
$style = '';
$image = wp_get_attachment_image_src( $attachment_id, 'full' );
// Early bail!!
if ( ! $image ) {
return;
}
list( $src, $width, $height ) = $image;
// Override image size with the size given in ad options, but in frontend only.
if ( ! is_admin() || wp_doing_ajax() ) {
$width = $ad->get_width();
$height = $ad->get_height();
}
$hwstring = image_hwstring( $width, $height );
$alt = trim( esc_textarea( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) );
// TODO: use an array for attributes so they are simpler to extend.
$sizes = '';
$srcset = '';
$more_attributes = $srcset;
// Create srcset and sizes attributes if we are in the the_content filter and in WordPress 4.4.
if (
isset( $wp_current_filter )
&& in_array( 'the_content', $wp_current_filter, true )
&& ! defined( 'ADVADS_DISABLE_RESPONSIVE_IMAGES' )
) {
if ( function_exists( 'wp_get_attachment_image_srcset' ) ) {
$srcset = wp_get_attachment_image_srcset( $attachment_id, 'full' );
}
if ( function_exists( 'wp_get_attachment_image_sizes' ) ) {
$sizes = wp_get_attachment_image_sizes( $attachment_id, 'full' );
}
if ( $srcset && $sizes ) {
$more_attributes .= ' srcset="' . $srcset . '" sizes="' . $sizes . '"';
}
}
// TODO: move to classes/compabtility.php when we have a simpler filter for additional attributes
// Compabitility with WP Smush.
// Disables their lazy load for image ads because it caused them to not show up in certain positions at all.
$wp_smush_settings = get_option( 'wp-smush-settings' );
if ( isset( $wp_smush_settings['lazy_load'] ) && $wp_smush_settings['lazy_load'] ) {
$more_attributes .= ' class="no-lazyload"';
}
// Add css rule to be able to center the ad.
if ( strpos( $ad->get_position(), 'center' ) === 0 ) {
$style .= 'display: inline-block;';
}
$style = apply_filters( 'advanced-ads-ad-image-tag-style', $style );
$style = '' !== $style ? 'style="' . $style . '"' : '';
$more_attributes = apply_filters( 'advanced-ads-ad-image-tag-attributes', $more_attributes );
$more_attributes .= ' ' . $hwstring . ' ' . $style;
$img = sprintf( '<img src="%s" alt="%s" %s />', esc_url( $src ), esc_attr( $alt ), $more_attributes );
// Add 'loading' attribute if applicable, available from WP 5.5.
if (
$wp_current_filter
&& function_exists( 'wp_lazy_loading_enabled' )
&& wp_lazy_loading_enabled( 'img', current_filter() )
&& ! strpos( $more_attributes, 'loading=' )
) {
// Optimize image HTML tag with loading attributes based on WordPress filter context.
$img = WordPress::img_tag_add_loading_attr( $img, current_filter() );
}
echo $img; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}

View File

@@ -0,0 +1,235 @@
<?php
/**
* This class represents the "Plain" ad type.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads\Types;
use AdvancedAds\Ads\Ad_Plain;
use AdvancedAds\Interfaces\Ad_Type;
use AdvancedAds\Utilities\Conditional;
defined( 'ABSPATH' ) || exit;
/**
* Type Plain.
*/
class Plain implements Ad_Type {
/**
* Get the unique identifier (ID) of the ad type.
*
* @return string The unique ID of the ad type.
*/
public function get_id(): string {
return 'plain';
}
/**
* Get the class name of the object as a string.
*
* @return string
*/
public function get_classname(): string {
return Ad_Plain::class;
}
/**
* Get the title or name of the ad type.
*
* @return string The title of the ad type.
*/
public function get_title(): string {
return __( 'Plain Text and Code', 'advanced-ads' );
}
/**
* Get a description of the ad type.
*
* @return string The description of the ad type.
*/
public function get_description(): string {
return __( 'Any ad network, Amazon, customized AdSense codes, shortcodes, and code like JavaScript, HTML or PHP.', 'advanced-ads' );
}
/**
* Check if this ad type requires premium.
*
* @return bool True if premium is required; otherwise, false.
*/
public function is_premium(): bool {
return false;
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_upgrade_url(): string {
return '';
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_image(): string {
return ADVADS_BASE_URL . 'assets/img/ad-types/plain.svg';
}
/**
* Check if this ad type has size parameters.
*
* @return bool True if has size parameters; otherwise, false.
*/
public function has_size(): bool {
return true;
}
/**
* Output for the ad parameters metabox
*
* @param Ad_Plain $ad Ad instance.
*
* @return void
*/
public function render_parameters( $ad ): void {
$content = $ad->get_content() ?? '';
?>
<p class="description">
<?php esc_html_e( 'Insert plain text or code into this field.', 'advanced-ads' ); ?>
</p>
<?php $this->error_unfiltered_html( $ad ); ?>
<textarea
id="advads-ad-content-plain"
cols="40"
rows="10"
name="advanced_ad[content]"
><?php echo esc_textarea( $content ); ?></textarea>
<?php
include ADVADS_ABSPATH . 'views/admin/metaboxes/ads/ad-info-after-textarea.php';
$this->render_php_allow( $ad );
$this->render_shortcodes_allow( $ad );
?>
<?php
}
/**
* Render php output field
*
* @param Ad_Plain $ad Ad instance.
*
* @return void
*/
private function render_php_allow( $ad ) {
?>
<label class="label" for="advads-parameters-php">
<?php esc_html_e( 'Allow PHP', 'advanced-ads' ); ?>
</label>
<div>
<input type="hidden" name="advanced_ad[allow_php]" value="off">
<input id="advads-parameters-php" type="checkbox" name="advanced_ad[allow_php]" value="on"<?php checked( $ad->is_php_allowed() ); ?><?php disabled( ! Conditional::is_php_allowed() ); ?> />
<span class="advads-help">
<span class="advads-tooltip">
<?php
echo wp_kses(
__( 'Execute PHP code (wrapped in <code>&lt;?php ?&gt;</code>)', 'advanced-ads' ),
[
'code' => [],
]
);
?>
</span>
</span>
<?php if ( ! Conditional::is_php_allowed() ) : ?>
<p class="advads-notice-inline advads-error">
<?php
printf(
/* translators: The name of the constant preventing PHP execution */
esc_html__( 'Executing PHP code has been disallowed by %s', 'advanced-ads' ),
sprintf( '<code>%s</code>', defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ? 'DISALLOW_FILE_EDIT' : 'ADVANCED_ADS_DISALLOW_PHP' )
);
?>
</p>
<?php else : ?>
<p class="advads-notice-inline advads-error" id="advads-allow-php-warning" style="display:none;">
<?php esc_html_e( 'Using PHP code can be dangerous. Please make sure you know what you are doing.', 'advanced-ads' ); ?>
</p>
<?php endif; ?>
<p class="advads-notice-inline advads-error" id="advads-parameters-php-warning" style="display:none;">
<?php esc_html_e( 'No PHP tag detected in your code.', 'advanced-ads' ); ?> <?php esc_html_e( 'Uncheck this checkbox for improved performance.', 'advanced-ads' ); ?>
</p>
</div>
<hr/>
<?php
}
/**
* Render allow shortcodes field.
*
* @param Ad_Plain $ad Ad instance.
*
* @return void
*/
private function render_shortcodes_allow( $ad ): void {
$allow_shortcodes = absint( $ad->is_shortcode_allowed() );
?>
<label class="label"
for="advads-parameters-shortcodes"><?php esc_html_e( 'Execute shortcodes', 'advanced-ads' ); ?></label>
<div>
<input type="hidden" name="advanced_ad[output][allow_shortcodes]" value="off"/>
<input id="advads-parameters-shortcodes" type="checkbox" name="advanced_ad[output][allow_shortcodes]" value="on" <?php checked( $allow_shortcodes ); ?>/>
<p class="advads-notice-inline advads-error" id="advads-parameters-shortcodes-warning"
style="display:none;"><?php esc_html_e( 'No shortcode detected in your code.', 'advanced-ads' ); ?> <?php esc_html_e( 'Uncheck this checkbox for improved performance.', 'advanced-ads' ); ?></p>
</div>
<hr/>
<?php
}
/**
* Check if we're on an ad edit screen, if yes and the user does not have `unfiltered_html` permissions,
* show an admin notice.
*
* @param Ad_Plain $ad Ad instance.
*
* @return void
*/
private function error_unfiltered_html( $ad ): void {
$author_id = absint( get_post_field( 'post_author', $ad->get_id() ) );
$user = wp_get_current_user();
$current_user_id = $user->ID;
if ( Conditional::can_author_unfiltered_html( $author_id ) ) {
return;
}
?>
<p class="advads-notice-inline advads-error">
<?php
if ( $author_id === $current_user_id ) {
esc_html_e( 'You do not have sufficient permissions to include all HTML tags.', 'advanced-ads' );
} else {
esc_html_e( 'The creator of the ad does not have sufficient permissions to include all HTML tags.', 'advanced-ads' );
if (
current_user_can( 'unfiltered_html' )
&& Conditional::has_user_role_on_site()
&& ! empty( $user->caps['administrator'] ) // A superadmin won't be listed in the author dropdown if he's registered as something other than admin on a blog of the network.
) {
printf( '<button type="button" onclick="(()=>Advanced_Ads_Admin.reassign_ad(%d))();" class="button button-primary">%s</button>', esc_attr( $current_user_id ), esc_html__( 'Assign ad to me', 'advanced-ads' ) );
}
}
?>
<a href="https://wpadvancedads.com/manual/ad-types/#Plain_Text_and_Code" class="advads-manual-link" target="_blank" rel="noopener">
<?php esc_html_e( 'Manual', 'advanced-ads' ); ?>
</a>
</p>
<?php
}
}

View File

@@ -0,0 +1,130 @@
<?php
/**
* This class represents the "Unknown" ad type.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.0
*/
namespace AdvancedAds\Ads\Types;
use AdvancedAds\Ads\Ad_Dummy;
use AdvancedAds\Interfaces\Ad_Type;
defined( 'ABSPATH' ) || exit;
/**
* Type Unknown.
*/
class Unknown implements Ad_Type {
/**
* Hold type data.
*
* @var array
*/
private $data = [];
/**
* The constructor.
*
* @param array $data Array of type data.
*/
public function __construct( array $data ) {
$this->data = $data;
}
/**
* Get the unique identifier (ID) of the ad type.
*
* @return string The unique ID of the ad type.
*/
public function get_id(): string {
return $this->data['id'] ?? 'default';
}
/**
* Get the class name of the object as a string.
*
* @return string
*/
public function get_classname(): string {
return $this->data['classname'] ?? Ad_Dummy::class;
}
/**
* Get the title or name of the ad type.
*
* @return string The title of the ad type.
*/
public function get_title(): string {
return $this->data['title'] ?? __( 'Unknown type', 'advanced-ads' );
}
/**
* Get a description of the ad type.
*
* @return string The description of the ad type.
*/
public function get_description(): string {
return $this->data['description'] ?? __( 'No description', 'advanced-ads' );
}
/**
* Check if this ad type requires premium.
*
* @return bool True if premium is required; otherwise, false.
*/
public function is_premium(): bool {
return boolval( $this->data['is_upgrade'] ?? $this->data['is_premium'] ?? true );
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_upgrade_url(): string {
return $this->data['upgrade_url'] ?? '';
}
/**
* Get the URL for upgrading to this ad type.
*
* @return string The upgrade URL for the ad type.
*/
public function get_image(): string {
if ( isset( $this->data['icon'] ) && ! empty( $this->data['icon'] ) ) {
return $this->data['icon'];
}
$icon_path = sprintf( 'assets/img/ad-types/%s.svg', $this->get_id() );
if ( ! file_exists( ADVADS_ABSPATH . $icon_path ) ) {
$icon_path = 'assets/img/ad-types/empty.svg';
}
return ADVADS_BASE_URL . $icon_path;
}
/**
* Check if this ad type has size parameters.
*
* @return bool True if has size parameters; otherwise, false.
*/
public function has_size(): bool {
return true;
}
/**
* Output for the ad parameters metabox
*
* @param Ad $ad Ad instance.
*
* @return void
*/
public function render_parameters( $ad ): void {
if ( isset( $this->data['render_parameters'] ) && is_callable( $this->data['render_parameters'] ) ) {
$this->data['render_parameters']( $ad );
}
}
}