- 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>
407 lines
10 KiB
PHP
Executable File
407 lines
10 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* This class is serving as the base for various placement types and providing a foundation for defining common placement attributes and methods.
|
|
*
|
|
* @package AdvancedAds
|
|
* @author Advanced Ads <info@wpadvancedads.com>
|
|
* @since 1.48.0
|
|
*/
|
|
|
|
namespace AdvancedAds\Abstracts;
|
|
|
|
use RuntimeException;
|
|
use AdvancedAds\Traits;
|
|
use AdvancedAds\Constants;
|
|
use AdvancedAds\Frontend\Stats;
|
|
use AdvancedAds\Framework\Utilities\Formatting;
|
|
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
/**
|
|
* Placement.
|
|
*/
|
|
class Placement extends Data {
|
|
|
|
use Traits\Entity;
|
|
use Traits\Wrapper;
|
|
|
|
/**
|
|
* This is the object type.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $object_type = 'placement';
|
|
|
|
/**
|
|
* This is the item object.
|
|
*
|
|
* @var Ad|Group|null
|
|
*/
|
|
protected $item_object = null;
|
|
|
|
/**
|
|
* This is the item type.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $item_type = '';
|
|
|
|
/**
|
|
* Core data for this object. Name value pairs (name + default value).
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $data = [
|
|
'title' => '',
|
|
'content' => '',
|
|
'type' => 'default',
|
|
'slug' => '',
|
|
'status' => '',
|
|
'item' => '',
|
|
'display' => [],
|
|
'visitors' => [],
|
|
];
|
|
|
|
/**
|
|
* Get the placement if ID is passed, otherwise the placement is new and empty.
|
|
*
|
|
* @param Placement|WP_Post|int $placement Placement to init.
|
|
*/
|
|
public function __construct( $placement = 0 ) {
|
|
parent::__construct();
|
|
|
|
$this->set_placement_id( $placement );
|
|
$this->data_store = wp_advads_get_placement_repository();
|
|
|
|
if ( $this->get_id() > 0 ) {
|
|
$this->data_store->read( $this );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the placement ID depending on what was passed.
|
|
*
|
|
* @param Placement|WP_Post|int $placement Placement instance, post instance or numeric.
|
|
*
|
|
* @return void
|
|
*/
|
|
private function set_placement_id( $placement ): void {
|
|
if ( is_numeric( $placement ) && $placement > 0 ) {
|
|
$this->set_id( $placement );
|
|
} elseif ( $placement instanceof self ) {
|
|
$this->set_id( absint( $placement->get_id() ) );
|
|
} elseif ( ! empty( $placement->ID ) ) {
|
|
$this->set_id( absint( $placement->ID ) );
|
|
} else {
|
|
$this->set_object_read( true );
|
|
}
|
|
}
|
|
|
|
/* Getter ------------------- */
|
|
|
|
/**
|
|
* Get item.
|
|
*
|
|
* @param string $context What the value is for. Valid values are view and edit.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_item( $context = 'view' ): string {
|
|
return $this->get_prop( 'item', $context );
|
|
}
|
|
|
|
/**
|
|
* Get the display conditions for the placement.
|
|
*
|
|
* @param string $context What the value is for. Valid values are view and edit.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_display_conditions( $context = 'view' ): array {
|
|
return $this->get_prop( 'display', $context );
|
|
}
|
|
|
|
/**
|
|
* Get the visitor conditions for the placement.
|
|
*
|
|
* @param string $context What the value is for. Valid values are view and edit.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_visitor_conditions( $context = 'view' ): array {
|
|
return $this->get_prop( 'visitors', $context );
|
|
}
|
|
|
|
/* Setter ------------------- */
|
|
|
|
/**
|
|
* Set item.
|
|
*
|
|
* @param string $item Placement item.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function set_item( $item ): void {
|
|
$this->set_prop( 'item', $item );
|
|
}
|
|
|
|
/**
|
|
* Set display conditions.
|
|
*
|
|
* @param string $conditions Placement conditions.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function set_display_conditions( $conditions ): void {
|
|
$this->set_prop( 'display', $conditions );
|
|
}
|
|
|
|
/**
|
|
* Set conditions.
|
|
*
|
|
* @param string $conditions Placement conditions.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function set_visitor_conditions( $conditions ): void {
|
|
$this->set_prop( 'visitors', $conditions );
|
|
}
|
|
|
|
/* Conditional ------------------- */
|
|
|
|
/**
|
|
* Check if placement item is allowed
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function is_item_allowed(): bool {
|
|
$item_type = $this->get_item_type();
|
|
$item_object = $this->get_item_object();
|
|
|
|
return $this->get_type_object()
|
|
->is_entity_allowed( $item_object->get_type(), $item_type );
|
|
}
|
|
|
|
/**
|
|
* Determines whether the placement can be displayed.
|
|
*
|
|
* @return bool True if the placement can be displayed, false otherwise.
|
|
*/
|
|
public function can_display(): bool {
|
|
return apply_filters( 'advanced-ads-can-display-placement', true, $this->get_id(), $this );
|
|
}
|
|
|
|
/**
|
|
* Determines whether the placement has cache busting enabled.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function has_cache_busting(): bool {
|
|
$value = $this->get_prop( 'cache-busting' );
|
|
return 'auto' === $value || Formatting::string_to_bool( $value );
|
|
}
|
|
|
|
/* Additional Methods ------------------- */
|
|
|
|
/**
|
|
* Prepares the output for the placement.
|
|
*
|
|
* @return mixed The prepared output or the overridden return value.
|
|
*/
|
|
public function prepare_output(): string {
|
|
// Early bail!!
|
|
if ( empty( $this->get_item_object() ) || Constants::ENTITY_PLACEMENT === $this->get_item_type() || 'publish' !== $this->get_status() ) {
|
|
return '';
|
|
}
|
|
|
|
$prefix = wp_advads()->get_frontend_prefix();
|
|
$ad_args = $this->get_prop( 'ad_args' );
|
|
$item_type = $this->get_item_type();
|
|
|
|
// Inject options.
|
|
$this->item_object->set_prop_temp( 'ad_args', $ad_args );
|
|
|
|
if ( ! $this->is_type( 'header' ) ) {
|
|
$class = $ad_args['output']['class'] ?? [];
|
|
|
|
if ( ! in_array( $prefix . $this->get_slug(), $class, true ) ) {
|
|
$class[] = $prefix . $this->get_slug();
|
|
}
|
|
|
|
$ad_args['output'] = $ad_args['output'] ?? [];
|
|
$ad_args['output']['class'] = $class;
|
|
}
|
|
|
|
// Create placement id for various features like ajax ads.
|
|
$ad_args['output']['placement_id'] = $this->get_id();
|
|
|
|
// Inject options.
|
|
$this->item_object->set_prop_temp( 'ad_args', $ad_args );
|
|
$this->item_object->set_parent( $this );
|
|
|
|
$method = Constants::ENTITY_AD === $item_type ? 'ad' : 'group';
|
|
$args = wp_advads_default_entity_arguments( $method, $this->item_object->get_id(), $ad_args );
|
|
$overridden_entity = Constants::ENTITY_AD === $item_type
|
|
? apply_filters( 'advanced-ads-ad-select-override-by-ad', false, $this->item_object, $args )
|
|
: apply_filters( 'advanced-ads-ad-select-override-by-group', false, $this->item_object, $this->item_object->get_ordered_ad_ids(), $args );
|
|
|
|
if ( false !== $overridden_entity ) {
|
|
return $overridden_entity;
|
|
}
|
|
|
|
$output = $this->item_object->can_display() ? $this->item_object->output() : '';
|
|
|
|
// Maintain Stats.
|
|
if ( $output ) {
|
|
Stats::get()->add_entity( 'placement', $this->get_id(), $this->get_title() );
|
|
Stats::get()->add_entity( $this->get_item_type(), $this->item_object->get_id(), $this->item_object->get_title(), $this->get_id() );
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* Update placement item.
|
|
*
|
|
* @param string $new_item Placement item id.
|
|
*
|
|
* @throws \RuntimeException If the new item is equal to the old item or if the item type is not allowed for the placement type.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function update_item( $new_item ) {
|
|
list( 'type' => $item_type, 'id' => $item_id ) = $this->get_item_parts( $this->get_item() );
|
|
list( 'type' => $new_item_type, 'id' => $new_item_id ) = $this->get_item_parts( $new_item );
|
|
|
|
if ( $new_item_id === $item_id ) {
|
|
throw new RuntimeException( 'New item is equal to old item.' );
|
|
}
|
|
|
|
$new_item_object = 'ad' === $new_item_type
|
|
? wp_advads_get_ad( $new_item_id )
|
|
: wp_advads_get_group( $new_item_id );
|
|
|
|
$is_allowed = $this->get_type_object()
|
|
->is_entity_allowed( $new_item_object->get_type(), $new_item_type );
|
|
|
|
if ( ! $is_allowed ) {
|
|
throw new RuntimeException(
|
|
sprintf(
|
|
/* translators: 1: Entity type 2: Item type 3: Placement title */
|
|
esc_html__( '%1$s type "%2$s" not allowed for placement type "%3$s"', 'advanced-ads' ),
|
|
strtoupper( $new_item_type ), // phpcs:ignore
|
|
$new_item_object->get_type(), // phpcs:ignore
|
|
$this->get_type_object()->get_title() // phpcs:ignore
|
|
)
|
|
);
|
|
}
|
|
|
|
if ( ! update_post_meta( $this->get_id(), 'item', $new_item ) ) {
|
|
throw new RuntimeException( 'Can\'t update item.' );
|
|
}
|
|
|
|
return $new_item_object;
|
|
}
|
|
|
|
/**
|
|
* Remove placement item.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function remove_item(): bool {
|
|
return delete_post_meta( $this->get_id(), 'item' );
|
|
}
|
|
|
|
/**
|
|
* Get placement item type
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_item_type(): string {
|
|
$this->get_item_object();
|
|
|
|
return $this->item_type;
|
|
}
|
|
|
|
/**
|
|
* Get placement item object
|
|
*
|
|
* @return Ad|Group|bool|null
|
|
*/
|
|
public function get_item_object() {
|
|
global $sitepress;
|
|
|
|
// Early bail!!
|
|
if ( empty( $this->get_item() ) ) {
|
|
return $this->item_object;
|
|
}
|
|
|
|
list( 'type' => $item_type, 'id' => $item_id ) = $this->get_item_parts( $this->get_item() );
|
|
|
|
if ( Constants::ENTITY_AD === $item_type && defined( 'ICL_SITEPRESS_VERSION' ) ) {
|
|
/**
|
|
* Deliver the translated version of an ad if set up with WPML.
|
|
* If an ad is not translated, show the ad in the original language when this is the selected option in the WPML settings.
|
|
*
|
|
* @source https://wpml.org/wpml-hook/wpml_object_id/
|
|
* @source https://wpml.org/forums/topic/backend-custom-post-types-page-overview-with-translation-options/
|
|
*/
|
|
$item_id = apply_filters( 'wpml_object_id', $item_id, 'advanced_ads', $sitepress->is_display_as_translated_post_type( 'advanced_ads' ) );
|
|
}
|
|
|
|
$this->item_type = $item_type;
|
|
$this->item_object = 'ad' === $item_type
|
|
? wp_advads_get_ad( $item_id )
|
|
: wp_advads_get_group( $item_id );
|
|
|
|
if ( $this->item_object ) {
|
|
$this->item_object->set_parent( $this );
|
|
}
|
|
|
|
return $this->item_object;
|
|
}
|
|
|
|
/**
|
|
* Get placement type object
|
|
*
|
|
* @return Placement_Type|bool
|
|
*/
|
|
public function get_type_object() {
|
|
if ( ! wp_advads_has_placement_type( $this->get_type() ) ) {
|
|
wp_advads_create_placement_type( $this->get_type() );
|
|
}
|
|
|
|
return wp_advads_get_placement_type( $this->get_type() );
|
|
}
|
|
|
|
/**
|
|
* Get the item parts
|
|
*
|
|
* @param string $item Placement item.
|
|
*
|
|
* @return array
|
|
*/
|
|
private function get_item_parts( $item ): array {
|
|
$item_parts = explode( '_', $item );
|
|
|
|
return [
|
|
'type' => trim( $item_parts[0] ),
|
|
'id' => absint( $item_parts[1] ?? 0 ),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get the placement edit link
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function get_edit_link() {
|
|
return add_query_arg(
|
|
[
|
|
'post_type' => Constants::POST_TYPE_PLACEMENT,
|
|
],
|
|
admin_url( 'edit.php#modal-placement-edit-' . $this->get_id() )
|
|
);
|
|
}
|
|
}
|