From a47405678f2b32b94e4e57ac5966041730099104 Mon Sep 17 00:00:00 2001
From: Owen Voke <development@voke.dev>
Date: Thu, 13 Mar 2025 10:37:54 +0000
Subject: [PATCH] feat: drop support for Laravel 10

---
 .editorconfig                                 |  2 +-
 .gitattributes                                | 37 +++++++--------
 .github/workflows/phpstan.yml                 | 26 ----------
 .github/workflows/static.yml                  | 47 +++++++++++++++++++
 .../workflows/{run-tests.yml => tests.yml}    | 17 +++----
 .gitignore                                    | 18 +++----
 composer.json                                 | 16 +++----
 docker-compose.yml                            |  7 ---
 docker/Dockerfile                             | 12 +----
 phpstan-baseline.neon                         | 46 ++++++++++++------
 phpstan.neon.dist                             | 11 +++--
 phpunit.xml.dist                              | 23 ++++++---
 src/Support/ConfigBasedFinder.php             |  4 +-
 13 files changed, 150 insertions(+), 116 deletions(-)
 delete mode 100644 .github/workflows/phpstan.yml
 create mode 100644 .github/workflows/static.yml
 rename .github/workflows/{run-tests.yml => tests.yml} (71%)

diff --git a/.editorconfig b/.editorconfig
index a7c44dd..dd9a2b5 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -2,9 +2,9 @@ root = true
 
 [*]
 charset = utf-8
+end_of_line = lf
 indent_size = 4
 indent_style = space
-end_of_line = lf
 insert_final_newline = true
 trim_trailing_whitespace = true
 
diff --git a/.gitattributes b/.gitattributes
index 83131a9..82c80c7 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,23 +1,22 @@
 # Path-based git attributes
-# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
+# https://git-scm.com/docs/gitattributes
+* text=auto
 
 # Ignore all test and documentation with "export-ignore".
-/.github            export-ignore
-/.gitattributes     export-ignore
-/.gitignore         export-ignore
-/phpunit.xml.dist   export-ignore
-/art                export-ignore
-/docs               export-ignore
-/tests              export-ignore
-/.editorconfig      export-ignore
-/phpcs.xml          export-ignore
-/.php_cs.dist.php   export-ignore
-/psalm.xml          export-ignore
-/psalm.xml.dist     export-ignore
-/testbench.yaml     export-ignore
-/UPGRADING.md       export-ignore
-/phpstan.neon.dist  export-ignore
+/.github                export-ignore
+/.gitattributes         export-ignore
+/.gitignore             export-ignore
+/phpunit.xml.dist       export-ignore
+/art                    export-ignore
+/docs                   export-ignore
+/tests                  export-ignore
+/.editorconfig          export-ignore
+/.php_cs.dist.php       export-ignore
+/psalm.xml              export-ignore
+/psalm.xml.dist         export-ignore
+/testbench.yaml         export-ignore
+/UPGRADING.md           export-ignore
+/phpstan.neon.dist      export-ignore
 /phpstan-baseline.neon  export-ignore
