From 33b5bdc2231303cd37b638d057e0dc78c86f9403 Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Sun, 8 Feb 2026 15:37:39 +0000 Subject: [PATCH 01/12] CI: use PHP 8.2 default, add PHP 8.2-8.5 test matrix, use @master workflows --- .github/.kodiak.toml | 10 --------- .github/workflows/codesniffer.yml | 7 ++++-- .github/workflows/coverage.yml | 17 ++++++--------- .github/workflows/phpstan.yml | 9 +++++--- .github/workflows/tests.yml | 36 ++++++++++++++++++++++++------- 5 files changed, 45 insertions(+), 34 deletions(-) delete mode 100644 .github/.kodiak.toml diff --git a/.github/.kodiak.toml b/.github/.kodiak.toml deleted file mode 100644 index 60c34b6..0000000 --- a/.github/.kodiak.toml +++ /dev/null @@ -1,10 +0,0 @@ -version = 1 - -[merge] -automerge_label = "automerge" -blacklist_title_regex = "^WIP.*" -blacklist_labels = ["WIP"] -method = "rebase" -delete_branch_on_merge = true -notify_on_conflict = true -optimistic_updates = false diff --git a/.github/workflows/codesniffer.yml b/.github/workflows/codesniffer.yml index 558132a..a58ac4f 100644 --- a/.github/workflows/codesniffer.yml +++ b/.github/workflows/codesniffer.yml @@ -2,9 +2,10 @@ name: "Codesniffer" on: pull_request: + workflow_dispatch: push: - branches: [ "*" ] + branches: ["*"] schedule: - cron: "0 8 * * 1" @@ -12,4 +13,6 @@ on: jobs: codesniffer: name: "Codesniffer" - uses: contributte/.github/.github/workflows/codesniffer.yml@v1 + uses: contributte/.github/.github/workflows/codesniffer.yml@master + with: + php: "8.2" diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 3e622d2..fac01f8 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -2,22 +2,17 @@ name: "Coverage" on: pull_request: + workflow_dispatch: push: - branches: [ "*" ] + branches: ["*"] schedule: - - cron: "0 8 * * 1" + - cron: "0 9 * * 1" jobs: - test81: + coverage: name: "Nette Tester" - uses: contributte/.github/.github/workflows/nette-tester-coverage.yml@v1 + uses: contributte/.github/.github/workflows/nette-tester-coverage-v2.yml@master with: - php: "8.1" - - test80: - name: "Nette Tester" - uses: contributte/.github/.github/workflows/nette-tester-coverage.yml@v1 - with: - php: "8.0" + php: "8.2" diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index fd9fa09..13ceb07 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -2,14 +2,17 @@ name: "Phpstan" on: pull_request: + workflow_dispatch: push: - branches: [ "*" ] + branches: ["*"] schedule: - - cron: "0 8 * * 1" + - cron: "0 10 * * 1" jobs: phpstan: name: "Phpstan" - uses: contributte/.github/.github/workflows/phpstan.yml@v1 + uses: contributte/.github/.github/workflows/phpstan.yml@master + with: + php: "8.2" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e948380..ef17693 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,22 +2,42 @@ name: "Nette Tester" on: pull_request: + workflow_dispatch: push: - branches: [ "*" ] + branches: ["*"] schedule: - - cron: "0 8 * * 1" + - cron: "0 10 * * 1" jobs: - test81: + test85: name: "Nette Tester" - uses: contributte/.github/.github/workflows/nette-tester.yml@v1 + uses: contributte/.github/.github/workflows/nette-tester.yml@master with: - php: "8.1" + php: "8.5" - test80: + test84: name: "Nette Tester" - uses: contributte/.github/.github/workflows/nette-tester.yml@v1 + uses: contributte/.github/.github/workflows/nette-tester.yml@master with: - php: "8.0" + php: "8.4" + + test83: + name: "Nette Tester" + uses: contributte/.github/.github/workflows/nette-tester.yml@master + with: + php: "8.3" + + test82: + name: "Nette Tester" + uses: contributte/.github/.github/workflows/nette-tester.yml@master + with: + php: "8.2" + + testlower: + name: "Nette Tester" + uses: contributte/.github/.github/workflows/nette-tester.yml@master + with: + php: "8.2" + composer: "composer update --no-interaction --no-progress --prefer-dist --prefer-stable --prefer-lowest" From b3b4246f3174943929a6c40dbe2fba0bf74e31ae Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Sun, 8 Feb 2026 15:38:33 +0000 Subject: [PATCH 02/12] Tests: convert from Codeception to Nette Tester, add bootstrap --- codeception.yml | 26 -------------------------- tests/.coveralls.yml | 4 ---- tests/Cases/CompanyTest.phpt | 21 +++++++++++++++++++++ tests/Cases/TemplateParaisoTest.phpt | 14 ++++++++++++++ tests/Cases/TemplateTuroisoTest.phpt | 14 ++++++++++++++ tests/Unit.suite.yml | 12 ------------ tests/Unit/CompanyTest.php | 22 ---------------------- tests/Unit/TemplateParaisoTest.php | 16 ---------------- tests/Unit/TemplateTuroisoTest.php | 16 ---------------- tests/_data/.gitkeep | 0 tests/_output/.gitignore | 2 -- tests/_support/Helper/Unit.php | 11 ----------- tests/_support/UnitTester.php | 26 -------------------------- tests/_support/_generated/.gitignore | 2 -- tests/bootstrap.php | 10 ++++++++++ 15 files changed, 59 insertions(+), 137 deletions(-) delete mode 100644 codeception.yml delete mode 100644 tests/.coveralls.yml create mode 100644 tests/Cases/CompanyTest.phpt create mode 100644 tests/Cases/TemplateParaisoTest.phpt create mode 100644 tests/Cases/TemplateTuroisoTest.phpt delete mode 100644 tests/Unit.suite.yml delete mode 100644 tests/Unit/CompanyTest.php delete mode 100644 tests/Unit/TemplateParaisoTest.php delete mode 100644 tests/Unit/TemplateTuroisoTest.php delete mode 100644 tests/_data/.gitkeep delete mode 100644 tests/_output/.gitignore delete mode 100644 tests/_support/Helper/Unit.php delete mode 100644 tests/_support/UnitTester.php delete mode 100644 tests/_support/_generated/.gitignore create mode 100644 tests/bootstrap.php diff --git a/codeception.yml b/codeception.yml deleted file mode 100644 index cc9ebe2..0000000 --- a/codeception.yml +++ /dev/null @@ -1,26 +0,0 @@ -actor: Tester - -paths: - # where the tests stored - tests: tests - - # directory for fixture data - data: tests/_data - - # directory for support code - support: tests/_support - - # directory for output - output: tests/_output - -extensions: - enabled: - - Codeception\Extension\RunFailed - -settings: - log: true - -coverage: - enabled: true - include: - - src/** diff --git a/tests/.coveralls.yml b/tests/.coveralls.yml deleted file mode 100644 index 740380b..0000000 --- a/tests/.coveralls.yml +++ /dev/null @@ -1,4 +0,0 @@ -# for php-coveralls -service_name: github-actions -coverage_clover: tests/_output/coverage.xml -json_path: tests/_output/coverage.json diff --git a/tests/Cases/CompanyTest.phpt b/tests/Cases/CompanyTest.phpt new file mode 100644 index 0000000..9f5c61b --- /dev/null +++ b/tests/Cases/CompanyTest.phpt @@ -0,0 +1,21 @@ +getName()); + Assert::same('town', $company->getTown()); + Assert::same('address', $company->getAddress()); + Assert::same('zip', $company->getZip()); + Assert::same('country', $company->getCountry()); + Assert::same('vatNumber', $company->getVatNumber()); + Assert::same('id', $company->getId()); +}); diff --git a/tests/Cases/TemplateParaisoTest.phpt b/tests/Cases/TemplateParaisoTest.phpt new file mode 100644 index 0000000..2fc208e --- /dev/null +++ b/tests/Cases/TemplateParaisoTest.phpt @@ -0,0 +1,14 @@ +renderToPdf(PreviewFactory::createOrder()); + (new ParaisoTemplate())->renderToSvg(PreviewFactory::createOrder()); +}); diff --git a/tests/Cases/TemplateTuroisoTest.phpt b/tests/Cases/TemplateTuroisoTest.phpt new file mode 100644 index 0000000..9b88e2d --- /dev/null +++ b/tests/Cases/TemplateTuroisoTest.phpt @@ -0,0 +1,14 @@ +renderToPdf(PreviewFactory::createOrder()); + (new TuroisoTemplate())->renderToSvg(PreviewFactory::createOrder()); +}); diff --git a/tests/Unit.suite.yml b/tests/Unit.suite.yml deleted file mode 100644 index d57a0b7..0000000 --- a/tests/Unit.suite.yml +++ /dev/null @@ -1,12 +0,0 @@ -error_level: "E_ALL" - -actor: UnitTester - -coverage: - enabled: true - -modules: - - enabled: - - Asserts - - \Helper\Unit diff --git a/tests/Unit/CompanyTest.php b/tests/Unit/CompanyTest.php deleted file mode 100644 index 7fbdbc3..0000000 --- a/tests/Unit/CompanyTest.php +++ /dev/null @@ -1,22 +0,0 @@ -getName()); - self::assertSame('town', $company->getTown()); - self::assertSame('address', $company->getAddress()); - self::assertSame('zip', $company->getZip()); - self::assertSame('country', $company->getCountry()); - self::assertSame('vatNumber', $company->getVatNumber()); - self::assertSame('id', $company->getId()); - } - -} diff --git a/tests/Unit/TemplateParaisoTest.php b/tests/Unit/TemplateParaisoTest.php deleted file mode 100644 index 0f427aa..0000000 --- a/tests/Unit/TemplateParaisoTest.php +++ /dev/null @@ -1,16 +0,0 @@ -renderToPdf(PreviewFactory::createOrder()); - (new ParaisoTemplate())->renderToSvg(PreviewFactory::createOrder()); - } - -} diff --git a/tests/Unit/TemplateTuroisoTest.php b/tests/Unit/TemplateTuroisoTest.php deleted file mode 100644 index 30d8d19..0000000 --- a/tests/Unit/TemplateTuroisoTest.php +++ /dev/null @@ -1,16 +0,0 @@ -renderToPdf(PreviewFactory::createOrder()); - (new TuroisoTemplate())->renderToSvg(PreviewFactory::createOrder()); - } - -} diff --git a/tests/_data/.gitkeep b/tests/_data/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tests/_output/.gitignore b/tests/_output/.gitignore deleted file mode 100644 index c96a04f..0000000 --- a/tests/_output/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/tests/_support/Helper/Unit.php b/tests/_support/Helper/Unit.php deleted file mode 100644 index cd18208..0000000 --- a/tests/_support/Helper/Unit.php +++ /dev/null @@ -1,11 +0,0 @@ - Date: Sun, 8 Feb 2026 15:39:19 +0000 Subject: [PATCH 03/12] Config: use PHP 8.2 base, update phpstan/ruleset/Makefile to contributte standards --- .editorconfig | 2 +- .gitattributes | 6 ++---- .gitignore | 8 ++++++-- Makefile | 24 +++++++++++++----------- phpstan.neon | 11 ++++++++--- ruleset.xml | 29 ++++++++++++++--------------- 6 files changed, 44 insertions(+), 36 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3faf149..5e5b915 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,6 +11,6 @@ indent_style = tab indent_size = tab tab_width = 4 -[{*.json, *.yaml, *.yml, *.md}] +[*.{json,yaml,yml,md}] indent_style = space indent_size = 2 diff --git a/.gitattributes b/.gitattributes index c5baa7b..aad8529 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,12 +1,10 @@ -# Not archived .docs export-ignore -tests export-ignore .editorconfig export-ignore .gitattributes export-ignore .gitignore export-ignore .travis.yml export-ignore Makefile export-ignore -phpstan.neon export-ignore -phpstan.php export-ignore README.md export-ignore +phpstan.neon export-ignore ruleset.xml export-ignore +tests export-ignore diff --git a/.gitignore b/.gitignore index b1b6f4d..f0b3670 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,9 @@ /composer.lock # Tests -/temp -/coverage.xml +/tests/tmp +/coverage.* +/tests/**/*.log +/tests/**/*.html +/tests/**/*.expected +/tests/**/*.actual diff --git a/Makefile b/Makefile index ea43277..33bc117 100644 --- a/Makefile +++ b/Makefile @@ -1,32 +1,34 @@ -.PHONY: install qa cs csf phpstan tests coverage - +.PHONY: install install: composer update +.PHONY: qa qa: phpstan cs +.PHONY: cs cs: ifdef GITHUB_ACTION - vendor/bin/codesniffer -q --report=checkstyle src tests | cs2pr + vendor/bin/phpcs --standard=ruleset.xml --encoding=utf-8 --extensions="php,phpt" --colors -nsp -q --report=checkstyle src tests | cs2pr else - vendor/bin/codesniffer src tests + vendor/bin/phpcs --standard=ruleset.xml --encoding=utf-8 --extensions="php,phpt" --colors -nsp src tests endif +.PHONY: csf csf: - vendor/bin/codefixer src tests + vendor/bin/phpcbf --standard=ruleset.xml --encoding=utf-8 --extensions="php,phpt" --colors -nsp src tests +.PHONY: phpstan phpstan: vendor/bin/phpstan analyse -c phpstan.neon +.PHONY: tests tests: - vendor/bin/codecept build - vendor/bin/codecept run + vendor/bin/tester -s -p php --colors 1 -C tests/Cases +.PHONY: coverage coverage: ifdef GITHUB_ACTION - vendor/bin/codecept build - XDEBUG_MODE=coverage vendor/bin/codecept run --coverage --coverage-xml + vendor/bin/tester -s -p phpdbg --colors 1 -C --coverage coverage.xml --coverage-src src tests/Cases else - vendor/bin/codecept build - XDEBUG_MODE=coverage vendor/bin/codecept run --coverage --coverage-html + vendor/bin/tester -s -p phpdbg --colors 1 -C --coverage coverage.html --coverage-src src tests/Cases endif diff --git a/phpstan.neon b/phpstan.neon index 8004f85..438a071 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,10 +1,15 @@ includes: - - vendor/phpstan/phpstan-deprecation-rules/rules.neon - - vendor/phpstan/phpstan-nette/extension.neon - - vendor/phpstan/phpstan-nette/rules.neon + - vendor/contributte/phpstan/phpstan.neon parameters: level: 8 + phpVersion: 80200 + + scanDirectories: + - src + + fileExtensions: + - php paths: - src diff --git a/ruleset.xml b/ruleset.xml index 3540b8e..1ad2162 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -1,19 +1,18 @@ - - - + + + - - - - - - + + + + + + + + + - - /tests/ - /src/Data/Account.php - /src/Renderers/PDF.php + + /tests/tmp From 36da8960aed28d0b5a5b8413b2a9103a4044eda3 Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Sun, 8 Feb 2026 15:39:56 +0000 Subject: [PATCH 04/12] Composer: use PHP 8.2, replace dev dependencies with contributte packages --- composer.json | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/composer.json b/composer.json index fb03851..687d4b4 100755 --- a/composer.json +++ b/composer.json @@ -1,41 +1,45 @@ { "name": "contributte/invoice", - "type": "library", "description": "Library for easily and quickly creating invoices for customers.", - "license": [ - "MIT" - ], - "keywords": [ - "contributte", - "invoice" + "keywords": ["contributte", "invoice"], + "type": "library", + "license": "MIT", + "homepage": "https://github.com/contributte/invoice", + "authors": [ + { + "name": "Milan Felix Ć ulc", + "homepage": "https://f3l1x.io" + } ], "require": { - "php": ">=8.0", - "webchemistry/svg-pdf": "~1.1.3" + "php": ">=8.2", + "webchemistry/svg-pdf": "^1.1.3" }, "require-dev": { - "codeception/codeception": "^5.0.4", - "codeception/module-asserts": "^3.0.0", - "codeception/module-phpbrowser": "^3.0.0", - "nette/di": "^3.0.0", + "contributte/phpstan": "~0.2.0", + "contributte/qa": "~0.4.0", + "contributte/tester": "~0.3.0", "nette/application": "^3.0.0", - "ninjify/qa": "^0.12.0", - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-nette": "^1.0" + "nette/di": "^3.0.0" }, "autoload": { "psr-4": { - "Contributte\\Invoice\\": "src/" + "Contributte\\Invoice\\": "src" } }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, "config": { "sort-packages": true, "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true } }, - "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "4.1.x-dev" From 6815aff95a1bcbeec69db913ea9144fd96be7173 Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Sun, 8 Feb 2026 15:42:59 +0000 Subject: [PATCH 05/12] Config: fix ruleset filename, add phpstan baseline --- phpstan-baseline.neon | 49 +++++++++++++++++++++++++++++++++++++++++++ phpstan.neon | 1 + ruleset.xml | 2 +- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 phpstan-baseline.neon diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..1ba514d --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,49 @@ +parameters: + ignoreErrors: + - + message: '#^Only booleans are allowed in an if condition, Nette\\DI\\Definitions\\Statement\|null given\.$#' + identifier: if.condNotBoolean + count: 1 + path: src/Bridge/Nette/DI/InvoiceExtension.php + + - + message: '#^Only booleans are allowed in an if condition, array\ given\.$#' + identifier: if.condNotBoolean + count: 1 + path: src/Bridge/Nette/DI/InvoiceExtension.php + + - + message: '#^Return type \(array\\) of method Contributte\\Invoice\\Data\\PaymentInformation\:\:getAccounts\(\) should be covariant with return type \(array\\) of method Contributte\\Invoice\\Data\\IPaymentInformation\:\:getAccounts\(\)$#' + identifier: method.childReturnType + count: 1 + path: src/Data/PaymentInformation.php + + - + message: '#^Only booleans are allowed in a negated boolean, array\ given\.$#' + identifier: booleanNot.exprNotBoolean + count: 1 + path: src/Provider/InvoiceAccountsProvider.php + + - + message: '#^Call to function array_filter\(\) requires parameter \#2 to be passed to avoid loose comparison semantics\.$#' + identifier: arrayFilter.strict + count: 5 + path: src/Templates/Template/ParaisoTemplateObject.php + + - + message: '#^Call to function array_filter\(\) requires parameter \#2 to be passed to avoid loose comparison semantics\.$#' + identifier: arrayFilter.strict + count: 1 + path: src/Templates/Template/TemplateObject.php + + - + message: '#^Only booleans are allowed in a negated boolean, array\ given\.$#' + identifier: booleanNot.exprNotBoolean + count: 1 + path: src/Templates/Template/TemplateObject.php + + - + message: '#^Call to function array_filter\(\) requires parameter \#2 to be passed to avoid loose comparison semantics\.$#' + identifier: arrayFilter.strict + count: 4 + path: src/Templates/Template/TuroisoTemplateObject.php diff --git a/phpstan.neon b/phpstan.neon index 438a071..a945062 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,6 @@ includes: - vendor/contributte/phpstan/phpstan.neon + - phpstan-baseline.neon parameters: level: 8 diff --git a/ruleset.xml b/ruleset.xml index 1ad2162..c10f9ee 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -1,7 +1,7 @@ - + From 79fae8ef50257c35a53c68ad522bcc9d8d607d99 Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Sun, 8 Feb 2026 15:43:06 +0000 Subject: [PATCH 06/12] Config: apply code style fixes for new ruleset --- src/Preview/PreviewFactory.php | 6 +----- src/Templates/ParaisoTemplate.php | 10 +++++----- src/Templates/Template.php | 11 +++++------ src/Templates/Template/ParaisoTemplateObject.php | 4 ++-- src/Templates/Translator/Translator.php | 1 + 5 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/Preview/PreviewFactory.php b/src/Preview/PreviewFactory.php index 7f78028..8974e26 100644 --- a/src/Preview/PreviewFactory.php +++ b/src/Preview/PreviewFactory.php @@ -75,11 +75,7 @@ private static function addItems(IOrder $order, ?int $itemCount = null, string $ ]; $count = count($items); - if ($itemCount === null) { - $itemCount = $count; - } else { - $itemCount = max($itemCount, 0); - } + $itemCount = $itemCount === null ? $count : max($itemCount, 0); if ($count < $itemCount) { $array = $items; diff --git a/src/Templates/ParaisoTemplate.php b/src/Templates/ParaisoTemplate.php index ff81ea5..58a9852 100644 --- a/src/Templates/ParaisoTemplate.php +++ b/src/Templates/ParaisoTemplate.php @@ -35,11 +35,6 @@ public function __construct(?ITranslator $translator = null) parent::__construct($renderer); } - protected function getTemplate(): string - { - return __DIR__ . '/templates/paraiso.phtml'; - } - /** * @internal */ @@ -48,4 +43,9 @@ public function createTemplateObject(IOrder $order): ParaisoTemplateObject return new ParaisoTemplateObject($order, $this->translator); } + protected function getTemplate(): string + { + return __DIR__ . '/templates/paraiso.phtml'; + } + } diff --git a/src/Templates/Template.php b/src/Templates/Template.php index d884970..ea07faf 100644 --- a/src/Templates/Template.php +++ b/src/Templates/Template.php @@ -4,7 +4,6 @@ use Contributte\Invoice\Data\IOrder; use Contributte\Invoice\Templates\Template\TemplateObject; -use Exception; use LogicException; use WebChemistry\SvgPdf\PdfSvg; @@ -31,7 +30,7 @@ public function renderToSvg(IOrder $order): string { ob_start(); - $template = $this->createTemplateObject($order); + $template = $this->createTemplateObject($order); // phpcs:ignore SlevomatCodingStandard.Variables.UnusedVariable.UnusedVariable require $this->getTemplate(); $content = ob_get_clean(); @@ -43,13 +42,13 @@ public function renderToSvg(IOrder $order): string return $content; } + abstract protected function getTemplate(): string; + + abstract protected function createTemplateObject(IOrder $order): TemplateObject; + protected function renderTemplate(IOrder $order): string { return $this->renderer->toPdf($this->renderToSvg($order))->toString(); } - abstract protected function getTemplate(): string; - - abstract protected function createTemplateObject(IOrder $order): TemplateObject; - } diff --git a/src/Templates/Template/ParaisoTemplateObject.php b/src/Templates/Template/ParaisoTemplateObject.php index 55d4a11..4630d82 100644 --- a/src/Templates/Template/ParaisoTemplateObject.php +++ b/src/Templates/Template/ParaisoTemplateObject.php @@ -76,8 +76,8 @@ public function __construct(IOrder $order, ITranslator $translator) $this->prepend( $translator->translate('Specific symbol') . ': ', $payment instanceof ISpecificSymbol ? $payment->getSpecificSymbol() : null, - ) - ]); + ), + ]); } /** diff --git a/src/Templates/Translator/Translator.php b/src/Templates/Translator/Translator.php index da86934..bd503f3 100644 --- a/src/Templates/Translator/Translator.php +++ b/src/Templates/Translator/Translator.php @@ -32,6 +32,7 @@ public function translate(string $message): string if (!isset($this->translations[$this->lang][$message])) { throw new \Exception($message); } + return $this->translations[$this->lang][$message] ?? $message; } From 5c279b94746dbc7e6e20d75c3d956f9213a0ae6e Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Sun, 8 Feb 2026 15:43:14 +0000 Subject: [PATCH 07/12] Tests: add assertions to template render tests --- tests/Cases/TemplateParaisoTest.phpt | 8 ++++++-- tests/Cases/TemplateTuroisoTest.phpt | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/Cases/TemplateParaisoTest.phpt b/tests/Cases/TemplateParaisoTest.phpt index 2fc208e..0c9e2a6 100644 --- a/tests/Cases/TemplateParaisoTest.phpt +++ b/tests/Cases/TemplateParaisoTest.phpt @@ -5,10 +5,14 @@ namespace Tests\Cases; use Contributte\Invoice\Preview\PreviewFactory; use Contributte\Invoice\Templates\ParaisoTemplate; use Contributte\Tester\Toolkit; +use Tester\Assert; require_once __DIR__ . '/../bootstrap.php'; Toolkit::test(static function (): void { - (new ParaisoTemplate())->renderToPdf(PreviewFactory::createOrder()); - (new ParaisoTemplate())->renderToSvg(PreviewFactory::createOrder()); + $pdf = (new ParaisoTemplate())->renderToPdf(PreviewFactory::createOrder()); + Assert::true(strlen($pdf) > 0); + + $svg = (new ParaisoTemplate())->renderToSvg(PreviewFactory::createOrder()); + Assert::true(strlen($svg) > 0); }); diff --git a/tests/Cases/TemplateTuroisoTest.phpt b/tests/Cases/TemplateTuroisoTest.phpt index 9b88e2d..1c62862 100644 --- a/tests/Cases/TemplateTuroisoTest.phpt +++ b/tests/Cases/TemplateTuroisoTest.phpt @@ -5,10 +5,14 @@ namespace Tests\Cases; use Contributte\Invoice\Preview\PreviewFactory; use Contributte\Invoice\Templates\TuroisoTemplate; use Contributte\Tester\Toolkit; +use Tester\Assert; require_once __DIR__ . '/../bootstrap.php'; Toolkit::test(static function (): void { - (new TuroisoTemplate())->renderToPdf(PreviewFactory::createOrder()); - (new TuroisoTemplate())->renderToSvg(PreviewFactory::createOrder()); + $pdf = (new TuroisoTemplate())->renderToPdf(PreviewFactory::createOrder()); + Assert::true(strlen($pdf) > 0); + + $svg = (new TuroisoTemplate())->renderToSvg(PreviewFactory::createOrder()); + Assert::true(strlen($svg) > 0); }); From c72374701fc6917b09331304913dc45b59bdea58 Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Mon, 9 Feb 2026 13:09:43 +0000 Subject: [PATCH 08/12] Phpstan: fix if.condNotBoolean, use explicit boolean conditions --- phpstan-baseline.neon | 12 ------------ src/Bridge/Nette/DI/InvoiceExtension.php | 4 ++-- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 1ba514d..8a67fc5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,17 +1,5 @@ parameters: ignoreErrors: - - - message: '#^Only booleans are allowed in an if condition, Nette\\DI\\Definitions\\Statement\|null given\.$#' - identifier: if.condNotBoolean - count: 1 - path: src/Bridge/Nette/DI/InvoiceExtension.php - - - - message: '#^Only booleans are allowed in an if condition, array\ given\.$#' - identifier: if.condNotBoolean - count: 1 - path: src/Bridge/Nette/DI/InvoiceExtension.php - - message: '#^Return type \(array\\) of method Contributte\\Invoice\\Data\\PaymentInformation\:\:getAccounts\(\) should be covariant with return type \(array\\) of method Contributte\\Invoice\\Data\\IPaymentInformation\:\:getAccounts\(\)$#' identifier: method.childReturnType diff --git a/src/Bridge/Nette/DI/InvoiceExtension.php b/src/Bridge/Nette/DI/InvoiceExtension.php index a62c37f..4211a08 100755 --- a/src/Bridge/Nette/DI/InvoiceExtension.php +++ b/src/Bridge/Nette/DI/InvoiceExtension.php @@ -38,13 +38,13 @@ public function loadConfiguration(): void $builder = $this->getContainerBuilder(); $company = $this->getCompany(); - if ($company) { + if ($company !== null) { $builder->addDefinition($this->prefix('companyProvider')) ->setFactory(InvoiceCompanyProvider::class, [$company]); } $accounts = $this->getAccounts(); - if ($accounts) { + if ($accounts !== []) { $builder->addDefinition($this->prefix('accountsProvider')) ->setFactory(InvoiceAccountsProvider::class, [$accounts]); } From 0085a239be7c8984ed061928c6b19e40fdf596c9 Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Mon, 9 Feb 2026 13:10:28 +0000 Subject: [PATCH 09/12] Phpstan: fix method.childReturnType, use IAccount in interface --- phpstan-baseline.neon | 6 ------ src/Data/IPaymentInformation.php | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 8a67fc5..f68243a 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,11 +1,5 @@ parameters: ignoreErrors: - - - message: '#^Return type \(array\\) of method Contributte\\Invoice\\Data\\PaymentInformation\:\:getAccounts\(\) should be covariant with return type \(array\\) of method Contributte\\Invoice\\Data\\IPaymentInformation\:\:getAccounts\(\)$#' - identifier: method.childReturnType - count: 1 - path: src/Data/PaymentInformation.php - - message: '#^Only booleans are allowed in a negated boolean, array\ given\.$#' identifier: booleanNot.exprNotBoolean diff --git a/src/Data/IPaymentInformation.php b/src/Data/IPaymentInformation.php index 593df8b..63912a7 100644 --- a/src/Data/IPaymentInformation.php +++ b/src/Data/IPaymentInformation.php @@ -6,7 +6,7 @@ interface IPaymentInformation { /** - * @return Account[] + * @return IAccount[] */ public function getAccounts(): array; From 1476f9e426cc4acc976d2a1180c0e2be8854ed8f Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Mon, 9 Feb 2026 13:11:15 +0000 Subject: [PATCH 10/12] Phpstan: fix booleanNot.exprNotBoolean, use strict empty array checks --- phpstan-baseline.neon | 12 ------------ src/Provider/InvoiceAccountsProvider.php | 2 +- src/Templates/Template/TemplateObject.php | 2 +- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index f68243a..5a4b801 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,11 +1,5 @@ parameters: ignoreErrors: - - - message: '#^Only booleans are allowed in a negated boolean, array\ given\.$#' - identifier: booleanNot.exprNotBoolean - count: 1 - path: src/Provider/InvoiceAccountsProvider.php - - message: '#^Call to function array_filter\(\) requires parameter \#2 to be passed to avoid loose comparison semantics\.$#' identifier: arrayFilter.strict @@ -18,12 +12,6 @@ parameters: count: 1 path: src/Templates/Template/TemplateObject.php - - - message: '#^Only booleans are allowed in a negated boolean, array\ given\.$#' - identifier: booleanNot.exprNotBoolean - count: 1 - path: src/Templates/Template/TemplateObject.php - - message: '#^Call to function array_filter\(\) requires parameter \#2 to be passed to avoid loose comparison semantics\.$#' identifier: arrayFilter.strict diff --git a/src/Provider/InvoiceAccountsProvider.php b/src/Provider/InvoiceAccountsProvider.php index f3cf55a..69cf151 100644 --- a/src/Provider/InvoiceAccountsProvider.php +++ b/src/Provider/InvoiceAccountsProvider.php @@ -18,7 +18,7 @@ final class InvoiceAccountsProvider */ public function __construct(array $accounts) { - if (!$accounts) { + if ($accounts === []) { throw new BadMethodCallException('Accounts array cannot be empty.'); } diff --git a/src/Templates/Template/TemplateObject.php b/src/Templates/Template/TemplateObject.php index 204fc3a..c1f07ff 100644 --- a/src/Templates/Template/TemplateObject.php +++ b/src/Templates/Template/TemplateObject.php @@ -41,7 +41,7 @@ protected function prepend(string $prepend, ?string $str): ?string protected function implode(array $items, string $separator): ?string { $items = array_filter($items); - if (!$items) { + if ($items === []) { return null; } From 286e576a2b980143e08d59ef1dd9c6c9a26ff6f6 Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Mon, 9 Feb 2026 13:12:44 +0000 Subject: [PATCH 11/12] Phpstan: fix arrayFilter.strict, add explicit filter callbacks --- phpstan-baseline.neon | 19 +------------------ .../Template/ParaisoTemplateObject.php | 10 +++++----- src/Templates/Template/TemplateObject.php | 2 +- .../Template/TuroisoTemplateObject.php | 8 ++++---- 4 files changed, 11 insertions(+), 28 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 5a4b801..aab4991 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,19 +1,2 @@ parameters: - ignoreErrors: - - - message: '#^Call to function array_filter\(\) requires parameter \#2 to be passed to avoid loose comparison semantics\.$#' - identifier: arrayFilter.strict - count: 5 - path: src/Templates/Template/ParaisoTemplateObject.php - - - - message: '#^Call to function array_filter\(\) requires parameter \#2 to be passed to avoid loose comparison semantics\.$#' - identifier: arrayFilter.strict - count: 1 - path: src/Templates/Template/TemplateObject.php - - - - message: '#^Call to function array_filter\(\) requires parameter \#2 to be passed to avoid loose comparison semantics\.$#' - identifier: arrayFilter.strict - count: 4 - path: src/Templates/Template/TuroisoTemplateObject.php + ignoreErrors: [] diff --git a/src/Templates/Template/ParaisoTemplateObject.php b/src/Templates/Template/ParaisoTemplateObject.php index 4630d82..2f35a0e 100644 --- a/src/Templates/Template/ParaisoTemplateObject.php +++ b/src/Templates/Template/ParaisoTemplateObject.php @@ -39,7 +39,7 @@ public function __construct(IOrder $order, ITranslator $translator) $this->toFullAddress($company), $this->prepend($translator->translate('ID') . ': ', $company->getId()), $this->prepend($translator->translate('VAT Number') . ': ', $company->getVatNumber()), - ]); + ], static fn (?string $v): bool => $v !== null && $v !== ''); $customer = $order->getCustomer(); $this->invoiceTo = array_filter([ @@ -48,14 +48,14 @@ public function __construct(IOrder $order, ITranslator $translator) $this->toFullAddress($customer), $this->prepend($translator->translate('ID') . ': ', $customer->getId()), $this->prepend($translator->translate('VAT Number') . ': ', $customer->getVatNumber()), - ]); + ], static fn (?string $v): bool => $v !== null && $v !== ''); $timestamps = $order->getTimestamps(); $this->invoiceInfo = array_filter([ sprintf('%s %s', $translator->translate('Invoice No.'), $order->getNumber()), sprintf('%s: %s', $translator->translate('Invoice date'), $timestamps->getCreated()), $this->prepend($this->translate('Invoice due to') . ': ', $timestamps->getDueTo()), - ]); + ], static fn (?string $v): bool => $v !== null && $v !== ''); $payment = $order->getPayment(); $account = $payment->getFirstAccount(); @@ -77,7 +77,7 @@ public function __construct(IOrder $order, ITranslator $translator) $translator->translate('Specific symbol') . ': ', $payment instanceof ISpecificSymbol ? $payment->getSpecificSymbol() : null, ), - ]); + ], static fn (?string $v): bool => $v !== null && $v !== ''); } /** @@ -124,7 +124,7 @@ private function toFullAddress(ISubject $subject): string $subject->getTown(), $subject->getZip(), $subject->getCountry(), - ])); + ], static fn (?string $v): bool => $v !== null && $v !== '')); } } diff --git a/src/Templates/Template/TemplateObject.php b/src/Templates/Template/TemplateObject.php index c1f07ff..e180d6d 100644 --- a/src/Templates/Template/TemplateObject.php +++ b/src/Templates/Template/TemplateObject.php @@ -40,7 +40,7 @@ protected function prepend(string $prepend, ?string $str): ?string */ protected function implode(array $items, string $separator): ?string { - $items = array_filter($items); + $items = array_filter($items, static fn (mixed $v): bool => $v !== null && $v !== ''); if ($items === []) { return null; } diff --git a/src/Templates/Template/TuroisoTemplateObject.php b/src/Templates/Template/TuroisoTemplateObject.php index 436051c..af99562 100644 --- a/src/Templates/Template/TuroisoTemplateObject.php +++ b/src/Templates/Template/TuroisoTemplateObject.php @@ -53,12 +53,12 @@ public function __construct(IOrder $order, ITranslator $translator) $this->implode([$company->getZip(), $company->getTown()], ' '), $company->getAddress(), $company->getCountry(), - ]); + ], static fn (?string $v): bool => $v !== null && $v !== ''); $this->leftHeaderRight = array_filter([ $this->prepend($translator->translate('ID') . ': ', $company->getId()), $this->prepend($translator->translate('VAT Number') . ': ', $company->getVatNumber()), - ]); + ], static fn (?string $v): bool => $v !== null && $v !== ''); $this->rightHeader = [ $translator->translate('Date') . ': ' . $order->getTimestamps()->getCreated(), @@ -72,7 +72,7 @@ public function __construct(IOrder $order, ITranslator $translator) $customer->getCountry(), $this->prepend($translator->translate('ID') . ': ', $customer->getId()), $this->prepend($translator->translate('VAT Number') . ': ', $customer->getVatNumber()), - ]); + ], static fn (?string $v): bool => $v !== null && $v !== ''); $this->rightSubheader = array_filter([ $this->prepend($translator->translate('Due to') . ': ', $order->getTimestamps()->getDueTo()), @@ -85,7 +85,7 @@ public function __construct(IOrder $order, ITranslator $translator) $this->prepend($translator->translate('Constant symbol') . ': ', $payment->getConstantSymbol()) : null, $payment instanceof ISpecificSymbol ? $this->prepend($translator->translate('Specific symbol') . ': ', $payment->getSpecificSymbol()) : null, - ]); + ], static fn (?string $v): bool => $v !== null && $v !== ''); } } From 81a36997487e9e36d9415c1580930a052e99d0a7 Mon Sep 17 00:00:00 2001 From: Contributte AI Date: Mon, 9 Feb 2026 14:39:27 +0000 Subject: [PATCH 12/12] Config: remove phpstan baseline, fix coverage to use php instead of phpdbg --- Makefile | 4 ++-- phpstan-baseline.neon | 2 -- phpstan.neon | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 phpstan-baseline.neon diff --git a/Makefile b/Makefile index 33bc117..750fec1 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ tests: .PHONY: coverage coverage: ifdef GITHUB_ACTION - vendor/bin/tester -s -p phpdbg --colors 1 -C --coverage coverage.xml --coverage-src src tests/Cases + vendor/bin/tester -s -p php --colors 1 -C --coverage coverage.xml --coverage-src src tests/Cases else - vendor/bin/tester -s -p phpdbg --colors 1 -C --coverage coverage.html --coverage-src src tests/Cases + vendor/bin/tester -s -p php --colors 1 -C --coverage coverage.html --coverage-src src tests/Cases endif diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon deleted file mode 100644 index aab4991..0000000 --- a/phpstan-baseline.neon +++ /dev/null @@ -1,2 +0,0 @@ -parameters: - ignoreErrors: [] diff --git a/phpstan.neon b/phpstan.neon index a945062..438a071 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,5 @@ includes: - vendor/contributte/phpstan/phpstan.neon - - phpstan-baseline.neon parameters: level: 8