diff --git a/app/Model/Configuration/Category.php b/app/Model/Configuration/Category.php index 2c4e775..bd475d0 100644 --- a/app/Model/Configuration/Category.php +++ b/app/Model/Configuration/Category.php @@ -40,7 +40,7 @@ public static function from( Fees $parentFees, DateTimeInterface $eventDate, ): self { - $fees = Fees::from($category['fees'] ?? [], $parentFees); + $fees = Fees::from("categories.$key", $category['fees'] ?? [], $parentFees); if ($fees->person === null) { throw new InvalidConfigurationException("No person fee set for category “{$key}”"); } diff --git a/app/Model/Configuration/CategoryGroup.php b/app/Model/Configuration/CategoryGroup.php index 0cfe04d..93e772e 100644 --- a/app/Model/Configuration/CategoryGroup.php +++ b/app/Model/Configuration/CategoryGroup.php @@ -27,7 +27,7 @@ public static function from( Fees $parentFees, DateTimeInterface $eventDate, ): self { - $fees = Fees::from($group['fees'] ?? [], $parentFees); + $fees = Fees::from("categories.$key", $group['fees'] ?? [], $parentFees); if (!isset($group['categories']) || !\is_array($group['categories']) || \count($group['categories']) === 0) { throw new InvalidConfigurationException("Category group #{$key} lacks categories"); diff --git a/app/Model/Configuration/Entries.php b/app/Model/Configuration/Entries.php index 0b4f5c2..93b3350 100644 --- a/app/Model/Configuration/Entries.php +++ b/app/Model/Configuration/Entries.php @@ -45,7 +45,7 @@ public static function from( array $entries, ): self { $allLocales = $entries['supportedLocales'] ?? ['en', 'cs']; - $fees = Fees::from($entries['fees'] ?? []); + $fees = Fees::fromRoot($entries['fees'] ?? []); $eventDate = $entries['eventDate']; $minMembers = $entries['minMembers'] ?? 0; $personFieldsRaw = Helpers::ensureFields('person', $entries['fields']['person'] ?? []); diff --git a/app/Model/Configuration/Fees.php b/app/Model/Configuration/Fees.php index b233679..72a8881 100644 --- a/app/Model/Configuration/Fees.php +++ b/app/Model/Configuration/Fees.php @@ -14,12 +14,28 @@ public function __construct( ) { } - public static function from(array $fees, ?self $parentFees = null): self { - $currency = $parentFees?->currency ?? new Currency($fees['currency'] ?? 'CZK'); + /** + * @param array $fees + */ + public static function fromRoot(array $fees): self { + $currencyCode = Helpers::ensureNonEmptyString('fees.currency', $fees['currency'] ?? 'CZK'); + $currency = new Currency($currencyCode); return new self( currency: $currency, - person: isset($fees['person']) ? new Money($fees['person'] * 100, $currency) : $parentFees?->person, + person: isset($fees['person']) ? new Money($fees['person'] * 100, $currency) : null, + ); + } + + /** + * @param array $fees + */ + public static function from(string $context, array $fees, self $parentFees): self { + $currency = isset($fees['currency']) ? new Currency(Helpers::ensureNonEmptyString("$context.fees.currency", $fees['currency'])) : $parentFees->currency; + + return new self( + currency: $currency, + person: isset($fees['person']) ? new Money($fees['person'] * 100, $currency) : $parentFees->person, ); } } diff --git a/app/Model/Configuration/Helpers.php b/app/Model/Configuration/Helpers.php index 678e811..8ec3592 100644 --- a/app/Model/Configuration/Helpers.php +++ b/app/Model/Configuration/Helpers.php @@ -141,6 +141,21 @@ public static function ensureIntMaybe(string $context, mixed $value): ?int { return $value; } + /** + * @return non-empty-string + */ + public static function ensureNonEmptyString(string $context, mixed $value): string { + if (!\is_string($value)) { + throw new InvalidConfigurationException("Expected string for {$context}."); + } + + if ($value === '') { + throw new InvalidConfigurationException("Expected non-empty string for {$context}."); + } + + return $value; + } + public static function ensureStringMaybe(string $context, mixed $value): ?string { if ($value === null) { return $value; diff --git a/tests/Model/Configuration/BasicReadTest.phpt b/tests/Model/Configuration/BasicReadTest.phpt index 69c7b2c..f67a438 100644 --- a/tests/Model/Configuration/BasicReadTest.phpt +++ b/tests/Model/Configuration/BasicReadTest.phpt @@ -115,6 +115,31 @@ class BasicReadTest extends TestCase { Assert::equal(new Money(20_00, new Currency('CZK')), $entries->categories->allCategories['inherited']->fees->person); } + public function testFlatCategoriesFeesWithCurrency(): void { + $entries = Entries::from([ + 'eventDate' => new DateTimeImmutable('2050-12-07'), + 'fees' => [ + 'person' => 20, + 'currency' => 'GBP', + ], + 'categories' => [ + 'overridden' => [ + 'fees' => [ + 'currency' => 'USD', + 'person' => 10, + ], + ], + 'inherited' => [ + 'fees' => [ + 'person' => 30, + ], + ], + ], + ]); + Assert::equal(new Money(10_00, new Currency('USD')), $entries->categories->allCategories['overridden']->fees->person); + Assert::equal(new Money(30_00, new Currency('GBP')), $entries->categories->allCategories['inherited']->fees->person); + } + public function testNestedCategoriesFees(): void { $entries = Entries::from([ 'eventDate' => new DateTimeImmutable('2050-12-07'),