-/renovate.json      export-ignore
-/docker-compose.yml export-ignore
-/docker export-ignore
+/docker                 export-ignore
+/docker-compose.yml     export-ignore
diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml
deleted file mode 100644
index 524abf6..0000000
--- a/.github/workflows/phpstan.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-name: PHPStan
-
-on:
-  push:
-    paths:
-      - '**.php'
-      - 'phpstan.neon.dist'
-
-jobs:
-  phpstan:
-    name: phpstan
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v4
-
-      - name: Setup PHP
-        uses: shivammathur/setup-php@v2
-        with:
-          php-version: '8.2'
-          coverage: none
-
-      - name: Install composer dependencies
-        uses: ramsey/composer-install@v2
-
-      - name: Run PHPStan
-        run: composer test:types
diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml
new file mode 100644
index 0000000..74a756e
--- /dev/null
+++ b/.github/workflows/static.yml
@@ -0,0 +1,47 @@
+name: Static Analysis
+
+on:
+  push:
+    paths:
+      - '**.php'
+      - 'phpstan.neon.dist'
+
+jobs:
+  phpstan:
+    name: PHPStan
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: '8.3'
+          coverage: none
+
+      - name: Install composer dependencies
+        uses: ramsey/composer-install@v3
+
+      - name: Run PHPStan
+        run: composer test:types
+
+  ecs:
+    name: ECS
+
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: '8.3'
+          coverage: none
+
+      - name: Install Dependencies
+        run: composer update --prefer-dist --no-interaction --no-progress --ansi
+
+      - name: Run ECS
+        run: composer test:style
diff --git a/.github/workflows/run-tests.yml b/.github/workflows/tests.yml
similarity index 71%
rename from .github/workflows/run-tests.yml
rename to .github/workflows/tests.yml
index d2fc67c..7e6787a 100644
--- a/.github/workflows/run-tests.yml
+++ b/.github/workflows/tests.yml
@@ -9,24 +9,20 @@ on:
 jobs:
   test:
     runs-on: ${{ matrix.os }}
-    env:
-      PREVENT_OUTPUT: true
     strategy:
       fail-fast: true
       matrix:
-        os: [ubuntu-latest, windows-latest]
-        php: [8.2, 8.3, 8.4]
-        laravel: [10.*, 11.*, 12.*]
+        os: [ubuntu-latest]
+        php: [8.4, 8.3]
+        laravel: [12.*, 11.*]
         stability: [prefer-lowest, prefer-stable]
         include:
-          - laravel: 10.*
-            testbench: 8.*
-          - laravel: 11.*
-            testbench: 9.*
           - laravel: 12.*
             testbench: 10.*
+          - laravel: 11.*
+            testbench: 9.*
 
-    name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
+    name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
 
     steps:
       - name: Checkout code
@@ -36,7 +32,6 @@ jobs:
         uses: shivammathur/setup-php@v2
         with:
           php-version: ${{ matrix.php }}
-          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
           coverage: none
 
       - name: Setup problem matchers
diff --git a/.gitignore b/.gitignore
index b212367..72bb0c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,15 +1,15 @@
-.idea
+/.idea
+/build
+/vendor
+/.php_cs.cache
+/composer.lock
+/phpunit.xml
+/phpstan.neon
 .php_cs
 .php_cs.cache
-.phpunit.result.cache
 .phpunit.cache
-build
-composer.lock
+.php-cs-fixer.cache
 coverage
 docs
-phpunit.xml
-phpstan.neon
-testbench.yaml
-vendor
 node_modules
