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/.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
diff --git a/README.md b/README.md
index 2fa7aca..4808bc8 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# OnMoon Money
[](https://github.com/onmoon/money/releases)
-[](https://travis-ci.org/onmoon/money)
+[](https://github.com/onmoon/money/actions)
[](https://github.com/onmoon/money/blob/master/LICENSE)
[](mailto:pf@csgo.com)
diff --git a/composer.json b/composer.json
index 19d9e25..0c81560 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": "^2",
+ "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;
}