diff --git a/.github/workflows/behat-tests.yml b/.github/workflows/behat-tests.yml index 4d201c2a..86bd0426 100644 --- a/.github/workflows/behat-tests.yml +++ b/.github/workflows/behat-tests.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: ['8.3'] + php: ['8.4'] coverage-driver: [pcov] name: PHP ${{ matrix.php }} steps: diff --git a/.github/workflows/phpunit-tests.yml b/.github/workflows/phpunit-tests.yml index 44af1076..ebdfe652 100644 --- a/.github/workflows/phpunit-tests.yml +++ b/.github/workflows/phpunit-tests.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: ['8.3'] + php: ['8.4'] coverage-driver: [pcov] name: PHP ${{ matrix.php }} steps: diff --git a/.github/workflows/psalm-analysis.yml b/.github/workflows/psalm-analysis.yml index e0b766da..88d0341c 100644 --- a/.github/workflows/psalm-analysis.yml +++ b/.github/workflows/psalm-analysis.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: [ '8.3' ] + php: [ '8.4' ] coverage-driver: [ pcov ] name: PHP ${{ matrix.php }} steps: @@ -41,4 +41,4 @@ jobs: run: composer install -n - name: Run Psalm - run: vendor/bin/psalm \ No newline at end of file + run: vendor/bin/psalm diff --git a/composer.json b/composer.json index befd66e2..093e86b6 100644 --- a/composer.json +++ b/composer.json @@ -65,7 +65,8 @@ "opis/closure": "3.x-dev as 3.6.x-dev", "cache/array-adapter": "*", "matthiasnoback/behat-expect-exception": "^v0.3.0", - "behat/gherkin": "~v4.11.0" + "behat/gherkin": "~v4.11.0", + "rector/rector": "dev-main" }, "suggest": { "ext-intl": "intl extension is required for formula support", diff --git a/rector.php b/rector.php new file mode 100644 index 00000000..7468ed74 --- /dev/null +++ b/rector.php @@ -0,0 +1,80 @@ +withAutoloadPaths([ + file_exists(__DIR__ . '/../../autoload.php') ? __DIR__ . '/../../autoload.php' : null, + file_exists(__DIR__ . '/vendor/autoload.php') ? __DIR__ . '/vendor/autoload.php' : null, + ]) + ->withCache(__DIR__ . '/../../../runtime/cache/rector', FileCacheStorage::class) + ->withPreparedSets(deadCode: true, codeQuality: true) + ->withPhpSets(php83: true, php84: true) + ->withPhpVersion(\Rector\ValueObject\PhpVersion::PHP_84) + ->withoutParallel() + ->withPaths([ + __DIR__ . '/src', + ]) + ->withRules([ + RemoveAlwaysElseRector::class, + ChangeNestedIfsToEarlyReturnRector::class, + ChangeIfElseValueAssignToEarlyReturnRector::class, + ChangeNestedForeachIfsToEarlyContinueRector::class, + ]) + ->withSkip([ + // Too many places where json_decode was used intentionally on wrong data =\ + JsonThrowOnErrorRector::class, + + // Frequently used for debug. Maybe, such places should be annotated with @noRector? + SimplifyUselessVariableRector::class, + + // Legacy modules are full of `_doSomeShit()` methods that are likely called as `$this->_do{$operation}` + RemoveUnusedPrivateMethodRector::class, + + // Does not make sense for us + SimplifyRegexPatternRector::class, + + // Requires whole project autoloaded to work well + RemoveUnusedPrivateClassConstantRector::class, + + // don't refactor with `empty` check function + DisallowedEmptyRuleFixerRector::class, + SimplifyEmptyArrayCheckRector::class, + SimplifyEmptyCheckOnEmptyArrayRector::class, + + // do not refactor `query` attribute like " . '$select' . " to 'SELECT $select ...' + JoinStringConcatRector::class, + + // do not refactor php version id checkers + RemovePhpVersionIdCheckRector::class, + RemoveExtraParametersRector::class, + + SwitchNegatedTernaryRector::class, + ]); diff --git a/src/EntityInterface.php b/src/EntityInterface.php index 497cd470..1e70fee6 100644 --- a/src/EntityInterface.php +++ b/src/EntityInterface.php @@ -1,4 +1,7 @@ id = $id; $this->type = $type; $this->target = $target; $this->quantity = $quantity; @@ -82,7 +75,6 @@ public function __construct( $this->sale = $sale; $this->state = $state; $this->parent = $parent; - $this->fractionOfMonth = $fractionOfMonth; } /** diff --git a/src/action/Action.php b/src/action/Action.php index af25f5e9..af92c4f9 100644 --- a/src/action/Action.php +++ b/src/action/Action.php @@ -1,4 +1,7 @@ start = $start; - $this->end = $end; - $this->month = self::toMonth($start); + $this->month = self::toMonth($this->start); } private static function toMonth(DateTimeImmutable $date): DateTimeImmutable @@ -48,7 +40,6 @@ public static function wholeMonth(DateTimeImmutable $time): self * @param DateTimeImmutable $start the start date of the sale * @param DateTimeImmutable|null $end the end date of the sale or null if the sale is active * @throws InvalidArgumentException if the start date is greater than the end date - * @return static */ public static function withinMonth( DateTimeImmutable $month, @@ -58,7 +49,7 @@ public static function withinMonth( $month = self::toMonth($month); $nextMonth = $month->modify('+1 month'); - if ($end !== null && $start > $end) { + if ($end instanceof \DateTimeImmutable && $start > $end) { throw new InvalidArgumentException('Start date must be less than end date'); } @@ -67,7 +58,7 @@ public static function withinMonth( $end = $month; } - if ($end !== null && $end < $month) { + if ($end instanceof \DateTimeImmutable && $end < $month) { $start = $month; $end = $month; } @@ -90,7 +81,6 @@ public static function withinMonth( * @param DateTimeImmutable $month the month to calculate the usage interval for * @param DateTimeImmutable $start the start date of the sale * @param float $fractionOfMonth the fraction of manth - * @return static */ public static function withMonthAndFraction( DateTimeImmutable $month, @@ -173,9 +163,6 @@ public function ratioOfMonth(): float /** * Extends the usage interval to include both current and other intervals. - * - * @param UsageInterval $other - * @return self */ public function extend(self $other): self { diff --git a/src/action/mux/ActionMuxInterface.php b/src/action/mux/ActionMuxInterface.php index 76c6e0b9..906813fb 100644 --- a/src/action/mux/ActionMuxInterface.php +++ b/src/action/mux/ActionMuxInterface.php @@ -1,4 +1,7 @@ id = $id; $this->type = $type; $this->time = $time; $this->sum = $sum; diff --git a/src/bill/BillCreationDto.php b/src/bill/BillCreationDto.php index 897ac8f2..ffb64f55 100644 --- a/src/bill/BillCreationDto.php +++ b/src/bill/BillCreationDto.php @@ -1,4 +1,7 @@ id = $id; - $this->name = $name; + /** + * @param int|string|null $id + */ + public function __construct( + protected $id = null, + protected ?string $name = null + ) { } public function getId() diff --git a/src/bill/BillState.php b/src/bill/BillState.php index 72601b62..6937d516 100644 --- a/src/bill/BillState.php +++ b/src/bill/BillState.php @@ -1,4 +1,7 @@ id = $id; $this->type = $type; $this->target = $target; $this->action = $action; diff --git a/src/charge/ChargeCreationDto.php b/src/charge/ChargeCreationDto.php index 028ce6a1..5d21459f 100644 --- a/src/charge/ChargeCreationDto.php +++ b/src/charge/ChargeCreationDto.php @@ -1,4 +1,7 @@ modifier->modifyCharge($charge, $action); } - return $charge ? [$charge] : []; + return $charge instanceof ChargeInterface ? [$charge] : []; } /** {@inheritdoc} */ diff --git a/src/charge/TimeLimitedModifierInterface.php b/src/charge/TimeLimitedModifierInterface.php index 68293a65..87eea9f0 100644 --- a/src/charge/TimeLimitedModifierInterface.php +++ b/src/charge/TimeLimitedModifierInterface.php @@ -1,4 +1,7 @@ addAddon(self::VALUE, new Discount($value)); } + #[\Override] public function getNext() { return $this; } - public function getValue(ChargeInterface $charge = null): Discount + public function getValue(?ChargeInterface $charge = null): Discount { return $this->getAddon(self::VALUE); } @@ -53,7 +56,7 @@ public function isRelative() return !$this->isAbsolute(); } - public function calculateSum(ChargeInterface $charge = null): Money + public function calculateSum(?ChargeInterface $charge = null): Money { return $this->getValue($charge)->calculateSum($charge); } @@ -62,14 +65,14 @@ private function getType() { $chargeTypeAddon = $this->getChargeType(); - $type = $chargeTypeAddon ? $chargeTypeAddon->getValue() : 'discount,discount'; + $type = $chargeTypeAddon instanceof ChargeType ? $chargeTypeAddon->getValue() : 'discount,discount'; return new Type(Type::ANY, $type); } public function modifyCharge(?ChargeInterface $charge, ActionInterface $action): array { - if ($charge === null) { + if (!$charge instanceof ChargeInterface) { return []; } @@ -88,7 +91,7 @@ public function modifyCharge(?ChargeInterface $charge, ActionInterface $action): $discount->setParent($charge); $reason = $this->getReason(); - if ($reason) { + if ($reason instanceof Reason) { $discount->setComment($reason->getValue()); } diff --git a/src/charge/modifiers/FullCombination.php b/src/charge/modifiers/FullCombination.php index 5b5ba510..1fb9400b 100644 --- a/src/charge/modifiers/FullCombination.php +++ b/src/charge/modifiers/FullCombination.php @@ -57,9 +57,7 @@ public function modifyCharge(?ChargeInterface $charge, ActionInterface $action): return []; // If there was at least one charge, but it disappeared – modifier does not want this charge to happen. Stop. } - $originalChargeExists = array_reduce($leftCharges, static function ($result, Charge $item) use ($charge) { - return $result || $charge === $item; - }, false); + $originalChargeExists = array_reduce($leftCharges, static fn($result, Charge $item) => $result || $charge === $item, false); if ($charge && !$originalChargeExists) { return $leftCharges; } @@ -155,7 +153,7 @@ private function unique(array $charges): array */ private function sumCharges(?ChargeInterface $originalCharge, array $producedCharges): ?ChargeInterface { - if ($originalCharge === null) { + if (!$originalCharge instanceof ChargeInterface) { return null; } @@ -175,9 +173,9 @@ private function sumCharges(?ChargeInterface $originalCharge, array $producedCha return $originalCharge; } - $query = (new ChargeDerivativeQuery())->changeSum($sum); + $query = new ChargeDerivativeQuery()->changeSum($sum); - return (new ChargeDerivative())->__invoke($originalCharge, $query); + return new ChargeDerivative()->__invoke($originalCharge, $query); } /** diff --git a/src/charge/modifiers/GrowingDiscount.php b/src/charge/modifiers/GrowingDiscount.php index 47506f44..99f6cd4c 100644 --- a/src/charge/modifiers/GrowingDiscount.php +++ b/src/charge/modifiers/GrowingDiscount.php @@ -16,6 +16,7 @@ use hiqdev\php\billing\charge\modifiers\addons\Maximum; use hiqdev\php\billing\charge\modifiers\addons\Minimum; use hiqdev\php\billing\charge\modifiers\addons\Period; +use hiqdev\php\billing\charge\modifiers\addons\Since; use hiqdev\php\billing\charge\modifiers\addons\Step; use Money\Money; @@ -40,6 +41,7 @@ public function __construct($step, $min = null, array $addons = []) } } + #[\Override] public function isAbsolute() { return $this->getStep()->isAbsolute(); @@ -87,6 +89,7 @@ public function every($string = 1) return $this->addAddon(self::PERIOD, Period::fromString($string)); } + #[\Override] public function calculateSum(?ChargeInterface $charge = null): Money { $sum = parent::calculateSum($charge); @@ -101,9 +104,10 @@ public function calculateSum(?ChargeInterface $charge = null): Money return $sum; } + #[\Override] public function getValue(?ChargeInterface $charge = null): Discount { - $time = $charge ? $charge->getAction()->getTime() : new DateTimeImmutable(); + $time = $charge instanceof ChargeInterface ? $charge->getAction()->getTime() : new DateTimeImmutable(); $num = (int) $this->countPeriodsPassed($time); return $this->getStep()->calculateFor($num, $this->getMin()); @@ -112,7 +116,7 @@ public function getValue(?ChargeInterface $charge = null): Discount protected function countPeriodsPassed(DateTimeImmutable $time) { $since = $this->getSince(); - if ($since === null) { + if (!$since instanceof Since) { throw new \Exception('no since given for growing discount'); } diff --git a/src/charge/modifiers/Increase.php b/src/charge/modifiers/Increase.php index e1d7f5af..2dc189cb 100644 --- a/src/charge/modifiers/Increase.php +++ b/src/charge/modifiers/Increase.php @@ -19,11 +19,6 @@ */ class Increase extends Modifier { - public function __construct(array $addons = []) - { - parent::__construct($addons); - } - public function grows($step, $min = null): GrowingDiscount { $increase = new GrowingDiscount($step, $min, $this->addons); diff --git a/src/charge/modifiers/Installment.php b/src/charge/modifiers/Installment.php index dcfe6a10..b97817a5 100644 --- a/src/charge/modifiers/Installment.php +++ b/src/charge/modifiers/Installment.php @@ -17,6 +17,8 @@ use hiqdev\php\billing\charge\Charge; use hiqdev\php\billing\charge\ChargeInterface; use hiqdev\php\billing\charge\modifiers\addons\Period; +use hiqdev\php\billing\charge\modifiers\addons\Reason; +use hiqdev\php\billing\charge\modifiers\addons\Since; use hiqdev\php\billing\charge\modifiers\event\InstallmentWasFinished; use hiqdev\php\billing\charge\modifiers\event\InstallmentWasStarted; use hiqdev\php\billing\formula\FormulaSemanticsError; @@ -56,21 +58,22 @@ public function getTarget() return new Target(Target::ANY, Target::ANY); } - public function till($time) + #[\Override] + public function till($time): never { throw new FormulaSemanticsError('till can not be defined for installment'); } public function modifyCharge(?ChargeInterface $charge, ActionInterface $action): array { - if ($charge === null) { + if (!$charge instanceof ChargeInterface) { throw new \Exception('unexpected null charge in Installment, to be implemented'); } $this->ensureIsValid(); $reason = $this->getReason(); - if ($reason) { + if ($reason instanceof Reason) { $charge->setComment($reason->getValue()); } @@ -89,12 +92,12 @@ public function modifyCharge(?ChargeInterface $charge, ActionInterface $action): protected function ensureIsValid(): void { $since = $this->getSince(); - if ($since === null) { + if (!$since instanceof Since) { throw new FormulaSemanticsError('no since given for installment'); } $term = $this->getTerm(); - if ($term === null) { + if (!$term instanceof Period) { throw new FormulaSemanticsError('no term given for installment'); } } @@ -105,12 +108,7 @@ private function isFirstMonthInInstallmentPassed(DateTimeImmutable $time): bool if ($since && $since->getValue() > $time) { return false; } - - if ($since->getValue()->diff($time)->format('%a') === '0') { - return true; - } - - return false; + return $since->getValue()->diff($time)->format('%a') === '0'; } private function isFirstMonthAfterInstallmentPassed(DateTimeImmutable $time): bool @@ -121,18 +119,12 @@ private function isFirstMonthAfterInstallmentPassed(DateTimeImmutable $time): bo } $till = $this->getTill(); - if ($till && $till->getValue() <= $time) { - if ($till->getValue()->diff($time)->format('%a') === '0') { - return true; - } - } - - $term = $this->getTerm(); - if ($term && $term->addTo($since->getValue())->diff($time)->format('%a') === '0') { + if ($till && $till->getValue() <= $time && $till->getValue()->diff($time)->format('%a') === '0') { return true; } - return false; + $term = $this->getTerm(); + return $term && $term->addTo($since->getValue())->diff($time)->format('%a') === '0'; } private function createInstallmentFinishingCharge(ChargeInterface $charge, DateTimeImmutable $month): ChargeInterface @@ -189,11 +181,11 @@ public function getRemainingPeriods(DateTimeImmutable $currentDate): ?Period $since = $this->getSince(); $term = $this->getTerm(); - if ($since === null || $term === null) { + if (!$since instanceof Since || !$term instanceof Period) { return null; } - $className = get_class($term); + $className = $term::class; $passedRatio = $term->countPeriodsPassed($since->getValue(), $currentDate); return new $className( diff --git a/src/charge/modifiers/Modifier.php b/src/charge/modifiers/Modifier.php index ee9965b8..58771562 100644 --- a/src/charge/modifiers/Modifier.php +++ b/src/charge/modifiers/Modifier.php @@ -16,6 +16,8 @@ use hiqdev\php\billing\charge\AddonsContainerInterface; use hiqdev\php\billing\charge\ChargeInterface; use hiqdev\php\billing\charge\ChargeModifier; +use hiqdev\php\billing\charge\modifiers\addons\Period; +use hiqdev\php\billing\charge\modifiers\addons\Since; use hiqdev\php\billing\charge\TimeLimitedModifierInterface; use hiqdev\php\billing\formula\FormulaRuntimeError; @@ -52,11 +54,7 @@ public function isSuitable(?ChargeInterface $charge, ActionInterface $action): b $month = $action->getTime()->modify('first day of this month midnight'); $since = $this->getSince(); - if ($since && $since->getValue() > $month) { - return false; - } - - return true; + return !($since && $since->getValue() > $month); } public function discount() @@ -125,8 +123,8 @@ public function checkPeriod(DateTimeImmutable $time): bool } $term = $this->getTerm(); - if ($term) { - if (!$since) { + if ($term instanceof Period) { + if (!$since instanceof Since) { throw new FormulaRuntimeError('since must be set to use term'); } if ($term->countPeriodsPassed($since->getValue(), $time) >= 1) { diff --git a/src/charge/modifiers/MonthlyCap.php b/src/charge/modifiers/MonthlyCap.php index 4126c52a..f4dc9f4d 100644 --- a/src/charge/modifiers/MonthlyCap.php +++ b/src/charge/modifiers/MonthlyCap.php @@ -20,6 +20,7 @@ use hiqdev\php\billing\charge\modifiers\addons\Boolean; use hiqdev\php\billing\charge\modifiers\addons\DayPeriod; use hiqdev\php\billing\charge\modifiers\addons\Period; +use hiqdev\php\billing\charge\modifiers\addons\Reason; use hiqdev\php\billing\Exception\NotSupportedException; use hiqdev\php\units\Quantity; use hiqdev\php\units\QuantityInterface; @@ -34,7 +35,7 @@ */ class MonthlyCap extends Modifier { - private const PERIOD = 'period'; + private const string PERIOD = 'period'; protected ChargeDerivative $chargeDerivative; @@ -56,6 +57,7 @@ public function forNonProportionalizedQuantity(): Modifier return $this->addAddon('non-proportionalized', new Boolean(true)); } + #[\Override] public function getNext() { return $this; @@ -63,7 +65,7 @@ public function getNext() public function modifyCharge(?ChargeInterface $charge, ActionInterface $action): array { - if ($charge === null) { + if (!$charge instanceof ChargeInterface) { return []; } @@ -81,8 +83,6 @@ public function modifyCharge(?ChargeInterface $charge, ActionInterface $action): } /** - * @param ChargeInterface $charge - * @param ActionInterface $action * @return ChargeInterface[] */ private function propotionalizeCharge(ChargeInterface $charge, ActionInterface $action): array @@ -133,7 +133,7 @@ private function splitCapFromCharge(ChargeInterface $charge, ActionInterface $ac $zeroChargeQuery->changeUsage($usageHours->subtract($cappedHours)); $zeroChargeQuery->changeParent($newCharge); $reason = $this->getReason(); - if ($reason) { + if ($reason instanceof Reason) { $zeroChargeQuery->changeComment($reason->getValue()); } $newZeroCharge = $this->chargeDerivative->__invoke($charge, $zeroChargeQuery); diff --git a/src/charge/modifiers/Once.php b/src/charge/modifiers/Once.php index 1679e9ee..222d8b58 100644 --- a/src/charge/modifiers/Once.php +++ b/src/charge/modifiers/Once.php @@ -9,10 +9,12 @@ use hiqdev\php\billing\charge\derivative\ChargeDerivativeQuery; use hiqdev\php\billing\charge\modifiers\addons\MonthPeriod; use hiqdev\php\billing\charge\modifiers\addons\Period; +use hiqdev\php\billing\charge\modifiers\addons\Reason; use hiqdev\php\billing\charge\modifiers\addons\Since; use hiqdev\php\billing\charge\modifiers\addons\WithSince; use hiqdev\php\billing\charge\modifiers\addons\YearPeriod; use hiqdev\php\billing\formula\FormulaEngineException; +use hiqdev\php\billing\sale\SaleInterface; use Money\Money; /** @@ -26,7 +28,7 @@ */ class Once extends Modifier { - private const MONTHS_IN_YEAR_ON_EARTH = 12; + private const int MONTHS_IN_YEAR_ON_EARTH = 12; protected ChargeDerivative $chargeDerivative; @@ -85,7 +87,7 @@ private function createNewZeroCharge(ChargeInterface $charge): ChargeInterface $zeroChargeQuery = new ChargeDerivativeQuery(); $zeroChargeQuery->changeSum(new Money(0, $charge->getSum()->getCurrency())); $reason = $this->getReason(); - if ($reason) { + if ($reason instanceof Reason) { $zeroChargeQuery->changeComment($reason->getValue()); } else { $zeroChargeQuery->changeComment('Billed once per ' . $this->getPer()->toString()); @@ -96,14 +98,14 @@ private function createNewZeroCharge(ChargeInterface $charge): ChargeInterface private function assertPeriod(?Period $period) { - if ($period === null) { + if (!$period instanceof Period) { throw new FormulaEngineException('Period cannot be null in Once'); } } private function assertCharge(?ChargeInterface $charge) { - if ($charge === null) { + if (!$charge instanceof ChargeInterface) { throw new FormulaEngineException('Charge cannot be null in Once'); } } @@ -128,7 +130,7 @@ private function getSinceDate(ActionInterface $action): DateTimeImmutable } $sale = $action->getSale(); - if ($sale !== null) { + if ($sale instanceof SaleInterface) { return $sale->getTime(); } @@ -145,7 +147,8 @@ private function getIntervalMonthsFromPeriod(Period $period): int { if ($period instanceof YearPeriod) { return self::MONTHS_IN_YEAR_ON_EARTH; - } elseif ($period instanceof MonthPeriod) { + } + if ($period instanceof MonthPeriod) { return $period->getValue(); } diff --git a/src/charge/modifiers/PercentPoint.php b/src/charge/modifiers/PercentPoint.php index 5c8205fc..4b7adc2d 100644 --- a/src/charge/modifiers/PercentPoint.php +++ b/src/charge/modifiers/PercentPoint.php @@ -1,4 +1,7 @@ number = $number; } /** diff --git a/src/charge/modifiers/addons/Boolean.php b/src/charge/modifiers/addons/Boolean.php index 6a63be7f..e0029f5f 100644 --- a/src/charge/modifiers/addons/Boolean.php +++ b/src/charge/modifiers/addons/Boolean.php @@ -1,4 +1,7 @@ ensureSameType($addend, 'addend'); - if ($this->isAbsolute()) { - $sum = $this->getValue()->add($addend->getValue()); - } else { - $sum = $this->getValue() + $addend->getValue(); - } + $sum = $this->isAbsolute() + ? $this->getValue()->add($addend->getValue()) + : $this->getValue() + $addend->getValue(); return new static($sum); } @@ -137,9 +135,9 @@ public function compare($other) if ($this->isAbsolute()) { return $this->value->compare($other->getValue()); - } else { - return $this->value - $other->getValue(); } + + return $this->value - $other->getValue(); } public function ensureSameType(self $other, $name) diff --git a/src/charge/modifiers/addons/Extremum.php b/src/charge/modifiers/addons/Extremum.php index 0043f845..77ff0f22 100644 --- a/src/charge/modifiers/addons/Extremum.php +++ b/src/charge/modifiers/addons/Extremum.php @@ -1,4 +1,7 @@ value instanceof Money diff --git a/src/charge/modifiers/addons/Minimum.php b/src/charge/modifiers/addons/Minimum.php index 09bcf09b..0e79c1ae 100644 --- a/src/charge/modifiers/addons/Minimum.php +++ b/src/charge/modifiers/addons/Minimum.php @@ -1,4 +1,7 @@ */ -abstract class Period implements AddonInterface +abstract class Period implements AddonInterface, \Stringable { /** * @var int @@ -49,12 +49,9 @@ public function getValue() public static function fromString($string) { - if (preg_match('/^((\d+) +)?(\w+)$/', trim($string), $ms)) { - if (isset(static::$periods[$ms[3]])) { - $class = static::$periods[$ms[3]]; - - return new $class($ms[1] ?: 1); - } + if (preg_match('/^((\d+) +)?(\w+)$/', trim((string) $string), $ms) && isset(static::$periods[$ms[3]])) { + $class = static::$periods[$ms[3]]; + return new $class($ms[1] ?: 1); } throw new FormulaSemanticsError("invalid period given: $string"); diff --git a/src/charge/modifiers/addons/Reason.php b/src/charge/modifiers/addons/Reason.php index 8b66e55e..dffd2c9f 100644 --- a/src/charge/modifiers/addons/Reason.php +++ b/src/charge/modifiers/addons/Reason.php @@ -1,4 +1,7 @@ isAbsolute() || $this->isPercentPoint()) { return $this->multiply($num)->add($start); @@ -30,7 +30,7 @@ public function calculateFor(int $num, ?Discount $min): Discount $start = $start->getValue()/100.0; $factor = $this->getValue()/100.0; - $value = 1 - (1 - $start)*pow(1 - $factor, $num); + $value = 1 - (1 - $start)*(1 - $factor) ** $num; return new Discount($value*100); } diff --git a/src/charge/modifiers/addons/Till.php b/src/charge/modifiers/addons/Till.php index b49fea03..579474d6 100644 --- a/src/charge/modifiers/addons/Till.php +++ b/src/charge/modifiers/addons/Till.php @@ -1,4 +1,7 @@ charge = $charge; - $this->time = $time; + private function __construct( + private readonly ChargeInterface $charge, + private readonly \DateTimeImmutable $time + ) { } public static function onCharge(ChargeInterface $charge, \DateTimeImmutable $time): self diff --git a/src/charge/modifiers/event/InstallmentWasStarted.php b/src/charge/modifiers/event/InstallmentWasStarted.php index 4731b6a2..01a5f36b 100644 --- a/src/charge/modifiers/event/InstallmentWasStarted.php +++ b/src/charge/modifiers/event/InstallmentWasStarted.php @@ -17,19 +17,10 @@ class InstallmentWasStarted extends AbstractEvent implements \JsonSerializable { - /** - * @var ChargeInterface - */ - private $charge; - /** - * @var \DateTimeImmutable - */ - private $time; - - private function __construct(ChargeInterface $charge, DateTimeImmutable $time) - { - $this->charge = $charge; - $this->time = $time; + private function __construct( + private readonly ChargeInterface $charge, + private readonly DateTimeImmutable $time + ) { } public static function onCharge(ChargeInterface $charge, DateTimeImmutable $time): self diff --git a/src/customer/Customer.php b/src/customer/Customer.php index 51658920..6e18c38a 100755 --- a/src/customer/Customer.php +++ b/src/customer/Customer.php @@ -1,4 +1,7 @@ id = $id; - $this->login = $login; + /** + * @param int $id + * @param string $login + */ + public function __construct( + protected $id, + protected $login, + ?CustomerInterface $seller = null + ) { $this->seller = $seller; } @@ -75,11 +72,9 @@ public function getSeller() public static function fromArray(array $info) { - if (!empty($info['seller_id']) && !empty($info['seller'])) { - $seller = new static($info['seller_id'], $info['seller']); - } else { - $seller = null; - } + $seller = !empty($info['seller_id']) && !empty($info['seller']) + ? new static($info['seller_id'], $info['seller']) + : null; return new static($info['id'], $info['login'], $seller); } diff --git a/src/customer/CustomerCreationDto.php b/src/customer/CustomerCreationDto.php index 21ff612c..7e19f7ba 100644 --- a/src/customer/CustomerCreationDto.php +++ b/src/customer/CustomerCreationDto.php @@ -1,4 +1,7 @@ setOperator('and', [$this, 'makeAnd']); + $this->setOperator('and', $this->makeAnd(...)); } public function makeAnd($lhs, $rhs) @@ -34,6 +34,7 @@ public function makeAnd($lhs, $rhs) return new FullCombination($lhs, $rhs); } + #[\Override] public function visitModel(Model $element, &$handle = null, $eldnah = null) { return $this->getExpression($element)->accept($this, $handle, $eldnah); diff --git a/src/formula/FormulaEngine.php b/src/formula/FormulaEngine.php index a1718b21..dea854c6 100755 --- a/src/formula/FormulaEngine.php +++ b/src/formula/FormulaEngine.php @@ -17,7 +17,9 @@ use hiqdev\php\billing\charge\modifiers\Increase; use hiqdev\php\billing\charge\modifiers\Installment; use hiqdev\php\billing\charge\modifiers\Once; +use Hoa\Compiler\Exception\Exception as CompilerException; use Hoa\Ruler\Context; +use Hoa\Ruler\Exception\Interpreter; use Hoa\Ruler\Model\Model; use Hoa\Ruler\Ruler; use Hoa\Visitor\Visit; @@ -47,7 +49,7 @@ class FormulaEngine implements FormulaEngineInterface protected ?Once $once = null; public function __construct( - private CacheInterface $cache + private readonly CacheInterface $cache ) { if (!class_exists(Context::class)) { throw new Exception('to use formula engine install `hoa/ruler`'); @@ -96,9 +98,7 @@ public function interpret(string $formula): Model } return $model; - } catch (\Hoa\Compiler\Exception\Exception $exception) { - throw FormulaSyntaxError::fromException($exception, $formula); - } catch (\Hoa\Ruler\Exception\Interpreter $exception) { + } catch (CompilerException|Interpreter $exception) { throw FormulaSyntaxError::fromException($exception, $formula); } catch (\Throwable $exception) { throw FormulaSyntaxError::create($formula, 'Failed to interpret formula: ' . $exception->getMessage()); @@ -139,7 +139,7 @@ public function validate(string $formula): ?string public function getRuler(): Ruler { - if ($this->ruler === null) { + if (!$this->ruler instanceof Ruler) { $this->ruler = new Ruler(); $this->ruler->setAsserter($this->getAsserter()); } @@ -150,7 +150,7 @@ public function getRuler(): Ruler public function setAsserter(Visit $asserter): self { $this->asserter = $asserter; - if ($this->ruler !== null) { + if ($this->ruler instanceof Ruler) { $this->ruler->setAsserter($asserter); } @@ -159,7 +159,7 @@ public function setAsserter(Visit $asserter): self public function getAsserter(): Visit { - if ($this->asserter === null) { + if (!$this->asserter instanceof Visit) { $this->asserter = new Asserter(); } @@ -168,7 +168,7 @@ public function getAsserter(): Visit public function getContext(): Context { - if ($this->context === null) { + if (!$this->context instanceof Context) { $this->context = $this->buildContext(); } @@ -189,7 +189,7 @@ protected function buildContext(): Context public function getDiscount(): ChargeModifier { - if ($this->discount === null) { + if (!$this->discount instanceof ChargeModifier) { $this->discount = new Discount(); } @@ -198,7 +198,7 @@ public function getDiscount(): ChargeModifier public function getInstallment(): ChargeModifier { - if ($this->installment === null) { + if (!$this->installment instanceof ChargeModifier) { $this->installment = new Installment(); } @@ -207,7 +207,7 @@ public function getInstallment(): ChargeModifier public function getIncrease(): ChargeModifier { - if ($this->increase === null) { + if (!$this->increase instanceof ChargeModifier) { $this->increase = new Increase(); } @@ -216,7 +216,7 @@ public function getIncrease(): ChargeModifier private function getCap(): ChargeModifier { - if ($this->cap === null) { + if (!$this->cap instanceof Cap) { $this->cap = new Cap(); } @@ -225,7 +225,7 @@ private function getCap(): ChargeModifier private function getOnce(): ChargeModifier { - if ($this->once === null) { + if (!$this->once instanceof Once) { $this->once = new Once(); } @@ -234,13 +234,13 @@ private function getOnce(): ChargeModifier public function __clone() { - if ($this->context !== null) { + if ($this->context instanceof Context) { $this->context = clone $this->context; } - if ($this->ruler !== null) { + if ($this->ruler instanceof Ruler) { $this->ruler = clone $this->ruler; } - if ($this->asserter !== null) { + if ($this->asserter instanceof Visit) { $this->asserter = clone $this->asserter; } } diff --git a/src/formula/FormulaEngineException.php b/src/formula/FormulaEngineException.php index f68ff2f3..1b376888 100644 --- a/src/formula/FormulaEngineException.php +++ b/src/formula/FormulaEngineException.php @@ -25,7 +25,7 @@ class FormulaEngineException extends Exception */ private $formula; - public static function fromException(Throwable $previous, string $formula, string $message = null): FormulaEngineException + public static function fromException(Throwable $previous, string $formula, ?string $message = null): FormulaEngineException { if ($message !== null) { $message .= ': '; diff --git a/src/formula/FormulaEngineInterface.php b/src/formula/FormulaEngineInterface.php index 889a7627..94f1d25d 100644 --- a/src/formula/FormulaEngineInterface.php +++ b/src/formula/FormulaEngineInterface.php @@ -1,4 +1,7 @@ calculations = $calculations; @@ -46,12 +41,9 @@ public function __invoke($periods) /** * @var string[] array of strings compatible with `strtotime()`, e.g. `first day of next month` - * @return array */ public function calculateForPeriods($periods): array { - $this->periods = $periods; - return $this->groupCalculationsByTarget(); } @@ -86,16 +78,14 @@ private function groupCalculationsByTarget() } unset($action); - if (!empty($chargesByTargetAndAction['targets'])) { - foreach ($chargesByTargetAndAction['targets'] as &$actions) { - foreach ($actions as &$action) { - $this->decorateAction($action); - } + foreach ($chargesByTargetAndAction['targets'] as &$actions) { + foreach ($actions as &$action) { + $this->decorateAction($action); } } unset($action, $actions); - $result[date("Y-m-d", strtotime($period))] = $chargesByTargetAndAction; + $result[date("Y-m-d", strtotime((string) $period))] = $chargesByTargetAndAction; } return $result; diff --git a/src/order/Billing.php b/src/order/Billing.php index 97edaf47..7cb588c1 100644 --- a/src/order/Billing.php +++ b/src/order/Billing.php @@ -63,7 +63,7 @@ public function __construct( $this->collector = $collector ?? new Collector(); } - public function calculate($source, DateTimeImmutable $time = null): array + public function calculate($source, ?DateTimeImmutable $time = null): array { $charges = $this->calculateCharges($source, $time); $bills = $this->aggregator->aggregateCharges($charges); @@ -71,7 +71,7 @@ public function calculate($source, DateTimeImmutable $time = null): array return $this->merger->mergeBills($bills); } - public function perform($source, DateTimeImmutable $time = null): array + public function perform($source, ?DateTimeImmutable $time = null): array { $charges = $this->calculateCharges($source, $time); $bills = $this->getRepoAggregator()->aggregateCharges($charges); @@ -79,7 +79,7 @@ public function perform($source, DateTimeImmutable $time = null): array return $this->saveBills($bills); } - public function calculateCharges($source, DateTimeImmutable $time = null): array + public function calculateCharges($source, ?DateTimeImmutable $time = null): array { $order = $this->collector->collect($source, $time); @@ -109,9 +109,6 @@ private function saveBills(array $bills): array return $res; } - /** - * @return CalculatorInterface - */ public function getCalculator(): CalculatorInterface { return $this->calculator; diff --git a/src/order/BillingInterface.php b/src/order/BillingInterface.php index 57fe201c..e71fb0d7 100644 --- a/src/order/BillingInterface.php +++ b/src/order/BillingInterface.php @@ -1,4 +1,7 @@ generalizer = $generalizer; - $this->saleRepository = $saleRepository; - $this->planRepository = $planRepository; $this->dateTimeProvider = $dateTimeProvider ?? new ActualDateTimeProvider(); } @@ -92,7 +87,7 @@ public function calculatePlan(PlanInterface $plan, ActionInterface $action): arr public function calculatePrice(PriceInterface $price, ActionInterface $action): array { $charge = $this->calculateCharge($price, $action); - if ($charge === null) { + if (!$charge instanceof ChargeInterface) { return []; } @@ -114,8 +109,6 @@ public function calculatePrice(PriceInterface $price, ActionInterface $action): /** * Calculates charge for given action and price. * Returns `null`, if $price is not applicable to $action. - * - * @return ChargeInterface|Charge|null */ public function calculateCharge(PriceInterface $price, ActionInterface $action): ?ChargeInterface { @@ -123,17 +116,17 @@ public function calculateCharge(PriceInterface $price, ActionInterface $action): return null; } - if ($action->getSale() !== null && $action->getSale()->getTime() > $this->dateTimeProvider->dateTimeImmutable()) { + if ($action->getSale() instanceof SaleInterface && $action->getSale()->getTime() > $this->dateTimeProvider->dateTimeImmutable()) { return null; } $usage = $price->calculateUsage($action->getQuantity()); - if ($usage === null) { + if (!$usage instanceof QuantityInterface) { return null; } $sum = $price->calculateSum($action->getQuantity()); - if ($sum === null) { + if (!$sum instanceof Money) { return null; } @@ -183,7 +176,7 @@ private function findPlans(OrderInterface $order): array } } - if ($lookPlanIds) { + if ($lookPlanIds !== []) { $foundPlans = $this->planRepository->findByIds($lookPlanIds); foreach ($foundPlans as $plan) { $foundPlans[$plan->getId()] = $plan; @@ -200,7 +193,6 @@ private function findPlans(OrderInterface $order): array } /** - * @param OrderInterface $order * @return SaleInterface[] */ private function findSales(OrderInterface $order): array @@ -216,7 +208,7 @@ private function findSales(OrderInterface $order): array } } - if ($lookActions) { + if ($lookActions !== []) { $lookOrder = new Order(null, $order->getCustomer(), $lookActions); $foundSales = $this->saleRepository->findByOrder($lookOrder); foreach ($foundSales as $actionKey => $sale) { diff --git a/src/order/CalculatorInterface.php b/src/order/CalculatorInterface.php index 51b2a780..0ef4e197 100644 --- a/src/order/CalculatorInterface.php +++ b/src/order/CalculatorInterface.php @@ -1,4 +1,7 @@ id = $id; $this->customer = $customer; $this->actions = $actions; } diff --git a/src/order/OrderInterface.php b/src/order/OrderInterface.php index a1f6c3c3..854e79b9 100644 --- a/src/order/OrderInterface.php +++ b/src/order/OrderInterface.php @@ -1,4 +1,7 @@ id = $id; - $this->name = $name; $this->seller = $seller; - $this->prices = $prices; $this->type = $type; - $this->parent_id = $parent_id; } public function getUniqueId() @@ -83,9 +62,6 @@ public function getId() return $this->id; } - /** - * @return string - */ public function getName(): string { return $this->name; diff --git a/src/plan/PlanCreationDto.php b/src/plan/PlanCreationDto.php index 92633ed6..95083c7b 100644 --- a/src/plan/PlanCreationDto.php +++ b/src/plan/PlanCreationDto.php @@ -1,4 +1,7 @@ createAnyPlan($dto); } - protected function createAnyPlan(PlanCreationDto $dto, string $class = null) + protected function createAnyPlan(PlanCreationDto $dto, ?string $class = null) { - $class = $class ?? Plan::class; + $class ??= Plan::class; return new $class( $dto->id, diff --git a/src/plan/PlanFactoryInterface.php b/src/plan/PlanFactoryInterface.php index 32e26ac1..67e187b4 100644 --- a/src/plan/PlanFactoryInterface.php +++ b/src/plan/PlanFactoryInterface.php @@ -1,4 +1,7 @@ id = $id; $this->type = $type; $this->target = $target; $this->plan = $plan; @@ -122,12 +119,12 @@ public function setPlan(PlanInterface $plan) public function calculateSum(QuantityInterface $quantity): ?Money { $usage = $this->calculateUsage($quantity); - if ($usage === null) { + if (!$usage instanceof QuantityInterface) { return null; } $price = $this->calculatePrice($quantity); - if ($price === null) { + if (!$price instanceof Money) { return null; } @@ -151,8 +148,6 @@ public function calculateSum(QuantityInterface $quantity): ?Money * Where we are using the result of this method? * Magic calls can't be determined and I don't know what can be broken if we change the method result. * Which structure must have the result, because array can contain anything? - * - * @return array */ public function jsonSerialize(): array { diff --git a/src/price/EnumPrice.php b/src/price/EnumPrice.php index a2eabb45..71abc4e8 100644 --- a/src/price/EnumPrice.php +++ b/src/price/EnumPrice.php @@ -28,25 +28,16 @@ */ class EnumPrice extends AbstractPrice implements PriceWithSumsInterface, PriceWithCurrencyInterface, PriceWithUnitInterface { - protected UnitInterface $unit; - - protected Currency $currency; - - protected Sums $sums; - public function __construct( $id, TypeInterface $type, TargetInterface $target, ?PlanInterface $plan, - UnitInterface $unit, - Currency $currency, - Sums $sums, + protected UnitInterface $unit, + protected Currency $currency, + protected Sums $sums, ) { parent::__construct($id, $type, $target, $plan); - $this->unit = $unit; - $this->currency = $currency; - $this->sums = $sums; } public function getUnit(): UnitInterface @@ -67,6 +58,7 @@ public function getSums(): Sums /** * {@inheritdoc} */ + #[\Override] public function calculateSum(QuantityInterface $quantity): ?Money { $usage = $this->calculateUsage($quantity)->getQuantity(); @@ -86,12 +78,12 @@ public function calculateSum(QuantityInterface $quantity): ?Money public function calculatePrice(QuantityInterface $quantity): ?Money { $sum = $this->calculateSum($quantity); - if ($sum === null) { + if (!$sum instanceof Money) { return null; } $usage = $this->calculateUsage($quantity); - if ($usage === null) { + if (!$usage instanceof QuantityInterface) { return null; } diff --git a/src/price/FailedCalculatePriceException.php b/src/price/FailedCalculatePriceException.php index 910a41be..a14308a5 100644 --- a/src/price/FailedCalculatePriceException.php +++ b/src/price/FailedCalculatePriceException.php @@ -1,4 +1,7 @@ types = $types; - $this->defaultClass = $defaultClass; } @@ -48,7 +50,7 @@ public function __construct(array $types = [], $defaultClass = null) public function create(PriceCreationDto $dto): PriceInterface { $class = $this->findClassForTypes([ - get_class($dto), + $dto::class, $dto->type->getName(), ]); $method = $this->findMethodForClass($class); diff --git a/src/price/PriceFactoryInterface.php b/src/price/PriceFactoryInterface.php index 2be827e7..88fc28bf 100644 --- a/src/price/PriceFactoryInterface.php +++ b/src/price/PriceFactoryInterface.php @@ -1,4 +1,7 @@ thresholds = $thresholds; $this->price = $price; $this->prepaid = $prepaid; } @@ -81,6 +78,7 @@ public function getCalculationTraces(): array return $this->calculationTraces; } + #[\Override] public function calculateSum(QuantityInterface $quantity): ?Money { $this->calculationTraces = []; @@ -105,8 +103,8 @@ public function calculateSum(QuantityInterface $quantity): ?Money $price = $threshold->price(); $chargedAmount = $price->money() - ->multiply((string)(sprintf('%.14F', $billedUsage->getQuantity()))) - ->divide((string)(sprintf('%.14F', $price->multiplier()))); + ->multiply(sprintf('%.14F', $billedUsage->getQuantity())) + ->divide(sprintf('%.14F', $price->multiplier())); $this->calculationTraces[] = new ProgressivePriceCalculationTrace( $threshold, $billedUsage, $chargedAmount diff --git a/src/price/ProgressivePriceThreshold.php b/src/price/ProgressivePriceThreshold.php index 120e4e99..f4697d5c 100644 --- a/src/price/ProgressivePriceThreshold.php +++ b/src/price/ProgressivePriceThreshold.php @@ -14,27 +14,24 @@ class ProgressivePriceThreshold implements JsonSerializable { - /** - * @var numeric-string $price The price of the progressive price threshold in currency (not cents) - */ - private string $price; - - private string $currency; - - private string $quantity; - - private string $unit; - - private function __construct(string $price, string $currency, string $quantity, string $unit) - { + private readonly string $currency; + + private readonly string $quantity; + + private function __construct( + /** + * @var numeric-string $price The price of the progressive price threshold in currency (not cents) + */ + private readonly string $price, + string $currency, + string $quantity, + private readonly string $unit + ) { if ($quantity < 0) { throw new InvalidArgumentException('Quantity of the progressive price threshold must be positive'); } - - $this->price = $price; $this->currency = strtoupper($currency); $this->quantity = $quantity; - $this->unit = $unit; } public static function createFromScalar(string $price, string $currency, string $quantity, string $unit): self diff --git a/src/price/ProgressivePriceThresholdList.php b/src/price/ProgressivePriceThresholdList.php index fa3b3a09..b8244ee6 100644 --- a/src/price/ProgressivePriceThresholdList.php +++ b/src/price/ProgressivePriceThresholdList.php @@ -39,14 +39,12 @@ public function __construct(array $thresholds) */ public static function fromScalarsArray(array $thresholds): self { - return new self(array_map(function ($threshold) { - return ProgressivePriceThreshold::createFromScalar( - $threshold['price'], - $threshold['currency'], - $threshold['quantity'], - $threshold['unit'] - ); - }, $thresholds)); + return new self(array_map(fn($threshold) => ProgressivePriceThreshold::createFromScalar( + $threshold['price'], + $threshold['currency'], + $threshold['quantity'], + $threshold['unit'] + ), $thresholds)); } private function checkCanBeAdded(ProgressivePriceThreshold $threshold): void diff --git a/src/price/RatePrice.php b/src/price/RatePrice.php index 71fff5f2..360df752 100644 --- a/src/price/RatePrice.php +++ b/src/price/RatePrice.php @@ -26,17 +26,14 @@ */ class RatePrice extends AbstractPrice implements PriceWithRateInterface { - protected float $rate; - public function __construct( $id, TypeInterface $type, TargetInterface $target, ?PlanInterface $plan, - float $rate + protected float $rate ) { parent::__construct($id, $type, $target, $plan); - $this->rate = $rate; } public function getRate(): float @@ -44,6 +41,7 @@ public function getRate(): float return $this->rate; } + #[\Override] public function calculateSum(QuantityInterface $quantity): ?Money { $sum = $quantity->multiply((string) -$this->rate); @@ -55,12 +53,12 @@ public function calculateSum(QuantityInterface $quantity): ?Money public function calculatePrice(QuantityInterface $quantity): ?Money { $sum = $this->calculateSum($quantity); - if ($sum === null) { + if (!$sum instanceof Money) { return null; } $usage = $this->calculateUsage($quantity); - if ($usage === null) { + if (!$usage instanceof QuantityInterface) { return null; } diff --git a/src/price/SinglePrice.php b/src/price/SinglePrice.php index 99c1ba33..0b667aac 100644 --- a/src/price/SinglePrice.php +++ b/src/price/SinglePrice.php @@ -36,9 +36,9 @@ public function __construct( $id, TypeInterface $type, TargetInterface $target, - PlanInterface $plan = null, - QuantityInterface $prepaid, - Money $price + ?PlanInterface $plan = null, + ?QuantityInterface $prepaid = null, + ?Money $price = null ) { parent::__construct($id, $type, $target, $plan); $this->prepaid = $prepaid; diff --git a/src/price/SumsHydrator.php b/src/price/SumsHydrator.php index 6ce98fe9..cad2e5d5 100644 --- a/src/price/SumsHydrator.php +++ b/src/price/SumsHydrator.php @@ -6,6 +6,7 @@ class SumsHydrator extends GeneratedHydrator { + #[\Override] public function hydrate(array $data, $object): object { if (!isset($data['sums'])) { diff --git a/src/product/Application/BillingRegistryService.php b/src/product/Application/BillingRegistryService.php index 8f9e53af..33be4a15 100644 --- a/src/product/Application/BillingRegistryService.php +++ b/src/product/Application/BillingRegistryService.php @@ -17,9 +17,9 @@ use hiqdev\php\billing\type\Type; use hiqdev\php\billing\type\TypeInterface; -final class BillingRegistryService implements BillingRegistryServiceInterface +final readonly class BillingRegistryService implements BillingRegistryServiceInterface { - public function __construct(private readonly BillingRegistryInterface $registry) + public function __construct(private BillingRegistryInterface $registry) { } @@ -88,7 +88,7 @@ public function getBehavior(string $type, string $behaviorClassWrapper): Behavio if ($priceTypeDefinition->hasType($billingType)) { $behavior = $this->findBehaviorInPriceType($priceTypeDefinition, $behaviorClassWrapper); - if ($behavior) { + if ($behavior instanceof BehaviorInterface) { return $behavior; } } diff --git a/src/product/Application/BillingRegistryServiceInterface.php b/src/product/Application/BillingRegistryServiceInterface.php index 7d38ddb3..3707cf74 100644 --- a/src/product/Application/BillingRegistryServiceInterface.php +++ b/src/product/Application/BillingRegistryServiceInterface.php @@ -16,36 +16,25 @@ interface BillingRegistryServiceInterface { /** - * @param string $representationClass * @return RepresentationInterface[] */ public function getRepresentationsByType(string $representationClass): array; - /** - * @deprecated - please use getPriceTypeDefinitionByPriceTypeName() method instead - * @param string $type - * @return AggregateInterface - */ + #[\Deprecated(message: '- please use getPriceTypeDefinitionByPriceTypeName() method instead')] public function getAggregate(string $type): AggregateInterface; /** - * @param string $typeName - * @return PriceTypeDefinitionInterface * @throws PriceTypeDefinitionNotFoundException */ public function getPriceTypeDefinitionByPriceTypeName(string $typeName): PriceTypeDefinitionInterface; /** - * @param string $tariffName - * @return TariffTypeDefinitionInterface * @throws TariffTypeDefinitionNotFoundException */ public function getTariffTypeDefinitionByTariffName(string $tariffName): TariffTypeDefinitionInterface; /** * @param string $type - full type like 'overuse,lb_capacity_unit' - * @param string $behaviorClassWrapper - * @return BehaviorInterface * @throws BehaviorNotFoundException * @throws InvalidBehaviorException */ @@ -55,7 +44,6 @@ public function getBehavior(string $type, string $behaviorClassWrapper): Behavio /** * Find all behaviors attached to any TariffType or PriceType by specified Behavior class. * - * @param string $behaviorClassWrapper * @return Generator */ public function getBehaviors(string $behaviorClassWrapper): Generator; @@ -63,7 +51,6 @@ public function getBehaviors(string $behaviorClassWrapper): Generator; /** * Find all PriceTypeDefinition in registry by specified Behavior class. * - * @param string $behaviorClassWrapper * @return Generator */ public function findPriceTypeDefinitionsByBehavior(string $behaviorClassWrapper): Generator; diff --git a/src/product/Domain/Model/Price/Exception/InvalidPriceTypeCollectionException.php b/src/product/Domain/Model/Price/Exception/InvalidPriceTypeCollectionException.php index c3bc435e..17e7e6ad 100644 --- a/src/product/Domain/Model/Price/Exception/InvalidPriceTypeCollectionException.php +++ b/src/product/Domain/Model/Price/Exception/InvalidPriceTypeCollectionException.php @@ -10,7 +10,7 @@ class InvalidPriceTypeCollectionException extends InvalidArgumentException { public static function becauseContainsNonPriceType(mixed $value): self { - $given = is_object($value) ? get_class($value) : gettype($value); + $given = get_debug_type($value); return new self(sprintf( 'PriceTypeCollection can only contain instances of PriceTypeInterface. Got: %s', diff --git a/src/product/Domain/Model/Price/PriceTypeCollection.php b/src/product/Domain/Model/Price/PriceTypeCollection.php index 9d374958..5b2b0904 100644 --- a/src/product/Domain/Model/Price/PriceTypeCollection.php +++ b/src/product/Domain/Model/Price/PriceTypeCollection.php @@ -17,7 +17,7 @@ class PriceTypeCollection implements IteratorAggregate, Countable /** * @var string[] - flipped type names for fast search */ - private array $flippedTypeNames; + private readonly array $flippedTypeNames; public function __construct(private readonly array $types = []) { diff --git a/src/product/InvoiceDescriptionsBuilder.php b/src/product/InvoiceDescriptionsBuilder.php index 8607ba0a..3e24f51a 100644 --- a/src/product/InvoiceDescriptionsBuilder.php +++ b/src/product/InvoiceDescriptionsBuilder.php @@ -4,11 +4,9 @@ class InvoiceDescriptionsBuilder { - private BillingRegistry $registry; - - public function __construct(BillingRegistry $registry) - { - $this->registry = $registry; + public function __construct( + private readonly BillingRegistry $registry + ) { } public function build(): array diff --git a/src/product/TariffTypeDefinition.php b/src/product/TariffTypeDefinition.php index 730517eb..50a197f7 100644 --- a/src/product/TariffTypeDefinition.php +++ b/src/product/TariffTypeDefinition.php @@ -60,7 +60,7 @@ public function getProduct(): ProductInterface private function ensureProductExists(): void { - if ($this->product === null) { + if (!$this->product instanceof ProductInterface) { throw new ProductNotDefinedException('Product is not set. Call the ofProduct() method first.'); } } diff --git a/src/product/TariffTypeDefinitionInterface.php b/src/product/TariffTypeDefinitionInterface.php index f6e7a847..5c31a490 100644 --- a/src/product/TariffTypeDefinitionInterface.php +++ b/src/product/TariffTypeDefinitionInterface.php @@ -19,9 +19,6 @@ public function tariffType(): TariffTypeInterface; /** * Check if TariffTypeDefinition belongs to specified TariffType - * - * @param TariffTypeInterface $tariffType - * @return bool */ public function belongToTariffType(TariffTypeInterface $tariffType): bool; diff --git a/src/product/behavior/BehaviorInterface.php b/src/product/behavior/BehaviorInterface.php index cc18ac94..1202489a 100644 --- a/src/product/behavior/BehaviorInterface.php +++ b/src/product/behavior/BehaviorInterface.php @@ -18,7 +18,6 @@ public function getTariffType(): TariffTypeInterface; * The description can be either static, or use the object values. * * It can be later used for UI or documentation purposes. - * @return string */ public function description(): string; } diff --git a/src/product/behavior/BehaviorPriceTypeDefinitionCollection.php b/src/product/behavior/BehaviorPriceTypeDefinitionCollection.php index 780b2a6c..b9b64f57 100644 --- a/src/product/behavior/BehaviorPriceTypeDefinitionCollection.php +++ b/src/product/behavior/BehaviorPriceTypeDefinitionCollection.php @@ -13,20 +13,16 @@ */ class BehaviorPriceTypeDefinitionCollection extends BehaviorCollection { - /** - * @psalm-var TPriceDefinition - */ - private readonly PriceTypeDefinitionInterface $parent; - /** * @psalm-param TPriceDefinition $parent */ public function __construct( - PriceTypeDefinitionInterface $parent, + /** + * @psalm-var TPriceDefinition + */ + private readonly PriceTypeDefinitionInterface $parent, TariffTypeInterface $tariffType ) { - $this->parent = $parent; - parent::__construct($tariffType); } diff --git a/src/product/behavior/PriceTypeBehaviorRegistry.php b/src/product/behavior/PriceTypeBehaviorRegistry.php index cc09de2b..f446866f 100644 --- a/src/product/behavior/PriceTypeBehaviorRegistry.php +++ b/src/product/behavior/PriceTypeBehaviorRegistry.php @@ -15,7 +15,7 @@ final class PriceTypeBehaviorRegistry extends BehaviorRegistry /** * @var BehaviorPriceTypeDefinitionCollection */ - private BehaviorPriceTypeDefinitionCollection $behaviorCollection; + private readonly BehaviorPriceTypeDefinitionCollection $behaviorCollection; /** * @psalm-param T $priceTypeDefinition diff --git a/src/product/behavior/TariffTypeBehaviorRegistry.php b/src/product/behavior/TariffTypeBehaviorRegistry.php index 1644bb16..8629bec3 100644 --- a/src/product/behavior/TariffTypeBehaviorRegistry.php +++ b/src/product/behavior/TariffTypeBehaviorRegistry.php @@ -31,7 +31,7 @@ final class TariffTypeBehaviorRegistry extends BehaviorRegistry /** * @var BehaviorTariffTypeCollection */ - private BehaviorTariffTypeCollection $behaviorCollection; + private readonly BehaviorTariffTypeCollection $behaviorCollection; /** * @psalm-param T $tariffTypeDefinition diff --git a/src/product/invoice/RepresentationCollection.php b/src/product/invoice/RepresentationCollection.php index ba90e2eb..dcf327bd 100644 --- a/src/product/invoice/RepresentationCollection.php +++ b/src/product/invoice/RepresentationCollection.php @@ -21,18 +21,15 @@ class RepresentationCollection implements IteratorAggregate, HasLockInterface private RepresentationUniquenessGuard $uniquenessGuard; - /** - * @psalm-var T - */ - private readonly PriceTypeDefinition $priceTypeDefinition; - /** * @psalm-param T $priceTypeDefinition */ public function __construct( - PriceTypeDefinition $priceTypeDefinition, + /** + * @psalm-var T + */ + private readonly PriceTypeDefinition $priceTypeDefinition, ) { - $this->priceTypeDefinition = $priceTypeDefinition; $this->uniquenessGuard = new RepresentationUniquenessGuard(); } diff --git a/src/product/price/PriceTypeDefinition.php b/src/product/price/PriceTypeDefinition.php index 1e3b4aa4..5df4e35e 100644 --- a/src/product/price/PriceTypeDefinition.php +++ b/src/product/price/PriceTypeDefinition.php @@ -48,20 +48,17 @@ class PriceTypeDefinition implements PriceTypeDefinitionInterface private ?AggregateInterface $aggregate = null; - /** @psalm-var TParentCollection */ - private readonly PriceTypeDefinitionCollectionInterface $parent; - private readonly PriceTypeBehaviorRegistry $behaviorRegistry; /** * @param TParentCollection $parent */ public function __construct( - PriceTypeDefinitionCollectionInterface $parent, + /** @psalm-var TParentCollection */ + private readonly PriceTypeDefinitionCollectionInterface $parent, private readonly TypeInterface $type, TariffTypeInterface $tariffType, ) { - $this->parent = $parent; $this->representationCollection = new RepresentationCollection($this); $this->behaviorRegistry = new PriceTypeBehaviorRegistry($this, $tariffType); @@ -204,12 +201,11 @@ public function aggregation(AggregateInterface $aggregate): static } /** - * @return AggregateInterface * @throws AggregateNotDefinedException */ public function getAggregate(): AggregateInterface { - if ($this->aggregate === null) { + if (!$this->aggregate instanceof AggregateInterface) { throw new AggregateNotDefinedException('Aggregate is not set. Call the aggregation() method first.'); } diff --git a/src/product/price/PriceTypeDefinitionCollection.php b/src/product/price/PriceTypeDefinitionCollection.php index b0a45693..dd5d72f7 100644 --- a/src/product/price/PriceTypeDefinitionCollection.php +++ b/src/product/price/PriceTypeDefinitionCollection.php @@ -31,7 +31,7 @@ public function __construct( */ private readonly TariffTypeDefinitionInterface $parent, private readonly PriceTypeDefinitionFactoryInterface $factory, - PriceTypeDefinitionCollectionInterface $collectionInstance = null, + ?PriceTypeDefinitionCollectionInterface $collectionInstance = null, ) { $this->storage = new PriceTypeStorage(); $this->collectionInstance = $collectionInstance ?? $this; diff --git a/src/product/price/PriceTypeDefinitionCollectionInterface.php b/src/product/price/PriceTypeDefinitionCollectionInterface.php index d800a15e..033043d7 100644 --- a/src/product/price/PriceTypeDefinitionCollectionInterface.php +++ b/src/product/price/PriceTypeDefinitionCollectionInterface.php @@ -27,7 +27,6 @@ public function getIterator(): Traversable; public function priceType(TypeInterface $type): PriceTypeDefinitionInterface; /** - * @return TariffTypeDefinitionInterface * @plsam-return M */ public function end(): TariffTypeDefinitionInterface; @@ -36,7 +35,6 @@ public function end(): TariffTypeDefinitionInterface; * For easier understanding and establishing a relationship between PriceTypeDefinitionCollection * and TariffTypeDefinition * - * @return TariffTypeDefinitionInterface * @plsam-return M */ public function getTariffTypeDefinition(): TariffTypeDefinitionInterface; diff --git a/src/product/price/PriceTypeDefinitionInterface.php b/src/product/price/PriceTypeDefinitionInterface.php index 2098f833..3c972f71 100644 --- a/src/product/price/PriceTypeDefinitionInterface.php +++ b/src/product/price/PriceTypeDefinitionInterface.php @@ -55,9 +55,6 @@ public function getUnit(): UnitInterface; /** * це параметер визначає агрегатну функцію яка застосовується для щоденно записаних ресурсів щоб визнизначти * місячне споживання за яке потрібно пробілити клієнта - * - * @param AggregateInterface $aggregate - * @return static */ public function aggregation(AggregateInterface $aggregate): static; @@ -65,8 +62,6 @@ public function getAggregate(): AggregateInterface; /** * For establishing a relationship between PriceTypeDefinition and TariffTypeDefinition - * - * @return TariffTypeDefinitionInterface */ public function getTariffTypeDefinition(): TariffTypeDefinitionInterface; diff --git a/src/product/quantity/FractionQuantityData.php b/src/product/quantity/FractionQuantityData.php index 5f6d409e..e94561a5 100644 --- a/src/product/quantity/FractionQuantityData.php +++ b/src/product/quantity/FractionQuantityData.php @@ -4,11 +4,11 @@ use hiqdev\php\units\Quantity; -final class FractionQuantityData +final readonly class FractionQuantityData { public function __construct( - public readonly Quantity $quantity, - public readonly string $time, - public readonly ?float $fractionOfMonth + public Quantity $quantity, + public string $time, + public ?float $fractionOfMonth ) {} } diff --git a/src/product/quantity/QuantityFormatterDefinition.php b/src/product/quantity/QuantityFormatterDefinition.php index 15da673f..a968c445 100644 --- a/src/product/quantity/QuantityFormatterDefinition.php +++ b/src/product/quantity/QuantityFormatterDefinition.php @@ -6,20 +6,14 @@ class QuantityFormatterDefinition { - /** @var class-string */ - private string $formatterClass; - - /** @var FractionUnitInterface|null|string */ - private $fractionUnit; - /** * @param class-string $formatterClass * @param FractionUnitInterface|string|null $fractionUnit */ - public function __construct(string $formatterClass, $fractionUnit = null) - { - $this->formatterClass = $formatterClass; - $this->fractionUnit = $fractionUnit; + public function __construct( + private readonly string $formatterClass, + private $fractionUnit = null + ) { } /** diff --git a/src/product/quantity/QuantityFormatterInterface.php b/src/product/quantity/QuantityFormatterInterface.php index 80966e83..90414e6e 100644 --- a/src/product/quantity/QuantityFormatterInterface.php +++ b/src/product/quantity/QuantityFormatterInterface.php @@ -7,22 +7,16 @@ interface QuantityFormatterInterface /** * Returns textual user friendly representation of the quantity. * E.g. 20 days, 30 GB, 1 year. - * - * @return string */ public function format(): string; /** * Returns numeric to be saved in DB. - * - * @return string */ public function getValue(): string; /** * Returns numeric user friendly representation of the quantity. - * - * @return string */ public function getClientValue(): string; } diff --git a/src/product/trait/HasLock.php b/src/product/trait/HasLock.php index b27b0124..22a42ce1 100644 --- a/src/product/trait/HasLock.php +++ b/src/product/trait/HasLock.php @@ -35,7 +35,6 @@ protected function afterLock(): void /** * @param HasLockInterface[] $items - * @return void */ protected function lockItems(array $items): void { diff --git a/src/sale/AbstractSaleRepository.php b/src/sale/AbstractSaleRepository.php index d5b7c42a..b0a593b1 100644 --- a/src/sale/AbstractSaleRepository.php +++ b/src/sale/AbstractSaleRepository.php @@ -1,4 +1,7 @@ id = $id; $this->target = $target; $this->customer = $customer; $this->plan = $plan; $this->time = $time ?? new DateTimeImmutable(); - $this->data = $data; } public function getId() @@ -107,7 +101,7 @@ public function getCloseTime(): ?DateTimeImmutable public function close(DateTimeImmutable $closeTime): self { - if ($this->closeTime !== null) { + if ($this->closeTime instanceof \DateTimeImmutable) { throw new InvariantException('Sale is already closed'); } diff --git a/src/sale/SaleCreationDto.php b/src/sale/SaleCreationDto.php index 144b6d50..c66e2519 100644 --- a/src/sale/SaleCreationDto.php +++ b/src/sale/SaleCreationDto.php @@ -1,4 +1,7 @@ customer = $customer; - $this->time = $time; - $this->balance = $balance; - $this->bills = $bills; - $this->period = $period; - $this->month = $month; - $this->total = $total; - $this->payment = $payment; - $this->amount = $amount; - $this->plans = $plans; } public function getCustomer(): CustomerInterface diff --git a/src/statement/StatementBill.php b/src/statement/StatementBill.php index 943f51aa..d93d4ab6 100644 --- a/src/statement/StatementBill.php +++ b/src/statement/StatementBill.php @@ -43,9 +43,6 @@ class StatementBill extends Bill implements StatementBillInterface /** @var string */ protected $from; - /** @var int */ - protected int $unique_objects_count = 0; - /** @var TypeInterface */ protected $tariff_type; @@ -57,16 +54,16 @@ public function __construct( QuantityInterface $quantity, CustomerInterface $customer, DateTimeImmutable $month, - int $unique_objects_count, - Money $price = null, - Money $overuse = null, - QuantityInterface $prepaid = null, + protected int $unique_objects_count, + ?Money $price = null, + ?Money $overuse = null, + ?QuantityInterface $prepaid = null, array $charges = [], - TargetInterface $target = null, - PlanInterface $plan = null, - BillState $state = null, + ?TargetInterface $target = null, + ?PlanInterface $plan = null, + ?BillState $state = null, ?string $from = null, - TypeInterface $tariff_type = null + ?TypeInterface $tariff_type = null ) { parent::__construct( $id, @@ -81,7 +78,6 @@ public function __construct( $state ); $this->month = $month; - $this->unique_objects_count = $unique_objects_count; $this->price = $price; $this->overuse = $overuse; $this->prepaid = $prepaid; diff --git a/src/statement/StatementBillInterface.php b/src/statement/StatementBillInterface.php index 43db5979..2fbe06e7 100644 --- a/src/statement/StatementBillInterface.php +++ b/src/statement/StatementBillInterface.php @@ -1,4 +1,7 @@ id = $id; - $this->type = $type; - $this->name = $name; } /** @@ -67,7 +54,7 @@ public function hasId() public function setId($id) { - if ((string) $this->id === (string) $id) { + if ((string)$this->id === (string)$id) { return; } if ($this->hasId()) { @@ -172,20 +159,22 @@ protected function matchStrings($lhs, $rhs) return false; } - return (string) $lhs === (string) $rhs; + return (string)$lhs === (string)$rhs; } public function jsonSerialize(): array { - return array_filter(array_merge( - get_object_vars($this), - [ - 'id' => $this->getId(), - 'type' => $this->getType(), - 'state' => $this->getState(), - 'name' => $this->getName(), - ], - )); + return array_filter( + array_merge( + get_object_vars($this), + [ + 'id' => $this->getId(), + 'type' => $this->getType(), + 'state' => $this->getState(), + 'name' => $this->getName(), + ], + ) + ); } protected static $anyTarget; diff --git a/src/target/RenewableTarget.php b/src/target/RenewableTarget.php index dad98fc9..3e1b908f 100644 --- a/src/target/RenewableTarget.php +++ b/src/target/RenewableTarget.php @@ -1,4 +1,7 @@ target = $target; } public function getTarget(): TargetInterface diff --git a/src/tools/AggregationException.php b/src/tools/AggregationException.php index 400f05b5..15bdf46c 100644 --- a/src/tools/AggregationException.php +++ b/src/tools/AggregationException.php @@ -1,4 +1,7 @@ getUniqueString(); - if (empty($bills[$uid])) { - $bills[$uid] = $bill; - } else { - $bills[$uid] = $this->aggregateBill($bills[$uid], $bill); - } + $bills[$uid] = empty($bills[$uid]) + ? $bill + : $this->aggregateBill($bills[$uid], $bill); } return $bills; diff --git a/src/tools/AggregatorInterface.php b/src/tools/AggregatorInterface.php index 83737a28..d738b5e7 100644 --- a/src/tools/AggregatorInterface.php +++ b/src/tools/AggregatorInterface.php @@ -1,4 +1,7 @@ */ -final class CachedDateTimeProvider implements CurrentDateTimeProviderInterface +final readonly class CachedDateTimeProvider implements CurrentDateTimeProviderInterface { - private DateTimeImmutable $dateTimeImmutable; - - public function __construct(DateTimeImmutable $dateTimeImmutable) + public function __construct(private DateTimeImmutable $dateTimeImmutable) { - $this->dateTimeImmutable = $dateTimeImmutable; } public function dateTimeImmutable(): DateTimeImmutable diff --git a/src/tools/DbMergingAggregator.php b/src/tools/DbMergingAggregator.php index cf70c280..d95431b5 100644 --- a/src/tools/DbMergingAggregator.php +++ b/src/tools/DbMergingAggregator.php @@ -1,4 +1,7 @@ billRepository = $billRepository; - $this->merger = $merger; - $this->localAggregator = $localAggregator; } public function mergeBills(array $bills): array diff --git a/src/tools/Factory.php b/src/tools/Factory.php index 95be85ad..23a4ff72 100644 --- a/src/tools/Factory.php +++ b/src/tools/Factory.php @@ -27,11 +27,8 @@ class Factory implements FactoryInterface { private $entities = []; - private $factories = []; - - public function __construct(array $factories) + public function __construct(private array $factories) { - $this->factories = $factories; } public function getMoney($data) @@ -51,7 +48,7 @@ public function getSums($data) public function parseMoney($str) { - [$amount, $currency] = explode(' ', $str); + [$amount, $currency] = explode(' ', (string) $str); return [ 'amount' => $amount*100, @@ -61,7 +58,7 @@ public function parseMoney($str) public function createMoney($data) { - return new Money($data['amount'], new Currency(strtoupper($data['currency']))); + return new Money($data['amount'], new Currency(strtoupper((string) $data['currency']))); } public function getCurrency($data) @@ -76,7 +73,7 @@ public function getQuantity($data) public function parseQuantity($str) { - [$quantity, $unit] = explode(' ', $str); + [$quantity, $unit] = explode(' ', (string) $str); return [ 'quantity' => $quantity, @@ -218,12 +215,8 @@ public function parseByUnique(string $entity, $str, $delimiter = ':') if (count($keys) === 1) { return [reset($keys) => $str]; } - $parts = explode($delimiter, $str, count($keys)); - if (count($parts) === count($keys)) { - $res = array_combine($keys, $parts); - } else { - $res = []; - } + $parts = explode($delimiter, (string) $str, count($keys)); + $res = count($parts) === count($keys) ? array_combine($keys, $parts) : []; $res['id'] = $str; return $res; diff --git a/src/tools/FactoryNotFoundException.php b/src/tools/FactoryNotFoundException.php index 095859fb..c26a98cd 100644 --- a/src/tools/FactoryNotFoundException.php +++ b/src/tools/FactoryNotFoundException.php @@ -1,4 +1,7 @@ getUniqueString(); - if (empty($res[$uid])) { - $res[$uid] = $bill; - } else { - $res[$uid] = $this->mergeBill($res[$uid], $bill); - } + $res[$uid] = empty($res[$uid]) ? $bill : $this->mergeBill($res[$uid], $bill); } return $res; @@ -71,11 +67,7 @@ protected function mergeCharges(array $charges): array $res = []; foreach ($charges as $charge) { $uid = $charge->getUniqueString(); - if (empty($res[$uid])) { - $res[$uid] = $charge; - } else { - $res[$uid] = $this->mergeCharge($res[$uid], $charge); - } + $res[$uid] = empty($res[$uid]) ? $charge : $this->mergeCharge($res[$uid], $charge); } return $res; diff --git a/src/tools/MergerInterface.php b/src/tools/MergerInterface.php index c2d97d8d..7c6f248a 100644 --- a/src/tools/MergerInterface.php +++ b/src/tools/MergerInterface.php @@ -1,4 +1,7 @@ id = $id; - $this->name = $name; + public function __construct( + /** + * @var int|string|null|float The unique identifier of the type. Can be an integer or string. + * Special values: + * - `Type::ANY` indicates that the type can match any ID. + * - `Type::NONE` indicates that there is no valid ID. + */ + protected $id, + /** + * @var string|null|float The name of the type. Can be a specific name or one of the special values: + * - `Type::ANY` indicates that the type can match any name. + * - `Type::NONE` indicates that there is no valid name. + */ + protected $name = self::ANY + ) { } /** @@ -83,7 +83,7 @@ protected function checkMatches($lhs, $rhs) return false; } - return (string) $lhs === (string) $rhs; + return (string)$lhs === (string)$rhs; } public function jsonSerialize(): array diff --git a/src/type/TypeCreationDto.php b/src/type/TypeCreationDto.php index 86a38240..19a60250 100644 --- a/src/type/TypeCreationDto.php +++ b/src/type/TypeCreationDto.php @@ -1,4 +1,7 @@ target = $target; - $this->time = $time; - $this->type = $type; - $this->amount = $amount; + public function __construct( + private readonly TargetInterface $target, + private readonly DateTimeImmutable $time, + private readonly TypeInterface $type, + private readonly Quantity $amount + ) { } public function target(): TargetInterface