diff --git a/.github/workflows/php-psr.yml b/.github/workflows/php-psr.yml index 6f2de99..abecdab 100644 --- a/.github/workflows/php-psr.yml +++ b/.github/workflows/php-psr.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '7.4' , '8.0' , '8.1' ] + php: [ '8.1' ] steps: - uses: actions/checkout@v2 name: Checkout diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index d20f815..9990748 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '7.4', '8.0', '8.1'] + php: ['8.1'] steps: - uses: actions/checkout@v2 name: Checkout diff --git a/composer.json b/composer.json index 44280f9..0e3c4ef 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "type": "library", "license": "GPL-3.0-or-later", "require": { - "php": "7.4.* | 8.0.* | 8.1.* ", + "php": "8.1.* ", "nette/utils": "^v3.2.0", "nette/di": "^3.0.0", "nette/application": "^3.1.0", diff --git a/src/DateTime/Period.php b/src/DateTime/Period.php new file mode 100644 index 0000000..edc9e0b --- /dev/null +++ b/src/DateTime/Period.php @@ -0,0 +1,61 @@ +begin > $this->end) { + throw new \LogicException(); + } + } + + public function isBefore(?\DateTimeInterface $dateTime = null): bool + { + return $this->begin > ($dateTime ?? new \DateTimeImmutable()); + } + + public function isAfter(?\DateTimeInterface $dateTime = null): bool + { + return $this->end < ($dateTime ?? new \DateTimeImmutable()); + } + + public function isOnGoing(?\DateTimeInterface $dateTime = null): bool + { + return $this->begin <= ($dateTime ?? new \DateTimeImmutable()) + && $this->end >= ($dateTime ?? new \DateTimeImmutable()); + } + + public function is(Phase $period, ?\DateTimeInterface $dateTime = null): bool + { + return match ($period) { + Phase::before => $this->isBefore($dateTime), + Phase::after => $this->isAfter($dateTime), + Phase::onGoing => $this->isOnGoing($dateTime) + }; + } + + public function getPhase(?\DateTimeInterface $dateTime = null): Phase + { + if ($this->isBefore($dateTime)) { + return Phase::before; + } + if ($this->isAfter($dateTime)) { + return Phase::after; + } + if ($this->isOnGoing($dateTime)) { + return Phase::onGoing; + } + throw new \LogicException(); + } + + public function duration(): \DateInterval + { + return $this->end->diff($this->begin); + } +} diff --git a/src/DateTime/Phase.php b/src/DateTime/Phase.php new file mode 100644 index 0000000..c6d43ab --- /dev/null +++ b/src/DateTime/Phase.php @@ -0,0 +1,12 @@ +|LangMap $map * @phpstan-return TValue */ - public function getVariant($map) + public function getVariant($map): mixed { if ($map instanceof LangMap) { return $map->get($this->lang); diff --git a/src/Localization/LangMap.php b/src/Localization/LangMap.php index c078507..8a3d4bc 100644 --- a/src/Localization/LangMap.php +++ b/src/Localization/LangMap.php @@ -27,7 +27,7 @@ public function __construct(array $variants) * @phpstan-param TLang $lang * @phpstan-return TValue */ - public function __get(string $lang) + public function __get(string $lang): mixed { return $this->get($lang); } @@ -36,7 +36,7 @@ public function __get(string $lang) * @phpstan-param TLang $lang * @phpstan-return TValue */ - public function get(string $lang) + public function get(string $lang): mixed { return $this->variants[$lang] ?? null; } diff --git a/src/Logging/Message.php b/src/Logging/Message.php index 1816464..5b06f36 100644 --- a/src/Logging/Message.php +++ b/src/Logging/Message.php @@ -4,29 +4,14 @@ namespace Fykosak\Utils\Logging; -use Nette\SmartObject; use Nette\Utils\Html; class Message { - use SmartObject; - - public const LVL_ERROR = 'danger'; - public const LVL_WARNING = 'warning'; - public const LVL_SUCCESS = 'success'; - public const LVL_INFO = 'info'; - public const LVL_PRIMARY = 'primary'; - - public $text; - public string $level; - - /** - * @param string|Html $message - */ - public function __construct($message, string $level) - { - $this->text = $message; - $this->level = $level; + public function __construct( + public readonly string|Html $text, + public readonly MessageLevel $level + ) { } /** @@ -36,7 +21,7 @@ public function __toArray(): array { return [ 'text' => ($this->text instanceof Html) ? $this->text->toHtml() : $this->text, - 'level' => $this->level, + 'level' => $this->level->value, ]; } } diff --git a/src/Logging/MessageLevel.php b/src/Logging/MessageLevel.php new file mode 100644 index 0000000..c5dacd7 --- /dev/null +++ b/src/Logging/MessageLevel.php @@ -0,0 +1,14 @@ +value = $currency; - } - - /** - * @return self[] - */ - public static function cases(): array - { - return [new self(self::CZK), new self(self::EUR)]; - } - - public static function tryFrom(string $currency): ?self - { - try { - return new self($currency); - } catch (NotImplementedException $exception) { - return null; - } - } - - /** - * @throws NotImplementedException - */ - public static function from(string $currency): self - { - return new self($currency); - } + case EUR = 'EUR'; + case CZK = 'CZK'; public function getLabel(): string { - switch ($this->value) { - case self::EUR: - return '€'; - case self::CZK: - return 'Kč'; - } - return ''; + return match ($this) { + self::EUR => '€', + self::CZK => 'Kč', + }; } public function format(float $amount): string diff --git a/src/Price/MultiCurrencyPrice.php b/src/Price/MultiCurrencyPrice.php index 22e25b5..d642d8f 100644 --- a/src/Price/MultiCurrencyPrice.php +++ b/src/Price/MultiCurrencyPrice.php @@ -76,7 +76,7 @@ public function add(self $multiPrice): void public function __get(string $name): ?Price { - return $this->getPrice(Currency::from($name)); + return $this->getPrice(Currency::from(strtoupper($name))); } public function __set(string $name, Price $value): void diff --git a/src/Price/Price.php b/src/Price/Price.php index 64fae1b..354ae1e 100644 --- a/src/Price/Price.php +++ b/src/Price/Price.php @@ -4,22 +4,15 @@ namespace Fykosak\Utils\Price; -use Nette\SmartObject; - -/** - * @phpstan-type TSerializedPrice array{currency:string,amount:float} - */ final class Price { - use SmartObject; - - private Currency $currency; private float $amount; - public function __construct(Currency $currency, ?float $amount = null) - { + public function __construct( + private readonly Currency $currency, + ?float $amount = null + ) { $this->amount = $amount ?? 0; - $this->currency = $currency; } /** @@ -27,7 +20,7 @@ public function __construct(Currency $currency, ?float $amount = null) */ public function add(Price $price): void { - if ($this->currency->value !== $price->getCurrency()->value) { + if ($this->currency !== $price->getCurrency()) { throw new \LogicException('Currencies are not a same'); } $this->amount += $price->getAmount(); @@ -54,7 +47,7 @@ public function __toString(): string } /** - * @phpstan-return TSerializedPrice + * @phpstan-return array{currency:string,amount:float} */ public function __serialize(): array { diff --git a/src/UI/Navigation/NavItem.php b/src/UI/Navigation/NavItem.php index 3683fef..b873300 100644 --- a/src/UI/Navigation/NavItem.php +++ b/src/UI/Navigation/NavItem.php @@ -5,35 +5,19 @@ namespace Fykosak\Utils\UI\Navigation; use Fykosak\Utils\UI\Title; -use Nette\SmartObject; class NavItem { - use SmartObject; - - public string $destination; - /** @phpstan-var array */ - public array $linkParams; - public Title $title; - /** @var NavItem[] */ - public array $children; - public bool $active; - /** * @phpstan-param array $linkParams * @phpstan-param NavItem[] $children */ public function __construct( - Title $title, - string $destination = '#', - array $linkParams = [], - array $children = [], - bool $active = false + public readonly Title $title, + public readonly string $destination = '#', + public readonly array $linkParams = [], + public readonly array $children = [], + public readonly bool $active = false ) { - $this->active = $active; - $this->destination = $destination; - $this->linkParams = $linkParams; - $this->title = $title; - $this->children = $children; } } diff --git a/src/UI/PageTitle.php b/src/UI/PageTitle.php index 983dc7b..eb451e4 100644 --- a/src/UI/PageTitle.php +++ b/src/UI/PageTitle.php @@ -8,17 +8,13 @@ class PageTitle extends Title { - /** @var string|Html|null */ - public $subTitle; - - /** - * @param string|Html $title - * @param string|Html|null $subTitle - */ - public function __construct(?string $id, $title, ?string $icon = null, $subTitle = null) - { + public function __construct( + ?string $id, + string|Html $title, + ?string $icon = null, + public string|Html|null $subTitle = null + ) { parent::__construct($id, $title, $icon); - $this->subTitle = $subTitle; } public function toHtml(bool $includeSubTitle = false): Html diff --git a/src/UI/Title.php b/src/UI/Title.php index b5fbeb8..5cbaf7b 100644 --- a/src/UI/Title.php +++ b/src/UI/Title.php @@ -9,18 +9,13 @@ class Title { - /** @var string|Html */ - public $title; - public ?string $icon; - public string $id; + public readonly string $id; - /** - * @param string|Html $title - */ - public function __construct(?string $id, $title, ?string $icon = null) - { - $this->title = $title; - $this->icon = $icon; + public function __construct( + ?string $id, + public readonly string|Html $title, + public readonly ?string $icon = null + ) { $this->id = $id ?? Random::generate(10, 'a-z'); } diff --git a/tests/Tests/Price/TestCurrency.phpt b/tests/Tests/Price/TestCurrency.phpt index 3dfd0a6..5487c1f 100644 --- a/tests/Tests/Price/TestCurrency.phpt +++ b/tests/Tests/Price/TestCurrency.phpt @@ -13,11 +13,6 @@ require_once __DIR__ . '/../FakeBootstrap.php'; class TestCurrency extends BaseTest { - public function testCreateNonExist(): void - { - Assert::exception(fn() => new Currency('XBT'), \Exception::class); - } - public function testCases(): void { foreach (Currency::cases() as $case) { @@ -27,21 +22,21 @@ class TestCurrency extends BaseTest public function testFromExists(): void { - $currency = Currency::from(Currency::CZK); + $currency = Currency::CZK; Assert::type(Currency::class, $currency); - $currencyLower = Currency::from('czk'); + $currencyLower = Currency::from('CZK'); Assert::type(Currency::class, $currencyLower); } public function testTryFromExists(): void { - $currency = Currency::tryFrom(Currency::CZK); + $currency = Currency::CZK; Assert::type(Currency::class, $currency); } public function testFromNonExists(): void { - Assert::exception(fn() => Currency::from('XBT'), \Exception::class); + Assert::exception(fn() => Currency::from('XBT'), \ValueError::class); } public function testTryFromNonExists(): void @@ -52,7 +47,7 @@ class TestCurrency extends BaseTest public function testRender(): void { - $currency = new Currency(Currency::CZK); + $currency = Currency::CZK; Assert::same('2.00 Kč', $currency->format(2.0)); } } diff --git a/tests/Tests/Price/TestMultiPrice.phpt b/tests/Tests/Price/TestMultiPrice.phpt index 48bb789..e6ed837 100644 --- a/tests/Tests/Price/TestMultiPrice.phpt +++ b/tests/Tests/Price/TestMultiPrice.phpt @@ -24,14 +24,14 @@ class TestMultiPrice extends BaseTest public function testCreateFilled(): void { - $multiPrice = new MultiCurrencyPrice([new Price(Currency::from(Currency::CZK))]); + $multiPrice = new MultiCurrencyPrice([new Price(Currency::CZK)]); $price = $multiPrice->czk; Assert::type(Price::class, $price); } public function testGetAccess(): void { - $multiPrice = new MultiCurrencyPrice([new Price(Currency::from(Currency::CZK), 4),]); + $multiPrice = new MultiCurrencyPrice([new Price(Currency::CZK, 4),]); Assert::type(Price::class, $multiPrice->czk); Assert::exception(fn() => $multiPrice->eur, \OutOfRangeException::class); Assert::type(Price::class, $multiPrice->CZK); @@ -39,32 +39,32 @@ class TestMultiPrice extends BaseTest public function testSetAccess(): void { - $multiPrice = new MultiCurrencyPrice([new Price(Currency::from(Currency::CZK), 4),]); - $multiPrice->czk = new Price(Currency::from(Currency::CZK), 2); + $multiPrice = new MultiCurrencyPrice([new Price(Currency::CZK, 4),]); + $multiPrice->czk = new Price(Currency::CZK, 2); Assert::type(Price::class, $multiPrice->czk); Assert::same(2.0, $multiPrice->czk->getAmount()); Assert::exception( - fn() => $multiPrice->czk = new Price(Currency::from(Currency::EUR)), + fn() => $multiPrice->czk = new Price(Currency::EUR), \LogicException::class ); Assert::exception( - fn() => $multiPrice->CZK = new Price(Currency::from(Currency::EUR)), + fn() => $multiPrice->CZK = new Price(Currency::EUR), \LogicException::class ); Assert::exception( - fn() => $multiPrice->eur = new Price(Currency::from(Currency::EUR)), + fn() => $multiPrice->eur = new Price(Currency::EUR), \OutOfRangeException::class ); } public function testCreateSum(): void { - $multiPrice1 = new MultiCurrencyPrice([new Price(Currency::from(Currency::CZK), 2)]); + $multiPrice1 = new MultiCurrencyPrice([new Price(Currency::CZK, 2)]); $multiPrice2 = new MultiCurrencyPrice( [ - new Price(Currency::from(Currency::CZK), 1), - new Price(Currency::from(Currency::EUR), 4), + new Price(Currency::CZK, 1), + new Price(Currency::EUR, 4), ] ); diff --git a/tests/Tests/Price/TestPrice.phpt b/tests/Tests/Price/TestPrice.phpt index e73e58c..c4ad895 100644 --- a/tests/Tests/Price/TestPrice.phpt +++ b/tests/Tests/Price/TestPrice.phpt @@ -16,8 +16,8 @@ class TestPrice extends BaseTest { public function testAddSame(): void { - $price1 = new Price(new Currency(Currency::CZK), 2); - $price2 = new Price(new Currency(Currency::CZK), 4); + $price1 = new Price(Currency::CZK, 2); + $price2 = new Price(Currency::CZK, 4); $price1->add($price2); Assert::same(6.0, $price1->getAmount()); Assert::same(4.0, $price2->getAmount()); @@ -25,14 +25,14 @@ class TestPrice extends BaseTest public function testNotSame(): void { - $price1 = new Price(new Currency(Currency::CZK), 2); - $price2 = new Price(new Currency(Currency::EUR), 4); + $price1 = new Price(Currency::CZK, 2); + $price2 = new Price(Currency::EUR, 4); Assert::exception(fn() => $price1->add($price2), \LogicException::class); } public function testAdd(): void { - $price1 = new Price(new Currency(Currency::CZK), 2); + $price1 = new Price(Currency::CZK, 2); $price1->addAmount(3.5); Assert::same(5.5, $price1->getAmount()); }