From 66c553749af98f93f4544c9128495524eb87dd48 Mon Sep 17 00:00:00 2001 From: Shelepov G Date: Mon, 27 Sep 2021 14:49:06 +0300 Subject: [PATCH 1/4] php 8 compatibility refs #3 --- composer.json | 22 ++-- phpstan.neon | 1 + phpunit.xml.dist | 31 ++--- psalm.xml | 2 - src/BaseMoney.php | 173 +++++++++++++++++--------- src/Bitcoin.php | 6 +- src/Currency.php | 24 ++-- src/Exception/CannotCreateMoney.php | 12 +- src/Exception/CannotWorkWithMoney.php | 4 +- src/GaapMoney.php | 4 +- src/Money.php | 9 +- src/Type/BTCMoneyType.php | 33 +++-- src/Type/CurrencyType.php | 9 +- src/Type/GaapMoneyType.php | 33 +++-- src/Type/MoneyType.php | 33 +++-- 15 files changed, 246 insertions(+), 150 deletions(-) diff --git a/composer.json b/composer.json index 19d9e25..def5c37 100644 --- a/composer.json +++ b/composer.json @@ -18,21 +18,21 @@ } ], "require": { - "php": "^7.4", + "php": "~8.0", "ext-bcmath": "*", - "doctrine/dbal": "^2.10", - "moneyphp/money": "^3.3", - "thecodingmachine/safe": "^1.0" + "doctrine/dbal": "^3.1", + "moneyphp/money": "^4.0", + "thecodingmachine/safe": "^1.3" }, "require-dev": { - "doctrine/coding-standard": "^7.0", - "phpstan/phpstan": "^0.12.11", - "phpunit/phpunit": "^7.5", - "roave/no-floaters": "^1.3", + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^0.12", + "phpunit/phpunit": "^9.5", + "roave/no-floaters": "^1.4", "sensiolabs/security-checker": "^6.0", - "squizlabs/php_codesniffer": "^3.5", + "squizlabs/php_codesniffer": "^3.6", "thecodingmachine/phpstan-safe-rule": "^1.0", - "vimeo/psalm": "^3.9" + "vimeo/psalm": "^4.10" }, "minimum-stability": "stable", "config": { @@ -56,7 +56,7 @@ "csfix": "phpcbf", "psalm": "psalm", "stan": "phpstan analyze src -l 8 --memory-limit=512m", - "sec": "security-checker security:check", + "sec": "rm -f local-php-security-checker && curl -s https://api.github.com/repos/fabpot/local-php-security-checker/releases/latest | grep -E \"browser_download_url(.+)linux_amd64\" | cut -d : -f 2,3 | tr -d \\\" | xargs -I % curl % -L -o local-php-security-checker && chmod +x local-php-security-checker && ./local-php-security-checker", "test": "phpunit", "all": "composer psalm && composer stan && composer test && composer cs && composer sec" } diff --git a/phpstan.neon b/phpstan.neon index 673933f..c888f1b 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,6 @@ parameters: checkMissingIterableValueType: false + reportUnmatchedIgnoredErrors: false includes: - vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon - vendor/roave/no-floaters/rules.neon \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index de264bb..7a1caeb 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,20 +1,13 @@ - - - - ./tests/ - - - - - - ./src/ - - - \ No newline at end of file + + + + ./src/ + + + + + ./tests/ + + + diff --git a/psalm.xml b/psalm.xml index 1ae0871..d7f7ed9 100644 --- a/psalm.xml +++ b/psalm.xml @@ -3,7 +3,6 @@ totallyTyped="true" resolveFromConfigFile="true" useDocblockTypes="true" - requireVoidReturnType="true" allowPhpStormGenerics="true" ignoreInternalFunctionFalseReturn="false" ignoreInternalFunctionNullReturn="false" @@ -35,7 +34,6 @@ - diff --git a/src/BaseMoney.php b/src/BaseMoney.php index 012df14..335563d 100644 --- a/src/BaseMoney.php +++ b/src/BaseMoney.php @@ -11,23 +11,31 @@ use OnMoon\Money\Exception\CannotCreateMoney; use OnMoon\Money\Exception\CannotWorkWithMoney; use RuntimeException; + use function array_map; use function bcdiv; use function bcmul; -use function get_class; use function Safe\preg_match; use function Safe\substr; use function str_pad; use function strpos; + use const STR_PAD_RIGHT; abstract class BaseMoney { private const HUMAN_READABLE_NAME = 'Money'; + /** @psalm-var numeric-string */ protected string $amount; + + /** @psalm-var non-empty-string */ protected string $currency; + /** + * @psalm-param numeric-string $amount + * @psalm-param non-empty-string $currency + */ final private function __construct(string $amount, string $currency) { $libCurrency = new LibCurrency($currency); @@ -66,9 +74,11 @@ final private function __construct(string $amount, string $currency) } /** + * @psalm-param numeric-string $amount + * * @return static */ - final public static function create(string $amount, Currency $currency) : self + final public static function create(string $amount, Currency $currency): self { $money = new static($amount, $currency->getCode()); @@ -109,14 +119,14 @@ final public static function create(string $amount, Currency $currency) : self return $money; } - final public static function createFromMoney(self $money) : self + final public static function createFromMoney(self $money): self { static::assertSameSubUnit($money, __FUNCTION__); return static::create($money->getAmount(), $money->getCurrency()); } - final public function convert(Converter $converter, Currency $toCurrency) : self + final public function convert(Converter $converter, Currency $toCurrency): self { return self::createFromLibMoney( $converter->convert($this->getLibMoney(), new LibCurrency($toCurrency->getCode())) @@ -126,59 +136,65 @@ final public function convert(Converter $converter, Currency $toCurrency) : self // phpcs:disable Squiz.Commenting.FunctionComment.WrongStyle // Methods from original Money library - final public function isSameCurrency(self $other) : bool + final public function isSameCurrency(self $other): bool { return $this->getLibMoney()->isSameCurrency($other->getLibMoney()); } - final public function equals(self $other) : bool + final public function equals(self $other): bool { static::assertSameSubUnit($other, __FUNCTION__); return $this->getLibMoney()->equals($other->getLibMoney()); } - final public function compare(self $other) : int + final public function compare(self $other): int { static::assertSameSubUnit($other, __FUNCTION__); return $this->getLibMoney()->compare($other->getLibMoney()); } - final public function greaterThan(self $other) : bool + final public function greaterThan(self $other): bool { static::assertSameSubUnit($other, __FUNCTION__); return $this->getLibMoney()->greaterThan($other->getLibMoney()); } - final public function greaterThanOrEqual(self $other) : bool + final public function greaterThanOrEqual(self $other): bool { static::assertSameSubUnit($other, __FUNCTION__); return $this->getLibMoney()->greaterThanOrEqual($other->getLibMoney()); } - final public function lessThan(self $other) : bool + final public function lessThan(self $other): bool { static::assertSameSubUnit($other, __FUNCTION__); return $this->getLibMoney()->lessThan($other->getLibMoney()); } - final public function lessThanOrEqual(self $other) : bool + final public function lessThanOrEqual(self $other): bool { static::assertSameSubUnit($other, __FUNCTION__); return $this->getLibMoney()->lessThanOrEqual($other->getLibMoney()); } - final public function getAmount() : string + /** + * @psalm-return numeric-string + */ + final public function getAmount(): string { return $this->formatAmount(static::fromSubunits($this->amount)); } - private function formatAmount(string $amount) : string + /** + * @psalm-return numeric-string + */ + private function formatAmount(string $amount): string { $currencySubunits = static::getAllowedCurrencies()->subunitFor(new LibCurrency($this->currency)); $dotPosition = strpos($amount, '.'); @@ -187,26 +203,29 @@ private function formatAmount(string $amount) : string throw new RuntimeException('Invalid money amount format'); } - return substr( + /** @psalm-var numeric-string $formattedAmount */ + $formattedAmount = substr( $amount, 0, $currencySubunits === 0 ? $dotPosition + $currencySubunits : $dotPosition + $currencySubunits + 1 ); + + return $formattedAmount; } - final public function getCurrency() : Currency + final public function getCurrency(): Currency { return Currency::create($this->currency); } - final public function add(self ...$addends) : self + final public function add(self ...$addends): self { return self::createFromLibMoney( $this->getLibMoney()->add( ...array_map( - static function (self $addend) : LibMoney { + static function (self $addend): LibMoney { static::assertSameSubUnit($addend, 'add'); return $addend->getLibMoney(); @@ -217,12 +236,12 @@ static function (self $addend) : LibMoney { ); } - final public function subtract(self ...$subtrahends) : self + final public function subtract(self ...$subtrahends): self { return self::createFromLibMoney( $this->getLibMoney()->subtract( ...array_map( - static function (self $subtrahend) : LibMoney { + static function (self $subtrahend): LibMoney { static::assertSameSubUnit($subtrahend, 'subtract'); return $subtrahend->getLibMoney(); @@ -233,21 +252,29 @@ static function (self $subtrahend) : LibMoney { ); } - final public function multiply(string $multiplier, int $roundingMode = LibMoney::ROUND_UP) : self + /** + * @psalm-param int|numeric-string $multiplier + * @psalm-param LibMoney::ROUND_* $roundingMode + */ + final public function multiply(int|string $multiplier, int $roundingMode = LibMoney::ROUND_UP): self { return self::createFromLibMoney( $this->getLibMoney()->multiply($multiplier, $roundingMode) ); } - final public function divide(string $divisor, int $roundingMode = LibMoney::ROUND_UP) : self + /** + * @psalm-param int|numeric-string $divisor + * @psalm-param LibMoney::ROUND_* $roundingMode + */ + final public function divide(int|string $divisor, int $roundingMode = LibMoney::ROUND_UP): self { return self::createFromLibMoney( $this->getLibMoney()->divide($divisor, $roundingMode) ); } - final public function mod(self $divisor) : self + final public function mod(self $divisor): self { static::assertSameSubUnit($divisor, __FUNCTION__); @@ -259,10 +286,13 @@ final public function mod(self $divisor) : self /** * @return self[] */ - final public function allocate(string ...$ratios) : array + final public function allocate(string ...$ratios): array { + /** @psalm-var non-empty-array $ratios */ + $ratios = array_map('floatval', $ratios); + return array_map( - function (LibMoney $money) : self { + function (LibMoney $money): self { return $this->createFromLibMoney($money); }, $this->getLibMoney()->allocate($ratios) @@ -270,46 +300,48 @@ function (LibMoney $money) : self { } /** + * @psalm-param positive-int $n + * * @return self[] */ - final public function allocateTo(int $n) : array + final public function allocateTo(int $n): array { return array_map( - function (LibMoney $money) : self { + function (LibMoney $money): self { return $this->createFromLibMoney($money); }, $this->getLibMoney()->allocateTo($n) ); } - final public function ratioOf(self $money) : string + final public function ratioOf(self $money): string { static::assertSameSubUnit($money, __FUNCTION__); return $this->getLibMoney()->ratioOf($money->getLibMoney()); } - final public function absolute() : self + final public function absolute(): self { return self::createFromLibMoney($this->getLibMoney()->absolute()); } - final public function negative() : self + final public function negative(): self { return self::createFromLibMoney($this->getLibMoney()->negative()); } - final public function isZero() : bool + final public function isZero(): bool { return $this->getLibMoney()->isZero(); } - final public function isPositive() : bool + final public function isPositive(): bool { return $this->getLibMoney()->isPositive(); } - final public function isNegative() : bool + final public function isNegative(): bool { return $this->getLibMoney()->isNegative(); } @@ -317,7 +349,7 @@ final public function isNegative() : bool /** * @return string[] */ - final public function jsonSerialize() : array + final public function jsonSerialize(): array { return [ 'amount' => $this->getAmount(), @@ -325,7 +357,7 @@ final public function jsonSerialize() : array ]; } - final public static function min(self $first, self ...$collection) : self + final public static function min(self $first, self ...$collection): self { $min = $first; @@ -342,7 +374,7 @@ final public static function min(self $first, self ...$collection) : self return $min; } - final public static function max(self $first, self ...$collection) : self + final public static function max(self $first, self ...$collection): self { $max = $first; @@ -359,7 +391,7 @@ final public static function max(self $first, self ...$collection) : self return $max; } - final public static function sum(self $first, self ...$collection) : self + final public static function sum(self $first, self ...$collection): self { $method = __FUNCTION__; @@ -367,7 +399,7 @@ final public static function sum(self $first, self ...$collection) : self $first->getLibMoney()::sum( $first->getLibMoney(), ...array_map( - static function (self $money) use ($first, $method) : LibMoney { + static function (self $money) use ($first, $method): LibMoney { $first::assertSameSubUnit($money, $method); return $money->getLibMoney(); @@ -378,7 +410,7 @@ static function (self $money) use ($first, $method) : LibMoney { ); } - final public static function avg(self $first, self ...$collection) : self + final public static function avg(self $first, self ...$collection): self { $method = __FUNCTION__; @@ -386,7 +418,7 @@ final public static function avg(self $first, self ...$collection) : self $first->getLibMoney()::avg( $first->getLibMoney(), ...array_map( - static function (self $money) use ($first, $method) : LibMoney { + static function (self $money) use ($first, $method): LibMoney { $first::assertSameSubUnit($money, $method); return $money->getLibMoney(); @@ -397,36 +429,36 @@ static function (self $money) use ($first, $method) : LibMoney { ); } - public function __toString() : string + public function __toString(): string { return $this->getAmount() . ' ' . (string) $this->getCurrency(); } - public static function humanReadableName() : string + public static function humanReadableName(): string { return self::HUMAN_READABLE_NAME; } - abstract protected static function classSubunits() : int; + abstract protected static function classSubunits(): int; - abstract protected static function getAllowedCurrencies() : Currencies; + abstract protected static function getAllowedCurrencies(): Currencies; - protected static function amountMustBeZeroOrGreater() : bool + protected static function amountMustBeZeroOrGreater(): bool { return false; } - protected static function amountMustBeGreaterThanZero() : bool + protected static function amountMustBeGreaterThanZero(): bool { return false; } - protected static function amountMustBeZeroOrLess() : bool + protected static function amountMustBeZeroOrLess(): bool { return false; } - protected static function amountMustBeLessThanZero() : bool + protected static function amountMustBeLessThanZero(): bool { return false; } @@ -434,21 +466,38 @@ protected static function amountMustBeLessThanZero() : bool /** * @throws CannotCreateMoney */ - protected static function validate(self $money) : void + protected static function validate(self $money): void { } - private static function fromSubunits(string $amount) : string + /** + * @psalm-param numeric-string $amount + * + * @psalm-return numeric-string + */ + private static function fromSubunits(string $amount): string { - return (string) bcdiv($amount, static::getSubunitMultiplier(), static::classSubunits()); + /* @phpstan-ignore-next-line */ + + /** + * wrong detection return type, conflict with psalm + * + * @phpstan-ignore-next-line + */ + return bcdiv($amount, static::getSubunitMultiplier(), static::classSubunits()); } - private static function toSubunits(string $amount) : string + /** + * @psalm-param numeric-string $amount + * + * @psalm-return numeric-string + */ + private static function toSubunits(string $amount): string { - return (string) bcmul($amount, static::getSubunitMultiplier(), 0); + return bcmul($amount, static::getSubunitMultiplier(), 0); } - private function createFromLibMoney(LibMoney $money) : self + private function createFromLibMoney(LibMoney $money): self { return self::create( static::fromSubunits($money->getAmount()), @@ -456,32 +505,38 @@ private function createFromLibMoney(LibMoney $money) : self ); } - private function getLibMoney() : LibMoney + private function getLibMoney(): LibMoney { return new LibMoney($this->amount, new LibCurrency($this->currency)); } - private static function getSubunitMultiplier() : string + /** + * @psalm-return numeric-string + */ + private static function getSubunitMultiplier(): string { - return static::classSubunits() > 0 ? + /** @psalm-var numeric-string $multiplier */ + $multiplier = static::classSubunits() > 0 ? str_pad('1', static::classSubunits() + 1, '0', STR_PAD_RIGHT) : '1'; + + return $multiplier; } - private static function assertSameSubUnit(self $money, string $methodName) : void + private static function assertSameSubUnit(self $money, string $methodName): void { if ($money::classSubunits() !== static::classSubunits()) { throw CannotWorkWithMoney::becauseMoneyHasDifferentSubunit( $methodName, static::class, - get_class($money), + $money::class, static::classSubunits(), $money::classSubunits() ); } } - private function getAmountFormatRegexp(int $subunits) : string + private function getAmountFormatRegexp(int $subunits): string { return '/^-?\d+' . ($subunits > 0 ? '\.\d{' . $subunits . '}' : '') . '$/'; } diff --git a/src/Bitcoin.php b/src/Bitcoin.php index 6cd1fd8..4a939a5 100644 --- a/src/Bitcoin.php +++ b/src/Bitcoin.php @@ -9,17 +9,17 @@ class Bitcoin extends BaseMoney { - public static function humanReadableName() : string + public static function humanReadableName(): string { return 'Bitcoin'; } - protected static function classSubunits() : int + protected static function classSubunits(): int { return 8; } - protected static function getAllowedCurrencies() : Currencies + protected static function getAllowedCurrencies(): Currencies { return new BitcoinCurrencies(); } diff --git a/src/Currency.php b/src/Currency.php index d2e592b..7e6ca11 100644 --- a/src/Currency.php +++ b/src/Currency.php @@ -9,44 +9,54 @@ class Currency { + /** @psalm-var non-empty-string */ private string $code; + /** + * @psalm-param non-empty-string $code + */ final private function __construct(string $code) { $this->code = $code; } - final public static function create(string $code) : self + /** + * @psalm-param non-empty-string $code + */ + final public static function create(string $code): self { return new static($code); } - final public function getCode() : string + /** + * @psalm-return non-empty-string + */ + final public function getCode(): string { return $this->getLibCurrency()->getCode(); } - final public function equals(self $other) : bool + final public function equals(self $other): bool { return $this->getLibCurrency()->equals($other->getLibCurrency()); } - final public function isAvailableWithin(Currencies $currencies) : bool + final public function isAvailableWithin(Currencies $currencies): bool { return $currencies->contains($this->getLibCurrency()); } - final public function jsonSerialize() : string + final public function jsonSerialize(): string { return $this->getLibCurrency()->jsonSerialize(); } - public function __toString() : string + public function __toString(): string { return (string) $this->getLibCurrency(); } - private function getLibCurrency() : LibCurrency + private function getLibCurrency(): LibCurrency { return new LibCurrency($this->code); } diff --git a/src/Exception/CannotCreateMoney.php b/src/Exception/CannotCreateMoney.php index 34e3c1a..8cab2c3 100644 --- a/src/Exception/CannotCreateMoney.php +++ b/src/Exception/CannotCreateMoney.php @@ -12,7 +12,7 @@ public static function becauseCurrencyNotAllowed( string $name, string $amount, string $currency - ) : self { + ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Currency not allowed.', @@ -28,7 +28,7 @@ public static function becauseAmountFormatIsInvalid( string $amount, string $currency, string $format - ) : self { + ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Invalid amount format. The correct format is: %s.', @@ -44,7 +44,7 @@ public static function becauseAmountMustBeGreaterThanZero( string $name, string $amount, string $currency - ) : self { + ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Amount must be greater than zero.', @@ -59,7 +59,7 @@ public static function becauseAmountMustBeZeroOrGreater( string $name, string $amount, string $currency - ) : self { + ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Amount must be zero or greater.', @@ -74,7 +74,7 @@ public static function becauseAmountMustBeZeroOrLess( string $name, string $amount, string $currency - ) : self { + ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Amount must be zero or less.', @@ -89,7 +89,7 @@ public static function becauseAmountMustBeLessThanZero( string $name, string $amount, string $currency - ) : self { + ): self { return new self( sprintf( 'Invalid %s with amount: %s and currency: %s. Amount must be less than zero.', diff --git a/src/Exception/CannotWorkWithMoney.php b/src/Exception/CannotWorkWithMoney.php index 6d6a587..e8c111b 100644 --- a/src/Exception/CannotWorkWithMoney.php +++ b/src/Exception/CannotWorkWithMoney.php @@ -14,7 +14,7 @@ public static function becauseCurrencyExceedsSubunitLimit( string $currency, int $currencySubunits, int $classSubunits - ) : self { + ): self { return new self( sprintf( 'Cannot instantiate %s with amount: %s and currency: %s. The currency has more subunits: %s then the class allows: %s.', @@ -33,7 +33,7 @@ public static function becauseMoneyHasDifferentSubunit( string $otherClass, int $subunits, int $otherSubunits - ) : self { + ): self { return new self( sprintf( 'Cannot execute method: %s on Money object: %s with other Money object as argument: %s. The classes have different subunits: %s and %s.', diff --git a/src/GaapMoney.php b/src/GaapMoney.php index 6613eea..b286742 100644 --- a/src/GaapMoney.php +++ b/src/GaapMoney.php @@ -9,12 +9,12 @@ class GaapMoney extends BaseMoney { - protected static function classSubunits() : int + protected static function classSubunits(): int { return 4; } - protected static function getAllowedCurrencies() : Currencies + protected static function getAllowedCurrencies(): Currencies { return new ISOCurrencies(); } diff --git a/src/Money.php b/src/Money.php index 9f93134..c7be55e 100644 --- a/src/Money.php +++ b/src/Money.php @@ -7,18 +7,17 @@ use Money\Currencies; use Money\Currencies\CurrencyList; use Money\Currencies\ISOCurrencies; -use Money\Currency as LibCurrency; class Money extends BaseMoney { private static ?Currencies $currencies = null; - protected static function classSubunits() : int + protected static function classSubunits(): int { return 2; } - protected static function getAllowedCurrencies() : Currencies + protected static function getAllowedCurrencies(): Currencies { if (self::$currencies !== null) { return self::$currencies; @@ -27,12 +26,11 @@ protected static function getAllowedCurrencies() : Currencies return self::initializeCurrencies(); } - private static function initializeCurrencies() : Currencies + private static function initializeCurrencies(): Currencies { $isoCurrencies = new ISOCurrencies(); $twoOrLessSubUnitCurrencies = []; - /** @var LibCurrency $currency */ foreach ($isoCurrencies->getIterator() as $currency) { $subUnit = $isoCurrencies->subunitFor($currency); @@ -43,6 +41,7 @@ private static function initializeCurrencies() : Currencies $twoOrLessSubUnitCurrencies[$currency->getCode()] = $subUnit; } + /** @psalm-var array $twoOrLessSubUnitCurrencies */ $currencies = new CurrencyList($twoOrLessSubUnitCurrencies); self::$currencies = $currencies; diff --git a/src/Type/BTCMoneyType.php b/src/Type/BTCMoneyType.php index 3f4d6a1..28fed95 100644 --- a/src/Type/BTCMoneyType.php +++ b/src/Type/BTCMoneyType.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\Type; + use function array_merge; use function bcdiv; use function bcmul; @@ -15,13 +16,13 @@ class BTCMoneyType extends Type public const TYPE_NAME = 'btc_money'; /** - * @param mixed[] $fieldDeclaration + * @param mixed[] $column */ - public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) : string + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { return $platform->getDecimalTypeDeclarationSQL( array_merge( - $fieldDeclaration, + $column, [ 'precision' => 16, 'scale' => 8, @@ -31,26 +32,38 @@ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $pla } /** - * @param mixed $value * * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint */ - public function convertToPHPValue($value, AbstractPlatform $platform) : ?string + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?string { - return $value !== null ? (string) bcmul((string) $value, '100000000', 0) : null; + if ($value === null) { + return null; + } + + /** @psalm-var numeric-string $value */ + $value = (string) $value; + + return bcmul($value, '100000000', 0); } /** - * @param mixed $value * * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) : ?string + public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?string { - return $value !== null ? (string) bcdiv((string) $value, '100000000', 8) : null; + if ($value === null) { + return null; + } + + /** @psalm-var numeric-string $value */ + $value = (string) $value; + + return bcdiv($value, '100000000', 8); } - public function getName() : string + public function getName(): string { return self::TYPE_NAME; } diff --git a/src/Type/CurrencyType.php b/src/Type/CurrencyType.php index 23625ef..4b9bd46 100644 --- a/src/Type/CurrencyType.php +++ b/src/Type/CurrencyType.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\Type; + use function array_merge; class CurrencyType extends Type @@ -13,16 +14,16 @@ class CurrencyType extends Type public const TYPE_NAME = 'currency'; /** - * @param mixed[] $fieldDeclaration + * @param mixed[] $column */ - public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) : string + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { return $platform->getVarcharTypeDeclarationSQL( - array_merge($fieldDeclaration, ['length' => 3]) + array_merge($column, ['length' => 3]) ); } - public function getName() : string + public function getName(): string { return self::TYPE_NAME; } diff --git a/src/Type/GaapMoneyType.php b/src/Type/GaapMoneyType.php index 00bae3e..2382400 100644 --- a/src/Type/GaapMoneyType.php +++ b/src/Type/GaapMoneyType.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\Type; + use function array_merge; use function bcdiv; use function bcmul; @@ -15,13 +16,13 @@ class GaapMoneyType extends Type public const TYPE_NAME = 'gaap_money'; /** - * @param mixed[] $fieldDeclaration + * @param mixed[] $column */ - public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) : string + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { return $platform->getDecimalTypeDeclarationSQL( array_merge( - $fieldDeclaration, + $column, [ 'precision' => 15, 'scale' => 4, @@ -31,26 +32,38 @@ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $pla } /** - * @param mixed $value * * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint */ - public function convertToPHPValue($value, AbstractPlatform $platform) : ?string + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?string { - return $value !== null ? (string) bcmul((string) $value, '10000', 0) : null; + if ($value === null) { + return null; + } + + /** @psalm-var numeric-string $value */ + $value = (string) $value; + + return bcmul($value, '10000', 0); } /** - * @param mixed $value * * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) : ?string + public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?string { - return $value !== null ? (string) bcdiv((string) $value, '10000', 4) : null; + if ($value === null) { + return null; + } + + /** @psalm-var numeric-string $value */ + $value = (string) $value; + + return bcdiv($value, '10000', 4); } - public function getName() : string + public function getName(): string { return self::TYPE_NAME; } diff --git a/src/Type/MoneyType.php b/src/Type/MoneyType.php index 1610e27..84b8ac1 100644 --- a/src/Type/MoneyType.php +++ b/src/Type/MoneyType.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\Type; + use function array_merge; use function bcdiv; use function bcmul; @@ -15,13 +16,13 @@ class MoneyType extends Type public const TYPE_NAME = 'money'; /** - * @param mixed[] $fieldDeclaration + * @param mixed[] $column */ - public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) : string + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { return $platform->getDecimalTypeDeclarationSQL( array_merge( - $fieldDeclaration, + $column, [ 'precision' => 10, 'scale' => 2, @@ -31,26 +32,38 @@ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $pla } /** - * @param mixed $value * * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint */ - public function convertToPHPValue($value, AbstractPlatform $platform) : ?string + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?string { - return $value !== null ? (string) bcmul((string) $value, '100', 0) : null; + if ($value === null) { + return null; + } + + /** @psalm-var numeric-string $value */ + $value = (string) $value; + + return bcmul($value, '100', 0); } /** - * @param mixed $value * * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) : ?string + public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?string { - return $value !== null ? (string) bcdiv((string) $value, '100', 2) : null; + if ($value === null) { + return null; + } + + /** @psalm-var numeric-string $value */ + $value = (string) $value; + + return bcdiv($value, '100', 2); } - public function getName() : string + public function getName(): string { return self::TYPE_NAME; } From f6e5261eab9458a7593064a853645521d16e0ea0 Mon Sep 17 00:00:00 2001 From: Shelepov G Date: Thu, 30 Sep 2021 19:52:15 +0300 Subject: [PATCH 2/4] ci github actions refs #4 --- .github/workflows/ci.yml | 246 +++++++++++++++++++++++++++++++++++++++ README.md | 2 +- 2 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b33039c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,246 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions +name: CI + +on: + - pull_request + - push + + +env: + PHP_EXTENSIONS: dom, mbstring, xml, bcmath + PHP_INI_VALUES: memory_limit=-1, assert.exception=1, zend.assertions=1, error_reporting=-1, log_errors_max_len=0, display_errors=On + +jobs: + unit: + name: Unit tests ${{matrix.php-versions}} + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + operating-system: ['ubuntu-latest'] + php-versions: ['8.0'] + phpunit-versions: ['latest'] + compiler: + - default + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.PHP_EXTENSIONS }} + ini-values: ${{ env.PHP_INI_VALUES }} + tools: composer:v2 + coverage: none + + - name: Determine composer cache directory + run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV + + - name: Cache dependencies installed with composer + uses: actions/cache@v2 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php${{ matrix.php-versions }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: | + php${{ matrix.php-versions }}-composer- + + - name: Update composer + run: composer self-update + + - name: Update dependencies with composer + run: composer update --no-interaction --no-ansi --no-progress + + - name: Execute tests + run: vendor/bin/phpunit + + psalm: + name: Psalm ${{matrix.php-versions}} + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + operating-system: ['ubuntu-latest'] + php-versions: ['8.0'] + phpunit-versions: ['latest'] + compiler: + - default + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.PHP_EXTENSIONS }} + ini-values: ${{ env.PHP_INI_VALUES }} + tools: composer:v2 + coverage: none + + - name: Determine composer cache directory + run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV + + - name: Cache dependencies installed with composer + uses: actions/cache@v2 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php${{ matrix.php-versions }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: | + php${{ matrix.php-versions }}-composer- + + - name: Update composer + run: composer self-update + + - name: Update dependencies with composer + run: composer update --no-interaction --no-ansi --no-progress + + - name: Execute Psalm + run: vendor/bin/psalm + stan: + name: PhpStan ${{matrix.php-versions}} + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + operating-system: ['ubuntu-latest'] + php-versions: ['8.0'] + phpunit-versions: ['latest'] + compiler: + - default + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.PHP_EXTENSIONS }} + ini-values: ${{ env.PHP_INI_VALUES }} + tools: composer:v2 + coverage: none + + - name: Determine composer cache directory + run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV + + - name: Cache dependencies installed with composer + uses: actions/cache@v2 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php${{ matrix.php-versions }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: | + php${{ matrix.php-versions }}-composer- + + - name: Update composer + run: composer self-update + + - name: Update dependencies with composer + run: composer update --no-interaction --no-ansi --no-progress + + - name: Execute PhpStan + run: composer stan + + code-style: + name: Code style ${{matrix.php-versions}} + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + operating-system: ['ubuntu-latest'] + php-versions: ['8.0'] + phpunit-versions: ['latest'] + compiler: + - default + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.PHP_EXTENSIONS }} + ini-values: ${{ env.PHP_INI_VALUES }} + tools: composer:v2 + coverage: none + + - name: Determine composer cache directory + run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV + + - name: Cache dependencies installed with composer + uses: actions/cache@v2 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php${{ matrix.php-versions }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: | + php${{ matrix.php-versions }}-composer- + + - name: Update composer + run: composer self-update + + - name: Update dependencies with composer + run: composer update --no-interaction --no-ansi --no-progress + + - name: Execute PhpCs + run: composer cs + + security: + name: Security check ${{matrix.php-versions}} + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + operating-system: ['ubuntu-latest'] + php-versions: ['8.0'] + phpunit-versions: ['latest'] + compiler: + - default + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.PHP_EXTENSIONS }} + ini-values: ${{ env.PHP_INI_VALUES }} + tools: composer:v2 + coverage: none + + - name: Determine composer cache directory + run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV + + - name: Cache dependencies installed with composer + uses: actions/cache@v2 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php${{ matrix.php-versions }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: | + php${{ matrix.php-versions }}-composer- + + - name: Update composer + run: composer self-update + + - name: Update dependencies with composer + run: composer update --no-interaction --no-ansi --no-progress + + - name: Execute security check + run: composer sec \ No newline at end of file diff --git a/README.md b/README.md index 2fa7aca..4808bc8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # OnMoon Money [![Latest Version](https://img.shields.io/github/v/release/onmoon/money)](https://github.com/onmoon/money/releases) -[![Build](https://img.shields.io/travis/onmoon/money/master)](https://travis-ci.org/onmoon/money) +[![Build](https://github.com/onmoon/money/actions/workflows/ci.yml/badge.svg)](https://github.com/onmoon/money/actions) [![License](https://img.shields.io/github/license/onmoon/money)](https://github.com/onmoon/money/blob/master/LICENSE) [![Email](https://img.shields.io/badge/email-pf@csgo.com-blue.svg?style=flat-square)](mailto:pf@csgo.com) From e75fc5cd108a4e12c03bba1819e3a5bfd9a07e5b Mon Sep 17 00:00:00 2001 From: Shelepov G Date: Thu, 30 Sep 2021 20:16:09 +0300 Subject: [PATCH 3/4] delete travis config refs #4 --- .travis.yml | 42 ------------------------------------------ 1 file changed, 42 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7143146..0000000 --- a/.travis.yml +++ /dev/null @@ -1,42 +0,0 @@ -dist: trusty -sudo: false -language: php - -cache: - directories: - - $HOME/.composer/cache - -php: - - 7.4 - - nightly - -install: - - travis_retry composer self-update - - travis_retry composer install --prefer-dist - -script: ./vendor/bin/phpunit - -jobs: - allow_failures: - - php: nightly - - stage: Security - include: - - stage: Psalm - php: 7.4 - script: ./vendor/bin/psalm - - - stage: PHPStan - php: 7.4 - script: ./vendor/bin/phpstan analyze src -l 8 - - - stage: Security - php: 7.4 - script: ./vendor/bin/security-checker security:check - - - stage: Code Style - php: 7.4 - script: - - composer show squizlabs/php_codesniffer - - composer show doctrine/coding-standard - - composer show slevomat/coding-standard - - ./vendor/bin/phpcs From 89d10bb353ea68743036458cb7aa04c88729c0cd Mon Sep 17 00:00:00 2001 From: goffyara Date: Fri, 1 Oct 2021 15:39:39 +0300 Subject: [PATCH 4/4] less strict doctrine/dbal version, fix on 2 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index def5c37..0c81560 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "require": { "php": "~8.0", "ext-bcmath": "*", - "doctrine/dbal": "^3.1", + "doctrine/dbal": "^2", "moneyphp/money": "^4.0", "thecodingmachine/safe": "^1.3" },