feat(api): implement javascript-first architecture for cache compatibility
- Add REST endpoint GET /roi-theme/v1/adsense-placement/visibility - Add Domain layer: UserContext, VisibilityDecision, AdsenseSettings VOs - Add Application layer: CheckAdsenseVisibilityUseCase - Add Infrastructure: AdsenseVisibilityChecker, Controller, Enqueuer - Add JavaScript controller with localStorage caching - Add test plan for production validation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
163
Public/AdsensePlacement/Domain/ValueObjects/AdsenseSettings.php
Normal file
163
Public/AdsensePlacement/Domain/ValueObjects/AdsenseSettings.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ROITheme\Public\AdsensePlacement\Domain\ValueObjects;
|
||||
|
||||
/**
|
||||
* Value Object que encapsula la configuracion de AdSense relevante para visibilidad.
|
||||
*
|
||||
* Inmutable despues de construccion. Sin dependencias de WordPress.
|
||||
*
|
||||
* @package ROITheme\Public\AdsensePlacement\Domain\ValueObjects
|
||||
*/
|
||||
final class AdsenseSettings
|
||||
{
|
||||
/**
|
||||
* @param bool $isEnabled Si AdSense esta activo globalmente
|
||||
* @param bool $showOnDesktop Si se muestra en desktop
|
||||
* @param bool $showOnMobile Si se muestra en mobile
|
||||
* @param bool $hideForLoggedIn Si se oculta para usuarios logueados
|
||||
* @param bool $javascriptFirstMode Si el modo JS-first esta activo
|
||||
* @param array<int> $excludedCategoryIds IDs de categorias excluidas
|
||||
* @param array<int> $excludedPostIds IDs de posts excluidos
|
||||
* @param array<string> $excludedPostTypes Post types excluidos
|
||||
*/
|
||||
public function __construct(
|
||||
private bool $isEnabled,
|
||||
private bool $showOnDesktop,
|
||||
private bool $showOnMobile,
|
||||
private bool $hideForLoggedIn,
|
||||
private bool $javascriptFirstMode,
|
||||
private array $excludedCategoryIds = [],
|
||||
private array $excludedPostIds = [],
|
||||
private array $excludedPostTypes = []
|
||||
) {
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->isEnabled;
|
||||
}
|
||||
|
||||
public function showOnDesktop(): bool
|
||||
{
|
||||
return $this->showOnDesktop;
|
||||
}
|
||||
|
||||
public function showOnMobile(): bool
|
||||
{
|
||||
return $this->showOnMobile;
|
||||
}
|
||||
|
||||
public function hideForLoggedIn(): bool
|
||||
{
|
||||
return $this->hideForLoggedIn;
|
||||
}
|
||||
|
||||
public function isJavascriptFirstMode(): bool
|
||||
{
|
||||
return $this->javascriptFirstMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int>
|
||||
*/
|
||||
public function getExcludedCategoryIds(): array
|
||||
{
|
||||
return $this->excludedCategoryIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int>
|
||||
*/
|
||||
public function getExcludedPostIds(): array
|
||||
{
|
||||
return $this->excludedPostIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getExcludedPostTypes(): array
|
||||
{
|
||||
return $this->excludedPostTypes;
|
||||
}
|
||||
|
||||
public function isPostExcluded(int $postId): bool
|
||||
{
|
||||
return in_array($postId, $this->excludedPostIds, true);
|
||||
}
|
||||
|
||||
public function isPostTypeExcluded(string $postType): bool
|
||||
{
|
||||
return in_array($postType, $this->excludedPostTypes, true);
|
||||
}
|
||||
|
||||
public function isCategoryExcluded(int $categoryId): bool
|
||||
{
|
||||
return in_array($categoryId, $this->excludedCategoryIds, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea instancia desde array de configuracion de BD.
|
||||
*
|
||||
* @param array<string, array<string, mixed>> $settings Configuracion agrupada
|
||||
*/
|
||||
public static function fromArray(array $settings): self
|
||||
{
|
||||
$visibility = $settings['visibility'] ?? [];
|
||||
$behavior = $settings['behavior'] ?? [];
|
||||
$forms = $settings['forms'] ?? [];
|
||||
|
||||
return new self(
|
||||
isEnabled: (bool) ($visibility['is_enabled'] ?? false),
|
||||
showOnDesktop: (bool) ($visibility['show_on_desktop'] ?? true),
|
||||
showOnMobile: (bool) ($visibility['show_on_mobile'] ?? true),
|
||||
hideForLoggedIn: (bool) ($visibility['hide_for_logged_in'] ?? false),
|
||||
javascriptFirstMode: (bool) ($behavior['javascript_first_mode'] ?? false),
|
||||
excludedCategoryIds: self::parseIds($forms['exclude_categories'] ?? ''),
|
||||
excludedPostIds: self::parseIds($forms['exclude_post_ids'] ?? ''),
|
||||
excludedPostTypes: self::parsePostTypes($forms['exclude_post_types'] ?? '')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsea string de IDs separados por coma a array de enteros.
|
||||
*
|
||||
* @return array<int>
|
||||
*/
|
||||
private static function parseIds(string $value): array
|
||||
{
|
||||
if (empty($value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_filter(
|
||||
array_map(
|
||||
static fn(string $id): int => (int) trim($id),
|
||||
explode(',', $value)
|
||||
),
|
||||
static fn(int $id): bool => $id > 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsea string de post types separados por coma.
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
private static function parsePostTypes(string $value): array
|
||||
{
|
||||
if (empty($value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_filter(
|
||||
array_map(
|
||||
static fn(string $type): string => trim($type),
|
||||
explode(',', $value)
|
||||
),
|
||||
static fn(string $type): bool => $type !== ''
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user