Files
portal-api/app/Support/ProductBillingCycles.php
T

111 lines
2.9 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support;
use App\Enums\Product\ProductTypeEnums;
use App\Models\Setting;
use Illuminate\Validation\Rule;
final class ProductBillingCycles
{
public const SETTING_KEY = 'product_billing_cycles';
private const YEARLY_TYPES = ['domain', 'ssl'];
/**
* @return array<string, list<string>>
*/
public static function all(): array
{
$saved = json_decode((string) Setting::where('key', self::SETTING_KEY)->value('value'), true);
$saved = is_array($saved) ? $saved : [];
$result = [];
foreach (self::types() as $type) {
$result[$type] = self::normalize($saved[$type] ?? self::defaults($type));
}
return $result;
}
/**
* @return list<string>
*/
public static function forType(?string $type): array
{
return self::all()[$type] ?? BillingCycleCatalog::codes();
}
public static function allows(?string $type, string $cycle): bool
{
return $cycle === 'onetime' || in_array($cycle, self::forType($type), true);
}
/**
* @return array<string, mixed>
*/
public static function rules(): array
{
return [
'cycles' => 'required|array',
'cycles.*' => 'array',
'cycles.*.*' => ['string', Rule::in(BillingCycleCatalog::codes())],
];
}
/**
* @param array<string, array<int, string>> $cycles
* @return array<string, list<string>>
*/
public static function save(array $cycles): array
{
$merged = array_merge(self::all(), array_intersect_key($cycles, array_flip(self::types())));
$normalized = array_map(self::normalize(...), $merged);
Setting::updateOrCreate(['key' => self::SETTING_KEY], ['value' => json_encode($normalized)]);
return $normalized;
}
/**
* @return list<array{type: string, label: string}>
*/
public static function typeOptions(): array
{
return array_map(
fn (string $type) => ['type' => $type, 'label' => ProductTypeEnums::from($type)->label()],
self::types()
);
}
/**
* @return list<string>
*/
private static function types(): array
{
return array_values(array_filter(
array_column(ProductTypeEnums::cases(), 'value'),
fn (string $type) => $type !== ProductTypeEnums::ADDON->value
));
}
/**
* @return list<string>
*/
private static function defaults(string $type): array
{
return in_array($type, self::YEARLY_TYPES, true) ? ['annually'] : BillingCycleCatalog::codes();
}
/**
* @param array<int, string> $cycles
* @return list<string>
*/
private static function normalize(array $cycles): array
{
return array_values(array_intersect(BillingCycleCatalog::codes(), $cycles));
}
}