From f4878df7a6ca8089cc637966af27adbd65ec0433 Mon Sep 17 00:00:00 2001 From: Jean-Paul van der Wegen Date: Wed, 22 Apr 2026 00:09:00 +0200 Subject: [PATCH 1/4] Fix AdditionalItemProperty deserialization to return typed objects --- src/Reader.php | 1 + tests/Read/ItemOriginCountryTest.php | 69 +++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/Reader.php b/src/Reader.php index 54e1d56..37c9084 100644 --- a/src/Reader.php +++ b/src/Reader.php @@ -28,6 +28,7 @@ public static function ubl($currencyId = 'EUR'): Service Schema::CAC. 'AccountingCustomerParty' => fn ($reader) => AccountingParty::xmlDeserialize($reader), Schema::CAC. 'AccountingSupplierParty' => fn ($reader) => AccountingParty::xmlDeserialize($reader), Schema::CAC. 'AdditionalDocumentReference' => fn ($reader) => AdditionalDocumentReference::xmlDeserialize($reader), + Schema::CAC. 'AdditionalItemProperty' => fn ($reader) => AdditionalItemProperty::xmlDeserialize($reader), Schema::CAC. 'Address' => fn ($reader) => Address::xmlDeserialize($reader), Schema::CAC. 'AddressLine' => fn ($reader) => AddressLine::xmlDeserialize($reader), Schema::CAC. 'AllowanceCharge' => fn ($reader) => AllowanceCharge::xmlDeserialize($reader), diff --git a/tests/Read/ItemOriginCountryTest.php b/tests/Read/ItemOriginCountryTest.php index 7f0d19a..22865f3 100644 --- a/tests/Read/ItemOriginCountryTest.php +++ b/tests/Read/ItemOriginCountryTest.php @@ -2,6 +2,7 @@ namespace NumNum\UBL\Tests\Read; +use NumNum\UBL\AdditionalItemProperty; use NumNum\UBL\Country; use NumNum\UBL\Invoice; use PHPUnit\Framework\TestCase; @@ -132,5 +133,71 @@ public function testItemWithoutOriginCountryCanBeRead() $originCountry = $item->getOriginCountry(); $this->assertNull($originCountry); } -} + /** @test */ + public function testAdditionalItemPropertiesAreHydratedAsObjects() + { + $xml = << + + 12345 + 2024-01-01 + + + + Supplier + + + + + + + Customer + + + + + 21.00 + + + 121.00 + + + 1 + 1 + 100 + + Test Product + + Color + Blue + + + + +XML; + + $ublReader = \NumNum\UBL\Reader::ubl(); + $invoice = $ublReader->parse($xml); + + $this->assertNotNull($invoice); + $this->assertInstanceOf(Invoice::class, $invoice); + + $invoiceLines = $invoice->getInvoiceLines(); + $this->assertNotEmpty($invoiceLines); + + $firstLine = array_values($invoiceLines)[0]; + $item = $firstLine->getItem(); + $this->assertNotNull($item); + + $additionalItemProperties = $item->getAdditionalItemProperties(); + $this->assertIsArray($additionalItemProperties); + $this->assertCount(1, $additionalItemProperties); + $firstAdditionalItemProperty = reset($additionalItemProperties); + $this->assertInstanceOf(AdditionalItemProperty::class, $firstAdditionalItemProperty); + $this->assertEquals('Color', $firstAdditionalItemProperty->getName()); + $this->assertEquals('Blue', $firstAdditionalItemProperty->getValue()); + } +} From 0a9a335069f997179a68e75dacbc75a2926c6598 Mon Sep 17 00:00:00 2001 From: Jean-Paul van der Wegen Date: Wed, 22 Apr 2026 00:09:10 +0200 Subject: [PATCH 2/4] Fix codestyling in Invoice.php --- src/Invoice.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Invoice.php b/src/Invoice.php index c4aede7..28c614e 100644 --- a/src/Invoice.php +++ b/src/Invoice.php @@ -902,10 +902,7 @@ public function xmlSerialize(Writer $writer): void } if (!empty($this->additionalDocumentReferences)) { - foreach ( - $this->additionalDocumentReferences - as $additionalDocumentReference - ) { + foreach ($this->additionalDocumentReferences as $additionalDocumentReference) { $writer->write([ Schema::CAC . "AdditionalDocumentReference" => $additionalDocumentReference, From 70ecce969fb5963a0273e2c93b38ea74ca23faef Mon Sep 17 00:00:00 2001 From: Jean-Paul van der Wegen Date: Wed, 22 Apr 2026 00:12:58 +0200 Subject: [PATCH 3/4] Add ext-libxml requirement to composer.json This is required to use LIBXML_PARSEHUGE in Reader.php --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 691ceae..ee5182c 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,7 @@ ], "require": { "php": "^7.4 || ^8.0", + "ext-libxml": "*", "sabre/xml": "^4.0", "nesbot/carbon": "^2.72 || ^3.11", "doctrine/collections": "^1.8 || ^2.0" From 5c44ae27d6d5673caab085123b674e77ab9cfeed Mon Sep 17 00:00:00 2001 From: Jean-Paul van der Wegen Date: Wed, 22 Apr 2026 00:24:16 +0200 Subject: [PATCH 4/4] Move test to ItemAdditionalItemPropertyTest --- tests/Read/ItemAdditionalItemPropertyTest.php | 78 +++++++++++++++++++ tests/Read/ItemOriginCountryTest.php | 67 ---------------- 2 files changed, 78 insertions(+), 67 deletions(-) create mode 100644 tests/Read/ItemAdditionalItemPropertyTest.php diff --git a/tests/Read/ItemAdditionalItemPropertyTest.php b/tests/Read/ItemAdditionalItemPropertyTest.php new file mode 100644 index 0000000..1e162e6 --- /dev/null +++ b/tests/Read/ItemAdditionalItemPropertyTest.php @@ -0,0 +1,78 @@ + + + 12345 + 2024-01-01 + + + + Supplier + + + + + + + Customer + + + + + 21.00 + + + 121.00 + + + 1 + 1 + 100 + + Test Product + + Color + Blue + + + + +XML; + + $ublReader = Reader::ubl(); + $invoice = $ublReader->parse($xml); + + $this->assertNotNull($invoice); + $this->assertInstanceOf(Invoice::class, $invoice); + + $invoiceLines = $invoice->getInvoiceLines(); + $this->assertNotEmpty($invoiceLines); + + $firstLine = array_values($invoiceLines)[0]; + $item = $firstLine->getItem(); + $this->assertNotNull($item); + + $additionalItemProperties = $item->getAdditionalItemProperties(); + $this->assertIsArray($additionalItemProperties); + $this->assertCount(1, $additionalItemProperties); + $firstAdditionalItemProperty = reset($additionalItemProperties); + $this->assertInstanceOf(AdditionalItemProperty::class, $firstAdditionalItemProperty); + $this->assertEquals('Color', $firstAdditionalItemProperty->getName()); + $this->assertEquals('Blue', $firstAdditionalItemProperty->getValue()); + } +} diff --git a/tests/Read/ItemOriginCountryTest.php b/tests/Read/ItemOriginCountryTest.php index 22865f3..95a2ad1 100644 --- a/tests/Read/ItemOriginCountryTest.php +++ b/tests/Read/ItemOriginCountryTest.php @@ -2,7 +2,6 @@ namespace NumNum\UBL\Tests\Read; -use NumNum\UBL\AdditionalItemProperty; use NumNum\UBL\Country; use NumNum\UBL\Invoice; use PHPUnit\Framework\TestCase; @@ -134,70 +133,4 @@ public function testItemWithoutOriginCountryCanBeRead() $this->assertNull($originCountry); } - /** @test */ - public function testAdditionalItemPropertiesAreHydratedAsObjects() - { - $xml = << - - 12345 - 2024-01-01 - - - - Supplier - - - - - - - Customer - - - - - 21.00 - - - 121.00 - - - 1 - 1 - 100 - - Test Product - - Color - Blue - - - - -XML; - - $ublReader = \NumNum\UBL\Reader::ubl(); - $invoice = $ublReader->parse($xml); - - $this->assertNotNull($invoice); - $this->assertInstanceOf(Invoice::class, $invoice); - - $invoiceLines = $invoice->getInvoiceLines(); - $this->assertNotEmpty($invoiceLines); - - $firstLine = array_values($invoiceLines)[0]; - $item = $firstLine->getItem(); - $this->assertNotNull($item); - - $additionalItemProperties = $item->getAdditionalItemProperties(); - $this->assertIsArray($additionalItemProperties); - $this->assertCount(1, $additionalItemProperties); - $firstAdditionalItemProperty = reset($additionalItemProperties); - $this->assertInstanceOf(AdditionalItemProperty::class, $firstAdditionalItemProperty); - $this->assertEquals('Color', $firstAdditionalItemProperty->getName()); - $this->assertEquals('Blue', $firstAdditionalItemProperty->getValue()); - } }