Files
roi-theme/Public/AdsensePlacement/Domain/ValueObjects/AdsenseSettings.php
FrankZamora 26546e1d69 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>
2025-12-11 13:03:14 -06:00

164 lines
4.5 KiB
PHP

<?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 !== ''
);
}
}