diff --git a/src/Entity/Base/AbstractCompany.php b/src/Entity/Base/AbstractCompany.php index b552d705..e1f5e757 100644 --- a/src/Entity/Base/AbstractCompany.php +++ b/src/Entity/Base/AbstractCompany.php @@ -82,6 +82,9 @@ abstract class AbstractCompany extends AbstractPartsContainingDBElement #[ORM\Column(type: Types::STRING)] protected string $website = ''; + #[Groups(['company:read', 'company:write'])] + protected string $comment = ''; + /** * @var string */ diff --git a/src/Entity/Base/AbstractStructuralDBElement.php b/src/Entity/Base/AbstractStructuralDBElement.php index 59d374c8..15550b50 100644 --- a/src/Entity/Base/AbstractStructuralDBElement.php +++ b/src/Entity/Base/AbstractStructuralDBElement.php @@ -75,7 +75,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement final public const PATH_DELIMITER_ARROW = ' → '; /** - * @var string The comment info for this element + * @var string The comment info for this element as markdown */ #[Groups(['full', 'import'])] #[ORM\Column(type: Types::TEXT)] @@ -221,7 +221,7 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement } /** - * Get the comment of the element. + * Get the comment of the element as markdown encoded string. * * @return string the comment diff --git a/src/Entity/Parts/Category.php b/src/Entity/Parts/Category.php index ac810cf8..c1d2e917 100644 --- a/src/Entity/Parts/Category.php +++ b/src/Entity/Parts/Category.php @@ -22,8 +22,17 @@ declare(strict_types=1); namespace App\Entity\Parts; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Serializer\Filter\PropertyFilter; use App\Entity\Attachments\Attachment; -use App\Entity\Attachments\AttachmentTypeAttachment; use App\Repository\Parts\CategoryRepository; use Doctrine\DBAL\Types\Types; use Doctrine\Common\Collections\ArrayCollection; @@ -45,6 +54,29 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: '`categories`')] #[ORM\Index(name: 'category_idx_name', columns: ['name'])] #[ORM\Index(name: 'category_idx_parent_name', columns: ['parent_id', 'name'])] +#[ApiResource( + operations: [ + new Get(security: 'is_granted("read", object)'), + new GetCollection(security: 'is_granted("@categories.read")'), + new Post(securityPostDenormalize: 'is_granted("create", object)'), + new Patch(security: 'is_granted("edit", object)'), + new Delete(security: 'is_granted("delete", object)'), + ], + normalizationContext: ['groups' => ['category:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'], + denormalizationContext: ['groups' => ['category:write', 'api:basic:write'], 'openapi_definition_name' => 'Write'], +)] +#[ApiResource( + uriTemplate: '/categories/{id}/children.{_format}', + operations: [ + new GetCollection(openapiContext: ['summary' => 'Retrieves the children elements of a category.'], + security: 'is_granted("@categories.read")') + ], + uriVariables: [ + 'id' => new Link(fromProperty: 'children', fromClass: Category::class) + ], + normalizationContext: ['groups' => ['category:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'] +)] +#[ApiFilter(PropertyFilter::class)] class Category extends AbstractPartsContainingDBElement { #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')] @@ -53,61 +85,66 @@ class Category extends AbstractPartsContainingDBElement #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\JoinColumn(name: 'parent_id')] + #[Groups(['category:read', 'category:write'])] + #[ApiProperty(readableLink: false, writableLink: false)] protected ?AbstractStructuralDBElement $parent = null; + #[Groups(['category:read', 'category:write'])] + protected string $comment = ''; + /** * @var string */ - #[Groups(['full', 'import'])] + #[Groups(['full', 'import', 'category:read', 'category:write'])] #[ORM\Column(type: Types::TEXT)] protected string $partname_hint = ''; /** * @var string */ - #[Groups(['full', 'import'])] + #[Groups(['full', 'import', 'category:read', 'category:write'])] #[ORM\Column(type: Types::TEXT)] protected string $partname_regex = ''; /** * @var bool */ - #[Groups(['full', 'import'])] + #[Groups(['full', 'import', 'category:read', 'category:write'])] #[ORM\Column(type: Types::BOOLEAN)] protected bool $disable_footprints = false; /** * @var bool */ - #[Groups(['full', 'import'])] + #[Groups(['full', 'import', 'category:read', 'category:write'])] #[ORM\Column(type: Types::BOOLEAN)] protected bool $disable_manufacturers = false; /** * @var bool */ - #[Groups(['full', 'import'])] + #[Groups(['full', 'import', 'category:read', 'category:write'])] #[ORM\Column(type: Types::BOOLEAN)] protected bool $disable_autodatasheets = false; /** * @var bool */ - #[Groups(['full', 'import'])] + #[Groups(['full', 'import', 'category:read', 'category:write'])] #[ORM\Column(type: Types::BOOLEAN)] protected bool $disable_properties = false; /** * @var string */ - #[Groups(['full', 'import'])] + #[Groups(['full', 'import', 'category:read', 'category:write'])] #[ORM\Column(type: Types::TEXT)] protected string $default_description = ''; /** * @var string */ - #[Groups(['full', 'import'])] + #[Groups(['full', 'import', 'category:read', 'category:write'])] #[ORM\Column(type: Types::TEXT)] protected string $default_comment = ''; @@ -115,19 +152,20 @@ class Category extends AbstractPartsContainingDBElement * @var Collection */ #[Assert\Valid] - #[Groups(['full'])] + #[Groups(['full', 'category:read'])] #[ORM\OneToMany(targetEntity: CategoryAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['name' => 'ASC'])] protected Collection $attachments; #[ORM\ManyToOne(targetEntity: CategoryAttachment::class)] #[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')] + #[Groups(['category:read'])] protected ?Attachment $master_picture_attachment = null; /** @var Collection */ #[Assert\Valid] - #[Groups(['full'])] + #[Groups(['full', 'category:read'])] #[ORM\OneToMany(targetEntity: CategoryParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] protected Collection $parameters; diff --git a/src/Entity/Parts/Footprint.php b/src/Entity/Parts/Footprint.php index 4126a63b..c7148deb 100644 --- a/src/Entity/Parts/Footprint.php +++ b/src/Entity/Parts/Footprint.php @@ -22,6 +22,16 @@ declare(strict_types=1); namespace App\Entity\Parts; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Serializer\Filter\PropertyFilter; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentTypeAttachment; use App\Repository\Parts\FootprintRepository; @@ -32,6 +42,7 @@ use App\Entity\Base\AbstractPartsContainingDBElement; use App\Entity\Parameters\FootprintParameter; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; /** @@ -43,26 +54,56 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table('`footprints`')] #[ORM\Index(name: 'footprint_idx_name', columns: ['name'])] #[ORM\Index(name: 'footprint_idx_parent_name', columns: ['parent_id', 'name'])] +#[ApiResource( + operations: [ + new Get(security: 'is_granted("read", object)'), + new GetCollection(security: 'is_granted("@footprints.read")'), + new Post(securityPostDenormalize: 'is_granted("create", object)'), + new Patch(security: 'is_granted("edit", object)'), + new Delete(security: 'is_granted("delete", object)'), + ], + normalizationContext: ['groups' => ['footprint:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'], + denormalizationContext: ['groups' => ['footprint:write', 'api:basic:write'], 'openapi_definition_name' => 'Write'], +)] +#[ApiResource( + uriTemplate: '/footprints/{id}/children.{_format}', + operations: [ + new GetCollection(openapiContext: ['summary' => 'Retrieves the children elements of a footprint.'], + security: 'is_granted("@footprints.read")') + ], + uriVariables: [ + 'id' => new Link(fromProperty: 'children', fromClass: Footprint::class) + ], + normalizationContext: ['groups' => ['footprint:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'] +)] +#[ApiFilter(PropertyFilter::class)] class Footprint extends AbstractPartsContainingDBElement { #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\JoinColumn(name: 'parent_id')] + #[Groups(['footprint:read', 'footprint:write'])] + #[ApiProperty(readableLink: false, writableLink: false)] protected ?AbstractStructuralDBElement $parent = null; #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')] #[ORM\OrderBy(['name' => 'ASC'])] protected Collection $children; + #[Groups(['footprint:read', 'footprint:write'])] + protected string $comment = ''; + /** * @var Collection */ #[Assert\Valid] #[ORM\OneToMany(targetEntity: FootprintAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['name' => 'ASC'])] + #[Groups(['footprint:read'])] protected Collection $attachments; #[ORM\ManyToOne(targetEntity: FootprintAttachment::class)] #[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')] + #[Groups(['footprint:read'])] protected ?Attachment $master_picture_attachment = null; /** @@ -70,6 +111,7 @@ class Footprint extends AbstractPartsContainingDBElement */ #[ORM\ManyToOne(targetEntity: FootprintAttachment::class)] #[ORM\JoinColumn(name: 'id_footprint_3d')] + #[Groups(['footprint:read'])] protected ?FootprintAttachment $footprint_3d = null; /** @var Collection @@ -77,6 +119,7 @@ class Footprint extends AbstractPartsContainingDBElement #[Assert\Valid] #[ORM\OneToMany(targetEntity: FootprintParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] + #[Groups(['footprint:read'])] protected Collection $parameters; /**************************************** diff --git a/src/Entity/Parts/MeasurementUnit.php b/src/Entity/Parts/MeasurementUnit.php index 538d4c57..d54ecf3b 100644 --- a/src/Entity/Parts/MeasurementUnit.php +++ b/src/Entity/Parts/MeasurementUnit.php @@ -22,6 +22,16 @@ declare(strict_types=1); namespace App\Entity\Parts; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Serializer\Filter\PropertyFilter; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentTypeAttachment; use App\Repository\Parts\MeasurementUnitRepository; @@ -48,6 +58,29 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: '`measurement_units`')] #[ORM\Index(name: 'unit_idx_name', columns: ['name'])] #[ORM\Index(name: 'unit_idx_parent_name', columns: ['parent_id', 'name'])] +#[ApiResource( + operations: [ + new Get(security: 'is_granted("read", object)'), + new GetCollection(security: 'is_granted("@measurement_unit.read")'), + new Post(securityPostDenormalize: 'is_granted("create", object)'), + new Patch(security: 'is_granted("edit", object)'), + new Delete(security: 'is_granted("delete", object)'), + ], + normalizationContext: ['groups' => ['measurement_unit:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'], + denormalizationContext: ['groups' => ['measurement_unit:write', 'api:basic:write'], 'openapi_definition_name' => 'Write'], +)] +#[ApiResource( + uriTemplate: '/footprints/{id}/children.{_format}', + operations: [ + new GetCollection(openapiContext: ['summary' => 'Retrieves the children elements of a MeasurementUnit.'], + security: 'is_granted("@measurement_unit.read")') + ], + uriVariables: [ + 'id' => new Link(fromProperty: 'children', fromClass: MeasurementUnit::class) + ], + normalizationContext: ['groups' => ['measurement_unit:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'] +)] +#[ApiFilter(PropertyFilter::class)] class MeasurementUnit extends AbstractPartsContainingDBElement { /** @@ -55,15 +88,18 @@ class MeasurementUnit extends AbstractPartsContainingDBElement * or m (for meters). */ #[Assert\Length(max: 10)] - #[Groups(['extended', 'full', 'import'])] + #[Groups(['extended', 'full', 'import', 'measurement_unit:read', 'measurement_unit:write'])] #[ORM\Column(type: Types::STRING, name: 'unit', nullable: true)] protected ?string $unit = null; + #[Groups(['measurement_unit:read', 'measurement_unit:write'])] + protected string $comment = ''; + /** * @var bool Determines if the amount value associated with this unit should be treated as integer. * Set to false, to measure continuous sizes likes masses or lengths. */ - #[Groups(['extended', 'full', 'import'])] + #[Groups(['extended', 'full', 'import', 'measurement_unit:read', 'measurement_unit:write'])] #[ORM\Column(type: Types::BOOLEAN, name: 'is_integer')] protected bool $is_integer = false; @@ -72,7 +108,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement * Useful for sizes like meters. For this the unit must be set */ #[Assert\Expression('this.isUseSIPrefix() == false or this.getUnit() != null', message: 'validator.measurement_unit.use_si_prefix_needs_unit')] - #[Groups(['full', 'import'])] + #[Groups(['full', 'import', 'measurement_unit:read', 'measurement_unit:write'])] #[ORM\Column(type: Types::BOOLEAN, name: 'use_si_prefix')] protected bool $use_si_prefix = false; @@ -82,6 +118,8 @@ class MeasurementUnit extends AbstractPartsContainingDBElement #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\JoinColumn(name: 'parent_id')] + #[Groups('measurement_unit:read', 'measurement_unit:write')] + #[ApiProperty(readableLink: false, writableLink: false)] protected ?AbstractStructuralDBElement $parent = null; /** @@ -90,10 +128,12 @@ class MeasurementUnit extends AbstractPartsContainingDBElement #[Assert\Valid] #[ORM\OneToMany(targetEntity: MeasurementUnitAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['name' => 'ASC'])] + #[Groups(['measurement_unit:read'])] protected Collection $attachments; #[ORM\ManyToOne(targetEntity: MeasurementUnitAttachment::class)] #[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')] + #[Groups(['measurement_unit:read'])] protected ?Attachment $master_picture_attachment = null; /** @var Collection @@ -101,6 +141,7 @@ class MeasurementUnit extends AbstractPartsContainingDBElement #[Assert\Valid] #[ORM\OneToMany(targetEntity: MeasurementUnitParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] + #[Groups(['measurement_unit:read'])] protected Collection $parameters; /** diff --git a/src/Entity/PriceInformations/Currency.php b/src/Entity/PriceInformations/Currency.php index 1aec8d8a..ddc17610 100644 --- a/src/Entity/PriceInformations/Currency.php +++ b/src/Entity/PriceInformations/Currency.php @@ -22,8 +22,19 @@ declare(strict_types=1); namespace App\Entity\PriceInformations; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Serializer\Filter\PropertyFilter; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentTypeAttachment; +use App\Entity\Parts\Footprint; use App\Repository\CurrencyRepository; use Doctrine\DBAL\Types\Types; use App\Entity\Attachments\CurrencyAttachment; @@ -49,6 +60,29 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'currencies')] #[ORM\Index(name: 'currency_idx_name', columns: ['name'])] #[ORM\Index(name: 'currency_idx_parent_name', columns: ['parent_id', 'name'])] +#[ApiResource( + operations: [ + new Get(security: 'is_granted("read", object)'), + new GetCollection(security: 'is_granted("@currencies.read")'), + new Post(securityPostDenormalize: 'is_granted("create", object)'), + new Patch(security: 'is_granted("edit", object)'), + new Delete(security: 'is_granted("delete", object)'), + ], + normalizationContext: ['groups' => ['currency:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'], + denormalizationContext: ['groups' => ['currency:write', 'api:basic:write'], 'openapi_definition_name' => 'Write'], +)] +#[ApiResource( + uriTemplate: '/currencies/{id}/children.{_format}', + operations: [ + new GetCollection(openapiContext: ['summary' => 'Retrieves the children elements of a currency.'], + security: 'is_granted("@currencies.read")') + ], + uriVariables: [ + 'id' => new Link(fromProperty: 'children', fromClass: Currency::class) + ], + normalizationContext: ['groups' => ['currency:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'] +)] +#[ApiFilter(PropertyFilter::class)] class Currency extends AbstractStructuralDBElement { final public const PRICE_SCALE = 5; @@ -59,14 +93,19 @@ class Currency extends AbstractStructuralDBElement */ #[ORM\Column(type: 'big_decimal', precision: 11, scale: 5, nullable: true)] #[BigDecimalPositive()] + #[Groups(['currency:read', 'currency:write'])] + #[ApiProperty(readableLink: false, writableLink: false)] protected ?BigDecimal $exchange_rate = null; + #[Groups(['currency:read', 'currency:write'])] + protected string $comment = ""; + /** * @var string the 3-letter ISO code of the currency */ #[Assert\Currency] #[Assert\NotBlank] - #[Groups(['extended', 'full', 'import'])] + #[Groups(['extended', 'full', 'import', 'currency:read', 'currency:write'])] #[ORM\Column(type: Types::STRING)] protected string $iso_code = ""; @@ -76,6 +115,8 @@ class Currency extends AbstractStructuralDBElement #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\JoinColumn(name: 'parent_id')] + #[Groups(['currency:read', 'currency:write'])] + #[ApiProperty(readableLink: false, writableLink: false)] protected ?AbstractStructuralDBElement $parent = null; /** @@ -84,10 +125,12 @@ class Currency extends AbstractStructuralDBElement #[Assert\Valid] #[ORM\OneToMany(targetEntity: CurrencyAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['name' => 'ASC'])] + #[Groups(['currency:read', 'currency:write'])] protected Collection $attachments; #[ORM\ManyToOne(targetEntity: CurrencyAttachment::class)] #[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')] + #[Groups(['currency:read', 'currency:write'])] protected ?Attachment $master_picture_attachment = null; /** @var Collection @@ -95,6 +138,7 @@ class Currency extends AbstractStructuralDBElement #[Assert\Valid] #[ORM\OneToMany(targetEntity: CurrencyParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] + #[Groups(['currency:read', 'currency:write'])] protected Collection $parameters; /** @var Collection @@ -136,6 +180,7 @@ class Currency extends AbstractStructuralDBElement /** * Returns the inverse exchange rate (how many of the current currency the base unit is worth). */ + #[Groups(['currency:read'])] public function getInverseExchangeRate(): ?BigDecimal { $tmp = $this->getExchangeRate(); diff --git a/src/Serializer/BigNumberNormalizer.php b/src/Serializer/BigNumberNormalizer.php index 8bb686ee..80bb98d7 100644 --- a/src/Serializer/BigNumberNormalizer.php +++ b/src/Serializer/BigNumberNormalizer.php @@ -22,13 +22,15 @@ declare(strict_types=1); */ namespace App\Serializer; +use Brick\Math\BigDecimal; use Brick\Math\BigNumber; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; /** * @see \App\Tests\Serializer\BigNumberNormalizerTest */ -class BigNumberNormalizer implements NormalizerInterface +class BigNumberNormalizer implements NormalizerInterface, DenormalizerInterface { public function supportsNormalization($data, string $format = null, array $context = []): bool @@ -52,6 +54,22 @@ class BigNumberNormalizer implements NormalizerInterface { return [ BigNumber::class => true, + BigDecimal::class => true, ]; } + + public function denormalize(mixed $data, string $type, string $format = null, array $context = []) + { + if (!is_a($type, BigNumber::class, true)) { + throw new \InvalidArgumentException('This normalizer only supports BigNumber objects!'); + } + + return $type::of($data); + } + + public function supportsDenormalization(mixed $data, string $type, string $format = null) + { + //data must be a string or a number (int, float, etc.) and the type must be BigNumber or BigDecimal + return (is_string($data) || is_numeric($data)) && (is_subclass_of($type, BigNumber::class)); + } } diff --git a/tests/Serializer/BigNumberNormalizerTest.php b/tests/Serializer/BigNumberNormalizerTest.php index 6e3ed79b..f64347ee 100644 --- a/tests/Serializer/BigNumberNormalizerTest.php +++ b/tests/Serializer/BigNumberNormalizerTest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace App\Tests\Serializer; use App\Serializer\BigNumberNormalizer; +use Brick\Math\BigInteger; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Brick\Math\BigDecimal; @@ -57,4 +58,30 @@ class BigNumberNormalizerTest extends WebTestCase $bigDecimal = BigDecimal::of(1); $this->assertTrue($this->service->supportsNormalization($bigDecimal)); } + + public function testSupportsDenormalization(): void + { + //Denormalizer must only support BigNumber objects (and child classes) + $this->assertFalse($this->service->supportsDenormalization("1.23", \stdClass::class)); + + //Denormalizer must only support number like input data + $this->assertFalse($this->service->supportsDenormalization(new \stdClass(), BigDecimal::class)); + + //Using the right class and data type + $this->assertTrue($this->service->supportsDenormalization("1.23", BigDecimal::class)); + $this->assertTrue($this->service->supportsDenormalization("123", BigInteger::class)); + $this->assertTrue($this->service->supportsDenormalization(123, BigInteger::class)); + $this->assertTrue($this->service->supportsDenormalization(12.3, BigDecimal::class)); + } + + public function testDenormalize(): void + { + $bigDecimal = $this->service->denormalize("1.23456789", BigDecimal::class); + $this->assertInstanceOf(BigDecimal::class, $bigDecimal); + $this->assertSame('1.23456789', (string) $bigDecimal); + + $bigInteger = $this->service->denormalize(1234, BigInteger::class); + $this->assertInstanceOf(BigInteger::class, $bigInteger); + $this->assertSame('1234', (string) $bigInteger); + } }