garak/money-bundle

View on GitHub
src/DoctrineType/MoneyType.php

Summary

Maintainability
A
0 mins
Test Coverage
A
92%
<?php

namespace Garak\Money\DoctrineType;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;
use Money\Currency;
use Money\Money;

final class MoneyType extends Type
{
    private string $currency = 'EUR';

    public function setCurrency(string $currency): void
    {
        $this->currency = $currency;
    }

    public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
    {
        return $platform->getIntegerTypeDeclarationSQL($column);
    }

    /**
     * @throws ConversionException
     */
    public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?Money
    {
        if (null === $value || '' === $value) {
            return null;
        }

        if ($value instanceof Money) {
            return $value;
        }

        try {
            $currency = new Currency($this->currency);

            return new Money($value, $currency);
        } catch (\InvalidArgumentException $exception) {
            $msg = sprintf('Could not convert database value "%s" to Doctrine Type money', $value);
            throw new ConversionException($msg, previous: $exception);
        }
    }

    /**
     * @throws ConversionException
     */
    public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?int
    {
        if (null === $value) {
            return null;
        }

        if ($value instanceof Money) {
            return (int) $value->getAmount();
        }

        $msg = sprintf('Could not convert money value value "%s" to database value', $value);
        throw new ConversionException($msg);
    }

    public function getName(): string
    {
        return 'money';
    }

    public function requiresSQLCommentHint(AbstractPlatform $platform): bool
    {
        return true;
    }
}