127 lines
3.6 KiB
PHP
127 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Addons;
|
|
|
|
use App\Models\PackageAddon;
|
|
use Illuminate\Support\Arr;
|
|
|
|
class EventAddonCatalog
|
|
{
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function all(): array
|
|
{
|
|
$dbAddons = PackageAddon::query()
|
|
->where('active', true)
|
|
->orderBy('sort')
|
|
->get()
|
|
->mapWithKeys(function (PackageAddon $addon) {
|
|
$metadata = $this->normalizeMetadata($addon->metadata);
|
|
|
|
return [$addon->key => [
|
|
'label' => $addon->label,
|
|
'variant_id' => $addon->variant_id,
|
|
'increments' => $addon->increments,
|
|
'price' => $addon->resolvePaypalPrice(),
|
|
'currency' => 'EUR',
|
|
'metadata' => $metadata,
|
|
]];
|
|
})
|
|
->all();
|
|
|
|
// Fallback to config and merge (DB wins)
|
|
$configAddons = collect((array) config('package-addons', []))
|
|
->filter(static fn (mixed $addon): bool => is_array($addon))
|
|
->map(function (array $addon): array {
|
|
$metadata = $this->normalizeMetadata($addon['metadata'] ?? []);
|
|
|
|
if (! isset($metadata['scope']) && is_string($addon['scope'] ?? null) && trim((string) $addon['scope']) !== '') {
|
|
$metadata['scope'] = trim((string) $addon['scope']);
|
|
}
|
|
|
|
if (! isset($metadata['entitlements']) && is_array($addon['entitlements'] ?? null)) {
|
|
$metadata['entitlements'] = $addon['entitlements'];
|
|
}
|
|
|
|
return [
|
|
'label' => $addon['label'] ?? null,
|
|
'variant_id' => $addon['variant_id'] ?? null,
|
|
'increments' => Arr::get($addon, 'increments', []),
|
|
'price' => $this->resolveConfiguredPrice($addon),
|
|
'currency' => $addon['currency'] ?? 'EUR',
|
|
'metadata' => $metadata,
|
|
];
|
|
})
|
|
->all();
|
|
|
|
return array_merge($configAddons, $dbAddons);
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>|null
|
|
*/
|
|
public function find(string $key): ?array
|
|
{
|
|
return $this->all()[$key] ?? null;
|
|
}
|
|
|
|
public function resolveVariantId(string $key): ?string
|
|
{
|
|
$addon = $this->find($key);
|
|
|
|
return $addon['variant_id'] ?? null;
|
|
}
|
|
|
|
public function resolvePrice(string $key): ?float
|
|
{
|
|
$addon = $this->find($key);
|
|
|
|
if (! $addon) {
|
|
return null;
|
|
}
|
|
|
|
$price = $addon['price'] ?? $addon['price_eur'] ?? null;
|
|
|
|
return is_numeric($price) ? (float) $price : null;
|
|
}
|
|
|
|
protected function resolveConfiguredPrice(array $addon): ?float
|
|
{
|
|
$price = $addon['price'] ?? $addon['price_eur'] ?? null;
|
|
|
|
return is_numeric($price) ? (float) $price : null;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
protected function normalizeMetadata(mixed $metadata): array
|
|
{
|
|
if (is_string($metadata)) {
|
|
$decoded = json_decode($metadata, true);
|
|
|
|
if (json_last_error() === JSON_ERROR_NONE) {
|
|
$metadata = $decoded;
|
|
}
|
|
}
|
|
|
|
return is_array($metadata) ? $metadata : [];
|
|
}
|
|
|
|
/**
|
|
* @return array<string, int>
|
|
*/
|
|
public function resolveIncrements(string $key): array
|
|
{
|
|
$addon = $this->find($key) ?? [];
|
|
|
|
$increments = Arr::get($addon, 'increments', []);
|
|
|
|
return collect($increments)
|
|
->map(fn ($value) => is_numeric($value) ? (int) $value : 0)
|
|
->filter(fn ($value) => $value > 0)
|
|
->all();
|
|
}
|
|
}
|