-.php-cs-fixer.cache
+testbench.yaml
diff --git a/composer.json b/composer.json
index 1a85b03..add00ef 100644
--- a/composer.json
+++ b/composer.json
@@ -16,16 +16,16 @@
         }
     ],
     "require": {
-        "php": "^8.2",
-        "illuminate/contracts": "^10.0 || ^11.0 || ^12.0"
+        "php": "^8.3",
+        "illuminate/contracts": "^11.0 || ^12.0"
     },
     "require-dev": {
-        "larastan/larastan": "^2.8 || ^3.0",
-        "nunomaduro/collision": "^7.0 || ^8.0",
-        "orchestra/testbench": "^8.20 || ^9.0 || ^10.0",
-        "pestphp/pest": "^2.30 || ^3.0",
-        "pestphp/pest-plugin-laravel": "^2.2 || ^3.0",
-        "worksome/coding-style": "^2.15 || ^3.1"
+        "larastan/larastan": "^3.1",
+        "nunomaduro/collision": "^7.10 || ^8.1.1",
+        "orchestra/testbench": "^9.12 || ^10.1",
+        "pestphp/pest": "^3.7",
+        "pestphp/pest-plugin-laravel": "^3.1",
+        "worksome/coding-style": "^3.2"
     },
     "autoload": {
         "psr-4": {
diff --git a/docker-compose.yml b/docker-compose.yml
index 0d0fae7..f23f2c2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,5 +1,3 @@
-version: "3.8"
-
 services:
   php:
     build: ./docker
@@ -8,11 +6,6 @@ services:
     environment:
       - XDEBUG_MODE=${XDEBUG_MODE:-off}
       - XDEBUG_CONFIG=${XDEBUG_CONFIG:-client_host=host.docker.internal}
-  pest:
-    build: ./docker
-    entrypoint: ["php", "./vendor/bin/pest"]
-    volumes:
-      - .:/var/www/html
   composer:
     build: ./docker
     entrypoint: ["composer"]
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 1664765..172cdec 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -1,15 +1,7 @@
-FROM php:8.2-cli
+FROM php:8.3-cli-alpine
 
+RUN apk add --no-cache $PHPIZE_DEPS linux-headers
 RUN pecl install xdebug
-
-RUN apt-get update \
-    && apt-get install -y libpng-dev libjpeg-dev libzip-dev zip
-
-RUN docker-php-ext-configure gd --with-jpeg
-RUN docker-php-ext-install gd
-
-RUN docker-php-ext-install zip
-
 RUN docker-php-ext-enable xdebug
 
 COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index d0d9fd6..03fd30c 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -1,5 +1,11 @@
 parameters:
 	ignoreErrors:
+		-
+			message: '#^PHP files should declare strict types\.$#'
+			identifier: worksome.declareStrictTypes
+			count: 1
+			path: config/request-factories.php
+
 		-
 			message: '#^Method Worksome\\RequestFactories\\Actions\\CreateFactoryResultSteps\\InvokeAfterCreatingHooks\:\:handle\(\) has parameter \$data with generic class Illuminate\\Support\\Collection but does not specify its types\: TKey, TValue$#'
 			identifier: missingType.generics
@@ -18,12 +24,6 @@ parameters:
 			count: 1
 			path: src/Actions/CreateFactoryResultSteps/InvokeAfterCreatingHooks.php
 
-		-
-			message: '#^Parameter \#1 \$callback of method Illuminate\\Support\\Collection\<\(int\|string\),mixed\>\:\:reduce\(\) expects callable\(mixed, mixed, int\|string\)\: mixed, Closure\(mixed, Closure\)\: mixed given\.$#'
-			identifier: argument.type
-			count: 1
-			path: src/Actions/CreateFactoryResultSteps/InvokeAfterCreatingHooks.php
-
 		-
 			message: '#^Method Worksome\\RequestFactories\\Actions\\CreateFactoryResultSteps\\RecursiveStep\:\:handle\(\) has parameter \$data with generic class Illuminate\\Support\\Collection but does not specify its types\: TKey, TValue$#'
 			identifier: missingType.generics
@@ -139,19 +139,37 @@ parameters:
 			path: src/Contracts/Actions/CreateFactoryResultStep.php
 
 		-
-			message: '#^Method Worksome\\RequestFactories\\RequestFactory\:\:getUndotsArrayKeysAction\(\) return type with generic interface Worksome\\RequestFactories\\Contracts\\Actions\\UndotsArrayKeys does not specify its types\: TValue$#'
-			identifier: missingType.generics
+			message: '#^Call to an undefined static method Worksome\\RequestFactories\\RequestFactoriesServiceProvider\:\:factory\(\)\.$#'
+			identifier: staticMethod.notFound
 			count: 1
-			path: src/RequestFactory.php
+			path: src/RequestFactoriesServiceProvider.php
 
 		-
-			message: '#^Parameter \#2 \$without of class Worksome\\RequestFactories\\RequestFactory constructor expects array\<int, string\>, array given\.$#'
-			identifier: argument.type
+			message: '#^Cannot access offset ''events'' on Illuminate\\Contracts\\Foundation\\Application\.$#'
+			identifier: offsetAccess.nonOffsetAccessible
 			count: 1
-			path: src/RequestFactory.php
+			path: src/RequestFactoriesServiceProvider.php
 
 		-
-			message: '#^Parameter \#3 \$afterCreatingHooks of class Worksome\\RequestFactories\\RequestFactory constructor expects array\<\(Closure\(array\)\: array\)\|void\>, array given\.$#'
-			identifier: argument.type
+			message: '#^Global helper function ''app'' should not be used\.$#'
+			identifier: larastanStrictRules.noGlobalLaravelFunction
+			count: 1
+			path: src/RequestFactoriesServiceProvider.php
+
+		-
+			message: '#^Global helper function ''config_path'' should not be used\.$#'
+			identifier: larastanStrictRules.noGlobalLaravelFunction
+			count: 1
+			path: src/RequestFactoriesServiceProvider.php
+
+		-
+			message: '#^Parameter \#2 \$macro of static method Illuminate\\Http\\Request\:\:macro\(\) expects bindable closure, static closure given\.$#'
+			identifier: argument.staticClosure
+			count: 2
+			path: src/RequestFactoriesServiceProvider.php
+
+		-
+			message: '#^Method Worksome\\RequestFactories\\RequestFactory\:\:getUndotsArrayKeysAction\(\) return type with generic interface Worksome\\RequestFactories\\Contracts\\Actions\\UndotsArrayKeys does not specify its types\: TValue$#'
+			identifier: missingType.generics
 			count: 1
 			path: src/RequestFactory.php
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 130f2a7..ce5cd50 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -3,12 +3,17 @@ includes:
     - phpstan-baseline.neon
 
 parameters:
-    level: max
+    level: 8
     paths:
         - src
-    excludePaths:
-        - src/RequestFactoriesServiceProvider.php
+        - config
     tmpDir: build/phpstan
     checkModelProperties: true
     parallel:
             processTimeout: 300.0
+
+    ignoreErrors:
+      -
+        identifier: larastan.noEnvCallsOutsideOfConfig
+        path: config
+        reportUnmatched: false
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index cf5cabc..d921fea 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,8 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" executionOrder="random" failOnWarning="true" failOnRisky="true" failOnEmptyTestSuite="true" beStrictAboutOutputDuringTests="true" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
-  <testsuites>
-    <testsuite name="Worksome Test Suite">
-      <directory>tests</directory>
-    </testsuite>
-  </testsuites>
+<phpunit
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
+    bootstrap="vendor/autoload.php"
+    colors="true"
+    cacheDirectory=".phpunit.cache"
+>
+    <testsuites>
+        <testsuite name="Test Suite">
+            <directory>tests</directory>
+        </testsuite>
+    </testsuites>
+    <source>
+        <include>
+            <directory suffix=".php">./src</directory>
+        </include>
+    </source>
 </phpunit>
diff --git a/src/Support/ConfigBasedFinder.php b/src/Support/ConfigBasedFinder.php
index 4eb8cad..c3093fb 100644
--- a/src/Support/ConfigBasedFinder.php
+++ b/src/Support/ConfigBasedFinder.php
@@ -25,12 +25,12 @@ public function requestFactoriesLocation(string $name = ''): string
 
     public function requestFactoriesNamespace(): string
     {
-        return strval($this->config['namespace'] ?? 'Tests\\RequestFactories'); // @phpstan-ignore argument.type
+        return strval($this->config['namespace'] ?? 'Tests\\RequestFactories');
     }
 
     private function getName(): string
     {
-        return strval($this->config['path'] ?? 'tests/RequestFactories'); // @phpstan-ignore argument.type
+        return strval($this->config['path'] ?? 'tests/RequestFactories');
     }
 
     private function withCorrectSeparator(string $path): string