diff --git a/.github/actions/php/action.yml b/.github/actions/php/action.yml index d3ae8d887..c1f94214d 100644 --- a/.github/actions/php/action.yml +++ b/.github/actions/php/action.yml @@ -16,11 +16,6 @@ inputs: required: false type: string default: "" - tools: - description: "Should tools be installed via composer or not (default `true`)" - required: false - type: boolean - default: true runs: using: composite @@ -54,13 +49,6 @@ runs: with: working-directory: ${{ inputs.working-directory }} - - name: Install tools - if: ${{ inputs.tools == 'true' || inputs.tools == 1 }} # https://github.com/actions/runner/issues/1483 - shell: bash - working-directory: ${{ inputs.working-directory }} - run: | - composer bin all install - - name: Setup problem matchers shell: bash run: | diff --git a/.github/actions/tool/action.yml b/.github/actions/tool/action.yml new file mode 100644 index 000000000..9833d2f6c --- /dev/null +++ b/.github/actions/tool/action.yml @@ -0,0 +1,27 @@ +name: 'Install Tool' +description: 'Install Tool (requires PHP to be installed first)' + +inputs: + tool: + description: "Tool to install." + required: true + type: string + working-directory: + description: "The directory where `composer.json` is located (default repository root)." + required: false + type: string + default: "" + +runs: + using: composite + steps: + - name: Detect path + id: path + shell: bash + working-directory: ${{ inputs.working-directory }} + run: | + echo "value=$(jq '.extra."bamarni-bin"."target-directory" // "vendor-bin"' -r -c composer.json)" >> $GITHUB_OUTPUT + - name: Install + uses: ramsey/composer-install@v3 + with: + working-directory: ${{ inputs.working-directory && inputs.working-directory || '.' }}/${{ steps.path.outputs.value }}/${{ inputs.tool }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9479cce42..95ffcc84a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,15 +27,45 @@ jobs: uses: actions/checkout@v4 - name: Install PHP uses: ./.github/actions/php + with: + dependencies: false + - name: Prepare + run: | + # Unwanted + # (because will install whole "laravel/framework") + composer remove --no-interaction --no-progress --ansi --no-update "orchestra/testbench" + composer remove --no-interaction --no-progress --ansi --no-update --dev "orchestra/testbench" + - name: Install dependencies + uses: ramsey/composer-install@v3 + + - name: Install monorepo-builder + uses: ./.github/actions/tool + with: + tool: monorepo-builder - name: Check package versions run: | composer run-script monorepo-builder + + - name: Install composer-dependency-analyser + uses: ./.github/actions/tool + with: + tool: composer-dependency-analyser - name: Check dependencies run: | composer run-script composer-dependency-analyser + + - name: Install composer-require-checker + uses: ./.github/actions/tool + with: + tool: composer-require-checker - name: Check packages run: | composer run-script composer-require-checker + + - name: Install composer-unused + uses: ./.github/actions/tool + with: + tool: composer-unused - name: Check unused packages run: | composer run-script composer-unused @@ -55,26 +85,50 @@ jobs: uses: actions/checkout@v4 - name: Install PHP uses: ./.github/actions/php - - name: Composer repositories + with: + dependencies: false + - name: Prepare shell: bash working-directory: ${{ needs.settings.outputs.packages-directory }}/${{ matrix.package }} run: | + # Unwanted + # (because will install whole "laravel/framework") + composer remove --no-interaction --no-progress --ansi --no-update "orchestra/testbench" + composer remove --no-interaction --no-progress --ansi --no-update --dev "orchestra/testbench" + + # Repositories for packages + # (because we need local version of the packages) PACKAGES=$(echo '${{ needs.settings.outputs.packages-names }}' | jq 'map(select(. != "${{ matrix.package }}"))' | jq -c -r '.[]' | tr -d '\r') while IFS= read -r PKG do composer config "repositories.${PKG}" path "../${PKG}" done <<< "${PACKAGES}" - - name: Install package dependencies + - name: Install dependencies uses: ramsey/composer-install@v3 with: working-directory: ${{ needs.settings.outputs.packages-directory }}/${{ matrix.package }} + + - name: Install composer-dependency-analyser + uses: ./.github/actions/tool + with: + tool: composer-dependency-analyser - name: Check dependencies run: | composer run-script composer-dependency-analyser -- --composer-json="${{ needs.settings.outputs.packages-directory }}/${{ matrix.package }}/composer.json" + + - name: Install composer-require-checker + uses: ./.github/actions/tool + with: + tool: composer-require-checker - name: Check packages run: | composer run-script composer-require-checker -- "${{ needs.settings.outputs.packages-directory }}/${{ matrix.package }}/composer.json" + + - name: Install composer-unused + uses: ./.github/actions/tool + with: + tool: composer-unused - name: Check unused packages run: | composer run-script composer-unused -- "${{ needs.settings.outputs.packages-directory }}/${{ matrix.package }}/composer.json" @@ -87,6 +141,10 @@ jobs: uses: actions/checkout@v4 - name: Install PHP uses: ./.github/actions/php + - name: Install phpcs + uses: ./.github/actions/tool + with: + tool: phpcs - name: Execute run: | composer run-script phpcs -- --report=checkstyle | cs2pr @@ -99,6 +157,10 @@ jobs: uses: actions/checkout@v4 - name: Install PHP uses: ./.github/actions/php + - name: Install phpstan + uses: ./.github/actions/tool + with: + tool: phpstan - name: Execute run: | composer run-script phpstan -- --error-format=checkstyle | cs2pr diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index a46e678ce..0873e6d1c 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -38,6 +38,7 @@ jobs: php-versions: ${{ steps.settings.outputs.php-versions }} dependencies: ${{ steps.settings.outputs.dependencies }} laravel-versions: ${{ steps.settings.outputs.laravel-versions }} + laravel-packages: ${{ steps.settings.outputs.laravel-packages }} optional-packages: ${{ steps.settings.outputs.optional-packages }} steps: - name: Checkout @@ -48,7 +49,6 @@ jobs: with: working-directory: ${{ env.WORKING_DIRECTORY }} dependencies: false - tools: false - name: Collect Settings id: settings @@ -65,7 +65,8 @@ jobs: echo "dependencies=$(echo "[\"$DEPS_HIGHEST\", \"$DEPS_LOCKED\", \"$DEPS_LOWEST\"]" | jq "[.[] | select(length > 0)]" -r -c)" >> $GITHUB_OUTPUT # Laravel - echo "laravel-versions=$(jq '.require."laravel/framework" // "null" | split("|") | sort' -c composer.json)" >> $GITHUB_OUTPUT + echo "laravel-versions=$(jq '.require | to_entries | map(select( (.key | startswith("illuminate/")) or (.key == "laravel/framework "))) | map( .value | split("|") ) | flatten | unique | sort | if . == [] then ["null"] else . end' -c composer.json)" >> $GITHUB_OUTPUT + echo "laravel-packages=$(jq '.require + ."require-dev" | to_entries | map(select( (.key | startswith("illuminate/")) or (.key == "laravel/framework "))) | map( .key ) | flatten | unique | sort ' -c composer.json)" >> $GITHUB_OUTPUT # Optional packages echo "optional-packages=$(jq '([((."extra"."lara-asp"."ci"."optional-packages" // ["null"]) | flatten | unique | sort | join(","))] + ["null"]) | unique' -r -c composer.json)" >> $GITHUB_OUTPUT @@ -112,7 +113,6 @@ jobs: with: version: ${{ matrix.php }} dependencies: false - tools: false working-directory: ${{ env.WORKING_DIRECTORY }} # Required to resolve packages correctly. @@ -135,9 +135,13 @@ jobs: shell: bash working-directory: ${{ env.WORKING_DIRECTORY }} run: | - composer remove --no-interaction --no-progress --ansi --no-update laravel/framework - composer require --no-interaction --no-progress --ansi --no-update "laravel/framework:${{ matrix.laravel }}" - composer remove --no-interaction --no-progress --ansi --no-update --dev larastan/larastan + PACKAGES=$(echo '${{ needs.settings.outputs.laravel-packages }}' | jq -c -r '.[]' | tr -d '\r') + + while IFS= read -r PKG + do + # It will move package to `require` section, not critical here + composer require --no-interaction --no-progress --ansi --no-update "${PKG}:${{ matrix.laravel }}" + done <<< "${PACKAGES}" - name: Remove optional packages if: ${{ matrix.optional != 'null' }} diff --git a/Vagrantfile b/Vagrantfile index 418052a80..b2ab30aba 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -140,14 +140,14 @@ EOT fi SHELL - config.vm.provision "PHP 8.1", type: "shell", privileged: false, inline: <<-SHELL + config.vm.provision "PHP 8.3", type: "shell", privileged: false, inline: <<-SHELL sudo add-apt-repository -y ppa:ondrej/php - sudo apt-get install -y php8.1-{cli,common,mbstring,bcmath,zip,intl,mbstring,xml,xdebug,curl,gd,imagick,ldap,pdo-sqlite} - sudo sed -i 's/^error_reporting = .\+$/error_reporting = E_ALL/' /etc/php/8.1/cli/php.ini - sudo sed -i 's/^display_errors = .\+$/display_errors = On/' /etc/php/8.1/cli/php.ini - sudo sed -i 's/^;opcache\.enable=.\+$/opcache.enable=1/' /etc/php/8.1/cli/php.ini - sudo sed -i 's/^;opcache\.enable_cli=.\+$/opcache.enable_cli=1/' /etc/php/8.1/cli/php.ini - sudo tee -a /etc/php/8.1/mods-available/xdebug.ini > /dev/null <<"EOT" + sudo apt-get install -y php8.3-{cli,common,mbstring,bcmath,zip,intl,mbstring,xml,xdebug,curl,pdo-sqlite} + sudo sed -i 's/^error_reporting = .\+$/error_reporting = E_ALL/' /etc/php/8.3/cli/php.ini + sudo sed -i 's/^display_errors = .\+$/display_errors = On/' /etc/php/8.3/cli/php.ini + sudo sed -i 's/^;opcache\.enable=.\+$/opcache.enable=1/' /etc/php/8.3/cli/php.ini + sudo sed -i 's/^;opcache\.enable_cli=.\+$/opcache.enable_cli=1/' /etc/php/8.3/cli/php.ini + sudo tee -a /etc/php/8.3/mods-available/xdebug.ini > /dev/null <<"EOT" xdebug.output_dir = /project/.xdebug xdebug.profiler_output_name = callgrind.out.%t.%r xdebug.client_host = 10.0.2.2 @@ -172,7 +172,7 @@ EOT config.vm.provision "composer install", type: "shell", privileged: false, inline: <<-SHELL if test -f "/project/composer.json"; then (cd /project && composer install) - (cs /project && composer bin all install) + (cd /project && composer bin all install) fi SHELL diff --git a/composer-dependency-analyser.php b/composer-dependency-analyser.php index 81ae3ef2b..03e32c82e 100644 --- a/composer-dependency-analyser.php +++ b/composer-dependency-analyser.php @@ -1,6 +1,10 @@ enableAnalysisOfUnusedDevDependencies() - ->disableReportingUnmatchedIgnores() - ->ignoreUnknownClasses([ - Example::class, - ]) + ->ignoreErrorsOnPackage('symfony/deprecation-contracts', [ErrorType::UNUSED_DEPENDENCY]) ->ignoreErrorsOnPackage('symfony/polyfill-php83', [ErrorType::UNUSED_DEPENDENCY]) + ->ignoreErrorsOnPackage('symfony/var-dumper', [ErrorType::UNUSED_DEPENDENCY]) ->ignoreErrorsOnPackage('bamarni/composer-bin-plugin', [ErrorType::UNUSED_DEPENDENCY]) - ->ignoreErrorsOnPackage('orchestra/testbench', [ErrorType::UNUSED_DEPENDENCY]) - ->ignoreErrorsOnPackage('orchestra/testbench-core', [ErrorType::SHADOW_DEPENDENCY]) - ->ignoreErrorsOnPackage('phpstan/phpstan', [ErrorType::SHADOW_DEPENDENCY]) - ->ignoreErrorsOnPackage('laravel/scout', [ErrorType::DEV_DEPENDENCY_IN_PROD]); + ->ignoreErrorsOnPackage('laravel/scout', [ErrorType::DEV_DEPENDENCY_IN_PROD]) + ->ignoreUnknownClasses([ + FormRequest::class, + RefreshDatabase::class, + RefreshDatabaseState::class, + TestCase::class, + TestbenchTestCase::class, + ]); + +// Load composer.json +$path = Path::resolve($this->cwd, ($options->composerJson ?? 'composer.json')); +$json = (string) file_get_contents($path); +$json = json_decode($json, true, JSON_THROW_ON_ERROR); +$root = Path::realpath(dirname(__FILE__).'/composer.json') === Path::realpath($path); + +if (!$root) { + $config->disableReportingUnmatchedIgnores(); +} // Configure paths // // In our case, tests located inside the same directory with class and // `exclude-from-classmap` is used to exclude them from the class map. // So we need to mark these excluded files as "dev". -$path = Path::resolve($this->cwd, ($options->composerJson ?? 'composer.json')); -$json = (string) file_get_contents($path); -$json = json_decode($json, true, JSON_THROW_ON_ERROR); +// +// Also, we don't want to check examples. The `autoload-dev.exclude-from-classmap` +// can be used to ignore them. $excluded = $json['autoload']['exclude-from-classmap'] ?? []; +$ignored = $json['autoload-dev']['exclude-from-classmap'] ?? []; -if ($excluded) { - $config = $config->disableComposerAutoloadPathScan(); - $regexp = array_map( - static function (string $exclude) use ($path): string { - // Similar to how composer process it, but not the exact match. - $exclude = dirname($path)."/{$exclude}"; - $exclude = preg_replace('{/+}', '/', preg_quote(trim(strtr($exclude, '\\', '/'), '/'))); - $exclude = strtr($exclude, ['\\*\\*' => '.+?', '\\*' => '[^/]+?']); +if ($excluded || $ignored) { + $config = $config->disableComposerAutoloadPathScan(); + $regexp = static function (array $excluded) use ($path): ?string { + $regexp = array_map( + static function (string $exclude) use ($path): string { + // Similar to how composer process it, but not the exact match. + $exclude = dirname($path)."/{$exclude}"; + $exclude = preg_replace('{/+}', '/', preg_quote(trim(strtr($exclude, '\\', '/'), '/'))); + $exclude = strtr($exclude, ['\\*\\*' => '.+?', '\\*' => '[^/]+?']); - return $exclude; - }, - $excluded, - ); - $regexp = '{('.implode(')|(', $regexp).')}'; + return $exclude; + }, + $excluded, + ); + $regexp = $regexp + ? '{('.implode(')|(', $regexp).')}' + : null; - foreach ($composerJson->autoloadPaths as $absolutePath => $isDevPath) { - if ($isDevPath) { - $config = $config->addPathToScan($absolutePath, $isDevPath); - } elseif (is_file($absolutePath)) { - $config = $config->addPathToScan($absolutePath, (bool) preg_match($regexp, $absolutePath)); + return $regexp; + }; + $ignored = $regexp($ignored); + $excluded = $regexp($excluded); + $processor = static function (string $path, bool $isDev) use (&$processor, $config, $excluded, $ignored): void { + if (is_file($path)) { + $isDev = $isDev || ($excluded && (bool) preg_match($excluded, $path)); + $isIgnored = $isDev && ($ignored && (bool) preg_match($ignored, $path)); + + if (!$isIgnored) { + $config->addPathToScan($path, $isDev); + } } else { - $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($absolutePath)); + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); foreach ($iterator as $entry) { if (!$entry->isFile() || !in_array($entry->getExtension(), $config->getFileExtensions(), true)) { continue; } - $entryPath = $entry->getPathname(); - $config = $config->addPathToScan($entryPath, (bool) preg_match($regexp, $entryPath)); + $processor($entry->getPathname(), $isDev); } } + }; + + foreach ($composerJson->autoloadPaths as $absolutePath => $isDevPath) { + $processor($absolutePath, $isDevPath); } } diff --git a/composer-require-checker.json b/composer-require-checker.json index 490eaabc9..112d8b825 100644 --- a/composer-require-checker.json +++ b/composer-require-checker.json @@ -1,6 +1,10 @@ { "symbol-whitelist": [ "Composer\\InstalledVersions", - "Laravel\\Scout\\Builder" + "Laravel\\Scout\\Builder", + "Illuminate\\Foundation\\Http\\FormRequest", + "Illuminate\\Foundation\\Testing\\RefreshDatabase", + "Illuminate\\Foundation\\Testing\\RefreshDatabaseState", + "Illuminate\\Foundation\\Testing\\TestCase" ] } diff --git a/composer.json b/composer.json index d69d3ad18..a8a9fb74d 100644 --- a/composer.json +++ b/composer.json @@ -36,17 +36,31 @@ "php": "^8.1|^8.2|^8.3", "ext-bcmath": "*", "ext-dom": "*", - "ext-intl": "*", "ext-filter": "*", + "ext-intl": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xmlreader": "*", "composer/semver": "^3.2", "doctrine/sql-formatter": "^1.1", + "illuminate/console": "^10.34.0", + "illuminate/container": "^10.34.0", + "illuminate/contracts": "^10.34.0", + "illuminate/support": "^10.34.0", + "illuminate/collections": "^10.34.0", + "illuminate/database": "^10.34.0", + "illuminate/macroable": "^10.34.0", + "illuminate/filesystem": "^10.34.0", + "illuminate/http": "^10.34.0", + "illuminate/pagination": "^10.34.0", + "illuminate/process": "^10.34.0", + "illuminate/routing": "^10.34.0", + "illuminate/validation": "^10.34.0", + "illuminate/testing": "^10.34.0", + "illuminate/translation": "^10.34.0", "guzzlehttp/psr7": "^1.9.1|^2.4.5", "http-interop/http-factory-guzzle": "^1.0.0", - "laravel/framework": "^10.34.0", "league/commonmark": "^2.4", "mockery/mockery": "^1.6.2", "nikic/php-parser": "^4.18|^5.0", @@ -59,6 +73,7 @@ "sebastian/comparator": "^5.0", "sebastian/exporter": "^5.0", "symfony/console": "^6.3.0", + "symfony/deprecation-contracts": "^3.0.0", "symfony/filesystem": "^6.3.0", "symfony/finder": "^6.3.0", "symfony/http-foundation": "^6.3.0", @@ -75,6 +90,8 @@ "ext-pdo_sqlite": "*", "bamarni/composer-bin-plugin": "^1.8", "composer/class-map-generator": "^1.0", + "illuminate/cache": "^10.34.0", + "fakerphp/faker": "^1.21.0", "laravel/scout": "^9.8.0|^10.0.0", "orchestra/testbench": "^8.0.0", "symfony/var-dumper": "^6.3.0" @@ -120,7 +137,8 @@ "LastDragon_ru\\LaraASP\\Testing\\Docs\\": "packages/testing/docs" }, "exclude-from-classmap": [ - "packages/*/docs" + "packages/*/docs", + "dev/**.php" ] }, "extra": { @@ -131,7 +149,8 @@ "LastDragon_ru\\LaraASP\\Spa\\Provider", "LastDragon_ru\\LaraASP\\GraphQL\\Provider", "LastDragon_ru\\LaraASP\\Serializer\\Provider", - "LastDragon_ru\\LaraASP\\Documentator\\Provider" + "LastDragon_ru\\LaraASP\\Documentator\\Provider", + "LastDragon_ru\\LaraASP\\Eloquent\\Provider" ] }, "bamarni-bin": { @@ -143,6 +162,9 @@ "required-extensions": { "league/flysystem": [ "ext-fileinfo" + ], + "illuminate/console": [ + "ext-mbstring" ] }, "optional-packages": { @@ -154,10 +176,6 @@ } }, "scripts": { - "validate:release": [ - "@validate:dependencies", - "@validate:commit" - ], "validate:commit": [ "@phpstan", "@phpunit", diff --git a/dev/App/Example.php b/dev/App/Example.php index 2b2085c4c..755c6a7a4 100644 --- a/dev/App/Example.php +++ b/dev/App/Example.php @@ -21,7 +21,6 @@ use function array_map; use function array_slice; -use function config; use function debug_backtrace; use function end; use function file; @@ -106,10 +105,11 @@ public static function config(string $root, array $settings): void { self::getDumper(); // Update - $config = (array) config($root, []); - $config = (new ConfigMerger())->merge([ConfigMerger::Strict => false], $config, $settings); + $repository = Container::getInstance()->make(Repository::class); + $config = (array) $repository->get($root, []); + $config = (new ConfigMerger())->merge([ConfigMerger::Strict => false], $config, $settings); - config([ + $repository->set([ $root => $config, ]); } diff --git a/metadata.json b/metadata.json index 571c6d55f..1e74d1deb 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,7 @@ { "version": "6.1.0", "require": [], + "merge": null, "requirements": { "HEAD": { "laravel/framework": [ diff --git a/packages/core/composer.json b/packages/core/composer.json index 34c2f7d9f..6820e053a 100644 --- a/packages/core/composer.json +++ b/packages/core/composer.json @@ -19,11 +19,13 @@ }, "require": { "php": "^8.1|^8.2|^8.3", - "ext-mbstring": "*", - "laravel/framework": "^10.34.0", + "illuminate/console": "^10.34.0", + "illuminate/container": "^10.34.0", + "illuminate/contracts": "^10.34.0", "symfony/polyfill-php83": "^1.28" }, "require-dev": { + "illuminate/support": "^10.34.0", "phpunit/phpunit": "^10.1.0", "lastdragon-ru/lara-asp-testing": "self.version", "mockery/mockery": "^1.6.2", @@ -52,6 +54,9 @@ "required-extensions": { "league/flysystem": [ "ext-fileinfo" + ], + "illuminate/console": [ + "ext-mbstring" ] } } diff --git a/packages/core/metadata.json b/packages/core/metadata.json index d09aaa224..46af61d16 100644 --- a/packages/core/metadata.json +++ b/packages/core/metadata.json @@ -1,6 +1,7 @@ { "version": "6.1.0", "require": [], + "merge": null, "requirements": { "HEAD": { "laravel/framework": [ diff --git a/packages/core/src/Provider/WithConfig.php b/packages/core/src/Provider/WithConfig.php index 80438e9ce..d1666a92f 100644 --- a/packages/core/src/Provider/WithConfig.php +++ b/packages/core/src/Provider/WithConfig.php @@ -2,12 +2,12 @@ namespace LastDragon_ru\LaraASP\Core\Provider; +use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use Illuminate\Contracts\Foundation\CachesConfiguration; use Illuminate\Support\ServiceProvider; use LastDragon_ru\LaraASP\Core\Utils\ConfigMerger; -use function config; - /** * @mixin ServiceProvider */ @@ -26,11 +26,12 @@ protected function bootConfig(): void { protected function loadConfigFrom(string $path, string $key): void { if (!($this->app instanceof CachesConfiguration && $this->app->configurationIsCached())) { - $merger = new ConfigMerger(); - $target = (array) require $path; - $current = (array) config($key, []); + $repository = Container::getInstance()->make(Repository::class); + $merger = new ConfigMerger(); + $target = (array) require $path; + $current = (array) $repository->get($key, []); - config([ + $repository->set([ $key => $merger->merge($target, $current), ]); } diff --git a/packages/documentator/UPGRADE.md b/packages/documentator/UPGRADE.md index 80066b1a4..e11f0898a 100644 --- a/packages/documentator/UPGRADE.md +++ b/packages/documentator/UPGRADE.md @@ -39,7 +39,7 @@ Please also see [changelog](https://github.com/LastDragon-ru/lara-asp/releases) * [ ] Replace `LastDragon_ru\LaraASP\Documentator\Preprocessor\InstructionContract` by `LastDragon_ru\LaraASP\Documentator\Preprocessor\Contracts\ProcessableInstruction` or `LastDragon_ru\LaraASP\Documentator\Preprocessor\Contracts\ParameterizableInstruction`. -* [ ] Use [`Illuminate\Support\Facades\Process`](https://laravel.com/docs/processes) instead of `LastDragon_ru\LaraASP\Documentator\Utils\Process`. +* [ ] Use [`illuminate/process`](https://laravel.com/docs/processes) instead of `LastDragon_ru\LaraASP\Documentator\Utils\Process`. * [ ] If you are extending built-in instructions, their classes were moved to `LastDragon_ru\LaraASP\Documentator\Preprocessor\Instructions\\Instruction` namespace. diff --git a/packages/documentator/composer.json b/packages/documentator/composer.json index b9d0af749..e9d83d54f 100644 --- a/packages/documentator/composer.json +++ b/packages/documentator/composer.json @@ -21,7 +21,11 @@ "php": "^8.1|^8.2|^8.3", "ext-mbstring": "*", "composer/semver": "^3.2", - "laravel/framework": "^10.34.0", + "illuminate/console": "^10.34.0", + "illuminate/container": "^10.34.0", + "illuminate/contracts": "^10.34.0", + "illuminate/process": "^10.34.0", + "illuminate/support": "^10.34.0", "league/commonmark": "^2.4", "nikic/php-parser": "^4.18|^5.0", "phpstan/phpdoc-parser": "^1.25", @@ -67,6 +71,9 @@ "required-extensions": { "league/flysystem": [ "ext-fileinfo" + ], + "illuminate/console": [ + "ext-mbstring" ] } } diff --git a/packages/documentator/metadata.json b/packages/documentator/metadata.json index fbad1415e..b73362471 100644 --- a/packages/documentator/metadata.json +++ b/packages/documentator/metadata.json @@ -1,6 +1,7 @@ { "version": "6.1.0", "require": [], + "merge": null, "requirements": { "HEAD": { "laravel/framework": [ diff --git a/packages/documentator/src/Preprocessor/Instructions/IncludeExample/Instruction.php b/packages/documentator/src/Preprocessor/Instructions/IncludeExample/Instruction.php index 0856bf9a7..1bf688bb0 100644 --- a/packages/documentator/src/Preprocessor/Instructions/IncludeExample/Instruction.php +++ b/packages/documentator/src/Preprocessor/Instructions/IncludeExample/Instruction.php @@ -3,7 +3,8 @@ namespace LastDragon_ru\LaraASP\Documentator\Preprocessor\Instructions\IncludeExample; use Exception; -use Illuminate\Support\Facades\Process; +use Illuminate\Container\Container; +use Illuminate\Process\Factory; use LastDragon_ru\LaraASP\Documentator\Preprocessor\Contracts\ProcessableInstruction; use LastDragon_ru\LaraASP\Documentator\Preprocessor\Exceptions\TargetExecFailed; use LastDragon_ru\LaraASP\Documentator\Preprocessor\Exceptions\TargetIsNotFile; @@ -25,9 +26,10 @@ class Instruction implements ProcessableInstruction { public const Limit = 50; protected const MarkdownRegexp = '/^\<(?Pmarkdown)\>(?P.*?)\<\/(?P=tag)\>$/msu'; + protected readonly Factory $factory; public function __construct() { - // empty + $this->factory = Container::getInstance()->make(Factory::class); // next(documentator): Inject in constructor } #[Override] @@ -76,7 +78,7 @@ public function process(string $path, string $target): string { if ($command) { // Call try { - $output = Process::path(dirname($path))->run($command)->throw()->output(); + $output = $this->factory->newPendingProcess()->path(dirname($path))->run($command)->throw()->output(); $output = trim($output); } catch (Exception $exception) { throw new TargetExecFailed($path, $target, $exception); diff --git a/packages/documentator/src/Preprocessor/Instructions/IncludeExample/InstructionTest.php b/packages/documentator/src/Preprocessor/Instructions/IncludeExample/InstructionTest.php index 988ae9ebe..226d110fc 100644 --- a/packages/documentator/src/Preprocessor/Instructions/IncludeExample/InstructionTest.php +++ b/packages/documentator/src/Preprocessor/Instructions/IncludeExample/InstructionTest.php @@ -3,8 +3,8 @@ namespace LastDragon_ru\LaraASP\Documentator\Preprocessor\Instructions\IncludeExample; use Illuminate\Container\Container; +use Illuminate\Process\Factory; use Illuminate\Process\PendingProcess; -use Illuminate\Support\Facades\Process; use LastDragon_ru\LaraASP\Documentator\Testing\Package\TestCase; use PHPUnit\Framework\Attributes\CoversClass; @@ -23,11 +23,13 @@ public function testProcessNoRun(): void { $path = self::getTestData()->path('~example.md'); $file = basename(self::getTestData()->path('~example.md')); $expected = trim(self::getTestData()->content('~example.md')); + $factory = $this->override(Factory::class, static function (): Factory { + return Container::getInstance()->make(Factory::class) + ->preventStrayProcesses() + ->fake(); + }); $instance = Container::getInstance()->make(Instruction::class); - Process::preventStrayProcesses(); - Process::fake(); - self::assertEquals( <<process($path, $file), ); - Process::assertNothingRan(); + $factory->assertNothingRan(); } public function testProcess(): void { @@ -46,13 +48,17 @@ public function testProcess(): void { $command = self::getTestData()->path('~runnable.run'); $expected = trim(self::getTestData()->content('~runnable.md')); $output = 'command output'; + $factory = $this->override(Factory::class, static function () use ($command, $output): Factory { + $factory = Container::getInstance()->make(Factory::class); + $factory->preventStrayProcesses(); + $factory->fake([ + $command => $factory->result($output), + ]); + + return $factory; + }); $instance = Container::getInstance()->make(Instruction::class); - Process::preventStrayProcesses(); - Process::fake([ - $command => Process::result($output), - ]); - self::assertEquals( <<process($path, $file), ); - Process::assertRan(static function (PendingProcess $process) use ($path, $command): bool { + $factory->assertRan(static function (PendingProcess $process) use ($path, $command): bool { return $process->path === dirname($path) && $process->command === $command; }); @@ -80,13 +86,17 @@ public function testProcessLongOutput(): void { $command = self::getTestData()->path('~runnable.run'); $expected = trim(self::getTestData()->content('~runnable.md')); $output = implode("\n", range(0, Instruction::Limit + 1)); + $factory = $this->override(Factory::class, static function () use ($command, $output): Factory { + $factory = Container::getInstance()->make(Factory::class); + $factory->preventStrayProcesses(); + $factory->fake([ + $command => $factory->result($output), + ]); + + return $factory; + }); $instance = Container::getInstance()->make(Instruction::class); - Process::preventStrayProcesses(); - Process::fake([ - $command => Process::result($output), - ]); - self::assertEquals( <<process($path, $file), ); - Process::assertRan(static function (PendingProcess $process) use ($path, $command): bool { + $factory->assertRan(static function (PendingProcess $process) use ($path, $command): bool { return $process->path === dirname($path) && $process->command === $command; }); @@ -116,13 +126,17 @@ public function testProcessMarkdown(): void { $command = self::getTestData()->path('~runnable.run'); $expected = trim(self::getTestData()->content('~runnable.md')); $output = 'command output'; + $factory = $this->override(Factory::class, static function () use ($command, $output): Factory { + $factory = Container::getInstance()->make(Factory::class); + $factory->preventStrayProcesses(); + $factory->fake([ + $command => $factory->result("{$output}"), + ]); + + return $factory; + }); $instance = Container::getInstance()->make(Instruction::class); - Process::preventStrayProcesses(); - Process::fake([ - $command => Process::result("{$output}"), - ]); - self::assertEquals( <<process($path, $file), ); - Process::assertRan(static function (PendingProcess $process) use ($path, $command): bool { + $factory->assertRan(static function (PendingProcess $process) use ($path, $command): bool { return $process->path === dirname($path) && $process->command === $command; }); @@ -146,13 +160,17 @@ public function testProcessMarkdownLongOutput(): void { $command = self::getTestData()->path('~runnable.run'); $expected = trim(self::getTestData()->content('~runnable.md')); $output = implode("\n", range(0, Instruction::Limit + 1)); + $factory = $this->override(Factory::class, static function () use ($command, $output): Factory { + $factory = Container::getInstance()->make(Factory::class); + $factory->preventStrayProcesses(); + $factory->fake([ + $command => $factory->result("{$output}"), + ]); + + return $factory; + }); $instance = Container::getInstance()->make(Instruction::class); - Process::preventStrayProcesses(); - Process::fake([ - $command => Process::result("{$output}"), - ]); - self::assertEquals( <<process($path, $file), ); - Process::assertRan(static function (PendingProcess $process) use ($path, $command): bool { + $factory->assertRan(static function (PendingProcess $process) use ($path, $command): bool { return $process->path === dirname($path) && $process->command === $command; }); diff --git a/packages/documentator/src/Preprocessor/Instructions/IncludeExec/Instruction.php b/packages/documentator/src/Preprocessor/Instructions/IncludeExec/Instruction.php index b52ae4751..90f7311c3 100644 --- a/packages/documentator/src/Preprocessor/Instructions/IncludeExec/Instruction.php +++ b/packages/documentator/src/Preprocessor/Instructions/IncludeExec/Instruction.php @@ -3,7 +3,8 @@ namespace LastDragon_ru\LaraASP\Documentator\Preprocessor\Instructions\IncludeExec; use Exception; -use Illuminate\Support\Facades\Process; +use Illuminate\Container\Container; +use Illuminate\Process\Factory; use LastDragon_ru\LaraASP\Documentator\Preprocessor\Contracts\ProcessableInstruction; use LastDragon_ru\LaraASP\Documentator\Preprocessor\Exceptions\TargetExecFailed; use Override; @@ -12,8 +13,10 @@ use function trim; class Instruction implements ProcessableInstruction { + protected readonly Factory $factory; + public function __construct() { - // empty + $this->factory = Container::getInstance()->make(Factory::class); // next(documentator): Inject in constructor } #[Override] @@ -34,7 +37,7 @@ public static function getTargetDescription(): ?string { #[Override] public function process(string $path, string $target): string { try { - return trim(Process::path(dirname($path))->run($target)->throw()->output()); + return trim($this->factory->newPendingProcess()->path(dirname($path))->run($target)->throw()->output()); } catch (Exception $exception) { throw new TargetExecFailed($path, $target, $exception); } diff --git a/packages/documentator/src/Preprocessor/Instructions/IncludeExec/InstructionTest.php b/packages/documentator/src/Preprocessor/Instructions/IncludeExec/InstructionTest.php index 4d51b5792..41e85f3ae 100644 --- a/packages/documentator/src/Preprocessor/Instructions/IncludeExec/InstructionTest.php +++ b/packages/documentator/src/Preprocessor/Instructions/IncludeExec/InstructionTest.php @@ -3,8 +3,8 @@ namespace LastDragon_ru\LaraASP\Documentator\Preprocessor\Instructions\IncludeExec; use Illuminate\Container\Container; +use Illuminate\Process\Factory; use Illuminate\Process\PendingProcess; -use Illuminate\Support\Facades\Process; use LastDragon_ru\LaraASP\Documentator\Testing\Package\TestCase; use PHPUnit\Framework\Attributes\CoversClass; @@ -19,16 +19,20 @@ public function testProcess(): void { $path = 'current/working/directory/file.md'; $expected = 'result'; $command = 'command to execute'; - $instance = Container::getInstance()->make(Instruction::class); + $factory = $this->override(Factory::class, static function () use ($command, $expected): Factory { + $factory = Container::getInstance()->make(Factory::class); + $factory->preventStrayProcesses(); + $factory->fake([ + $command => $factory->result($expected), + ]); - Process::preventStrayProcesses(); - Process::fake([ - $command => Process::result($expected), - ]); + return $factory; + }); + $instance = Container::getInstance()->make(Instruction::class); self::assertEquals($expected, $instance->process($path, $command)); - Process::assertRan(static function (PendingProcess $process) use ($path, $command): bool { + $factory->assertRan(static function (PendingProcess $process) use ($path, $command): bool { return $process->path === dirname($path) && $process->command === $command; }); diff --git a/packages/documentator/src/Utils/Git.php b/packages/documentator/src/Utils/Git.php index b7bc24d10..bb387ec45 100644 --- a/packages/documentator/src/Utils/Git.php +++ b/packages/documentator/src/Utils/Git.php @@ -2,7 +2,8 @@ namespace LastDragon_ru\LaraASP\Documentator\Utils; -use Illuminate\Support\Facades\Process; +use Illuminate\Container\Container; +use Illuminate\Process\Factory; use function array_filter; use function array_values; @@ -10,8 +11,10 @@ use function trim; class Git { + protected readonly Factory $factory; + public function __construct() { - // empty + $this->factory = Container::getInstance()->make(Factory::class); // next(documentator): Inject in constructor } /** @@ -44,7 +47,8 @@ public function getRoot(string $root = null): string { * @param array|string $command */ private function run(array|string $command, string $root = null): string { - $process = $root !== null ? Process::path($root) : Process::command(''); + $process = $this->factory->newPendingProcess(); + $process = $root !== null ? $process->path($root) : $process->command(''); $output = $process->run($command)->throw()->output(); $output = trim($output); diff --git a/packages/eloquent/composer.json b/packages/eloquent/composer.json index af242d027..95f9c9284 100644 --- a/packages/eloquent/composer.json +++ b/packages/eloquent/composer.json @@ -18,12 +18,15 @@ }, "require": { "php": "^8.1|^8.2|^8.3", - "laravel/framework": "^10.34.0", + "illuminate/collections": "^10.34.0", + "illuminate/database": "^10.34.0", + "illuminate/support": "^10.34.0", "lastdragon-ru/lara-asp-core": "self.version", "symfony/polyfill-php83": "^1.28" }, "require-dev": { "ext-pdo_sqlite": "*", + "illuminate/container": "^10.34.0", "lastdragon-ru/lara-asp-testing": "self.version", "mockery/mockery": "^1.6.2", "orchestra/testbench": "^8.0.0", @@ -50,6 +53,11 @@ ] }, "extra": { + "laravel": { + "providers": [ + "LastDragon_ru\\LaraASP\\Eloquent\\Provider" + ] + }, "lara-asp": { "ci": { "required-extensions": { diff --git a/packages/eloquent/metadata.json b/packages/eloquent/metadata.json index 571c6d55f..1e74d1deb 100644 --- a/packages/eloquent/metadata.json +++ b/packages/eloquent/metadata.json @@ -1,6 +1,7 @@ { "version": "6.1.0", "require": [], + "merge": null, "requirements": { "HEAD": { "laravel/framework": [ diff --git a/packages/eloquent/src/Provider.php b/packages/eloquent/src/Provider.php new file mode 100644 index 000000000..50878c341 --- /dev/null +++ b/packages/eloquent/src/Provider.php @@ -0,0 +1,9 @@ +afterApplicationCreated(static function (): void { - $table = (new TestObject())->getTable(); + $schema = Container::getInstance()->make(Builder::class); + $table = (new TestObject())->getTable(); - if (Schema::hasTable($table)) { + if ($schema->hasTable($table)) { return; } - Schema::create($table, static function ($table): void { + $schema->create($table, static function ($table): void { $table->increments('id'); $table->string('value', 40)->nullable(); }); }); } + + /** + * @internal + */ + #[After] + protected function withTestObjectAfter(): void { + $this->beforeApplicationDestroyed(static function (): void { + $schema = Container::getInstance()->make(Builder::class); + $table = (new TestObject())->getTable(); + + if ($schema->hasTable($table)) { + return; + } + + $schema->drop($table); + }); + } } diff --git a/packages/formatter/composer.json b/packages/formatter/composer.json index fb6d0f614..fbf5b62aa 100644 --- a/packages/formatter/composer.json +++ b/packages/formatter/composer.json @@ -22,7 +22,10 @@ "ext-bcmath": "*", "ext-intl": "*", "ext-mbstring": "*", - "laravel/framework": "^10.34.0", + "illuminate/container": "^10.34.0", + "illuminate/contracts": "^10.34.0", + "illuminate/macroable": "^10.34.0", + "illuminate/support": "^10.34.0", "lastdragon-ru/lara-asp-core": "self.version", "symfony/polyfill-php83": "^1.28" }, diff --git a/packages/formatter/metadata.json b/packages/formatter/metadata.json index 571c6d55f..1e74d1deb 100644 --- a/packages/formatter/metadata.json +++ b/packages/formatter/metadata.json @@ -1,6 +1,7 @@ { "version": "6.1.0", "require": [], + "merge": null, "requirements": { "HEAD": { "laravel/framework": [ diff --git a/packages/formatter/src/Formatter.php b/packages/formatter/src/Formatter.php index c57999ff2..b7ec2ed0f 100644 --- a/packages/formatter/src/Formatter.php +++ b/packages/formatter/src/Formatter.php @@ -7,6 +7,7 @@ use DateTimeInterface; use DateTimeZone; use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use Illuminate\Contracts\Foundation\Application; use Illuminate\Support\Str; use Illuminate\Support\Traits\Macroable; @@ -24,7 +25,6 @@ use function abs; use function bccomp; use function bcdiv; -use function config; use function is_float; use function is_int; use function is_null; @@ -451,21 +451,23 @@ protected function getDefaultLocale(): string { } protected function getDefaultTimezone(): IntlTimeZone|DateTimeZone|string|null { - return config('app.timezone') ?: null; + return Container::getInstance()->make(Repository::class)->get('app.timezone') ?: null; } protected function getOptions(string $type, mixed $default = null): mixed { - $package = Package::Name; - $key = "{$package}.options.{$type}"; + $repository = Container::getInstance()->make(Repository::class); + $package = Package::Name; + $key = "{$package}.options.{$type}"; - return config($key, $default); + return $repository->get($key, $default); } protected function getLocaleOptions(string $type, string $option): mixed { - $package = Package::Name; - $locale = $this->getLocale(); - $pattern = config("{$package}.locales.{$locale}.{$type}.{$option}") - ?: config("{$package}.all.{$type}.{$option}"); + $repository = Container::getInstance()->make(Repository::class); + $package = Package::Name; + $locale = $this->getLocale(); + $pattern = $repository->get("{$package}.locales.{$locale}.{$type}.{$option}") + ?: $repository->get("{$package}.all.{$type}.{$option}"); return $pattern; } diff --git a/packages/formatter/src/FormatterTest.php b/packages/formatter/src/FormatterTest.php index 3b63f2b69..56d00df60 100644 --- a/packages/formatter/src/FormatterTest.php +++ b/packages/formatter/src/FormatterTest.php @@ -10,7 +10,6 @@ use Override; use PHPUnit\Framework\Attributes\CoversClass; -use function config; use function pow; use function str_replace; @@ -77,7 +76,7 @@ public function testDecimal(): void { } public function testDecimalConfig(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::Decimal => 4, Package::Name.'.locales.ru_RU.'.Formatter::Decimal.'.'.Formatter::IntlAttributes => [ NumberFormatter::FRACTION_DIGITS => 9, // should be ignored @@ -118,7 +117,7 @@ public function testPercent(): void { } public function testPercentConfig(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::Percent => 2, ]); @@ -131,7 +130,7 @@ public function testDuration(): void { } public function testDurationConfig(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::Duration => NumberFormatter::DURATION, ]); @@ -140,7 +139,7 @@ public function testDurationConfig(): void { } public function testDurationCustomFormat(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::Duration => 'custom', Package::Name.'.all.'.Formatter::Duration.'.custom' => 'mm:ss', Package::Name.'.all.'.Formatter::Duration.'.custom2' => 'H:mm:ss.SSS', @@ -161,7 +160,7 @@ public function testTime(): void { } public function testTimeConfig(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::Time => IntlDateFormatter::MEDIUM, ]); @@ -171,7 +170,7 @@ public function testTimeConfig(): void { } public function testTimeCustomFormat(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::Time => 'custom', Package::Name.'.all.'.Formatter::Time.'.custom' => 'HH:mm:ss.SSS', Package::Name.'.all.'.Formatter::Time.'.custom2' => 'HH:mm:ss.SSS', @@ -191,7 +190,7 @@ public function testDate(): void { } public function testDateConfig(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::Date => IntlDateFormatter::MEDIUM, ]); @@ -201,7 +200,7 @@ public function testDateConfig(): void { } public function testDateCustomFormat(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::Date => 'custom', Package::Name.'.all.'.Formatter::Date.'.custom' => 'd MMM YYYY', Package::Name.'.all.'.Formatter::Date.'.custom2' => 'd MMM YYYY', @@ -224,7 +223,7 @@ public function testDatetime(): void { } public function testDatetimeConfig(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::DateTime => IntlDateFormatter::MEDIUM, ]); @@ -237,7 +236,7 @@ public function testDatetimeConfig(): void { } public function testDatetimeCustomFormat(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::DateTime => 'custom', Package::Name.'.all.'.Formatter::DateTime.'.custom' => 'd MMM YYYY || HH:mm:ss', Package::Name.'.all.'.Formatter::DateTime.'.custom2' => 'd MMM YYYY || HH:mm:ss', @@ -271,7 +270,7 @@ public function testSecret(): void { } public function testSecretConfig(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::Secret => 3, ]); @@ -328,7 +327,7 @@ public function testCurrency(): void { } public function testCurrencyConfig(): void { - config([ + $this->setConfig([ Package::Name.'.options.'.Formatter::Currency => 'RUB', ]); diff --git a/packages/graphql-printer/metadata.json b/packages/graphql-printer/metadata.json index 2b4c98f93..2c912fc59 100644 --- a/packages/graphql-printer/metadata.json +++ b/packages/graphql-printer/metadata.json @@ -4,6 +4,7 @@ "php": "PHP", "webonyx/graphql-php": "`webonyx/graphql-php`" }, + "merge": null, "requirements": { "HEAD": { "php": [ diff --git a/packages/graphql/composer.json b/packages/graphql/composer.json index ab4b500a9..bc89e1a61 100644 --- a/packages/graphql/composer.json +++ b/packages/graphql/composer.json @@ -22,7 +22,11 @@ "ext-filter": "*", "ext-mbstring": "*", "composer/semver": "^3.2", - "laravel/framework": "^10.34.0", + "illuminate/collections": "^10.34.0", + "illuminate/container": "^10.34.0", + "illuminate/contracts": "^10.34.0", + "illuminate/database": "^10.34.0", + "illuminate/support": "^10.34.0", "nuwave/lighthouse": "^6.5.0", "lastdragon-ru/lara-asp-core": "self.version", "lastdragon-ru/lara-asp-eloquent": "self.version", @@ -33,6 +37,7 @@ }, "require-dev": { "ext-pdo_sqlite": "*", + "illuminate/cache": "^10.34.0", "laravel/scout": "^9.8.0|^10.0.0", "mockery/mockery": "^1.6.2", "phpunit/phpunit": "^10.1.0", diff --git a/packages/graphql/metadata.json b/packages/graphql/metadata.json index a065fc149..d08777c3f 100644 --- a/packages/graphql/metadata.json +++ b/packages/graphql/metadata.json @@ -5,6 +5,7 @@ "laravel/framework": "Laravel", "nuwave/lighthouse": "Lighthouse" }, + "merge": null, "requirements": { "HEAD": { "laravel/framework": [ diff --git a/packages/graphql/src/Builder/Types/InputObject.php b/packages/graphql/src/Builder/Types/InputObject.php index de2070640..7a84019d3 100644 --- a/packages/graphql/src/Builder/Types/InputObject.php +++ b/packages/graphql/src/Builder/Types/InputObject.php @@ -12,6 +12,8 @@ use GraphQL\Type\Definition\FieldDefinition; use GraphQL\Type\Definition\InputObjectField; use GraphQL\Type\Definition\Type; +use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use LastDragon_ru\LaraASP\GraphQL\Builder\Context\HandlerContextImplicit; use LastDragon_ru\LaraASP\GraphQL\Builder\Context\HandlerContextOperators; use LastDragon_ru\LaraASP\GraphQL\Builder\Contracts\Context; @@ -34,7 +36,6 @@ use Nuwave\Lighthouse\Support\Contracts\FieldResolver; use Override; -use function config; use function count; use function is_a; use function is_string; @@ -442,8 +443,9 @@ protected function isFieldDirectiveAllowed( } // Allowed? - $isAllowed = false; - $allowed = (array) config(Package::Name.'.builder.allowed_directives'); + $repository = Container::getInstance()->make(Repository::class); + $isAllowed = false; + $allowed = (array) $repository->get(Package::Name.'.builder.allowed_directives'); foreach ($allowed as $class) { if (is_string($class) && $directive instanceof $class) { diff --git a/packages/graphql/src/Builder/Types/InputObjectTest.php b/packages/graphql/src/Builder/Types/InputObjectTest.php index 8428c1c70..d321e6688 100644 --- a/packages/graphql/src/Builder/Types/InputObjectTest.php +++ b/packages/graphql/src/Builder/Types/InputObjectTest.php @@ -28,8 +28,6 @@ use Override; use PHPUnit\Framework\Attributes\CoversClass; -use function config; - /** * @internal */ @@ -49,7 +47,7 @@ public function testIsFieldDirectiveAllowed( ContextContract $context, ): void { if ($allowed !== null) { - config([ + $this->setConfig([ Package::Name.'.builder.allowed_directives' => $allowed, ]); } diff --git a/packages/graphql/src/SearchBy/Directives/DirectiveTest.php b/packages/graphql/src/SearchBy/Directives/DirectiveTest.php index 095103649..b5d37d9d2 100644 --- a/packages/graphql/src/SearchBy/Directives/DirectiveTest.php +++ b/packages/graphql/src/SearchBy/Directives/DirectiveTest.php @@ -70,7 +70,6 @@ use PHPUnit\Framework\Attributes\CoversClass; use function array_merge; -use function config; use function implode; use function is_array; use function json_encode; @@ -120,7 +119,7 @@ public function testManipulateArgDefinition(string $expected, string $graphql, ? #[RequiresLaravelScout] public function testManipulateArgDefinitionScoutBuilder(): void { - config([ + $this->setConfig([ Package::Name.'.search_by.operators.Date' => [ SearchByOperatorEqualDirective::class, ], @@ -160,7 +159,7 @@ public function testManipulateArgDefinitionScoutBuilderV5Compat(): void { ->andReturn(false); }); - config([ + $this->setConfig([ Package::Name.'.search_by.operators.Date' => [ SearchByOperatorEqualDirective::class, ], @@ -674,7 +673,7 @@ static function (): void { 'AllowedDirectives' => [ 'AllowedDirectives.expected.graphql', 'AllowedDirectives.schema.graphql', - static function (): void { + static function (TestCase $test): void { $locator = Container::getInstance()->make(DirectiveLocator::class); $allowed = new class () extends BaseDirective { #[Override] @@ -696,7 +695,7 @@ public static function definition(): string { $locator->setResolved('allowed', $allowed::class); $locator->setResolved('forbidden', $forbidden::class); - config([ + $test->setConfig([ Package::Name.'.builder.allowed_directives' => [ RenameDirective::class, $allowed::class, @@ -713,8 +712,8 @@ public static function definition(): string { 'Ignored' => [ 'Ignored.expected.graphql', 'Ignored.schema.graphql', - static function (): void { - config([ + static function (TestCase $test): void { + $test->setConfig([ Package::Name.'.search_by.operators.String' => [ SearchByOperatorEqualDirective::class, ], @@ -741,8 +740,8 @@ static function (): void { 'Example' => [ 'Example.expected.graphql', 'Example.schema.graphql', - static function (): void { - config([ + static function (TestCase $test): void { + $test->setConfig([ Package::Name.'.search_by.operators.Date' => [ SearchByOperatorBetweenDirective::class, ], @@ -752,8 +751,8 @@ static function (): void { 'InterfaceUpdate' => [ 'InterfaceUpdate.expected.graphql', 'InterfaceUpdate.schema.graphql', - static function (): void { - config([ + static function (TestCase $test): void { + $test->setConfig([ Package::Name.'.search_by.operators.'.Operators::ID => [ SearchByOperatorEqualDirective::class, ], diff --git a/packages/graphql/src/SearchBy/Operators.php b/packages/graphql/src/SearchBy/Operators.php index 8d25c5e72..0a6748ed9 100644 --- a/packages/graphql/src/SearchBy/Operators.php +++ b/packages/graphql/src/SearchBy/Operators.php @@ -3,6 +3,8 @@ namespace LastDragon_ru\LaraASP\GraphQL\SearchBy; use GraphQL\Type\Definition\Type; +use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use LastDragon_ru\LaraASP\GraphQL\Builder\Contracts\Operator as BuilderOperator; use LastDragon_ru\LaraASP\GraphQL\Builder\Operators as BuilderOperators; use LastDragon_ru\LaraASP\GraphQL\Package; @@ -43,7 +45,6 @@ use Override; use function array_merge; -use function config; class Operators extends BuilderOperators { private const Prefix = Directive::Name.'Operators'; @@ -168,7 +169,8 @@ class Operators extends BuilderOperators { public function __construct() { /** @var array|string>> $operators */ - $operators = (array) config(Package::Name.'.search_by.operators'); + $operators = (array) Container::getInstance()->make(Repository::class) + ->get(Package::Name.'.search_by.operators'); parent::__construct($operators); } diff --git a/packages/graphql/src/SearchBy/OperatorsTest.php b/packages/graphql/src/SearchBy/OperatorsTest.php index b1446287e..784d2227f 100644 --- a/packages/graphql/src/SearchBy/OperatorsTest.php +++ b/packages/graphql/src/SearchBy/OperatorsTest.php @@ -19,8 +19,6 @@ use Override; use PHPUnit\Framework\Attributes\CoversClass; -use function config; - /** * @internal */ @@ -29,7 +27,7 @@ final class OperatorsTest extends TestCase { // // ========================================================================= public function testConstructor(): void { - config([ + $this->setConfig([ Package::Name.'.search_by.operators' => [ Operators::ID => [ OperatorsTest__Operator::class, diff --git a/packages/graphql/src/SortBy/Directives/DirectiveTest.php b/packages/graphql/src/SortBy/Directives/DirectiveTest.php index 0c562d1ab..f319bd3f2 100644 --- a/packages/graphql/src/SortBy/Directives/DirectiveTest.php +++ b/packages/graphql/src/SortBy/Directives/DirectiveTest.php @@ -55,7 +55,6 @@ use PHPUnit\Framework\Attributes\CoversClass; use function array_merge; -use function config; use function implode; use function is_array; use function json_encode; @@ -105,7 +104,7 @@ public function testManipulateArgDefinition(string $expected, string $graphql, ? #[RequiresLaravelScout] public function testManipulateArgDefinitionScoutBuilder(): void { - config([ + $this->setConfig([ Package::Name.'.sort_by.operators' => [ Operators::Extra => [ Operators::Extra, @@ -148,7 +147,7 @@ public function testManipulateArgDefinitionScoutBuilderV5Compat(): void { } public function testManipulateArgDefinitionTypeRegistryEmpty(): void { - config([ + $this->setConfig([ Package::Name.'.sort_by.operators' => [ Operators::Extra => [ SortByOperatorFieldDirective::class, @@ -612,7 +611,7 @@ static function (): void { 'AllowedDirectives' => [ 'AllowedDirectives.expected.graphql', 'AllowedDirectives.schema.graphql', - static function (): void { + static function (TestCase $test): void { $locator = Container::getInstance()->make(DirectiveLocator::class); $allowed = new class () extends BaseDirective { #[Override] @@ -634,7 +633,7 @@ public static function definition(): string { $locator->setResolved('allowed', $allowed::class); $locator->setResolved('forbidden', $forbidden::class); - config([ + $test->setConfig([ Package::Name.'.builder.allowed_directives' => [ RenameDirective::class, $allowed::class, @@ -648,8 +647,8 @@ public static function definition(): string { 'Ignored' => [ 'Ignored.expected.graphql', 'Ignored.schema.graphql', - static function (): void { - config([ + static function (TestCase $test): void { + $test->setConfig([ Package::Name.'.sort_by.operators.'.Operators::Extra => [ SortByOperatorFieldDirective::class, ], @@ -673,8 +672,8 @@ static function (): void { 'InterfaceUpdate' => [ 'InterfaceUpdate.expected.graphql', 'InterfaceUpdate.schema.graphql', - static function (): void { - config([ + static function (TestCase $test): void { + $test->setConfig([ Package::Name.'.sort_by.operators.'.Operators::Extra => [ SortByOperatorFieldDirective::class, ], @@ -888,10 +887,10 @@ public static function dataProviderHandleBuilder(): array { 'random' => 'yes', ], ], - static function (): void { + static function (TestCase $test): void { $package = Package::Name; - config([ + $test->setConfig([ "{$package}.sort_by.operators" => [ Operators::Extra => [ SortByOperatorFieldDirective::class, @@ -927,10 +926,10 @@ static function (): void { ], ], ], - static function (): void { + static function (TestCase $test): void { $package = Package::Name; - config([ + $test->setConfig([ "{$package}.sort_by.nulls" => [ Direction::Asc->value => Nulls::Last, Direction::Desc->value => Nulls::First, @@ -1091,10 +1090,10 @@ public static function dataProviderHandleBuilderV5Compat(): array { 'random' => 'yes', ], ], - static function (): void { + static function (TestCase $test): void { $package = Package::Name; - config([ + $test->setConfig([ "{$package}.sort_by.operators" => [ Operators::Extra => [ SortByOperatorFieldDirective::class, @@ -1126,10 +1125,10 @@ static function (): void { 'value' => 'desc', ], ], - static function (): void { + static function (TestCase $test): void { $package = Package::Name; - config([ + $test->setConfig([ "{$package}.sort_by.nulls" => [ Direction::Asc->value => Nulls::Last, Direction::Desc->value => Nulls::First, diff --git a/packages/graphql/src/SortBy/Operators.php b/packages/graphql/src/SortBy/Operators.php index 5f39502d9..d349fd0bc 100644 --- a/packages/graphql/src/SortBy/Operators.php +++ b/packages/graphql/src/SortBy/Operators.php @@ -2,6 +2,8 @@ namespace LastDragon_ru\LaraASP\GraphQL\SortBy; +use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use LastDragon_ru\LaraASP\GraphQL\Builder\Contracts\Operator as BuilderOperator; use LastDragon_ru\LaraASP\GraphQL\Builder\Operators as BuilderOperators; use LastDragon_ru\LaraASP\GraphQL\Package; @@ -15,7 +17,6 @@ use Override; use function array_merge; -use function config; class Operators extends BuilderOperators { private const Prefix = Directive::Name.'Operators'; @@ -39,7 +40,8 @@ class Operators extends BuilderOperators { public function __construct() { /** @var array|string>> $operators */ - $operators = (array) config(Package::Name.'.sort_by.operators'); + $operators = (array) Container::getInstance()->make(Repository::class) + ->get(Package::Name.'.sort_by.operators'); parent::__construct($operators); } diff --git a/packages/graphql/src/SortBy/Operators/Sort.php b/packages/graphql/src/SortBy/Operators/Sort.php index 449d235b0..a83d106e3 100644 --- a/packages/graphql/src/SortBy/Operators/Sort.php +++ b/packages/graphql/src/SortBy/Operators/Sort.php @@ -2,6 +2,8 @@ namespace LastDragon_ru\LaraASP\GraphQL\SortBy\Operators; +use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use LastDragon_ru\LaraASP\GraphQL\Builder\Contracts\BuilderFieldResolver; use LastDragon_ru\LaraASP\GraphQL\Builder\Contracts\Context; use LastDragon_ru\LaraASP\GraphQL\Builder\Contracts\Handler; @@ -18,7 +20,6 @@ use Nuwave\Lighthouse\Execution\Arguments\Argument; use Override; -use function config; use function is_array; class Sort extends Operator { @@ -106,7 +107,7 @@ protected function getNulls(Sorter $sorter, Context $context, Direction $directi // Default $nulls = null; - $config = config(Package::Name.'.sort_by.nulls'); + $config = Container::getInstance()->make(Repository::class)->get(Package::Name.'.sort_by.nulls'); $direction = match ($direction) { Direction::asc => Direction::Asc, Direction::desc => Direction::Desc, diff --git a/packages/graphql/src/SortBy/Operators/SortTest.php b/packages/graphql/src/SortBy/Operators/SortTest.php index df7a982be..bb0452b10 100644 --- a/packages/graphql/src/SortBy/Operators/SortTest.php +++ b/packages/graphql/src/SortBy/Operators/SortTest.php @@ -30,7 +30,6 @@ use Override; use PHPUnit\Framework\Attributes\CoversClass; -use function config; use function implode; /** @@ -168,9 +167,7 @@ public function testGetNulls( Closure $contextFactory, Direction $direction, ): void { - if ($config) { - config($config); - } + $this->setConfig($config); $sorter = $sorterFactory($this); $context = $contextFactory($this); diff --git a/packages/graphql/src/SortBy/OperatorsTest.php b/packages/graphql/src/SortBy/OperatorsTest.php index 7c4dc44d5..11ed1b6e5 100644 --- a/packages/graphql/src/SortBy/OperatorsTest.php +++ b/packages/graphql/src/SortBy/OperatorsTest.php @@ -19,8 +19,6 @@ use Override; use PHPUnit\Framework\Attributes\CoversClass; -use function config; - /** * @internal */ @@ -29,7 +27,7 @@ final class OperatorsTest extends TestCase { // // ========================================================================= public function testConstructor(): void { - config([ + $this->setConfig([ Package::Name.'.sort_by.operators' => [ Operators::Extra => [ OperatorsTest__Operator::class, diff --git a/packages/graphql/src/Stream/Directives/Directive.php b/packages/graphql/src/Stream/Directives/Directive.php index 223d29c9c..90d7c9600 100644 --- a/packages/graphql/src/Stream/Directives/Directive.php +++ b/packages/graphql/src/Stream/Directives/Directive.php @@ -10,6 +10,7 @@ use GraphQL\Type\Definition\HasFieldsType; use GraphQL\Type\Definition\Type; use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Model as EloquentModel; use Illuminate\Database\Eloquent\Relations\Relation as EloquentRelation; @@ -73,7 +74,6 @@ use function array_key_exists; use function array_key_first; use function class_exists; -use function config; use function count; use function explode; use function gettype; @@ -189,6 +189,7 @@ public function manipulateFieldDefinition( ObjectTypeDefinitionNode|InterfaceTypeDefinitionNode &$parentType, ): void { // Prepare + $repository = Container::getInstance()->make(Repository::class); $manipulator = $this->getAstManipulator($documentAST); $source = $this->getFieldSource($manipulator, $parentType, $fieldDefinition); $prefix = self::Settings; @@ -220,7 +221,7 @@ public function manipulateFieldDefinition( // Searchable? $searchable = Cast::toBool( $this->directiveArgValue(self::ArgSearchable) - ?? config("{$prefix}.search.enabled") + ?? $repository->get("{$prefix}.search.enabled") ?? false, ); @@ -229,7 +230,7 @@ public function manipulateFieldDefinition( $manipulator, $source, SearchByDirective::class, - Cast::toString(config("{$prefix}.search.name") ?: 'where'), + Cast::toString($repository->get("{$prefix}.search.name") ?: 'where'), $manipulator::Placeholder, ); } @@ -237,7 +238,7 @@ public function manipulateFieldDefinition( // Sortable? $sortable = Cast::toBool( $this->directiveArgValue(self::ArgSortable) - ?? config("{$prefix}.sort.enabled") + ?? $repository->get("{$prefix}.sort.enabled") ?? false, ); @@ -246,7 +247,7 @@ public function manipulateFieldDefinition( $manipulator, $source, SortByDirective::class, - Cast::toString(config("{$prefix}.sort.name") ?: 'order'), + Cast::toString($repository->get("{$prefix}.sort.name") ?: 'order'), $manipulator::Placeholder, ); } diff --git a/packages/graphql/src/Stream/Directives/DirectiveTest.php b/packages/graphql/src/Stream/Directives/DirectiveTest.php index 67a45816f..7472b32d3 100644 --- a/packages/graphql/src/Stream/Directives/DirectiveTest.php +++ b/packages/graphql/src/Stream/Directives/DirectiveTest.php @@ -76,7 +76,6 @@ use stdClass; use function array_merge; -use function config; use function is_string; use function json_encode; @@ -207,7 +206,7 @@ public function testDirectiveScout( string|int|null $offset, ): void { // Config - config([ + $this->setConfig([ 'scout.driver' => 'database', ]); @@ -281,7 +280,7 @@ public function testDirectiveScout( } public function testManipulateFieldDefinition(): void { - config([ + $this->setConfig([ 'lighthouse.namespaces.models' => [ (new ReflectionClass(TestObject::class))->getNamespaceName(), ], @@ -301,7 +300,7 @@ public function testManipulateFieldDefinition(): void { #[RequiresLaravelScout] public function testManipulateFieldDefinitionScoutBuilder(): void { - config([ + $this->setConfig([ 'lighthouse.namespaces.models' => [ (new ReflectionClass(TestObject::class))->getNamespaceName(), ], @@ -474,7 +473,7 @@ public function testGetBuilderInfo( } public function testGetBuilder(): void { - config([ + $this->setConfig([ 'lighthouse.namespaces.models' => [ (new ReflectionClass(Car::class))->getNamespaceName(), ], @@ -551,7 +550,7 @@ public function testGetBuilder(): void { #[RequiresLaravelScout] public function testGetBuilderScoutBuilder(): void { - config([ + $this->setConfig([ 'lighthouse.namespaces.models' => [ (new ReflectionClass(TestObjectSearchable::class))->getNamespaceName(), ], @@ -617,7 +616,7 @@ public function testGetBuilderScoutBuilder(): void { } public function testGetBuilderLighthouseEnhancer(): void { - config([ + $this->setConfig([ 'lighthouse.namespaces.models' => [ (new ReflectionClass(Car::class))->getNamespaceName(), ], @@ -798,7 +797,7 @@ public function testGetResolver(): void { */ public function testGetResolverExplicit(array|null $expected, string $arguments): void { // Prepare - config([ + $this->setConfig([ 'lighthouse.namespaces.models' => [ (new ReflectionClass(Car::class))->getNamespaceName(), ], @@ -835,7 +834,7 @@ public function testGetResolverExplicit(array|null $expected, string $arguments) public function testGetResolverRelation(): void { // Prepare - config([ + $this->setConfig([ 'lighthouse.namespaces.models' => [ (new ReflectionClass(Car::class))->getNamespaceName(), ], @@ -931,7 +930,7 @@ public function getResolverRelation(string $model, string $relation): ?Closure { public function testGetResolverQuery(): void { // Prepare - config([ + $this->setConfig([ 'lighthouse.namespaces.queries' => [ (new ReflectionClass(Query::class))->getNamespaceName(), ], @@ -974,7 +973,7 @@ public function getResolverQuery(string $type, string $field): ?array { public function testGetResolverModel(): void { // Prepare - config([ + $this->setConfig([ 'lighthouse.namespaces.models' => [ (new ReflectionClass(Car::class))->getNamespaceName(), ], @@ -1100,7 +1099,7 @@ public function getArgKey( } public function testResolveField(): void { - config([ + $this->setConfig([ 'lighthouse.namespaces.models' => [ (new ReflectionClass(Car::class))->getNamespaceName(), ], diff --git a/packages/graphql/src/Stream/Directives/Limit.php b/packages/graphql/src/Stream/Directives/Limit.php index 28ade6f75..286ddb1b4 100644 --- a/packages/graphql/src/Stream/Directives/Limit.php +++ b/packages/graphql/src/Stream/Directives/Limit.php @@ -10,6 +10,8 @@ use GraphQL\Language\Parser; use GraphQL\Type\Definition\Type; use GraphQL\Utils\AST; +use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use LastDragon_ru\LaraASP\Core\Utils\Cast; use LastDragon_ru\LaraASP\GraphQL\Builder\Traits\WithManipulator; use LastDragon_ru\LaraASP\GraphQL\Stream\Contracts\FieldArgumentDirective; @@ -21,7 +23,6 @@ use Nuwave\Lighthouse\Validation\RulesDirective; use Override; -use function config; use function max; use function min; use function strtr; @@ -39,7 +40,8 @@ class Limit extends BaseDirective implements ArgManipulator, FieldArgumentDirect * @return array{name: string, default: int, max: int} */ final public static function settings(): array { - $settings = (array) config(Directive::Settings.'.limit'); + $repository = Container::getInstance()->make(Repository::class); + $settings = (array) $repository->get(Directive::Settings.'.limit'); return [ 'name' => Cast::toString($settings['name'] ?? 'limit'), diff --git a/packages/graphql/src/Stream/Directives/Offset.php b/packages/graphql/src/Stream/Directives/Offset.php index e8971b5bc..ac98d264b 100644 --- a/packages/graphql/src/Stream/Directives/Offset.php +++ b/packages/graphql/src/Stream/Directives/Offset.php @@ -7,6 +7,8 @@ use GraphQL\Language\AST\InterfaceTypeDefinitionNode; use GraphQL\Language\AST\ObjectTypeDefinitionNode; use GraphQL\Language\Parser; +use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use LastDragon_ru\LaraASP\Core\Utils\Cast; use LastDragon_ru\LaraASP\GraphQL\Builder\Context; use LastDragon_ru\LaraASP\GraphQL\Builder\Traits\WithManipulator; @@ -23,7 +25,6 @@ use Override; use function array_map; -use function config; use function implode; use function is_int; use function max; @@ -39,7 +40,8 @@ class Offset extends BaseDirective implements ArgManipulator, FieldArgumentDirec * @return array{name: string} */ final public static function settings(): array { - $settings = (array) config(Directive::Settings.'.offset'); + $repository = Container::getInstance()->make(Repository::class); + $settings = (array) $repository->get(Directive::Settings.'.offset'); return [ 'name' => Cast::toString($settings['name'] ?? 'offset'), diff --git a/packages/graphql/src/Stream/Streams/DatabaseTest.php b/packages/graphql/src/Stream/Streams/DatabaseTest.php index 926e2fcde..11e00734d 100644 --- a/packages/graphql/src/Stream/Streams/DatabaseTest.php +++ b/packages/graphql/src/Stream/Streams/DatabaseTest.php @@ -2,7 +2,6 @@ namespace LastDragon_ru\LaraASP\GraphQL\Stream\Streams; -use Illuminate\Foundation\Testing\WithFaker; use Illuminate\Support\Collection; use LastDragon_ru\LaraASP\GraphQL\Stream\Offset; use LastDragon_ru\LaraASP\GraphQL\Testing\Package\Data\Models\TestObject; @@ -21,13 +20,12 @@ */ #[CoversClass(Database::class)] final class DatabaseTest extends TestCase { - use WithFaker; use WithQueryLog; use WithTestObject; public function testGetItems(): void { - $limit = max(1, $this->faker->numberBetween(1, 4)); - $offset = max(0, $this->faker->numberBetween(0, 2)); + $limit = max(1, $this->getFaker()->numberBetween(1, 4)); + $offset = max(0, $this->getFaker()->numberBetween(0, 2)); $builder = TestObject::query(); $stream = new Database( $builder, @@ -64,7 +62,7 @@ public function testGetItems(): void { } public function testGetLength(): void { - $count = $this->faker->numberBetween(1, 5); + $count = $this->getFaker()->numberBetween(1, 5); $builder = TestObject::query(); $stream = new Database($builder, 'key', 1, new Offset('path', 0, null)); diff --git a/packages/graphql/src/Stream/Streams/ScoutTest.php b/packages/graphql/src/Stream/Streams/ScoutTest.php index 03adbe19c..fc188d24c 100644 --- a/packages/graphql/src/Stream/Streams/ScoutTest.php +++ b/packages/graphql/src/Stream/Streams/ScoutTest.php @@ -3,7 +3,6 @@ namespace LastDragon_ru\LaraASP\GraphQL\Stream\Streams; use Illuminate\Contracts\Pagination\LengthAwarePaginator; -use Illuminate\Foundation\Testing\WithFaker; use LastDragon_ru\LaraASP\GraphQL\Stream\Offset; use LastDragon_ru\LaraASP\GraphQL\Stream\Utils\Page; use LastDragon_ru\LaraASP\GraphQL\Testing\Package\Data\Models\TestObjectSearchable; @@ -16,7 +15,6 @@ use PHPUnit\Framework\Attributes\CoversClass; use function array_slice; -use function config; use function max; use function usort; @@ -26,7 +24,6 @@ #[CoversClass(Scout::class)] #[RequiresLaravelScout] final class ScoutTest extends TestCase { - use WithFaker; use WithQueryLog; use WithTestObject; @@ -39,7 +36,7 @@ final class ScoutTest extends TestCase { protected function getEnvironmentSetUp($app): void { parent::getEnvironmentSetUp($app); - config([ + $this->setConfig([ 'scout.driver' => 'database', ]); } @@ -48,8 +45,8 @@ protected function getEnvironmentSetUp($app): void { // // ========================================================================= public function testGetItems(): void { - $limit = max(1, $this->faker->numberBetween(1, 4)); - $offset = max(0, $this->faker->numberBetween(0, 2)); + $limit = max(1, $this->getFaker()->numberBetween(1, 4)); + $offset = max(0, $this->getFaker()->numberBetween(0, 2)); $builder = TestObjectSearchable::search(); $stream = new Scout($builder, $builder->model->getKeyName(), $limit, new Offset('path', $offset, null)); $objects = [ @@ -97,7 +94,7 @@ public function testGetItems(): void { } public function testGetLength(): void { - $count = $this->faker->numberBetween(1, 5); + $count = $this->getFaker()->numberBetween(1, 5); $builder = TestObjectSearchable::search(); $stream = new Scout($builder, $builder->model->getKeyName(), 1, new Offset('path', 0, null)); diff --git a/packages/graphql/src/Testing/Package/Data/Models/WithTestObject.php b/packages/graphql/src/Testing/Package/Data/Models/WithTestObject.php index 2d4adafd2..d37159cad 100644 --- a/packages/graphql/src/Testing/Package/Data/Models/WithTestObject.php +++ b/packages/graphql/src/Testing/Package/Data/Models/WithTestObject.php @@ -2,10 +2,11 @@ namespace LastDragon_ru\LaraASP\GraphQL\Testing\Package\Data\Models; +use Illuminate\Container\Container; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\TestCase; -use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Builder; +use LastDragon_ru\LaraASP\GraphQL\Testing\Package\TestCase; +use PHPUnit\Framework\Attributes\After; use PHPUnit\Framework\Attributes\Before; /** @@ -14,24 +15,40 @@ * @mixin TestCase */ trait WithTestObject { - use RefreshDatabase; - /** * @internal */ #[Before] protected function initWithTestObject(): void { $this->afterApplicationCreated(static function (): void { - $table = (new TestObject())->getTable(); + $schema = Container::getInstance()->make(Builder::class); + $table = (new TestObject())->getTable(); - if (Schema::hasTable($table)) { + if ($schema->hasTable($table)) { return; } - Schema::create($table, static function (Blueprint $table): void { + $schema->create($table, static function (Blueprint $table): void { $table->string('id')->primary(); $table->string('value', 40)->nullable(); }); }); } + + /** + * @internal + */ + #[After] + protected function withTestObjectAfter(): void { + $this->beforeApplicationDestroyed(static function (): void { + $schema = Container::getInstance()->make(Builder::class); + $table = (new TestObject())->getTable(); + + if ($schema->hasTable($table)) { + return; + } + + $schema->drop($table); + }); + } } diff --git a/packages/graphql/src/Testing/Package/TestCase.php b/packages/graphql/src/Testing/Package/TestCase.php index 0de43d47d..2648ee256 100644 --- a/packages/graphql/src/Testing/Package/TestCase.php +++ b/packages/graphql/src/Testing/Package/TestCase.php @@ -29,7 +29,6 @@ use ReflectionClass; use SplFileInfo; -use function config; use function mb_substr; /** @@ -62,7 +61,7 @@ protected function getPackageProviders(mixed $app): array { protected function getEnvironmentSetUp($app): void { parent::getEnvironmentSetUp($app); - config([ + $this->setConfig([ 'lighthouse.namespaces.models' => [ (new ReflectionClass(TestObject::class))->getNamespaceName(), ], diff --git a/packages/migrator/composer.json b/packages/migrator/composer.json index d60ee22a5..c5e573394 100644 --- a/packages/migrator/composer.json +++ b/packages/migrator/composer.json @@ -22,7 +22,11 @@ "require": { "php": "^8.1|^8.2|^8.3", "ext-json": "*", - "laravel/framework": "^10.34.0", + "illuminate/container": "^10.34.0", + "illuminate/contracts": "^10.34.0", + "illuminate/database": "^10.34.0", + "illuminate/filesystem": "^10.34.0", + "illuminate/support": "^10.34.0", "lastdragon-ru/lara-asp-core": "self.version", "symfony/console": "^6.3.0", "symfony/finder": "^6.3.0", diff --git a/packages/migrator/metadata.json b/packages/migrator/metadata.json index 571c6d55f..1e74d1deb 100644 --- a/packages/migrator/metadata.json +++ b/packages/migrator/metadata.json @@ -1,6 +1,7 @@ { "version": "6.1.0", "require": [], + "merge": null, "requirements": { "HEAD": { "laravel/framework": [ diff --git a/packages/migrator/src/Commands/RawMigrationTest.php b/packages/migrator/src/Commands/RawMigrationTest.php index d023b2b64..ff079321c 100644 --- a/packages/migrator/src/Commands/RawMigrationTest.php +++ b/packages/migrator/src/Commands/RawMigrationTest.php @@ -4,13 +4,11 @@ use Composer\InstalledVersions; use Composer\Semver\VersionParser; -use Illuminate\Support\Collection; use Illuminate\Support\Composer; use LastDragon_ru\LaraASP\Migrator\Package; use LastDragon_ru\LaraASP\Migrator\Testing\Package\TestCase; use Mockery; use PHPUnit\Framework\Attributes\CoversClass; -use SplFileInfo; use Symfony\Component\Finder\Finder; use function array_slice; @@ -61,12 +59,11 @@ public function testHandle(): void { 'raw_migration~down.sql', 'raw_migration~up.sql', ]; - $actual = (new Collection($finder->files()->sortByName())) - ->map(static function (SplFileInfo $file): string { - return implode('_', array_slice(explode('_', $file->getFilename()), 4)); - }) - ->values() - ->all(); + $actual = []; + + foreach ($finder->files()->sortByName() as $file) { + $actual[] = implode('_', array_slice(explode('_', $file->getFilename()), 4)); + } self::assertEquals($expected, $actual); } diff --git a/packages/migrator/src/Commands/RawSeederTest.php b/packages/migrator/src/Commands/RawSeederTest.php index 3c4b5f3fb..7eaca1165 100644 --- a/packages/migrator/src/Commands/RawSeederTest.php +++ b/packages/migrator/src/Commands/RawSeederTest.php @@ -2,11 +2,9 @@ namespace LastDragon_ru\LaraASP\Migrator\Commands; -use Illuminate\Support\Collection; use LastDragon_ru\LaraASP\Migrator\Package; use LastDragon_ru\LaraASP\Migrator\Testing\Package\TestCase; use PHPUnit\Framework\Attributes\CoversClass; -use SplFileInfo; use Symfony\Component\Finder\Finder; /** @@ -37,12 +35,11 @@ public function testHandle(): void { 'RawSeeder.php', 'RawSeeder.sql', ]; - $actual = (new Collection($finder->files()->sortByName())) - ->map(static function (SplFileInfo $file): string { - return $file->getFilename(); - }) - ->values() - ->all(); + $actual = []; + + foreach ($finder->files()->sortByName() as $file) { + $actual[] = $file->getFilename(); + } self::assertEquals($expected, $actual); } diff --git a/packages/serializer/composer.json b/packages/serializer/composer.json index 4b824fcbb..6a758a562 100644 --- a/packages/serializer/composer.json +++ b/packages/serializer/composer.json @@ -18,7 +18,10 @@ }, "require": { "php": "^8.1|^8.2|^8.3", - "laravel/framework": "^10.34.0", + "illuminate/container": "^10.34.0", + "illuminate/contracts": "^10.34.0", + "illuminate/database": "^10.34.0", + "illuminate/support": "^10.34.0", "lastdragon-ru/lara-asp-core": "self.version", "phpdocumentor/type-resolver": "^1.7", "phpstan/phpdoc-parser": "^1.25", diff --git a/packages/serializer/metadata.json b/packages/serializer/metadata.json index 040896c03..2e5fcf0e2 100644 --- a/packages/serializer/metadata.json +++ b/packages/serializer/metadata.json @@ -1,6 +1,7 @@ { "version": "6.1.0", "require": [], + "merge": null, "requirements": { "HEAD": { "laravel/framework": [ diff --git a/packages/serializer/src/Factory.php b/packages/serializer/src/Factory.php index ef8242fca..283fdbe1c 100644 --- a/packages/serializer/src/Factory.php +++ b/packages/serializer/src/Factory.php @@ -3,6 +3,7 @@ namespace LastDragon_ru\LaraASP\Serializer; use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use LastDragon_ru\LaraASP\Serializer\Contracts\Serializer as SerializerContract; use LastDragon_ru\LaraASP\Serializer\Normalizers\DateTimeNormalizer; use LastDragon_ru\LaraASP\Serializer\Normalizers\DateTimeNormalizerContextBuilder; @@ -26,7 +27,6 @@ use function array_filter; use function array_key_exists; use function array_keys; -use function config; use const JSON_BIGINT_AS_STRING; use const JSON_PRESERVE_ZERO_FRACTION; @@ -92,7 +92,9 @@ protected function make( protected function getConfigFormat(?string $config): ?string { /** @var ?string $format */ - $format = $config ? config("{$config}.default") : null; + $format = $config + ? Container::getInstance()->make(Repository::class)->get("{$config}.default") + : null; return $format; } @@ -102,7 +104,9 @@ protected function getConfigFormat(?string $config): ?string { */ protected function getConfigContext(?string $config): array { /** @var array $context */ - $context = $config ? (array) config("{$config}.context") : []; + $context = $config + ? (array) Container::getInstance()->make(Repository::class)->get("{$config}.context") + : []; return $context; } @@ -135,7 +139,9 @@ protected function getEncoders(array $encoders, array &$context, ?string $config */ protected function getConfigEncoders(?string $config): array { /** @var array, array> $encoders */ - $encoders = $config ? (array) config("{$config}.encoders") : []; + $encoders = $config + ? (array) Container::getInstance()->make(Repository::class)->get("{$config}.encoders") + : []; return $encoders; } @@ -195,7 +201,9 @@ protected function getNormalizers(array $normalizers, array &$context, ?string $ */ protected function getConfigNormalizers(?string $config): array { /** @var array, array|null> $normalizers */ - $normalizers = $config ? (array) config("{$config}.normalizers") : $config; + $normalizers = $config + ? (array) Container::getInstance()->make(Repository::class)->get("{$config}.normalizers") + : $config; return $normalizers; } diff --git a/packages/serializer/src/FactoryTest.php b/packages/serializer/src/FactoryTest.php index 9f0c42558..df67d5916 100644 --- a/packages/serializer/src/FactoryTest.php +++ b/packages/serializer/src/FactoryTest.php @@ -18,15 +18,13 @@ use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeZoneNormalizer; -use function config; - /** * @internal */ #[CoversClass(Factory::class)] final class FactoryTest extends TestCase { public function testCreate(): void { - config([ + $this->setConfig([ Package::Name => [ 'default' => 'format from config', 'encoders' => [ diff --git a/packages/spa/composer.json b/packages/spa/composer.json index 6ec5f73d7..4dd14d942 100644 --- a/packages/spa/composer.json +++ b/packages/spa/composer.json @@ -20,8 +20,16 @@ "require": { "php": "^8.1|^8.2|^8.3", "ext-mbstring": "*", + "illuminate/collections": "^10.34.0", + "illuminate/container": "^10.34.0", + "illuminate/contracts": "^10.34.0", + "illuminate/database": "^10.34.0", + "illuminate/http": "^10.34.0", + "illuminate/pagination": "^10.34.0", + "illuminate/routing": "^10.34.0", + "illuminate/support": "^10.34.0", + "illuminate/validation": "^10.34.0", "guzzlehttp/psr7": "^1.9.1|^2.4.5", - "laravel/framework": "^10.34.0", "lastdragon-ru/lara-asp-core": "self.version", "symfony/http-kernel": "^6.3.0", "symfony/polyfill-php83": "^1.28" diff --git a/packages/spa/defaults/routes.php b/packages/spa/defaults/routes.php index a0e15dab7..2800991bb 100644 --- a/packages/spa/defaults/routes.php +++ b/packages/spa/defaults/routes.php @@ -1,24 +1,29 @@ make(Repository::class); $package = Package::Name; -$prefix = config("{$package}.routes.prefix"); -$enabled = config("{$package}.routes.enabled"); -$middleware = config("{$package}.routes.middleware"); +$prefix = $repository->get("{$package}.routes.prefix"); +$enabled = $repository->get("{$package}.routes.enabled"); +$middleware = $repository->get("{$package}.routes.middleware"); -if (!$enabled) { +if (!$enabled || !Container::getInstance()->bound(Registrar::class)) { return; } // SPA Routes -Route::group([ - 'middleware' => $middleware, - 'prefix' => $prefix, -], static function (Router $router): void { - $router->get('settings', [SpaController::class, 'settings']); - $router->get('user', [SpaController::class, 'user']); -}); +Container::getInstance()->make(Registrar::class)->group( + [ + 'middleware' => $middleware, + 'prefix' => $prefix, + ], + static function (Registrar $router): void { + $router->get('settings', [SpaController::class, 'settings']); + $router->get('user', [SpaController::class, 'user']); + }, +); diff --git a/packages/spa/metadata.json b/packages/spa/metadata.json index 2b4437e0d..4758fa920 100644 --- a/packages/spa/metadata.json +++ b/packages/spa/metadata.json @@ -1,6 +1,7 @@ { "version": "6.1.0", "require": [], + "merge": null, "requirements": { "HEAD": { "laravel/framework": [ diff --git a/packages/spa/src/Http/Controllers/SpaController.php b/packages/spa/src/Http/Controllers/SpaController.php index 9a32ae181..90d05048b 100644 --- a/packages/spa/src/Http/Controllers/SpaController.php +++ b/packages/spa/src/Http/Controllers/SpaController.php @@ -2,13 +2,13 @@ namespace LastDragon_ru\LaraASP\Spa\Http\Controllers; +use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use Illuminate\Http\UploadedFile; use Illuminate\Routing\Controller; use LastDragon_ru\LaraASP\Core\Utils\ConfigMerger; use LastDragon_ru\LaraASP\Spa\Package; -use function config; - class SpaController extends Controller { // // ========================================================================= @@ -28,16 +28,17 @@ public function settings(): array { * @return array */ protected function getSettings(): array { - $package = Package::Name; - $default = [ + $repository = Container::getInstance()->make(Repository::class); + $package = Package::Name; + $default = [ ConfigMerger::Strict => false, - 'title' => config('app.name'), + 'title' => $repository->get('app.name'), 'upload' => [ 'max' => UploadedFile::getMaxFilesize(), ], ]; - $custom = config("{$package}.spa"); - $settings = (new ConfigMerger())->merge($default, $custom); + $custom = $repository->get("{$package}.spa"); + $settings = (new ConfigMerger())->merge($default, $custom); return $settings; } diff --git a/packages/spa/src/Http/Controllers/SpaControllerTest.php b/packages/spa/src/Http/Controllers/SpaControllerTest.php index 9e63b9cd5..ec86f0e21 100644 --- a/packages/spa/src/Http/Controllers/SpaControllerTest.php +++ b/packages/spa/src/Http/Controllers/SpaControllerTest.php @@ -20,8 +20,6 @@ use Override; use PHPUnit\Framework\Attributes\CoversClass; -use function config; - /** * @internal */ @@ -36,7 +34,7 @@ final class SpaControllerTest extends TestCase { protected function getEnvironmentSetUp($app): void { parent::getEnvironmentSetUp($app); - config([ + $this->setConfig([ Package::Name.'.routes.enabled' => false, ]); } @@ -57,7 +55,7 @@ public function testSettings( array $headers = [], array $settings = [], ): void { - config([ + $this->setConfig([ Package::Name.'.routes.enabled' => $routes, Package::Name.'.routes.prefix' => $prefix, Package::Name.'.spa' => $settings, diff --git a/packages/spa/src/Http/Request.php b/packages/spa/src/Http/Request.php index c2796bf2d..f66306273 100644 --- a/packages/spa/src/Http/Request.php +++ b/packages/spa/src/Http/Request.php @@ -3,48 +3,18 @@ namespace LastDragon_ru\LaraASP\Spa\Http; use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Arr; -use Illuminate\Validation\Validator; use Override; -use function data_get; -use function is_null; - +/** + * @deprecated ${version} Please use own class and {@see WithValueProvider} trait. + */ abstract class Request extends FormRequest { + use WithValueProvider { + validated as private defaultValidated; + } + #[Override] public function validated(mixed $key = null, mixed $default = null): mixed { - // We need `\Illuminate\Validation\Validator::getRules()` but it doesn't - // exists in `\Illuminate\Contracts\Validation\Validator`. - $validator = $this->getValidatorInstance(); - $validated = parent::validated(); - - if (!($validator instanceof Validator)) { - return $validated; - } - - // Replace values - foreach ($validator->getRules() as $attribute => $rules) { - /** @var ValueProvider|null $provider */ - $provider = Arr::last($rules, static function ($rule): bool { - return $rule instanceof ValueProvider; - }); - $attribute = (string) $attribute; - - if ($provider && Arr::has($validated, $attribute)) { - $value = Arr::get($validated, $attribute); - - if (!is_null($value)) { - Arr::set($validated, $attribute, $provider->getValue($value)); - } - } - } - - // Key? - if ($key !== null) { - $validated = data_get($validated, $key, $default); - } - - // Return - return $validated; + return $this->defaultValidated($key, $default); } } diff --git a/packages/spa/src/Http/RequestTest.php b/packages/spa/src/Http/RequestTest.php index 86b49f63e..8c2ab405d 100644 --- a/packages/spa/src/Http/RequestTest.php +++ b/packages/spa/src/Http/RequestTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\Attributes\CoversClass; /** + * @deprecated ${version} * @internal */ #[CoversClass(Request::class)] diff --git a/packages/spa/src/Http/Resources/Scalar/BoolResourceTest.php b/packages/spa/src/Http/Resources/Scalar/BoolResourceTest.php index 3bfc7a420..ad2df3f06 100644 --- a/packages/spa/src/Http/Resources/Scalar/BoolResourceTest.php +++ b/packages/spa/src/Http/Resources/Scalar/BoolResourceTest.php @@ -2,7 +2,8 @@ namespace LastDragon_ru\LaraASP\Spa\Http\Resources\Scalar; -use Illuminate\Support\Facades\Route; +use Illuminate\Container\Container; +use Illuminate\Contracts\Routing\Registrar; use LastDragon_ru\LaraASP\Spa\Testing\Package\TestCase; use LastDragon_ru\LaraASP\Testing\Responses\Laravel\Json\OkResponse; use PHPUnit\Framework\Attributes\CoversClass; @@ -13,9 +14,10 @@ #[CoversClass(BoolResource::class)] final class BoolResourceTest extends TestCase { public function testToResponse(): void { - Route::get(__METHOD__, static function (): mixed { - return new BoolResource(true); - }); + Container::getInstance()->make(Registrar::class) + ->get(__METHOD__, static function (): mixed { + return new BoolResource(true); + }); $this->get(__METHOD__)->assertThat(new OkResponse(BoolResource::class)); } diff --git a/packages/spa/src/Http/Resources/Scalar/FalseResourceTest.php b/packages/spa/src/Http/Resources/Scalar/FalseResourceTest.php index 42726ff83..8b8b1c274 100644 --- a/packages/spa/src/Http/Resources/Scalar/FalseResourceTest.php +++ b/packages/spa/src/Http/Resources/Scalar/FalseResourceTest.php @@ -2,7 +2,8 @@ namespace LastDragon_ru\LaraASP\Spa\Http\Resources\Scalar; -use Illuminate\Support\Facades\Route; +use Illuminate\Container\Container; +use Illuminate\Contracts\Routing\Registrar; use LastDragon_ru\LaraASP\Spa\Testing\Package\TestCase; use LastDragon_ru\LaraASP\Testing\Responses\Laravel\Json\OkResponse; use PHPUnit\Framework\Attributes\CoversClass; @@ -13,9 +14,10 @@ #[CoversClass(FalseResource::class)] final class FalseResourceTest extends TestCase { public function testToResponse(): void { - Route::get(__METHOD__, static function (): mixed { - return new FalseResource(); - }); + Container::getInstance()->make(Registrar::class) + ->get(__METHOD__, static function (): mixed { + return new FalseResource(); + }); $this->get(__METHOD__)->assertThat(new OkResponse(FalseResource::class)); } diff --git a/packages/spa/src/Http/Resources/Scalar/IntResourceTest.php b/packages/spa/src/Http/Resources/Scalar/IntResourceTest.php index 95873dca8..0eb059f1a 100644 --- a/packages/spa/src/Http/Resources/Scalar/IntResourceTest.php +++ b/packages/spa/src/Http/Resources/Scalar/IntResourceTest.php @@ -2,7 +2,8 @@ namespace LastDragon_ru\LaraASP\Spa\Http\Resources\Scalar; -use Illuminate\Support\Facades\Route; +use Illuminate\Container\Container; +use Illuminate\Contracts\Routing\Registrar; use LastDragon_ru\LaraASP\Spa\Testing\Package\TestCase; use LastDragon_ru\LaraASP\Testing\Responses\Laravel\Json\OkResponse; use PHPUnit\Framework\Attributes\CoversClass; @@ -13,9 +14,10 @@ #[CoversClass(IntResource::class)] final class IntResourceTest extends TestCase { public function testToResponse(): void { - Route::get(__METHOD__, static function (): mixed { - return new IntResource(123); - }); + Container::getInstance()->make(Registrar::class) + ->get(__METHOD__, static function (): mixed { + return new IntResource(123); + }); $this->get(__METHOD__)->assertThat(new OkResponse(IntResource::class)); } diff --git a/packages/spa/src/Http/Resources/Scalar/NullResourceTest.php b/packages/spa/src/Http/Resources/Scalar/NullResourceTest.php index 3202214b5..63e2934a1 100644 --- a/packages/spa/src/Http/Resources/Scalar/NullResourceTest.php +++ b/packages/spa/src/Http/Resources/Scalar/NullResourceTest.php @@ -2,7 +2,8 @@ namespace LastDragon_ru\LaraASP\Spa\Http\Resources\Scalar; -use Illuminate\Support\Facades\Route; +use Illuminate\Container\Container; +use Illuminate\Contracts\Routing\Registrar; use LastDragon_ru\LaraASP\Spa\Testing\Package\TestCase; use LastDragon_ru\LaraASP\Testing\Responses\Laravel\Json\OkResponse; use PHPUnit\Framework\Attributes\CoversClass; @@ -13,9 +14,10 @@ #[CoversClass(NullResource::class)] final class NullResourceTest extends TestCase { public function testToResponse(): void { - Route::get(__METHOD__, static function (): mixed { - return new NullResource(); - }); + Container::getInstance()->make(Registrar::class) + ->get(__METHOD__, static function (): mixed { + return new NullResource(); + }); $this->get(__METHOD__)->assertThat(new OkResponse(NullResource::class)); } diff --git a/packages/spa/src/Http/Resources/Scalar/NumberResourceTest.php b/packages/spa/src/Http/Resources/Scalar/NumberResourceTest.php index a1b3edaa8..b550dc18f 100644 --- a/packages/spa/src/Http/Resources/Scalar/NumberResourceTest.php +++ b/packages/spa/src/Http/Resources/Scalar/NumberResourceTest.php @@ -2,7 +2,8 @@ namespace LastDragon_ru\LaraASP\Spa\Http\Resources\Scalar; -use Illuminate\Support\Facades\Route; +use Illuminate\Container\Container; +use Illuminate\Contracts\Routing\Registrar; use LastDragon_ru\LaraASP\Spa\Testing\Package\TestCase; use LastDragon_ru\LaraASP\Testing\Responses\Laravel\Json\OkResponse; use PHPUnit\Framework\Attributes\CoversClass; @@ -13,9 +14,10 @@ #[CoversClass(NumberResource::class)] final class NumberResourceTest extends TestCase { public function testToResponse(): void { - Route::get(__METHOD__, static function (): mixed { - return new NumberResource(123); - }); + Container::getInstance()->make(Registrar::class) + ->get(__METHOD__, static function (): mixed { + return new NumberResource(123); + }); $this->get(__METHOD__)->assertThat(new OkResponse(NumberResource::class)); } diff --git a/packages/spa/src/Http/Resources/Scalar/StringResourceTest.php b/packages/spa/src/Http/Resources/Scalar/StringResourceTest.php index 81d1de2fb..c809e298e 100644 --- a/packages/spa/src/Http/Resources/Scalar/StringResourceTest.php +++ b/packages/spa/src/Http/Resources/Scalar/StringResourceTest.php @@ -2,7 +2,8 @@ namespace LastDragon_ru\LaraASP\Spa\Http\Resources\Scalar; -use Illuminate\Support\Facades\Route; +use Illuminate\Container\Container; +use Illuminate\Contracts\Routing\Registrar; use LastDragon_ru\LaraASP\Spa\Testing\Package\TestCase; use LastDragon_ru\LaraASP\Testing\Responses\Laravel\Json\OkResponse; use PHPUnit\Framework\Attributes\CoversClass; @@ -13,9 +14,10 @@ #[CoversClass(StringResource::class)] final class StringResourceTest extends TestCase { public function testToResponse(): void { - Route::get(__METHOD__, static function (): mixed { - return new StringResource('123'); - }); + Container::getInstance()->make(Registrar::class) + ->get(__METHOD__, static function (): mixed { + return new StringResource('123'); + }); $this->get(__METHOD__)->assertThat(new OkResponse(StringResource::class)); } diff --git a/packages/spa/src/Http/Resources/Scalar/TrueResourceTest.php b/packages/spa/src/Http/Resources/Scalar/TrueResourceTest.php index 1d00ce1f9..fdc600984 100644 --- a/packages/spa/src/Http/Resources/Scalar/TrueResourceTest.php +++ b/packages/spa/src/Http/Resources/Scalar/TrueResourceTest.php @@ -2,7 +2,8 @@ namespace LastDragon_ru\LaraASP\Spa\Http\Resources\Scalar; -use Illuminate\Support\Facades\Route; +use Illuminate\Container\Container; +use Illuminate\Contracts\Routing\Registrar; use LastDragon_ru\LaraASP\Spa\Testing\Package\TestCase; use LastDragon_ru\LaraASP\Testing\Responses\Laravel\Json\OkResponse; use PHPUnit\Framework\Attributes\CoversClass; @@ -13,9 +14,10 @@ #[CoversClass(TrueResource::class)] final class TrueResourceTest extends TestCase { public function testToResponse(): void { - Route::get(__METHOD__, static function (): mixed { - return new TrueResource(); - }); + Container::getInstance()->make(Registrar::class) + ->get(__METHOD__, static function (): mixed { + return new TrueResource(); + }); $this->get(__METHOD__)->assertThat(new OkResponse(TrueResource::class)); } diff --git a/packages/spa/src/Http/WithValueProvider.php b/packages/spa/src/Http/WithValueProvider.php new file mode 100644 index 000000000..8008cd79a --- /dev/null +++ b/packages/spa/src/Http/WithValueProvider.php @@ -0,0 +1,59 @@ +|int|string|null $key + */ + public function validated(mixed $key = null, mixed $default = null): mixed { + // We need `\Illuminate\Validation\Validator::getRules()` but it doesn't + // exists in `\Illuminate\Contracts\Validation\Validator`. + $validator = $this->getValidatorInstance(); + $validated = $validator->validated(); + + if (!($validator instanceof Validator)) { + return $validated; + } + + // Replace values + foreach ($validator->getRules() as $attribute => $rules) { + /** @var ValueProvider|null $provider */ + $provider = Arr::last($rules, static function ($rule): bool { + return $rule instanceof ValueProvider; + }); + $attribute = (string) $attribute; + + if ($provider && Arr::has($validated, $attribute)) { + $value = Arr::get($validated, $attribute); + + if (!is_null($value)) { + Arr::set($validated, $attribute, $provider->getValue($value)); + } + } + } + + // Key? + if ($key !== null) { + $validated = data_get($validated, $key, $default); + } + + // Return + return $validated; + } + + /** + * @noinspection PhpMissingReturnTypeInspection + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint + * + * @return ValidatorContract + */ + abstract protected function getValidatorInstance(); +} diff --git a/packages/spa/src/Http/WithValueProviderTest.php b/packages/spa/src/Http/WithValueProviderTest.php new file mode 100644 index 000000000..549d98c6b --- /dev/null +++ b/packages/spa/src/Http/WithValueProviderTest.php @@ -0,0 +1,154 @@ +make(Router::class); + $translator = Container::getInstance()->make(Translator::class); + $resolverRuleA = new ResolverRule( + $translator, + new class($router) extends Resolver { + /** + * @inheritDoc + */ + #[Override] + protected function resolve(mixed $value, array $parameters): mixed { + return ['a' => $value]; + } + }, + ); + $resolverRuleB = new ResolverRule( + $translator, + new class($router) extends Resolver { + /** + * @inheritDoc + */ + #[Override] + protected function resolve(mixed $value, array $parameters): mixed { + return ['b' => $value]; + } + }, + ); + $rule = new class() implements Rule { + /** + * @inheritDoc + */ + #[Override] + public function passes($attribute, $value): bool { + return (bool) $value; + } + + #[Override] + public function message(): string { + return static::class; + } + }; + $data = [ + 'rule' => true, + 'rule_nullable' => null, + 'resolver' => 1, + 'resolver_nullable' => null, + 'resolver_chained' => 2, + 'array' => [ + [ + 'rule' => true, + 'resolver' => 3, + ], + [ + 'rule' => true, + 'resolver' => 4, + ], + ], + ]; + + $request = new class($rule, $resolverRuleA, $resolverRuleB, $data) { + use WithValueProvider; + + /** + * @param array $data + */ + public function __construct( + private readonly Rule $rule, + private readonly ResolverRule $resolverRuleA, + private readonly ResolverRule $resolverRuleB, + private readonly array $data, + ) { + // empty + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint + * + * @return Validator + */ + #[Override] + protected function getValidatorInstance() { + $factory = Container::getInstance()->make(Factory::class); + $validator = $factory->make($this->data, [ + 'rule' => ['required', $this->rule], + 'rule_nullable' => ['nullable', 'int'], + 'resolver' => ['required', $this->resolverRuleA], + 'resolver_nullable' => ['nullable', $this->resolverRuleA], + 'resolver_chained' => ['required', $this->resolverRuleA, $this->resolverRuleB], + 'array' => ['required', 'array'], + 'array.*.rule' => ['required', $this->rule], + 'array.*.resolver' => ['required', $this->resolverRuleA], + ]); + + return $validator; + } + }; + + self::assertEquals([ + 'rule' => true, + 'rule_nullable' => null, + 'resolver' => ['a' => 1], + 'array' => [ + [ + 'rule' => true, + 'resolver' => ['a' => 3], + ], + [ + 'rule' => true, + 'resolver' => ['a' => 4], + ], + ], + 'resolver_nullable' => null, + 'resolver_chained' => ['b' => 2], + ], $request->validated()); + + self::assertEquals(null, $request->validated('rule_nullable')); + self::assertEquals(['a' => 1], $request->validated('resolver')); + self::assertEquals(['a' => 4], $request->validated('array.1.resolver')); + self::assertEquals( + [ + [ + 'rule' => true, + 'resolver' => ['a' => 3], + ], + [ + 'rule' => true, + 'resolver' => ['a' => 4], + ], + ], + $request->validated('array'), + ); + } +} diff --git a/packages/spa/src/Provider.php b/packages/spa/src/Provider.php index 5da51ddf7..3f3e77275 100644 --- a/packages/spa/src/Provider.php +++ b/packages/spa/src/Provider.php @@ -2,16 +2,11 @@ namespace LastDragon_ru\LaraASP\Spa; -use Exception; -use Illuminate\Contracts\Debug\ExceptionHandler; -use Illuminate\Foundation\Exceptions\Handler; use Illuminate\Support\ServiceProvider; use LastDragon_ru\LaraASP\Core\Provider\WithConfig; use LastDragon_ru\LaraASP\Core\Provider\WithRoutes; use LastDragon_ru\LaraASP\Core\Provider\WithTranslations; -use LastDragon_ru\LaraASP\Spa\Routing\UnresolvedValueException; use Override; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class Provider extends ServiceProvider { use WithConfig; @@ -24,7 +19,6 @@ public function boot(): void { $this->bootConfig(); $this->bootRoutes(); $this->bootTranslations(); - $this->bootExceptionHandler(); } // @@ -34,20 +28,5 @@ public function boot(): void { protected function getName(): string { return Package::Name; } - - protected function bootExceptionHandler(): void { - $this->callAfterResolving(ExceptionHandler::class, static function (ExceptionHandler $handler): void { - if (!($handler instanceof Handler)) { - return; - } - - $handler->map( - UnresolvedValueException::class, - static function (UnresolvedValueException $exception): Exception { - return new NotFoundHttpException($exception->getMessage() ?: 'Not found.', $exception); - }, - ); - }); - } // } diff --git a/packages/spa/src/Routing/UnresolvedValueException.php b/packages/spa/src/Routing/UnresolvedValueException.php index 72ca33746..f493b619d 100644 --- a/packages/spa/src/Routing/UnresolvedValueException.php +++ b/packages/spa/src/Routing/UnresolvedValueException.php @@ -2,7 +2,9 @@ namespace LastDragon_ru\LaraASP\Spa\Routing; +use Exception; use RuntimeException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Throwable; class UnresolvedValueException extends RuntimeException { @@ -17,4 +19,8 @@ public function __construct(mixed $value, string $message = '', int $code = 0, T public function getValue(): mixed { return $this->value; } + + public function getInnerException(): Exception { + return new NotFoundHttpException($this->getMessage() ?: 'Not found.', $this); + } } diff --git a/packages/spa/src/Routing/UnresolvedValueExceptionTest.php b/packages/spa/src/Routing/UnresolvedValueExceptionTest.php index 58653af1e..656b9ffef 100644 --- a/packages/spa/src/Routing/UnresolvedValueExceptionTest.php +++ b/packages/spa/src/Routing/UnresolvedValueExceptionTest.php @@ -2,7 +2,8 @@ namespace LastDragon_ru\LaraASP\Spa\Routing; -use Illuminate\Support\Facades\Route; +use Illuminate\Container\Container; +use Illuminate\Contracts\Routing\Registrar; use LastDragon_ru\LaraASP\Spa\Testing\Package\TestCase; use LastDragon_ru\LaraASP\Testing\Constraints\Response\StatusCodes\NotFound; use PHPUnit\Framework\Attributes\CoversClass; @@ -13,9 +14,10 @@ #[CoversClass(UnresolvedValueException::class)] final class UnresolvedValueExceptionTest extends TestCase { public function testHttpResponse(): void { - Route::get(__FUNCTION__, static function (): void { - throw new UnresolvedValueException(123); - }); + Container::getInstance()->make(Registrar::class) + ->get(__FUNCTION__, static function (): void { + throw new UnresolvedValueException(123); + }); $this->get(__FUNCTION__)->assertThat(new NotFound()); } diff --git a/packages/spa/src/Validation/Rules/DateTimeRule.php b/packages/spa/src/Validation/Rules/DateTimeRule.php index d8355ec7e..82c30146d 100644 --- a/packages/spa/src/Validation/Rules/DateTimeRule.php +++ b/packages/spa/src/Validation/Rules/DateTimeRule.php @@ -5,19 +5,20 @@ use DateTime; use DateTimeImmutable; use DateTimeInterface; +use Illuminate\Container\Container; +use Illuminate\Contracts\Config\Repository; use LastDragon_ru\LaraASP\Spa\Package; use Override; -use function config; - /** * ISO 8601 DateTime. */ class DateTimeRule extends DateRule { #[Override] public function getValue(mixed $value): DateTimeInterface|null { - $value = parent::getValue($value); - $tz = config('app.timezone') ?: 'UTC'; + $repository = Container::getInstance()->make(Repository::class); + $value = parent::getValue($value); + $tz = $repository->get('app.timezone') ?: 'UTC'; if ($value instanceof DateTime || $value instanceof DateTimeImmutable) { $value = $value->setTimezone($tz); diff --git a/packages/spa/src/Validation/Rules/DateTimeRuleTest.php b/packages/spa/src/Validation/Rules/DateTimeRuleTest.php index 54003204a..a170eff0f 100644 --- a/packages/spa/src/Validation/Rules/DateTimeRuleTest.php +++ b/packages/spa/src/Validation/Rules/DateTimeRuleTest.php @@ -9,7 +9,6 @@ use PHPUnit\Framework\Attributes\CoversClass; use Throwable; -use function config; use function is_array; /** @@ -50,7 +49,7 @@ public function testGetValue(string|array $expected, ?string $tz, string $value) $translator = Container::getInstance()->make(Translator::class); $rule = new DateTimeRule($translator); - config([ + $this->setConfig([ 'app.timezone' => $tz, ]); diff --git a/packages/testing/README.md b/packages/testing/README.md index 5c61f7eec..5bb1ba977 100644 --- a/packages/testing/README.md +++ b/packages/testing/README.md @@ -49,20 +49,30 @@ composer require --dev lastdragon-ru/lara-asp-testing > > By default, package overrides scalar comparator to make it strict! So `assertEquals(true, 1)` is `false`. -In the general case, you just need to update `tests/TestCase.php` to include almost everything, but you also can include only desired features, please see base [`TestCase`](./src/TestCase.php) to found what is supported. +In the general case, you just need to update `tests/TestCase.php` to include most important things, but you also can include only desired features, please see related traits and extensions below. + +[include:example]: ./docs/Examples/TestCase.php +[//]: # (start: d64050243e2262fdd649a43b4d5b7f9784ba701372776c15d760357c38e581e1) +[//]: # (warning: Generated automatically. Do not edit.) ```php [!TIP] @@ -114,7 +124,7 @@ Makes comparison of scalars strict. ## PHPUnit `TestCase` -### [`RefreshDatabaseIfEmpty`](./src/Database/RefreshDatabaseIfEmpty.php) +### [`RefreshDatabaseIfEmpty`](./src/Database/RefreshDatabaseIfEmpty.php) 💀 [include:docblock]: ./src/Database/RefreshDatabaseIfEmpty.php [//]: # (start: 8a2c47eb73624557058f09279338b44619ddc48d2bd07d975721ad9383bd1df3) diff --git a/packages/testing/composer.json b/packages/testing/composer.json index 2ab5b9e53..a00975538 100644 --- a/packages/testing/composer.json +++ b/packages/testing/composer.json @@ -28,13 +28,20 @@ "composer/semver": "^3.2", "doctrine/sql-formatter": "^1.1", "http-interop/http-factory-guzzle": "^1.0.0", - "laravel/framework": "^10.34.0", + "illuminate/collections": "^10.34.0", + "illuminate/console": "^10.34.0", + "illuminate/container": "^10.34.0", + "illuminate/contracts": "^10.34.0", + "illuminate/database": "^10.34.0", + "illuminate/testing": "^10.34.0", + "illuminate/translation": "^10.34.0", "mockery/mockery": "^1.6.2", "opis/json-schema": "^2.3.0", "phpunit/phpunit": "^10.1.0", "psr/http-message": "^1.0.0|^2.0.0", "sebastian/comparator": "^5.0", "sebastian/exporter": "^5.0", + "symfony/deprecation-contracts": "^3.0.0", "symfony/filesystem": "^6.3.0", "symfony/http-foundation": "^6.3.0", "symfony/mime": "^6.3.0", @@ -42,7 +49,9 @@ "symfony/polyfill-php83": "^1.28" }, "require-dev": { + "fakerphp/faker": "^1.21.0", "guzzlehttp/psr7": "^1.9.1|^2.4.5", + "illuminate/http": "^10.34.0", "laravel/scout": "^9.8.0|^10.0.0", "orchestra/testbench": "^8.0.0", "symfony/console": "^6.3.0", @@ -74,6 +83,9 @@ "required-extensions": { "league/flysystem": [ "ext-fileinfo" + ], + "illuminate/console": [ + "ext-mbstring" ] } } diff --git a/packages/testing/docs/Assertions/AssertScoutQueryEquals.md b/packages/testing/docs/Assertions/AssertScoutQueryEquals.md index 6d1fa85f6..c5687e6a9 100644 --- a/packages/testing/docs/Assertions/AssertScoutQueryEquals.md +++ b/packages/testing/docs/Assertions/AssertScoutQueryEquals.md @@ -13,8 +13,8 @@ namespace LastDragon_ru\LaraASP\Testing\Docs\Assertions; use Illuminate\Database\Eloquent\Model; use Laravel\Scout\Builder; -use LastDragon_ru\LaraASP\GraphQL\Testing\Package\Requirements\RequiresLaravelScout; use LastDragon_ru\LaraASP\Testing\Assertions\ScoutAssertions; +use LastDragon_ru\LaraASP\Testing\Requirements\Requirements\RequiresComposerPackage; use Orchestra\Testbench\TestCase; use PHPUnit\Framework\Attributes\CoversNothing; @@ -22,7 +22,7 @@ use PHPUnit\Framework\Attributes\CoversNothing; * @internal */ #[CoversNothing] -#[RequiresLaravelScout] +#[RequiresComposerPackage('laravel/scout')] final class AssertScoutQueryEqualsTest extends TestCase { /** * Trait where assertion defined. diff --git a/packages/testing/docs/Examples/TestCase.php b/packages/testing/docs/Examples/TestCase.php new file mode 100644 index 000000000..e3e9219a5 --- /dev/null +++ b/packages/testing/docs/Examples/TestCase.php @@ -0,0 +1,13 @@ +overrides[$class])); + Container::getInstance()->bind( $class, ($this->overrides[$class])(...), diff --git a/packages/testing/src/Database/RefreshDatabaseIfEmpty.php b/packages/testing/src/Database/RefreshDatabaseIfEmpty.php index 0be3b4ccb..1f0790a74 100644 --- a/packages/testing/src/Database/RefreshDatabaseIfEmpty.php +++ b/packages/testing/src/Database/RefreshDatabaseIfEmpty.php @@ -4,7 +4,6 @@ use Illuminate\Container\Container; use Illuminate\Database\DatabaseManager; -use Illuminate\Foundation\Application; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabaseState; use PHPUnit\Framework\TestCase; @@ -14,7 +13,7 @@ * difference: it will refresh the database only if it is empty. This is very * useful for local testing and allow significantly reduce bootstrap time. * - * @property-read Application $app + * @deprecated ${version} Please use own trait. * * @phpstan-require-extends TestCase */ diff --git a/packages/testing/src/Database/RefreshDatabaseIfEmptyTest.php b/packages/testing/src/Database/RefreshDatabaseIfEmptyTest.php index 51a22366c..2c0fb828d 100644 --- a/packages/testing/src/Database/RefreshDatabaseIfEmptyTest.php +++ b/packages/testing/src/Database/RefreshDatabaseIfEmptyTest.php @@ -10,6 +10,7 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; /** + * @deprecated ${version} * @internal */ #[CoversClass(RefreshDatabaseIfEmpty::class)] diff --git a/packages/testing/src/Package/TestCase.php b/packages/testing/src/Package/TestCase.php index eee1dc7c1..aad9aa4d4 100644 --- a/packages/testing/src/Package/TestCase.php +++ b/packages/testing/src/Package/TestCase.php @@ -20,6 +20,8 @@ abstract class TestCase extends TestbenchTestCase { use Assertions; use Concerns; + use WithFaker; + use WithConfig; use WithTestData; use WithTempFile; use WithTempDirectory; diff --git a/packages/testing/src/Package/WithConfig.php b/packages/testing/src/Package/WithConfig.php new file mode 100644 index 000000000..5dfce08e4 --- /dev/null +++ b/packages/testing/src/Package/WithConfig.php @@ -0,0 +1,33 @@ + + * @phpstan-type SettingsCallback callable(static, Repository): Settings + * @phpstan-type SettingsFactory SettingsCallback|Settings|null + */ +trait WithConfig { + /** + * @param SettingsFactory $settings + */ + public function setConfig(callable|array|null $settings): void { + $repository = Container::getInstance()->make(Repository::class); + $settings = is_callable($settings) ? $settings($this, $repository) : $settings; + + if ($settings !== null) { + $repository->set($settings); + } + } +} diff --git a/packages/testing/src/Package/WithFaker.php b/packages/testing/src/Package/WithFaker.php new file mode 100644 index 000000000..350bf8b5e --- /dev/null +++ b/packages/testing/src/Package/WithFaker.php @@ -0,0 +1,33 @@ + + */ + private array $withFaker = []; + + #[After] + protected function withFakerAfter(): void { + $this->withFaker = []; + } + + protected function getFaker(string $locale = null): Generator { + $locale ??= Factory::DEFAULT_LOCALE; + $this->withFaker[$locale] ??= Factory::create($locale); + + return $this->withFaker[$locale]; + } +} diff --git a/packages/testing/src/Responses/Laravel/Json/ValidationErrorResponseTest.php b/packages/testing/src/Responses/Laravel/Json/ValidationErrorResponseTest.php index 645a7d80f..904847baa 100644 --- a/packages/testing/src/Responses/Laravel/Json/ValidationErrorResponseTest.php +++ b/packages/testing/src/Responses/Laravel/Json/ValidationErrorResponseTest.php @@ -3,9 +3,9 @@ namespace LastDragon_ru\LaraASP\Testing\Responses\Laravel\Json; use Illuminate\Container\Container; +use Illuminate\Contracts\Routing\Registrar; use Illuminate\Contracts\Validation\Factory as ValidatorFactory; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Route; use LastDragon_ru\LaraASP\Testing\Constraints\Response\Factory as ResponseFactory; use LastDragon_ru\LaraASP\Testing\Package\TestCase; use PHPUnit\Framework\Attributes\CoversClass; @@ -24,11 +24,12 @@ final class ValidationErrorResponseTest extends TestCase { * @param array|null $errors */ public function testEvaluate(bool $expected, array $rules, ?array $errors): void { - Route::get(__FUNCTION__, static function (Request $request) use ($rules) { - return Container::getInstance() - ->make(ValidatorFactory::class) - ->validate($request->all(), $rules); - }); + Container::getInstance()->make(Registrar::class) + ->get(__FUNCTION__, static function (Request $request) use ($rules) { + return Container::getInstance() + ->make(ValidatorFactory::class) + ->validate($request->all(), $rules); + }); $response = ResponseFactory::make($this->getJson(__FUNCTION__)); $constraint = new ValidationErrorResponse($errors); diff --git a/packages/testing/src/TestCase.php b/packages/testing/src/TestCase.php index 6a9a478e6..5e5690dcb 100644 --- a/packages/testing/src/TestCase.php +++ b/packages/testing/src/TestCase.php @@ -7,6 +7,15 @@ use LastDragon_ru\LaraASP\Testing\Concerns\Concerns; use LastDragon_ru\LaraASP\Testing\Utils\WithTestData; +use function trigger_deprecation; + +// phpcs:disable PSR1.Files.SideEffects + +trigger_deprecation(Package::Name, '${version}', 'Please use own base TestCase class.'); + +/** + * @deprecated ${version} Please use own class. + */ abstract class TestCase extends BaseTestCase { use Assertions; use Concerns; diff --git a/phpstan-baseline-well-known.neon b/phpstan-baseline-well-known.neon index 01fbb306d..9c3874205 100644 --- a/phpstan-baseline-well-known.neon +++ b/phpstan-baseline-well-known.neon @@ -1,4 +1,7 @@ parameters: + excludePaths: + - packages/testing/docs/Examples/TestCase.php + ignoreErrors: # Unwanted strict rules # (is there a better way to disable them?) @@ -54,8 +57,6 @@ parameters: message: "#^Creating callable from Mockery\\\\MockInterface but it might not be a callable\\.$#" paths: - packages/**/*Test.php - - packages/testing/src/Package/TestCase.php - - packages/testing/src/TestCase.php # False positive # https://github.com/phpstan/phpstan-mockery/issues/18 diff --git a/phpstan.neon b/phpstan.neon index 798b9705b..b845da7fd 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -26,8 +26,19 @@ parameters: classes: - PHPUnit\Framework\TestCase ignored: + - Tests\TestCase - LastDragon_ru\LaraASP\Testing\TestCase + # Forbidden + disallowedNamespaces: + - + namespace: Illuminate\Support\Facades\* + exclude: + - Illuminate\Support\Facades\Date + allowIn: + - dev/App/* + - packages/*/docs/* + includes: # Vendor - ./vendor-bin/phpstan/vendor/phpstan/phpstan/conf/bleedingEdge.neon