feat: implement AI styling foundation and billing scope rework
This commit is contained in:
134
app/Services/AiEditing/AiStyleAccessService.php
Normal file
134
app/Services/AiEditing/AiStyleAccessService.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\AiEditing;
|
||||
|
||||
use App\Models\AiStyle;
|
||||
use App\Models\Event;
|
||||
use App\Models\EventPackage;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class AiStyleAccessService
|
||||
{
|
||||
public function __construct(private readonly AiStylingEntitlementService $entitlements) {}
|
||||
|
||||
public function canUseStyle(Event $event, AiStyle $style): bool
|
||||
{
|
||||
$entitlement = $this->entitlements->resolveForEvent($event);
|
||||
if (! $entitlement['allowed']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$allowedSources = $this->allowedSources($style);
|
||||
if (! in_array((string) $entitlement['granted_by'], $allowedSources, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$requiredPackageFeatures = $this->requiredPackageFeatures($style);
|
||||
if ($requiredPackageFeatures === []) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$packageFeatures = $this->resolveEventPackageFeatures($event);
|
||||
|
||||
foreach ($requiredPackageFeatures as $requiredFeature) {
|
||||
if (! in_array($requiredFeature, $packageFeatures, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, AiStyle> $styles
|
||||
* @return Collection<int, AiStyle>
|
||||
*/
|
||||
public function filterStylesForEvent(Event $event, Collection $styles): Collection
|
||||
{
|
||||
return $styles
|
||||
->filter(fn (AiStyle $style): bool => $this->canUseStyle($event, $style))
|
||||
->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function allowedSources(AiStyle $style): array
|
||||
{
|
||||
$metadataSources = $this->normalizeStringList(Arr::get($style->metadata ?? [], 'entitlements.allowed_sources', []));
|
||||
if ($metadataSources !== []) {
|
||||
return $metadataSources;
|
||||
}
|
||||
|
||||
if (is_bool(Arr::get($style->metadata ?? [], 'entitlements.allow_with_addon'))) {
|
||||
return Arr::get($style->metadata ?? [], 'entitlements.allow_with_addon')
|
||||
? ['package', 'addon']
|
||||
: ['package'];
|
||||
}
|
||||
|
||||
return $style->is_premium ? ['package'] : ['package', 'addon'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function requiredPackageFeatures(AiStyle $style): array
|
||||
{
|
||||
return $this->normalizeStringList(
|
||||
Arr::get($style->metadata ?? [], 'entitlements.required_package_features', [])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function resolveEventPackageFeatures(Event $event): array
|
||||
{
|
||||
$eventPackage = $event->relationLoaded('eventPackage') && $event->eventPackage
|
||||
? $event->eventPackage
|
||||
: $event->eventPackage()->with('package')->first();
|
||||
|
||||
if (! $eventPackage instanceof EventPackage) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$package = $eventPackage->relationLoaded('package') ? $eventPackage->package : $eventPackage->package()->first();
|
||||
|
||||
return $this->normalizeFeatureList($package?->features);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function normalizeFeatureList(mixed $value): array
|
||||
{
|
||||
if (is_string($value)) {
|
||||
$decoded = json_decode($value, true);
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
$value = $decoded;
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_array($value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (array_is_list($value)) {
|
||||
return $this->normalizeStringList($value);
|
||||
}
|
||||
|
||||
return $this->normalizeStringList(array_keys(array_filter($value, static fn (mixed $enabled): bool => (bool) $enabled)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function normalizeStringList(array $values): array
|
||||
{
|
||||
return array_values(array_unique(array_filter(array_map(
|
||||
static fn (mixed $value): string => trim((string) $value),
|
||||
$values
|
||||
))));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user