From a62642a015f9158289dcf91d65a6693fd6e381a3 Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Fri, 9 Jun 2023 12:56:55 +0200 Subject: [PATCH 01/18] add EditionStatement to DescriptiveDetail --- src/Product/DescriptiveDetail.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/Product/DescriptiveDetail.php b/src/Product/DescriptiveDetail.php index 8d3880d..c88d3ee 100644 --- a/src/Product/DescriptiveDetail.php +++ b/src/Product/DescriptiveDetail.php @@ -88,6 +88,13 @@ class DescriptiveDetail */ protected $EditionNumber; + /** + * EditionStatement + * + * @var string + */ + protected $EditionStatement; + /** * Array of Extents * @@ -293,6 +300,22 @@ public function setEditionNumber(string $EditionNumber) $this->EditionNumber = $EditionNumber; } + /** + * @return string + */ + public function getEditionStatement(): string + { + return $this->EditionStatement; + } + + /** + * @param string $EditionStatement + */ + public function setEditionStatement(string $EditionStatement) + { + $this->EditionStatement = $EditionStatement; + } + /** * Add new Extent * From e718a1dff320795f779ac51981ef4314f5c43e14 Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Fri, 9 Jun 2023 17:09:17 +0200 Subject: [PATCH 02/18] add SubjectSchemeName to Subject --- src/Product/Subject.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Product/Subject.php b/src/Product/Subject.php index 6eb2d4c..08d570f 100644 --- a/src/Product/Subject.php +++ b/src/Product/Subject.php @@ -21,6 +21,13 @@ class Subject */ protected $SubjectSchemeIdentifier; + /** + * SubjectSchemeName + * + * @var string + */ + protected $SubjectSchemeName; + /** * SubjectSchemeVersion * @@ -96,6 +103,16 @@ public function setSubjectHeadingText(string $SubjectHeadingText) $this->SubjectHeadingText = $SubjectHeadingText; } + /** + * Set SubjectSchemeName + * + * @return string + */ + public function setSubjectSchemeName(string $SubjectSchemeName) + { + $this->SubjectSchemeName = $SubjectSchemeName; + } + /** * Get MainSubject * @@ -146,4 +163,11 @@ public function getSubjectHeadingText() return $this->SubjectHeadingText; } + /** + * @return string + */ + public function getSubjectSchemeName() + { + return $this->SubjectSchemeName; + } } From 074d341e3caf0959774487754e4a237b637d64eb Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Thu, 29 Jun 2023 19:25:17 +0200 Subject: [PATCH 03/18] edition statement can be empty --- src/Product/DescriptiveDetail.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Product/DescriptiveDetail.php b/src/Product/DescriptiveDetail.php index c88d3ee..fe144c4 100644 --- a/src/Product/DescriptiveDetail.php +++ b/src/Product/DescriptiveDetail.php @@ -91,7 +91,7 @@ class DescriptiveDetail /** * EditionStatement * - * @var string + * @var string|null */ protected $EditionStatement; @@ -301,17 +301,17 @@ public function setEditionNumber(string $EditionNumber) } /** - * @return string + * @return string|null */ - public function getEditionStatement(): string + public function getEditionStatement(): ?string { return $this->EditionStatement; } /** - * @param string $EditionStatement + * @param string|null $EditionStatement */ - public function setEditionStatement(string $EditionStatement) + public function setEditionStatement(?string $EditionStatement) { $this->EditionStatement = $EditionStatement; } From 593b71ce3c3d4a5611c1b7b51f65437fd0793a8c Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Wed, 22 Oct 2025 11:30:38 +0200 Subject: [PATCH 04/18] update to symfony 7.3 / min php 8.2 --- composer.json | 14 +- composer.lock | 509 +++++++++++++++-------- src/Normalizer/CodeListNormalizer.php | 12 +- src/Normalizer/DateNormalizer.php | 14 +- src/Normalizer/ShortTagNameConverter.php | 4 +- src/Normalizer/TextNormalizer.php | 21 +- src/ONIXEncoder.php | 2 +- src/Parser.php | 2 +- 8 files changed, 390 insertions(+), 188 deletions(-) diff --git a/composer.json b/composer.json index ed19e7b..c261146 100644 --- a/composer.json +++ b/composer.json @@ -7,16 +7,22 @@ { "name": "Chris Ribal", "email": "c.ribal@ribal-webentwicklung.de" + }, + { + "name": "Alex Schwarz", + "email": "alexschwarz@live.de" } ], "require": { - "symfony/serializer": "^5.4", - "symfony/property-info": "^5.4", - "symfony/property-access": "^5.4" + "symfony/serializer": "^7.3", + "symfony/property-info": "^7.3", + "symfony/property-access": "^7.3", + "ext-dom": "*", + "php": ">=8.2" }, "autoload": { "psr-4": { "Ribal\\Onix\\": "src/" } } -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index c3edb39..45cf378 100644 --- a/composer.lock +++ b/composer.lock @@ -4,33 +4,86 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b76e95d0e5feea8e7d190596b17a819a", + "content-hash": "b9729bdafb1175a199e0dd4efee103da", "packages": [ + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -54,6 +107,9 @@ ], "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -68,24 +124,24 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -95,12 +151,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -133,6 +186,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -142,41 +198,42 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -211,6 +268,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -220,41 +280,42 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2025-06-27T09:58:17+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -292,6 +353,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -301,29 +365,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -333,12 +402,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -372,6 +438,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -381,38 +450,39 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { - "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "name": "symfony/polyfill-php84", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -420,7 +490,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Php84\\": "" }, "classmap": [ "Resources/stubs" @@ -431,10 +501,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -444,7 +510,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -452,6 +518,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -461,38 +530,37 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2025-06-24T13:30:11+00:00" }, { "name": "symfony/property-access", - "version": "v5.4.15", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "0f3e8f40a1d3da90f674b3dd772e4777ccde4273" + "reference": "4a4389e5c8bd1d0320d80a23caa6a1ac71cb81a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/0f3e8f40a1d3da90f674b3dd772e4777ccde4273", - "reference": "0f3e8f40a1d3da90f674b3dd772e4777ccde4273", + "url": "https://api.github.com/repos/symfony/property-access/zipball/4a4389e5c8bd1d0320d80a23caa6a1ac71cb81a7", + "reference": "4a4389e5c8bd1d0320d80a23caa6a1ac71cb81a7", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/property-info": "^5.2|^6.0" + "php": ">=8.2", + "symfony/property-info": "^6.4|^7.0" }, "require-dev": { - "symfony/cache": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/cache-implementation": "To cache access methods." + "symfony/cache": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -527,9 +595,12 @@ "injection", "object", "property", - "property path", + "property-path", "reflection" ], + "support": { + "source": "https://github.com/symfony/property-access/tree/v7.3.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -539,51 +610,50 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-10-27T07:55:40+00:00" + "time": "2025-08-04T15:15:28+00:00" }, { "name": "symfony/property-info", - "version": "v5.4.16", + "version": "v7.3.4", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "9dd148c4fbfc231fa4bff00def8dc16a2cd89944" + "reference": "7b6db23f23d13ada41e1cb484748a8ec028fbace" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/9dd148c4fbfc231fa4bff00def8dc16a2cd89944", - "reference": "9dd148c4fbfc231fa4bff00def8dc16a2cd89944", + "url": "https://api.github.com/repos/symfony/property-info/zipball/7b6db23f23d13ada41e1cb484748a8ec028fbace", + "reference": "7b6db23f23d13ada41e1cb484748a8ec028fbace", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/string": "^5.1|^6.0" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0", + "symfony/type-info": "~7.2.8|^7.3.1" }, "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/dependency-injection": "<4.4" + "phpdocumentor/reflection-docblock": "<5.2", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/cache": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/serializer": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.10.4", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "phpstan/phpdoc-parser": "^1.0", - "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/serializer": "^4.4|^5.0|^6.0" - }, - "suggest": { - "phpdocumentor/reflection-docblock": "To use the PHPDoc", - "psr/cache-implementation": "To cache results", - "symfony/doctrine-bridge": "To use Doctrine metadata", - "symfony/serializer": "To use Serializer metadata" + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "symfony/cache": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -618,6 +688,9 @@ "type", "validator" ], + "support": { + "source": "https://github.com/symfony/property-info/tree/v7.3.4" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -627,71 +700,71 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-11-19T17:41:50+00:00" + "time": "2025-09-15T13:55:54+00:00" }, { "name": "symfony/serializer", - "version": "v5.4.15", + "version": "v7.3.4", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "e80871599f6f0929bb349afc3d9ecaba783e68bd" + "reference": "0df5af266c6fe9a855af7db4fea86e13b9ca3ab1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/e80871599f6f0929bb349afc3d9ecaba783e68bd", - "reference": "e80871599f6f0929bb349afc3d9ecaba783e68bd", + "url": "https://api.github.com/repos/symfony/serializer/zipball/0df5af266c6fe9a855af7db4fea86e13b9ca3ab1", + "reference": "0df5af266c6fe9a855af7db4fea86e13b9ca3ab1", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-php84": "^1.30" }, "conflict": { - "doctrine/annotations": "<1.12", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", - "symfony/dependency-injection": "<4.4", - "symfony/property-access": "<5.4", - "symfony/property-info": "<5.3.13", - "symfony/uid": "<5.3", - "symfony/yaml": "<4.4" + "symfony/dependency-injection": "<6.4", + "symfony/property-access": "<6.4", + "symfony/property-info": "<6.4", + "symfony/uid": "<6.4", + "symfony/validator": "<6.4", + "symfony/yaml": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.12", "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0", - "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/form": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.3.13|^6.0", - "symfony/uid": "^5.3|^6.0", - "symfony/validator": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0", - "symfony/var-exporter": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/cache-implementation": "For using the metadata cache.", - "symfony/config": "For using the XML mapping loader.", - "symfony/mime": "For using a MIME type guesser within the DataUriNormalizer.", - "symfony/property-access": "For using the ObjectNormalizer.", - "symfony/property-info": "To deserialize relations.", - "symfony/var-exporter": "For using the metadata compiler.", - "symfony/yaml": "For using the default YAML mapping loader." + "phpstan/phpdoc-parser": "^1.0|^2.0", + "seld/jsonlint": "^1.10", + "symfony/cache": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^7.2", + "symfony/error-handler": "^6.4|^7.0", + "symfony/filesystem": "^6.4|^7.0", + "symfony/form": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/type-info": "^7.1.8", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -718,6 +791,9 @@ ], "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/serializer/tree/v7.3.4" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -727,43 +803,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-10-23T09:52:07+00:00" + "time": "2025-09-15T13:39:02+00:00" }, { "name": "symfony/string", - "version": "v5.4.15", + "version": "v7.3.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed" + "reference": "f96476035142921000338bad71e5247fbc138872" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/571334ce9f687e3e6af72db4d3b2a9431e4fd9ed", - "reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed", + "url": "https://api.github.com/repos/symfony/string/zipball/f96476035142921000338bad71e5247fbc138872", + "reference": "f96476035142921000338bad71e5247fbc138872", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" + "symfony/emoji": "^7.1", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -801,6 +881,92 @@ "utf-8", "utf8" ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-09-11T14:36:48+00:00" + }, + { + "name": "symfony/type-info", + "version": "v7.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/type-info.git", + "reference": "d34eaeb57f39c8a9c97eb72a977c423207dfa35b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/type-info/zipball/d34eaeb57f39c8a9c97eb72a977c423207dfa35b", + "reference": "d34eaeb57f39c8a9c97eb72a977c423207dfa35b", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "phpstan/phpdoc-parser": "<1.30" + }, + "require-dev": { + "phpstan/phpdoc-parser": "^1.30|^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\TypeInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mathias Arlaud", + "email": "mathias.arlaud@gmail.com" + }, + { + "name": "Baptiste LEDUC", + "email": "baptiste.leduc@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts PHP types information.", + "homepage": "https://symfony.com", + "keywords": [ + "PHPStan", + "phpdoc", + "symfony", + "type" + ], + "support": { + "source": "https://github.com/symfony/type-info/tree/v7.3.4" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -810,12 +976,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-10-05T15:16:54+00:00" + "time": "2025-09-11T15:33:27+00:00" } ], "packages-dev": [], @@ -824,7 +994,10 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "ext-dom": "*", + "php": ">=8.2" + }, "platform-dev": [], - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.6.0" } diff --git a/src/Normalizer/CodeListNormalizer.php b/src/Normalizer/CodeListNormalizer.php index 0cfa129..0dd63b7 100644 --- a/src/Normalizer/CodeListNormalizer.php +++ b/src/Normalizer/CodeListNormalizer.php @@ -35,7 +35,7 @@ public function __construct(string $language = 'en') * @param array $context * @return boolean */ - public function supportsNormalization($data, $format = null, array $context = []) + public function supportsNormalization($data, $format = null, array $context = []): bool { return $data instanceof CodeList; } @@ -48,7 +48,7 @@ public function supportsNormalization($data, $format = null, array $context = [] * @param array $context * @return void */ - public function normalize($data, $format = null, array $context = []) + public function normalize($data, $format = null, array $context = []): array|bool|string|int|float|null|\ArrayObject { return $data->getCode(); } @@ -62,7 +62,7 @@ public function normalize($data, $format = null, array $context = []) * @param array $context * @return boolean */ - public function supportsDenormalization($data, $type, $format = null, array $context = []) + public function supportsDenormalization($data, $type, $format = null, array $context = []): bool { return is_subclass_of($type, CodeList::class); } @@ -77,9 +77,13 @@ public function supportsDenormalization($data, $type, $format = null, array $con * @param array $context * @return CodeListList */ - public function denormalize($data, $type, $format = null, array $context = []) + public function denormalize($data, $type, $format = null, array $context = []): mixed { return $type::resolve($data, $this->language); } + public function getSupportedTypes(?string $format): array + { + return [CodeList::class => true]; + } } diff --git a/src/Normalizer/DateNormalizer.php b/src/Normalizer/DateNormalizer.php index 0355a97..8efdd21 100644 --- a/src/Normalizer/DateNormalizer.php +++ b/src/Normalizer/DateNormalizer.php @@ -10,12 +10,12 @@ class DateNormalizer implements NormalizerInterface, DenormalizerInterface { - public function normalize($object, $format = null, array $context = []) + public function normalize($object, $format = null, array $context = []): array|bool|string|int|float|null|\ArrayObject { return $object->formatOnix(); } - public function denormalize($data, $type, $format = null, array $context = []) + public function denormalize($data, $type, $format = null, array $context = []): mixed { $date = Date::parse( is_array($data) ? $data['#'] : $data, @@ -25,14 +25,20 @@ public function denormalize($data, $type, $format = null, array $context = []) return $date; } - public function supportsNormalization($data, $format = null) + public function supportsNormalization($data, $format = null, array $context = []): bool { return $data instanceof Date; } - public function supportsDenormalization($data, $type, $format = null) + public function supportsDenormalization($data, $type, $format = null, array $context = []): bool { return $type == Date::class; } + public function getSupportedTypes(?string $format): array + { + return [ + Date::class => true, + ]; + } } \ No newline at end of file diff --git a/src/Normalizer/ShortTagNameConverter.php b/src/Normalizer/ShortTagNameConverter.php index 7d317eb..aad871d 100644 --- a/src/Normalizer/ShortTagNameConverter.php +++ b/src/Normalizer/ShortTagNameConverter.php @@ -458,7 +458,7 @@ class ShortTagNameConverter implements NameConverterInterface * @param string $propertyName * @return string */ - public function normalize($propertyName) + public function normalize($propertyName): string { return ($key = array_search($propertyName, self::$shortToRef)) ? $key : $propertyName; @@ -471,7 +471,7 @@ public function normalize($propertyName) * @param string $propertyName * @return string */ - public function denormalize($propertyName) + public function denormalize($propertyName): string { return array_key_exists($propertyName, self::$shortToRef) ? self::$shortToRef[$propertyName] : $propertyName; diff --git a/src/Normalizer/TextNormalizer.php b/src/Normalizer/TextNormalizer.php index 648eea3..6eb5f48 100644 --- a/src/Normalizer/TextNormalizer.php +++ b/src/Normalizer/TextNormalizer.php @@ -13,7 +13,7 @@ class TextNormalizer implements NormalizerInterface, DenormalizerInterface /** * {@inheritDoc} */ - public function normalize($object, $format = null, array $context = []) + public function normalize($object, $format = null, array $context = []): array|bool|string|int|float|null|\ArrayObject { } @@ -21,7 +21,7 @@ public function normalize($object, $format = null, array $context = []) /** * {@inheritDoc} */ - public function denormalize($data, $type, $format = null, array $context = []) + public function denormalize($data, $type, $format = null, array $context = []): mixed { $textFormat = isset($data['@textformat']) ? $data['@textformat'] : Text::TYPE_DEFAULT; @@ -38,18 +38,31 @@ public function denormalize($data, $type, $format = null, array $context = []) /** * {@inheritDoc} + * @param mixed $data + * @param null $format + * @param array $context */ - public function supportsNormalization($data, $format = null) + public function supportsNormalization($data, $format = null, array $context = []): bool { } /** * {@inheritDoc} + * @param mixed $data + * @param string $type + * @param null $format + * @param array $context */ - public function supportsDenormalization($data, $type, $format = null) + public function supportsDenormalization($data, $type, $format = null, array $context = []): bool { return $type == Text::class; } + public function getSupportedTypes(?string $format): array + { + return [ + Text::class => true, + ]; + } } diff --git a/src/ONIXEncoder.php b/src/ONIXEncoder.php index 6a9a190..dc2610c 100644 --- a/src/ONIXEncoder.php +++ b/src/ONIXEncoder.php @@ -13,7 +13,7 @@ class ONIXEncoder extends XmlEncoder /** * {@inheritdoc} */ - public function decode($data, $format, array $context = []) + public function decode(string $data, string $format, array $context = []): mixed { if ('' === trim($data)) { diff --git a/src/Parser.php b/src/Parser.php index 2de263c..4747cde 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -51,7 +51,7 @@ public function __construct(string $language = 'en') $supportedLanguages = ['en', 'es', 'de', 'fr', 'it', 'nb', 'tr']; if (!in_array($language, $supportedLanguages)) { - throw new \InvalidArgumentException('Language must be one of ' . join(', ', $supportedLanguages)); + throw new \InvalidArgumentException('Language must be one of ' . implode(', ', $supportedLanguages)); } $this->encoder = new ONIXEncoder(); From 5d6c47f5eb3e83544874a86238601a7325aeac84 Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Wed, 22 Oct 2025 14:58:16 +0200 Subject: [PATCH 05/18] Update readme.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 68b9721..2ba1caf 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,13 @@ # PHP ONIX 3.0 Parser + +This fork requires PHP 8.2+ and is updated to use Symfony 7.3+ + This package is a simple PHP library for reading ONIX 3.0 files in the general formats Short and Ref. Helper functions in the individual units make it easy to read out the details that you need from the data record. Text elements in different formats as well as the different ONIX date formats are automatically parsed and can therefore be used easily. __This package is currently under development. Although most fields should be detected and parsed by the library, some fields still need more work.__ ## Installation -PHP 7.1 or greater is required. +PHP 8.2 or greater is required. Installation is recommended to be done via composer by running: ``` From 45b80b6e39dbff11fb66bb14e4450833717c9bae Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Tue, 28 Oct 2025 15:15:34 +0100 Subject: [PATCH 06/18] Updated CodeList196 to issue 70 --- src/CodeList/CodeList196.php | 460 ++++++++++++++++------------------- 1 file changed, 204 insertions(+), 256 deletions(-) diff --git a/src/CodeList/CodeList196.php b/src/CodeList/CodeList196.php index 0c540f7..38f5958 100644 --- a/src/CodeList/CodeList196.php +++ b/src/CodeList/CodeList196.php @@ -1,7 +1,9 @@ - 'Accessibility summary', - '01' => 'LIA Compliance Scheme', - '02' => 'EPUB Accessibility Specification 1.0 A', - '03' => 'EPUB Accessibility Specification 1.0 AA', - '05' => 'PDF/UA', - '09' => 'Inaccessible', - '10' => 'No reading system accessibility options disabled (except)', - '11' => 'Table of contents navigation', - '12' => 'Index navigation', - '13' => 'Reading order', - '14' => 'Short alternative descriptions', - '15' => 'Full alternative descriptions', - '16' => 'Visualised data also available as non-graphical data', - '17' => 'Accessible math content', - '18' => 'Accessible chem content', - '19' => 'Print-equivalent page numbering', - '20' => 'Synchronised pre-recorded audio', - '21' => 'Text-to-speech hinting provided', - '22' => 'Language tagging provided', - '24' => 'Dyslexia readability', - '25' => 'Use of color', - '26' => 'Use of contrast', - '94' => 'Compliance web page for detailed accessibility information', - '95' => 'Trusted intermediary’s web page for detailed accessibility information', - '96' => 'Publisher’s web page for detailed accessibility information', - '97' => 'Compatibility tested', - '98' => 'Trusted Intermediary contact', - '99' => 'Publisher contact for further accessibility information', - ]; - - /** - * Code List 196 for es - * - * @var array - * @see https://ns.editeur.org/onix/es/196 - */ - protected static $es = [ - '00' => 'Resumen de accesibilidad', - '01' => 'Esquema de conformidad LIA', - '02' => 'Especificación de accesibilidad EPUB 1.0 A', - '03' => 'Especificación de accesibilidad EPUB 1.0 AA', - '05' => 'PDF/UA', - '09' => 'Inaccesible', - '10' => 'No está desactivada ninguna opción de accesibilidad al sistema de lectura (Con excepciones)', - '11' => 'Navegación en la tabla de contenidos', - '12' => 'Índice navegable', - '13' => 'Orden de lectura', - '14' => 'Descripciones alternativas cortas', - '15' => 'Descripciones alternativas completas', - '16' => 'Visualizaciones de datos también disponibles en forma no gráfica', - '17' => 'Contenido matemático accesible', - '18' => 'Contenido de notación química accesible', - '19' => 'Numeración de páginas equivalente a la de la versión impresa', - '20' => 'Audio pregrabado sincronizado', - '21' => 'Incluye pistas para la síntesis de voz', - '22' => 'Incluye etiquetado de idioma', - '24' => 'Legibilidad para personas con dislexia', - '25' => 'Uso del color', - '26' => 'Uso del contraste', - '94' => 'Página web de certificación, con información detallada de accesibilidad', - '95' => 'Página web de un intermediario de confianza, con información detallada de accesibilidad', - '96' => 'Página web de la editorial, con información detallada de accesibilidad', - '97' => 'Testeado para compatibilidad', - '98' => 'Contacto de intermediario de confianza', - '99' => 'Contacto en la editorial para más información sobre accesibilidad', - ]; - - /** - * Code List 196 for de - * - * @var array - * @see https://ns.editeur.org/onix/de/196 - */ - protected static $de = [ - '00' => 'Accessibility summary', - '01' => 'LIA Compliance Scheme', - '02' => 'EPUB Accessibility Specification 1.0 A', - '03' => 'EPUB Accessibility Specification 1.0 AA', - '05' => 'PDF/UA', - '09' => 'Inaccessible', - '10' => 'No reading system accessibility options disabled (except)', - '11' => 'Table of contents navigation', - '12' => 'Index navigation', - '13' => 'Reading order', - '14' => 'Short alternative descriptions', - '15' => 'Full alternative descriptions', - '16' => 'Visualised data also available as non-graphical data', - '17' => 'Accessible math content', - '18' => 'Accessible chem content', - '19' => 'Print-equivalent page numbering', - '20' => 'Synchronised pre-recorded audio', - '21' => 'Text-to-speech hinting provided', - '22' => 'Language tagging provided', - '24' => 'Dyslexia readability', - '25' => 'Use of color', - '26' => 'Use of contrast', - '94' => 'Compliance web page for detailed accessibility information', - '95' => 'Trusted intermediary’s web page for detailed accessibility information', - '96' => 'Publisher’s web page for detailed accessibility information', - '97' => 'Compatibility tested', - '98' => 'Trusted Intermediary contact', - '99' => 'Publisher contact for further accessibility information', - ]; + /** + * Code List 196 for en (English) + * E-publication accessibility details + * + * @var array + * @see https://ns.editeur.org/onix/en/196 + */ + protected static $en = [ + '00' => 'Accessibility summary', + '01' => 'LIA Compliance Scheme', + '02' => 'EPUB Accessibility Specification 1.0 A', + '03' => 'EPUB Accessibility Specification 1.0 AA', + '05' => 'PDF/UA', + '08' => 'Unknown accessibility', // NEW in Issue 70 + '09' => 'Inaccessible', + '10' => 'No reading system accessibility options disabled (except)', + '11' => 'Table of contents navigation', + '12' => 'Index navigation', + '13' => 'Reading order', + '14' => 'Short alternative descriptions', + '15' => 'Full alternative descriptions', + '16' => 'Visualised data also available as non-graphical data', + '17' => 'Accessible math content', + '18' => 'Accessible chem content', + '19' => 'Print-equivalent page numbering', + '20' => 'Synchronised pre-recorded audio', + '21' => 'Text-to-speech hinting provided', + '22' => 'Language tagging provided', + '23' => 'Accessible interactive elements', // NEW in Issue 65 + '24' => 'Dyslexia readability', + '25' => 'Use of color', + '26' => 'Use of contrast', + '27' => 'Accessibility certification', // NEW in Issue 68 + '94' => 'Compliance web page for detailed accessibility information', + '95' => "Trusted intermediary's web page for detailed accessibility information", + '96' => "Publisher's web page for detailed accessibility information", + '97' => 'Compatibility tested', + '98' => 'Trusted Intermediary contact', + '99' => 'Publisher contact for further accessibility information', + ]; - /** - * Code List 196 for fr - * - * @var array - * @see https://ns.editeur.org/onix/fr/196 - */ - protected static $fr = [ - '00' => 'Résumé sur l’accessibilité', - '01' => 'Conforme aux instructions de la LIA (Libri Italiani Accessibili)', - '02' => 'Spécifications d’accessibilité EPUB 1.0 A', - '03' => 'Spécifications d’accessibilité EPUB 1.0 AA', - '05' => 'PDF/UA', - '09' => 'Inaccessible', - '10' => 'Aucune option d’accessibilité au système désactivée (exception)', - '11' => 'Navigation dans la table des matières', - '12' => 'Navigation dans l’index', - '13' => 'Ordre de lecture', - '14' => 'Brèves descriptions alternatives', - '15' => 'Descriptions alternatives complètes', - '16' => 'Représentations graphiques de données également accessibles comme données non graphiques', - '17' => 'Contenu mathématique accessible', - '18' => 'Contenu chimique accessible', - '19' => 'Numérotation de pages équivalente au document imprimé', - '20' => 'Audio synchronisé préenregistré', - '21' => 'Synthèse vocale optimisée', - '22' => 'Balisage de la langue fourni', - '24' => 'Lisibilité adaptée à la dyslexie', - '25' => 'Use of color', - '26' => 'Use of contrast', - '94' => 'Page web pour les informations détaillées d’accessibilité', - '95' => 'Page web d’un intermédiaire approuvé pour les informations détaillées d’accessibilité', - '96' => 'Page web de l’éditeur pour les informations détaillées d’accessibilité', - '97' => 'Compatibilité testée', - '98' => 'Contact intermédiaire approuvé', - '99' => 'Contact éditeur pour informations complémentaires sur l’accessibilité', - ]; + /** + * Code List 196 for de (German) + * E-Publikations-Zugänglichkeitsdetails + * + * @var array + * @see https://ns.editeur.org/onix/de/196 + */ + protected static $de = [ + '00' => 'Zugänglichkeit-Zusammenfassung', + '01' => 'LIA-Konformitätsplan', + '02' => 'EPUB Accessibility Specification 1.0 A', + '03' => 'EPUB Accessibility Specification 1.0 AA', + '05' => 'PDF/UA', + '08' => 'Unbekannte Zugänglichkeit', + '09' => 'Nicht zugänglich', + '10' => 'Keine Lesegerät-Zugänglichkeitsoptionen deaktiviert (außer)', + '11' => 'Inhaltsverzeichnis-Navigation', + '12' => 'Index-Navigation', + '13' => 'Lesereihenfolge', + '14' => 'Kurze Alternativbeschreibungen', + '15' => 'Vollständige Alternativbeschreibungen', + '16' => 'Visualisierte Daten auch als nicht-graphische Daten verfügbar', + '17' => 'Zugänglicher Mathematikinhalt', + '18' => 'Zugänglicher Chemieinhalt', + '19' => 'Druckäquivalente Seitennummerierung', + '20' => 'Synchronisiertes vorab aufgenommenes Audio', + '21' => 'Text-to-Speech-Hinweise bereitgestellt', + '22' => 'Sprachkennzeichnung bereitgestellt', + '23' => 'Zugängliche interaktive Elemente', + '24' => 'Legbarkeit für Menschen mit Dyslexie', + '25' => 'Verwendung von Farben', + '26' => 'Verwendung von Kontrast', + '27' => 'Zugänglichkeits-Zertifizierung', + '94' => 'Webseite für Konformität mit detaillierten Zugänglichkeitsinformationen', + '95' => 'Webseite eines vertrauenswürdigen Vermittlers mit detaillierten Zugänglichkeitsinformationen', + '96' => 'Webseite des Verlags mit detaillierten Zugänglichkeitsinformationen', + '97' => 'Kompatibilität getestet', + '98' => 'Kontakt des vertrauenswürdigen Vermittlers', + '99' => 'Verlagskontakt für weitere Zugänglichkeitsinformationen', + ]; - /** - * Code List 196 for it - * - * @var array - * @see https://ns.editeur.org/onix/it/196 - */ - protected static $it = [ - '00' => 'Riepilogo sull’accessibilità', - '01' => 'Certificazione LIA', - '02' => 'Specifiche di accessibilità EPUB 1.0 A', - '03' => 'Specifiche di accessibilità EPUB 1.0 AA', - '05' => 'PDF/UA', - '09' => 'Non accessibile', - '10' => 'Opzioni di accessibilità del sistema di lettura attive (con eccezione)', - '11' => 'Navigazione dell’indice dei contenuti', - '12' => 'Navigazione dell’indice analitico', - '13' => 'Ordine di lettura', - '14' => 'Descrizioni alternative brevi', - '15' => 'Descrizioni alternative estese', - '16' => 'Dati visualizzati disponibili anche come dati non grafici', - '17' => 'Contenuto di matematica accessibile', - '18' => 'Contenuto di chimica accessibile', - '19' => 'Numerazione delle pagine equivalente alla versione a stampa', - '20' => 'Audio sincronizzato pre-registrato', - '21' => 'Funzione di sintesi vocale inclusa', - '22' => 'Funzione di riconoscimento della lingua inclusa', - '24' => 'Leggibilità per dislessici', - '25' => 'Utilizzo del colore', - '26' => 'Utilizzo del contrasto', - '94' => 'Pagina internet con informazioni dettagliate sull’accessibilità', - '95' => 'Pagina internet dell’intermediario accreditato con le informazioni sull’accessibilità', - '96' => 'Pagina internet dell’editore con le informazioni sull’accessibilità', - '97' => 'Esito verifica sulla compatibilità', - '98' => 'Contatto dell’intermediario accreditato', - '99' => 'Contatto dell’editore per ulteriori informazioni sull’accessibilità', - ]; + /** + * Code List 196 for es (Spanish) + * Detalles de accesibilidad de publicaciones electrónicas + * + * @var array + * @see https://ns.editeur.org/onix/es/196 + */ + protected static $es = [ + '00' => 'Resumen de accesibilidad', + '01' => 'Esquema de conformidad LIA', + '02' => 'Especificación de accesibilidad EPUB 1.0 A', + '03' => 'Especificación de accesibilidad EPUB 1.0 AA', + '05' => 'PDF/UA', + '08' => 'Accesibilidad desconocida', + '09' => 'Inaccesible', + '10' => 'No está desactivada ninguna opción de accesibilidad al sistema de lectura (Con excepciones)', + '11' => 'Navegación en la tabla de contenidos', + '12' => 'Índice navegable', + '13' => 'Orden de lectura', + '14' => 'Descripciones alternativas cortas', + '15' => 'Descripciones alternativas completas', + '16' => 'Visualizaciones de datos también disponibles en forma no gráfica', + '17' => 'Contenido matemático accesible', + '18' => 'Contenido de notación química accesible', + '19' => 'Numeración de páginas equivalente a la de la versión impresa', + '20' => 'Audio pregrabado sincronizado', + '21' => 'Incluye pistas para la síntesis de voz', + '22' => 'Incluye etiquetado de idioma', + '23' => 'Elementos interactivos accesibles', + '24' => 'Legibilidad para personas con dislexia', + '25' => 'Uso del color', + '26' => 'Uso del contraste', + '27' => 'Certificación de accesibilidad', + '94' => 'Página web de certificación, con información detallada de accesibilidad', + '95' => 'Página web de un intermediario de confianza, con información detallada de accesibilidad', + '96' => 'Página web de la editorial, con información detallada de accesibilidad', + '97' => 'Testeado para compatibilidad', + '98' => 'Contacto de intermediario de confianza', + '99' => 'Contacto en la editorial para más información sobre accesibilidad', + ]; - /** - * Code List 196 for nb - * - * @var array - * @see https://ns.editeur.org/onix/nb/196 - */ - protected static $nb = [ - '00' => 'Tilgjengelighet, sammendrag', - '01' => 'LIA Compliance Scheme', - '02' => 'EPUB Tilgjengelighetsspesifikasjon 1.0 A', - '03' => 'EPUB Tilgjengelighetsspesifikasjon 1.0 AA', - '05' => 'PDF/UA', - '09' => 'Utilgjengelig', - '10' => 'Ingen av lesesystemets funksjoner for tilgjengelighet er deaktivert (unntatt)', - '11' => 'Innholdsfortegnelse med navigasjon', - '12' => 'Register med navigasjon', - '13' => 'Leserekkefølge', - '14' => 'Korte alternative beskrivelser', - '15' => 'Fullstendige alternative beskrivelser', - '16' => 'Visuelle data er også tilgjengelig som ikke-grafisk data', - '17' => 'Tilgjengelig matematisk innhold', - '18' => 'Tilgjengelig kjemisk innhold', - '19' => 'Sidetall i tilsvarende trykt utgave', - '20' => 'Synkronisert forhåndsinnspilt lyd', - '21' => 'Tekst-til-tale er tilgjengelig', - '22' => 'Språktagging er tilgjengelig', - '24' => 'Dysleksi: lesbarhet', - '25' => 'Bruk av farge', - '26' => 'Bruk av kontrast', - '94' => 'Nettside for detaljert tilgjengelighetsinformasjon', - '95' => 'Nettside for detaljert tilgjengelighetsinformasjon, fra en pålitelig tredjepart', - '96' => 'Utgivers nettside for detaljert tilgjengelighetsinformasjon', - '97' => 'Testet for kompatibilitet', - '98' => 'Kontaktinformasjon til en pålitelig tredjepart', - '99' => 'Kontaktinformasjon til utgiver for ytterligere informasjon om tilgjengelighet', - ]; + /** + * Code List 196 for it (Italian) + * Dettagli di accessibilità per e-pubblicazioni + * + * @var array + * @see https://ns.editeur.org/onix/it/196 + */ + protected static $it = [ + '00' => 'Riepilogo accessibilità', + '01' => 'Schema di conformità LIA', + '02' => 'Specifica di accessibilità EPUB 1.0 A', + '03' => 'Specifica di accessibilità EPUB 1.0 AA', + '05' => 'PDF/UA', + '08' => 'Accessibilità sconosciuta', + '09' => 'Non accessibile', + '10' => "Nessuna opzione di accessibilità del sistema di lettura disabilitata (eccetto)", + '11' => 'Navigazione nel sommario', + '12' => 'Navigazione nell\'indice', + '13' => 'Ordine di lettura', + '14' => 'Descrizioni alternative brevi', + '15' => 'Descrizioni alternative complete', + '16' => 'Dati visualizzati anche disponibili come dati non grafici', + '17' => 'Contenuto matematico accessibile', + '18' => 'Contenuto chimico accessibile', + '19' => 'Numerazione delle pagine equivalente alla versione stampata', + '20' => 'Audio preregistrato sincronizzato', + '21' => 'Forniti suggerimenti per la sintesi vocale', + '22' => 'Fornita etichettatura linguistica', + '23' => 'Elementi interattivi accessibili', + '24' => 'Leggibilità per dislessici', + '25' => 'Utilizzo del colore', + '26' => 'Utilizzo del contrasto', + '27' => 'Certificazione di accessibilità', + '94' => "Pagina web di conformità per informazioni dettagliate sull'accessibilità", + '95' => "Pagina web di un intermediario fidato per informazioni dettagliate sull'accessibilità", + '96' => "Pagina web dell'editore per informazioni dettagliate sull'accessibilità", + '97' => 'Compatibilità testata', + '98' => 'Contatto intermediario fidato', + '99' => "Contatto editore per ulteriori informazioni sull'accessibilità", + ]; - /** - * Code List 196 for tr - * - * @var array - * @see https://ns.editeur.org/onix/tr/196 - */ - protected static $tr = [ - '00' => 'Erişilebilirlik özeti', - '01' => 'LIA Uyumluluk Düzeni', - '02' => 'Erişilebilirlik Spesifikasyonu 1.0 A', - '03' => 'Erişilebilirlik Spesifikasyonu 1.0 AA', - '05' => 'PDF/UA', - '09' => 'Erişim dışı', - '10' => 'Hiçbir okuyucu sistemi erişilebilirlik seçeneği geçersizkılınmamıştır (istisna)', - '11' => 'İçindekiler tablosu gezintisi', - '12' => 'Dizin gezintisi', - '13' => 'Okuma düzeni', - '14' => 'Kısa alternatif tanımlar', - '15' => 'Tam alternatif tanımlar', - '16' => 'Görselleştirilmiş veri grafik olmayan veri olarak da mevcut', - '17' => 'Erişilebilir matematiksel içerik', - '18' => 'Erişilebilir kimyasal içerik', - '19' => 'Basılı eşdeğeri sayfa numaralandırma', - '20' => 'Senkronize ön kayıtlı işitsel', - '21' => 'Metin okuma desteği var', - '22' => 'Dil etiketleme var', - '24' => 'Disleksi okunabilirliği', - '25' => 'Use of color', - '26' => 'Use of contrast', - '94' => 'Ayrıntılı erişilebilirlik bilgileri için uygunluk web sayfası', - '95' => 'Ayrıntılı erişilebilirlik bilgileri için güvenilir aracı kuruluşun web sayfası', - '96' => 'Ayrıntılı erişilebilirlik bilgileri için yayımcının web sayfası', - '97' => 'Uyumluluk test edildi', - '98' => 'Güvenilir aracı ilişki', - '99' => 'Daha fazla erişilebilirlik bilgisi için yayımcı ilişkisi', - ]; -} + /** + * Code List 196 for tr (Turkish) + * E-yayın erişilebilirlik detayları + * + * @var array + * @see https://ns.editeur.org/onix/tr/196 + */ + protected static $tr = [ + '00' => 'Erişilebilirlik özeti', + '01' => 'LIA Uyum Planı', + '02' => 'EPUB Erişilebilirlik Spesifikasyonu 1.0 A', + '03' => 'EPUB Erişilebilirlik Spesifikasyonu 1.0 AA', + '05' => 'PDF/UA', + '08' => 'Bilinmeyen erişilebilirlik', // NEW in Issue 70 + '09' => 'Erişilemez', + '10' => 'Okuma sistemi erişilebilirlik seçenekleri devre dışı bırakılmadı (istisnalar hariç)', + '11' => 'İçindekiler tablosu gezinimi', + '12' => 'İndeks gezinimi', + '13' => 'Okuma sırası', + '14' => 'Kısa alternatif açıklamalar', + '15' => 'Tam alternatif açıklamalar', + '16' => 'Görselleştirilmiş veriler ayrıca grafik olmayan veri olarak da mevcut', + '17' => 'Erişilebilir matematik içeriği', + '18' => 'Erişilebilir kimya içeriği', + '19' => 'Baskı eşdeğeri sayfa numaralandırması', + '20' => 'Senkronize önceden kaydedilmiş ses', + '21' => 'Metin-konuşma ipuçları sağlandı', + '22' => 'Dil etiketleme sağlandı', + '23' => 'Erişilebilir etkileşimli öğeler', // NEW in Issue 65 + '24' => 'Disleksi okunabilirliği', + '25' => 'Renk kullanımı', + '26' => 'Kontrast kullanımı', + '27' => 'Erişilebilirlik sertifikasyonu', // NEW in Issue 68 + '94' => 'Detaylı erişilebilirlik bilgileri için uyum web sayfası', + '95' => 'Detaylı erişilebilirlik bilgileri için güvenilir aracı web sayfası', + '96' => 'Detaylı erişilebilirlik bilgileri için yayıncı web sayfası', + '97' => 'Uyumluluk test edildi', + '98' => 'Güvenilir aracı iletişim', + '99' => 'Daha fazla erişilebilirlik bilgisi için yayıncı iletişim', + ]; +} \ No newline at end of file From f65c5604a54251f5b2572b3efa9f5d87e85a54ad Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Tue, 11 Nov 2025 11:23:20 +0100 Subject: [PATCH 07/18] add missing getter for taxratepercent --- src/Product/Tax.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Product/Tax.php b/src/Product/Tax.php index 99dfaf2..e7208d5 100644 --- a/src/Product/Tax.php +++ b/src/Product/Tax.php @@ -138,4 +138,11 @@ public function getTaxAmount() return $this->TaxAmount; } + /** + * @return float + */ + public function getTaxRatePercent() + { + return $this->TaxRatePercent; + } } \ No newline at end of file From 69496852f65db6f88fd07371ec1f9cd7d26067e0 Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Tue, 25 Nov 2025 20:49:46 +0100 Subject: [PATCH 08/18] add support for PriceDate --- src/Product/Price.php | 17 ++++++++++ src/Product/PriceDate.php | 68 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/Product/PriceDate.php diff --git a/src/Product/Price.php b/src/Product/Price.php index 3ec07b0..4591b56 100644 --- a/src/Product/Price.php +++ b/src/Product/Price.php @@ -81,6 +81,23 @@ class Price */ protected $Territory; + /** + * PriceDate + * + * @var PriceDate + */ + protected ?PriceDate $PriceDate = null; + + public function setPriceDate(?PriceDate $PriceDate) + { + $this->PriceDate = $PriceDate; + } + + public function getPriceDate(): ?PriceDate + { + return $this->PriceDate; + } + /** * Set PriceType * diff --git a/src/Product/PriceDate.php b/src/Product/PriceDate.php new file mode 100644 index 0000000..9473d46 --- /dev/null +++ b/src/Product/PriceDate.php @@ -0,0 +1,68 @@ +Date = $date; + } + + public function getDate(): ?string + { + return $this->Date; + } + + /** + * Set DateFormat (b306@dateformat) + */ + public function setDateFormat(?string $format): void + { + $this->DateFormat = $format; + } + + public function getDateFormat(): ?string + { + return $this->DateFormat; + } + + /** + * Set PriceDateRole + * + * @param int $PriceDateRole + * @return void + */ + public function setPriceDateRole(CodeList173 $PriceDateRole) + { + $this->PriceDateRole = $PriceDateRole; + } + + public function getPriceDateRole(): CodeList + { + return $this->PriceDateRole; + } +} \ No newline at end of file From 667a95cf2713f76fe51771ccbf41eac34ce3b325 Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Thu, 22 Jan 2026 11:47:45 +0100 Subject: [PATCH 09/18] add support for illustrationsnote, normalizer for productformfeature to separate between codelist196 and codelist98 --- .../ProductFormFeatureNormalizer.php | 78 +++++++++++++++++++ src/Parser.php | 2 + src/Product/DescriptiveDetail.php | 28 +++++++ src/Product/ProductFormFeature.php | 5 +- 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 src/Normalizer/ProductFormFeatureNormalizer.php diff --git a/src/Normalizer/ProductFormFeatureNormalizer.php b/src/Normalizer/ProductFormFeatureNormalizer.php new file mode 100644 index 0000000..4689757 --- /dev/null +++ b/src/Normalizer/ProductFormFeatureNormalizer.php @@ -0,0 +1,78 @@ +language = $language; + } + + public function supportsNormalization($data, $format = null, array $context = []): bool + { + return $data instanceof ProductFormFeature; + } + + public function normalize($data, $format = null, array $context = []): array|bool|string|int|float|null|\ArrayObject + { + return $this->denormalizer->normalize($data, $format, $context); + } + + public function supportsDenormalization($data, $type, $format = null, array $context = []): bool + { + return $type === ProductFormFeature::class; + } + + public function denormalize($data, $type, $format = null, array $context = []): mixed + { + $feature = new ProductFormFeature(); + + if (isset($data['ProductFormFeatureType'])) { + $typeCode = is_array($data['ProductFormFeatureType']) ? ($data['ProductFormFeatureType']['#'] ?? null) : $data['ProductFormFeatureType']; + if ($typeCode) { + $featureType = CodeList79::resolve($typeCode, $this->language); + $feature->setProductFormFeatureType($featureType); + } + } + + if (isset($data['ProductFormFeatureDescription'])) { + $feature->setProductFormFeatureDescription($data['ProductFormFeatureDescription']); + } + + if (isset($data['ProductFormFeatureValue'])) { + $valueCode = is_array($data['ProductFormFeatureValue']) ? ($data['ProductFormFeatureValue']['#'] ?? null) : $data['ProductFormFeatureValue']; + + if ($valueCode) { + $typeCode = $feature->getProductFormFeatureType() ? $feature->getProductFormFeatureType()->getCode() : null; + + // If Type is 09 (E-publication accessibility detail), use CodeList 196 + if ($typeCode === '09') { + $feature->setProductFormFeatureValue(CodeList196::resolve($valueCode, $this->language)); + } else { + $feature->setProductFormFeatureValue(CodeList98::resolve($valueCode, $this->language)); + } + } + } + + return $feature; + } + + public function getSupportedTypes(?string $format): array + { + return [ProductFormFeature::class => true]; + } +} diff --git a/src/Parser.php b/src/Parser.php index 4747cde..f079efe 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -5,6 +5,7 @@ use Ribal\Onix\Message\Message; use Ribal\Onix\Normalizer\CodeListNormalizer; use Ribal\Onix\Normalizer\DateNormalizer; +use Ribal\Onix\Normalizer\ProductFormFeatureNormalizer; use Ribal\Onix\Normalizer\ShortTagNameConverter; use Ribal\Onix\Normalizer\TextNormalizer; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; @@ -58,6 +59,7 @@ public function __construct(string $language = 'en') $this->normalizers = [ new ArrayDenormalizer(), + new ProductFormFeatureNormalizer($language), new CodeListNormalizer($language), new DateNormalizer(), new TextNormalizer(), diff --git a/src/Product/DescriptiveDetail.php b/src/Product/DescriptiveDetail.php index fe144c4..e57a3eb 100644 --- a/src/Product/DescriptiveDetail.php +++ b/src/Product/DescriptiveDetail.php @@ -81,6 +81,13 @@ class DescriptiveDetail */ protected $ContributorStatement; + /** + * IllustrationsNote + * + * @var string + */ + protected $IllustrationsNote; + /** * EditionNumber * @@ -493,6 +500,27 @@ public function getContributorStatement() return $this->ContributorStatement; } + /** + * Set IllustrationsNote + * + * @param string $IllustrationsNote + * @return void + */ + public function setIllustrationsNote(string $IllustrationsNote) + { + $this->IllustrationsNote = $IllustrationsNote; + } + + /** + * Get IllustrationsNote + * + * @return string + */ + public function getIllustrationsNote() + { + return $this->IllustrationsNote; + } + /** * Get Title detail * diff --git a/src/Product/ProductFormFeature.php b/src/Product/ProductFormFeature.php index 5ca8efb..580cb41 100644 --- a/src/Product/ProductFormFeature.php +++ b/src/Product/ProductFormFeature.php @@ -2,6 +2,7 @@ namespace Ribal\Onix\Product; +use Ribal\Onix\CodeList\CodeList196; use Ribal\Onix\CodeList\CodeList79; use Ribal\Onix\CodeList\CodeList98; @@ -43,10 +44,10 @@ public function setProductFormFeatureType(CodeList79 $ProductFormFeatureType) /** * Set ProductFormFeatureValue * - * @param CodeList98 $ProductFormFeatureValue + * @param CodeList98|CodeList196 $ProductFormFeatureValue * @return void */ - public function setProductFormFeatureValue(CodeList98 $ProductFormFeatureValue) + public function setProductFormFeatureValue(CodeList98 | CodeList196 $ProductFormFeatureValue) { $this->ProductFormFeatureValue = $ProductFormFeatureValue; } From 5ede022a2242cbda31e29b5c22e3caff05b98380 Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Thu, 22 Jan 2026 12:50:18 +0100 Subject: [PATCH 10/18] changed product form feature normalization to shortcodes --- .../ProductFormFeatureNormalizer.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Normalizer/ProductFormFeatureNormalizer.php b/src/Normalizer/ProductFormFeatureNormalizer.php index 4689757..74f7f28 100644 --- a/src/Normalizer/ProductFormFeatureNormalizer.php +++ b/src/Normalizer/ProductFormFeatureNormalizer.php @@ -41,26 +41,29 @@ public function denormalize($data, $type, $format = null, array $context = []): { $feature = new ProductFormFeature(); - if (isset($data['ProductFormFeatureType'])) { - $typeCode = is_array($data['ProductFormFeatureType']) ? ($data['ProductFormFeatureType']['#'] ?? null) : $data['ProductFormFeatureType']; + $productFormFeatureType = $data['ProductFormFeatureType'] ?? $data['b334'] ?? null; + if ($productFormFeatureType) { + $typeCode = is_array($productFormFeatureType) ? ($productFormFeatureType['#'] ?? null) : $productFormFeatureType; if ($typeCode) { $featureType = CodeList79::resolve($typeCode, $this->language); $feature->setProductFormFeatureType($featureType); } } - if (isset($data['ProductFormFeatureDescription'])) { - $feature->setProductFormFeatureDescription($data['ProductFormFeatureDescription']); + $productFormFeatureDescription = $data['ProductFormFeatureDescription'] ?? $data['b336'] ?? null; + if ($productFormFeatureDescription) { + $feature->setProductFormFeatureDescription($productFormFeatureDescription); } - if (isset($data['ProductFormFeatureValue'])) { - $valueCode = is_array($data['ProductFormFeatureValue']) ? ($data['ProductFormFeatureValue']['#'] ?? null) : $data['ProductFormFeatureValue']; + $productFormFeatureValue = $data['ProductFormFeatureValue'] ?? $data['b335'] ?? null; + if ($productFormFeatureValue) { + $valueCode = is_array($productFormFeatureValue) ? ($productFormFeatureValue['#'] ?? null) : $productFormFeatureValue; if ($valueCode) { $typeCode = $feature->getProductFormFeatureType() ? $feature->getProductFormFeatureType()->getCode() : null; - // If Type is 09 (E-publication accessibility detail), use CodeList 196 - if ($typeCode === '09') { + // If Type is 09 (E-publication accessibility detail), 11 (E-publication accessibility compliance) or 12 (E-publication accessibility compliance code), use CodeList 196 + if (in_array($typeCode, ['09', '11', '12'])) { $feature->setProductFormFeatureValue(CodeList196::resolve($valueCode, $this->language)); } else { $feature->setProductFormFeatureValue(CodeList98::resolve($valueCode, $this->language)); From 28298a9331c6804045d2ecd8a768d721672535ed Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Fri, 23 Jan 2026 13:47:15 +0100 Subject: [PATCH 11/18] add website relation to contributor --- src/Product/Contributor.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Product/Contributor.php b/src/Product/Contributor.php index ec0bbd9..f781340 100644 --- a/src/Product/Contributor.php +++ b/src/Product/Contributor.php @@ -8,7 +8,7 @@ class Contributor { - private const CODE_AUTHOR = 'A01'; + private const CODE_AUTHOR = 'A01'; /** * SequenceNumber @@ -17,6 +17,13 @@ class Contributor */ protected $SequenceNumber; + /** + * Website + * + * @var Website + */ + protected $Website; + /** * ContributorRole * @@ -208,4 +215,13 @@ public function isAuthor() return $this->ContributorRole->getCode() === self::CODE_AUTHOR; } + public function getWebsite(): ?Website + { + return $this->Website; + } + + public function setWebsite(?Website $Website): void + { + $this->Website = $Website; + } } From 44c037b6b606ef263217b196f6b654614b32fd90 Mon Sep 17 00:00:00 2001 From: Alex Schwarz Date: Wed, 4 Feb 2026 09:50:28 +0100 Subject: [PATCH 12/18] use Date type instead of string --- src/CodeList/CodeList196.php | 364 +++++++++++++++++++++++------------ src/Product/PriceDate.php | 27 +-- 2 files changed, 249 insertions(+), 142 deletions(-) diff --git a/src/CodeList/CodeList196.php b/src/CodeList/CodeList196.php index 38f5958..2ae53b5 100644 --- a/src/CodeList/CodeList196.php +++ b/src/CodeList/CodeList196.php @@ -5,7 +5,7 @@ use Ribal\Onix\CodeList\CodeListInterface; /** - * ONIX Code List 196 + * ONIX Code List 196 (Issue 72) * * Used with * @@ -25,30 +25,63 @@ class CodeList196 extends CodeList implements CodeListInterface '01' => 'LIA Compliance Scheme', '02' => 'EPUB Accessibility Specification 1.0 A', '03' => 'EPUB Accessibility Specification 1.0 AA', - '05' => 'PDF/UA', - '08' => 'Unknown accessibility', // NEW in Issue 70 - '09' => 'Inaccessible', - '10' => 'No reading system accessibility options disabled (except)', + '04' => 'EPUB Accessibility Specification 1.1', + '05' => 'PDF/UA-1', + '06' => 'PDF/UA-2', + '08' => 'Unknown accessibility', + '09' => 'Inaccessible, or known limited accessibility', + '10' => 'No reading system accessibility options actively disabled (except)', '11' => 'Table of contents navigation', '12' => 'Index navigation', - '13' => 'Reading order', - '14' => 'Short alternative descriptions', - '15' => 'Full alternative descriptions', - '16' => 'Visualised data also available as non-graphical data', - '17' => 'Accessible math content', - '18' => 'Accessible chem content', + '13' => 'Single logical reading order', + '14' => 'Short alternative textual descriptions', + '15' => 'Full alternative textual descriptions', + '16' => 'Visualized data also available as non-graphical data', + '17' => 'Accessible math content as MathML', + '18' => 'Accessible chemistry content as ChemML', '19' => 'Print-equivalent page numbering', - '20' => 'Synchronised pre-recorded audio', + '20' => 'Synchronized pre-recorded audio', '21' => 'Text-to-speech hinting provided', '22' => 'Language tagging provided', - '23' => 'Accessible interactive elements', // NEW in Issue 65 '24' => 'Dyslexia readability', - '25' => 'Use of color', - '26' => 'Use of contrast', - '27' => 'Accessibility certification', // NEW in Issue 68 + '25' => 'Use of color is not sole means of conveying information', + '26' => 'Use of high contrast between text and background color', + '27' => 'Use of high contrast between foreground and background audio', + '28' => 'Full alternative audio descriptions', + '29' => 'Next / Previous structural navigation', + '30' => 'ARIA roles provided', + '31' => 'Accessible controls provided', + '32' => 'Landmark navigation', + '34' => 'Accessible chemistry content (as MathML)', + '35' => 'Accessible math content (as LaTeX)', + '36' => 'Appearance of all textual content can be modified', + '37' => 'Use of ultra-high contrast between text foreground and background', + '38' => 'Unusual words or abbreviations explained', + '39' => 'Supplementary material to an audiobook is accessible', + '40' => 'Link purposes clear', + '41' => 'Page list navigation', + '51' => 'All non-decorative content supports reading via pre-recorded audio', + '52' => 'All non-decorative content supports reading without sight', + '53' => 'Described math content', + '54' => 'Accessible chemistry content (as LaTeX)', + '75' => 'EAA exception 1 – Micro-enterprises', + '76' => 'EAA exception 2 – Disproportionate burden', + '77' => 'EAA exception 3 – Fundamental alteration', + '80' => 'WCAG v2.0', + '81' => 'WCAG v2.1', + '82' => 'WCAG v2.2', + '84' => 'WCAG level A', + '85' => 'WCAG level AA', + '86' => 'WCAG level AAA', + '88' => 'Certifier credentialled by (name)', + '89' => 'Certifier credentialled by (URL)', + '90' => 'Compliance certification by (name)', + '91' => 'Latest accessibility assessment date', + '92' => 'Accessibility addendum', + '93' => 'Compliance certification by (URL)', '94' => 'Compliance web page for detailed accessibility information', - '95' => "Trusted intermediary's web page for detailed accessibility information", - '96' => "Publisher's web page for detailed accessibility information", + '95' => 'Trusted intermediary’s web page for detailed accessibility information', + '96' => 'Publisher’s web page for detailed accessibility information', '97' => 'Compatibility tested', '98' => 'Trusted Intermediary contact', '99' => 'Publisher contact for further accessibility information', @@ -62,37 +95,68 @@ class CodeList196 extends CodeList implements CodeListInterface * @see https://ns.editeur.org/onix/de/196 */ protected static $de = [ - '00' => 'Zugänglichkeit-Zusammenfassung', - '01' => 'LIA-Konformitätsplan', - '02' => 'EPUB Accessibility Specification 1.0 A', - '03' => 'EPUB Accessibility Specification 1.0 AA', - '05' => 'PDF/UA', - '08' => 'Unbekannte Zugänglichkeit', - '09' => 'Nicht zugänglich', - '10' => 'Keine Lesegerät-Zugänglichkeitsoptionen deaktiviert (außer)', - '11' => 'Inhaltsverzeichnis-Navigation', - '12' => 'Index-Navigation', - '13' => 'Lesereihenfolge', - '14' => 'Kurze Alternativbeschreibungen', - '15' => 'Vollständige Alternativbeschreibungen', - '16' => 'Visualisierte Daten auch als nicht-graphische Daten verfügbar', - '17' => 'Zugänglicher Mathematikinhalt', - '18' => 'Zugänglicher Chemieinhalt', - '19' => 'Druckäquivalente Seitennummerierung', - '20' => 'Synchronisiertes vorab aufgenommenes Audio', - '21' => 'Text-to-Speech-Hinweise bereitgestellt', - '22' => 'Sprachkennzeichnung bereitgestellt', - '23' => 'Zugängliche interaktive Elemente', - '24' => 'Legbarkeit für Menschen mit Dyslexie', - '25' => 'Verwendung von Farben', - '26' => 'Verwendung von Kontrast', - '27' => 'Zugänglichkeits-Zertifizierung', - '94' => 'Webseite für Konformität mit detaillierten Zugänglichkeitsinformationen', - '95' => 'Webseite eines vertrauenswürdigen Vermittlers mit detaillierten Zugänglichkeitsinformationen', - '96' => 'Webseite des Verlags mit detaillierten Zugänglichkeitsinformationen', - '97' => 'Kompatibilität getestet', - '98' => 'Kontakt des vertrauenswürdigen Vermittlers', - '99' => 'Verlagskontakt für weitere Zugänglichkeitsinformationen', + '00' => 'Barrierefreiheit zusammengefasst', + '01' => 'entspricht den Vorgaben der LIA Konformitätserklärung', + '02' => 'entspricht den Vorgaben der EPUB Accessibility Specification 1.0 A', + '03' => 'entspricht den Vorgaben der EPUB Accessibility Specification 1.0 AA', + '04' => 'entspricht den Vorgaben der EPUB Accessibility Specification 1.1', + '05' => 'entspricht den Vorgaben der PDF / UA 1', + '06' => 'entspricht den Vorgaben der PDF / UA 2', + '08' => 'keine Information zur Barrierefreiheit bekannt', + '09' => 'nicht oder eingeschränkt barrierefrei', + '10' => 'keine Vorlesefunktionen des Lesesystems deaktiviert (bis auf)', + '11' => 'navigierbares Inhaltsverzeichnis', + '12' => 'navigierbarer Index', + '13' => 'logische Lesereihenfolge eingehalten', + '14' => 'kurze Alternativtexte (z.B für Abbildungen) vorhanden', + '15' => 'ausführliche Alternativtexte (z.B für Abbildungen) vorhanden', + '16' => 'Datenbasis von Grafiken in nicht graphischer Form verfügbar', + '17' => 'mathematische Inhalte in MathML', + '18' => 'chemische Inhalte in ChemML', + '19' => 'Seitennummerierung folgt dem gedruckten Werk', + '20' => 'mit dem Text synchronisierte Tonspur vorhanden', + '21' => 'Text-to-Speech-Optimierung vorhanden', + '22' => 'Sprachkennzeichnung vorhanden', + '24' => 'verbesserte Lesbarkeit für Leser mit Lese- Rechtschreibschwäche', + '25' => 'Inhalt auch ohne Farbwahrnehmung verständlich dargestellt', + '26' => 'hoher Kontrast zwischen Text und Hintergrund', + '27' => 'hoher Kontrast zwischen Vorder- und Hintergrundaudio', + '28' => 'alle Beschreibungen auch als Audioaufzeichnung', + '29' => 'Navigation über vor-/zurück-Elemente', + '30' => 'ARIA-Rollen vorhanden', + '31' => 'barrierefreie Steuerelemente vorhanden', + '32' => 'Landmark-Navigation vorhanden', + '34' => 'chemische Inhalte in MathML', + '35' => 'mathematische Inhalte in LaTeX', + '36' => 'alle Texte können angepasst werden', + '37' => 'sehr hoher Kontrast zwischen Text und Hintergrund', + '38' => 'Erklärung besonderer Begriffe oder von Abkürzungen enthalten', + '39' => 'Zusatzmaterial zum Hörbuch ist barrierefrei', + '40' => 'Funktion von Links ist klar erkennbar', + '41' => 'Liste für die Seitennavigation', + '51' => 'alle zum Verständnis notwendigen Inhalte als Audioaufzeichnung', + '52' => 'alle zum Verständnis notwendigen Inhalte über Screenreader zugänglich', + '53' => 'mathematische Inhalte in textueller Form beschrieben', + '54' => 'chemische Inhalte in LaTeX', + '75' => 'Produkt vom BFSG ausgenommen: Hersteller ist Kleinstunternehmen', + '76' => 'Produkt vom BFSG ausgenommen: barrierefreie Adaption stellt unverhältnismäßige Belastung für den Hersteller dar', + '77' => 'Produkt vom BFSG ausgenommen: barrierefreie Adaption verändert Produkt grundlegend', + '80' => 'entspricht den Vorgaben der WCAG v2.0', + '81' => 'entspricht den Vorgaben der WCAG v2.1', + '82' => 'entspricht den Vorgaben der WCAG v2.2', + '84' => 'entspricht den Vorgaben der WCAG Level A', + '85' => 'entspricht den Vorgaben der WCAG Level AA', + '86' => 'entspricht den Vorgaben der WCAG Level AAA', + '90' => 'als barrierefrei zertifiziert durch (Name)', + '91' => 'Datum der letzten Bewertung der Barrierefreiheit', + '92' => 'Barrierefreiheit weiterführende Informationen', + '93' => 'als barrierefrei zertifiziert durch (URL)', + '94' => 'Link zu einer Seite mit weiterführenden Informationen zur Barrierefreiheit', + '95' => 'Link zu einer Seite eines vertrauenswürdigen Mittlers für weiterführende Informationen zur Barrierefreiheit', + '96' => 'Link zu einer Seite des Verlags zu weiterführenden Informationen zur Barrierefreiheit', + '97' => 'Link zu einer Seite zum Nachweis der Vereinbarkeit eines Produktes im Hinblick auf Barrierefreiheit', + '98' => 'E-Mail eines vertrauenswürdigen Mittlers bei Fragen zur Barrierefreiheit', + '99' => 'E-Mail des Verlages bei Fragen zur Barrierefreiheit', ]; /** @@ -107,27 +171,60 @@ class CodeList196 extends CodeList implements CodeListInterface '01' => 'Esquema de conformidad LIA', '02' => 'Especificación de accesibilidad EPUB 1.0 A', '03' => 'Especificación de accesibilidad EPUB 1.0 AA', - '05' => 'PDF/UA', + '04' => 'Accesibilidad EPUB 1.1', + '05' => 'PDF/UA-1', + '06' => 'PDF/UA-2', '08' => 'Accesibilidad desconocida', - '09' => 'Inaccesible', - '10' => 'No está desactivada ninguna opción de accesibilidad al sistema de lectura (Con excepciones)', + '09' => 'Inaccesible o se sabe que es de accesibilidad limitada', + '10' => 'No está activamente desactivada ninguna opción de accesibilidad al sistema de lectura (Con excepciones)', '11' => 'Navegación en la tabla de contenidos', '12' => 'Índice navegable', - '13' => 'Orden de lectura', - '14' => 'Descripciones alternativas cortas', - '15' => 'Descripciones alternativas completas', + '13' => 'Orden lógico de lectura único', + '14' => 'Descripciones textuales alternativas cortas', + '15' => 'Descripciones textuales alternativas completas', '16' => 'Visualizaciones de datos también disponibles en forma no gráfica', - '17' => 'Contenido matemático accesible', - '18' => 'Contenido de notación química accesible', + '17' => 'Contenido de notación matemática accesible como MathML', + '18' => 'Contenido de notación química accesible como ChemML', '19' => 'Numeración de páginas equivalente a la de la versión impresa', '20' => 'Audio pregrabado sincronizado', - '21' => 'Incluye pistas para la síntesis de voz', + '21' => 'Incluye pistas («hints») para la conversión de texto a voz', '22' => 'Incluye etiquetado de idioma', - '23' => 'Elementos interactivos accesibles', - '24' => 'Legibilidad para personas con dislexia', - '25' => 'Uso del color', - '26' => 'Uso del contraste', - '27' => 'Certificación de accesibilidad', + '24' => 'Legibilidad mejorada para personas con dislexia', + '25' => 'Uso inclusivo del color', + '26' => 'Uso inclusivo de contraste entre color de texto y fondo', + '27' => 'Uso inclusivo del contraste en el volumen de audio', + '28' => 'Descripciones de audio completas', + '29' => 'Navegación estructural «Anterior / Siguiente»', + '30' => 'Incluye roles ARIA', + '31' => 'Incluye controles accesibles', + '32' => 'Navegación por puntos de referencia', + '34' => 'Contenido de notación química accesible (como MathML)', + '35' => 'Contenido de notación matemática accesible (como LaTeX)', + '36' => 'La apariencia de todo el contenido textual se puede modificar', + '37' => 'Uso de un contraste muy alto entre el primer plano del texto y el fondo', + '38' => 'Explicación de palabras o abreviaturas poco usuales', + '39' => 'El material complementario del audiolibro es accesible', + '40' => 'Propósito de los enlaces explícito', + '41' => 'Navegación con lista de páginas', + '51' => 'Todo el contenido «no decorativo» permite la lectura mediante audio pregrabado', + '52' => 'Todo el contenido «no decorativo» admite la lectura sin visión', + '53' => 'Contenido matemático descrito', + '54' => 'Contenido químico accesible (en forma de LaTeX)', + '75' => 'Entra en la exención 1 de la LEA – Microempresas', + '76' => 'Entra en la exención 2 de la LEA – Carga desproporcionada', + '77' => 'Entra en la exención 3 de la LEA – Modificación sustancial', + '80' => 'Cumple WCAG v2.0', + '81' => 'Cumple WCAG v2.1', + '82' => 'Cumple WCAG v2.2', + '84' => 'Cumple WCAG nivel A', + '85' => 'Cumple WCAG nivel AA', + '86' => 'Cumple WCAG nivel AAA', + '88' => 'Certificador acreditado por (nombre)', + '89' => 'Certificador acreditado por (URL)', + '90' => 'Certificación de cumplimiento por (nombre)', + '91' => 'Fecha de la última evaluación de la accesibilidad', + '92' => 'Apéndice de accesibilidad', + '93' => 'Certificación de accesibilidad expedida por', '94' => 'Página web de certificación, con información detallada de accesibilidad', '95' => 'Página web de un intermediario de confianza, con información detallada de accesibilidad', '96' => 'Página web de la editorial, con información detallada de accesibilidad', @@ -144,37 +241,70 @@ class CodeList196 extends CodeList implements CodeListInterface * @see https://ns.editeur.org/onix/it/196 */ protected static $it = [ - '00' => 'Riepilogo accessibilità', - '01' => 'Schema di conformità LIA', - '02' => 'Specifica di accessibilità EPUB 1.0 A', - '03' => 'Specifica di accessibilità EPUB 1.0 AA', - '05' => 'PDF/UA', + '00' => 'Riepilogo sull’accessibilità', + '01' => 'Certificazione LIA', + '02' => 'Specifiche di accessibilità EPUB 1.0 A', + '03' => 'Specifiche di accessibilità EPUB 1.0 AA', + '04' => 'Specifiche di accessibilità EPUB 1.1', + '05' => 'PDF/UA-1', + '06' => 'PDF/UA-2', '08' => 'Accessibilità sconosciuta', - '09' => 'Non accessibile', - '10' => "Nessuna opzione di accessibilità del sistema di lettura disabilitata (eccetto)", - '11' => 'Navigazione nel sommario', - '12' => 'Navigazione nell\'indice', - '13' => 'Ordine di lettura', - '14' => 'Descrizioni alternative brevi', - '15' => 'Descrizioni alternative complete', - '16' => 'Dati visualizzati anche disponibili come dati non grafici', - '17' => 'Contenuto matematico accessibile', - '18' => 'Contenuto chimico accessibile', - '19' => 'Numerazione delle pagine equivalente alla versione stampata', - '20' => 'Audio preregistrato sincronizzato', - '21' => 'Forniti suggerimenti per la sintesi vocale', - '22' => 'Fornita etichettatura linguistica', - '23' => 'Elementi interattivi accessibili', + '09' => 'Non accessibile, o con limiti noti all’accessibilità', + '10' => 'Nessuna funzione di accessibilità del sistema di lettura attivamente disabilitata (con eccezioni)', + '11' => 'Navigazione dell’indice dei contenuti', + '12' => 'Navigazione dell’indice analitico', + '13' => 'Ordine logico di lettura univoco', + '14' => 'Descrizioni testuali alternative brevi', + '15' => 'Descrizioni testuali alternative estese', + '16' => 'Dati visualizzati disponibili anche come dati non grafici', + '17' => 'Contenuto di matematica accessibile in formato MathML', + '18' => 'Contenuto di chimica accessibile in formato ChemML', + '19' => 'Numerazione delle pagine equivalente alla versione a stampa', + '20' => 'Audio sincronizzato pre-registrato', + '21' => 'Funzione di sintesi vocale inclusa', + '22' => 'Funzione di riconoscimento della lingua inclusa', '24' => 'Leggibilità per dislessici', - '25' => 'Utilizzo del colore', - '26' => 'Utilizzo del contrasto', - '27' => 'Certificazione di accessibilità', - '94' => "Pagina web di conformità per informazioni dettagliate sull'accessibilità", - '95' => "Pagina web di un intermediario fidato per informazioni dettagliate sull'accessibilità", - '96' => "Pagina web dell'editore per informazioni dettagliate sull'accessibilità", - '97' => 'Compatibilità testata', - '98' => 'Contatto intermediario fidato', - '99' => "Contatto editore per ulteriori informazioni sull'accessibilità", + '25' => 'L’uso del colore non è l’unico mezzo per veicolare informazioni', + '26' => 'Utilizzo di un elevato contrasto tra il colore del testo e dello sfondo', + '27' => 'Utilizzo di un elevato contrasto tra l’audio in primo piano e di sottofondo', + '28' => 'Descrizioni audio alternative complete', + '29' => 'Navigazione strutturata successiva/precedente', + '30' => 'Ruoli ARIA assegnati', + '31' => 'Controlli accessibili presenti', + '32' => 'Navigazione per punti di riferimento', + '34' => 'Contenuti di chimica accessibili (in formato MathML)', + '35' => 'Contenuti di matematica accessibili (in formato LaTeX)', + '36' => 'L’aspetto di tutto il contenuto testuale può essere modificato', + '37' => 'Utilizzo di contrasto elevatissimo tra il colore del testo in primo piano e lo sfondo', + '38' => 'Spiegazione di parole o abbreviazioni insolite', + '39' => 'Il materiale di supporto all’audiolibro è accessibile', + '40' => 'Lo scopo del link è chiaro', + '41' => 'Navigazione nell’elenco delle pagine', + '51' => 'Tutti i contenuti non decorativi supportano la lettura tramite audio preregistrato', + '52' => 'Tutti i contenuti non decorativi supportano la lettura non visuale', + '53' => 'Descrizione dei contenuti di matematica', + '54' => 'Contenuti di chimica accessibili (in formato LaTeX)', + '75' => 'Atto Europeo sull’Accessibilità – Eccezione 1: microimprese', + '76' => 'Atto Europeo sull’Accessibilità – Eccezione 2: onere sproporzionato', + '77' => 'Atto Europeo sull’Accessibilità – Eccezione 3: modifica sostanziale', + '80' => 'WCAG v2.0', + '81' => 'WCAG v2.1', + '82' => 'WCAG v2.2', + '84' => 'WCAG livello A', + '85' => 'WCAG livello AA', + '86' => 'WCAG livello AAA', + '88' => 'Certificatore accreditato da (nome)', + '89' => 'Certificatore accreditato da (URL)', + '90' => 'Certificazione di conformità di (nome)', + '91' => 'Data dell’ultima valutazione di accessibilità', + '92' => 'Addendum sull’accessibilità', + '93' => 'Certificazione di conformità di (URL)', + '94' => 'Pagina internet con informazioni dettagliate sull’accessibilità', + '95' => 'Pagina internet dell’intermediario accreditato con le informazioni sull’accessibilità', + '96' => 'Pagina internet dell’editore con le informazioni sull’accessibilità', + '97' => 'Esito verifica sulla compatibilità', + '98' => 'Contatto dell’intermediario accreditato', + '99' => 'Contatto dell’editore per ulteriori informazioni sull’accessibilità', ]; /** @@ -186,35 +316,29 @@ class CodeList196 extends CodeList implements CodeListInterface */ protected static $tr = [ '00' => 'Erişilebilirlik özeti', - '01' => 'LIA Uyum Planı', - '02' => 'EPUB Erişilebilirlik Spesifikasyonu 1.0 A', - '03' => 'EPUB Erişilebilirlik Spesifikasyonu 1.0 AA', - '05' => 'PDF/UA', - '08' => 'Bilinmeyen erişilebilirlik', // NEW in Issue 70 - '09' => 'Erişilemez', - '10' => 'Okuma sistemi erişilebilirlik seçenekleri devre dışı bırakılmadı (istisnalar hariç)', - '11' => 'İçindekiler tablosu gezinimi', - '12' => 'İndeks gezinimi', - '13' => 'Okuma sırası', - '14' => 'Kısa alternatif açıklamalar', - '15' => 'Tam alternatif açıklamalar', - '16' => 'Görselleştirilmiş veriler ayrıca grafik olmayan veri olarak da mevcut', - '17' => 'Erişilebilir matematik içeriği', - '18' => 'Erişilebilir kimya içeriği', - '19' => 'Baskı eşdeğeri sayfa numaralandırması', - '20' => 'Senkronize önceden kaydedilmiş ses', - '21' => 'Metin-konuşma ipuçları sağlandı', - '22' => 'Dil etiketleme sağlandı', - '23' => 'Erişilebilir etkileşimli öğeler', // NEW in Issue 65 + '01' => 'LIA Uyumluluk Düzeni', + '02' => 'Erişilebilirlik Spesifikasyonu 1.0 A', + '03' => 'Erişilebilirlik Spesifikasyonu 1.0 AA', + '09' => 'Erişim dışı', + '10' => 'Hiçbir okuyucu sistemi erişilebilirlik seçeneği geçersizkılınmamıştır (istisna)', + '11' => 'İçindekiler tablosu gezintisi', + '12' => 'Dizin gezintisi', + '13' => 'Okuma düzeni', + '14' => 'Kısa alternatif tanımlar', + '15' => 'Tam alternatif tanımlar', + '16' => 'Görselleştirilmiş veri grafik olmayan veri olarak da mevcut', + '17' => 'Erişilebilir matematiksel içerik', + '18' => 'Erişilebilir kimyasal içerik', + '19' => 'Basılı eşdeğeri sayfa numaralandırma', + '20' => 'Senkronize ön kayıtlı işitsel', + '21' => 'Metin okuma desteği var', + '22' => 'Dil etiketleme var', '24' => 'Disleksi okunabilirliği', - '25' => 'Renk kullanımı', - '26' => 'Kontrast kullanımı', - '27' => 'Erişilebilirlik sertifikasyonu', // NEW in Issue 68 - '94' => 'Detaylı erişilebilirlik bilgileri için uyum web sayfası', - '95' => 'Detaylı erişilebilirlik bilgileri için güvenilir aracı web sayfası', - '96' => 'Detaylı erişilebilirlik bilgileri için yayıncı web sayfası', + '94' => 'Ayrıntılı erişilebilirlik bilgileri için uygunluk web sayfası', + '95' => 'Ayrıntılı erişilebilirlik bilgileri için güvenilir aracı kuruluşun web sayfası', + '96' => 'Ayrıntılı erişilebilirlik bilgileri için yayımcının web sayfası', '97' => 'Uyumluluk test edildi', - '98' => 'Güvenilir aracı iletişim', - '99' => 'Daha fazla erişilebilirlik bilgisi için yayıncı iletişim', + '98' => 'Güvenilir aracı ilişki', + '99' => 'Daha fazla erişilebilirlik bilgisi için yayımcı ilişkisi', ]; } \ No newline at end of file diff --git a/src/Product/PriceDate.php b/src/Product/PriceDate.php index 9473d46..1244eb2 100644 --- a/src/Product/PriceDate.php +++ b/src/Product/PriceDate.php @@ -4,6 +4,7 @@ use Ribal\Onix\CodeList\CodeList; use Ribal\Onix\CodeList\CodeList173; +use Ribal\Onix\Date; class PriceDate { @@ -15,41 +16,23 @@ class PriceDate protected CodeList $PriceDateRole; /** - * @var string|null YYYYMMDD or YYYY + * @var Date|null */ - protected ?string $Date = null; - - /** - * @var string|null ONIX dateformat code (attribute of b306) - */ - protected ?string $DateFormat = null; + protected ?Date $Date = null; /** * Set Date (b306) */ - public function setDate(string $date): void + public function setDate(Date $date): void { $this->Date = $date; } - public function getDate(): ?string + public function getDate(): ?Date { return $this->Date; } - /** - * Set DateFormat (b306@dateformat) - */ - public function setDateFormat(?string $format): void - { - $this->DateFormat = $format; - } - - public function getDateFormat(): ?string - { - return $this->DateFormat; - } - /** * Set PriceDateRole * From 03a8070ceefad23fa63de01c6fde3045f6fc3386 Mon Sep 17 00:00:00 2001 From: Axel Krysztofiak Date: Thu, 12 Feb 2026 13:45:14 +0100 Subject: [PATCH 13/18] multiple websites in publishers data --- src/Product/Publisher.php | 33 +++++++++++++++++++++++++++------ src/Product/Website.php | 24 +++++++++++++++++++++--- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/Product/Publisher.php b/src/Product/Publisher.php index 91f590b..3b83035 100644 --- a/src/Product/Publisher.php +++ b/src/Product/Publisher.php @@ -29,11 +29,11 @@ class Publisher protected $PublisherName; /** - * Website + * Publisher Websites * - * @var Website + * @var Website[] */ - protected $Website; + protected $Website= []; /** * Set PublishingRole @@ -89,9 +89,20 @@ public function setPublisherName(string $PublisherName) * @param Website $Website * @return void */ - public function setWebsite(Website $Website) + public function addWebsite(Website $Website) { - $this->Website = $Website; + $this->Website[] = $Website; + } + + /** + * Removes a Website from collection + * + * @param Website $website + * @return void + */ + public function removeWebsite(Website $website) + { + } /** @@ -127,13 +138,23 @@ public function getPublisherName() /** * Get Website * - * @return Website + * @return array */ public function getWebsite() { return $this->Website; } + /** + * Get Website + * + * @return array + */ + public function getWebsites() + { + return $this->Website; + } + /** * Get PublisherIdentifier * diff --git a/src/Product/Website.php b/src/Product/Website.php index eaddd90..1d3f91b 100644 --- a/src/Product/Website.php +++ b/src/Product/Website.php @@ -12,14 +12,32 @@ class Website * * @var CodeList */ - protected $WebsiteRole; + protected $WebsiteRole = ''; /** * WebsiteLink * * @var string */ - protected $WebsiteLink; + protected $WebsiteLink = ''; + + /** + * WebsiteDescription + * + * @var string + */ + protected $WebsiteDescription = ''; + + public function getWebsiteDescription(): string + { + return $this->WebsiteDescription; + } + + public function setWebsiteDescription(string $WebsiteDescription): Website + { + $this->WebsiteDescription = $WebsiteDescription; + return $this; + } /** * Set WebsiteRole @@ -63,4 +81,4 @@ public function getWebsiteLink() return $this->WebsiteLink; } -} \ No newline at end of file +} From d61f9a5b3e03238951a3750ae84c03896b0af66c Mon Sep 17 00:00:00 2001 From: Axel Krysztofiak Date: Thu, 12 Feb 2026 17:04:27 +0100 Subject: [PATCH 14/18] add missing contributor websites add missing revised by entries --- src/Product/Contributor.php | 61 +++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/src/Product/Contributor.php b/src/Product/Contributor.php index f781340..82e1990 100644 --- a/src/Product/Contributor.php +++ b/src/Product/Contributor.php @@ -9,6 +9,8 @@ class Contributor { private const CODE_AUTHOR = 'A01'; + private const CODE_EDITOR = 'B01'; + private const CODE_REVISOR = 'B02'; /** * SequenceNumber @@ -17,13 +19,6 @@ class Contributor */ protected $SequenceNumber; - /** - * Website - * - * @var Website - */ - protected $Website; - /** * ContributorRole * @@ -59,6 +54,15 @@ class Contributor */ protected $KeyNames; + + + /** + * Publisher Websites + * + * @var Website[] + */ + protected $Website = []; + /** * Set SequenceNumber * @@ -212,16 +216,53 @@ public function getLastname() */ public function isAuthor() { + return match ($this->ContributorRole->getCode()) { + self::CODE_AUTHOR, self::CODE_EDITOR, self::CODE_REVISOR => true, + default => false, + }; return $this->ContributorRole->getCode() === self::CODE_AUTHOR; } - public function getWebsite(): ?Website + /** + * Set Website + * + * @param Website $Website + * @return void + */ + public function addWebsite(Website $Website) + { + $this->Website[] = $Website; + } + + /** + * Removes a Website from collection + * + * @param Website $website + * @return void + */ + public function removeWebsite(Website $website) + { + + } + + /** + * Get Website + * + * @return array + */ + public function getWebsite() { return $this->Website; } - public function setWebsite(?Website $Website): void + /** + * Get Website + * + * @return array + */ + public function getWebsites() { - $this->Website = $Website; + return $this->Website; } + } From 22653ca7b0cabb28fa7fa1e6d94f28d4b53fb3bf Mon Sep 17 00:00:00 2001 From: Axel Krysztofiak Date: Fri, 13 Feb 2026 11:22:47 +0100 Subject: [PATCH 15/18] add instructional resource links --- src/Product/CollateralDetail.php | 12 ++++ src/Product/ResourceFeature.php | 65 +++++++++++++++++ src/Product/SupportingResource.php | 108 ++++++++++++++++++++++++++--- 3 files changed, 176 insertions(+), 9 deletions(-) create mode 100644 src/Product/ResourceFeature.php diff --git a/src/Product/CollateralDetail.php b/src/Product/CollateralDetail.php index c6c5473..e45e26a 100644 --- a/src/Product/CollateralDetail.php +++ b/src/Product/CollateralDetail.php @@ -179,4 +179,16 @@ public function getImageResources() }); } + /** + * Get the front cover resource, if set + * + * @return SupportingResource[]|array + */ + public function getInstructionalResources() + { + return array_filter($this->SupportingResource, function($resource) { + return $resource->isInstructional(); + }); + } + } diff --git a/src/Product/ResourceFeature.php b/src/Product/ResourceFeature.php new file mode 100644 index 0000000..d811692 --- /dev/null +++ b/src/Product/ResourceFeature.php @@ -0,0 +1,65 @@ +FeatureNote; + } + + /** + * @param mixed $FeatureNote + * @return ResourceFeature + */ + public function setFeatureNote($FeatureNote) + { + $this->FeatureNote = $FeatureNote; + return $this; + } + + /** + * @return mixed + */ + public function getFeatureValue() + { + return $this->FeatureValue; + } + + /** + * @param mixed $FeatureValue + * @return ResourceFeature + */ + public function setFeatureValue($FeatureValue) + { + $this->FeatureValue = $FeatureValue; + return $this; + } + + /** + * @return CodeList160 + */ + public function getResourceFeatureType() + { + return $this->ResourceFeatureType; + } + + /** + * @param CodeList160 $ResourceFeatureType + * @return ResourceFeature + */ + public function setResourceFeatureType(CodeList160 $ResourceFeatureType) + { + $this->ResourceFeatureType = $ResourceFeatureType; + return $this; + } +} diff --git a/src/Product/SupportingResource.php b/src/Product/SupportingResource.php index cc6c58b..8bf05b4 100644 --- a/src/Product/SupportingResource.php +++ b/src/Product/SupportingResource.php @@ -5,15 +5,19 @@ use Ribal\Onix\CodeList\CodeList154; use Ribal\Onix\CodeList\CodeList158; use Ribal\Onix\CodeList\CodeList159; +use Ribal\Onix\CodeList\CodeList160; class SupportingResource { - private const TYPE_FRONTCOVER = '01'; - private const TYPE_BACKCOVER = '02'; - - private const MODE_IMAGE = '03'; - + private const TYPE_FRONTCOVER = '01'; + private const TYPE_BACKCOVER = '02'; + private const TYPE_INSTRUCTIONAL = '39'; + + private const MODE_IMAGE = '03'; + + private const TYPE_FEATURE_LINKTEXT = '02'; + private const TYPE_COPYRIGHT_NOTE = '03'; /** * ResourceContentType @@ -43,6 +47,55 @@ class SupportingResource */ protected $ResourceVersion; + + /** + * ResourceFeature + * + * @var ResourceFeature[] + */ + protected array $ResourceFeature = []; + + /** + * Add a new ResourceFeature + * + * @param ResourceFeature $ResourceFeature + * @return void + */ + public function addResourceFeature(ResourceFeature $ResourceFeature) + { + $this->ResourceFeature[] = $ResourceFeature; + } + + /** + * Remove ResourceFeature + * + * @param ResourceFeature $ResourceFeature + * @return void + */ + public function removeResourceFeature(ResourceFeature $ResourceFeature) + { + } + + /** + * Get ResourceFeatures + * + * @return array + */ + public function getResourceFeature() + { + return $this->ResourceFeature; + } + + /** + * Get ResourceFeatures + * + * @return array + */ + public function getResourceFeatures() + { + return $this->ResourceFeature; + } + /** * Set ResourceContentType * @@ -156,7 +209,17 @@ public function isImage() { return $this->ResourceMode->getCode() === self::MODE_IMAGE; } - + + /** + * Check, if the Resource is a link to additional material + * + * @return boolean + */ + public function isInstructional() + { + return $this->ResourceContentType->getCode() === self::TYPE_INSTRUCTIONAL; + } + /** * Get the link to a file or resource * @@ -164,9 +227,36 @@ public function isImage() */ public function getLink() { - if ($this->ResourceVersion && $this->ResourceVersion->hasLink()) { - return $this->ResourceVersion->getResourceLink(); - } + if ($this->ResourceVersion && $this->ResourceVersion->hasLink()) { + return $this->ResourceVersion->getResourceLink(); + } + } + + /** + * Get the link description + * + * @return string + */ + public function getLinkDescription() + { + $links = array_filter($this->ResourceFeature, function ($resourceFeature) { + return $resourceFeature->getResourceFeatureType()->getCode() === self::TYPE_FEATURE_LINKTEXT; + }); + return $links[0]?->getFeatureNote(); + } + + /** + * Get the link copyright note + * + * @return string + */ + public function getCopyrightNote() + { + $links = array_filter($this->ResourceFeature, function ($resourceFeature) { + return $resourceFeature->getResourceFeatureType()->getCode() === self::TYPE_COPYRIGHT_NOTE; + }); + + return $links[0]?->getFeatureNote(); } } From 34870b7bba067f8f9028fb57161562808e97a490 Mon Sep 17 00:00:00 2001 From: Axel Krysztofiak Date: Fri, 13 Feb 2026 14:16:21 +0100 Subject: [PATCH 16/18] add trailer links --- src/Product/CollateralDetail.php | 12 ++++++++++++ src/Product/SupportingResource.php | 11 ++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Product/CollateralDetail.php b/src/Product/CollateralDetail.php index e45e26a..9f35b77 100644 --- a/src/Product/CollateralDetail.php +++ b/src/Product/CollateralDetail.php @@ -191,4 +191,16 @@ public function getInstructionalResources() }); } + /** + * Get the front cover resource, if set + * + * @return SupportingResource[]|array + */ + public function getTrailerResources() + { + return array_filter($this->SupportingResource, function($resource) { + return $resource->isTrailer(); + }); + } + } diff --git a/src/Product/SupportingResource.php b/src/Product/SupportingResource.php index 8bf05b4..3fde911 100644 --- a/src/Product/SupportingResource.php +++ b/src/Product/SupportingResource.php @@ -5,7 +5,6 @@ use Ribal\Onix\CodeList\CodeList154; use Ribal\Onix\CodeList\CodeList158; use Ribal\Onix\CodeList\CodeList159; -use Ribal\Onix\CodeList\CodeList160; class SupportingResource { @@ -13,6 +12,7 @@ class SupportingResource private const TYPE_FRONTCOVER = '01'; private const TYPE_BACKCOVER = '02'; private const TYPE_INSTRUCTIONAL = '39'; + private const TYPE_TRAILER = '26'; private const MODE_IMAGE = '03'; @@ -220,6 +220,15 @@ public function isInstructional() return $this->ResourceContentType->getCode() === self::TYPE_INSTRUCTIONAL; } + /** + * Check, if the Resource is a trailer link + * + * @return boolean + */ public function isTrailer() + { + return $this->ResourceContentType->getCode() === self::TYPE_TRAILER; + } + /** * Get the link to a file or resource * From 2b09734c4f06986f586302373b6f62601f9cb237 Mon Sep 17 00:00:00 2001 From: Axel Krysztofiak Date: Fri, 13 Feb 2026 16:29:42 +0100 Subject: [PATCH 17/18] bugfix: array key 0 does not exist --- src/Product/SupportingResource.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Product/SupportingResource.php b/src/Product/SupportingResource.php index 3fde911..8925de7 100644 --- a/src/Product/SupportingResource.php +++ b/src/Product/SupportingResource.php @@ -248,9 +248,12 @@ public function getLink() */ public function getLinkDescription() { - $links = array_filter($this->ResourceFeature, function ($resourceFeature) { + $links = array_values(array_filter($this->ResourceFeature, function ($resourceFeature) { return $resourceFeature->getResourceFeatureType()->getCode() === self::TYPE_FEATURE_LINKTEXT; - }); + })); + if(!isset($links[0])) { + return ''; + } return $links[0]?->getFeatureNote(); } @@ -261,10 +264,12 @@ public function getLinkDescription() */ public function getCopyrightNote() { - $links = array_filter($this->ResourceFeature, function ($resourceFeature) { + $links = array_values(array_filter($this->ResourceFeature, function ($resourceFeature) { return $resourceFeature->getResourceFeatureType()->getCode() === self::TYPE_COPYRIGHT_NOTE; - }); - + })); + if(!isset($links[0])) { + return ''; + } return $links[0]?->getFeatureNote(); } From b654fed484e187ebdbd595df034f7bdbd32e3c9f Mon Sep 17 00:00:00 2001 From: Axel Krysztofiak Date: Tue, 17 Feb 2026 16:07:19 +0100 Subject: [PATCH 18/18] Ability to find author image in product data --- src/Product/SupportingResource.php | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Product/SupportingResource.php b/src/Product/SupportingResource.php index 8925de7..fac00b1 100644 --- a/src/Product/SupportingResource.php +++ b/src/Product/SupportingResource.php @@ -11,8 +11,9 @@ class SupportingResource private const TYPE_FRONTCOVER = '01'; private const TYPE_BACKCOVER = '02'; - private const TYPE_INSTRUCTIONAL = '39'; + private const TYPE_AUTHOR = '04'; private const TYPE_TRAILER = '26'; + private const TYPE_INSTRUCTIONAL = '39'; private const MODE_IMAGE = '03'; @@ -199,7 +200,17 @@ public function isBackCover() { return $this->ResourceContentType->getCode() == self::TYPE_BACKCOVER; } - + + /** + * Check, if the Resource is a book front cover + * + * @return boolean + */ + public function isAuthorImage() + { + return $this->ResourceContentType->getCode() == self::TYPE_AUTHOR; + } + /** * Check, if the Resource is an image * @@ -224,7 +235,8 @@ public function isInstructional() * Check, if the Resource is a trailer link * * @return boolean - */ public function isTrailer() + */ + public function isTrailer() { return $this->ResourceContentType->getCode() === self::TYPE_TRAILER; } @@ -251,7 +263,7 @@ public function getLinkDescription() $links = array_values(array_filter($this->ResourceFeature, function ($resourceFeature) { return $resourceFeature->getResourceFeatureType()->getCode() === self::TYPE_FEATURE_LINKTEXT; })); - if(!isset($links[0])) { + if (!isset($links[0])) { return ''; } return $links[0]?->getFeatureNote(); @@ -267,7 +279,7 @@ public function getCopyrightNote() $links = array_values(array_filter($this->ResourceFeature, function ($resourceFeature) { return $resourceFeature->getResourceFeatureType()->getCode() === self::TYPE_COPYRIGHT_NOTE; })); - if(!isset($links[0])) { + if (!isset($links[0])) { return ''; } return $links[0]?->getFeatureNote();