From 85b054b8d94c48c5fa1ff25a6522a0a6133da30c Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Wed, 17 Jul 2024 08:40:47 +0000
Subject: [PATCH 01/14] fix: require php version "^8.1"

Related: quiqqer/discount#17
---
 composer.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/composer.json b/composer.json
index fbc7f6a..98b6c33 100644
--- a/composer.json
+++ b/composer.json
@@ -18,7 +18,7 @@
     "url": "https://www.pcsg.de"
   },
   "require": {
-    "php": "^8.2",
+    "php": "^8.1",
     "quiqqer/core": "^2",
     "quiqqer/areas": "^2",
     "quiqqer/products": "^2",
-- 
GitLab


From 0fc53475e9b43d49454365db329bc82f1b83dcf6 Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Fri, 24 May 2024 17:07:47 +0200
Subject: [PATCH 02/14] chore: add .gitattributes file

---
 .gitattributes | 15 +++++++++++++++
 .gitignore     |  3 ++-
 2 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 .gitattributes

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..9ab59b1
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,15 @@
+
+# Ignore developer files when exporting
+.gitattributes         export-ignore
+.gitignore             export-ignore
+.gitlab-ci.yml         export-ignore
+.phive                 export-ignore
+captainhook.json       export-ignore
+phpcs.xml.dist         export-ignore
+phpstan-baseline.neon  export-ignore
+phpstan.dist.neon      export-ignore
+phpunit.dist.xml       export-ignore
+tests                  export-ignore
+
+# Explicitly set file type and line endings for PHP files, improves git diff output
+*.php     text eol=lf diff=php
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index f4da208..e87e64d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
 tools/
 phpstan.neon
 .phpunit.result.cache
-phpunit.xml
\ No newline at end of file
+phpunit.xml
+tools/
-- 
GitLab


From eb90e1d43a3567570df8537f46f3ca592214be2b Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Fri, 24 May 2024 17:07:48 +0200
Subject: [PATCH 03/14] chore: setup PHPStan for project tooling

---
 .gitignore       | 2 ++
 .phive/phars.xml | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index e87e64d..bb11804 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,5 @@ phpstan.neon
 .phpunit.result.cache
 phpunit.xml
 tools/
+
+phpstan.neon
diff --git a/.phive/phars.xml b/.phive/phars.xml
index a1315a0..f909b52 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <phive xmlns="https://phar.io/phive">
-  <phar name="phpstan" version="^1.10.67" installed="1.10.67" location="./tools/phpstan" copy="false"/>
+  <phar name="phpstan" version="1.11.1" installed="1.11.1" location="./tools/phpstan" copy="false"/>
 </phive>
-- 
GitLab


From 10334b69dd83433aaf1ea0f77c9c327be99cba71 Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Fri, 24 May 2024 17:07:48 +0200
Subject: [PATCH 04/14] chore: setup PHPUnit for project tooling

---
 .gitignore                  |  4 ++++
 .phive/phars.xml            |  1 +
 phpunit.dist.xml            |  8 ++++++++
 tests/phpunit-bootstrap.php | 11 +++++++++++
 4 files changed, 24 insertions(+)
 create mode 100644 phpunit.dist.xml
 create mode 100644 tests/phpunit-bootstrap.php

diff --git a/.gitignore b/.gitignore
index bb11804..e25391c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,7 @@ phpunit.xml
 tools/
 
 phpstan.neon
+
+.phpunit.result.cache
+
+phpunit.xml
diff --git a/.phive/phars.xml b/.phive/phars.xml
index f909b52..6984891 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <phive xmlns="https://phar.io/phive">
   <phar name="phpstan" version="1.11.1" installed="1.11.1" location="./tools/phpstan" copy="false"/>
+  <phar name="phpunit" version="^10.5.20" installed="10.5.20" location="./tools/phpunit" copy="false"/>
 </phive>
diff --git a/phpunit.dist.xml b/phpunit.dist.xml
new file mode 100644
index 0000000..f6c7bec
--- /dev/null
+++ b/phpunit.dist.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="tests/phpunit-bootstrap.php">
+    <testsuites>
+        <testsuite name="Tests">
+            <directory>tests/</directory>
+        </testsuite>
+    </testsuites>
+</phpunit>
diff --git a/tests/phpunit-bootstrap.php b/tests/phpunit-bootstrap.php
new file mode 100644
index 0000000..eca92fd
--- /dev/null
+++ b/tests/phpunit-bootstrap.php
@@ -0,0 +1,11 @@
+<?php
+
+if (!defined('QUIQQER_SYSTEM')) {
+    define('QUIQQER_SYSTEM', true);
+}
+
+if (!defined('QUIQQER_AJAX')) {
+    define('QUIQQER_AJAX', true);
+}
+
+require_once __DIR__ . '/../../../../bootstrap.php';
-- 
GitLab


From 3fa692bdbe7059ba01c14221846701ff3c53b597 Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Fri, 24 May 2024 17:07:48 +0200
Subject: [PATCH 05/14] chore: setup PHP_CodeSniffer for project tooling

---
 .phive/phars.xml |  2 ++
 phpcs.xml.dist   | 23 +++++++++++++++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 phpcs.xml.dist

diff --git a/.phive/phars.xml b/.phive/phars.xml
index 6984891..3c7dea3 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -2,4 +2,6 @@
 <phive xmlns="https://phar.io/phive">
   <phar name="phpstan" version="1.11.1" installed="1.11.1" location="./tools/phpstan" copy="false"/>
   <phar name="phpunit" version="^10.5.20" installed="10.5.20" location="./tools/phpunit" copy="false"/>
+  <phar name="phpcs" version="^3.10.1" installed="3.10.1" location="./tools/phpcs" copy="false"/>
+  <phar name="phpcbf" version="^3.10.1" installed="3.10.1" location="./tools/phpcbf" copy="false"/>
 </phive>
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
new file mode 100644
index 0000000..d48084f
--- /dev/null
+++ b/phpcs.xml.dist
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<ruleset>
+    <!-- Use PSR-12 ruleset -->
+    <rule ref="PSR12"/>
+
+    <!-- Only scan *.php files -->
+    <arg name="extensions" value="php"/>
+
+    <!-- Ignore warnings -->
+    <arg name="warning-severity" value="0"/>
+
+    <!-- Process 64 (or number of CPU cores) files in parallel -->
+    <arg name="parallel" value="64"/>
+
+    <!-- Output relative file paths, by setting the current folder as the basepath -->
+    <arg name="basepath" value="."/>
+
+    <!-- Show colored output -->
+    <arg name="colors"/>
+
+    <!-- Scan everything in the current folder -->
+    <file>.</file>
+</ruleset>
-- 
GitLab


From a4650ed1c4ce4ac428fd16f2d04ee495d6867dfc Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Fri, 24 May 2024 17:07:49 +0200
Subject: [PATCH 06/14] chore: setup CaptainHook for project tooling

---
 .phive/phars.xml                |  1 +
 captainhook.json                | 16 ++++++++++++++++
 tests/captainhook-bootstrap.php |  3 +++
 3 files changed, 20 insertions(+)
 create mode 100644 captainhook.json
 create mode 100644 tests/captainhook-bootstrap.php

diff --git a/.phive/phars.xml b/.phive/phars.xml
index 3c7dea3..63a030f 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -4,4 +4,5 @@
   <phar name="phpunit" version="^10.5.20" installed="10.5.20" location="./tools/phpunit" copy="false"/>
   <phar name="phpcs" version="^3.10.1" installed="3.10.1" location="./tools/phpcs" copy="false"/>
   <phar name="phpcbf" version="^3.10.1" installed="3.10.1" location="./tools/phpcbf" copy="false"/>
+  <phar name="captainhook" version="^5.23.0" installed="5.23.0" location="./tools/captainhook" copy="false"/>
 </phive>
diff --git a/captainhook.json b/captainhook.json
new file mode 100644
index 0000000..30f1064
--- /dev/null
+++ b/captainhook.json
@@ -0,0 +1,16 @@
+{
+  "config": {
+    "bootstrap": "tests/captainhook-bootstrap.php"
+  },
+  "pre-commit": {
+    "enabled": true,
+    "actions": [
+      {
+        "action": "\\CaptainHook\\App\\Hook\\PHP\\Action\\Linting"
+      },
+      {
+        "action": "composer test"
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/tests/captainhook-bootstrap.php b/tests/captainhook-bootstrap.php
new file mode 100644
index 0000000..1b61b73
--- /dev/null
+++ b/tests/captainhook-bootstrap.php
@@ -0,0 +1,3 @@
+<?php
+
+// This file is supposed to be empty, see https://github.com/captainhookphp/captainhook/issues/248
-- 
GitLab


From 7aa93ba9764138da64299e61c653acc2ea61ba2d Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Fri, 24 May 2024 17:07:49 +0200
Subject: [PATCH 07/14] chore: add developer scripts to composer.json

---
 composer.json | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/composer.json b/composer.json
index 98b6c33..46d2b55 100644
--- a/composer.json
+++ b/composer.json
@@ -29,5 +29,47 @@
       "QUI\\ERP\\Discount\\": "src/QUI/ERP/Discount",
       "QUITests\\ERP\\Discount\\": "tests/QUITests/ERP/Discount"
     }
+  },
+  "scripts": {
+    "test": [
+      "@dev:lint",
+      "@dev:phpunit"
+    ],
+    "dev:phpunit": "./tools/phpunit",
+    "dev:lint": [
+      "@dev:lint:phpstan",
+      "@dev:lint:style"
+    ],
+    "dev:lint:phpstan": "./tools/phpstan",
+    "dev:lint:style": "./tools/phpcs",
+    "dev:lint:style:fix": "./tools/phpcbf",
+    "dev:init": [
+      "@dev:init:check-requirements",
+      "@dev:init:tools",
+      "@dev:init:git-hooks"
+    ],
+    "dev:init:check-requirements": [
+      "which composer > /dev/null || (echo 'Error: composer has to be globally installed'; exit 1)",
+      "which phive > /dev/null || (echo 'Error: PHIVE has to be globally installed'; exit 1)"
+    ],
+    "dev:init:tools": "phive install --temporary",
+    "dev:init:git-hooks": "./tools/captainhook install --only-enabled --force"
+  },
+  "scripts-aliases": {
+    "test": [
+      "dev:test"
+    ]
+  },
+  "scripts-descriptions": {
+    "test": "Runs linting, static analysis, and unit tests.",
+    "dev:phpunit": "Run PHPUnit test suites",
+    "dev:lint": "Run PHPStan and code style check",
+    "dev:lint:phpstan": "Run PHPStan",
+    "dev:lint:style": "Run code style check (PHP_CodeSniffer)",
+    "dev:lint:style:fix": "Try to fix code style errors automatically",
+    "dev:init": "Initialize the developer tooling (tools and git hooks)",
+    "dev:init:check-requirements": "Check if the necessary requirements are met",
+    "dev:init:tools": "Install all developer tools (requires PHIVE)",
+    "dev:init:git-hooks": "Install all git hooks (may require tools to be installed)"
   }
 }
-- 
GitLab


From 4c27bd1e83937e42ad7a96e8752210cdc586db78 Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Fri, 24 May 2024 17:07:49 +0200
Subject: [PATCH 08/14] ci: use quiqqer-package-bundle component

---
 .gitlab-ci.yml | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b8d20ac..b5a64b4 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,3 +1,17 @@
 include:
-  - project: 'quiqqer/stabilization/semantic-release'
-    file: '/ci-templates/.gitlab-ci.yml'
+  - component: dev.quiqqer.com/quiqqer/stabilization/ci-cd-components/quiqqer-package-bundle/quiqqer-package-bundle@main
+
+# Remove the entire phpunit-php8.1 block, to allow PHPUnit to run on PHP 8.1 in your pipeline
+phpunit-php8.1:
+  rules:
+    - when: never
+
+# Remove the entire phpunit-php8.2 block, to allow PHPUnit to run on PHP 8.2 in your pipeline
+phpunit-php8.2:
+  rules:
+    - when: never
+
+# Remove the entire phpunit-php8.3 block, to allow PHPUnit to run on PHP 8.3 in your pipeline
+phpunit-php8.3:
+  rules:
+    - when: never
\ No newline at end of file
-- 
GitLab


From 6bf2236299d3d55a0507821589f18dccdb9abf1d Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Fri, 24 May 2024 17:07:49 +0200
Subject: [PATCH 09/14] docs: add CONTRIBUTING.md file

---
 CONTRIBUTING.md | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 CONTRIBUTING.md

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..4a69a59
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,3 @@
+# Contributing
+
+This package follows the [QUIQQER contribution guidelines](https://dev.quiqqer.com/quiqqer/stabilization/documentation/-/wikis/home).
\ No newline at end of file
-- 
GitLab


From 07d1c375a950c8f0e69dd63bf23ef104a7ea7562 Mon Sep 17 00:00:00 2001
From: Henning Leutz <leutz@pcsg.de>
Date: Thu, 16 May 2024 13:56:26 +0200
Subject: [PATCH 10/14] chore: phpstan rules added

---
 phpstan.dist.neon | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/phpstan.dist.neon b/phpstan.dist.neon
index a545a04..28b833b 100644
--- a/phpstan.dist.neon
+++ b/phpstan.dist.neon
@@ -7,4 +7,27 @@ parameters:
         - src
         - ajax
     bootstrapFiles:
-        - tests/phpstan-bootstrap.php
\ No newline at end of file
+        - tests/phpstan-bootstrap.php
+    treatPhpDocTypesAsCertain: false
+    customRulesetUsed: true
+services:
+    -
+        class: \PHPStan\Rules\Properties\TypesAssignedToPropertiesRule
+        tags:
+            - phpstan.rules.rule
+    -
+        class: \PHPStan\Rules\Functions\ArrowFunctionReturnTypeRule
+        tags:
+            - phpstan.rules.rule
+    -
+        class: \PHPStan\Rules\Functions\ClosureReturnTypeRule
+        tags:
+            - phpstan.rules.rule
+    -
+        class: \PHPStan\Rules\Functions\ReturnTypeRule
+        tags:
+            - phpstan.rules.rule
+    -
+        class: \PHPStan\Rules\Methods\ReturnTypeRule
+        tags:
+            - phpstan.rules.rule
-- 
GitLab


From 5b2f7399f6772c913399e8e526a1d0a9c3965707 Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Fri, 2 Aug 2024 15:53:55 +0200
Subject: [PATCH 11/14] chore: set PHPStan to level 5 with baseline

---
 .phive/phars.xml      |  2 +-
 phpstan-baseline.neon | 46 +++++++++++++++++++++++++++++++++++++++++++
 phpstan.dist.neon     |  2 +-
 3 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/.phive/phars.xml b/.phive/phars.xml
index 63a030f..ebb5988 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <phive xmlns="https://phar.io/phive">
-  <phar name="phpstan" version="1.11.1" installed="1.11.1" location="./tools/phpstan" copy="false"/>
+  <phar name="phpstan" version="1.11.8" installed="1.11.8" location="./tools/phpstan" copy="false"/>
   <phar name="phpunit" version="^10.5.20" installed="10.5.20" location="./tools/phpunit" copy="false"/>
   <phar name="phpcs" version="^3.10.1" installed="3.10.1" location="./tools/phpcs" copy="false"/>
   <phar name="phpcbf" version="^3.10.1" installed="3.10.1" location="./tools/phpcbf" copy="false"/>
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index e69de29..74b2d37 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -0,0 +1,46 @@
+parameters:
+	ignoreErrors:
+		-
+			message: "#^Call to an undefined method QUI\\\\CRUD\\\\Child\\:\\:isActive\\(\\)\\.$#"
+			count: 1
+			path: ajax/activate.php
+
+		-
+			message: "#^Call to an undefined method QUI\\\\CRUD\\\\Child\\:\\:isActive\\(\\)\\.$#"
+			count: 1
+			path: ajax/deactivate.php
+
+		-
+			message: "#^Call to an undefined method QUI\\\\CRUD\\\\Child\\:\\:getTitle\\(\\)\\.$#"
+			count: 1
+			path: ajax/get.php
+
+		-
+			message: "#^Parameter \\#2 \\$callback of function usort expects callable\\(mixed, mixed\\)\\: int, Closure\\(mixed, mixed\\)\\: bool given\\.$#"
+			count: 1
+			path: ajax/search.php
+
+		-
+			message: "#^Call to an undefined method QUI\\\\CRUD\\\\Child\\:\\:isActive\\(\\)\\.$#"
+			count: 2
+			path: ajax/toggle.php
+
+		-
+			message: "#^Call to method getArticles\\(\\) on an unknown class QUI\\\\ERP\\\\Order\\\\OrderInterface\\.$#"
+			count: 1
+			path: src/QUI/ERP/Discount/Discount.php
+
+		-
+			message: "#^Parameter \\#2 \\$array of function implode expects array\\|null, string given\\.$#"
+			count: 1
+			path: src/QUI/ERP/Discount/Discount.php
+
+		-
+			message: "#^Parameter \\$Order of method QUI\\\\ERP\\\\Discount\\\\Discount\\:\\:canUsedInOrder\\(\\) has invalid type QUI\\\\ERP\\\\Order\\\\OrderInterface\\.$#"
+			count: 2
+			path: src/QUI/ERP/Discount/Discount.php
+
+		-
+			message: "#^Parameter \\#2 \\$string of function explode expects string, float\\|int\\<min, \\-1\\>\\|int\\<1, max\\>\\|true given\\.$#"
+			count: 1
+			path: src/QUI/ERP/Discount/PriceFactor.php
diff --git a/phpstan.dist.neon b/phpstan.dist.neon
index 28b833b..56d8bea 100644
--- a/phpstan.dist.neon
+++ b/phpstan.dist.neon
@@ -2,7 +2,7 @@ includes:
     - phpstan-baseline.neon
 
 parameters:
-    level: 1
+    level: 5
     paths:
         - src
         - ajax
-- 
GitLab


From 88a4fb8ecd0e663748f382fdae1f00bf5a6a6b0c Mon Sep 17 00:00:00 2001
From: Jan Wennrich <jan.wennrich@pcsg.de>
Date: Fri, 2 Aug 2024 15:53:55 +0200
Subject: [PATCH 12/14] chore: upgrade CaptainHook to version ^5.23.3

---
 .phive/phars.xml                |  2 +-
 captainhook.json                | 25 +++++++++++--------------
 tests/captainhook-bootstrap.php |  3 ---
 3 files changed, 12 insertions(+), 18 deletions(-)
 delete mode 100644 tests/captainhook-bootstrap.php

diff --git a/.phive/phars.xml b/.phive/phars.xml
index ebb5988..5bfa092 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -4,5 +4,5 @@
   <phar name="phpunit" version="^10.5.20" installed="10.5.20" location="./tools/phpunit" copy="false"/>
   <phar name="phpcs" version="^3.10.1" installed="3.10.1" location="./tools/phpcs" copy="false"/>
   <phar name="phpcbf" version="^3.10.1" installed="3.10.1" location="./tools/phpcbf" copy="false"/>
-  <phar name="captainhook" version="^5.23.0" installed="5.23.0" location="./tools/captainhook" copy="false"/>
+  <phar name="captainhook" version="^5.23.3" installed="5.23.3" location="./tools/captainhook" copy="false"/>
 </phive>
diff --git a/captainhook.json b/captainhook.json
index 30f1064..3702e1a 100644
--- a/captainhook.json
+++ b/captainhook.json
@@ -1,16 +1,13 @@
 {
-  "config": {
-    "bootstrap": "tests/captainhook-bootstrap.php"
-  },
-  "pre-commit": {
-    "enabled": true,
-    "actions": [
-      {
-        "action": "\\CaptainHook\\App\\Hook\\PHP\\Action\\Linting"
-      },
-      {
-        "action": "composer test"
-      }
-    ]
-  }
+    "pre-commit": {
+        "enabled": true,
+        "actions": [
+            {
+                "action": "\\CaptainHook\\App\\Hook\\PHP\\Action\\Linting"
+            },
+            {
+                "action": "composer test"
+            }
+        ]
+    }
 }
\ No newline at end of file
diff --git a/tests/captainhook-bootstrap.php b/tests/captainhook-bootstrap.php
deleted file mode 100644
index 1b61b73..0000000
--- a/tests/captainhook-bootstrap.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
-
-// This file is supposed to be empty, see https://github.com/captainhookphp/captainhook/issues/248
-- 
GitLab


From 6100708fe13f429aa7a3b1ec0f1e82aabb815b50 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Fri, 14 Feb 2025 09:27:59 +0100
Subject: [PATCH 13/14] fix(phpstan): improved method validity checks and
 reduced error handling

This commit fixes several issues in different PHP files.
- Added `method_exists` checks for `isActive` method in `activate.php`, `deactivate.php` and
`toggle.php` to prevent calls to an undefined method.
- Similar check added for `getTitle` method in `get.php`.
- Fixed sorting functionality in `search.php` by using `strcmp` instead of greater than comparison.
- Removed a large number of ignored errors in `phpstan-baseline.neon`, indicating reduced error
handling.
- Corrected the `implode` parameters order in `Discount.php` and typecasted variable to string
before using `explode` in `PriceFactor.php`.
- Updated `getTitle` & `toPriceFactor` method parameters in `Discount.php` to use union types for
compatibility with different data types.

Related: quiqqer/discount#18
---
 ajax/activate.php                    |  2 +-
 ajax/deactivate.php                  |  2 +-
 ajax/get.php                         |  2 +-
 ajax/search.php                      |  2 +-
 ajax/toggle.php                      |  4 +++
 phpstan-baseline.neon                | 46 +---------------------------
 src/QUI/ERP/Discount/Discount.php    |  6 ++--
 src/QUI/ERP/Discount/PriceFactor.php |  2 +-
 8 files changed, 13 insertions(+), 53 deletions(-)

diff --git a/ajax/activate.php b/ajax/activate.php
index b84ce10..138f7ab 100644
--- a/ajax/activate.php
+++ b/ajax/activate.php
@@ -22,7 +22,7 @@ function ($discountId) {
         $Discount->setAttribute('active', 1);
         $Discount->update();
 
-        return $Discount->isActive();
+        return method_exists($Discount, 'isActive') ? $Discount->isActive() : false;
     },
     ['discountId'],
     'Permission::checkAdminUser'
diff --git a/ajax/deactivate.php b/ajax/deactivate.php
index d82213b..2ecbc73 100644
--- a/ajax/deactivate.php
+++ b/ajax/deactivate.php
@@ -22,7 +22,7 @@ function ($discountId) {
         $Discount->setAttribute('active', 0);
         $Discount->update();
 
-        return $Discount->isActive();
+        return method_exists($Discount, 'isActive') ? $Discount->isActive() : false;
     },
     ['discountId'],
     'Permission::checkAdminUser'
diff --git a/ajax/get.php b/ajax/get.php
index 7a941df..c1aa502 100644
--- a/ajax/get.php
+++ b/ajax/get.php
@@ -22,7 +22,7 @@ function ($id) {
         $attributes = $Discount->getAttributes();
 
         /* @var $Discount Discount */
-        $attributes['title'] = $Discount->getTitle();
+        $attributes['title'] = method_exists($Discount, 'getTitle') ? $Discount->getTitle() : '';
 
         return $attributes;
     },
diff --git a/ajax/search.php b/ajax/search.php
index 0dfdbc1..f1a1706 100644
--- a/ajax/search.php
+++ b/ajax/search.php
@@ -67,7 +67,7 @@ function ($fields, $params) {
         }
 
         usort($result, function ($a, $b) {
-            return $a['text'] > $b['text'];
+            return strcmp($a['text'], $b['text']);
         });
 
         return $result;
diff --git a/ajax/toggle.php b/ajax/toggle.php
index 2ff6bc5..8e318cb 100644
--- a/ajax/toggle.php
+++ b/ajax/toggle.php
@@ -19,6 +19,10 @@ function ($discountId) {
         $Discount = $Handler->getChild($discountId);
 
         /* @var $Discount Discount */
+        if (!method_exists($Discount, 'isActive')) {
+            return false;
+        }
+
         if ($Discount->isActive()) {
             $Discount->setAttribute('active', 0);
         } else {
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 74b2d37..1339890 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -1,46 +1,2 @@
 parameters:
-	ignoreErrors:
-		-
-			message: "#^Call to an undefined method QUI\\\\CRUD\\\\Child\\:\\:isActive\\(\\)\\.$#"
-			count: 1
-			path: ajax/activate.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\CRUD\\\\Child\\:\\:isActive\\(\\)\\.$#"
-			count: 1
-			path: ajax/deactivate.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\CRUD\\\\Child\\:\\:getTitle\\(\\)\\.$#"
-			count: 1
-			path: ajax/get.php
-
-		-
-			message: "#^Parameter \\#2 \\$callback of function usort expects callable\\(mixed, mixed\\)\\: int, Closure\\(mixed, mixed\\)\\: bool given\\.$#"
-			count: 1
-			path: ajax/search.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\CRUD\\\\Child\\:\\:isActive\\(\\)\\.$#"
-			count: 2
-			path: ajax/toggle.php
-
-		-
-			message: "#^Call to method getArticles\\(\\) on an unknown class QUI\\\\ERP\\\\Order\\\\OrderInterface\\.$#"
-			count: 1
-			path: src/QUI/ERP/Discount/Discount.php
-
-		-
-			message: "#^Parameter \\#2 \\$array of function implode expects array\\|null, string given\\.$#"
-			count: 1
-			path: src/QUI/ERP/Discount/Discount.php
-
-		-
-			message: "#^Parameter \\$Order of method QUI\\\\ERP\\\\Discount\\\\Discount\\:\\:canUsedInOrder\\(\\) has invalid type QUI\\\\ERP\\\\Order\\\\OrderInterface\\.$#"
-			count: 2
-			path: src/QUI/ERP/Discount/Discount.php
-
-		-
-			message: "#^Parameter \\#2 \\$string of function explode expects string, float\\|int\\<min, \\-1\\>\\|int\\<1, max\\>\\|true given\\.$#"
-			count: 1
-			path: src/QUI/ERP/Discount/PriceFactor.php
+	ignoreErrors:
\ No newline at end of file
diff --git a/src/QUI/ERP/Discount/Discount.php b/src/QUI/ERP/Discount/Discount.php
index 399ae32..a28e43e 100644
--- a/src/QUI/ERP/Discount/Discount.php
+++ b/src/QUI/ERP/Discount/Discount.php
@@ -248,7 +248,7 @@ public function setAttribute(string $name, mixed $value): void
      * @param null|QUI\Locale $Locale - optional, locale object
      * @return string
      */
-    public function getTitle(QUI\Locale $Locale = null): string
+    public function getTitle(null | QUI\Locale $Locale = null): string
     {
         if (!$Locale) {
             $Locale = QUI::getLocale();
@@ -284,7 +284,7 @@ public function canCombinedWith(Discount $Discount): bool
             return false;
         }
 
-        $combine = implode($combine, ',');
+        $combine = implode(',', $combine);
 
         if (in_array($Discount->getId(), (array)$combine)) {
             return true;
@@ -521,7 +521,7 @@ public function verifyUser(User $User): void
     public function toPriceFactor(
         $Locale = null,
         $Customer = null
-    ): QUI\ERP\Products\Interfaces\PriceFactorInterface|QUI\ERP\Products\Interfaces\PriceFactorWithVatInterface|QUI\ERP\Products\Utils\PriceFactor {
+    ): QUI\ERP\Products\Interfaces\PriceFactorInterface | QUI\ERP\Products\Interfaces\PriceFactorWithVatInterface | QUI\ERP\Products\Utils\PriceFactor {
         switch ($this->getAttribute('discount_type')) {
             case QUI\ERP\Accounting\Calc::CALCULATION_PERCENTAGE:
                 $calculation = QUI\ERP\Accounting\Calc::CALCULATION_PERCENTAGE;
diff --git a/src/QUI/ERP/Discount/PriceFactor.php b/src/QUI/ERP/Discount/PriceFactor.php
index c18cdb2..12d57d8 100644
--- a/src/QUI/ERP/Discount/PriceFactor.php
+++ b/src/QUI/ERP/Discount/PriceFactor.php
@@ -47,7 +47,7 @@ public function getVatType(): QUI\ERP\Tax\TaxType
             return QUI\ERP\Tax\Utils::getShopTaxType();
         }
 
-        $standardTax = explode(':', $this->vat);
+        $standardTax = explode(':', (string)$this->vat);
 
         if (!isset($standardTax[1])) {
             return QUI\ERP\Tax\Utils::getShopTaxType();
-- 
GitLab


From e8c4d77cb59d0d5b5cd725cb5b8963c88c29de91 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Fri, 14 Feb 2025 09:34:29 +0100
Subject: [PATCH 14/14] refactor(phpstan): change order interface to erp entity
 interface in Discount

Updated the 'canUsedInOrder' function in Discount.php to accept ERP Entity Interface arguments
instead of Order Interfaces for better flexibility and compatibility. Added checks to ensure that
the provided entity is an instance of the Order Interface, increasing robustness.
---
 src/QUI/ERP/Discount/Discount.php | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/QUI/ERP/Discount/Discount.php b/src/QUI/ERP/Discount/Discount.php
index a28e43e..5ea7ba7 100644
--- a/src/QUI/ERP/Discount/Discount.php
+++ b/src/QUI/ERP/Discount/Discount.php
@@ -437,15 +437,23 @@ public function canUsedWith(QUI\ERP\Products\Interfaces\ProductInterface $Produc
     }
 
     /**
-     * @param OrderInterface $Order
+     * @param QUI\ERP\ErpEntityInterface $Order
      * @return bool
      */
-    public function canUsedInOrder(OrderInterface $Order): bool
+    public function canUsedInOrder(QUI\ERP\ErpEntityInterface $Order): bool
     {
         if ($this->isActive() === false) {
             return false;
         }
 
+        if (!interface_exists('QUI\ERP\Order\OrderInterface')) {
+            return false;
+        }
+
+        if (!($Order instanceof QUI\ERP\Order\OrderInterface)) {
+            return false;
+        }
+
         $Articles = $Order->getArticles();
 
         foreach ($Articles as $Article) {
-- 
GitLab