From a48e48e8349405db89cff1d2d445f610a1e7e463 Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Tue, 25 Aug 2026 15:30:25 +0600 Subject: [PATCH 001/179] 4.x: revamp skeleton folder structure for version 4.x --- src/Phaseolies/Application.php | 14 ++-- src/Phaseolies/Config/Config.php | 2 +- src/Phaseolies/Console/Command.php | 2 +- .../Commands/FrontendInstallCommand.php | 12 ++-- .../Commands/FrontendUninstallCommand.php | 22 +++---- .../Console/Commands/MakeAuthCommand.php | 64 +++++++++---------- .../Commands/MakeAuthorizerCommand.php | 2 +- .../Console/Commands/MakeConsoleCommand.php | 2 +- .../Commands/MakeControllerCommand.php | 6 +- .../Console/Commands/MakeHookCommand.php | 2 +- .../Console/Commands/MakeMailCommand.php | 2 +- .../Commands/MakeMiddlewareCommand.php | 2 +- .../Console/Commands/MakeModelCommand.php | 4 +- .../Console/Commands/MakeProviderCommand.php | 2 +- .../Console/Commands/MakeRequestCommand.php | 2 +- .../Console/Commands/MakeRuleCommand.php | 2 +- .../Console/Commands/MakeWatcherCommand.php | 2 +- .../Migrations/AddColumnMigrationCommand.php | 2 +- .../Migrations/CreateMigrationCommand.php | 2 +- .../Commands/Migrations/CreateSeedCommand.php | 2 +- .../Migrations/MigrateTemporalCommand.php | 2 +- .../Commands/PaginationPublishCommand.php | 2 +- .../Commands/Presenter/BundleCommand.php | 2 +- .../Commands/Presenter/PresenterCommand.php | 2 +- .../Console/Commands/ViewCacheCommand.php | 4 +- .../stubs/controller/layouts/complete.stub | 2 +- .../stubs/frontend/configs/tsconfig.stub | 4 +- .../Commands/stubs/frontend/configs/vite.stub | 4 +- .../Database/Migration/Migrator.php | 2 +- src/Phaseolies/Helpers/helpers.php | 6 +- .../Http/Controllers/Controller.php | 6 +- src/Phaseolies/Http/Response.php | 4 +- .../Providers/RouteServiceProvider.php | 2 +- src/Phaseolies/Support/Router.php | 2 +- .../InteractsWithDynamicControllerBinding.php | 2 +- tests/Application/ApplicationTest.php | 26 ++++---- tests/Console/CommandBehaviorCoverageTest.php | 36 +++++------ tests/Console/FrontendInstallCommandTest.php | 20 +++--- .../Support/CommandTestEnvironment.php | 2 +- 39 files changed, 140 insertions(+), 140 deletions(-) diff --git a/src/Phaseolies/Application.php b/src/Phaseolies/Application.php index 847c64c4..0134c67d 100644 --- a/src/Phaseolies/Application.php +++ b/src/Phaseolies/Application.php @@ -239,7 +239,7 @@ public function __construct() */ public function langPath($path = ''): string { - return $this->getPath($this->buildPathFragment('lang', $path)); + return $this->getPath($this->buildPathFragment('templates/lang', $path)); } /** @@ -486,7 +486,7 @@ protected function getPath(string $folder): string */ public function resourcesPath($path = ''): string { - return $this->resourcesPath = $this->getPath($this->buildPathFragment('resources', $path)); + return $this->resourcesPath = $this->getPath($this->buildPathFragment('templates', $path)); } /** @@ -497,7 +497,7 @@ public function resourcesPath($path = ''): string */ public function clientPath($path = ''): string { - return $this->clientPath = $this->getPath($this->buildPathFragment('resources/client', $path)); + return $this->clientPath = $this->getPath($this->buildPathFragment('templates/client', $path)); } /** @@ -508,7 +508,7 @@ public function clientPath($path = ''): string */ public function bootstrapPath($path = ''): string { - return $this->bootstrapPath = $this->getPath($this->buildPathFragment('bootstrap', $path)); + return $this->bootstrapPath = $this->getPath($this->buildPathFragment('runtime', $path)); } /** @@ -519,7 +519,7 @@ public function bootstrapPath($path = ''): string */ public function databasePath($path = ''): string { - return $this->databasePath = $this->getPath($this->buildPathFragment('database', $path)); + return $this->databasePath = $this->getPath($this->buildPathFragment('schema', $path)); } /** @@ -568,7 +568,7 @@ protected function buildPathFragment(string $prefix, string $path = ''): string */ public function appPath(): string { - return $this->appPath = $this->basePath(); + return $this->appPath = $this->getPath('src'); } /** @@ -588,7 +588,7 @@ public function basePath(): string */ public function configPath($path = ''): string { - return $this->configPath = $this->getPath("config/{$path}"); + return $this->configPath = $this->getPath("runtime/config/{$path}"); } /** diff --git a/src/Phaseolies/Config/Config.php b/src/Phaseolies/Config/Config.php index 2749752f..a7ec7d04 100644 --- a/src/Phaseolies/Config/Config.php +++ b/src/Phaseolies/Config/Config.php @@ -68,7 +68,7 @@ public static function initialize(): void */ protected static function getConfigFiles(): array { - return self::$configFiles ??= glob(base_path('config/*.php')) ?: []; + return self::$configFiles ??= glob(base_path('runtime/config/*.php')) ?: []; } /** diff --git a/src/Phaseolies/Console/Command.php b/src/Phaseolies/Console/Command.php index 5c8563a1..e5e9a313 100644 --- a/src/Phaseolies/Console/Command.php +++ b/src/Phaseolies/Console/Command.php @@ -52,7 +52,7 @@ public function registerCommands(Console $console): void return 'Phaseolies\\Console\\Commands' . $relativePath; }, $commandFiles); - $userDefineCommandsDir = base_path('app/Schedule/Commands'); + $userDefineCommandsDir = base_path('src/Schedule/Commands'); if (is_dir($userDefineCommandsDir)) { $files = []; $dirIterator = new RecursiveDirectoryIterator($userDefineCommandsDir); diff --git a/src/Phaseolies/Console/Commands/FrontendInstallCommand.php b/src/Phaseolies/Console/Commands/FrontendInstallCommand.php index 25195733..9620a158 100644 --- a/src/Phaseolies/Console/Commands/FrontendInstallCommand.php +++ b/src/Phaseolies/Console/Commands/FrontendInstallCommand.php @@ -159,8 +159,8 @@ protected function writeFrontendFiles(array $options, array &$state): void client_path('css/app.css') => $this->clientCss($cssStack), client_path('js/' . $this->bootstrapFilename($typescript)) => $this->bootstrapFile($cssStack, $typescript, $htmx), client_path('js/' . $this->entryFilename($framework, $typescript)) => $this->entryFile($framework, $cssStack, $typescript), - base_path('resources/views/layouts/app.odo.php') => $this->appLayoutView($framework, $typescript), - base_path('resources/views/welcome.odo.php') => $this->welcomeView($framework, $typescript), + base_path('templates/views/layouts/app.odo.php') => $this->appLayoutView($framework, $typescript), + base_path('templates/views/welcome.odo.php') => $this->welcomeView($framework, $typescript), ]; if ($cssStack === 'tailwind') { @@ -278,9 +278,9 @@ protected function trackFrontendDirectories(array &$state): void protected function trackedFrontendDirectories(): array { return [ - $this->projectPath('resources/client'), - $this->projectPath('resources/client/css'), - $this->projectPath('resources/client/js'), + $this->projectPath('templates/client'), + $this->projectPath('templates/client/css'), + $this->projectPath('templates/client/js'), $this->projectPath('public/build'), ]; } @@ -313,7 +313,7 @@ protected function projectPath(string $path = ''): string */ protected function entryFilePath(string $framework, bool $typescript): string { - return 'resources/client/js/' . $this->entryFilename($framework, $typescript); + return 'templates/client/js/' . $this->entryFilename($framework, $typescript); } /** diff --git a/src/Phaseolies/Console/Commands/FrontendUninstallCommand.php b/src/Phaseolies/Console/Commands/FrontendUninstallCommand.php index a51f98b8..6e834787 100644 --- a/src/Phaseolies/Console/Commands/FrontendUninstallCommand.php +++ b/src/Phaseolies/Console/Commands/FrontendUninstallCommand.php @@ -135,11 +135,11 @@ protected function performLegacyFrontendCleanup(bool $removeNodeModules = false) client_path('js/App.tsx'), client_path('js/App.vue'), client_path('js/App.svelte'), - base_path('client/css/app.css'), - base_path('client/js/app.js'), - base_path('client/js/app.ts'), - base_path('client/js/bootstrap.js'), - base_path('client/js/bootstrap.ts'), + base_path('templates/client/css/app.css'), + base_path('templates/client/js/app.js'), + base_path('templates/client/js/app.ts'), + base_path('templates/client/js/bootstrap.js'), + base_path('templates/client/js/bootstrap.ts'), base_path('client/js/main.js'), base_path('client/js/main.ts'), base_path('client/js/main.jsx'), @@ -195,7 +195,7 @@ protected function performLegacyFrontendCleanup(bool $removeNodeModules = false) protected function legacyFrontendDirectories(): array { return [ - $this->projectPath('resources/client'), + $this->projectPath('templates/client'), $this->projectPath('client'), ]; } @@ -226,7 +226,7 @@ protected function projectPath(string $path = ''): string */ protected function removeLegacyViteMarkersFromLayouts(): int { - $viewsPath = base_path('resources/views'); + $viewsPath = base_path('templates/views'); if (!is_dir($viewsPath)) { return 0; @@ -357,7 +357,7 @@ protected function isGeneratedViteConfig(string $contents): bool && str_contains($contents, "storage/framework/vite.hot") && str_contains($contents, "outDir: 'public/build'") && ( - str_contains($contents, "path.resolve(__dirname, 'resources/client')") + str_contains($contents, "path.resolve(__dirname, 'templates/client')") || str_contains($contents, "path.resolve(__dirname, 'client')") ); } @@ -378,13 +378,13 @@ protected function isGeneratedTsConfig(string $contents): bool return ($decoded['compilerOptions']['moduleResolution'] ?? null) === 'Bundler' && ($decoded['compilerOptions']['baseUrl'] ?? null) === '.' - && in_array(($decoded['compilerOptions']['paths']['@/*'][0] ?? null), ['resources/client/js/*', 'client/js/*'], true) + && in_array(($decoded['compilerOptions']['paths']['@/*'][0] ?? null), ['templates/client/js/*', 'client/js/*'], true) && ( - in_array('resources/client/**/*.ts', $decoded['include'] ?? [], true) + in_array('templates/client/**/*.ts', $decoded['include'] ?? [], true) || in_array('client/**/*.ts', $decoded['include'] ?? [], true) ) && ( - in_array('resources/client/**/*.tsx', $decoded['include'] ?? [], true) + in_array('templates/client/**/*.tsx', $decoded['include'] ?? [], true) || in_array('client/**/*.tsx', $decoded['include'] ?? [], true) ); } diff --git a/src/Phaseolies/Console/Commands/MakeAuthCommand.php b/src/Phaseolies/Console/Commands/MakeAuthCommand.php index d6525170..930fa5d7 100644 --- a/src/Phaseolies/Console/Commands/MakeAuthCommand.php +++ b/src/Phaseolies/Console/Commands/MakeAuthCommand.php @@ -57,9 +57,9 @@ public function handle(): int protected function createDirectories(): void { $paths = [ - base_path('app/Http/Controllers/Auth/'), - base_path('resources/views/auth/'), - base_path('resources/views/layouts/'), + base_path('src/Http/Controllers/Auth/'), + base_path('templates/views/auth/'), + base_path('templates/views/layouts/'), ]; foreach ($paths as $path) { @@ -75,27 +75,27 @@ protected function createDirectories(): void protected function generateControllers(): void { $this->createFile( - base_path('app/Http/Controllers/Auth/LoginController.php'), + base_path('src/Http/Controllers/Auth/LoginController.php'), $this->getStubContent('LoginController.stub') ); $this->createFile( - base_path('app/Http/Controllers/Auth/RegisterController.php'), + base_path('src/Http/Controllers/Auth/RegisterController.php'), $this->getStubContent('RegisterController.stub') ); $this->createFile( - base_path('app/Http/Controllers/Auth/TwoFactorAuthController.php'), + base_path('src/Http/Controllers/Auth/TwoFactorAuthController.php'), $this->getStubContent('TwoFactorAuthController.stub') ); $this->createFile( - base_path('app/Http/Controllers/HomeController.php'), + base_path('src/Http/Controllers/HomeController.php'), $this->getStubContent('HomeController.stub') ); $this->createFile( - base_path('app/Http/Controllers/ProfileController.php'), + base_path('src/Http/Controllers/ProfileController.php'), $this->getStubContent('ProfileController.stub') ); } @@ -115,7 +115,7 @@ protected function generateViews(): void ]; foreach ($views as $destination => $stubFile) { - $destinationPath = base_path('resources/views/' . $destination); + $destinationPath = base_path('templates/views/' . $destination); $content = $this->getStubContent($stubFile); $this->createFile($destinationPath, $content); } @@ -126,7 +126,7 @@ protected function generateViews(): void */ protected function appendRoutes(): void { - $routesPath = base_path('routes/web.php'); + $routesPath = base_path('runtime/routes/web.php'); if (!file_exists($routesPath)) { throw new RuntimeException('Routes file not found: ' . $routesPath); @@ -167,17 +167,17 @@ protected function getStubContent(string $stubName): string protected function authFilesExist(): bool { $filesToCheck = [ - base_path('app/Http/Controllers/Auth/LoginController.php'), - base_path('app/Http/Controllers/Auth/RegisterController.php'), - base_path('app/Http/Controllers/Auth/TwoFactorAuthController.php'), - base_path('app/Http/Controllers/HomeController.php'), - base_path('app/Http/Controllers/ProfileController.php'), - base_path('resources/views/auth/login.odo.php'), - base_path('resources/views/auth/2fa.odo.php'), - base_path('resources/views/auth/register.odo.php'), - base_path('resources/views/layouts/app.odo.php'), - base_path('resources/views/home.odo.php'), - base_path('resources/views/profile.odo.php'), + base_path('src/Http/Controllers/Auth/LoginController.php'), + base_path('src/Http/Controllers/Auth/RegisterController.php'), + base_path('src/Http/Controllers/Auth/TwoFactorAuthController.php'), + base_path('src/Http/Controllers/HomeController.php'), + base_path('src/Http/Controllers/ProfileController.php'), + base_path('templates/views/auth/login.odo.php'), + base_path('templates/views/auth/2fa.odo.php'), + base_path('templates/views/auth/register.odo.php'), + base_path('templates/views/layouts/app.odo.php'), + base_path('templates/views/home.odo.php'), + base_path('templates/views/profile.odo.php'), ]; foreach ($filesToCheck as $file) { @@ -196,19 +196,19 @@ protected function listExistingAuthFiles(): void { $files = [ 'Controllers' => [ - base_path('app/Http/Controllers/Auth/LoginController.php'), - base_path('app/Http/Controllers/Auth/RegisterController.php'), - base_path('app/Http/Controllers/Auth/TwoFactorAuthController.php'), - base_path('app/Http/Controllers/HomeController.php'), - base_path('app/Http/Controllers/ProfileController.php'), + base_path('src/Http/Controllers/Auth/LoginController.php'), + base_path('src/Http/Controllers/Auth/RegisterController.php'), + base_path('src/Http/Controllers/Auth/TwoFactorAuthController.php'), + base_path('src/Http/Controllers/HomeController.php'), + base_path('src/Http/Controllers/ProfileController.php'), ], 'Views' => [ - base_path('resources/views/auth/login.odo.php'), - base_path('resources/views/auth/register.odo.php'), - base_path('resources/views/auth/2fa.odo.php'), - base_path('resources/views/layouts/app.odo.php'), - base_path('resources/views/home.odo.php'), - base_path('resources/views/profile.odo.php'), + base_path('templates/views/auth/login.odo.php'), + base_path('templates/views/auth/register.odo.php'), + base_path('templates/views/auth/2fa.odo.php'), + base_path('templates/views/layouts/app.odo.php'), + base_path('templates/views/home.odo.php'), + base_path('templates/views/profile.odo.php'), ] ]; diff --git a/src/Phaseolies/Console/Commands/MakeAuthorizerCommand.php b/src/Phaseolies/Console/Commands/MakeAuthorizerCommand.php index add18ecf..8c5dd5c4 100644 --- a/src/Phaseolies/Console/Commands/MakeAuthorizerCommand.php +++ b/src/Phaseolies/Console/Commands/MakeAuthorizerCommand.php @@ -32,7 +32,7 @@ public function handle(): int $model = $this->option('model') ?? $this->option('m'); $namespace = 'App\\Authorizers' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Authorizers', $name); + $filePath = $this->generatedFilePath('src/Authorizers', $name); if (file_exists($filePath)) { $this->displayError('Authorizer already exists at:'); diff --git a/src/Phaseolies/Console/Commands/MakeConsoleCommand.php b/src/Phaseolies/Console/Commands/MakeConsoleCommand.php index 01266a37..95210e01 100644 --- a/src/Phaseolies/Console/Commands/MakeConsoleCommand.php +++ b/src/Phaseolies/Console/Commands/MakeConsoleCommand.php @@ -30,7 +30,7 @@ public function handle(): int return $this->executeWithTiming(function() { [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); $namespace = 'App\\Schedule\\Commands' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Schedule/Commands', $name); + $filePath = $this->generatedFilePath('src/Schedule/Commands', $name); if (file_exists($filePath)) { $this->displayError('Command already exists at:'); diff --git a/src/Phaseolies/Console/Commands/MakeControllerCommand.php b/src/Phaseolies/Console/Commands/MakeControllerCommand.php index f8b47720..2178e6b8 100644 --- a/src/Phaseolies/Console/Commands/MakeControllerCommand.php +++ b/src/Phaseolies/Console/Commands/MakeControllerCommand.php @@ -129,7 +129,7 @@ protected function replacePlaceholders( string $routeName ): string { $baseNamespace = 'App\\Http\\Controllers'; - $basePath = 'app/Http/Controllers/'; + $basePath = 'src/Http/Controllers/'; // Normalize route view name $routeView = str_replace(['\\', '/'], '.', $routeName); @@ -201,7 +201,7 @@ protected function resolveNamespacesAndPaths(string $name, bool $isApi): array $namespace = $baseNamespace . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); $filePath = $this->generatedFilePath( - 'app/Http/Controllers' . ($isApi ? '/API' : ''), + 'src/Http/Controllers' . ($isApi ? '/API' : ''), $name ); @@ -236,7 +236,7 @@ protected function generateLayout(string $namespace, string $className, string $ $layoutDir = base_path(str_replace( ['/', '\\'], DIRECTORY_SEPARATOR, - 'resources/views/' . $this->normalizeGeneratedName($routeName) + 'templates/views/' . $this->normalizeGeneratedName($routeName) )); $this->createDirIfMissing($layoutDir); $layoutPath = $layoutDir . '/default.odo.php'; diff --git a/src/Phaseolies/Console/Commands/MakeHookCommand.php b/src/Phaseolies/Console/Commands/MakeHookCommand.php index 72bb8d5d..a8eb35cb 100644 --- a/src/Phaseolies/Console/Commands/MakeHookCommand.php +++ b/src/Phaseolies/Console/Commands/MakeHookCommand.php @@ -30,7 +30,7 @@ public function handle(): int return $this->executeWithTiming(function() { [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); $namespace = 'App\\Hooks' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Hooks', $name); + $filePath = $this->generatedFilePath('src/Hooks', $name); // Check if hook already exists if (file_exists($filePath)) { diff --git a/src/Phaseolies/Console/Commands/MakeMailCommand.php b/src/Phaseolies/Console/Commands/MakeMailCommand.php index a95bb680..4c7d039d 100644 --- a/src/Phaseolies/Console/Commands/MakeMailCommand.php +++ b/src/Phaseolies/Console/Commands/MakeMailCommand.php @@ -36,7 +36,7 @@ public function handle(): int } $namespace = 'App\\Mail' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Mail', $name); + $filePath = $this->generatedFilePath('src/Mail', $name); // Check if Mailable already exists if (file_exists($filePath)) { diff --git a/src/Phaseolies/Console/Commands/MakeMiddlewareCommand.php b/src/Phaseolies/Console/Commands/MakeMiddlewareCommand.php index 86f2ca58..89d46153 100644 --- a/src/Phaseolies/Console/Commands/MakeMiddlewareCommand.php +++ b/src/Phaseolies/Console/Commands/MakeMiddlewareCommand.php @@ -30,7 +30,7 @@ public function handle(): int return $this->executeWithTiming(function() { [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); $namespace = 'App\\Http\\Middleware' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Http/Middleware', $name); + $filePath = $this->generatedFilePath('src/Http/Middleware', $name); // Check if middleware already exists if (file_exists($filePath)) { diff --git a/src/Phaseolies/Console/Commands/MakeModelCommand.php b/src/Phaseolies/Console/Commands/MakeModelCommand.php index 8ee5bf63..f97d47d5 100644 --- a/src/Phaseolies/Console/Commands/MakeModelCommand.php +++ b/src/Phaseolies/Console/Commands/MakeModelCommand.php @@ -51,7 +51,7 @@ public function handle(): int [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); $withMigration = $this->option('m'); $namespace = 'App\\Models' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Models', $name); + $filePath = $this->generatedFilePath('src/Models', $name); // Check if model already exists if (file_exists($filePath)) { @@ -129,6 +129,6 @@ protected function createMigration(string $name, string $table): string */ protected function getMigrationPath(): string { - return base_path('database/migrations'); + return base_path('schema/migrations'); } } diff --git a/src/Phaseolies/Console/Commands/MakeProviderCommand.php b/src/Phaseolies/Console/Commands/MakeProviderCommand.php index 42d3d2e4..b3a1fe68 100644 --- a/src/Phaseolies/Console/Commands/MakeProviderCommand.php +++ b/src/Phaseolies/Console/Commands/MakeProviderCommand.php @@ -30,7 +30,7 @@ public function handle(): int return $this->executeWithTiming(function () { [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); $namespace = 'App\\Providers' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Providers', $name); + $filePath = $this->generatedFilePath('src/Providers', $name); // Check if provider already exists if (file_exists($filePath)) { diff --git a/src/Phaseolies/Console/Commands/MakeRequestCommand.php b/src/Phaseolies/Console/Commands/MakeRequestCommand.php index 024ea32d..8f9624ea 100644 --- a/src/Phaseolies/Console/Commands/MakeRequestCommand.php +++ b/src/Phaseolies/Console/Commands/MakeRequestCommand.php @@ -36,7 +36,7 @@ public function handle(): int } $namespace = 'App\\Http\\Validations' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Http/Validations', $name); + $filePath = $this->generatedFilePath('src/Http/Validations', $name); // Check if request already exists if (file_exists($filePath)) { diff --git a/src/Phaseolies/Console/Commands/MakeRuleCommand.php b/src/Phaseolies/Console/Commands/MakeRuleCommand.php index a498329f..34711bc2 100644 --- a/src/Phaseolies/Console/Commands/MakeRuleCommand.php +++ b/src/Phaseolies/Console/Commands/MakeRuleCommand.php @@ -30,7 +30,7 @@ public function handle(): int return $this->executeWithTiming(function () { [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); $namespace = 'App\\Http\\Validations\\Rules' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Http/Validations/Rules', $name); + $filePath = $this->generatedFilePath('src/Http/Validations/Rules', $name); // Check if rule already exists if (file_exists($filePath)) { diff --git a/src/Phaseolies/Console/Commands/MakeWatcherCommand.php b/src/Phaseolies/Console/Commands/MakeWatcherCommand.php index ef382bff..9e1f9ffc 100644 --- a/src/Phaseolies/Console/Commands/MakeWatcherCommand.php +++ b/src/Phaseolies/Console/Commands/MakeWatcherCommand.php @@ -30,7 +30,7 @@ public function handle(): int return $this->executeWithTiming(function () { [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); $namespace = 'App\\Watchers' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Watchers', $name); + $filePath = $this->generatedFilePath('src/Watchers', $name); if (file_exists($filePath)) { $this->displayError('Watcher already exists at:'); diff --git a/src/Phaseolies/Console/Commands/Migrations/AddColumnMigrationCommand.php b/src/Phaseolies/Console/Commands/Migrations/AddColumnMigrationCommand.php index 6f144e9c..154be94f 100644 --- a/src/Phaseolies/Console/Commands/Migrations/AddColumnMigrationCommand.php +++ b/src/Phaseolies/Console/Commands/Migrations/AddColumnMigrationCommand.php @@ -76,6 +76,6 @@ public function handle(): int */ protected function getMigrationPath(): string { - return base_path('database/migrations'); + return base_path('schema/migrations'); } } diff --git a/src/Phaseolies/Console/Commands/Migrations/CreateMigrationCommand.php b/src/Phaseolies/Console/Commands/Migrations/CreateMigrationCommand.php index 947b8727..2b8b6b68 100644 --- a/src/Phaseolies/Console/Commands/Migrations/CreateMigrationCommand.php +++ b/src/Phaseolies/Console/Commands/Migrations/CreateMigrationCommand.php @@ -78,6 +78,6 @@ public function handle(): int */ protected function getMigrationPath(): string { - return base_path('database/migrations'); + return base_path('schema/migrations'); } } diff --git a/src/Phaseolies/Console/Commands/Migrations/CreateSeedCommand.php b/src/Phaseolies/Console/Commands/Migrations/CreateSeedCommand.php index 66a04001..3e161cec 100644 --- a/src/Phaseolies/Console/Commands/Migrations/CreateSeedCommand.php +++ b/src/Phaseolies/Console/Commands/Migrations/CreateSeedCommand.php @@ -29,7 +29,7 @@ public function handle(): int { return $this->executeWithTiming(function() { $name = $this->argument('name'); - $filePath = base_path('database/seeders/' . $name . '.php'); + $filePath = base_path('schema/seeders/' . $name . '.php'); if (file_exists($filePath)) { $this->displayError('Seed file already exists!'); diff --git a/src/Phaseolies/Console/Commands/Migrations/MigrateTemporalCommand.php b/src/Phaseolies/Console/Commands/Migrations/MigrateTemporalCommand.php index 4dc9eb68..90da28ca 100644 --- a/src/Phaseolies/Console/Commands/Migrations/MigrateTemporalCommand.php +++ b/src/Phaseolies/Console/Commands/Migrations/MigrateTemporalCommand.php @@ -37,7 +37,7 @@ public function handle(): int return $this->executeWithTiming(function () { $connection = $this->option('connection') ?: null; $dryRun = (bool) $this->option('show'); - $modelsPath = $this->option('path') ?: base_path('app/Models'); + $modelsPath = $this->option('path') ?: base_path('src/Models'); $connectionLabel = $connection ?: 'per-model'; diff --git a/src/Phaseolies/Console/Commands/PaginationPublishCommand.php b/src/Phaseolies/Console/Commands/PaginationPublishCommand.php index b4f64c88..23b2bfce 100644 --- a/src/Phaseolies/Console/Commands/PaginationPublishCommand.php +++ b/src/Phaseolies/Console/Commands/PaginationPublishCommand.php @@ -18,7 +18,7 @@ class PaginationPublishCommand extends Command * * @var string */ - protected $description = 'Publish pagination views to resources/views/vendor/pagination'; + protected $description = 'Publish pagination views to templates/views/vendor/pagination'; /** * Execute the console command. diff --git a/src/Phaseolies/Console/Commands/Presenter/BundleCommand.php b/src/Phaseolies/Console/Commands/Presenter/BundleCommand.php index 51812a46..8dbe73ae 100644 --- a/src/Phaseolies/Console/Commands/Presenter/BundleCommand.php +++ b/src/Phaseolies/Console/Commands/Presenter/BundleCommand.php @@ -30,7 +30,7 @@ public function handle(): int return $this->executeWithTiming(function () { [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); $namespace = 'App\\Http\\Presenters' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Http/Presenters', $name); + $filePath = $this->generatedFilePath('src/Http/Presenters', $name); if (file_exists($filePath)) { $this->displayError('Bundle class already exists at:'); diff --git a/src/Phaseolies/Console/Commands/Presenter/PresenterCommand.php b/src/Phaseolies/Console/Commands/Presenter/PresenterCommand.php index 873e874b..5fbfeb8a 100644 --- a/src/Phaseolies/Console/Commands/Presenter/PresenterCommand.php +++ b/src/Phaseolies/Console/Commands/Presenter/PresenterCommand.php @@ -30,7 +30,7 @@ public function handle(): int return $this->executeWithTiming(function () { [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); $namespace = 'App\\Http\\Presenters' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('app/Http/Presenters', $name); + $filePath = $this->generatedFilePath('src/Http/Presenters', $name); if (file_exists($filePath)) { $this->displayError('Presenters already exists at:'); diff --git a/src/Phaseolies/Console/Commands/ViewCacheCommand.php b/src/Phaseolies/Console/Commands/ViewCacheCommand.php index 376970ee..d1f5a0b6 100644 --- a/src/Phaseolies/Console/Commands/ViewCacheCommand.php +++ b/src/Phaseolies/Console/Commands/ViewCacheCommand.php @@ -37,7 +37,7 @@ class ViewCacheCommand extends Command public function handle(): int { return $this->executeWithTiming(function() { - $viewPath = base_path('resources/views'); + $viewPath = base_path('templates/views'); $cachePath = base_path('storage/framework/views'); // Validate directories @@ -77,7 +77,7 @@ protected function compileViews(array $viewFiles): array $results = ['success' => [], 'failed' => []]; foreach ($viewFiles as $file) { - $relativePath = $this->relativePath($file, base_path('resources/views')); + $relativePath = $this->relativePath($file, base_path('templates/views')); $viewName = str_replace(['/', '.odo.php'], ['.', ''], $relativePath); try { diff --git a/src/Phaseolies/Console/Commands/stubs/controller/layouts/complete.stub b/src/Phaseolies/Console/Commands/stubs/controller/layouts/complete.stub index d37e125e..f7561a5b 100644 --- a/src/Phaseolies/Console/Commands/stubs/controller/layouts/complete.stub +++ b/src/Phaseolies/Console/Commands/stubs/controller/layouts/complete.stub @@ -20,7 +20,7 @@

The following files were created for you:

diff --git a/src/Phaseolies/Console/Commands/stubs/frontend/configs/tsconfig.stub b/src/Phaseolies/Console/Commands/stubs/frontend/configs/tsconfig.stub index 7491ad18..13fb1b13 100644 --- a/src/Phaseolies/Console/Commands/stubs/frontend/configs/tsconfig.stub +++ b/src/Phaseolies/Console/Commands/stubs/frontend/configs/tsconfig.stub @@ -12,8 +12,8 @@ {{ jsxOption }} "baseUrl": ".", "paths": { - "@/*": ["resources/client/js/*"] + "@/*": ["templates/client/js/*"] } }, - "include": ["resources/client/**/*.ts", "resources/client/**/*.tsx", "resources/client/**/*.vue", "resources/client/**/*.svelte"] + "include": ["templates/client/**/*.ts", "templates/client/**/*.tsx", "templates/client/**/*.vue", "templates/client/**/*.svelte"] } diff --git a/src/Phaseolies/Console/Commands/stubs/frontend/configs/vite.stub b/src/Phaseolies/Console/Commands/stubs/frontend/configs/vite.stub index 40072f84..2cc73c21 100644 --- a/src/Phaseolies/Console/Commands/stubs/frontend/configs/vite.stub +++ b/src/Phaseolies/Console/Commands/stubs/frontend/configs/vite.stub @@ -46,8 +46,8 @@ export default defineConfig({ publicDir: false, resolve: { alias: { - '~client': path.resolve(__dirname, 'resources/client'), - '@': path.resolve(__dirname, 'resources/client/js'), + '~client': path.resolve(__dirname, 'templates/client'), + '@': path.resolve(__dirname, 'templates/client/js'), }, }, server: { diff --git a/src/Phaseolies/Database/Migration/Migrator.php b/src/Phaseolies/Database/Migration/Migrator.php index 9748df45..b3f95a33 100644 --- a/src/Phaseolies/Database/Migration/Migrator.php +++ b/src/Phaseolies/Database/Migration/Migrator.php @@ -171,7 +171,7 @@ public function getMigrationFiles(?string $connection = null): array /** * 🧠 Build a map by basename so project migrations override vendor ones * Example: - * 2025_10_11_000001_create_users_table.php → pick from database/migrations if exists + * 2025_10_11_000001_create_users_table.php → pick from schema/migrations if exists */ $migrationMap = []; diff --git a/src/Phaseolies/Helpers/helpers.php b/src/Phaseolies/Helpers/helpers.php index 397c6f2e..fcf91c32 100644 --- a/src/Phaseolies/Helpers/helpers.php +++ b/src/Phaseolies/Helpers/helpers.php @@ -326,10 +326,10 @@ function route(string $name, mixed $params = []): ?string * Retrieve a configuration value by key. * * @param string $key - * @param string $default + * @param mixed $default * @return mixed */ - function config(string|array $key, ?string $default = null): mixed + function config(string|array $key, mixed $default = null): mixed { if (is_array($key)) { foreach ($key as $k => $v) { @@ -415,7 +415,7 @@ function base_path(string $path = ''): string if ($basePath === null) { if (app()->runningInConsole()) { - $basePath = rtrim(getcwd(), DIRECTORY_SEPARATOR); + $basePath = rtrim(getcwd(), DIRECTORY_SEPARATOR); } elseif (defined('BASE_PATH')) { $basePath = rtrim(BASE_PATH, DIRECTORY_SEPARATOR); } else { diff --git a/src/Phaseolies/Http/Controllers/Controller.php b/src/Phaseolies/Http/Controllers/Controller.php index 90ae5f4d..2e8c46f1 100644 --- a/src/Phaseolies/Http/Controllers/Controller.php +++ b/src/Phaseolies/Http/Controllers/Controller.php @@ -129,7 +129,7 @@ public function __construct() { parent::__construct(); $this->setFileExtension('.odo.php'); - $this->setViewFolder('resources/views' . DIRECTORY_SEPARATOR); + $this->setViewFolder('templates/views' . DIRECTORY_SEPARATOR); $this->setCacheFolder('storage/framework/views' . DIRECTORY_SEPARATOR); $this->createCacheFolder(); $this->setSymlinkPathFolder('storage/app/public' . DIRECTORY_SEPARATOR); @@ -320,9 +320,9 @@ protected function findNamespacedView(string $view): string $viewPath = str_replace('.', DIRECTORY_SEPARATOR, $viewName); - // First check published views in resources/views/vendor/{namespace} + // First check published views in templates/views/vendor/{namespace} // Prioritize published views over package views - $publishedPath = base_path('resources/views/vendor/' . $namespace); + $publishedPath = base_path('templates/views/vendor/' . $namespace); if (is_dir($publishedPath)) { $possiblePaths = [ $publishedPath . DIRECTORY_SEPARATOR . $viewPath . $this->fileExtension, diff --git a/src/Phaseolies/Http/Response.php b/src/Phaseolies/Http/Response.php index e2c2ce44..b0cf97be 100644 --- a/src/Phaseolies/Http/Response.php +++ b/src/Phaseolies/Http/Response.php @@ -662,7 +662,7 @@ public static function dispatchHttpException(HttpException $exception): void */ protected static function renderErrorPage(int $status, string $message): void { - $customPath = base_path("resources/views/errors/{$status}.odo.php"); + $customPath = base_path("templates/views/errors/{$status}.odo.php"); $errorPage = base_path("vendor/doppar/framework/src/Phaseolies/Support/View/errors/{$status}.odo.php"); if (file_exists($customPath)) { @@ -734,7 +734,7 @@ public function renderView(string $view, array $data = []): string ob_start(); - include base_path("resources/views/{$viewPath}.odo.php"); + include base_path("templates/views/{$viewPath}.odo.php"); return ob_get_clean(); } diff --git a/src/Phaseolies/Providers/RouteServiceProvider.php b/src/Phaseolies/Providers/RouteServiceProvider.php index 07cc089e..62f2f21f 100644 --- a/src/Phaseolies/Providers/RouteServiceProvider.php +++ b/src/Phaseolies/Providers/RouteServiceProvider.php @@ -39,7 +39,7 @@ public function boot() $this->app->router->loadAttributeBasedRoutes(); - Route::group(['prefix' => 'api'], fn() => require base_path('routes/api.php')); + Route::group(['prefix' => 'api'], fn() => require base_path('runtime/routes/api.php')); if ($this->app->router->shouldCacheRoutes()) { $this->app->router->cacheRoutes(); diff --git a/src/Phaseolies/Support/Router.php b/src/Phaseolies/Support/Router.php index b922ce9c..3c36d8ae 100644 --- a/src/Phaseolies/Support/Router.php +++ b/src/Phaseolies/Support/Router.php @@ -1041,7 +1041,7 @@ protected function getOriginalClosure(Request $request): mixed protected function loadRoutesFromFiles(): void { $routeFiles = [ - base_path('routes/web.php') + base_path('runtime/routes/web.php') ]; foreach ($routeFiles as $file) { diff --git a/src/Phaseolies/Support/Router/InteractsWithDynamicControllerBinding.php b/src/Phaseolies/Support/Router/InteractsWithDynamicControllerBinding.php index e20ac9e4..a53ae1dd 100644 --- a/src/Phaseolies/Support/Router/InteractsWithDynamicControllerBinding.php +++ b/src/Phaseolies/Support/Router/InteractsWithDynamicControllerBinding.php @@ -151,7 +151,7 @@ protected function isControllerClass(string $class): bool */ protected function scanDefaultControllerDirectory(): array { - $controllerPath = base_path('app/Http/Controllers'); + $controllerPath = base_path('src/Http/Controllers'); $controllers = []; if (!is_dir($controllerPath)) { diff --git a/tests/Application/ApplicationTest.php b/tests/Application/ApplicationTest.php index 35ed2fc5..b12be02b 100644 --- a/tests/Application/ApplicationTest.php +++ b/tests/Application/ApplicationTest.php @@ -107,14 +107,14 @@ protected function tearDown(): void private function createDirectoryStructure(): void { $dirs = [ - '/config', - '/bootstrap', - '/database/migrations', + '/runtime/config', + '/runtime', + '/schema/migrations', '/public', '/storage', - '/resources', - '/resources/lang', - '/app', + '/templates', + '/templates/lang', + '/src', ]; foreach ($dirs as $dir) { @@ -122,7 +122,7 @@ private function createDirectoryStructure(): void } // Create minimal config file - file_put_contents($this->tempBasePath . '/config/app.php', "tempBasePath . '/runtime/config/app.php', " 'testing', 'locale' => 'en', 'fallback_locale' => 'en', @@ -185,14 +185,14 @@ public function testApplicationIsContainerInstance(): void public function testPathMethodsReturnCorrectPaths(): void { $stringService = app(StringService::class); - $this->assertStringEndsWith('/resources/views', $stringService->urlHarmonize($this->app->resourcesPath('views'))); - $this->assertStringEndsWith('/resources/client/js/pages', $stringService->urlHarmonize($this->app->clientPath('js\\pages'))); - $this->assertStringEndsWith('/bootstrap/cache', $stringService->urlHarmonize($this->app->bootstrapPath('cache'))); - $this->assertStringEndsWith('/database/migrations', $stringService->urlHarmonize($this->app->databasePath('migrations'))); + $this->assertStringEndsWith('/templates/views', $stringService->urlHarmonize($this->app->resourcesPath('views'))); + $this->assertStringEndsWith('/templates/client/js/pages', $stringService->urlHarmonize($this->app->clientPath('js\\pages'))); + $this->assertStringEndsWith('/runtime/cache', $stringService->urlHarmonize($this->app->bootstrapPath('cache'))); + $this->assertStringEndsWith('/schema/migrations', $stringService->urlHarmonize($this->app->databasePath('migrations'))); $this->assertStringEndsWith('/public/assets', $stringService->urlHarmonize($this->app->publicPath('assets'))); $this->assertStringEndsWith('/storage/logs', $stringService->urlHarmonize($this->app->storagePath('logs'))); - $this->assertStringEndsWith('/config/app.php', $stringService->urlHarmonize($this->app->configPath('app.php'))); - $this->assertStringEndsWith('/lang/en', $stringService->urlHarmonize($this->app->langPath('en'))); + $this->assertStringEndsWith('/runtime/config/app.php', $stringService->urlHarmonize($this->app->configPath('app.php'))); + $this->assertStringEndsWith('/templates/lang/en', $stringService->urlHarmonize($this->app->langPath('en'))); } public function testPathCaching(): void diff --git a/tests/Console/CommandBehaviorCoverageTest.php b/tests/Console/CommandBehaviorCoverageTest.php index 638a6305..7c82a3e7 100644 --- a/tests/Console/CommandBehaviorCoverageTest.php +++ b/tests/Console/CommandBehaviorCoverageTest.php @@ -73,7 +73,7 @@ public function testMakeConsoleCommandCreatesKebabCaseCommandClass(): void $command->fakeArguments['name'] = 'ReportsSyncCommand'; $result = $command->handle(); - $file = Env::path('app/Schedule/Commands/ReportsSyncCommand.php'); + $file = Env::path('src/Schedule/Commands/ReportsSyncCommand.php'); $this->assertSame(0, $result); $this->assertFileExists($file); @@ -88,16 +88,16 @@ public function testMakeAuthCommandGeneratesExpectedFilesAndRoutes(): void use InteractsWithFakeCommandIO; }; - $routesPath = Env::path('routes/web.php'); + $routesPath = Env::path('runtime/routes/web.php'); mkdir(dirname($routesPath), 0755, true); file_put_contents($routesPath, "handle(); $this->assertSame(0, $result); - $this->assertFileExists(Env::path('app/Http/Controllers/Auth/LoginController.php')); - $this->assertFileExists(Env::path('resources/views/auth/login.odo.php')); - $this->assertFileExists(Env::path('resources/views/layouts/app.odo.php')); + $this->assertFileExists(Env::path('src/Http/Controllers/Auth/LoginController.php')); + $this->assertFileExists(Env::path('templates/views/auth/login.odo.php')); + $this->assertFileExists(Env::path('templates/views/layouts/app.odo.php')); $this->assertSame("assertContains('Authentication scaffolding generated successfully', $command->capturedSuccesses); } @@ -122,7 +122,7 @@ public function testMakeControllerCommandValidatesConflictingFlagsAndBuildsPlace $this->assertStringContainsString('namespace App\\Http\\Controllers\\Admin;', $content); $this->assertStringContainsString('class UserController', $content); $this->assertStringContainsString('view admin.users', $content); - $this->assertStringContainsString('path app/Http/Controllers/Admin/UserController.php', $content); + $this->assertStringContainsString('path src/Http/Controllers/Admin/UserController.php', $content); } public function testCommandHelpersNormalizeGeneratedNamesAndRelativePaths(): void @@ -140,8 +140,8 @@ public function testCommandHelpersNormalizeGeneratedNamesAndRelativePaths(): voi $this->assertSame(['Admin', 'Hello'], $parts); $this->assertSame('TestProvider', $className); $this->assertSame( - 'app/Providers/Hello/TestProvider.php', - $this->invokeMethod($command, 'relativePath', [Env::path('app/Providers/Hello/TestProvider.php')]) + 'src/Providers/Hello/TestProvider.php', + $this->invokeMethod($command, 'relativePath', [Env::path('src/Providers/Hello/TestProvider.php')]) ); } @@ -155,7 +155,7 @@ public function testMakeProviderCommandAcceptsBackslashesAndOutputsRelativePathW $command->fakeArguments['name'] = 'Hello\\TestProvider'; $result = $command->handle(); - $file = Env::path('app/Providers/Hello/TestProvider.php'); + $file = Env::path('src/Providers/Hello/TestProvider.php'); $contents = (string) file_get_contents($file); $lines = array_map(static fn(array $line): string => $line[0], $command->capturedLines); @@ -164,7 +164,7 @@ public function testMakeProviderCommandAcceptsBackslashesAndOutputsRelativePathW $this->assertStringContainsString('namespace App\\Providers\\Hello;', $contents); $this->assertStringContainsString('class TestProvider extends ServiceProvider', $contents); $this->assertContains( - '📦 File: app/Providers/Hello/TestProvider.php', + '📦 File: src/Providers/Hello/TestProvider.php', $lines ); } @@ -194,11 +194,11 @@ protected function getLayoutStub(string $stubName): string $this->assertSame('App\\Http\\Controllers\\Admin', $namespace); $this->assertSame( - str_replace(['/', '\\'], DIRECTORY_SEPARATOR, Env::path('app/Http/Controllers/Admin/UserController.php')), + str_replace(['/', '\\'], DIRECTORY_SEPARATOR, Env::path('src/Http/Controllers/Admin/UserController.php')), $filePath ); $this->assertSame('UserController', $className); - $this->assertFileExists(Env::path('resources/views/admin/users/default.odo.php')); + $this->assertFileExists(Env::path('templates/views/admin/users/default.odo.php')); } public function testMakeAuthorizerCommandGeneratesModelAwarePolicyMethods(): void @@ -338,8 +338,8 @@ public function testMigrationCommandsPassExpectedArgumentsToCreator(): void $this->assertSame(0, $addColumn->handle()); $this->assertSame( [ - ['create_users_table', Env::path('database/migrations'), 'users', true], - ['add_status_to_orders', Env::path('database/migrations'), 'orders', false, 'status', 'string', 'name'], + ['create_users_table', Env::path('schema/migrations'), 'users', true], + ['add_status_to_orders', Env::path('schema/migrations'), 'orders', false, 'status', 'string', 'name'], ], $calls ); @@ -355,7 +355,7 @@ public function testPaginationPublishCommandCreatesFilesAndSkipsDuplicates(): vo $firstRun = $command->handle(); $secondRun = $command->handle(); - $paginationDir = Env::path('resources/views/vendor/pagination'); + $paginationDir = Env::path('templates/views/vendor/pagination'); $this->assertSame(0, $firstRun); $this->assertSame(0, $secondRun); @@ -541,13 +541,13 @@ public function testViewCacheCommandDiscoversViewsAndCreatesCacheDirectory(): vo use InteractsWithFakeCommandIO; }; - $viewDir = Env::path('resources/views/admin'); + $viewDir = Env::path('templates/views/admin'); mkdir($viewDir, 0755, true); file_put_contents($viewDir . '/dashboard.odo.php', '

Dashboard

'); $cacheDir = Env::path('storage/framework/views'); - $this->invokeMethod($command, 'ensureDirectoriesExist', [Env::path('resources/views'), $cacheDir]); - $files = $this->invokeMethod($command, 'getAllViewFiles', [Env::path('resources/views')]); + $this->invokeMethod($command, 'ensureDirectoriesExist', [Env::path('templates/views'), $cacheDir]); + $files = $this->invokeMethod($command, 'getAllViewFiles', [Env::path('templates/views')]); $this->assertDirectoryExists($cacheDir); $this->assertSame([realpath($viewDir . '/dashboard.odo.php')], $files); diff --git a/tests/Console/FrontendInstallCommandTest.php b/tests/Console/FrontendInstallCommandTest.php index 5ebf6db0..0a3c68df 100644 --- a/tests/Console/FrontendInstallCommandTest.php +++ b/tests/Console/FrontendInstallCommandTest.php @@ -16,7 +16,7 @@ public function testReactTypescriptUsesMainEntryFile(): void $pathMethod = new \ReflectionMethod($command, 'entryFilePath'); $this->assertSame('main.tsx', $filenameMethod->invoke($command, 'react', true)); - $this->assertSame('resources/client/js/main.tsx', $pathMethod->invoke($command, 'react', true)); + $this->assertSame('templates/client/js/main.tsx', $pathMethod->invoke($command, 'react', true)); } public function testVanillaWelcomeUsesSharedAppLayout(): void @@ -57,7 +57,7 @@ public function testClientFrameworkWelcomeUsesSharedLayoutShell(): void $this->assertStringContainsString("#extends('layouts.app')", $welcome); $this->assertStringContainsString('#section(\'content\')', $welcome); $this->assertStringContainsString('
', $welcome); - $this->assertStringContainsString("#vite('resources/client/js/main.ts')", $layout); + $this->assertStringContainsString("#vite('templates/client/js/main.ts')", $layout); $this->assertStringContainsString('', $layout); $this->assertStringContainsString('window.__DOPPAR_FRONTEND__', $layout); $this->assertStringContainsString('csrfToken: "[[ csrf_token() ]]"', $layout); @@ -72,7 +72,7 @@ public function testVanillaAppLayoutUsesAppEntrypoint(): void $layout = $method->invoke($command, 'vanilla', true); - $this->assertStringContainsString("#vite('resources/client/js/app.ts')", $layout); + $this->assertStringContainsString("#vite('templates/client/js/app.ts')", $layout); $this->assertStringContainsString("#yield('content')", $layout); } @@ -85,7 +85,7 @@ public function testViteConfigTargetsMainReactEntrypoint(): void $config = $method->invoke($command, 'react', true); $entryFile = $entryMethod->invoke($command, 'react', 'none', true); - $this->assertStringContainsString("input: ['resources/client/js/main.tsx']", $config); + $this->assertStringContainsString("input: ['templates/client/js/main.tsx']", $config); $this->assertStringContainsString("publicDir: false", $config); $this->assertStringContainsString('fs.writeFileSync(hotFile, `${protocol}://${host}:${address.port}`);', $config); $this->assertStringContainsString("import './bootstrap';", $entryFile); @@ -172,9 +172,9 @@ public function testFrontendInstallTracksResourcesClientDirectories(): void $directories = array_map($this->normalizePath(...), $method->invoke($command)); - $this->assertContains($this->normalizePath(getcwd() . '/resources/client'), $directories); - $this->assertContains($this->normalizePath(getcwd() . '/resources/client/css'), $directories); - $this->assertContains($this->normalizePath(getcwd() . '/resources/client/js'), $directories); + $this->assertContains($this->normalizePath(getcwd() . '/templates/client'), $directories); + $this->assertContains($this->normalizePath(getcwd() . '/templates/client/css'), $directories); + $this->assertContains($this->normalizePath(getcwd() . '/templates/client/js'), $directories); } public function testFrontendUninstallCommandIsRegisteredWithExpectedSignature(): void @@ -195,7 +195,7 @@ public function testFrontendUninstallStripsInjectedViteMarkersFromLayouts(): voi - #vite('resources/client/js/main.tsx') + #vite('templates/client/js/main.tsx') @@ -207,7 +207,7 @@ public function testFrontendUninstallStripsInjectedViteMarkersFromLayouts(): voi $updated = $method->invoke($command, $contents); $this->assertStringNotContainsString('DOPPAR_FRONTEND_VITE_START', $updated); - $this->assertStringNotContainsString("#vite('resources/client/js/main.tsx')", $updated); + $this->assertStringNotContainsString("#vite('templates/client/js/main.tsx')", $updated); $this->assertStringNotContainsString('
', $updated); } @@ -218,7 +218,7 @@ public function testFrontendUninstallLegacyDirectoriesIncludeResourcesClient(): $directories = array_map($this->normalizePath(...), $method->invoke($command)); - $this->assertContains($this->normalizePath(getcwd() . '/resources/client'), $directories); + $this->assertContains($this->normalizePath(getcwd() . '/templates/client'), $directories); $this->assertContains($this->normalizePath(getcwd() . '/client'), $directories); } diff --git a/tests/Console/Support/CommandTestEnvironment.php b/tests/Console/Support/CommandTestEnvironment.php index 6c4c39c2..cb358daa 100644 --- a/tests/Console/Support/CommandTestEnvironment.php +++ b/tests/Console/Support/CommandTestEnvironment.php @@ -263,7 +263,7 @@ function storage_path(string $path = ''): string if (!function_exists(__NAMESPACE__ . '\resource_path')) { function resource_path(string $path = ''): string { - return CommandTestEnvironment::path('resources/' . ltrim($path, '/')); + return CommandTestEnvironment::path('templates/' . ltrim($path, '/')); } } From 7b21d01f74e57573bcfda47f9404e962c54ce0fb Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Tue, 25 Aug 2026 18:56:37 +0600 Subject: [PATCH 002/179] techmahedy-4.x: database_path and resource_path function name changed: --- src/Phaseolies/Application.php | 22 +- .../Commands/FrontendInstallCommand.php | 2 +- .../Commands/PaginationPublishCommand.php | 4 +- .../Database/Migration/Migrator.php | 2 +- src/Phaseolies/Helpers/helpers.php | 20 +- .../Providers/PackageServiceProvider.php | 4 +- src/Phaseolies/Support/Facades/App.php | 4 +- src/Phaseolies/Utilities/Paginator.php | 4 +- tests/Application/ApplicationTest.php | 4 +- .../Support/CommandTestEnvironment.php | 334 +++++++++--------- .../Database/ModelQueryDriverTestCase.php | 4 +- 11 files changed, 201 insertions(+), 203 deletions(-) diff --git a/src/Phaseolies/Application.php b/src/Phaseolies/Application.php index 0134c67d..7a6950c4 100644 --- a/src/Phaseolies/Application.php +++ b/src/Phaseolies/Application.php @@ -56,7 +56,7 @@ class Application extends Container * * @var string */ - protected $resourcesPath; + protected $templatesPath; /** * The path to the client-side assets directory. @@ -84,7 +84,7 @@ class Application extends Container * * @var string */ - protected $databasePath; + protected $schemaPath; /** * The path to the public directory. @@ -454,10 +454,10 @@ protected function setNecessaryFolderPath(): void $this->configPath = $this->configPath(); $this->appPath = $this->appPath(); $this->bootstrapPath = $this->bootstrapPath(); - $this->databasePath = $this->databasePath(); + $this->schemaPath = $this->schemaPath(); $this->publicPath = $this->publicPath(); $this->storagePath = $this->storagePath(); - $this->resourcesPath = $this->resourcesPath(); + $this->templatesPath = $this->templatesPath(); $this->clientPath = $this->clientPath(); } @@ -484,9 +484,9 @@ protected function getPath(string $folder): string * @param string $path * @return string */ - public function resourcesPath($path = ''): string + public function templatesPath($path = ''): string { - return $this->resourcesPath = $this->getPath($this->buildPathFragment('templates', $path)); + return $this->templatesPath = $this->getPath($this->buildPathFragment('templates', $path)); } /** @@ -517,9 +517,9 @@ public function bootstrapPath($path = ''): string * @param string $path * @return string */ - public function databasePath($path = ''): string + public function schemaPath($path = ''): string { - return $this->databasePath = $this->getPath($this->buildPathFragment('schema', $path)); + return $this->schemaPath = $this->getPath($this->buildPathFragment('schema', $path)); } /** @@ -748,9 +748,9 @@ public function bindApplicationNecessaryPath(): void $this->singleton('path.config', fn() => $this->configPath()); $this->singleton('path.public', fn() => $this->publicPath()); $this->singleton('path.storage', fn() => $this->storagePath()); - $this->singleton('path.resources', fn() => $this->resourcesPath()); + $this->singleton('path.resources', fn() => $this->templatesPath()); $this->singleton('path.client', fn() => $this->clientPath()); - $this->singleton('path.database', fn() => $this->databasePath()); + $this->singleton('path.database', fn() => $this->schemaPath()); } /** @@ -781,7 +781,7 @@ protected function bindSingletonClasses(): void fn() => new \Phaseolies\Database\Migration\Migrator( new \Phaseolies\Database\Migration\MigrationRepository(), - database_path('migrations') + schema_path('migrations') ) ); } diff --git a/src/Phaseolies/Console/Commands/FrontendInstallCommand.php b/src/Phaseolies/Console/Commands/FrontendInstallCommand.php index 9620a158..23065c61 100644 --- a/src/Phaseolies/Console/Commands/FrontendInstallCommand.php +++ b/src/Phaseolies/Console/Commands/FrontendInstallCommand.php @@ -129,7 +129,7 @@ protected function ensureClientDirectories(): void client_path(), client_path('css'), client_path('js'), - resource_path('views/layouts'), + template_path('views/layouts'), storage_path('framework'), ] as $directory ) { diff --git a/src/Phaseolies/Console/Commands/PaginationPublishCommand.php b/src/Phaseolies/Console/Commands/PaginationPublishCommand.php index 23b2bfce..29e8f57c 100644 --- a/src/Phaseolies/Console/Commands/PaginationPublishCommand.php +++ b/src/Phaseolies/Console/Commands/PaginationPublishCommand.php @@ -27,8 +27,8 @@ class PaginationPublishCommand extends Command */ public function handle(): int { - return $this->executeWithTiming(function() { - $paginationPath = resource_path('views/vendor/pagination'); + return $this->executeWithTiming(function () { + $paginationPath = template_path('views/vendor/pagination'); if (!is_dir($paginationPath)) { if (!mkdir($paginationPath, 0755, true)) { diff --git a/src/Phaseolies/Database/Migration/Migrator.php b/src/Phaseolies/Database/Migration/Migrator.php index b3f95a33..9128478a 100644 --- a/src/Phaseolies/Database/Migration/Migrator.php +++ b/src/Phaseolies/Database/Migration/Migrator.php @@ -88,7 +88,7 @@ public function run(string $connection, ?string $path = null): array $migrations = array_diff($fileNames, $ran); foreach ($vendorMigrations as $basename => $vendorPath) { - if (!file_exists(database_path('migration/' . $basename))) { + if (!file_exists(schema_path('migration/' . $basename))) { $migrations[] = $vendorPath; } diff --git a/src/Phaseolies/Helpers/helpers.php b/src/Phaseolies/Helpers/helpers.php index fcf91c32..38416480 100644 --- a/src/Phaseolies/Helpers/helpers.php +++ b/src/Phaseolies/Helpers/helpers.php @@ -225,7 +225,7 @@ function redirect($to = null, $status = 302, $headers = [], $secure = null) * @param int $status * @param array $headers * @param mixed $fallback - * @return \Phaseolies\Http\RedirectResponse + * @return \Phaseolies\Http\Response\RedirectResponse */ function back($status = 302, $headers = [], $fallback = false) { @@ -415,7 +415,7 @@ function base_path(string $path = ''): string if ($basePath === null) { if (app()->runningInConsole()) { - $basePath = rtrim(getcwd(), DIRECTORY_SEPARATOR); + $basePath = rtrim(getcwd(), DIRECTORY_SEPARATOR); } elseif (defined('BASE_PATH')) { $basePath = rtrim(BASE_PATH, DIRECTORY_SEPARATOR); } else { @@ -728,16 +728,16 @@ function public_path(string $path = ''): string } } -if (!function_exists('resource_path')) { +if (!function_exists('template_path')) { /** - * Get the resources path of the application. + * Get the template path of the application. * * @param string $path * @return string */ - function resource_path(string $path = ''): string + function template_path(string $path = ''): string { - return app()->resourcesPath($path); + return app()->templatesPath($path); } } @@ -767,16 +767,16 @@ function config_path(string $path = ''): string } } -if (!function_exists('database_path')) { +if (!function_exists('schema_path')) { /** - * Get the database path of the application. + * Get the schema path of the application. * * @param string $path * @return string */ - function database_path(string $path = ''): string + function schema_path(string $path = ''): string { - return app()->databasePath($path); + return app()->schemaPath($path); } } diff --git a/src/Phaseolies/Providers/PackageServiceProvider.php b/src/Phaseolies/Providers/PackageServiceProvider.php index 7e17656e..ebdb3418 100644 --- a/src/Phaseolies/Providers/PackageServiceProvider.php +++ b/src/Phaseolies/Providers/PackageServiceProvider.php @@ -84,8 +84,8 @@ protected function convertPathsToPublishArray(array|string $paths, string $type) foreach ($paths as $from) { $publishPaths[$from] = match ($type) { - 'migrations' => database_path('migrations/' . basename($from)), - 'views' => resource_path('views/vendor/' . $this->packageName), + 'migrations' => schema_path('migrations/' . basename($from)), + 'views' => template_path('views/vendor/' . $this->packageName), 'lang' => lang_path('vendor/' . $this->packageName), default => $from, }; diff --git a/src/Phaseolies/Support/Facades/App.php b/src/Phaseolies/Support/Facades/App.php index aadaa4a8..36b3b4b1 100644 --- a/src/Phaseolies/Support/Facades/App.php +++ b/src/Phaseolies/Support/Facades/App.php @@ -5,9 +5,9 @@ /** * @method static \Phaseolies\Application langPath($path = ''): string * @method static \Phaseolies\Application setBasePath(string $basePath): self - * @method static \Phaseolies\Application resourcesPath($path = ''): string + * @method static \Phaseolies\Application templatesPath($path = ''): string * @method static \Phaseolies\Application bootstrapPath($path = ''): string - * @method static \Phaseolies\Application databasePath($path = ''): string + * @method static \Phaseolies\Application schemaPath($path = ''): string * @method static \Phaseolies\Application publicPath($path = ''): string * @method static \Phaseolies\Application storagePath($path = ''): string * @method static \Phaseolies\Application appPath(): string diff --git a/src/Phaseolies/Utilities/Paginator.php b/src/Phaseolies/Utilities/Paginator.php index f376c920..a1a4392a 100644 --- a/src/Phaseolies/Utilities/Paginator.php +++ b/src/Phaseolies/Utilities/Paginator.php @@ -209,7 +209,7 @@ public function url($page): string */ public function linkWithJumps(): ?string { - if (file_exists(resource_path('views/vendor/pagination/jump.odo.php'))) { + if (file_exists(template_path('views/vendor/pagination/jump.odo.php'))) { return view('vendor.pagination.jump', ['paginator' => $this])->render(); } @@ -272,7 +272,7 @@ public function linkWithJumps(): ?string */ public function links(): ?string { - if (file_exists(resource_path('views/vendor/pagination/number.odo.php'))) { + if (file_exists(template_path('views/vendor/pagination/number.odo.php'))) { return view('vendor.pagination.number', ['paginator' => $this])->render(); } diff --git a/tests/Application/ApplicationTest.php b/tests/Application/ApplicationTest.php index b12be02b..89b8ebeb 100644 --- a/tests/Application/ApplicationTest.php +++ b/tests/Application/ApplicationTest.php @@ -185,10 +185,10 @@ public function testApplicationIsContainerInstance(): void public function testPathMethodsReturnCorrectPaths(): void { $stringService = app(StringService::class); - $this->assertStringEndsWith('/templates/views', $stringService->urlHarmonize($this->app->resourcesPath('views'))); + $this->assertStringEndsWith('/templates/views', $stringService->urlHarmonize($this->app->templatesPath('views'))); $this->assertStringEndsWith('/templates/client/js/pages', $stringService->urlHarmonize($this->app->clientPath('js\\pages'))); $this->assertStringEndsWith('/runtime/cache', $stringService->urlHarmonize($this->app->bootstrapPath('cache'))); - $this->assertStringEndsWith('/schema/migrations', $stringService->urlHarmonize($this->app->databasePath('migrations'))); + $this->assertStringEndsWith('/schema/migrations', $stringService->urlHarmonize($this->app->schemaPath('migrations'))); $this->assertStringEndsWith('/public/assets', $stringService->urlHarmonize($this->app->publicPath('assets'))); $this->assertStringEndsWith('/storage/logs', $stringService->urlHarmonize($this->app->storagePath('logs'))); $this->assertStringEndsWith('/runtime/config/app.php', $stringService->urlHarmonize($this->app->configPath('app.php'))); diff --git a/tests/Console/Support/CommandTestEnvironment.php b/tests/Console/Support/CommandTestEnvironment.php index cb358daa..9bb51938 100644 --- a/tests/Console/Support/CommandTestEnvironment.php +++ b/tests/Console/Support/CommandTestEnvironment.php @@ -2,242 +2,240 @@ namespace Tests\Unit\Console\Support { -final class CommandTestEnvironment -{ - public static string $root; + final class CommandTestEnvironment + { + public static string $root; - public static array $config = []; + public static array $config = []; - public static array $appBindings = []; + public static array $appBindings = []; - public static ?object $appInstance = null; + public static ?object $appInstance = null; - public static array $errors = []; + public static array $errors = []; - public static function reset(): void - { - self::$root = rtrim(sys_get_temp_dir(), '/\\') - . DIRECTORY_SEPARATOR - . 'doppar-command-tests-' - . bin2hex(random_bytes(5)); - self::$config = [ - 'app.name' => 'Doppar Demo', - 'app.timezone' => 'UTC', - 'database.default' => 'testing', - ]; - self::$appBindings = []; - self::$appInstance = null; - self::$errors = []; - - if (!is_dir(self::$root)) { - mkdir(self::$root, 0755, true); + public static function reset(): void + { + self::$root = rtrim(sys_get_temp_dir(), '/\\') + . DIRECTORY_SEPARATOR + . 'doppar-command-tests-' + . bin2hex(random_bytes(5)); + self::$config = [ + 'app.name' => 'Doppar Demo', + 'app.timezone' => 'UTC', + 'database.default' => 'testing', + ]; + self::$appBindings = []; + self::$appInstance = null; + self::$errors = []; + + if (!is_dir(self::$root)) { + mkdir(self::$root, 0755, true); + } } - } - public static function cleanup(): void - { - if (!isset(self::$root) || !is_dir(self::$root)) { - return; - } + public static function cleanup(): void + { + if (!isset(self::$root) || !is_dir(self::$root)) { + return; + } - $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator(self::$root, \FilesystemIterator::SKIP_DOTS), - \RecursiveIteratorIterator::CHILD_FIRST - ); + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator(self::$root, \FilesystemIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST + ); - foreach ($iterator as $item) { - if ($item->isLink()) { - unlink($item->getPathname()); - continue; - } + foreach ($iterator as $item) { + if ($item->isLink()) { + unlink($item->getPathname()); + continue; + } + + if ($item->isDir()) { + rmdir($item->getPathname()); + continue; + } - if ($item->isDir()) { - rmdir($item->getPathname()); - continue; + unlink($item->getPathname()); } - unlink($item->getPathname()); + rmdir(self::$root); } - rmdir(self::$root); - } + public static function path(string $path = ''): string + { + $base = rtrim(self::$root, '/\\'); - public static function path(string $path = ''): string - { - $base = rtrim(self::$root, '/\\'); + if ($path === '') { + return $base; + } - if ($path === '') { - return $base; + return $base . DIRECTORY_SEPARATOR . ltrim($path, '/\\'); } - return $base . DIRECTORY_SEPARATOR . ltrim($path, '/\\'); - } + public static function config(?string $key = null, mixed $default = null): mixed + { + if ($key === null) { + return self::$config; + } - public static function config(?string $key = null, mixed $default = null): mixed - { - if ($key === null) { - return self::$config; + return self::$config[$key] ?? $default; } - return self::$config[$key] ?? $default; - } + public static function app(?string $key = null): mixed + { + if ($key === null) { + return self::$appInstance; + } - public static function app(?string $key = null): mixed - { - if ($key === null) { - return self::$appInstance; + return self::$appBindings[$key] ?? null; } - return self::$appBindings[$key] ?? null; - } + public static function bind(string $key, mixed $value): void + { + self::$appBindings[$key] = $value; + } - public static function bind(string $key, mixed $value): void - { - self::$appBindings[$key] = $value; + public static function recordError(string $message): void + { + self::$errors[] = $message; + } } - public static function recordError(string $message): void + final class FakeStringHelper { - self::$errors[] = $message; - } -} + public function suffixAppend(string $value, string $suffix): string + { + return str_ends_with($value, $suffix) ? $value : $value . $suffix; + } -final class FakeStringHelper -{ - public function suffixAppend(string $value, string $suffix): string - { - return str_ends_with($value, $suffix) ? $value : $value . $suffix; - } + public function removeSuffix(string $value, string $suffix): string + { + if (!str_ends_with($value, $suffix)) { + return $value; + } - public function removeSuffix(string $value, string $suffix): string - { - if (!str_ends_with($value, $suffix)) { - return $value; + return substr($value, 0, -strlen($suffix)); } - return substr($value, 0, -strlen($suffix)); + public function snake(string $value): string + { + $value = preg_replace('/(?flushCount++; + } } -} - -final class FakeSessionStore -{ - public int $flushCount = 0; - public function flush(): void + final class FakeDatabaseInspector { - $this->flushCount++; - } -} + public array $columns = []; -final class FakeDatabaseInspector -{ - public array $columns = []; + public function getTableColumns(string $table): array + { + return $this->columns[$table] ?? []; + } + } - public function getTableColumns(string $table): array + trait InteractsWithFakeCommandIO { - return $this->columns[$table] ?? []; - } -} + public array $fakeArguments = []; -trait InteractsWithFakeCommandIO -{ - public array $fakeArguments = []; + public array $fakeOptions = []; - public array $fakeOptions = []; + public array $capturedLines = []; - public array $capturedLines = []; + public array $capturedInfos = []; - public array $capturedInfos = []; + public array $capturedErrors = []; - public array $capturedErrors = []; + public array $capturedWarnings = []; - public array $capturedWarnings = []; + public array $capturedSuccesses = []; - public array $capturedSuccesses = []; + protected function argument($key = null) + { + if ($key === null) { + return $this->fakeArguments; + } - protected function argument($key = null) - { - if ($key === null) { - return $this->fakeArguments; + return $this->fakeArguments[$key] ?? null; } - return $this->fakeArguments[$key] ?? null; - } + protected function option($key = null) + { + if ($key === null) { + return $this->fakeOptions; + } - protected function option($key = null) - { - if ($key === null) { - return $this->fakeOptions; + return $this->fakeOptions[$key] ?? null; } - return $this->fakeOptions[$key] ?? null; - } + protected function info($string): void + { + $this->capturedInfos[] = (string) $string; + } - protected function info($string): void - { - $this->capturedInfos[] = (string) $string; - } + protected function error($string): void + { + $this->capturedErrors[] = (string) $string; + } - protected function error($string): void - { - $this->capturedErrors[] = (string) $string; - } + protected function line(string $string, ?string $style = null): void + { + $this->capturedLines[] = [$string, $style]; + } - protected function line(string $string, ?string $style = null): void - { - $this->capturedLines[] = [$string, $style]; - } + protected function newLine($count = 1): void {} - protected function newLine($count = 1): void - { - } + protected function displaySuccess(string $message): void + { + $this->capturedSuccesses[] = $message; + } - protected function displaySuccess(string $message): void - { - $this->capturedSuccesses[] = $message; - } + protected function displayError(string $message): void + { + $this->capturedErrors[] = $message; + } - protected function displayError(string $message): void - { - $this->capturedErrors[] = $message; - } + protected function displayWarning(string $message): void + { + $this->capturedWarnings[] = $message; + } - protected function displayWarning(string $message): void - { - $this->capturedWarnings[] = $message; - } + protected function displayInfo(string $message): void + { + $this->capturedInfos[] = $message; + } - protected function displayInfo(string $message): void - { - $this->capturedInfos[] = $message; - } + protected function executeWithTiming(callable $callback): int + { + $result = $callback(); - protected function executeWithTiming(callable $callback): int - { - $result = $callback(); + return is_int($result) ? $result : 0; + } - return is_int($result) ? $result : 0; - } + protected function withTiming(callable $operation, ?string $successMessage = null): int + { + $result = $operation(); - protected function withTiming(callable $operation, ?string $successMessage = null): int - { - $result = $operation(); + if ($successMessage !== null) { + $this->displaySuccess($successMessage); + } - if ($successMessage !== null) { - $this->displaySuccess($successMessage); + return is_int($result) ? $result : 0; } - - return is_int($result) ? $result : 0; } } -} namespace Phaseolies\Console\Commands { @@ -260,8 +258,8 @@ function storage_path(string $path = ''): string } } - if (!function_exists(__NAMESPACE__ . '\resource_path')) { - function resource_path(string $path = ''): string + if (!function_exists(__NAMESPACE__ . '\template_path')) { + function template_path(string $path = ''): string { return CommandTestEnvironment::path('templates/' . ltrim($path, '/')); } diff --git a/tests/Support/Database/ModelQueryDriverTestCase.php b/tests/Support/Database/ModelQueryDriverTestCase.php index 9d072389..0a42ce0c 100644 --- a/tests/Support/Database/ModelQueryDriverTestCase.php +++ b/tests/Support/Database/ModelQueryDriverTestCase.php @@ -317,7 +317,7 @@ protected function createSqlitePdo(): PDO $this->markTestSkipped('The pdo_sqlite extension is required for SQLite model query tests.'); } - return new PDO('sqlite:' . $this->sqliteDatabasePath()); + return new PDO('sqlite:' . $this->sqliteschemaPath()); } protected function createMysqlPdo(): PDO @@ -431,7 +431,7 @@ protected function pgsqlConnectionConfig(): array ]; } - protected function sqliteDatabasePath(): string + protected function sqliteschemaPath(): string { $className = str_replace('\\', '-', static::class); From f6d4d9df6cc8c1eeb61300772569a394210b28f6 Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Tue, 25 Aug 2026 19:02:16 +0600 Subject: [PATCH 003/179] techmahedy-4.x: fix error page path from error class: --- src/Phaseolies/Application.php | 4 +-- src/Phaseolies/Error/WebErrorRenderer.php | 2 +- .../Http/Support/RequestAbortion.php | 5 ++- tests/Support/ViteManagerTest.php | 34 +++++++++---------- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/Phaseolies/Application.php b/src/Phaseolies/Application.php index 7a6950c4..32957c40 100644 --- a/src/Phaseolies/Application.php +++ b/src/Phaseolies/Application.php @@ -479,7 +479,7 @@ protected function getPath(string $folder): string } /** - * Gets the resources path. + * Gets the templates path. * * @param string $path * @return string @@ -748,7 +748,7 @@ public function bindApplicationNecessaryPath(): void $this->singleton('path.config', fn() => $this->configPath()); $this->singleton('path.public', fn() => $this->publicPath()); $this->singleton('path.storage', fn() => $this->storagePath()); - $this->singleton('path.resources', fn() => $this->templatesPath()); + $this->singleton('path.templates', fn() => $this->templatesPath()); $this->singleton('path.client', fn() => $this->clientPath()); $this->singleton('path.database', fn() => $this->schemaPath()); } diff --git a/src/Phaseolies/Error/WebErrorRenderer.php b/src/Phaseolies/Error/WebErrorRenderer.php index ce058d1f..417e8690 100644 --- a/src/Phaseolies/Error/WebErrorRenderer.php +++ b/src/Phaseolies/Error/WebErrorRenderer.php @@ -223,7 +223,7 @@ protected function resolveStatusCode(Throwable $exception): int protected function resolveErrorViewPath(int $statusCode): ?string { $customPath = base_path( - 'resources' + 'templates' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . "{$statusCode}.odo.php" diff --git a/src/Phaseolies/Http/Support/RequestAbortion.php b/src/Phaseolies/Http/Support/RequestAbortion.php index f35485d2..e38d07c3 100644 --- a/src/Phaseolies/Http/Support/RequestAbortion.php +++ b/src/Phaseolies/Http/Support/RequestAbortion.php @@ -26,7 +26,7 @@ public function abort(int $code, string $message = '', array $headers = []): voi $customPath = base_path( - 'resources' + 'templates' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . "{$code}.odo.php" @@ -99,8 +99,7 @@ protected function buildErrorViewResponse( string $message = '', array $headers = [], mixed $original = null - ): Response - { + ): Response { if (ob_get_level() > 0) { ob_get_clean(); } diff --git a/tests/Support/ViteManagerTest.php b/tests/Support/ViteManagerTest.php index 516e6576..3431a88c 100644 --- a/tests/Support/ViteManagerTest.php +++ b/tests/Support/ViteManagerTest.php @@ -62,10 +62,10 @@ public function testTagsUseHotServerWhenHotFileExists(): void $manager = $this->stubbedManager(true); - $tags = $manager->tags('resources/client/js/app.js'); + $tags = $manager->tags('templates/client/js/app.js'); $this->assertStringContainsString('http://127.0.0.1:5173/@vite/client', $tags); - $this->assertStringContainsString('http://127.0.0.1:5173/resources/client/js/app.js', $tags); + $this->assertStringContainsString('http://127.0.0.1:5173/templates/client/js/app.js', $tags); } public function testHotReactEntriesAutomaticallyIncludeRefreshPreamble(): void @@ -74,12 +74,12 @@ public function testHotReactEntriesAutomaticallyIncludeRefreshPreamble(): void $manager = $this->stubbedManager(true); - $tags = $manager->tags('resources/client/js/main.tsx'); + $tags = $manager->tags('templates/client/js/main.tsx'); $this->assertStringContainsString('http://127.0.0.1:5173/@react-refresh', $tags); $this->assertStringContainsString('__vite_plugin_react_preamble_installed__ = true', $tags); $this->assertStringContainsString('http://127.0.0.1:5173/@vite/client', $tags); - $this->assertStringContainsString('http://127.0.0.1:5173/resources/client/js/main.tsx', $tags); + $this->assertStringContainsString('http://127.0.0.1:5173/templates/client/js/main.tsx', $tags); } public function testTagsResolveManifestImportsStylesAndScripts(): void @@ -87,19 +87,19 @@ public function testTagsResolveManifestImportsStylesAndScripts(): void file_put_contents( Paths::$public . '/build/manifest.json', json_encode([ - 'resources/client/js/app.js' => [ + 'templates/client/js/app.js' => [ 'file' => 'assets/app-123.js', 'css' => ['assets/app-123.css'], - 'imports' => ['resources/client/js/vendor.js'], + 'imports' => ['templates/client/js/vendor.js'], ], - 'resources/client/js/vendor.js' => [ + 'templates/client/js/vendor.js' => [ 'file' => 'assets/vendor-456.js', 'css' => ['assets/vendor-456.css'], ], ], JSON_PRETTY_PRINT) ); - $tags = (new ViteManager())->tags('resources/client/js/app.js'); + $tags = (new ViteManager())->tags('templates/client/js/app.js'); $this->assertStringContainsString('modulepreload', $tags); $this->assertStringContainsString('https://example.test/build/assets/vendor-456.js', $tags); @@ -113,7 +113,7 @@ public function testAssetResolvesFromManifestAndHotServer(): void file_put_contents( Paths::$public . '/build/manifest.json', json_encode([ - 'resources/client/js/app.js' => ['file' => 'assets/app-123.js'], + 'templates/client/js/app.js' => ['file' => 'assets/app-123.js'], ], JSON_PRETTY_PRINT) ); @@ -121,7 +121,7 @@ public function testAssetResolvesFromManifestAndHotServer(): void $this->assertSame( 'https://example.test/build/assets/app-123.js', - $manager->asset('resources/client/js/app.js') + $manager->asset('templates/client/js/app.js') ); file_put_contents(Paths::$storage . '/framework/vite.hot', 'http://127.0.0.1:5173'); @@ -129,8 +129,8 @@ public function testAssetResolvesFromManifestAndHotServer(): void $hotManager = $this->stubbedManager(true); $this->assertSame( - 'http://127.0.0.1:5173/resources/client/js/app.js', - $hotManager->asset('resources/client/js/app.js') + 'http://127.0.0.1:5173/templates/client/js/app.js', + $hotManager->asset('templates/client/js/app.js') ); } @@ -140,7 +140,7 @@ public function testStaleHotFileFallsBackToManifestAssets(): void file_put_contents( Paths::$public . '/build/manifest.json', json_encode([ - 'resources/client/js/app.js' => [ + 'templates/client/js/app.js' => [ 'file' => 'assets/app-123.js', ], ], JSON_PRETTY_PRINT) @@ -148,7 +148,7 @@ public function testStaleHotFileFallsBackToManifestAssets(): void $manager = $this->stubbedManager(false); - $tags = $manager->tags('resources/client/js/app.js'); + $tags = $manager->tags('templates/client/js/app.js'); $this->assertStringContainsString('https://example.test/build/assets/app-123.js', $tags); $this->assertFileDoesNotExist(Paths::$storage . '/framework/vite.hot'); @@ -161,13 +161,13 @@ public function testTagsResolveManifestFromViteSevenDefaultDirectory(): void file_put_contents( Paths::$public . '/build/.vite/manifest.json', json_encode([ - 'resources/client/js/app.js' => [ + 'templates/client/js/app.js' => [ 'file' => 'assets/app-123.js', ], ], JSON_PRETTY_PRINT) ); - $tags = (new ViteManager())->tags('resources/client/js/app.js'); + $tags = (new ViteManager())->tags('templates/client/js/app.js'); $this->assertStringContainsString('https://example.test/build/assets/app-123.js', $tags); } @@ -177,7 +177,7 @@ public function testManifestPathAcceptsWindowsStyleBuildDirectory(): void file_put_contents( Paths::$public . '/build/manifest.json', json_encode([ - 'resources/client/js/app.js' => [ + 'templates/client/js/app.js' => [ 'file' => 'assets/app-123.js', ], ], JSON_PRETTY_PRINT) From 03b1f37998b185bd2fcc6fa3cf45b727a7afe334 Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Wed, 26 Aug 2026 16:58:03 +0600 Subject: [PATCH 004/179] techmahedy-4.x: fix migrations path --- src/Phaseolies/Database/Migration/Migrator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Phaseolies/Database/Migration/Migrator.php b/src/Phaseolies/Database/Migration/Migrator.php index 9128478a..62b4e351 100644 --- a/src/Phaseolies/Database/Migration/Migrator.php +++ b/src/Phaseolies/Database/Migration/Migrator.php @@ -88,7 +88,7 @@ public function run(string $connection, ?string $path = null): array $migrations = array_diff($fileNames, $ran); foreach ($vendorMigrations as $basename => $vendorPath) { - if (!file_exists(schema_path('migration/' . $basename))) { + if (!file_exists(schema_path('migrations/' . $basename))) { $migrations[] = $vendorPath; } From acaf653ec4f55b09c70b2dd4844379c12d511a1d Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Wed, 26 Aug 2026 17:10:48 +0600 Subject: [PATCH 005/179] techmahedy-4.x: fix unit test warnings --- tests/Application/ApplicationTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/Application/ApplicationTest.php b/tests/Application/ApplicationTest.php index 89b8ebeb..053bbbb9 100644 --- a/tests/Application/ApplicationTest.php +++ b/tests/Application/ApplicationTest.php @@ -118,7 +118,11 @@ private function createDirectoryStructure(): void ]; foreach ($dirs as $dir) { - mkdir($this->tempBasePath . $dir, 0777, true); + $path = $this->tempBasePath . $dir; + + if (!is_dir($path)) { + mkdir($path, 0777, true); + } } // Create minimal config file From 8b2e82293eca6903e27e412ede6ddb9f9d97a8f2 Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Thu, 27 Aug 2026 14:35:32 +0600 Subject: [PATCH 006/179] bump php version 8.3 to 8.5 and update tests.yml and static-analysis also --- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 24 +++++---------------- composer.json | 30 +++++++++++++-------------- 3 files changed, 21 insertions(+), 35 deletions(-) diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index f9ba055b..bbbe121c 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -25,7 +25,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.3 + php-version: 8.5 tools: composer:v2 coverage: none diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 21a34be6..c9efaab2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -31,16 +31,9 @@ jobs: strategy: fail-fast: true matrix: - php: [8.3, 8.4, 8.5] - phpunit: ['12.5.0', '12.5.8'] + php: [8.5] + phpunit: ['13.3.0', '13.3.1'] stability: [prefer-lowest, prefer-stable] - exclude: - - php: 8.3 - phpunit: '12.0.0' - - php: 8.4 - phpunit: '12.0.0' - - php: 8.5 - phpunit: '12.0.0' name: PHP ${{ matrix.php }} - PHPUnit ${{ matrix.phpunit }} - ${{ matrix.stability }} @@ -130,7 +123,7 @@ jobs: with: timeout_minutes: 5 max_attempts: 5 - command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress --with="phpunit/phpunit:~12.5.8" + command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress --with="phpunit/phpunit:~13.3.1" - name: Execute MySQL model query tests if: matrix.driver == 'mysql' @@ -168,16 +161,9 @@ jobs: strategy: fail-fast: true matrix: - php: [8.3, 8.4, 8.5] - phpunit: ['12.5.0', '12.5.8'] + php: [8.5] + phpunit: ['13.3.0', '13.3.1'] stability: [prefer-lowest, prefer-stable] - exclude: - - php: 8.3 - phpunit: '12.0.0' - - php: 8.4 - phpunit: '12.0.0' - - php: 8.5 - phpunit: '12.0.0' name: PHP ${{ matrix.php }} - PHPUnit ${{ matrix.phpunit }} - ${{ matrix.stability }} - Windows diff --git a/composer.json b/composer.json index 960a3068..e9071a30 100644 --- a/composer.json +++ b/composer.json @@ -19,26 +19,26 @@ } ], "require": { - "php": "^8.3", - "chillerlan/php-qrcode": "^5.0", - "dragonmantank/cron-expression": "^3.4", - "monolog/monolog": "^3.0", - "nesbot/carbon": "^3.8", - "paragonie/constant_time_encoding": "^3.0", - "phpmailer/phpmailer": "^6.9", + "php": "^8.5", + "chillerlan/php-qrcode": "^6.0", + "dragonmantank/cron-expression": "^3.6", + "monolog/monolog": "^3.10", + "nesbot/carbon": "^3.13", + "paragonie/constant_time_encoding": "^3.1", + "phpmailer/phpmailer": "^7.1", "psr/simple-cache": "^3.0", "ramsey/collection": "^2.1", "react/event-loop": "^1.6", - "spomky-labs/otphp": "^11.3", - "symfony/cache": "^7.4", - "symfony/console": "^7.4", - "symfony/process": "^7.4", - "symfony/var-dumper": "^7.4", - "vlucas/phpdotenv": "^5.6" + "spomky-labs/otphp": "^11.5", + "symfony/cache": "^8.1", + "symfony/console": "^8.1", + "symfony/process": "^8.1", + "symfony/var-dumper": "^8.1", + "vlucas/phpdotenv": "^5.7" }, "require-dev": { "mockery/mockery": "^1.6", - "phpunit/phpunit": "^12.5" + "phpunit/phpunit": "^13.3" }, "autoload": { "psr-4": { @@ -70,7 +70,7 @@ "ext-pdo": "Provides the core database abstraction required for all DB operations.", "ext-pcntl": "Enables full functionality of the queue worker and support for console signal handling.", "ext-redis": "Required for using Redis-backed cache.", - "symfony/cache": "Supplies the PSR-6 cache integration layer (version ^7.4)." + "symfony/cache": "Supplies the PSR-6 cache integration layer (version ^8.1)." }, "config": { "sort-packages": true, From a58a5061bcee79f132aa4123f9b93d1acc17b63c Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Thu, 27 Aug 2026 15:24:42 +0600 Subject: [PATCH 007/179] added CodeQL security analysis github action --- .github/workflows/security-analysis.yml | 70 +++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 .github/workflows/security-analysis.yml diff --git a/.github/workflows/security-analysis.yml b/.github/workflows/security-analysis.yml new file mode 100644 index 00000000..b9e77d8c --- /dev/null +++ b/.github/workflows/security-analysis.yml @@ -0,0 +1,70 @@ +name: security analysis + +on: + push: + branches: + - master + - '*.x' + pull_request: + schedule: + - cron: '0 3 * * *' + +permissions: + contents: read + +jobs: + composer-audit: + runs-on: ubuntu-24.04 + + name: Composer audit + + permissions: + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.5 + tools: composer:v2 + coverage: none + + - name: Set Framework version + run: composer config version "2.x-dev" + + - name: Install dependencies + uses: nick-fields/retry@v3 + with: + timeout_minutes: 5 + max_attempts: 5 + command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress + + - name: Audit dependencies for known vulnerabilities + run: composer audit --no-dev --format=table --locked + + codeql: + runs-on: ubuntu-24.04 + + name: CodeQL + + permissions: + contents: read + security-events: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: php + queries: security-extended + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@v3 + with: + category: '/language:php' From 7fe86e530e0f5e8c86e7e014962e1e0796fcfd47 Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Thu, 27 Aug 2026 15:30:44 +0600 Subject: [PATCH 008/179] added Semgrep security analysis github action --- .github/workflows/security-analysis.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/security-analysis.yml b/.github/workflows/security-analysis.yml index b9e77d8c..1914aec9 100644 --- a/.github/workflows/security-analysis.yml +++ b/.github/workflows/security-analysis.yml @@ -45,10 +45,10 @@ jobs: - name: Audit dependencies for known vulnerabilities run: composer audit --no-dev --format=table --locked - codeql: + semgrep: runs-on: ubuntu-24.04 - name: CodeQL + name: Semgrep permissions: contents: read @@ -58,13 +58,14 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + - name: Run Semgrep + uses: semgrep/semgrep-action@v1 with: - languages: php - queries: security-extended + config: p/security-audit p/php + generateSarif: '1' - - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@v3 + - name: Upload SARIF results + if: always() + uses: github/codeql-action/upload-sarif@v3 with: - category: '/language:php' + sarif_file: semgrep.sarif From 3f1c9432049663f02e336b6e9678b51b78831f32 Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Thu, 27 Aug 2026 15:40:34 +0600 Subject: [PATCH 009/179] dependabot.yml and phpstan: --- .github/dependabot.yml | 13 + .github/workflows/static-analysis.yml | 7 +- .gitignore | 1 + .phpstan/stubs/AppHttpKernel.php | 14 + composer.json | 4 +- phpstan-baseline.neon | 2605 +++++++++++++++++++++++++ phpstan.neon.dist | 11 + 7 files changed, 2652 insertions(+), 3 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .phpstan/stubs/AppHttpKernel.php create mode 100644 phpstan-baseline.neon create mode 100644 phpstan.neon.dist diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..005c672e --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 + +updates: + - package-ecosystem: composer + directory: / + schedule: + interval: weekly + open-pull-requests-limit: 10 + + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index bbbe121c..3d98bb2b 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -16,7 +16,7 @@ jobs: matrix: directory: [src] - name: ${{ matrix.directory == 'src'}} + name: PHPStan (${{ matrix.directory }}) steps: - name: Checkout code @@ -37,4 +37,7 @@ jobs: with: timeout_minutes: 5 max_attempts: 5 - command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress \ No newline at end of file + command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress + + - name: Run PHPStan + run: composer analyse -- --no-progress --error-format=github \ No newline at end of file diff --git a/.gitignore b/.gitignore index b4e1fdc6..cf119c9c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /.phpunit.cache +/.phpstan.cache /vendor /storage composer.phar diff --git a/.phpstan/stubs/AppHttpKernel.php b/.phpstan/stubs/AppHttpKernel.php new file mode 100644 index 00000000..4d7220a3 --- /dev/null +++ b/.phpstan/stubs/AppHttpKernel.php @@ -0,0 +1,14 @@ +, string given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Application.php + + - + message: '#^Property Phaseolies\\Application\:\:\$cachedConfig \(null\) does not accept true\.$#' + identifier: assign.propertyType + count: 1 + path: src/Phaseolies/Application.php + + - + message: '#^Call to an undefined method Phaseolies\\Support\\Router\:\:handle\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/ApplicationBuilder.php + + - + message: '#^PHPDoc tag @var for property Phaseolies\\ApplicationBuilder\:\:\$request contains generic type Phaseolies\\Http\\Request\ but class Phaseolies\\Http\\Request is not generic\.$#' + identifier: generics.notGeneric + count: 1 + path: src/Phaseolies/ApplicationBuilder.php + + - + message: '#^Parameter \#1 \$abstract of method Phaseolies\\Application\:\:make\(\) expects class\-string\, string given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/ApplicationBuilder.php + + - + message: '#^Parameter \#1 \$abstract of method Phaseolies\\Application\:\:make\(\) expects class\-string\, string given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/ApplicationBuilder.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$id\.$#' + identifier: property.notFound + count: 5 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$remember_token\.$#' + identifier: property.notFound + count: 2 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$two_factor_recovery_codes\.$#' + identifier: property.notFound + count: 4 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$two_factor_secret\.$#' + identifier: property.notFound + count: 3 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Access to undefined constant chillerlan\\QRCode\\QRCode\:\:ECC_M\.$#' + identifier: classConstant.notFound + count: 1 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Access to undefined constant chillerlan\\QRCode\\QRCode\:\:OUTPUT_MARKUP_SVG\.$#' + identifier: classConstant.notFound + count: 1 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Call to an undefined static method Phaseolies\\Database\\Entity\\Model\:\:where\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Crypt\:\:decrypt\(\)\.$#' + identifier: staticMethod.notFound + count: 3 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Crypt\:\:encrypt\(\)\.$#' + identifier: staticMethod.notFound + count: 5 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Hash\:\:check\(\)\.$#' + identifier: staticMethod.notFound + count: 3 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Hash\:\:make\(\)\.$#' + identifier: staticMethod.notFound + count: 2 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Class Doppar\\Flarion\\ApiAuthenticate not found\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$size$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Ternary operator condition is always true\.$#' + identifier: ternary.alwaysTrue + count: 1 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Using nullsafe property access "\?\-\>id" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' + identifier: nullsafe.neverNull + count: 1 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Using nullsafe property access on non\-nullable type Phaseolies\\Database\\Entity\\Model\. Use \-\> instead\.$#' + identifier: nullsafe.neverNull + count: 1 + path: src/Phaseolies/Auth/Security/Authenticate.php + + - + message: '#^Call to function is_string\(\) with string will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/Cache/CacheStore.php + + - + message: '#^PHPDoc tag @param for parameter \$owner with type string\|null is not subtype of native type string\.$#' + identifier: parameter.phpDocType + count: 1 + path: src/Phaseolies/Cache/CacheStore.php + + - + message: '#^Parameter \#3 \$ttl of method Phaseolies\\Cache\\CacheStore\:\:set\(\) expects null, int\|Phaseolies\\Cache\\DateInterval given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Cache/CacheStore.php + + - + message: '#^Parameter \$ttl of method Phaseolies\\Cache\\CacheStore\:\:stash\(\) has invalid type Phaseolies\\Cache\\DateInterval\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Cache/CacheStore.php + + - + message: '#^Strict comparison using \!\=\= between null and null will always evaluate to false\.$#' + identifier: notIdentical.alwaysFalse + count: 1 + path: src/Phaseolies/Cache/CacheStore.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Pool\:\:call\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Console/Commands/AppBoostCommand.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Cache\:\:clear\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Console/Commands/ClearCacheCommand.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Route\:\:clearRouteCache\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Console/Commands/ClearRouteCacheCommand.php + + - + message: '#^Call to method getCommands\(\) on an unknown class App\\Schedule\\Schedule\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Console/Commands/Cron/CronListCommand.php + + - + message: '#^Call to method schedule\(\) on an unknown class App\\Schedule\\Schedule\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Console/Commands/Cron/CronListCommand.php + + - + message: '#^Instantiated class App\\Schedule\\Schedule not found\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Console/Commands/Cron/CronListCommand.php + + - + message: '#^Call to method getCommands\(\) on an unknown class App\\Schedule\\Schedule\.$#' + identifier: class.notFound + count: 2 + path: src/Phaseolies/Console/Commands/Cron/CronRunCommand.php + + - + message: '#^Call to method schedule\(\) on an unknown class App\\Schedule\\Schedule\.$#' + identifier: class.notFound + count: 2 + path: src/Phaseolies/Console/Commands/Cron/CronRunCommand.php + + - + message: '#^Instantiated class App\\Schedule\\Schedule not found\.$#' + identifier: class.notFound + count: 2 + path: src/Phaseolies/Console/Commands/Cron/CronRunCommand.php + + - + message: '#^Unreachable statement \- code above always terminates\.$#' + identifier: deadCode.unreachable + count: 1 + path: src/Phaseolies/Console/Commands/KeyGenerateCommand.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Hash\:\:make\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Console/Commands/MakePasswordCommand.php + + - + message: '#^Method Phaseolies\\Database\\Migration\\MigrationCreator\:\:create\(\) invoked with 7 parameters, 2\-4 required\.$#' + identifier: arguments.count + count: 1 + path: src/Phaseolies/Console/Commands/Migrations/AddColumnMigrationCommand.php + + - + message: '#^PHPDoc tag @param has invalid value \(string \\\$className\)\: Unexpected token "\\\\\$className", expected variable at offset 82 on line 4$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Console/Commands/Migrations/CreateSeedCommand.php + + - + message: '#^Call to method run\(\) on an unknown class Database\\Seeders\\DatabaseSeeder\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Console/Commands/Migrations/DBSeedCommand.php + + - + message: '#^Instantiated class Database\\Seeders\\DatabaseSeeder not found\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Console/Commands/Migrations/DBSeedCommand.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\DB\:\:connection\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Console/Commands/Migrations/MigrateRefreshCommand.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Schema\:\:connection\(\)\.$#' + identifier: staticMethod.notFound + count: 2 + path: src/Phaseolies/Console/Commands/Migrations/MigrateRefreshCommand.php + + - + message: '#^Using nullsafe property access "\?\-\>trackActor" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' + identifier: nullsafe.neverNull + count: 1 + path: src/Phaseolies/Console/Commands/Migrations/MigrateTemporalCommand.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Route\:\:cacheRoutes\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Console/Commands/RouteCacheCommand.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Pool\:\:call\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Console/Commands/RouteListCommand.php + + - + message: '#^Call to function is_int\(\) with int\\|int\<1, max\> will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/Console/Commands/Server/ServerStartCommand.php + + - + message: '#^Parameter \#1 \$port of method Phaseolies\\Console\\Commands\\Server\\ServerStartCommand\:\:isPortOk\(\) expects int\|null, array\|string\|null given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Console/Commands/Server/ServerStartCommand.php + + - + message: '#^PHPDoc tag @param has invalid value \(string string\)\: Unexpected token "string", expected variable at offset 113 on line 5$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Console/Console.php + + - + message: '#^Call to an undefined method Symfony\\Component\\Console\\Helper\\HelperInterface\:\:ask\(\)\.$#' + identifier: method.notFound + count: 5 + path: src/Phaseolies/Console/Schedule/Command.php + + - + message: '#^Call to an undefined method Symfony\\Component\\Console\\Question\\ChoiceQuestion\:\:setDefault\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Console/Schedule/Command.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Log\:\:error\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Console/Schedule/Command.php + + - + message: '#^Offset 1 on array\{0\: non\-falsy\-string, 1\: string, 2\: non\-empty\-string, 3\?\: string\} on left side of \?\? always exists and is not nullable\.$#' + identifier: nullCoalesce.offset + count: 1 + path: src/Phaseolies/Console/Schedule/Command.php + + - + message: '#^Trait Phaseolies\\Console\\Schedule\\InteractsWithSchedule is used zero times and is not analysed\.$#' + identifier: trait.unused + count: 1 + path: src/Phaseolies/Console/Schedule/InteractsWithSchedule.php + + - + message: '#^Parameter \#3 \$env of class Symfony\\Component\\Process\\Process constructor expects array\\|null, non\-empty\-array\ given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Console/Schedule/SchedulePool.php + + - + message: '#^Function now invoked with 1 parameter, 0 required\.$#' + identifier: arguments.count + count: 1 + path: src/Phaseolies/Console/Schedule/ScheduledCommand.php + + - + message: '#^Left side of && is always true\.$#' + identifier: booleanAnd.leftAlwaysTrue + count: 1 + path: src/Phaseolies/Console/Schedule/ScheduledCommand.php + + - + message: '#^Method Phaseolies\\Console\\Schedule\\ScheduledCommand\:\:getRateLimit\(\) should return string\|null but returns int\|null\.$#' + identifier: return.type + count: 1 + path: src/Phaseolies/Console/Schedule/ScheduledCommand.php + + - + message: '#^Parameter \#1 \$hour of method Carbon\\Traits\\Date\:\:setTime\(\) expects int, string given\.$#' + identifier: argument.type + count: 2 + path: src/Phaseolies/Console/Schedule/ScheduledCommand.php + + - + message: '#^Parameter \#2 \$minute of method Carbon\\Traits\\Date\:\:setTime\(\) expects int, string given\.$#' + identifier: argument.type + count: 2 + path: src/Phaseolies/Console/Schedule/ScheduledCommand.php + + - + message: '#^Parameter \#2 \$string of function explode expects string, int\\|int\<1, max\> given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Console/Schedule/ScheduledCommand.php + + - + message: '#^Property Phaseolies\\Console\\Schedule\\ScheduledCommand\:\:\$additionalConditions \(array\) in isset\(\) is not nullable\.$#' + identifier: isset.property + count: 1 + path: src/Phaseolies/Console/Schedule/ScheduledCommand.php + + - + message: '#^Property Phaseolies\\Console\\Schedule\\ScheduledCommand\:\:\$rateLimit \(int\|null\) does not accept string\.$#' + identifier: assign.propertyType + count: 1 + path: src/Phaseolies/Console/Schedule/ScheduledCommand.php + + - + message: '#^Property Phaseolies\\Console\\Schedule\\ScheduledCommand\:\:\$rateLimit \(int\|null\) is never assigned int so it can be removed from the property type\.$#' + identifier: property.unusedType + count: 1 + path: src/Phaseolies/Console/Schedule/ScheduledCommand.php + + - + message: '#^Trait Phaseolies\\DI\\Concerns\\EnforcesImmutability is used zero times and is not analysed\.$#' + identifier: trait.unused + count: 1 + path: src/Phaseolies/DI/Concerns/EnforcesImmutability.php + + - + message: '#^Call to an undefined method ReflectionType\:\:getName\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/DI/Container.php + + - + message: '#^Call to an undefined method ReflectionType\:\:isBuiltin\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/DI/Container.php + + - + message: '#^Call to function is_callable\(\) with callable\(\)\: mixed will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/DI/Container.php + + - + message: '#^Call to function is_object\(\) with \*NEVER\* will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/DI/Container.php + + - + message: '#^Right side of && is always false\.$#' + identifier: booleanAnd.rightAlwaysFalse + count: 1 + path: src/Phaseolies/DI/Container.php + + - + message: '#^Strict comparison using \!\=\= between mixed and null will always evaluate to true\.$#' + identifier: notIdentical.alwaysTrue + count: 2 + path: src/Phaseolies/DI/Container.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 1 + path: src/Phaseolies/DI/Container.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Database\:\:\$conditions\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Database.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Database\:\:\$pdo\.$#' + identifier: property.notFound + count: 3 + path: src/Phaseolies/Database/Database.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Database\:\:\$table\.$#' + identifier: property.notFound + count: 7 + path: src/Phaseolies/Database/Database.php + + - + message: '#^Dead catch \- Throwable is never thrown in the try block\.$#' + identifier: catch.neverThrown + count: 1 + path: src/Phaseolies/Database/Database.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 1 + path: src/Phaseolies/Database/Database.php + + - + message: '#^Variable \$stmt in empty\(\) always exists and is not falsy\.$#' + identifier: empty.variable + count: 1 + path: src/Phaseolies/Database/Database.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$name$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Database/Drivers/SQLiteDriver.php + + - + message: '#^Access to an undefined property \$this\(Phaseolies\\Database\\Entity\\Builder\)\:\:\$originalAttributes\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Access to an undefined property \$this\(Phaseolies\\Database\\Entity\\Builder\)\:\:\$primaryKey\.$#' + identifier: property.notFound + count: 2 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Access to an undefined property \$this\(Phaseolies\\Database\\Entity\\Builder\)\:\:\$timeStamps\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Builder\:\:\$attributes\.$#' + identifier: property.notFound + count: 3 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Builder\:\:\$connection\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Builder\:\:\$creatable\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Builder\:\:\$originalAttributes\.$#' + identifier: property.notFound + count: 3 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Builder\:\:\$pageSize\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Builder\:\:\$primaryKey\.$#' + identifier: property.notFound + count: 4 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Builder\:\:\$relations\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Builder\:\:\$timeStamps\.$#' + identifier: property.notFound + count: 2 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method \$this\(Phaseolies\\Database\\Entity\\Builder\)\:\:fireAfterHooks\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method \$this\(Phaseolies\\Database\\Entity\\Builder\)\:\:fireBeforeHooks\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method \$this\(Phaseolies\\Database\\Entity\\Builder\)\:\:firePropertyWatches\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method \$this\(Phaseolies\\Database\\Entity\\Builder\)\:\:newQuery\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method \$this\(Phaseolies\\Database\\Entity\\Builder\)\:\:pruneNonColumnDirtyAttributes\(\)\.$#' + identifier: method.notFound + count: 2 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method Phaseolies\\Database\\Entity\\Builder\:\:fill\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method Phaseolies\\Database\\Entity\\Builder\:\:fireAfterHooks\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method Phaseolies\\Database\\Entity\\Builder\:\:fireBeforeHooks\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method Phaseolies\\Database\\Entity\\Builder\:\:getTable\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method Phaseolies\\Database\\Entity\\Builder\:\:newQuery\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method Phaseolies\\Database\\Entity\\Builder\:\:pruneNonColumnAttributes\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method Phaseolies\\Database\\Entity\\Builder\:\:setRelation\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined method Phaseolies\\Database\\Entity\\Builder\:\:toArray\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\URL\:\:current\(\)\.$#' + identifier: staticMethod.notFound + count: 2 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to function is_array\(\) with array will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 2 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to function is_callable\(\) with null will always evaluate to false\.$#' + identifier: function.impossibleType + count: 2 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to function is_int\(\) with int will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to function unset\(\) contains undefined variable \$chunkQuery\.$#' + identifier: unset.variable + count: 2 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Call to function unset\(\) contains undefined variable \$results\.$#' + identifier: unset.variable + count: 2 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^If condition is always false\.$#' + identifier: if.alwaysFalse + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Instanceof between \$this\(Phaseolies\\Database\\Entity\\Builder\) and Phaseolies\\Support\\Collection will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Method Phaseolies\\Database\\Entity\\Builder\:\:absent\(\) invoked with 2 parameters, 1 required\.$#' + identifier: arguments.count + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Method Phaseolies\\Database\\Entity\\Builder\:\:createFromModel\(\) should return static\(Phaseolies\\Database\\Entity\\Builder\) but returns Phaseolies\\Database\\Entity\\Model\.$#' + identifier: return.type + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^PHPDoc tag @param has invalid value \(int chunkSize\)\: Unexpected token "chunkSize", expected variable at offset 89 on line 4$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$boolean$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$page$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Parameter \#1 \.\.\.\$arrays of function array_merge expects array, null given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Parameter \#2 \$type of method Phaseolies\\Database\\Entity\\Builder\:\:formatDateTime\(\) expects string, true given\.$#' + identifier: argument.type + count: 2 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Static call to instance method Phaseolies\\Database\\Entity\\Builder\:\:create\(\)\.$#' + identifier: method.staticCall + count: 3 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Strict comparison using \=\=\= between mixed and null will always evaluate to false\.$#' + identifier: identical.alwaysFalse + count: 2 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Undefined variable\: \$inspectQuery$#' + identifier: variable.undefined + count: 4 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 6 + path: src/Phaseolies/Database/Entity/Builder.php + + - + message: '#^Offset ''when'' on array\{handler\: \(callable\(\)\: mixed\)\|string, when\: bool\|\(callable\(\)\: mixed\)\} on left side of \?\? always exists and is not nullable\.$#' + identifier: nullCoalesce.offset + count: 1 + path: src/Phaseolies/Database/Entity/Hooks/HookHandler.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$__action\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$__actor\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$__changed_cols\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$__history_id\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$__valid_from\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$modelClass\.$#' + identifier: property.notFound + count: 2 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Offset ''key'' does not exist on string\.$#' + identifier: offsetAccess.notFound + count: 4 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Offset ''method'' does not exist on string\.$#' + identifier: offsetAccess.notFound + count: 5 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Property Phaseolies\\Database\\Entity\\Model\:\:\$lastLocalKey \(string\) on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.property + count: 1 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Property Phaseolies\\Database\\Entity\\Model\:\:\$table \(string\) in isset\(\) is not nullable\.$#' + identifier: isset.property + count: 2 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Unreachable statement \- code above always terminates\.$#' + identifier: deadCode.unreachable + count: 1 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 11 + path: src/Phaseolies/Database/Entity/Model.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\URL\:\:current\(\)\.$#' + identifier: staticMethod.notFound + count: 2 + path: src/Phaseolies/Database/Entity/Query/Builder.php + + - + message: '#^Call to function is_int\(\) with int will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/Database/Entity/Query/Builder.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$boolean$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Query/Builder.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$modelClass$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Query/Builder.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$page$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Query/Builder.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$rowPerPage$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Database/Entity/Query/Builder.php + + - + message: '#^Parameter \#2 \$type of method Phaseolies\\Database\\Entity\\Query\\Builder\:\:formatDateTime\(\) expects string, true given\.$#' + identifier: argument.type + count: 2 + path: src/Phaseolies/Database/Entity/Query/Builder.php + + - + message: '#^Strict comparison using \=\=\= between mixed and null will always evaluate to false\.$#' + identifier: identical.alwaysFalse + count: 2 + path: src/Phaseolies/Database/Entity/Query/Builder.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 1 + path: src/Phaseolies/Database/Entity/Query/Builder.php + + - + message: '#^Call to function is_bool\(\) with bool will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/Database/Entity/Watches/WatchesHandler.php + + - + message: '#^Call to function is_null\(\) with mixed will always evaluate to false\.$#' + identifier: function.impossibleType + count: 1 + path: src/Phaseolies/Database/Migration/ColumnDefinition.php + + - + message: '#^Variable \$keys in empty\(\) always exists and is not falsy\.$#' + identifier: empty.variable + count: 1 + path: src/Phaseolies/Database/Migration/Grammars/SQLiteGrammar.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\DB\:\:connection\(\)\.$#' + identifier: staticMethod.notFound + count: 4 + path: src/Phaseolies/Database/Migration/MigrationRepository.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Schema\:\:connection\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Database/Migration/MigrationRepository.php + + - + message: '#^Variable \$connection on left side of \?\? always exists and is not nullable\.$#' + identifier: nullCoalesce.variable + count: 1 + path: src/Phaseolies/Database/Migration/Migrator.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\DB\:\:connection\(\)\.$#' + identifier: staticMethod.notFound + count: 6 + path: src/Phaseolies/Database/Migration/Schema.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 1 + path: src/Phaseolies/Database/Migration/Schema.php + + - + message: '#^PHPDoc tag @param has invalid value \(array\)\: Unexpected token "\\n ", expected variable at offset 98 on line 4$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Database/Procedure/ProcedureResult.php + + - + message: '#^Method Phaseolies\\Database\\Temporal\\TemporalManager\:\:resolveActor\(\) never returns int so it can be removed from the return type\.$#' + identifier: return.unusedType + count: 1 + path: src/Phaseolies/Database/Temporal/TemporalManager.php + + - + message: '#^Using nullsafe property access "\?\-\>suffix" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' + identifier: nullsafe.neverNull + count: 1 + path: src/Phaseolies/Database/Temporal/TemporalManager.php + + - + message: '#^Class App\\Http\\Exceptions\\BeforeExceptionHandler not found\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Error/ErrorHandler.php + + - + message: '#^PHPDoc tag @param has invalid value \(int\)\: Unexpected token "\\n \* ", expected variable at offset 98 on line 5$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Error/Handlers/CliErrorHandler.php + + - + message: '#^PHPDoc tag @return with type void is incompatible with native type string\.$#' + identifier: return.phpDocType + count: 1 + path: src/Phaseolies/Error/Handlers/CliErrorHandler.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 2 + path: src/Phaseolies/Error/Traces/Frame.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$id\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Error/WebErrorRenderer.php + + - + message: '#^Array has 2 duplicate keys with value ''request_body'' \(''request_body'', ''request_body''\)\.$#' + identifier: array.duplicateKey + count: 1 + path: src/Phaseolies/Error/WebErrorRenderer.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Route\:\:currentRouteAction\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Error/WebErrorRenderer.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Route\:\:currentRouteName\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Error/WebErrorRenderer.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Route\:\:getCurrentMiddlewareNames\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Error/WebErrorRenderer.php + + - + message: '#^Parameter \#1 \$content of function response expects null, string given\.$#' + identifier: argument.type + count: 3 + path: src/Phaseolies/Error/WebErrorRenderer.php + + - + message: '#^Using nullsafe method call on non\-nullable type Phaseolies\\Auth\\ActorManager\|Phaseolies\\Auth\\Security\\Authenticate\. Use \-\> instead\.$#' + identifier: nullsafe.neverNull + count: 1 + path: src/Phaseolies/Error/WebErrorRenderer.php + + - + message: '#^If condition is always true\.$#' + identifier: if.alwaysTrue + count: 1 + path: src/Phaseolies/Facade/BaseFacade.php + + - + message: '#^Unreachable statement \- code above always terminates\.$#' + identifier: deadCode.unreachable + count: 1 + path: src/Phaseolies/Facade/BaseFacade.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Crypt\:\:decrypt\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Crypt\:\:encrypt\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Log\:\:alert\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Log\:\:critical\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Log\:\:debug\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Log\:\:emergency\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Log\:\:error\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Log\:\:info\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Log\:\:notice\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Log\:\:warning\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Call to static method create\(\) on an unknown class Faker\\Factory\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Condition "null is null" in conditional return type is always true\.$#' + identifier: conditionalType.alwaysTrue + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Function __\(\) never returns array so it can be removed from the return type\.$#' + identifier: return.unusedType + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Function fake\(\) has invalid return type Faker\\Generator\.$#' + identifier: class.notFound + count: 2 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^PHPDoc tag @param has invalid value \(int\)\: Unexpected token "\\n \* ", expected variable at offset 108 on line 4$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^PHPDoc tag @param has invalid value \(string\)\: Unexpected token "\\n \* ", expected variable at offset 86 on line 4$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^Variable \$content on left side of \?\? always exists and is always null\.$#' + identifier: nullCoalesce.variable + count: 1 + path: src/Phaseolies/Helpers/helpers.php + + - + message: '#^PHPDoc tag @param for parameter \$callback with type string is incompatible with native type Closure\.$#' + identifier: parameter.phpDocType + count: 1 + path: src/Phaseolies/Http/Controllers/Controller.php + + - + message: '#^Property Phaseolies\\Http\\Controllers\\Controller\:\:\$soloCounter \(int\) on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.property + count: 1 + path: src/Phaseolies/Http/Controllers/Controller.php + + - + message: '#^Ternary operator condition is always true\.$#' + identifier: ternary.alwaysTrue + count: 1 + path: src/Phaseolies/Http/Controllers/Controller.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 1 + path: src/Phaseolies/Http/Exceptions/HttpException.php + + - + message: '#^Method Phaseolies\\Http\\Exceptions\\StreamedResponseException\:\:render\(\) has invalid return type Illuminate\\Http\\Response\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Http/Exceptions/StreamedResponseException.php + + - + message: '#^Method Phaseolies\\Http\\Exceptions\\StreamedResponseException\:\:render\(\) should return Illuminate\\Http\\Response but returns Phaseolies\\Http\\Response\.$#' + identifier: return.type + count: 1 + path: src/Phaseolies/Http/Exceptions/StreamedResponseException.php + + - + message: '#^Method Phaseolies\\Http\\HeaderBag\:\:getIterator\(\) should return ArrayIterator\\> but returns ArrayIterator\\>\.$#' + identifier: return.type + count: 1 + path: src/Phaseolies/Http/HeaderBag.php + + - + message: '#^Instanceof between array\|null and Closure will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Http/ParameterBag.php + + - + message: '#^Argument of an invalid type Phaseolies\\Http\\InputBag supplied for foreach, only iterables are supported\.$#' + identifier: foreach.nonIterable + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Call to an undefined method ReflectionType\:\:getName\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Call to an undefined method ReflectionType\:\:isBuiltin\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\App\:\:setLocale\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Str\:\:contains\(\)\.$#' + identifier: staticMethod.notFound + count: 2 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Str\:\:startsWith\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Str\:\:substr\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Method Phaseolies\\Http\\Request\:\:header\(\) invoked with 2 parameters, 1 required\.$#' + identifier: arguments.count + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Method Phaseolies\\Http\\Request\:\:headers\(\) should return array\ but returns array\\>\.$#' + identifier: return.type + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Method Phaseolies\\Http\\Request\:\:prefers\(\) should return string\|null but return statement is missing\.$#' + identifier: return.missing + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Non\-static access to static property Phaseolies\\Http\\Request\:\:\$trustedHeaderSet\.$#' + identifier: staticProperty.nonStaticAccess + count: 5 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Non\-static access to static property Phaseolies\\Http\\Request\:\:\$trustedProxies\.$#' + identifier: staticProperty.nonStaticAccess + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^PHPDoc tag @return has invalid value \(string\|null\.\)\: Unexpected token "\.", expected TOKEN_HORIZONTAL_WS at offset 108 on line 5$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^PHPDoc tag @return with type array\|Phaseolies\\Http\\Response\|null is not subtype of native type array\|Phaseolies\\Http\\Response\.$#' + identifier: return.phpDocType + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^PHPDoc tag @throws with type Phaseolies\\Http\\SuspiciousOperationException is not subtype of Throwable$#' + identifier: throws.notThrowable + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Property Phaseolies\\Http\\Request\:\:\$errors \(array\\) on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.property + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Strict comparison using \!\=\= between resource\|string and false will always evaluate to true\.$#' + identifier: notIdentical.alwaysTrue + count: 3 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Strict comparison using \=\=\= between null and string will always evaluate to false\.$#' + identifier: identical.alwaysFalse + count: 2 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Strict comparison using \=\=\= between resource\|string and false will always evaluate to false\.$#' + identifier: identical.alwaysFalse + count: 1 + path: src/Phaseolies/Http/Request.php + + - + message: '#^Expression on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.expr + count: 2 + path: src/Phaseolies/Http/Response.php + + - + message: '#^If condition is always true\.$#' + identifier: if.alwaysTrue + count: 1 + path: src/Phaseolies/Http/Response.php + + - + message: '#^Instanceof between array\ and Phaseolies\\Http\\HeaderBag will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Http/Response.php + + - + message: '#^Method Phaseolies\\Http\\Request\:\:isHead\(\) invoked with 1 parameter, 0 required\.$#' + identifier: arguments.count + count: 1 + path: src/Phaseolies/Http/Response.php + + - + message: '#^PHPDoc tag @return with type Phaseolies\\Http\\Response is not subtype of native type static\(Phaseolies\\Http\\Response\)\.$#' + identifier: return.phpDocType + count: 4 + path: src/Phaseolies/Http/Response.php + + - + message: '#^PHPDoc tag @return with type void is incompatible with native type static\(Phaseolies\\Http\\Response\)\.$#' + identifier: return.phpDocType + count: 1 + path: src/Phaseolies/Http/Response.php + + - + message: '#^Parameter \#2 \$datetime of static method DateTimeImmutable\:\:createFromFormat\(\) expects string, int\<\-172799, max\> given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Http/Response.php + + - + message: '#^Parameter \#2 \$value of method Phaseolies\\Http\\HeaderBag\:\:addCacheControlDirective\(\) expects bool\|string, int given\.$#' + identifier: argument.type + count: 4 + path: src/Phaseolies/Http/Response.php + + - + message: '#^Parameter \#2 \$values of method Phaseolies\\Http\\Response\\ResponseHeaderBag\:\:set\(\) expects array\\|string\|null, int given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Http/Response.php + + - + message: '#^Parameter \#2 \$values of method Phaseolies\\Http\\Response\\ResponseHeaderBag\:\:set\(\) expects array\\|string\|null, int\|null given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Http/Response.php + + - + message: '#^Unreachable statement \- code above always terminates\.$#' + identifier: deadCode.unreachable + count: 1 + path: src/Phaseolies/Http/Response.php + + - + message: '#^Method Phaseolies\\Http\\Response\\BaseJsonResponse\:\:update\(\) should return \$this\(Phaseolies\\Http\\Response\\BaseJsonResponse\) but returns static\(Phaseolies\\Http\\Response\\BaseJsonResponse\)\.$#' + identifier: return.type + count: 2 + path: src/Phaseolies/Http/Response/BaseJsonResponse.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 1 + path: src/Phaseolies/Http/Response/BaseJsonResponse.php + + - + message: '#^Call to function in_array\(\) with arguments ''lax''\|''none''\|''strict''\|null, array\{''lax'', ''strict'', ''none'', null\} and true will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/Http/Response/Cookie.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 1 + path: src/Phaseolies/Http/Response/Cookie.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Str\:\:snake\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Http/Response/RedirectResponse.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Str\:\:startsWith\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Http/Response/RedirectResponse.php + + - + message: '#^PHPDoc tag @return with type Phaseolies\\Http\\Response is not subtype of native type Phaseolies\\Http\\Response\\RedirectResponse\.$#' + identifier: return.phpDocType + count: 1 + path: src/Phaseolies/Http/Response/RedirectResponse.php + + - + message: '#^Expression on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.expr + count: 1 + path: src/Phaseolies/Http/Response/ResponseHeaderBag.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$partitioned$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Http/Response/ResponseHeaderBag.php + + - + message: '#^Method Phaseolies\\Http\\Request\:\:isGet\(\) invoked with 1 parameter, 0 required\.$#' + identifier: arguments.count + count: 1 + path: src/Phaseolies/Http/Response/Stream/BinaryFileResponse.php + + - + message: '#^Method Phaseolies\\Http\\Request\:\:isHead\(\) invoked with 1 parameter, 0 required\.$#' + identifier: arguments.count + count: 1 + path: src/Phaseolies/Http/Response/Stream/BinaryFileResponse.php + + - + message: '#^Parameter \#2 \$datetime of static method DateTimeImmutable\:\:createFromFormat\(\) expects string, int\|false given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Http/Response/Stream/BinaryFileResponse.php + + - + message: '#^Parameter \#2 \$values of method Phaseolies\\Http\\Response\\ResponseHeaderBag\:\:set\(\) expects array\\|string\|null, int given\.$#' + identifier: argument.type + count: 2 + path: src/Phaseolies/Http/Response/Stream/BinaryFileResponse.php + + - + message: '#^Strict comparison using \=\=\= between false and int will always evaluate to false\.$#' + identifier: identical.alwaysFalse + count: 1 + path: src/Phaseolies/Http/Response/Stream/BinaryFileResponse.php + + - + message: '#^Strict comparison using \=\=\= between false and string will always evaluate to false\.$#' + identifier: identical.alwaysFalse + count: 1 + path: src/Phaseolies/Http/Response/Stream/BinaryFileResponse.php + + - + message: '#^Instanceof between mixed and ArrayObject will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Http/ResponseFactory.php + + - + message: '#^Instanceof between mixed and JsonSerializable will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Http/ResponseFactory.php + + - + message: '#^Instanceof between mixed and Phaseolies\\Database\\Entity\\Builder will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Http/ResponseFactory.php + + - + message: '#^Instanceof between mixed and Phaseolies\\Database\\Entity\\Model will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Http/ResponseFactory.php + + - + message: '#^Instanceof between mixed and Phaseolies\\Support\\Collection will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Http/ResponseFactory.php + + - + message: '#^Instanceof between mixed and stdClass will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Http/ResponseFactory.php + + - + message: '#^Trait Phaseolies\\Http\\Support\\InteractsWithTrustedProxies is used zero times and is not analysed\.$#' + identifier: trait.unused + count: 1 + path: src/Phaseolies/Http/Support/InteractsWithTrustedProxies.php + + - + message: '#^Trait Phaseolies\\Http\\Support\\InteractsWithVerifyTwoFactorUser is used zero times and is not analysed\.$#' + identifier: trait.unused + count: 1 + path: src/Phaseolies/Http/Support/InteractsWithVerifyTwoFactorUser.php + + - + message: '#^Parameter \#1 \$content of function response expects null, string given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Http/Support/RequestAbortion.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 1 + path: src/Phaseolies/Http/Validation/Bind.php + + - + message: '#^Call to an undefined method Phaseolies\\Http\\Validation\\FormRequest\:\:sanitize\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Http/Validation/FormRequest.php + + - + message: '#^PHPDoc tag @throws with type Phaseolies\\Http\\Validation\\HttpResponseException is not subtype of Throwable$#' + identifier: throws.notThrowable + count: 1 + path: src/Phaseolies/Http/Validation/FormRequest.php + + - + message: '#^Call to method getIO\(\) on an unknown class Composer\\Script\\Event\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Installer.php + + - + message: '#^Parameter \$event of method Phaseolies\\Installer\:\:postCreateProject\(\) has invalid type Composer\\Script\\Event\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Installer.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$channel$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Logger/Contracts/AbstractHandler.php + + - + message: '#^Method Phaseolies\\Middleware\\CacheHeaders\:\:__invoke\(\) has invalid return type Phaseolies\\Middleware\\Phaseolies\\Http\\Response\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Middleware/CacheHeaders.php + + - + message: '#^Method Phaseolies\\Middleware\\CacheHeaders\:\:__invoke\(\) should return Phaseolies\\Http\\Response but returns mixed\.$#' + identifier: return.type + count: 1 + path: src/Phaseolies/Middleware/CacheHeaders.php + + - + message: '#^PHPDoc tag @param has invalid value \(\\Closure\(\\Phaseolies\\Http\\Request\) \$next\)\: Unexpected token "\(", expected variable at offset 124 on line 5$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Middleware/CacheHeaders.php + + - + message: '#^PHPDoc tag @return with type Phaseolies\\Middleware\\Phaseolies\\Http\\Response is not subtype of native type Phaseolies\\Http\\Response\.$#' + identifier: return.phpDocType + count: 1 + path: src/Phaseolies/Middleware/CacheHeaders.php + + - + message: '#^Strict comparison using \!\=\= between string\|null and false will always evaluate to true\.$#' + identifier: notIdentical.alwaysTrue + count: 1 + path: src/Phaseolies/Middleware/CacheHeaders.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Str\:\:toUpper\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Middleware/CsrfTokenMiddleware.php + + - + message: '#^Dead catch \- Exception is never thrown in the try block\.$#' + identifier: catch.neverThrown + count: 1 + path: src/Phaseolies/Middleware/CsrfTokenMiddleware.php + + - + message: '#^Method Phaseolies\\Middleware\\CsrfTokenMiddleware\:\:shouldAddXsrfTokenCookie\(\) invoked with 1 parameter, 0 required\.$#' + identifier: arguments.count + count: 1 + path: src/Phaseolies/Middleware/CsrfTokenMiddleware.php + + - + message: '#^PHPDoc tag @param has invalid value \(\\Closure\(\\Phaseolies\\Http\\Request\) \$next\)\: Unexpected token "\(", expected variable at offset 128 on line 5$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Middleware/CsrfTokenMiddleware.php + + - + message: '#^PHPDoc tag @throws with type Phaseolies\\Middleware\\HttpException is not subtype of Throwable$#' + identifier: throws.notThrowable + count: 1 + path: src/Phaseolies/Middleware/CsrfTokenMiddleware.php + + - + message: '#^Parameter \#1 \$string of function sha1 expects string, int\|null given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Middleware/ThrottleRequests.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Route\:\:group\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Providers/RouteServiceProvider.php + + - + message: '#^Method Phaseolies\\Providers\\ServiceProvider\:\:pathsForProviderOrGroup\(\) should return array\|null but returns string\.$#' + identifier: return.type + count: 1 + path: src/Phaseolies/Providers/ServiceProvider.php + + - + message: '#^Property Phaseolies\\Providers\\ServiceProvider\:\:\$publishGroups \(array\\>\) in isset\(\) is not nullable\.$#' + identifier: isset.property + count: 1 + path: src/Phaseolies/Providers/ServiceProvider.php + + - + message: '#^Property Phaseolies\\Providers\\ServiceProvider\:\:\$publishes \(array\\) in isset\(\) is not nullable\.$#' + identifier: isset.property + count: 1 + path: src/Phaseolies/Providers/ServiceProvider.php + + - + message: '#^Property Phaseolies\\Support\\Collection\:\:\$data \(array\) on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.property + count: 1 + path: src/Phaseolies/Support/Collection.php + + - + message: '#^Property Phaseolies\\Support\\Collection\:\:\$model \(string\) on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.property + count: 2 + path: src/Phaseolies/Support/Collection.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 16 + path: src/Phaseolies/Support/Collection.php + + - + message: '#^Comparison operation "\<" between int\<80500, 80599\> and 70300 is always false\.$#' + identifier: smaller.alwaysFalse + count: 1 + path: src/Phaseolies/Support/CookieJar.php + + - + message: '#^PHPDoc tag @return with type void is incompatible with native type bool\.$#' + identifier: return.phpDocType + count: 1 + path: src/Phaseolies/Support/CookieJar.php + + - + message: '#^Variable \$cookies on left side of \?\? always exists and is not nullable\.$#' + identifier: nullCoalesce.variable + count: 1 + path: src/Phaseolies/Support/CookieJar.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: array\)\: Unexpected token "\\n \* ", expected type at offset 430 on line 10$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: array\)\: Unexpected token "\\n \* ", expected type at offset 657 on line 14$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 327 on line 7$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 477 on line 11$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 763 on line 16$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(Model \$user\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 714 on line 15$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(Model \$user, string \$code\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 605 on line 13$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$code\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 535 on line 12$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$qrCodeUrl\)\: string\)\: Unexpected token "\\n \*", expected type at offset 832 on line 17$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(static id\(\)\: \?int\)\: Unexpected token "\\n \* ", expected type at offset 383 on line 9$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(static onceUsingId\(int \$id\)\: \?User\)\: Unexpected token "\\n \* ", expected type at offset 263 on line 5$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(static user\(\)\: \?User\)\: Unexpected token "\\n \* ", expected type at offset 295 on line 6$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Auth.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$name, string \$owner\)\: AtomicLock\)\: Unexpected token "\\n \* ", expected type at offset 1405 on line 18$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Cache.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: PDO\)\: Unexpected token "\\n \* ", expected type at offset 631 on line 14$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: array\)\: Unexpected token "\\n \* ", expected type at offset 489 on line 11$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: int\)\: Unexpected token "\\n \* ", expected type at offset 297 on line 7$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: int\)\: Unexpected token "\\n \* ", expected type at offset 402 on line 9$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 114 on line 3$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 148 on line 4$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 184 on line 5$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: void\)\: Unexpected token "\\n \*", expected type at offset 1532 on line 26$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(Model \$model\)\: string\)\: Unexpected token "\\n \* ", expected type at offset 591 on line 13$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$table\)\: Builder\)\: Unexpected token "\\n \* ", expected type at offset 451 on line 10$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$table\)\: \\Phaseolies\\Database\\Entity\\Query\\Builder\)\: Unexpected token "\\n \* ", expected type at offset 1221 on line 21$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$table\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 541 on line 12$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/DB.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: array\)\: Unexpected token "\\n \* ", expected type at offset 2932 on line 58$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 1633 on line 30$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 1667 on line 31$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 1708 on line 32$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 1886 on line 36$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 1927 on line 37$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 2897 on line 57$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 3103 on line 61$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 3142 on line 62$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 3182 on line 63$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 3222 on line 64$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 3253 on line 65$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 3291 on line 66$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 3328 on line 67$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 661 on line 14$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 695 on line 15$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: int\)\: Unexpected token "\\n \* ", expected type at offset 2068 on line 40$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: int\)\: Unexpected token "\\n \* ", expected type at offset 433 on line 10$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 1020 on line 21$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 1747 on line 33$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 1785 on line 34$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2103 on line 41$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2863 on line 56$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: string\)\: Unexpected token "\\n \* ", expected type at offset 1252 on line 25$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: string\)\: Unexpected token "\\n \* ", expected type at offset 804 on line 17$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\?\\DateTimeInterface \$date\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2219 on line 43$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\?string \$body\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 52 on line 2$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(HttpException \$exception\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 1217 on line 24$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(Request \$request\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 3067 on line 60$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(Request \$request\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 856 on line 18$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\\DateTimeInterface \$date\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2036 on line 39$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(array \$headers\)\: Response\)\: Unexpected token "\\n \* ", expected type at offset 573 on line 12$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(array \$options\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2820 on line 55$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(int \$seconds\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2553 on line 50$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(int \$seconds\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2606 on line 51$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(int \$statusCode\)\: string\)\: Unexpected token "\\n \* ", expected type at offset 980 on line 20$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(int \$targetLevel, bool \$flush\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 1145 on line 23$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(int \$value\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2303 on line 45$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(int \$value\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2357 on line 46$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(int \$value\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2419 on line 47$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(int \$value\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 2473 on line 48$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$charset\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 224 on line 6$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$version\)\: static\)\: Unexpected token "\\n \* ", expected type at offset 757 on line 16$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(static getBody\(\)\: \?string\)\: Unexpected token "\\n \* ", expected type at offset 89 on line 3$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(static getCharset\(\)\: \?string\)\: Unexpected token "\\n \* ", expected type at offset 264 on line 7$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(static getDate\(\)\: \?\\DateTimeImmutable\)\: Unexpected token "\\n \* ", expected type at offset 1976 on line 38$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(static getEtag\(\)\: \?string\)\: Unexpected token "\\n \* ", expected type at offset 2700 on line 53$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(static getExpires\(\)\: \?\\DateTimeImmutable\)\: Unexpected token "\\n \* ", expected type at offset 2155 on line 42$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(static getLastModified\(\)\: \?\\DateTimeImmutable\)\: Unexpected token "\\n \* ", expected type at offset 2663 on line 52$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(static getMaxAge\(\)\: \?int\)\: Unexpected token "\\n \* ", expected type at offset 2255 on line 44$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(static getTtl\(\)\: \?int\)\: Unexpected token "\\n \* ", expected type at offset 2506 on line 49$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Response.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: array\)\: Unexpected token "\\n \* ", expected type at offset 529 on line 12$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: string\)\: Unexpected token "\\n \* ", expected type at offset 563 on line 13$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 253 on line 6$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 432 on line 10$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 639 on line 15$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 801 on line 19$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: void\)\: Unexpected token "\\n \*", expected type at offset 843 on line 20$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$id\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 605 on line 14$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$key\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 356 on line 8$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string \$key\)\: void\)\: Unexpected token "\\n \* ", expected type at offset 400 on line 9$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^PHPDoc tag @method has invalid value \(static token\(\)\: \?string\)\: Unexpected token "\\n \* ", expected type at offset 674 on line 16$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Facades/Session.php + + - + message: '#^Call to an undefined static method Phaseolies\\Support\\Facades\\Storage\:\:getDiskPath\(\)\.$#' + identifier: staticMethod.notFound + count: 1 + path: src/Phaseolies/Support/File.php + + - + message: '#^Call to function is_null\(\) with string will always evaluate to false\.$#' + identifier: function.impossibleType + count: 1 + path: src/Phaseolies/Support/File.php + + - + message: '#^Method Phaseolies\\Support\\File\:\:generateUniqueName\(\) invoked with 1 parameter, 0 required\.$#' + identifier: arguments.count + count: 2 + path: src/Phaseolies/Support/File.php + + - + message: '#^PHPDoc tag @method for method Phaseolies\\Support\\Lens\:\:flat\(\) parameter \#2 \$depth default value contains unresolvable type\.$#' + identifier: methodTag.unresolvableType + count: 1 + path: src/Phaseolies/Support/Lens.php + + - + message: '#^Unsafe call to private method Phaseolies\\Support\\Lens\:\:make\(\) through static\:\:\.$#' + identifier: staticClassAccess.privateMethod + count: 1 + path: src/Phaseolies/Support/Lens.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 1 + path: src/Phaseolies/Support/Lens.php + + - + message: '#^Property Phaseolies\\Support\\Mail\\Driver\\MailMailDriver\:\:\$config is never read, only written\.$#' + identifier: property.onlyWritten + count: 1 + path: src/Phaseolies/Support/Mail/Driver/MailMailDriver.php + + - + message: '#^Property Phaseolies\\Support\\Mail\\Driver\\QmailMailDriver\:\:\$config is never read, only written\.$#' + identifier: property.onlyWritten + count: 1 + path: src/Phaseolies/Support/Mail/Driver/QmailMailDriver.php + + - + message: '#^Access to an undefined property Phaseolies\\Database\\Entity\\Model\:\:\$email\.$#' + identifier: property.notFound + count: 1 + path: src/Phaseolies/Support/Mail/MailService.php + + - + message: '#^Call to an undefined method Phaseolies\\Support\\Mail\\Mailable\:\:attachment\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Support/Mail/MailService.php + + - + message: '#^Call to an undefined method Phaseolies\\Support\\Mail\\Mailable\:\:subject\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Support/Mail/MailService.php + + - + message: '#^Call to function is_array\(\) with array will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 2 + path: src/Phaseolies/Support/Mail/MailService.php + + - + message: '#^Class Phaseolies\\Support\\Mail\\MailService constructor invoked with 1 parameter, 0 required\.$#' + identifier: arguments.count + count: 1 + path: src/Phaseolies/Support/Mail/MailService.php + + - + message: '#^Call to an undefined method Phaseolies\\Support\\Mail\\Mailable\:\:content\(\)\.$#' + identifier: method.notFound + count: 3 + path: src/Phaseolies/Support/Mail/Mailable/View.php + + - + message: '#^Call to function is_array\(\) with array will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/Support/Mail/Mailable/View.php + + - + message: '#^Using nullsafe property access "\?\-\>view" in empty\(\) is unnecessary\. Use \-\> instead\.$#' + identifier: nullsafe.neverNull + count: 1 + path: src/Phaseolies/Support/Mail/Mailable/View.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 1 + path: src/Phaseolies/Support/Presenter/Presenter.php + + - + message: '#^Access to an undefined property Phaseolies\\Support\\Router\:\:\$routeMiddleware\.$#' + identifier: property.notFound + count: 2 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Call to an undefined method \$this\(Phaseolies\\Support\\Router\)\:\:applyMiddleware\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Call to an undefined method Phaseolies\\Support\\Router\:\:handle\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Call to an undefined method ReflectionType\:\:getName\(\)\.$#' + identifier: method.notFound + count: 4 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Call to an undefined method ReflectionType\:\:isBuiltin\(\)\.$#' + identifier: method.notFound + count: 4 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Call to function is_array\(\) with array will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 2 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Call to function is_string\(\) with \*NEVER\* will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Cannot call method bindTo\(\) on request\|string\.$#' + identifier: method.nonObject + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Class App\\Http\\Controllers\\Controller not found\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Instanceof between \*NEVER\* and Closure will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Instanceof between mixed and ArrayObject will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Instanceof between mixed and JsonSerializable will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Instanceof between mixed and Phaseolies\\Database\\Entity\\Builder will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Instanceof between mixed and Phaseolies\\Database\\Entity\\Model will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Instanceof between mixed and Ramsey\\Collection\\Collection will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Instanceof between mixed and stdClass will always evaluate to false\.$#' + identifier: instanceof.alwaysFalse + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Method Phaseolies\\Support\\Router\:\:middleware\(\) has invalid return type Phaseolies\\Support\\Route\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Offset 0 on non\-empty\-list\&callable\(string\)\: void on left side of \?\? always exists and is not nullable\.$#' + identifier: nullCoalesce.offset + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$key$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^PHPDoc tag @return with type Phaseolies\\Support\\Route is not subtype of native type Phaseolies\\Support\\Router\.$#' + identifier: return.phpDocType + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Parameter \#1 \$abstract of method Phaseolies\\Application\:\:make\(\) expects class\-string\, string given\.$#' + identifier: argument.type + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Property Phaseolies\\Utilities\\Attributes\\BindPayload\:\:\$strict \(bool\) on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.property + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Property Phaseolies\\Utilities\\Attributes\\Route\:\:\$middleware \(array\) on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.property + count: 1 + path: src/Phaseolies/Support/Router.php + + - + message: '#^Variable \$attributes on left side of \?\? always exists and is not nullable\.$#' + identifier: nullCoalesce.variable + count: 2 + path: src/Phaseolies/Support/Router.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$data$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Support/Session.php + + - + message: '#^Call to function is_null\(\) with string will always evaluate to false\.$#' + identifier: function.impossibleType + count: 1 + path: src/Phaseolies/Support/Storage/FileSystem.php + + - + message: '#^PHPDoc tag @method for method Phaseolies\\Support\\Storage\\StorageFileService\:\:store\(\) parameter \#2 \$file contains unknown class Phaseolies\\Support\\Storage\\File\.$#' + identifier: class.notFound + count: 1 + path: src/Phaseolies/Support/Storage/StorageFileService.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(\)\: string\)\: Unexpected token "\\n \* ", expected type at offset 130 on line 3$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Storage/StorageFileService.php + + - + message: '#^PHPDoc tag @method has invalid value \(\(string\|array \$path\)\: bool\)\: Unexpected token "\\n \* ", expected type at offset 259 on line 6$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Storage/StorageFileService.php + + - + message: '#^PHPDoc tag @method has invalid value \(static get\(string \$path\)\: \?string\)\: Unexpected token "\\n \* ", expected type at offset 175 on line 4$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/Storage/StorageFileService.php + + - + message: '#^Instanceof between Iterator and Traversable will always evaluate to true\.$#' + identifier: instanceof.alwaysTrue + count: 1 + path: src/Phaseolies/Support/StreamCollection.php + + - + message: '#^Result of && is always false\.$#' + identifier: booleanAnd.alwaysFalse + count: 1 + path: src/Phaseolies/Support/StreamCollection.php + + - + message: '#^Unreachable statement \- code above always terminates\.$#' + identifier: deadCode.unreachable + count: 1 + path: src/Phaseolies/Support/StreamCollection.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 10 + path: src/Phaseolies/Support/StreamCollection.php + + - + message: '#^Offset 0 on array\{list\\} on left side of \?\? always exists and is not nullable\.$#' + identifier: nullCoalesce.offset + count: 1 + path: src/Phaseolies/Support/StringService.php + + - + message: '#^PHPDoc tag @param has invalid value \(string\)\: Unexpected token "\\n ", expected variable at offset 219 on line 7$#' + identifier: phpDoc.parseError + count: 1 + path: src/Phaseolies/Support/StringService.php + + - + message: '#^Expression on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.expr + count: 1 + path: src/Phaseolies/Support/UrlGenerator.php + + - + message: '#^Strict comparison using \=\=\= between mixed and null will always evaluate to false\.$#' + identifier: identical.alwaysFalse + count: 2 + path: src/Phaseolies/Support/Validation/Sanitizer.php + + - + message: '#^Call to an undefined method Phaseolies\\Support\\View\\View\:\:prepare\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Phaseolies/Support/View/View.php + + - + message: '#^Call to function is_string\(\) with string will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: src/Phaseolies/Support/View/View.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$view$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Support/View/View.php + + - + message: '#^Variable \$message might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: src/Phaseolies/Support/View/errors/401.odo.php + + - + message: '#^Variable \$message might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: src/Phaseolies/Support/View/errors/403.odo.php + + - + message: '#^Variable \$message might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: src/Phaseolies/Support/View/errors/404.odo.php + + - + message: '#^Variable \$message might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: src/Phaseolies/Support/View/errors/429.odo.php + + - + message: '#^Variable \$message might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: src/Phaseolies/Support/View/errors/500.odo.php + + - + message: '#^Call to function is_string\(\) with array will always evaluate to false\.$#' + identifier: function.impossibleType + count: 1 + path: src/Phaseolies/Utilities/Attributes/Route.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$v4Bytes$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Utilities/IpUtils.php + + - + message: '#^PHPDoc tag @param references unknown parameter\: \$v6Bytes$#' + identifier: parameter.notFound + count: 1 + path: src/Phaseolies/Utilities/IpUtils.php + + - + message: '#^PHPDoc tag @return with type string\|null is incompatible with native type array\.$#' + identifier: return.phpDocType + count: 1 + path: src/Phaseolies/Utilities/Paginator.php + + - + message: '#^Strict comparison using \=\=\= between 1 and 1 will always evaluate to true\.$#' + identifier: identical.alwaysTrue + count: 1 + path: src/Phaseolies/Utilities/Paginator.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 00000000..d904d60f --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,11 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 5 + paths: + - src + scanFiles: + - .phpstan/stubs/AppHttpKernel.php + tmpDir: .phpstan.cache + reportUnmatchedIgnoredErrors: false From 3d8d41333fc8089990945cfe890e169bbd036e3a Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Thu, 27 Aug 2026 15:48:12 +0600 Subject: [PATCH 010/179] fix: validation rules class after adding phpstan --- src/Phaseolies/Http/Support/ValidationRules.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Phaseolies/Http/Support/ValidationRules.php b/src/Phaseolies/Http/Support/ValidationRules.php index 3860688e..8ed11464 100644 --- a/src/Phaseolies/Http/Support/ValidationRules.php +++ b/src/Phaseolies/Http/Support/ValidationRules.php @@ -569,7 +569,7 @@ protected function isNullable(array $input, string $fieldName): bool { $value = $input[$fieldName] ?? ''; - return $value === null || $value === ''; + return $value === ''; } /** @@ -832,7 +832,7 @@ protected function isEmptyFieldRequired(array $input, string $fieldName): bool return empty($value); } - return $value === '' || $value === null; + return $value === ''; } /** From bc6289f11922e49bcf47cd27f2f5493b693a9c47 Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Thu, 27 Aug 2026 21:16:51 +0600 Subject: [PATCH 011/179] Rename ServiceProvider to Launcher --- phpunit.xml.dist | 2 +- src/Phaseolies/Application.php | 80 +++++++++------ .../Console/Commands/MakeLauncherCommand.php | 99 +++++++++++++++++++ .../Console/Commands/MakeProviderCommand.php | 98 +----------------- .../Console/Commands/VendorPublishCommand.php | 30 +++--- .../CacheLauncher.php} | 10 +- .../FacadeLauncher.php} | 6 +- .../GhostableLauncher.php} | 4 +- .../LanguageLauncher.php} | 10 +- .../PackageServiceLauncher.php} | 4 +- .../RateLimiterLauncher.php} | 10 +- .../RouteLauncher.php} | 6 +- .../ServiceLauncher.php} | 18 ++-- .../SessionLauncher.php} | 10 +- src/Phaseolies/Support/Facades/Route.php | 6 ++ tests/Application/ApplicationTest.php | 4 +- .../Mock/Providers/GhostableTestProvider.php | 8 +- .../Builder/DatabaseBuilderAllDriverTest.php | 10 +- .../DatabaseBuilderBetweenNullCountTest.php | 10 +- .../Builder/DatabaseBuilderCountFetchTest.php | 20 ++-- .../DatabaseBuilderDynamicWhereTest.php | 2 +- .../Builder/DatabaseBuilderInRawOrderTest.php | 6 +- .../DatabaseBuilderJoinsFromOmitTest.php | 10 +- .../DatabaseBuilderJsonDateTimeTest.php | 6 +- .../Builder/DatabaseBuilderLikeSearchTest.php | 10 +- .../DatabaseBuilderMutationDistinctTest.php | 16 +-- tests/Builder/DatabaseBuilderTest.php | 10 +- .../DatabaseBuilderUpsertGroupTest.php | 8 +- tests/Builder/DatabaseBuilderWriteOpsTest.php | 10 +- tests/Builder/DatabaseTest.php | 4 +- tests/Builder/TimeframeOrConditionsTest.php | 14 +-- tests/Console/CommandBehaviorCoverageTest.php | 20 ++-- .../ServiceLauncherTest.php} | 32 +++--- tests/Requests/RateLimiterTest.php | 18 ++-- tests/Translation/TranslatorTest.php | 6 +- 35 files changed, 326 insertions(+), 291 deletions(-) create mode 100644 src/Phaseolies/Console/Commands/MakeLauncherCommand.php rename src/Phaseolies/{Providers/CacheServiceProvider.php => Launchers/CacheLauncher.php} (95%) rename src/Phaseolies/{Providers/FacadeServiceProvider.php => Launchers/FacadeLauncher.php} (97%) rename src/Phaseolies/{Providers/GhostableProvider.php => Launchers/GhostableLauncher.php} (75%) rename src/Phaseolies/{Providers/LanguageServiceProvider.php => Launchers/LanguageLauncher.php} (86%) rename src/Phaseolies/{Providers/PackageServiceProvider.php => Launchers/PackageServiceLauncher.php} (96%) rename src/Phaseolies/{Providers/RateLimiterServiceProvider.php => Launchers/RateLimiterLauncher.php} (75%) rename src/Phaseolies/{Providers/RouteServiceProvider.php => Launchers/RouteLauncher.php} (90%) rename src/Phaseolies/{Providers/ServiceProvider.php => Launchers/ServiceLauncher.php} (93%) rename src/Phaseolies/{Providers/SessionServiceProvider.php => Launchers/SessionLauncher.php} (56%) rename tests/{Providers/ServiceProviderTest.php => Launchers/ServiceLauncherTest.php} (89%) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7ff869cc..44a48534 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,4 +16,4 @@ --> - \ No newline at end of file + diff --git a/src/Phaseolies/Application.php b/src/Phaseolies/Application.php index 32957c40..1df714f9 100644 --- a/src/Phaseolies/Application.php +++ b/src/Phaseolies/Application.php @@ -4,8 +4,8 @@ use Phaseolies\Auth\ActorManager; use Phaseolies\Support\Router; -use Phaseolies\Providers\GhostableProvider; -use Phaseolies\Providers\ServiceProvider; +use Phaseolies\Launchers\GhostableLauncher; +use Phaseolies\Launchers\ServiceLauncher; use Phaseolies\Http\DispatchResult; use Phaseolies\Http\Response; use Phaseolies\Http\Request; @@ -122,7 +122,7 @@ class Application extends Container protected $isRunningInConsole = null; /** - * The registered service providers. + * The registered service launchers. * * @var array */ @@ -131,28 +131,28 @@ class Application extends Container /** * The queued ghost providers keyed by class name. * - * @var array, ServiceProvider> + * @var array, ServiceLauncher> */ protected array $ghostProviders = []; /** * Map of service identifiers to ghost provider classes. * - * @var array> + * @var array> */ protected array $ghostServices = []; /** * Tracks ghost providers that have already been loaded. * - * @var array, true> + * @var array, true> */ protected array $loadedGhostProviders = []; /** * Tracks ghost providers currently being loaded. * - * @var array, true> + * @var array, true> */ protected array $loadingGhostProviders = []; @@ -173,7 +173,7 @@ class Application extends Container /** * Tracks providers whose boot method has already run. * - * @var array, true> + * @var array, true> */ protected array $bootedProviderClasses = []; @@ -331,7 +331,7 @@ public function getEnvironment(): string */ protected function registerCoreProviders(): self { - $providers = [...($this->loadCoreProviders()), ...(config('app.providers') ?? [])]; + $providers = [...($this->loadCoreProviders()), ...(config('app.launchers') ?? [])]; $this->registerProviders($providers); @@ -348,7 +348,7 @@ protected function registerProviders(array $providers = []): void foreach ($providers as $provider) { $providerInstance = new $provider($this); - if ($providerInstance instanceof ServiceProvider) { + if ($providerInstance instanceof ServiceLauncher) { if ($this->shouldQueueGhostProvider($providerInstance)) { $this->queueGhostProvider($providerInstance); continue; @@ -362,21 +362,21 @@ protected function registerProviders(array $providers = []): void /** * Determine if the provider should be queued as a ghost provider * - * @param ServiceProvider $providerInstance + * @param ServiceLauncher $providerInstance * @return bool */ - protected function shouldQueueGhostProvider(ServiceProvider $providerInstance): bool + protected function shouldQueueGhostProvider(ServiceLauncher $providerInstance): bool { - return !$this->runningInConsole() && $providerInstance instanceof GhostableProvider; + return !$this->runningInConsole() && $providerInstance instanceof GhostableLauncher; } /** * Register and track an eager provider instance. * - * @param ServiceProvider $providerInstance + * @param ServiceLauncher $providerInstance * @return void */ - protected function registerProviderInstance(ServiceProvider $providerInstance): void + protected function registerProviderInstance(ServiceLauncher $providerInstance): void { $providerInstance->register(); @@ -386,12 +386,12 @@ protected function registerProviderInstance(ServiceProvider $providerInstance): /** * Queue a ghost provider until one of its services is requested. * - * @param ServiceProvider $providerInstance + * @param ServiceLauncher $providerInstance * @return void */ - protected function queueGhostProvider(ServiceProvider $providerInstance): void + protected function queueGhostProvider(ServiceLauncher $providerInstance): void { - /** @var GhostableProvider $providerInstance */ + /** @var ServiceLauncher&GhostableLauncher $providerInstance */ $providerClass = $providerInstance::class; $this->ghostProviders[$providerClass] = $providerInstance; @@ -794,12 +794,12 @@ protected function bindSingletonClasses(): void protected function loadCoreProviders(): array { return [ - \Phaseolies\Providers\FacadeServiceProvider::class, - \Phaseolies\Providers\LanguageServiceProvider::class, - \Phaseolies\Providers\SessionServiceProvider::class, - \Phaseolies\Providers\RouteServiceProvider::class, - \Phaseolies\Providers\CacheServiceProvider::class, - \Phaseolies\Providers\RateLimiterServiceProvider::class, + \Phaseolies\Launchers\FacadeLauncher::class, + \Phaseolies\Launchers\LanguageLauncher::class, + \Phaseolies\Launchers\SessionLauncher::class, + \Phaseolies\Launchers\RouteLauncher::class, + \Phaseolies\Launchers\CacheLauncher::class, + \Phaseolies\Launchers\RateLimiterLauncher::class, ]; } @@ -813,13 +813,23 @@ public function getProviders(): array return $this->serviceProviders; } + /** + * Get all registered service launchers. + * + * @return array + */ + public function getLaunchers(): array + { + return $this->serviceProviders; + } + /** * Get a specific provider by class name * * @param string $provider - * @return ServiceProvider|null + * @return ServiceLauncher|null */ - public function getProvider(string $provider): ?ServiceProvider + public function getProvider(string $provider): ?ServiceLauncher { foreach ($this->serviceProviders as $serviceProvider) { if (get_class($serviceProvider) === $provider) { @@ -830,6 +840,14 @@ public function getProvider(string $provider): ?ServiceProvider return null; } + /** + * Get a registered launcher by class name. + */ + public function getLauncher(string $launcher): ?ServiceLauncher + { + return $this->getProvider($launcher); + } + /** * Determine if the application has a binding or queued ghost for the given service. * @@ -861,13 +879,13 @@ public function loadGhostProvider(string $abstract): bool $providerInstance = $this->ghostProviders[$providerClass] ?? null; - if (!$providerInstance instanceof ServiceProvider) { + if (!$providerInstance instanceof ServiceLauncher) { return false; } $this->loadingGhostProviders[$providerClass] = true; - foreach (($providerInstance instanceof GhostableProvider ? $providerInstance->ghosts() : []) as $ghost) { + foreach (($providerInstance instanceof GhostableLauncher ? $providerInstance->ghosts() : []) as $ghost) { unset($this->ghostServices[$ghost]); } @@ -889,10 +907,10 @@ public function loadGhostProvider(string $abstract): bool /** * Boot a provider instance once. * - * @param ServiceProvider $providerInstance + * @param ServiceLauncher $providerInstance * @return void */ - protected function bootProviderInstance(ServiceProvider $providerInstance): void + protected function bootProviderInstance(ServiceLauncher $providerInstance): void { $providerClass = $providerInstance::class; @@ -900,7 +918,7 @@ protected function bootProviderInstance(ServiceProvider $providerInstance): void return; } - $providerInstance->boot(); + $providerInstance->launch(); $this->bootedProviderClasses[$providerClass] = true; } diff --git a/src/Phaseolies/Console/Commands/MakeLauncherCommand.php b/src/Phaseolies/Console/Commands/MakeLauncherCommand.php new file mode 100644 index 00000000..669cdaa3 --- /dev/null +++ b/src/Phaseolies/Console/Commands/MakeLauncherCommand.php @@ -0,0 +1,99 @@ +executeWithTiming(function () { + [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); + $namespace = 'App\\Launchers' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); + $filePath = $this->generatedFilePath('src/Launchers', $name); + + // Check if launcher already exists + if (file_exists($filePath)) { + $this->displayError('Launcher already exists at:'); + $this->line('' . $this->relativePath($filePath) . ''); + return Command::FAILURE; + } + + // Create directory if needed + $directoryPath = dirname($filePath); + if (!is_dir($directoryPath)) { + mkdir($directoryPath, 0755, true); + } + + // Generate and save Launcher class + $content = $this->generateProviderContent($namespace, $className); + file_put_contents($filePath, $content); + + $this->displaySuccess('Launcher created successfully'); + $this->line('📦 File: ' . $this->relativePath($filePath) . ''); + $this->newLine(); + $this->line('📌 Class: ' . $className . ''); + + return Command::SUCCESS; + }); + } + + /** + * Generate provider class content. + */ + protected function generateProviderContent(string $namespace, string $className): string + { + return <<executeWithTiming(function () { - [$name, $parts, $className] = $this->splitGeneratedName((string) $this->argument('name')); - $namespace = 'App\\Providers' . (count($parts) > 0 ? '\\' . implode('\\', $parts) : ''); - $filePath = $this->generatedFilePath('src/Providers', $name); - - // Check if provider already exists - if (file_exists($filePath)) { - $this->displayError('Provider already exists at:'); - $this->line('' . $this->relativePath($filePath) . ''); - return Command::FAILURE; - } - - // Create directory if needed - $directoryPath = dirname($filePath); - if (!is_dir($directoryPath)) { - mkdir($directoryPath, 0755, true); - } - - // Generate and save provider class - $content = $this->generateProviderContent($namespace, $className); - file_put_contents($filePath, $content); - - $this->displaySuccess('Provider created successfully'); - $this->line('📦 File: ' . $this->relativePath($filePath) . ''); - $this->newLine(); - $this->line('📌 Class: ' . $className . ''); - - return Command::SUCCESS; - }); - } - - /** - * Generate provider class content. - */ - protected function generateProviderContent(string $namespace, string $className): string - { - return <<executeWithTiming(function () { - $provider = $this->option('provider'); + $launcher = $this->option('launcher'); $tag = $this->option('tag'); $force = $this->option('force'); - if ($provider) { - $this->publishProvider($provider, $force); + if ($launcher) { + $this->publishLauncher($launcher, $force); return Command::SUCCESS; } @@ -60,28 +60,28 @@ public function handle(): int }); } - protected function publishProvider(string $provider, bool $force = false) + protected function publishLauncher(string $launcher, bool $force = false) { - $providerClass = $this->app->getProvider($provider); + $launcherClass = $this->app->getLauncher($launcher); - if (!$providerClass) { - $this->displayError("Unable to locate provider: {$provider}"); + if (!$launcherClass) { + $this->displayError("Unable to locate launcher: {$launcher}"); return; } - $paths = $providerClass->pathsToPublish($provider); + $paths = $launcherClass->pathsToPublish($launcher); $this->publishPaths($paths, $force); $this->newLine(); - $this->displaySuccess("Published assets for provider: {$provider}"); + $this->displaySuccess("Published assets for launcher: {$launcher}"); } protected function publishTag(string $tag, bool $force = false) { $paths = []; - foreach ($this->app->getProviders() as $provider) { - $providerPaths = $provider->pathsToPublish(null, $tag); + foreach ($this->app->getLaunchers() as $launcher) { + $providerPaths = $launcher->pathsToPublish(null, $tag); if (!empty($providerPaths)) { $paths = array_merge($paths, $providerPaths); } @@ -101,8 +101,8 @@ protected function publishTag(string $tag, bool $force = false) protected function publishAll(bool $force = false) { $publishedCount = 0; - foreach ($this->app->getProviders() as $provider) { - $paths = $provider->pathsToPublish(); + foreach ($this->app->getLaunchers() as $launcher) { + $paths = $launcher->pathsToPublish(); if (!empty($paths)) { $this->publishPaths($paths, $force); $publishedCount++; @@ -110,7 +110,7 @@ protected function publishAll(bool $force = false) } $this->newLine(); - $this->displaySuccess("Published assets from {$publishedCount} providers"); + $this->displaySuccess("Published assets from {$publishedCount} launchers"); } protected function publishPaths(array $paths, bool $force = false) diff --git a/src/Phaseolies/Providers/CacheServiceProvider.php b/src/Phaseolies/Launchers/CacheLauncher.php similarity index 95% rename from src/Phaseolies/Providers/CacheServiceProvider.php rename to src/Phaseolies/Launchers/CacheLauncher.php index 113343df..235a3974 100644 --- a/src/Phaseolies/Providers/CacheServiceProvider.php +++ b/src/Phaseolies/Launchers/CacheLauncher.php @@ -1,18 +1,18 @@ app); } diff --git a/src/Phaseolies/Providers/PackageServiceProvider.php b/src/Phaseolies/Launchers/PackageServiceLauncher.php similarity index 96% rename from src/Phaseolies/Providers/PackageServiceProvider.php rename to src/Phaseolies/Launchers/PackageServiceLauncher.php index ebdb3418..67333f02 100644 --- a/src/Phaseolies/Providers/PackageServiceProvider.php +++ b/src/Phaseolies/Launchers/PackageServiceLauncher.php @@ -1,8 +1,8 @@ app->router->shouldCacheRoutes() && diff --git a/src/Phaseolies/Providers/ServiceProvider.php b/src/Phaseolies/Launchers/ServiceLauncher.php similarity index 93% rename from src/Phaseolies/Providers/ServiceProvider.php rename to src/Phaseolies/Launchers/ServiceLauncher.php index 3b0de7fe..8b56be39 100644 --- a/src/Phaseolies/Providers/ServiceProvider.php +++ b/src/Phaseolies/Launchers/ServiceLauncher.php @@ -1,11 +1,11 @@ publishes)) { - $this->publishes = []; - } - - if (!isset($this->publishGroups)) { - $this->publishGroups = []; - } + // Publish registries are initialized at declaration time. } /** @@ -223,7 +217,7 @@ protected function pathsForProviderOrGroup(string|null $provider, string|null $g } elseif ($group && isset($this->publishGroups[$group])) { return $this->publishGroups[$group]; } elseif ($provider && isset($this->publishes[$provider])) { - return $this->publishes[$provider]; + return [$provider => $this->publishes[$provider]]; } return null; diff --git a/src/Phaseolies/Providers/SessionServiceProvider.php b/src/Phaseolies/Launchers/SessionLauncher.php similarity index 56% rename from src/Phaseolies/Providers/SessionServiceProvider.php rename to src/Phaseolies/Launchers/SessionLauncher.php index 400c3f61..67cfef90 100644 --- a/src/Phaseolies/Providers/SessionServiceProvider.php +++ b/src/Phaseolies/Launchers/SessionLauncher.php @@ -1,10 +1,10 @@ group($attributes, $callback); + } + protected static function getFacadeAccessor() { return 'route'; diff --git a/tests/Application/ApplicationTest.php b/tests/Application/ApplicationTest.php index 053bbbb9..57e4fdba 100644 --- a/tests/Application/ApplicationTest.php +++ b/tests/Application/ApplicationTest.php @@ -221,8 +221,8 @@ public function testCoreProvidersAreLoaded(): void $providers = $this->callProtectedMethod($this->app, 'loadCoreProviders'); $this->assertIsArray($providers); - $this->assertContains(\Phaseolies\Providers\RouteServiceProvider::class, $providers); - $this->assertContains(\Phaseolies\Providers\LanguageServiceProvider::class, $providers); + $this->assertContains(\Phaseolies\Launchers\RouteLauncher::class, $providers); + $this->assertContains(\Phaseolies\Launchers\LanguageLauncher::class, $providers); } public function testGhostableProvidersAreQueuedOutsideConsole(): void diff --git a/tests/Application/Mock/Providers/GhostableTestProvider.php b/tests/Application/Mock/Providers/GhostableTestProvider.php index b7f1cfd4..fe33fae8 100644 --- a/tests/Application/Mock/Providers/GhostableTestProvider.php +++ b/tests/Application/Mock/Providers/GhostableTestProvider.php @@ -2,10 +2,10 @@ namespace Tests\Application\Mock\Providers; -use Phaseolies\Providers\ServiceProvider; -use Phaseolies\Providers\GhostableProvider; +use Phaseolies\Launchers\ServiceLauncher; +use Phaseolies\Launchers\GhostableLauncher; -class GhostableTestProvider extends ServiceProvider implements GhostableProvider +class GhostableTestProvider extends ServiceLauncher implements GhostableLauncher { public static int $registerCount = 0; public static int $bootCount = 0; @@ -29,7 +29,7 @@ public function register(): void } } - public function boot(): void + public function launch(): void { self::$bootCount++; diff --git a/tests/Builder/DatabaseBuilderAllDriverTest.php b/tests/Builder/DatabaseBuilderAllDriverTest.php index 549da9ee..cf9384fa 100644 --- a/tests/Builder/DatabaseBuilderAllDriverTest.php +++ b/tests/Builder/DatabaseBuilderAllDriverTest.php @@ -5,9 +5,11 @@ use PDO; use PDOStatement; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; use Phaseolies\Database\Database; use Phaseolies\Database\Entity\Builder; +#[AllowMockObjectsWithoutExpectations] class DatabaseBuilderAllDriverTest extends TestCase { private $database; @@ -17,9 +19,7 @@ protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute') - ->with(PDO::ATTR_DRIVER_NAME) - ->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); @@ -61,9 +61,7 @@ private function createBuilder(): Builder private function setBuilderDriver(string $driver): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute') - ->with(PDO::ATTR_DRIVER_NAME) - ->willReturn($driver); + $this->pdoMock->method('getAttribute')->willReturn($driver); } /** diff --git a/tests/Builder/DatabaseBuilderBetweenNullCountTest.php b/tests/Builder/DatabaseBuilderBetweenNullCountTest.php index 372dbcec..3a6303af 100644 --- a/tests/Builder/DatabaseBuilderBetweenNullCountTest.php +++ b/tests/Builder/DatabaseBuilderBetweenNullCountTest.php @@ -5,9 +5,11 @@ use PDO; use PDOStatement; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; use Phaseolies\Database\Database; use Phaseolies\Database\Entity\Builder; +#[AllowMockObjectsWithoutExpectations] class DatabaseBuilderBetweenNullCountTest extends TestCase { private $database; @@ -16,7 +18,7 @@ class DatabaseBuilderBetweenNullCountTest extends TestCase protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); $this->database = new Database('default'); @@ -43,7 +45,7 @@ private function createBuilder(): Builder private function setBuilderDriver(string $driver): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn($driver); + $this->pdoMock->method('getAttribute')->willReturn($driver); } public function testWhereBetweenAndNotBetweenSql() @@ -98,10 +100,10 @@ public function testCountWithGroupByUsesSubquery() $stmtMock = $this->createMock(PDOStatement::class); $stmtMock->method('execute')->willReturn(true); - $stmtMock->method('fetch')->with($this->anything())->willReturn(['aggregate' => 5]); + $stmtMock->expects($this->once())->method('fetch')->with($this->anything())->willReturn(['aggregate' => 5]); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('prepare')->willReturn($stmtMock); $builder = $this->createBuilder(); diff --git a/tests/Builder/DatabaseBuilderCountFetchTest.php b/tests/Builder/DatabaseBuilderCountFetchTest.php index fccae201..b0133c62 100644 --- a/tests/Builder/DatabaseBuilderCountFetchTest.php +++ b/tests/Builder/DatabaseBuilderCountFetchTest.php @@ -5,9 +5,11 @@ use PDO; use PDOStatement; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; use Phaseolies\Database\Database; use Phaseolies\Database\Entity\Builder; +#[AllowMockObjectsWithoutExpectations] class DatabaseBuilderCountFetchTest extends TestCase { private $database; @@ -16,7 +18,7 @@ class DatabaseBuilderCountFetchTest extends TestCase protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); $this->database = new Database('default'); @@ -45,10 +47,10 @@ public function testCountWithoutGroupReturnsAggregate() { $stmt = $this->createMock(PDOStatement::class); $stmt->method('execute')->willReturn(true); - $stmt->method('fetch')->with($this->anything())->willReturn(['aggregate' => 7]); + $stmt->expects($this->once())->method('fetch')->with($this->anything())->willReturn(['aggregate' => 7]); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('prepare')->willReturn($stmt); $builder = $this->createBuilder(); @@ -63,15 +65,15 @@ public function testFirstReturnsModelAndNullWhenNoRows() // First call: one row $stmt1 = $this->createMock(PDOStatement::class); $stmt1->method('execute')->willReturn(true); - $stmt1->method('fetch')->with($this->anything())->willReturn(['id' => 1, 'name' => 'Alice']); + $stmt1->expects($this->once())->method('fetch')->with($this->anything())->willReturn(['id' => 1, 'name' => 'Alice']); // Second call: no rows $stmt2 = $this->createMock(PDOStatement::class); $stmt2->method('execute')->willReturn(true); - $stmt2->method('fetch')->with($this->anything())->willReturn(false); + $stmt2->expects($this->once())->method('fetch')->with($this->anything())->willReturn(false); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('prepare')->willReturnOnConsecutiveCalls($stmt1, $stmt2); $builder = $this->createBuilder(); @@ -88,15 +90,15 @@ public function testExistsTrueAndFalse() // True: fetch returns row $stmt1 = $this->createMock(PDOStatement::class); $stmt1->method('execute')->willReturn(true); - $stmt1->method('fetch')->with($this->anything())->willReturn(['id' => 1]); + $stmt1->expects($this->once())->method('fetch')->with($this->anything())->willReturn(['id' => 1]); // False: fetch returns false $stmt2 = $this->createMock(PDOStatement::class); $stmt2->method('execute')->willReturn(true); - $stmt2->method('fetch')->with($this->anything())->willReturn(false); + $stmt2->expects($this->once())->method('fetch')->with($this->anything())->willReturn(false); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('prepare')->willReturnOnConsecutiveCalls($stmt1, $stmt2); $builder = $this->createBuilder(); diff --git a/tests/Builder/DatabaseBuilderDynamicWhereTest.php b/tests/Builder/DatabaseBuilderDynamicWhereTest.php index 9b7d87f9..a300f289 100644 --- a/tests/Builder/DatabaseBuilderDynamicWhereTest.php +++ b/tests/Builder/DatabaseBuilderDynamicWhereTest.php @@ -17,7 +17,7 @@ class DatabaseBuilderDynamicWhereTest extends TestCase protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); $this->database = new Database('default'); diff --git a/tests/Builder/DatabaseBuilderInRawOrderTest.php b/tests/Builder/DatabaseBuilderInRawOrderTest.php index 66f6c772..cffc6fc3 100644 --- a/tests/Builder/DatabaseBuilderInRawOrderTest.php +++ b/tests/Builder/DatabaseBuilderInRawOrderTest.php @@ -5,9 +5,11 @@ use PDO; use PDOStatement; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; use Phaseolies\Database\Database; use Phaseolies\Database\Entity\Builder; +#[AllowMockObjectsWithoutExpectations] class DatabaseBuilderInRawOrderTest extends TestCase { private $database; @@ -16,7 +18,7 @@ class DatabaseBuilderInRawOrderTest extends TestCase protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); $this->database = new Database('default'); @@ -43,7 +45,7 @@ private function createBuilder(): Builder private function setBuilderDriver(string $driver): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn($driver); + $this->pdoMock->method('getAttribute')->willReturn($driver); } public function testWhereInGeneratesPlaceholdersAndToSql() diff --git a/tests/Builder/DatabaseBuilderJoinsFromOmitTest.php b/tests/Builder/DatabaseBuilderJoinsFromOmitTest.php index f100d7e1..cea02cb1 100644 --- a/tests/Builder/DatabaseBuilderJoinsFromOmitTest.php +++ b/tests/Builder/DatabaseBuilderJoinsFromOmitTest.php @@ -5,9 +5,11 @@ use PDO; use PDOStatement; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; use Phaseolies\Database\Database; use Phaseolies\Database\Entity\Builder; +#[AllowMockObjectsWithoutExpectations] class DatabaseBuilderJoinsFromOmitTest extends TestCase { private $database; @@ -16,7 +18,7 @@ class DatabaseBuilderJoinsFromOmitTest extends TestCase protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); $this->database = new Database('default'); @@ -43,7 +45,7 @@ private function createBuilder(): Builder private function setBuilderDriver(string $driver): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn($driver); + $this->pdoMock->method('getAttribute')->willReturn($driver); } public function testJoinClausesInToSql() @@ -72,14 +74,14 @@ public function testOmitExcludesColumnsFromSelect() { // DESCRIBE users -> columns id,name,email $describeStmt = $this->createMock(PDOStatement::class); - $describeStmt->method('fetchAll')->with($this->anything())->willReturn([ + $describeStmt->expects($this->once())->method('fetchAll')->with($this->anything())->willReturn([ ['Field' => 'id'], ['Field' => 'name'], ['Field' => 'email'], ]); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('query')->willReturn($describeStmt); $builder = $this->createBuilder(); diff --git a/tests/Builder/DatabaseBuilderJsonDateTimeTest.php b/tests/Builder/DatabaseBuilderJsonDateTimeTest.php index 74e4ea7d..27238896 100644 --- a/tests/Builder/DatabaseBuilderJsonDateTimeTest.php +++ b/tests/Builder/DatabaseBuilderJsonDateTimeTest.php @@ -4,9 +4,11 @@ use PDO; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; use Phaseolies\Database\Database; use Phaseolies\Database\Entity\Builder; +#[AllowMockObjectsWithoutExpectations] class DatabaseBuilderJsonDateTimeTest extends TestCase { private $database; @@ -15,7 +17,7 @@ class DatabaseBuilderJsonDateTimeTest extends TestCase protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); $this->database = new Database('default'); @@ -42,7 +44,7 @@ private function createBuilder(): Builder private function setBuilderDriver(string $driver): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn($driver); + $this->pdoMock->method('getAttribute')->willReturn($driver); } public function testJsonContainsMySQL() diff --git a/tests/Builder/DatabaseBuilderLikeSearchTest.php b/tests/Builder/DatabaseBuilderLikeSearchTest.php index 038cefbb..61feae6b 100644 --- a/tests/Builder/DatabaseBuilderLikeSearchTest.php +++ b/tests/Builder/DatabaseBuilderLikeSearchTest.php @@ -5,9 +5,11 @@ use PDO; use PDOStatement; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; use Phaseolies\Database\Database; use Phaseolies\Database\Entity\Builder; +#[AllowMockObjectsWithoutExpectations] class DatabaseBuilderLikeSearchTest extends TestCase { private $database; @@ -17,9 +19,7 @@ protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute') - ->with(PDO::ATTR_DRIVER_NAME) - ->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); @@ -48,9 +48,7 @@ private function createBuilder(): Builder private function setBuilderDriver(string $driver): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute') - ->with(PDO::ATTR_DRIVER_NAME) - ->willReturn($driver); + $this->pdoMock->method('getAttribute')->willReturn($driver); } private function getBuilderConditions(Builder $builder): array diff --git a/tests/Builder/DatabaseBuilderMutationDistinctTest.php b/tests/Builder/DatabaseBuilderMutationDistinctTest.php index eacf65b7..24ae5fce 100644 --- a/tests/Builder/DatabaseBuilderMutationDistinctTest.php +++ b/tests/Builder/DatabaseBuilderMutationDistinctTest.php @@ -18,7 +18,7 @@ class DatabaseBuilderMutationDistinctTest extends TestCase protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); $this->database = new Database('default'); @@ -45,7 +45,7 @@ private function createBuilder(): Builder private function setBuilderDriver(string $driver): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn($driver); + $this->pdoMock->method('getAttribute')->willReturn($driver); } public function testIncrementAndDecrementReturnRowCount() @@ -58,7 +58,7 @@ public function testIncrementAndDecrementReturnRowCount() $stmtMock->method('rowCount')->willReturn(3); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('prepare')->willReturn($stmtMock); $builder = $this->createBuilder(); @@ -74,12 +74,12 @@ public function testDistinctInvalidColumnThrows() $this->setBuilderDriver('mysql'); $describeStmt = $this->createMock(PDOStatement::class); - $describeStmt->method('fetchAll') + $describeStmt->expects($this->once())->method('fetchAll') ->with($this->anything()) ->willReturn([['Field' => 'id'], ['Field' => 'name']]); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('query')->willReturn($describeStmt); $this->expectException(\InvalidArgumentException::class); @@ -92,16 +92,16 @@ public function testDistinctReturnsCollection() $this->setBuilderDriver('mysql'); $describeStmt = $this->createMock(PDOStatement::class); - $describeStmt->method('fetchAll') + $describeStmt->expects($this->once())->method('fetchAll') ->with($this->anything()) ->willReturn([['Field' => 'id'], ['Field' => 'status']]); $selectStmt = $this->createMock(PDOStatement::class); $selectStmt->method('execute')->willReturn(true); - $selectStmt->method('fetchAll')->with($this->anything(), $this->equalTo(0))->willReturn(['active', 'pending']); + $selectStmt->expects($this->once())->method('fetchAll')->with($this->anything(), $this->equalTo(0))->willReturn(['active', 'pending']); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('query')->willReturn($describeStmt); $this->pdoMock->method('prepare')->willReturn($selectStmt); diff --git a/tests/Builder/DatabaseBuilderTest.php b/tests/Builder/DatabaseBuilderTest.php index d418cfa2..1bb08239 100644 --- a/tests/Builder/DatabaseBuilderTest.php +++ b/tests/Builder/DatabaseBuilderTest.php @@ -5,9 +5,11 @@ use PDO; use PDOStatement; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; use Phaseolies\Database\Database; use Phaseolies\Database\Entity\Builder; +#[AllowMockObjectsWithoutExpectations] class DatabaseBuilderTest extends TestCase { private $database; @@ -17,9 +19,7 @@ protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute') - ->with(PDO::ATTR_DRIVER_NAME) - ->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); @@ -61,9 +61,7 @@ private function createBuilder(): Builder private function setBuilderDriver(string $driver): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute') - ->with(PDO::ATTR_DRIVER_NAME) - ->willReturn($driver); + $this->pdoMock->method('getAttribute')->willReturn($driver); } /** diff --git a/tests/Builder/DatabaseBuilderUpsertGroupTest.php b/tests/Builder/DatabaseBuilderUpsertGroupTest.php index 0bda2755..ddf8171d 100644 --- a/tests/Builder/DatabaseBuilderUpsertGroupTest.php +++ b/tests/Builder/DatabaseBuilderUpsertGroupTest.php @@ -17,7 +17,7 @@ class DatabaseBuilderUpsertGroupTest extends TestCase protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); $this->database = new Database('default'); @@ -44,7 +44,7 @@ private function createBuilder(): Builder private function setBuilderDriver(string $driver): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn($driver); + $this->pdoMock->method('getAttribute')->willReturn($driver); } public function testGroupByAutoAggregatesNonGroupedFields() @@ -98,12 +98,12 @@ public function testGetUpsertSqlPostgreSQL() public function testGetUpsertSqlSQLite() { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('sqlite'); + $this->pdoMock->method('getAttribute')->willReturn('sqlite'); $versionStmt = $this->createMock(\PDOStatement::class); $versionStmt->method('fetchColumn')->willReturn('3.39.0'); - $this->pdoMock->method('query') + $this->pdoMock->expects($this->once())->method('query') ->with($this->equalTo('SELECT sqlite_version()')) ->willReturn($versionStmt); diff --git a/tests/Builder/DatabaseBuilderWriteOpsTest.php b/tests/Builder/DatabaseBuilderWriteOpsTest.php index ac7d9240..2e4e52d1 100644 --- a/tests/Builder/DatabaseBuilderWriteOpsTest.php +++ b/tests/Builder/DatabaseBuilderWriteOpsTest.php @@ -18,7 +18,7 @@ class DatabaseBuilderWriteOpsTest extends TestCase protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); $this->database = new Database('default'); @@ -48,7 +48,7 @@ private function createBuilder(): Builder // $stmt->method('execute')->willReturn(true); // $this->pdoMock = $this->createMock(PDO::class); - // $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + // $this->pdoMock->method('getAttribute')->willReturn('mysql'); // $this->pdoMock->method('prepare')->willReturn($stmt); // $this->pdoMock->method('lastInsertId')->willReturn('42'); @@ -82,7 +82,7 @@ public function testInsertManyBindsAndChunks() $stmt->method('rowCount')->willReturn(2); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('prepare')->willReturn($stmt); $builder = $this->createBuilder(); @@ -103,7 +103,7 @@ public function testUpdateBuildsSetAndBinds() $stmt->method('bindValue'); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('prepare')->willReturn($stmt); $builder = $this->createBuilder(); @@ -119,7 +119,7 @@ public function testDeleteBindsConditions() $stmt->method('bindValue'); $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute')->with(PDO::ATTR_DRIVER_NAME)->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->pdoMock->method('prepare')->willReturn($stmt); $builder = $this->createBuilder(); diff --git a/tests/Builder/DatabaseTest.php b/tests/Builder/DatabaseTest.php index 72b32978..d837974c 100644 --- a/tests/Builder/DatabaseTest.php +++ b/tests/Builder/DatabaseTest.php @@ -25,9 +25,7 @@ protected function setUp(): void $this->pdoMock = $this->createMock(PDO::class); // Mock the driver attribute for all tests - $this->pdoMock->method('getAttribute') - ->with(PDO::ATTR_DRIVER_NAME) - ->willReturn('mysql'); // or 'sqlite' + $this->pdoMock->method('getAttribute')->willReturn('mysql'); // or 'sqlite' $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); diff --git a/tests/Builder/TimeframeOrConditionsTest.php b/tests/Builder/TimeframeOrConditionsTest.php index 4076a968..cdb6d8bf 100644 --- a/tests/Builder/TimeframeOrConditionsTest.php +++ b/tests/Builder/TimeframeOrConditionsTest.php @@ -4,10 +4,12 @@ use PDO; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; use Phaseolies\Database\Database; use Phaseolies\Database\Entity\Builder; use Tests\Support\Model\MockUser; +#[AllowMockObjectsWithoutExpectations] class TimeframeOrConditionsTest extends TestCase { private $pdoMock; @@ -15,9 +17,7 @@ class TimeframeOrConditionsTest extends TestCase protected function setUp(): void { $this->pdoMock = $this->createMock(PDO::class); - $this->pdoMock->method('getAttribute') - ->with(PDO::ATTR_DRIVER_NAME) - ->willReturn('mysql'); + $this->pdoMock->method('getAttribute')->willReturn('mysql'); $this->setStaticProperty(Database::class, 'connections', ['default' => $this->pdoMock]); $this->setStaticProperty(Database::class, 'transactions', []); @@ -208,9 +208,7 @@ public function testOrWhereYesterdayAloneAddsDateCondition() public function testOrWhereTimeForPostgresUsesExtract() { $pgPdo = $this->createMock(PDO::class); - $pgPdo->method('getAttribute') - ->with(PDO::ATTR_DRIVER_NAME) - ->willReturn('pgsql'); + $pgPdo->method('getAttribute')->willReturn('pgsql'); $b = new Builder($pgPdo, 'users', MockUser::class, 15); @@ -223,9 +221,7 @@ public function testOrWhereTimeForPostgresUsesExtract() public function testOrWhereMonthForSqliteUsesStrftime() { $sqPdo = $this->createMock(PDO::class); - $sqPdo->method('getAttribute') - ->with(PDO::ATTR_DRIVER_NAME) - ->willReturn('sqlite'); + $sqPdo->method('getAttribute')->willReturn('sqlite'); $b = new Builder($sqPdo, 'users', MockUser::class, 15); diff --git a/tests/Console/CommandBehaviorCoverageTest.php b/tests/Console/CommandBehaviorCoverageTest.php index 7c82a3e7..d0d9fcfd 100644 --- a/tests/Console/CommandBehaviorCoverageTest.php +++ b/tests/Console/CommandBehaviorCoverageTest.php @@ -140,8 +140,8 @@ public function testCommandHelpersNormalizeGeneratedNamesAndRelativePaths(): voi $this->assertSame(['Admin', 'Hello'], $parts); $this->assertSame('TestProvider', $className); $this->assertSame( - 'src/Providers/Hello/TestProvider.php', - $this->invokeMethod($command, 'relativePath', [Env::path('src/Providers/Hello/TestProvider.php')]) + 'src/Launchers/Hello/TestProvider.php', + $this->invokeMethod($command, 'relativePath', [Env::path('src/Launchers/Hello/TestProvider.php')]) ); } @@ -152,19 +152,19 @@ public function testMakeProviderCommandAcceptsBackslashesAndOutputsRelativePathW use InteractsWithFakeCommandIO; }; - $command->fakeArguments['name'] = 'Hello\\TestProvider'; + $command->fakeArguments['name'] = 'Hello\\TestLauncher'; $result = $command->handle(); - $file = Env::path('src/Providers/Hello/TestProvider.php'); + $file = Env::path('src/Launchers/Hello/TestLauncher.php'); $contents = (string) file_get_contents($file); $lines = array_map(static fn(array $line): string => $line[0], $command->capturedLines); $this->assertSame(0, $result); $this->assertFileExists($file); - $this->assertStringContainsString('namespace App\\Providers\\Hello;', $contents); - $this->assertStringContainsString('class TestProvider extends ServiceProvider', $contents); + $this->assertStringContainsString('namespace App\\Launchers\\Hello;', $contents); + $this->assertStringContainsString('class TestLauncher extends ServiceLauncher', $contents); $this->assertContains( - '📦 File: src/Providers/Hello/TestProvider.php', + '📦 File: src/Launchers/Hello/TestLauncher.php', $lines ); } @@ -245,11 +245,11 @@ public function __construct() }; return [ - 'provider' => [ + 'launcher' => [ new MakeProviderCommand(), 'generateProviderContent', - ['App\\Providers', 'AppServiceProvider'], - ['class AppServiceProvider extends ServiceProvider', 'public function register(): void'], + ['App\\Launchers', 'AppLauncher'], + ['class AppLauncher extends ServiceLauncher', 'public function launch(): void'], ], 'rule' => [ new MakeRuleCommand(), diff --git a/tests/Providers/ServiceProviderTest.php b/tests/Launchers/ServiceLauncherTest.php similarity index 89% rename from tests/Providers/ServiceProviderTest.php rename to tests/Launchers/ServiceLauncherTest.php index 984eb85c..b1ac6a94 100644 --- a/tests/Providers/ServiceProviderTest.php +++ b/tests/Launchers/ServiceLauncherTest.php @@ -1,22 +1,22 @@ app = $this->createMock(Application::class); - $this->provider = new TestServiceProvider($this->app); + $this->app = $this->createStub(Application::class); + $this->provider = new TestServiceLauncher($this->app); } public function testConstructor() { - $this->assertInstanceOf(ServiceProvider::class, $this->provider); + $this->assertInstanceOf(ServiceLauncher::class, $this->provider); // Test that app is properly set via reflection $reflection = new \ReflectionClass($this->provider); @@ -84,7 +84,7 @@ public function testLoadRoutesWithNonExistingFile() public function testMergeConfigWithoutConfigService() { - $this->app->method('has')->with('config')->willReturn(false); + $this->app->method('has')->willReturn(false); // Should not throw any exception when config service doesn't exist $this->provider->mergeConfig('/some/path.php', 'test.key'); @@ -94,7 +94,7 @@ public function testPublishesViews() { $paths = ['path1', 'path2']; - $provider = new class($this->app) extends TestServiceProvider { + $provider = new class($this->app) extends TestServiceLauncher { public function testPublishesViews(array $paths, string $group = 'views') { $this->publishesViews($paths, $group); @@ -113,14 +113,14 @@ public function testPublishesViews(array $paths, string $group = 'views') public function testLoadViewsWithoutViewService() { - $this->app->method('has')->with('view')->willReturn(false); + $this->app->method('has')->willReturn(false); $this->provider->loadViews('/test/path', 'test-namespace'); } public function testLoadTranslationsWithoutTranslatorService() { - $this->app->method('has')->with('translator')->willReturn(false); + $this->app->method('has')->willReturn(false); $this->provider->loadTranslations('/test/path', 'test-namespace'); } @@ -213,10 +213,10 @@ public function testPathsToPublishWithProviderOnly() { $reflection = new \ReflectionClass($this->provider); $publishesProperty = $reflection->getProperty('publishes'); - $publishesProperty->setValue($this->provider, ['test-provider' => ['provider-path']]); + $publishesProperty->setValue($this->provider, ['test-provider' => 'provider-path']); $paths = $this->provider->pathsToPublish('test-provider', null); - $this->assertEquals(['provider-path'], $paths); + $this->assertEquals(['test-provider' => 'provider-path'], $paths); } public function testPathsToPublishWithoutArguments() @@ -244,6 +244,6 @@ public function testCommandsNotInConsole() public function testAbstractMethodsExist() { $this->assertTrue(method_exists($this->provider, 'register')); - $this->assertTrue(method_exists($this->provider, 'boot')); + $this->assertTrue(method_exists($this->provider, 'launch')); } } diff --git a/tests/Requests/RateLimiterTest.php b/tests/Requests/RateLimiterTest.php index adb958f2..b4972933 100644 --- a/tests/Requests/RateLimiterTest.php +++ b/tests/Requests/RateLimiterTest.php @@ -150,7 +150,8 @@ public function testTooManyAttempts() $key = 'test_key'; $maxAttempts = 5; - $this->cache->method('get') + $this->cache->expects($this->once()) + ->method('get') ->with($key) ->willReturn(5); @@ -163,7 +164,8 @@ public function testAvailableIn() $remainingTime = 30; $now = time(); - $this->cache->method('get') + $this->cache->expects($this->once()) + ->method('get') ->with($key . '_timer') ->willReturn($now + $remainingTime); @@ -175,7 +177,8 @@ public function testAvailableInWhenTimerMissing() { $key = 'test_key'; - $this->cache->method('get') + $this->cache->expects($this->once()) + ->method('get') ->with($key . '_timer') ->willReturn(null); @@ -274,7 +277,8 @@ public function testAttempts() $key = 'test_key'; $attempts = 3; - $this->cache->method('get') + $this->cache->expects($this->once()) + ->method('get') ->with($key) ->willReturn($attempts); @@ -286,7 +290,8 @@ public function testAttemptsWhenKeyMissing() { $key = 'test_key'; - $this->cache->method('get') + $this->cache->expects($this->once()) + ->method('get') ->with($key) ->willReturn(null); @@ -311,7 +316,8 @@ public function testCacheExceptionHandling() $key = 'test_key'; $exception = new class extends \Exception implements InvalidArgumentException {}; - $this->cache->method('add') + $this->cache->expects($this->once()) + ->method('add') ->with($key, 1, 60) ->willThrowException($exception); diff --git a/tests/Translation/TranslatorTest.php b/tests/Translation/TranslatorTest.php index 7d7397e6..1f56b0cb 100644 --- a/tests/Translation/TranslatorTest.php +++ b/tests/Translation/TranslatorTest.php @@ -495,7 +495,8 @@ public function testGetWithNoFallbackWhenSameAsLocale(): void public function testGetWithNullLocaleUsesCurrent(): void { - $this->loader->method('load') + $this->loader->expects($this->once()) + ->method('load') ->with('fr', 'messages', null) ->willReturn(['welcome' => 'Bienvenue!']); @@ -523,7 +524,8 @@ public function testMultipleGroupsAreLoadedSeparately(): void public function testGetWithNamespace(): void { - $this->loader->method('load') + $this->loader->expects($this->once()) + ->method('load') ->with('en', 'messages', 'package') ->willReturn(['welcome' => 'Package Welcome!']); From 603c0272fedd7228fdcd14409efaf706ee3dcf1e Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Thu, 27 Aug 2026 21:30:37 +0600 Subject: [PATCH 012/179] remove unnecessary duplicate group method --- src/Phaseolies/Support/Facades/Route.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Phaseolies/Support/Facades/Route.php b/src/Phaseolies/Support/Facades/Route.php index 20a9d30f..9a9ae235 100644 --- a/src/Phaseolies/Support/Facades/Route.php +++ b/src/Phaseolies/Support/Facades/Route.php @@ -31,11 +31,6 @@ class Route extends BaseFacade { - public static function group(array $attributes, \Closure $callback): void - { - static::resolveInstance()->group($attributes, $callback); - } - protected static function getFacadeAccessor() { return 'route'; From 78bad25f5f601fe0020658c9dd5e7ca3da11138b Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Thu, 27 Aug 2026 21:36:41 +0600 Subject: [PATCH 013/179] fix: phpstan error --- src/Phaseolies/Support/Facades/Route.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Phaseolies/Support/Facades/Route.php b/src/Phaseolies/Support/Facades/Route.php index 9a9ae235..482e9bd8 100644 --- a/src/Phaseolies/Support/Facades/Route.php +++ b/src/Phaseolies/Support/Facades/Route.php @@ -2,6 +2,8 @@ namespace Phaseolies\Support\Facades; +use Phaseolies\Facade\BaseFacade; + /** * @method static \Phaseolies\Support\Router get(string $uri, array|string|callable|null $callback) * @method static \Phaseolies\Support\Router post(string $uri, array|string|callable|null $callback) @@ -26,9 +28,6 @@ * * @see \Phaseolies\Support\Router */ - -use Phaseolies\Facade\BaseFacade; - class Route extends BaseFacade { protected static function getFacadeAccessor() From fb11c18216f95451d11b11fb62c8a14ed693e5c2 Mon Sep 17 00:00:00 2001 From: Arif Hoque Date: Thu, 27 Aug 2026 23:27:24 +0600 Subject: [PATCH 014/179] Error Page Redesign for 4.x --- src/Phaseolies/Error/Traces/Frame.php | 27 +- src/Phaseolies/Error/Utils/PathResolver.php | 92 + src/Phaseolies/Error/WebErrorRenderer.php | 3 +- .../Error/views/template-headers.odo.php | 43 +- src/Phaseolies/Error/views/template.odo.php | 1787 ++++++++++------- .../Error/views/trace-frames.odo.php | 37 +- 6 files changed, 1225 insertions(+), 764 deletions(-) create mode 100644 src/Phaseolies/Error/Utils/PathResolver.php diff --git a/src/Phaseolies/Error/Traces/Frame.php b/src/Phaseolies/Error/Traces/Frame.php index 1985d9ce..ea7e9160 100644 --- a/src/Phaseolies/Error/Traces/Frame.php +++ b/src/Phaseolies/Error/Traces/Frame.php @@ -3,6 +3,7 @@ namespace Phaseolies\Error\Traces; use Phaseolies\Error\Utils\Highlighter; +use Phaseolies\Error\Utils\PathResolver; class Frame { @@ -74,15 +75,14 @@ public function getFile(): string } /** - * Get the file path relative to the application's base path. + * Get the file path as a namespace-style path (e.g. "App/Http/Controllers/HomeController.php"), + * falling back to a path relative to the application's base path. * * @return string */ public function getShortFile(): string { - $basePath = base_path(); - - return str_replace($basePath . '/', '', $this->file); + return PathResolver::toDisplayPath($this->file); } /** @@ -142,7 +142,9 @@ public function getArgs(): array */ public function isVendor(): bool { - return strpos($this->file, 'doppar/framework') !== false; + return strpos($this->file, '/vendor/') !== false + || strpos($this->file, 'doppar/framework') !== false + || strpos($this->file, 'package/doppar/src') !== false; } /** @@ -239,7 +241,7 @@ public static function fromTrace(array $trace): static public function getCodeLinesContent(): string { if (!$this->fileExists() || $this->getLine() <= 0) { - return '
No code available
'; + return '
No source available for this frame.
'; } $fileLines = file($this->getFile()); @@ -252,18 +254,11 @@ public function getCodeLinesContent(): string for ($i = $start; $i < $end; $i++) { $number = $i + 1; - $highlight = $number === $this->getLine(); - - $classes = $highlight - ? 'bg-red-500/10 border-l-2 border-l-red-500 text-red-700 dark:text-red-400' - : 'text-neutral-600 dark:text-neutral-400'; + $class = $number === $this->getLine() ? 'code-line-error' : 'code-line'; $output[] = sprintf( - '
- %d - %s -
', - $classes, + '
%d%s
', + $class, $number, Highlighter::make($fileLines[$i]) ); diff --git a/src/Phaseolies/Error/Utils/PathResolver.php b/src/Phaseolies/Error/Utils/PathResolver.php new file mode 100644 index 00000000..1845f853 --- /dev/null +++ b/src/Phaseolies/Error/Utils/PathResolver.php @@ -0,0 +1,92 @@ + directories map from Composer's autoloader. + * + * @var array|null + */ + private static ?array $psr4Map = null; + + /** + * Convert an absolute file path into its namespace-style path + * (e.g. "App/Http/Controllers/HomeController.php") by matching it + * against the application's registered PSR-4 autoload prefixes. + * + * Falls back to a path relative to the application base path when + * no PSR-4 prefix matches the given file. + * + * @param string $absoluteFile + * @return string + */ + public static function toDisplayPath(string $absoluteFile): string + { + $match = self::matchPsr4Prefix($absoluteFile); + + if ($match === null) { + return str_replace(base_path() . '/', '', $absoluteFile); + } + + [$prefix, $directory] = $match; + + $relative = substr($absoluteFile, strlen($directory)); + $namespacePath = str_replace('\\', '/', rtrim($prefix, '\\')); + + return $namespacePath . '/' . ltrim($relative, '/'); + } + + /** + * Find the longest matching PSR-4 directory for the given file. + * + * @param string $absoluteFile + * @return array{0: string, 1: string}|null + */ + private static function matchPsr4Prefix(string $absoluteFile): ?array + { + $map = self::psr4Map(); + + $bestPrefix = null; + $bestDirectory = null; + + foreach ($map as $prefix => $directories) { + foreach ($directories as $directory) { + $directory = rtrim($directory, '/') . '/'; + + if ( + str_starts_with($absoluteFile, $directory) + && ($bestDirectory === null || strlen($directory) > strlen($bestDirectory)) + ) { + $bestPrefix = $prefix; + $bestDirectory = $directory; + } + } + } + + return $bestPrefix === null ? null : [$bestPrefix, $bestDirectory]; + } + + /** + * Load and cache Composer's PSR-4 autoload map. + * + * @return array + */ + private static function psr4Map(): array + { + if (self::$psr4Map !== null) { + return self::$psr4Map; + } + + $file = base_path('vendor/composer/autoload_psr4.php'); + + try { + self::$psr4Map = is_file($file) ? (require $file) : []; + } catch (\Throwable) { + self::$psr4Map = []; + } + + return self::$psr4Map; + } +} diff --git a/src/Phaseolies/Error/WebErrorRenderer.php b/src/Phaseolies/Error/WebErrorRenderer.php index 417e8690..1813dcb1 100644 --- a/src/Phaseolies/Error/WebErrorRenderer.php +++ b/src/Phaseolies/Error/WebErrorRenderer.php @@ -6,6 +6,7 @@ use Phaseolies\Error\Traces\Frame; use Phaseolies\Error\Utils\ExceptionMarkdownReport; use Phaseolies\Error\Utils\Highlighter; +use Phaseolies\Error\Utils\PathResolver; use Phaseolies\Http\Controllers\Controller; use Phaseolies\Http\Exceptions\HttpException; use Phaseolies\Http\Response; @@ -61,7 +62,7 @@ public function renderDebug(Throwable $exception): Response 'traces' => Frame::extractFramesCollectionFromEngine($exception->getTrace()), 'headers' => ($this->getHeaders()), 'error_message' => ucfirst($exception->getMessage()), - 'error_file' => $errorFile, + 'error_file' => PathResolver::toDisplayPath($errorFile), 'error_line' => $errorLine, 'routing' => $this->getRouteDetails(), 'contents' => $this->buildContents($codeLines), diff --git a/src/Phaseolies/Error/views/template-headers.odo.php b/src/Phaseolies/Error/views/template-headers.odo.php index 4691da12..d32d017d 100644 --- a/src/Phaseolies/Error/views/template-headers.odo.php +++ b/src/Phaseolies/Error/views/template-headers.odo.php @@ -1,25 +1,18 @@ - -
-
- #foreach ($headers as $header_name => $header_value) -
- [[ $header_name ]] -
- [[ $header_value ]] -
- #endforeach -
-
\ No newline at end of file + +
+
+ #foreach ($headers as $header_name => $header_value) +
+ [[ $header_name ]] + + [[ $header_value ]] +
+ #endforeach +
+
diff --git a/src/Phaseolies/Error/views/template.odo.php b/src/Phaseolies/Error/views/template.odo.php index 921a47fe..81b92931 100644 --- a/src/Phaseolies/Error/views/template.odo.php +++ b/src/Phaseolies/Error/views/template.odo.php @@ -4,98 +4,133 @@ - Error — [[ $error_message ]] - - - - + [[ $status_code ]] · [[ $error_message ]] - + - - - + .frame-toggle { + display: flex; + align-items: center; + gap: 12px; + width: 100%; + text-align: left; + background: none; + border: none; + padding: 13px 4px 13px 0; + min-height: 56px; + } - -
-
-
+ .frame-toggle:hover { + background: color-mix(in srgb, var(--ink) 3%, transparent); + } -
+ .frame-main { + flex: 1; + min-width: 0; + } -
-
- - [[ $exception_class ]] -
+ .frame-sig { + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 12.5px; + font-weight: 600; + color: var(--ink); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } -
- - - -
-
- Doppar - [[ $doppar_version ]] -
-
- PHP - [[ $php_version ]] -
-
-
-
+ .frame-file { + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 11px; + color: var(--muted); + margin-top: 2px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } -

- [[ $error_message ]] -

-
-
+ .vendor-tag { + font-size: 9.5px; + font-weight: 700; + letter-spacing: .06em; + text-transform: uppercase; + color: var(--muted); + border: 1px solid var(--line); + border-radius: 4px; + padding: 1px 5px; + flex: none; + } - -
-
-
- [[ $request_method ]] - [[ $request_url ]] - -
-
-
+ .chev { + width: 14px; + height: 14px; + color: var(--muted); + flex: none; + transition: transform .18s ease; + } - -
-
-
- -
- [[ $timestamp ]] -
-
- -
- - - [[ $status_code ]] - -
-
- -
- - [[ $request_method ]] - -
-
-
+ .frame-toggle[aria-expanded="true"] .chev, + .kv-toggle[aria-expanded="true"] .chev { + transform: rotate(180deg); + } - -
+ .frame-body { + display: none; + border-top: 1px solid var(--line); + background: var(--surface-2); + } - -
-
-
-
-
-
-
- [[ $error_file ]] - Line [[ $error_line ]] -
-
-
[[! $contents !]]
-
-
+ .frame-body .code { + background: transparent; + } - -
-
-
- - - -

Stack Trace

- -
- -
+ /* ============ DUAL COLUMN ============ */ + .dual-col { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 18px; + margin-bottom: 18px; + } -
- #include('trace-frames', ['traces' => $traces]) -
-
+ .dual-col .panel { + margin-bottom: 0; + } - -
- #include('template-headers', ['headers' => $headers]) -
+ @media (max-width: 760px) { + .dual-col { + grid-template-columns: 1fr; + } + } - -
-
-
- - - -
- Request Body - #if (!empty($request_body)) - - - - #endif -
- #if (!empty($request_body)) - - #else -
- - - -

Empty Request Body

-
- #endif -
+ .kv-toggle { + width: 100%; + background: none; + border: none; + text-align: left; + cursor: pointer; + padding: 0; + } - -
+ .kv-panel { + display: none; + } -
-
-
- - - -
-
-

Routing

-
-
-
+ .kv-list { + padding: 6px 16px 14px; + } -
+ .kv-row { + display: flex; + align-items: baseline; + gap: 8px; + padding: 6px 0; + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 12px; + } - -
- -
- - Name - - - - [[ $current_route_name ?? 'unnamed_route' ]] - -
-
+ .kv-key { + color: var(--muted); + text-transform: uppercase; + letter-spacing: .03em; + font-size: 10.5px; + flex: none; + } - -
- + .kv-dots { + flex: 1; + border-bottom: 1px dashed var(--line); + margin-bottom: 4px; + min-width: 12px; + } -
- - Action - - + .kv-val { + color: var(--ink-soft); + text-align: right; + max-width: 60%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } - #if(!empty($current_route_action)) - - [[ $current_route_action ]] - - #else - - Closure / No Action - - #endif -
-
+ .empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 34px 16px; + color: var(--muted); + gap: 8px; + } - -
- + .empty-state svg { + width: 28px; + height: 28px; + opacity: .55; + } - #if (!empty($current_middleware)) - #foreach(($current_middleware ?? []) as $index => $mw) -
- - [[ $index + 1 ]] - - - - [[ $mw ]] - -
- #endforeach - #else -
-
- No middleware -
- #endif -
+ .empty-state span { + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 10.5px; + letter-spacing: .1em; + text-transform: uppercase; + } - -
- + .json-body { + margin: 0; + padding: 14px 16px; + overflow-x: auto; + font-size: 12px; + line-height: 1.6; + color: var(--ink-soft); + background: var(--surface-2); + } - #if (!empty($current_route_params)) - #foreach ($current_route_params as $key => $val) -
- - [[ $key ]] - - - - [[ $val ]] - -
- #endforeach - #else -
-
- No parameters -
- #endif -
+ /* ============ ROUTING ============ */ + .routing-grid { + padding: 18px 16px 4px; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 18px 28px; + } + + .field-label { + font-size: 10.5px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: .09em; + color: var(--muted); + margin-bottom: 10px; + } + + .route-row { + display: flex; + align-items: baseline; + gap: 8px; + padding: 5px 0; + } + + .route-key { + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 10.5px; + font-weight: 700; + color: var(--muted); + text-transform: uppercase; + flex: none; + } + + .route-dots { + flex: 1; + border-bottom: 1px dashed var(--line); + margin-bottom: 4px; + } + + .route-val { + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 13px; + font-weight: 600; + color: var(--ink-soft); + word-break: break-all; + } + + .route-none { + font-size: 12px; + font-style: italic; + color: var(--muted); + padding-bottom: 14px; + } + + /* ============ INFO GRID ============ */ + .info-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 18px; + margin-bottom: 18px; + } + + @media (max-width: 760px) { + .info-grid { + grid-template-columns: 1fr; + } + } + + .info-card { + padding: 16px; + } + + .info-card .field-label { + margin-bottom: 12px; + } + .info-row { + margin-bottom: 12px; + } + + .info-row:last-child { + margin-bottom: 0; + } + + .info-row .k { + font-size: 10.5px; + color: var(--muted); + text-transform: uppercase; + letter-spacing: .04em; + margin-bottom: 2px; + } + + .info-row .v { + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 13px; + color: var(--ink-soft); + font-variant-numeric: tabular-nums; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .foot { + text-align: center; + padding: 18px 0 36px; + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 10px; + letter-spacing: .18em; + text-transform: uppercase; + color: var(--muted); + } + + + + +
+ +
+ [[ $exception_class ]] +
+
+ DOPPAR [[ $doppar_version ]] + PHP [[ $php_version ]] +
+ + +
+
+ +
+ +

Uncaught — [[ $exception_class ]]

+

[[ $error_message ]]

+
+ [[ $status_code ]] + [[ $request_method ]] + [[ count($traces) ]] frames + [[ $timestamp ]]
+
+ +
+ [[ $request_method ]] + [[ $request_url ]] +
- -
- -
-
-
- - - -
- System +
+ +
+
+ + [[ $error_file ]] + Line [[ $error_line ]]
-
-
- -
[[ $server_software ]]
-
-
- -
[[ $platform ]]
+
[[! $contents !]]
+
+ + +
+
+

Stack Trace

+ [[ count($traces) ]] frames +
+ + +
-
- - -
-
-
- - - -
- Memory +
+ #include('trace-frames', ['traces' => $traces])
-
-
- -
[[ number_format($memory_usage / 1024 / 1024, 2) ]] MB
+ + + +
+
+ #include('template-headers', ['headers' => $headers]) +
+ +
+
+

Request Body

+ + #if (!empty($request_body)) + payload + #else + empty + #endif +
-
- -
[[ number_format($peack_memory_usage / 1024 / 1024, 2) ]] MB
+ #if (!empty($request_body)) +
[[ json_encode($request_body, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) ]]
+ #else +
+
+ + No payload on this request +
-
+ #endif +
- -
-
-
- - - -
- User + +
+
+

Routing

- #if ($user_info) -
+
- -
[[ $user_info['id'] ]]
+
Route
+
Name[[ $current_route_name ?? 'unnamed_route' ]]
+
+ Action + #if (!empty($current_route_action)) + [[ $current_route_action ]] + #else + Closure + #endif +
- -
[[ $user_info['email'] ]]
+
Middleware ([[ count($current_middleware ?? []) ]])
+ #if (!empty($current_middleware)) + #foreach(($current_middleware ?? []) as $index => $mw) +
[[ $index + 1 ]][[ $mw ]]
+ #endforeach + #else +
No middleware
+ #endif +
+
+
Route Parameters
+ #if (!empty($current_route_params)) + #foreach ($current_route_params as $key => $val) +
[[ $key ]][[ $val ]]
+ #endforeach + #else +
No parameters
+ #endif
- #else -
- - - -

No User

-
- #endif +
+ + +
+
+
System
+
Server
[[ $server_software ]]
+
Platform
[[ $platform ]]
+
+
+
Memory
+
Current Usage
[[ number_format($memory_usage / 1024 / 1024, 2) ]] MB
+
Peak Usage
[[ number_format($peack_memory_usage / 1024 / 1024, 2) ]] MB
+
+
+
User
+ #if ($user_info) +
ID
[[ $user_info['id'] ]]
+
Email
[[ $user_info['email'] ]]
+ #else +
+ + No user +
+ #endif +
-
- - -
- Doppar Framework -
-
+
Doppar Framework · Request Diagnostic
+ +
- + - \ No newline at end of file + diff --git a/src/Phaseolies/Error/views/trace-frames.odo.php b/src/Phaseolies/Error/views/trace-frames.odo.php index bde91fe0..906386db 100644 --- a/src/Phaseolies/Error/views/trace-frames.odo.php +++ b/src/Phaseolies/Error/views/trace-frames.odo.php @@ -1,27 +1,24 @@ #if (empty($traces)) -
-

No stack trace available

+
+ No stack trace available
#else #foreach ($traces as $index => $trace) -
-