diff --git a/CHANGELOG.md b/CHANGELOG.md
index 12b663c90..c7b47dece 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,25 @@
## [3.0.0] - TBD
### Changed
+- **BREAKING:** Refactored app bootstrapping and DI ownership model (#373):
+ - Introduced `AppContext` as the central execution state holder (mode, baseDir, DiContainer, Environment, Config, Request, Response, Routes)
+ - Split `Di` into a static facade delegating to an instance-based `DiContainer`, one container per application execution
+ - Added `Di::set()`, `Di::has()`, and `Di::isRegistered()` for explicit service management
+ - `Di::get()` now enforces a strict contract: throws if the dependency is not explicitly registered (no more implicit auto-registration)
+ - Introduced `BootPipeline` and `BootStageInterface` for explicit, ordered boot sequences
+ - Extracted boot stages: `LoadHelpersStage`, `LoadEnvironmentStage`, `LoadAppConfigStage`, `SetupErrorHandlerStage`, `InitHttpStage`, `InitDebuggerStage`
+ - Removed `AppTrait`; all adapter boot logic moved to pipeline stages and focused private methods in `WebAppTrait`/`ConsoleAppTrait`
+- **BREAKING:** Converted `Request` and `Response` from static facades to instance-based classes (#454):
+ - Merged `HttpRequest`/`HttpResponse` wrapper layer directly into `Request`/`Response`
+ - All request/response access now goes through `request()` and `response()` helper functions
+- **BREAKING:** Removed all static singleton patterns from core services (#381, #382):
+ - Migrated all 12 first-party factories (Auth, Archive, Cache, Captcha, Cryptor, FileSystem, Lang, Logger, Mailer, Renderer, Session, View) from static instance caches to DI-managed lifetimes
+ - Migrated service singletons to DI ownership: Cookie, Config, Environment, Server, AssetManager, Csrf, Database, MailTrap, Debugger, ViewCache, ErrorHandler, HookManager, ModuleLoader
+- **BREAKING:** `Environment` class is no longer a static singleton (#456):
+ - Uses `Dotenv::createArrayBacked()` for isolated, deterministic env loading
+ - New `environment()` helper function and shorthand check methods: `isProduction()`, `isTesting()`, `isStaging()`, `isDevelopment()`, `isLocal()`
+ - `env()` helper now delegates through `environment()->getValue()`
+
- **BREAKING:** Minimum PHP version requirement raised from 7.3 to 7.4
- Modernized codebase with PHP 7.4+ syntax using Rector:
- Array destructuring: `list()` → `[]`
@@ -48,6 +67,11 @@
- Fixed cURL error message assertions for cross-version compatibility
### Added
+- `AppContext` class representing the runtime identity of a single application execution
+- `DiContainer` instance-based dependency injection container, isolated per execution
+- `BootPipeline` and `BootStageInterface` for declarative, ordered boot sequences
+- `environment()` global helper and `Environment` shorthand methods (`isProduction()`, `isTesting()`, etc.)
+- Lazy registration guards (`Di::register()` + `Di::isRegistered()`) at all DI call sites for explicit dependency management
- Rector as dev dependency for automated code refactoring
- Additional PHP extensions required in CI: `bcmath`, `gd`, `zip`
- PHPUnit strict testing flags: `--fail-on-warning`, `--fail-on-risky`
@@ -75,3 +99,9 @@
### Removed
- Support for PHP 7.3 and earlier versions
- Legacy routing static state and implicit controller resolution via `RouteController`
+- `AppTrait` — replaced by boot pipeline stages and adapter-specific traits
+- Static singleton patterns from all core services and factories
+- `Environment::getInstance()` static singleton accessor
+- `HttpRequest`/`HttpResponse` static facade wrapper classes (merged into `Request`/`Response`)
+- Implicit auto-registration in `Di::get()` — all dependencies must be explicitly registered
+- `RegisterCoreDependenciesStage` and `dependencies.php` — replaced by lazy registration at call sites
diff --git a/coverage.xml b/coverage.xml
deleted file mode 100644
index 835c45703..000000000
--- a/coverage.xml
+++ /dev/null
@@ -1,4904 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/App/Adapters/AppAdapter.php b/src/App/Adapters/AppAdapter.php
index db9cd43fa..41844b5fa 100644
--- a/src/App/Adapters/AppAdapter.php
+++ b/src/App/Adapters/AppAdapter.php
@@ -16,11 +16,8 @@
namespace Quantum\App\Adapters;
-use Quantum\App\Exceptions\BaseException;
use Quantum\App\Contracts\AppInterface;
-use Quantum\Di\Exceptions\DiException;
-use Quantum\App\Traits\AppTrait;
-use ReflectionException;
+use Quantum\App\AppContext;
/**
* Class AppAdapter
@@ -28,20 +25,10 @@
*/
abstract class AppAdapter implements AppInterface
{
- use AppTrait;
+ protected AppContext $context;
- private static string $baseDir;
-
- /**
- * @throws BaseException
- * @throws DiException
- * @throws ReflectionException
- */
- public function __construct()
+ public function __construct(AppContext $context)
{
- $this->loadCoreDependencies();
- $this->loadComponentHelperFunctions();
- $this->loadAppHelperFunctions();
- $this->loadModuleHelperFunctions();
+ $this->context = $context;
}
}
diff --git a/src/App/Adapters/ConsoleAppAdapter.php b/src/App/Adapters/ConsoleAppAdapter.php
index 4d2875f59..1854becd5 100644
--- a/src/App/Adapters/ConsoleAppAdapter.php
+++ b/src/App/Adapters/ConsoleAppAdapter.php
@@ -18,15 +18,16 @@
use Symfony\Component\Console\Output\ConsoleOutput;
use Quantum\App\Exceptions\StopExecutionException;
-use Quantum\Environment\Exceptions\EnvException;
use Symfony\Component\Console\Input\ArgvInput;
-use Quantum\Config\Exceptions\ConfigException;
+use Quantum\App\Stages\SetupErrorHandlerStage;
+use Quantum\App\Stages\LoadEnvironmentStage;
use Symfony\Component\Console\Application;
-use Quantum\Lang\Exceptions\LangException;
-use Quantum\App\Exceptions\BaseException;
+use Quantum\App\Stages\LoadAppConfigStage;
+use Quantum\App\Stages\LoadHelpersStage;
use Quantum\App\Traits\ConsoleAppTrait;
-use Quantum\Di\Exceptions\DiException;
-use ReflectionException;
+use Quantum\App\BootPipeline;
+use Quantum\App\AppContext;
+use Exception;
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
@@ -46,18 +47,30 @@ class ConsoleAppAdapter extends AppAdapter
protected Application $application;
- public function __construct()
+ public function __construct(AppContext $context)
{
- parent::__construct();
+ parent::__construct($context);
$this->input = new ArgvInput();
$this->output = new ConsoleOutput();
$commandName = $this->input->getFirstArgument();
+ $stages = [
+ new LoadHelpersStage(),
+ ];
+
if ($commandName !== 'core:env') {
- $this->loadEnvironment();
- $this->loadAppConfig();
+ $stages[] = new LoadEnvironmentStage();
+ $stages[] = new LoadAppConfigStage();
+ $stages[] = new SetupErrorHandlerStage();
+ }
+
+ $pipeline = new BootPipeline($stages);
+ $pipeline->run($this->context);
+
+ if ($commandName !== 'core:env') {
+ environment()->setMutable(true);
}
$this->application = $this->createApplication(
@@ -67,23 +80,14 @@ public function __construct()
}
/**
- * @throws DiException
- * @throws EnvException
- * @throws BaseException
- * @throws ConfigException
- * @throws LangException
- * @throws ReflectionException
- */
+ * @throws Exception
+ */
public function start(): ?int
{
try {
- $this->loadLanguage();
-
$this->registerCoreCommands();
$this->registerAppCommands();
- $this->setupErrorHandler();
-
$this->validateCommand();
$exitCode = $this->application->run($this->input, $this->output);
diff --git a/src/App/Adapters/WebAppAdapter.php b/src/App/Adapters/WebAppAdapter.php
index 9dc0cf616..a8c54af23 100644
--- a/src/App/Adapters/WebAppAdapter.php
+++ b/src/App/Adapters/WebAppAdapter.php
@@ -17,32 +17,27 @@
namespace Quantum\App\Adapters;
use Quantum\Middleware\Exceptions\MiddlewareException;
-use Quantum\Database\Exceptions\DatabaseException;
use Quantum\App\Exceptions\StopExecutionException;
-use Quantum\Session\Exceptions\SessionException;
-use Quantum\Environment\Exceptions\EnvException;
+use Quantum\Loader\Exceptions\LoaderException;
use Quantum\Module\Exceptions\ModuleException;
use Quantum\Config\Exceptions\ConfigException;
+use Quantum\App\Stages\SetupErrorHandlerStage;
use Quantum\Router\Exceptions\RouteException;
-use Quantum\Http\Exceptions\HttpException;
+use Quantum\App\Stages\LoadEnvironmentStage;
use Quantum\Csrf\Exceptions\CsrfException;
use Quantum\Lang\Exceptions\LangException;
-use Quantum\Middleware\MiddlewareManager;
+use Quantum\App\Stages\LoadAppConfigStage;
use Quantum\App\Exceptions\BaseException;
+use Quantum\App\Stages\InitDebuggerStage;
+use Quantum\Middleware\MiddlewareManager;
+use Quantum\App\Stages\LoadHelpersStage;
+use Quantum\App\Stages\InitHttpStage;
use Quantum\Di\Exceptions\DiException;
use Quantum\App\Traits\WebAppTrait;
-use Quantum\Router\RouteCollection;
use Quantum\Router\RouteDispatcher;
-use Quantum\Router\RouteBuilder;
-use Quantum\Module\ModuleLoader;
-use DebugBar\DebugBarException;
-use Quantum\Router\RouteFinder;
-use Quantum\Debugger\Debugger;
-use Quantum\Hook\HookManager;
-use Quantum\Http\Response;
-use Quantum\Http\Request;
+use Quantum\App\BootPipeline;
+use Quantum\App\AppContext;
use ReflectionException;
-use Quantum\Di\Di;
/**
* Class WebAppAdapter
@@ -52,110 +47,51 @@ class WebAppAdapter extends AppAdapter
{
use WebAppTrait;
- /**
- * @var Request
- */
- private $request;
-
- /**
- * @var Response
- */
- private $response;
-
- /**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws EnvException
- * @throws ReflectionException
- */
- public function __construct()
+ public function __construct(AppContext $context)
{
- parent::__construct();
-
- $this->loadEnvironment();
- $this->loadAppConfig();
-
- $this->request = Di::get(Request::class);
- $this->response = Di::get(Response::class);
+ parent::__construct($context);
+
+ $pipeline = new BootPipeline([
+ new LoadHelpersStage(),
+ new LoadEnvironmentStage(),
+ new LoadAppConfigStage(),
+ new SetupErrorHandlerStage(),
+ new InitHttpStage(),
+ new InitDebuggerStage(),
+ ]);
+
+ $pipeline->run($this->context);
}
/**
* Starts the web app
- * @throws BaseException
- * @throws ConfigException
- * @throws CsrfException
- * @throws DatabaseException
- * @throws DebugBarException
- * @throws DiException
- * @throws HttpException
- * @throws LangException
- * @throws ModuleException
- * @throws ReflectionException
- * @throws RouteException
- * @throws SessionException
- * @throws MiddlewareException
+ * @throws ModuleException|MiddlewareException|LangException|RouteException|CsrfException|ConfigException|DiException|BaseException|LoaderException|ReflectionException
*/
public function start(): ?int
{
try {
- $this->initializeRequestResponse($this->request, $this->response);
-
- if ($this->request->isMethod('OPTIONS')) {
+ if (request()->isMethod('OPTIONS')) {
stop();
}
- $this->setupErrorHandler();
- $this->initializeDebugger();
+ $this->loadModules();
- $moduleLoader = ModuleLoader::getInstance();
-
- $builder = new RouteBuilder();
-
- $collection = $builder->build(
- $moduleLoader->loadModulesRoutes(),
- $moduleLoader->getModuleConfigs()
- );
-
- Di::set(RouteCollection::class, $collection);
-
- $routeFinder = new RouteFinder($collection);
-
- $matchedRoute = $routeFinder->find($this->request);
-
- if ($matchedRoute === null) {
- page_not_found();
- stop();
- }
-
- $this->request->setMatchedRoute($matchedRoute);
+ $matchedRoute = $this->resolveRoute();
$this->loadLanguage();
- $debugger = Debugger::getInstance();
- if ($debugger->isEnabled()) {
- $debugger->addToStoreCell(Debugger::HOOKS, 'info', HookManager::getInstance()->getRegistered());
- }
-
- $middlewareManager = new MiddlewareManager($matchedRoute);
-
- [$this->request, $this->response] = $middlewareManager->applyMiddlewares(
- $this->request,
- $this->response
- );
+ $this->logDebugInfo();
- $viewCache = $this->setupViewCache();
+ [$request, $response] = (new MiddlewareManager($matchedRoute))->applyMiddlewares(request(), response());
- if ($viewCache->serveCachedView(route_uri() ?? '', $this->response)) {
+ if ($this->setupViewCache()->serveCachedView(route_uri() ?? '', $response)) {
stop();
}
- $dispatcher = new RouteDispatcher();
- $dispatcher->dispatch($matchedRoute, $this->request);
+ (new RouteDispatcher())->dispatch($matchedRoute, $request);
stop();
} catch (StopExecutionException $exception) {
- $this->handleCors($this->response);
- $this->response->send();
+ $this->sendResponse();
return $exception->getCode();
}
diff --git a/src/App/App.php b/src/App/App.php
index 15adf8292..cf1bf7768 100644
--- a/src/App/App.php
+++ b/src/App/App.php
@@ -29,7 +29,7 @@
*/
class App
{
- private static ?string $baseDir = null;
+ private static ?AppContext $context = null;
private AppInterface $adapter;
@@ -38,18 +38,23 @@ public function __construct(AppInterface $adapter)
$this->adapter = $adapter;
}
- public static function setBaseDir(string $baseDir): void
+ public static function setContext(AppContext $context): void
{
- self::$baseDir = $baseDir;
+ self::$context = $context;
}
- public static function getBaseDir(): string
+ public static function getContext(): AppContext
{
- if (self::$baseDir === null || self::$baseDir === '') {
- throw new RuntimeException('Base directory is not initialized.');
+ if (self::$context === null) {
+ throw new RuntimeException('AppContext is not initialized.');
}
- return self::$baseDir;
+ return self::$context;
+ }
+
+ public static function getBaseDir(): string
+ {
+ return self::getContext()->getBaseDir();
}
public function getAdapter(): AppInterface
diff --git a/src/App/AppContext.php b/src/App/AppContext.php
new file mode 100644
index 000000000..a9d9d06d4
--- /dev/null
+++ b/src/App/AppContext.php
@@ -0,0 +1,86 @@
+
+ * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
+ * @link http://quantum.softberg.org/
+ * @since 3.0.0
+ */
+
+namespace Quantum\App;
+
+use Quantum\Environment\Environment;
+use Quantum\Router\RouteCollection;
+use Quantum\Di\DiContainer;
+use Quantum\Config\Config;
+use Quantum\Http\Response;
+use Quantum\Http\Request;
+
+/**
+ * Class AppContext
+ * @package Quantum\App
+ */
+class AppContext
+{
+ private string $baseDir;
+
+ private DiContainer $container;
+
+ public function __construct(string $baseDir, DiContainer $container)
+ {
+ $this->baseDir = $baseDir;
+ $this->container = $container;
+ }
+
+ public function getBaseDir(): string
+ {
+ return $this->baseDir;
+ }
+
+ public function getContainer(): DiContainer
+ {
+ return $this->container;
+ }
+
+ public function getEnvironment(): Environment
+ {
+ return $this->resolveFromContainer(Environment::class);
+ }
+
+ public function getConfig(): Config
+ {
+ return $this->resolveFromContainer(Config::class);
+ }
+
+ public function getRequest(): Request
+ {
+ return $this->resolveFromContainer(Request::class);
+ }
+
+ public function getResponse(): Response
+ {
+ return $this->resolveFromContainer(Response::class);
+ }
+
+ public function getRoutes(): RouteCollection
+ {
+ return $this->resolveFromContainer(RouteCollection::class);
+ }
+
+ /**
+ * @template T of object
+ * @param class-string $class
+ * @return T
+ */
+ private function resolveFromContainer(string $class)
+ {
+ return $this->container->get($class);
+ }
+}
diff --git a/src/App/BootPipeline.php b/src/App/BootPipeline.php
new file mode 100644
index 000000000..6194838cf
--- /dev/null
+++ b/src/App/BootPipeline.php
@@ -0,0 +1,55 @@
+
+ * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
+ * @link http://quantum.softberg.org/
+ * @since 3.0.0
+ */
+
+namespace Quantum\App;
+
+use Quantum\App\Contracts\BootStageInterface;
+use InvalidArgumentException;
+
+/**
+ * Class BootPipeline
+ * @package Quantum\App
+ */
+class BootPipeline
+{
+ /**
+ * @var BootStageInterface[]
+ */
+ private array $stages;
+
+ /**
+ * @param BootStageInterface[] $stages
+ */
+ public function __construct(array $stages = [])
+ {
+ foreach ($stages as $stage) {
+ if (!$stage instanceof BootStageInterface) {
+ throw new InvalidArgumentException(
+ 'All stages must implement ' . BootStageInterface::class
+ );
+ }
+ }
+
+ $this->stages = $stages;
+ }
+
+ public function run(AppContext $context): void
+ {
+ foreach ($this->stages as $stage) {
+ $stage->process($context);
+ }
+ }
+}
diff --git a/src/App/Config/dependencies.php b/src/App/Config/dependencies.php
deleted file mode 100644
index 9b8a91fa6..000000000
--- a/src/App/Config/dependencies.php
+++ /dev/null
@@ -1,7 +0,0 @@
- \Quantum\Loader\Loader::class,
- \Quantum\Http\Request::class => \Quantum\Http\Request::class,
- \Quantum\Http\Response::class => \Quantum\Http\Response::class,
-];
diff --git a/src/App/Contracts/BootStageInterface.php b/src/App/Contracts/BootStageInterface.php
new file mode 100644
index 000000000..c907490a8
--- /dev/null
+++ b/src/App/Contracts/BootStageInterface.php
@@ -0,0 +1,31 @@
+
+ * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
+ * @link http://quantum.softberg.org/
+ * @since 3.0.0
+ */
+
+namespace Quantum\App\Contracts;
+
+use Quantum\App\AppContext;
+
+/**
+ * Interface BootStageInterface
+ * @package Quantum\App
+ */
+interface BootStageInterface
+{
+ /**
+ * Processes a single boot stage
+ */
+ public function process(AppContext $context): void;
+}
diff --git a/src/App/Exceptions/BaseException.php b/src/App/Exceptions/BaseException.php
index ff55e5ea5..42a14d1db 100644
--- a/src/App/Exceptions/BaseException.php
+++ b/src/App/Exceptions/BaseException.php
@@ -30,10 +30,7 @@ final public function __construct(string $message = '', int $code = 0)
parent::__construct($message, $code);
}
- /**
- * @return static
- */
- public static function methodNotSupported(string $methodName, string $className)
+ public static function methodNotSupported(string $methodName, string $className): BaseException
{
return new static(
_message(ExceptionMessages::METHOD_NOT_SUPPORTED, [$methodName, $className]),
@@ -41,10 +38,7 @@ public static function methodNotSupported(string $methodName, string $className)
);
}
- /**
- * @return static
- */
- public static function adapterNotSupported(string $name)
+ public static function adapterNotSupported(string $name): BaseException
{
return new static(
_message(ExceptionMessages::ADAPTER_NOT_SUPPORTED, [$name]),
@@ -52,10 +46,7 @@ public static function adapterNotSupported(string $name)
);
}
- /**
- * @return static
- */
- public static function driverNotSupported(string $name)
+ public static function driverNotSupported(string $name): BaseException
{
return new static(
_message(ExceptionMessages::DRIVER_NOT_SUPPORTED, [$name]),
@@ -63,10 +54,7 @@ public static function driverNotSupported(string $name)
);
}
- /**
- * @return static
- */
- public static function fileNotFound(string $name)
+ public static function fileNotFound(string $name): BaseException
{
return new static(
_message(ExceptionMessages::FILE_NOT_FOUND, [$name]),
@@ -74,10 +62,7 @@ public static function fileNotFound(string $name)
);
}
- /**
- * @return static
- */
- public static function notFound(string $subject, string $name)
+ public static function notFound(string $subject, string $name): BaseException
{
return new static(
_message(ExceptionMessages::NOT_FOUND, [$subject, $name]),
@@ -85,10 +70,7 @@ public static function notFound(string $subject, string $name)
);
}
- /**
- * @return static
- */
- public static function notInstanceOf(string $instance, string $name)
+ public static function notInstanceOf(string $instance, string $name): BaseException
{
return new static(
_message(ExceptionMessages::NOT_INSTANCE_OF, [$instance, $name]),
@@ -96,10 +78,7 @@ public static function notInstanceOf(string $instance, string $name)
);
}
- /**
- * @return static
- */
- public static function cantConnect(string $name)
+ public static function cantConnect(string $name): BaseException
{
return new static(
_message(ExceptionMessages::CANT_CONNECT, [$name]),
@@ -107,10 +86,7 @@ public static function cantConnect(string $name)
);
}
- /**
- * @return static
- */
- public static function missingConfig(string $name)
+ public static function missingConfig(string $name): BaseException
{
return new static(
_message(ExceptionMessages::MISSING_CONFIG, $name),
@@ -118,10 +94,7 @@ public static function missingConfig(string $name)
);
}
- /**
- * @return static
- */
- public static function requestMethodNotAvailable(string $name)
+ public static function requestMethodNotAvailable(string $name): BaseException
{
return new static(
_message(ExceptionMessages::UNAVAILABLE_REQUEST_METHOD, [$name]),
diff --git a/src/App/Factories/AppFactory.php b/src/App/Factories/AppFactory.php
index 79fa4c6dc..e00a1bd35 100644
--- a/src/App/Factories/AppFactory.php
+++ b/src/App/Factories/AppFactory.php
@@ -21,6 +21,8 @@
use Quantum\App\Exceptions\AppException;
use Quantum\App\Adapters\WebAppAdapter;
use Quantum\App\Enums\AppType;
+use Quantum\App\AppContext;
+use Quantum\Di\DiContainer;
use Quantum\App\App;
/**
@@ -69,10 +71,13 @@ private static function createInstance(string $type, string $baseDir): App
throw AppException::adapterNotSupported($type);
}
- $adapterClass = self::ADAPTERS[$type];
+ $container = new DiContainer();
+
+ $context = new AppContext($baseDir, $container);
+ App::setContext($context);
- App::setBaseDir($baseDir);
+ $adapterClass = self::ADAPTERS[$type];
- return new App(new $adapterClass());
+ return new App(new $adapterClass($context));
}
}
diff --git a/src/App/Stages/InitDebuggerStage.php b/src/App/Stages/InitDebuggerStage.php
new file mode 100644
index 000000000..b6ef6aecb
--- /dev/null
+++ b/src/App/Stages/InitDebuggerStage.php
@@ -0,0 +1,43 @@
+
+ * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
+ * @link http://quantum.softberg.org/
+ * @since 3.0.0
+ */
+
+namespace Quantum\App\Stages;
+
+use Quantum\App\Contracts\BootStageInterface;
+use Quantum\Di\Exceptions\DiException;
+use Quantum\Debugger\Debugger;
+use Quantum\App\AppContext;
+use ReflectionException;
+use Quantum\Di\Di;
+
+/**
+ * Class InitDebuggerStage
+ * @package Quantum\App
+ */
+class InitDebuggerStage implements BootStageInterface
+{
+ /**
+ * @throws DiException|ReflectionException
+ */
+ public function process(AppContext $context): void
+ {
+ if (!Di::isRegistered(Debugger::class)) {
+ Di::register(Debugger::class);
+ }
+
+ Di::get(Debugger::class)->initStore();
+ }
+}
diff --git a/src/App/Stages/InitHttpStage.php b/src/App/Stages/InitHttpStage.php
new file mode 100644
index 000000000..45956bf19
--- /dev/null
+++ b/src/App/Stages/InitHttpStage.php
@@ -0,0 +1,46 @@
+
+ * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
+ * @link http://quantum.softberg.org/
+ * @since 3.0.0
+ */
+
+namespace Quantum\App\Stages;
+
+use Quantum\App\Contracts\BootStageInterface;
+use Quantum\Di\Exceptions\DiException;
+use Quantum\App\AppContext;
+use Quantum\Http\Response;
+use Quantum\Http\Request;
+use ReflectionException;
+use Quantum\Di\Di;
+
+/**
+ * Class InitHttpStage
+ * @package Quantum\App
+ */
+class InitHttpStage implements BootStageInterface
+{
+ /**
+ * @throws DiException|ReflectionException
+ */
+ public function process(AppContext $context): void
+ {
+ if (!Di::isRegistered(Request::class)) {
+ Di::register(Request::class);
+ }
+
+ if (!Di::isRegistered(Response::class)) {
+ Di::register(Response::class);
+ }
+ }
+}
diff --git a/src/App/Stages/LoadAppConfigStage.php b/src/App/Stages/LoadAppConfigStage.php
new file mode 100644
index 000000000..49e90b917
--- /dev/null
+++ b/src/App/Stages/LoadAppConfigStage.php
@@ -0,0 +1,42 @@
+
+ * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
+ * @link http://quantum.softberg.org/
+ * @since 3.0.0
+ */
+
+namespace Quantum\App\Stages;
+
+use Quantum\App\Contracts\BootStageInterface;
+use Quantum\Config\Exceptions\ConfigException;
+use Quantum\Loader\Exceptions\LoaderException;
+use Quantum\Di\Exceptions\DiException;
+use Quantum\App\AppContext;
+use Quantum\Loader\Setup;
+use ReflectionException;
+
+/**
+ * Class LoadAppConfigStage
+ * @package Quantum\App
+ */
+class LoadAppConfigStage implements BootStageInterface
+{
+ /**
+ * @throws LoaderException|ConfigException|DiException|ReflectionException
+ */
+ public function process(AppContext $context): void
+ {
+ if (!config()->has('app')) {
+ config()->import(new Setup('config', 'app'));
+ }
+ }
+}
diff --git a/src/App/Stages/LoadEnvironmentStage.php b/src/App/Stages/LoadEnvironmentStage.php
new file mode 100644
index 000000000..7aaa2dabc
--- /dev/null
+++ b/src/App/Stages/LoadEnvironmentStage.php
@@ -0,0 +1,46 @@
+
+ * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
+ * @link http://quantum.softberg.org/
+ * @since 3.0.0
+ */
+
+namespace Quantum\App\Stages;
+
+use Quantum\Environment\Exceptions\EnvException;
+use Quantum\App\Contracts\BootStageInterface;
+use Quantum\App\Exceptions\BaseException;
+use Quantum\Di\Exceptions\DiException;
+use Quantum\Environment\Environment;
+use Quantum\App\AppContext;
+use Quantum\Loader\Setup;
+use ReflectionException;
+use Quantum\Di\Di;
+
+/**
+ * Class LoadEnvironmentStage
+ * @package Quantum\App
+ */
+class LoadEnvironmentStage implements BootStageInterface
+{
+ /**
+ * @throws EnvException|DiException|BaseException|ReflectionException
+ */
+ public function process(AppContext $context): void
+ {
+ $environment = new Environment();
+
+ $environment->load(new Setup('config', 'env'));
+
+ Di::set(Environment::class, $environment);
+ }
+}
diff --git a/src/App/Stages/LoadHelpersStage.php b/src/App/Stages/LoadHelpersStage.php
new file mode 100644
index 000000000..12b138885
--- /dev/null
+++ b/src/App/Stages/LoadHelpersStage.php
@@ -0,0 +1,72 @@
+
+ * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
+ * @link http://quantum.softberg.org/
+ * @since 3.0.0
+ */
+
+namespace Quantum\App\Stages;
+
+use Quantum\App\Contracts\BootStageInterface;
+use Quantum\Di\Exceptions\DiException;
+use Quantum\App\AppContext;
+use Quantum\Loader\Loader;
+use ReflectionException;
+use Quantum\App\App;
+use Quantum\Di\Di;
+
+/**
+ * Class LoadHelpersStage
+ * @package Quantum\App
+ */
+class LoadHelpersStage implements BootStageInterface
+{
+ /**
+ * @throws DiException|ReflectionException
+ */
+ public function process(AppContext $context): void
+ {
+ if (!Di::isRegistered(Loader::class)) {
+ Di::register(Loader::class);
+ }
+
+ $loader = Di::get(Loader::class);
+
+ $this->loadComponentHelpers($loader);
+ $this->loadAppHelpers($loader);
+ $this->loadModuleHelpers($loader);
+ }
+
+ private function loadComponentHelpers(Loader $loader): void
+ {
+ $srcDir = dirname(__DIR__, 2);
+
+ $componentDirs = glob($srcDir . DS . '*', GLOB_ONLYDIR);
+
+ foreach (is_array($componentDirs) ? $componentDirs : [] as $componentDir) {
+ $helperPath = $componentDir . DS . 'Helpers';
+ if (is_dir($helperPath)) {
+ $loader->loadDir($helperPath);
+ }
+ }
+ }
+
+ private function loadAppHelpers(Loader $loader): void
+ {
+ $loader->loadDir(App::getBaseDir() . DS . 'helpers');
+ }
+
+ private function loadModuleHelpers(Loader $loader): void
+ {
+ $loader->loadDir(App::getBaseDir() . DS . 'modules' . DS . '*' . DS . 'helpers');
+ }
+}
diff --git a/src/App/Stages/SetupErrorHandlerStage.php b/src/App/Stages/SetupErrorHandlerStage.php
new file mode 100644
index 000000000..b39a80ed6
--- /dev/null
+++ b/src/App/Stages/SetupErrorHandlerStage.php
@@ -0,0 +1,46 @@
+
+ * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
+ * @link http://quantum.softberg.org/
+ * @since 3.0.0
+ */
+
+namespace Quantum\App\Stages;
+
+use Quantum\Config\Exceptions\ConfigException;
+use Quantum\App\Contracts\BootStageInterface;
+use Quantum\Logger\Factories\LoggerFactory;
+use Quantum\App\Exceptions\BaseException;
+use Quantum\Di\Exceptions\DiException;
+use Quantum\Tracer\ErrorHandler;
+use Quantum\App\AppContext;
+use ReflectionException;
+use Quantum\Di\Di;
+
+/**
+ * Class SetupErrorHandlerStage
+ * @package Quantum\App
+ */
+class SetupErrorHandlerStage implements BootStageInterface
+{
+ /**
+ * @throws ConfigException|DiException|BaseException|ReflectionException
+ */
+ public function process(AppContext $context): void
+ {
+ if (!Di::isRegistered(ErrorHandler::class)) {
+ Di::register(ErrorHandler::class);
+ }
+
+ Di::get(ErrorHandler::class)->setup(LoggerFactory::get());
+ }
+}
diff --git a/src/App/Traits/AppTrait.php b/src/App/Traits/AppTrait.php
deleted file mode 100644
index 620cb44c6..000000000
--- a/src/App/Traits/AppTrait.php
+++ /dev/null
@@ -1,151 +0,0 @@
-
- * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
- * @link http://quantum.softberg.org/
- * @since 3.0.0
- */
-
-namespace Quantum\App\Traits;
-
-use Quantum\Config\Exceptions\ConfigException;
-use Quantum\Loader\Exceptions\LoaderException;
-use Quantum\Logger\Factories\LoggerFactory;
-use Quantum\Lang\Exceptions\LangException;
-use Quantum\App\Exceptions\BaseException;
-use Quantum\Lang\Factories\LangFactory;
-use Quantum\Di\Exceptions\DiException;
-use Quantum\Tracer\ErrorHandler;
-use Quantum\Loader\Loader;
-use Quantum\Config\Config;
-use Quantum\Loader\Setup;
-use ReflectionException;
-use Quantum\App\App;
-use Quantum\Di\Di;
-
-/**
- * Class AppTrait
- * @package Quantum\App
- */
-trait AppTrait
-{
- /**
- * Sets the app base directory
- */
- public static function setBaseDir(string $baseDir): void
- {
- self::$baseDir = $baseDir;
- }
-
- /**
- * Gets the app base directory
- */
- public static function getBaseDir(): string
- {
- return self::$baseDir;
- }
-
- /**
- * @throws DiException
- */
- protected function loadCoreDependencies(): void
- {
- $file = dirname(__DIR__) . DS . 'Config' . DS . 'dependencies.php';
-
- $coreDependencies = (is_file($file) && is_array($deps = require $file)) ? $deps : [];
-
- Di::registerDependencies($coreDependencies);
- }
-
- /**
- * Loads component helper functions
- * @throws DiException
- * @throws ReflectionException
- */
- protected function loadComponentHelperFunctions(): void
- {
- $loader = Di::get(Loader::class);
-
- $srcDir = dirname(__DIR__, 2);
-
- $componentDirs = glob($srcDir . DS . '*', GLOB_ONLYDIR);
-
- foreach (is_array($componentDirs) ? $componentDirs : [] as $componentDir) {
- $helperPath = $componentDir . DS . 'Helpers';
- if (is_dir($helperPath)) {
- $loader->loadDir($helperPath);
- }
- }
- }
-
- /**
- * Loads app helper functions
- * @throws DiException
- * @throws ReflectionException
- */
- protected function loadAppHelperFunctions(): void
- {
- $loader = Di::get(Loader::class);
- $loader->loadDir(App::getBaseDir() . DS . 'helpers');
- }
-
- /**
- * Loads module helper functions
- * @throws DiException
- * @throws ReflectionException
- */
- protected function loadModuleHelperFunctions(): void
- {
- $loader = Di::get(Loader::class);
- $loader->loadDir(App::getBaseDir() . DS . 'modules' . DS . '*' . DS . 'helpers');
- }
-
- /**
- * @return void
- * @throws DiException
- * @throws ReflectionException
- * @throws ConfigException|LoaderException
- */
- protected function loadAppConfig()
- {
- if (!config()->has('app')) {
- Config::getInstance()->import(new Setup('config', 'app'));
- }
- }
-
- /**
- * @return void
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
- */
- protected function setupErrorHandler()
- {
- ErrorHandler::getInstance()->setup(LoggerFactory::get());
- }
-
- /**
- * @return void
- * @throws BaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws LangException
- */
- protected function loadLanguage()
- {
- $lang = LangFactory::get();
-
- if ($lang->isEnabled()) {
- $lang->load();
- }
- }
-}
diff --git a/src/App/Traits/ConsoleAppTrait.php b/src/App/Traits/ConsoleAppTrait.php
index 85c2be9b1..b8207b662 100644
--- a/src/App/Traits/ConsoleAppTrait.php
+++ b/src/App/Traits/ConsoleAppTrait.php
@@ -16,14 +16,9 @@
namespace Quantum\App\Traits;
-use Quantum\Environment\Exceptions\EnvException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Application;
-use Quantum\App\Exceptions\BaseException;
-use Quantum\Di\Exceptions\DiException;
use Quantum\Console\CommandDiscovery;
-use Quantum\Environment\Environment;
-use Quantum\Loader\Setup;
use ReflectionException;
use Exception;
@@ -33,19 +28,6 @@
*/
trait ConsoleAppTrait
{
- /**
- * @throws DiException
- * @throws ReflectionException
- * @throws EnvException
- * @throws BaseException
- */
- protected function loadEnvironment(): void
- {
- Environment::getInstance()
- ->setMutable(true)
- ->load(new Setup('config', 'env'));
- }
-
public function createApplication(string $name, string $version): Application
{
return new Application($name, $version);
diff --git a/src/App/Traits/WebAppTrait.php b/src/App/Traits/WebAppTrait.php
index f41922b86..605759035 100644
--- a/src/App/Traits/WebAppTrait.php
+++ b/src/App/Traits/WebAppTrait.php
@@ -16,21 +16,27 @@
namespace Quantum\App\Traits;
-use Quantum\Environment\Exceptions\EnvException;
+use Quantum\App\Exceptions\StopExecutionException;
+use Quantum\Module\Exceptions\ModuleException;
use Quantum\Config\Exceptions\ConfigException;
use Quantum\Loader\Exceptions\LoaderException;
-use Quantum\Http\Exceptions\HttpException;
+use Quantum\Router\Exceptions\RouteException;
+use Quantum\Lang\Exceptions\LangException;
use Quantum\App\Exceptions\BaseException;
+use Quantum\Lang\Factories\LangFactory;
use Quantum\Di\Exceptions\DiException;
use Quantum\ResourceCache\ViewCache;
-use Quantum\Environment\Environment;
-use DebugBar\DebugBarException;
-use Quantum\Environment\Server;
+use Quantum\Router\RouteCollection;
+use Quantum\Router\RouteBuilder;
+use Quantum\Module\ModuleLoader;
+use Quantum\Router\MatchedRoute;
+use Quantum\Router\RouteFinder;
use Quantum\Debugger\Debugger;
use Quantum\Http\Response;
-use Quantum\Http\Request;
use Quantum\Loader\Setup;
use ReflectionException;
+use Quantum\Di\Di;
+use Exception;
/**
* Trait WebAppTrait
@@ -39,45 +45,78 @@
trait WebAppTrait
{
/**
- * @throws DiException
- * @throws ReflectionException
- * @throws EnvException
- * @throws BaseException
+ * @throws ModuleException|RouteException|DiException|ReflectionException
*/
- protected function loadEnvironment(): void
+ private function loadModules(): void
{
- Environment::getInstance()->load(new Setup('config', 'env'));
+ if (!Di::isRegistered(ModuleLoader::class)) {
+ Di::register(ModuleLoader::class);
+ }
+
+ $moduleLoader = Di::get(ModuleLoader::class);
+
+ $collection = (new RouteBuilder())->build(
+ $moduleLoader->loadModulesRoutes(),
+ $moduleLoader->getModuleConfigs()
+ );
+
+ Di::set(RouteCollection::class, $collection);
}
/**
- * @throws BaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws HttpException
+ * @return MatchedRoute
+ * @throws RouteException|StopExecutionException|ConfigException|BaseException|DiException|ReflectionException
*/
- private function initializeRequestResponse(Request $request, Response $response): void
+ private function resolveRoute(): MatchedRoute
{
- $request->init(Server::getInstance());
- $response->init();
+ $routeFinder = new RouteFinder(Di::get(RouteCollection::class));
+
+ $matchedRoute = $routeFinder->find(request());
+
+ if ($matchedRoute === null) {
+ page_not_found();
+ stop();
+ }
+
+ request()->setMatchedRoute($matchedRoute);
+
+ return $matchedRoute;
}
/**
- * @throws DebugBarException
+ * @throws LangException|ConfigException|DiException|BaseException|ReflectionException
*/
- private function initializeDebugger(): void
+ private function loadLanguage(): void
{
- $debugger = Debugger::getInstance();
- $debugger->initStore();
+ $lang = LangFactory::get();
+
+ if ($lang->isEnabled()) {
+ $lang->load();
+ }
}
/**
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException|LoaderException
+ * @throws DiException|ReflectionException
+ */
+ private function logDebugInfo(): void
+ {
+ $debugger = Di::get(Debugger::class);
+
+ if ($debugger->isEnabled()) {
+ $debugger->addToStoreCell(Debugger::HOOKS, 'info', hook()->getRegistered());
+ }
+ }
+
+ /**
+ * @throws ConfigException|DiException|ReflectionException|LoaderException
*/
private function setupViewCache(): ViewCache
{
- $viewCache = ViewCache::getInstance();
+ if (!Di::isRegistered(ViewCache::class)) {
+ Di::register(ViewCache::class);
+ }
+
+ $viewCache = Di::get(ViewCache::class);
if ($viewCache->isEnabled()) {
$viewCache->setup();
@@ -87,9 +126,7 @@ private function setupViewCache(): ViewCache
}
/**
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException|LoaderException
+ * @throws ConfigException|LoaderException|DiException|ReflectionException
*/
private function handleCors(Response $response): void
{
@@ -101,4 +138,13 @@ private function handleCors(Response $response): void
$response->setHeader($key, (string) $value);
}
}
+
+ /**
+ * @throws ConfigException|LoaderException|DiException|ReflectionException|Exception
+ */
+ private function sendResponse(): void
+ {
+ $this->handleCors(response());
+ response()->send();
+ }
}
diff --git a/src/Archive/Factories/ArchiveFactory.php b/src/Archive/Factories/ArchiveFactory.php
index 4b07dbab9..489722022 100644
--- a/src/Archive/Factories/ArchiveFactory.php
+++ b/src/Archive/Factories/ArchiveFactory.php
@@ -22,16 +22,15 @@
use Quantum\Archive\Adapters\ZipAdapter;
use Quantum\Archive\Enums\ArchiveType;
use Quantum\Archive\Archive;
+use ReflectionException;
+use Quantum\Di\Di;
/**
- * Class Cryptor
- * @package Quantum\Encryption
+ * Class ArchiveFactory
+ * @package Quantum\Archive
*/
class ArchiveFactory
{
- /**
- * Supported adapters
- */
public const ADAPTERS = [
ArchiveType::PHAR => PharAdapter::class,
ArchiveType::ZIP => ZipAdapter::class,
@@ -40,24 +39,36 @@ class ArchiveFactory
/**
* @var array
*/
- private static array $instances = [];
+ private array $instances = [];
/**
- * @throws BaseException
+ * @throws BaseException|ReflectionException
*/
public static function get(string $type = ArchiveType::PHAR): Archive
{
- if (!isset(self::$instances[$type])) {
- self::$instances[$type] = self::createInstance($type);
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve($type);
+ }
+
+ /**
+ * @throws BaseException
+ */
+ public function resolve(string $type = ArchiveType::PHAR): Archive
+ {
+ if (!isset($this->instances[$type])) {
+ $this->instances[$type] = $this->createInstance($type);
}
- return self::$instances[$type];
+ return $this->instances[$type];
}
/**
* @throws BaseException
*/
- private static function createInstance(string $type): Archive
+ private function createInstance(string $type): Archive
{
if (!isset(self::ADAPTERS[$type])) {
throw ArchiveException::adapterNotSupported($type);
diff --git a/src/Asset/Asset.php b/src/Asset/Asset.php
index 64ab140a2..6baec5760 100644
--- a/src/Asset/Asset.php
+++ b/src/Asset/Asset.php
@@ -16,6 +16,9 @@
namespace Quantum\Asset;
+use Quantum\Di\Exceptions\DiException;
+use ReflectionException;
+
/**
* Class Asset
* @package Quantum\Asset
@@ -110,6 +113,7 @@ public function getAttributes(): ?array
/**
* Gets asset url
+ * @throws DiException|ReflectionException
*/
public function url(): string
{
@@ -122,6 +126,7 @@ public function url(): string
/**
* Renders asset tag
+ * @throws DiException|ReflectionException
*/
public function tag(): string
{
diff --git a/src/Asset/AssetManager.php b/src/Asset/AssetManager.php
index 1c81558e7..aa7aee139 100644
--- a/src/Asset/AssetManager.php
+++ b/src/Asset/AssetManager.php
@@ -17,7 +17,8 @@
namespace Quantum\Asset;
use Quantum\Asset\Exceptions\AssetException;
-use Quantum\Lang\Exceptions\LangException;
+use Quantum\Di\Exceptions\DiException;
+use ReflectionException;
/**
* Class AssetFactory
@@ -45,30 +46,13 @@ class AssetManager
*/
private array $published = [];
- /**
- * Asset instance
- */
- private static ?AssetManager $instance = null;
-
- private function __construct()
+ public function __construct()
{
foreach (self::STORES as $type) {
$this->published[$type] = [];
}
}
- /**
- * AssetManager instance
- */
- public static function getInstance(): AssetManager
- {
- if (self::$instance == null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
-
/**
* Gets the asset by name
*/
@@ -85,6 +69,7 @@ public function get(string $name): ?Asset
/**
* Asset url
+ * @throws DiException|ReflectionException
*/
public function url(string $path): string
{
@@ -128,8 +113,7 @@ public function flush(): void
/**
* Dumps the assets
- * @throws AssetException
- * @throws LangException
+ * @throws AssetException|DiException|ReflectionException
*/
public function dump(int $type): void
{
diff --git a/src/Asset/Helpers/asset.php b/src/Asset/Helpers/asset.php
index 659d02732..d5923eaeb 100644
--- a/src/Asset/Helpers/asset.php
+++ b/src/Asset/Helpers/asset.php
@@ -13,23 +13,28 @@
*/
use Quantum\Asset\Exceptions\AssetException;
-use Quantum\Lang\Exceptions\LangException;
+use Quantum\Di\Exceptions\DiException;
use Quantum\Asset\AssetManager;
+use Quantum\Di\Di;
/**
- * Gets the AssetFactory instance
+ * Gets the AssetManager instance
+ * @throws DiException|ReflectionException
*/
function asset(): AssetManager
{
- return AssetManager::getInstance();
+ if (!Di::isRegistered(AssetManager::class)) {
+ Di::register(AssetManager::class);
+ }
+
+ return Di::get(AssetManager::class);
}
/**
* Dumps the assets
- * @throws AssetException
- * @throws LangException
+ * @throws AssetException|DiException|ReflectionException
*/
function assets(string $type): void
{
- AssetManager::getInstance()->dump(AssetManager::STORES[$type]);
+ asset()->dump(AssetManager::STORES[$type]);
}
diff --git a/src/Auth/Adapters/JwtAuthAdapter.php b/src/Auth/Adapters/JwtAuthAdapter.php
index db91f780b..132982148 100644
--- a/src/Auth/Adapters/JwtAuthAdapter.php
+++ b/src/Auth/Adapters/JwtAuthAdapter.php
@@ -20,13 +20,13 @@
use Quantum\Auth\Contracts\AuthServiceInterface;
use Quantum\Auth\Exceptions\AuthException;
use Quantum\Jwt\Exceptions\JwtException;
+use Quantum\Di\Exceptions\DiException;
use Quantum\Auth\Traits\AuthTrait;
use Quantum\Auth\Enums\AuthKeys;
use Quantum\Mailer\Mailer;
use Quantum\Hasher\Hasher;
-use Quantum\Http\Response;
-use Quantum\Http\Request;
use Quantum\Jwt\JwtToken;
+use ReflectionException;
use Quantum\Auth\User;
use Exception;
@@ -57,9 +57,7 @@ public function __construct(AuthServiceInterface $authService, Mailer $mailer, H
/**
* @inheritDoc
- * @throws AuthException
- * @throws JwtException
- * @throws Exception
+ * @throws AuthException|DiException|JwtException|ReflectionException|Exception
*/
public function signin(string $username, string $password)
{
@@ -74,10 +72,11 @@ public function signin(string $username, string $password)
/**
* @inheritDoc
+ * @throws DiException|ReflectionException
*/
public function signout(): bool
{
- $refreshToken = Request::getHeader($this->keyFields[AuthKeys::REFRESH_TOKEN]);
+ $refreshToken = request()->getHeader($this->keyFields[AuthKeys::REFRESH_TOKEN]);
$user = $this->authService->get($this->keyFields[AuthKeys::REFRESH_TOKEN], $refreshToken);
@@ -88,9 +87,9 @@ public function signout(): bool
array_merge($this->getVisibleFields($user), [$this->keyFields[AuthKeys::REFRESH_TOKEN] => ''])
);
- Request::deleteHeader($this->keyFields[AuthKeys::REFRESH_TOKEN]);
- Request::deleteHeader('Authorization');
- Response::delete('tokens');
+ request()->deleteHeader($this->keyFields[AuthKeys::REFRESH_TOKEN]);
+ request()->deleteHeader('Authorization');
+ response()->delete('tokens');
return true;
}
@@ -100,7 +99,7 @@ public function signout(): bool
/**
* @inheritDoc
- * @throws JwtException
+ * @throws JwtException|DiException|ReflectionException
*/
public function user(): ?User
{
@@ -113,7 +112,7 @@ public function user(): ?User
/**
* Refresh user data
- * @throws JwtException
+ * @throws JwtException|DiException|ReflectionException
*/
public function refreshUser(string $uuid): bool
{
@@ -130,9 +129,8 @@ public function refreshUser(string $uuid): bool
/**
* Verify OTP
- * @throws AuthException
- * @throws JwtException
* @return array
+ * @throws AuthException|JwtException|DiException|ReflectionException
*/
public function verifyOtp(int $otp, string $otpToken): array
{
@@ -157,7 +155,7 @@ protected function getUpdatedTokens(User $user): array
/**
* Set Updated Tokens
* @return array
- * @throws JwtException
+ * @throws JwtException|DiException|ReflectionException
*/
protected function setUpdatedTokens(User $user): array
{
@@ -169,9 +167,9 @@ protected function setUpdatedTokens(User $user): array
array_merge($this->getVisibleFields($user), [$this->keyFields[AuthKeys::REFRESH_TOKEN] => $tokens[$this->keyFields[AuthKeys::REFRESH_TOKEN]]])
);
- Request::setHeader($this->keyFields[AuthKeys::REFRESH_TOKEN], $tokens[$this->keyFields[AuthKeys::REFRESH_TOKEN]]);
- Request::setHeader('Authorization', 'Bearer ' . $tokens[$this->keyFields[AuthKeys::ACCESS_TOKEN]]);
- Response::set('tokens', $tokens);
+ request()->setHeader($this->keyFields[AuthKeys::REFRESH_TOKEN], $tokens[$this->keyFields[AuthKeys::REFRESH_TOKEN]]);
+ request()->setHeader('Authorization', 'Bearer ' . $tokens[$this->keyFields[AuthKeys::ACCESS_TOKEN]]);
+ response()->set('tokens', $tokens);
return $tokens;
}
@@ -183,13 +181,16 @@ protected function checkRefreshToken(): ?User
{
return $this->authService->get(
$this->keyFields[AuthKeys::REFRESH_TOKEN],
- Request::getHeader($this->keyFields[AuthKeys::REFRESH_TOKEN])
+ request()->getHeader($this->keyFields[AuthKeys::REFRESH_TOKEN])
);
}
+ /**
+ * @throws DiException|ReflectionException
+ */
private function getUserFromAccessToken(): ?User
{
- $authorizationBearer = Request::getAuthorizationBearer();
+ $authorizationBearer = request()->getAuthorizationBearer();
if (!$authorizationBearer) {
return null;
@@ -203,11 +204,11 @@ private function getUserFromAccessToken(): ?User
}
/**
- * @throws JwtException
+ * @throws JwtException|DiException|ReflectionException
*/
private function getUserFromRefreshToken(): ?User
{
- if (!Request::hasHeader($this->keyFields[AuthKeys::REFRESH_TOKEN])) {
+ if (!request()->hasHeader($this->keyFields[AuthKeys::REFRESH_TOKEN])) {
return null;
}
diff --git a/src/Auth/Adapters/SessionAuthAdapter.php b/src/Auth/Adapters/SessionAuthAdapter.php
index 3e051a158..31ccf5e11 100644
--- a/src/Auth/Adapters/SessionAuthAdapter.php
+++ b/src/Auth/Adapters/SessionAuthAdapter.php
@@ -172,6 +172,7 @@ public function verifyOtp(int $otp, string $otpToken): bool
/**
* Check Remember Token
* @return User|false
+ * @throws BaseException
*/
private function checkRememberToken()
{
diff --git a/src/Auth/Factories/AuthFactory.php b/src/Auth/Factories/AuthFactory.php
index bf2c9b12e..80dff5f25 100644
--- a/src/Auth/Factories/AuthFactory.php
+++ b/src/Auth/Factories/AuthFactory.php
@@ -33,6 +33,7 @@
use Quantum\Loader\Setup;
use ReflectionException;
use Quantum\Auth\Auth;
+use Quantum\Di\Di;
/**
* Class AuthFactory
@@ -40,9 +41,6 @@
*/
class AuthFactory
{
- /**
- * Supported adapters
- */
public const ADAPTERS = [
AuthType::SESSION => SessionAuthAdapter::class,
AuthType::JWT => JwtAuthAdapter::class,
@@ -51,7 +49,7 @@ class AuthFactory
/**
* @var array
*/
- private static array $instances = [];
+ private array $instances = [];
/**
* @throws AuthException
@@ -62,6 +60,18 @@ class AuthFactory
* @throws ServiceException
*/
public static function get(?string $adapter = null): Auth
+ {
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve($adapter);
+ }
+
+ /**
+ * @throws AuthException|ConfigException|ServiceException|BaseException|DiException|ReflectionException
+ */
+ public function resolve(?string $adapter = null): Auth
{
if (!config()->has('auth')) {
config()->import(new Setup('config', 'auth'));
@@ -69,30 +79,25 @@ public static function get(?string $adapter = null): Auth
$adapter ??= config()->get('auth.default');
- $adapterClass = self::getAdapterClass($adapter);
+ $adapterClass = $this->getAdapterClass($adapter);
- if (!isset(self::$instances[$adapter])) {
- self::$instances[$adapter] = self::createInstance($adapterClass, $adapter);
+ if (!isset($this->instances[$adapter])) {
+ $this->instances[$adapter] = $this->createInstance($adapterClass, $adapter);
}
- return self::$instances[$adapter];
+ return $this->instances[$adapter];
}
/**
- * @throws AuthException
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
- * @throws ServiceException
+ * @throws AuthException|ConfigException|ServiceException|BaseException|DiException|ReflectionException
*/
- private static function createInstance(string $adapterClass, string $adapter): Auth
+ private function createInstance(string $adapterClass, string $adapter): Auth
{
- $authService = self::createAuthService($adapter);
+ $authService = $this->createAuthService($adapter);
$authConfig = (array) config()->get('auth');
$adapterInstance = $adapter === AuthType::JWT
- ? new $adapterClass($authService, mailer(), new Hasher(), self::createJwtInstance(), $authConfig)
+ ? new $adapterClass($authService, mailer(), new Hasher(), $this->createJwtInstance(), $authConfig)
: new $adapterClass($authService, mailer(), new Hasher(), $authConfig);
if (!$adapterInstance instanceof AuthenticatableInterface) {
@@ -105,7 +110,7 @@ private static function createInstance(string $adapterClass, string $adapter): A
/**
* @throws BaseException
*/
- private static function getAdapterClass(string $adapter): string
+ private function getAdapterClass(string $adapter): string
{
if (!array_key_exists($adapter, self::ADAPTERS)) {
throw AuthException::adapterNotSupported($adapter);
@@ -115,12 +120,9 @@ private static function getAdapterClass(string $adapter): string
}
/**
- * @throws BaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws ServiceException
+ * @throws ServiceException|BaseException|DiException|ReflectionException
*/
- private static function createAuthService(string $adapter): AuthServiceInterface
+ private function createAuthService(string $adapter): AuthServiceInterface
{
$authServiceClass = config()->get('auth.' . $adapter . '.service');
@@ -134,7 +136,7 @@ private static function createAuthService(string $adapter): AuthServiceInterface
return $authService;
}
- private static function createJwtInstance(): JwtToken
+ private function createJwtInstance(): JwtToken
{
return (new JwtToken())
->setLeeway(1)
diff --git a/src/Auth/Helpers/auth.php b/src/Auth/Helpers/auth.php
index e4f1e7bd5..cd75ee361 100644
--- a/src/Auth/Helpers/auth.php
+++ b/src/Auth/Helpers/auth.php
@@ -22,12 +22,7 @@
/**
* Gets the Auth handler
- * @throws AuthException
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
- * @throws ServiceException
+ * @throws AuthException|ConfigException|ServiceException|BaseException|DiException|ReflectionException
*/
function auth(?string $adapter = null): Auth
{
diff --git a/src/Auth/User.php b/src/Auth/User.php
index 1bbac695e..17f2cde78 100644
--- a/src/Auth/User.php
+++ b/src/Auth/User.php
@@ -106,5 +106,4 @@ public function __get(string $property)
{
return $this->getFieldValue($property);
}
-
}
diff --git a/src/Cache/Adapters/DatabaseAdapter.php b/src/Cache/Adapters/DatabaseAdapter.php
index 555fb002a..902fb3017 100644
--- a/src/Cache/Adapters/DatabaseAdapter.php
+++ b/src/Cache/Adapters/DatabaseAdapter.php
@@ -16,6 +16,7 @@
namespace Quantum\Cache\Adapters;
+use Quantum\Model\Exceptions\ModelException;
use Quantum\Cache\Enums\ExceptionMessages;
use Quantum\App\Exceptions\BaseException;
use Quantum\Model\Factories\ModelFactory;
@@ -155,22 +156,8 @@ public function setMultiple($values, $ttl = null): bool
/**
* @inheritDoc
- */
- public function delete($key): bool
- {
- $cacheItem = $this->cacheModel->findOneBy('key', $this->keyHash($key));
-
- if ($cacheItem !== null && !empty($cacheItem->asArray())) {
- return $cacheItem->delete();
- }
-
- return false;
- }
-
- /**
- * @inheritDoc
- * @throws InvalidArgumentException
* @param iterable $keys
+ * @throws ModelException|BaseException|InvalidArgumentException
*/
public function deleteMultiple($keys): bool
{
@@ -190,6 +177,21 @@ public function deleteMultiple($keys): bool
return !in_array(false, $results, true);
}
+ /**
+ * @inheritDoc
+ * @throws ModelException|BaseException
+ */
+ public function delete($key): bool
+ {
+ $cacheItem = $this->cacheModel->findOneBy('key', $this->keyHash($key));
+
+ if ($cacheItem !== null && !empty($cacheItem->asArray())) {
+ return $cacheItem->delete();
+ }
+
+ return false;
+ }
+
/**
* @inheritDoc
*/
@@ -197,5 +199,4 @@ public function clear(): bool
{
return $this->cacheModel->deleteMany();
}
-
}
diff --git a/src/Cache/Factories/CacheFactory.php b/src/Cache/Factories/CacheFactory.php
index 7f2cc130f..4b62610c0 100644
--- a/src/Cache/Factories/CacheFactory.php
+++ b/src/Cache/Factories/CacheFactory.php
@@ -29,6 +29,7 @@
use Quantum\Loader\Setup;
use ReflectionException;
use Quantum\Cache\Cache;
+use Quantum\Di\Di;
/**
* Class CacheFactory
@@ -36,9 +37,6 @@
*/
class CacheFactory
{
- /**
- * Supported adapters
- */
public const ADAPTERS = [
CacheType::FILE => FileAdapter::class,
CacheType::DATABASE => DatabaseAdapter::class,
@@ -49,15 +47,24 @@ class CacheFactory
/**
* @var array
*/
- private static array $instances = [];
+ private array $instances = [];
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|BaseException|DiException|ReflectionException
*/
public static function get(?string $adapter = null): Cache
+ {
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve($adapter);
+ }
+
+ /**
+ * @throws ConfigException|BaseException|DiException|ReflectionException
+ */
+ public function resolve(?string $adapter = null): Cache
{
if (!config()->has('cache')) {
config()->import(new Setup('config', 'cache'));
@@ -65,19 +72,19 @@ public static function get(?string $adapter = null): Cache
$adapter ??= config()->get('cache.default');
- $adapterClass = self::getAdapterClass($adapter);
+ $adapterClass = $this->getAdapterClass($adapter);
- if (!isset(self::$instances[$adapter])) {
- self::$instances[$adapter] = self::createInstance($adapterClass, $adapter);
+ if (!isset($this->instances[$adapter])) {
+ $this->instances[$adapter] = $this->createInstance($adapterClass, $adapter);
}
- return self::$instances[$adapter];
+ return $this->instances[$adapter];
}
/**
- * @throws CacheException
+ * @throws CacheException|BaseException
*/
- private static function createInstance(string $adapterClass, string $adapter): Cache
+ private function createInstance(string $adapterClass, string $adapter): Cache
{
$cacheAdapter = new $adapterClass(config()->get('cache.' . $adapter));
@@ -91,7 +98,7 @@ private static function createInstance(string $adapterClass, string $adapter): C
/**
* @throws BaseException
*/
- private static function getAdapterClass(string $adapter): string
+ private function getAdapterClass(string $adapter): string
{
if (!array_key_exists($adapter, self::ADAPTERS)) {
throw CacheException::adapterNotSupported($adapter);
diff --git a/src/Cache/Helpers/cache.php b/src/Cache/Helpers/cache.php
index 82f44b162..164c4e11b 100644
--- a/src/Cache/Helpers/cache.php
+++ b/src/Cache/Helpers/cache.php
@@ -19,10 +19,7 @@
use Quantum\Cache\Cache;
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|BaseException|DiException|ReflectionException
*/
function cache(?string $adapter = null): Cache
{
diff --git a/src/Cache/Traits/CacheTrait.php b/src/Cache/Traits/CacheTrait.php
index de64e695e..b886703a4 100644
--- a/src/Cache/Traits/CacheTrait.php
+++ b/src/Cache/Traits/CacheTrait.php
@@ -25,15 +25,9 @@
*/
trait CacheTrait
{
- /**
- * @var int
- */
- protected $ttl;
+ protected int $ttl;
- /**
- * @var string
- */
- protected $prefix;
+ protected string $prefix;
/**
* Gets the hashed key
diff --git a/src/Captcha/Adapters/HcaptchaAdapter.php b/src/Captcha/Adapters/HcaptchaAdapter.php
index a918fd44c..313e170a9 100644
--- a/src/Captcha/Adapters/HcaptchaAdapter.php
+++ b/src/Captcha/Adapters/HcaptchaAdapter.php
@@ -32,10 +32,7 @@ class HcaptchaAdapter implements CaptchaInterface
public const CLIENT_API = 'https://hcaptcha.com/1/api.js?onload=onLoadCallback&recaptchacompat=off';
- /**
- * @var string
- */
- protected $name = 'h-captcha';
+ protected string $name = 'h-captcha';
/**
* @var string[]
diff --git a/src/Captcha/Adapters/RecaptchaAdapter.php b/src/Captcha/Adapters/RecaptchaAdapter.php
index cb4b9a7ed..e7a098c53 100644
--- a/src/Captcha/Adapters/RecaptchaAdapter.php
+++ b/src/Captcha/Adapters/RecaptchaAdapter.php
@@ -32,10 +32,7 @@ class RecaptchaAdapter implements CaptchaInterface
public const CLIENT_API = 'https://www.google.com/recaptcha/api.js';
- /**
- * @var string
- */
- protected $name = 'g-recaptcha';
+ protected string $name = 'g-recaptcha';
/**
* @var string[]
diff --git a/src/Captcha/Factories/CaptchaFactory.php b/src/Captcha/Factories/CaptchaFactory.php
index 751e46137..57efd3351 100644
--- a/src/Captcha/Factories/CaptchaFactory.php
+++ b/src/Captcha/Factories/CaptchaFactory.php
@@ -28,6 +28,7 @@
use Quantum\Captcha\Captcha;
use Quantum\Loader\Setup;
use ReflectionException;
+use Quantum\Di\Di;
/**
* Class CaptchaFactory
@@ -35,9 +36,6 @@
*/
class CaptchaFactory
{
- /**
- * Supported adapters
- */
public const ADAPTERS = [
CaptchaType::HCAPTCHA => HcaptchaAdapter::class,
CaptchaType::RECAPTCHA => RecaptchaAdapter::class,
@@ -46,7 +44,7 @@ class CaptchaFactory
/**
* @var array
*/
- private static array $instances = [];
+ private array $instances = [];
/**
* @throws BaseException
@@ -55,6 +53,18 @@ class CaptchaFactory
* @throws ReflectionException
*/
public static function get(?string $adapter = null): Captcha
+ {
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve($adapter);
+ }
+
+ /**
+ * @throws ConfigException|BaseException|DiException|ReflectionException
+ */
+ public function resolve(?string $adapter = null): Captcha
{
if (!config()->has('captcha')) {
config()->import(new Setup('config', 'captcha'));
@@ -62,19 +72,19 @@ public static function get(?string $adapter = null): Captcha
$adapter ??= config()->get('captcha.default');
- $adapterClass = self::getAdapterClass($adapter);
+ $adapterClass = $this->getAdapterClass($adapter);
- if (!isset(self::$instances[$adapter])) {
- self::$instances[$adapter] = self::createInstance($adapterClass, $adapter);
+ if (!isset($this->instances[$adapter])) {
+ $this->instances[$adapter] = $this->createInstance($adapterClass, $adapter);
}
- return self::$instances[$adapter];
+ return $this->instances[$adapter];
}
/**
- * @throws CaptchaException
+ * @throws CaptchaException|BaseException
*/
- private static function createInstance(string $adapterClass, string $adapter): Captcha
+ private function createInstance(string $adapterClass, string $adapter): Captcha
{
$adapterInstance = new $adapterClass(config()->get('captcha.' . $adapter), new HttpClient());
@@ -88,7 +98,7 @@ private static function createInstance(string $adapterClass, string $adapter): C
/**
* @throws BaseException
*/
- private static function getAdapterClass(string $adapter): string
+ private function getAdapterClass(string $adapter): string
{
if (!array_key_exists($adapter, self::ADAPTERS)) {
throw CaptchaException::adapterNotSupported($adapter);
diff --git a/src/Captcha/Helpers/captcha.php b/src/Captcha/Helpers/captcha.php
index 8fe75d26d..4a8c05ab8 100644
--- a/src/Captcha/Helpers/captcha.php
+++ b/src/Captcha/Helpers/captcha.php
@@ -19,10 +19,7 @@
use Quantum\Captcha\Captcha;
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|BaseException|DiException|ReflectionException
*/
function captcha(?string $adapter = null): Captcha
{
diff --git a/src/Captcha/Traits/CaptchaTrait.php b/src/Captcha/Traits/CaptchaTrait.php
index 4ebd4e150..6345e84da 100644
--- a/src/Captcha/Traits/CaptchaTrait.php
+++ b/src/Captcha/Traits/CaptchaTrait.php
@@ -20,9 +20,7 @@
use Quantum\Asset\Exceptions\AssetException;
use Quantum\Lang\Exceptions\LangException;
use Quantum\Http\Exceptions\HttpException;
-use Quantum\App\Exceptions\BaseException;
use Quantum\HttpClient\HttpClient;
-use Quantum\Asset\AssetManager;
use Quantum\Asset\Asset;
use ErrorException;
use Exception;
@@ -89,7 +87,7 @@ public function addToForm(string $formIdentifier = '', array $attributes = []):
throw new Exception('Captcha type is not set');
}
- AssetManager::getInstance()->registerAsset(new Asset(Asset::JS, static::CLIENT_API, 'captcha', -1, ['async', 'defer']));
+ asset()->registerAsset(new Asset(Asset::JS, static::CLIENT_API, 'captcha', -1, ['async', 'defer']));
if (strtolower($this->type) == self::CAPTCHA_INVISIBLE) {
return $this->getInvisibleElement($formIdentifier);
@@ -100,11 +98,7 @@ public function addToForm(string $formIdentifier = '', array $attributes = []):
/**
* Checks the code given by the captcha
- * @throws LangException
- * @throws ErrorException
- * @throws BaseException
- * @throws HttpException
- * @throws Exception
+ * @throws LangException|HttpException|ErrorException|Exception
*/
public function verify(string $code): bool
{
@@ -193,9 +187,6 @@ function onSubmit (){
';
}
- /**
- * @param string $type
- */
protected function isValidCaptchaType(string $type): bool
{
$captchaTypes = [
diff --git a/src/Config/Config.php b/src/Config/Config.php
index c23794200..bf008d7f9 100644
--- a/src/Config/Config.php
+++ b/src/Config/Config.php
@@ -32,21 +32,7 @@
*/
class Config implements ConfigInterface
{
- private static ?Data $configs = null;
-
- private static ?Config $instance = null;
-
- /**
- * GetInstance
- */
- public static function getInstance(): Config
- {
- if (self::$instance === null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
+ private ?Data $configs = null;
/**
* @inheritDoc
@@ -54,11 +40,11 @@ public static function getInstance(): Config
*/
public function load(Setup $setup): void
{
- if (self::$configs !== null) {
+ if ($this->configs !== null) {
return;
}
- self::$configs = new Data(Di::get(Loader::class)->setup($setup)->load());
+ $this->configs = new Data($this->loadConfig($setup));
}
/**
@@ -75,10 +61,12 @@ public function import(Setup $setup): void
throw ConfigException::configCollision($fileName);
}
- if (!self::$configs) {
- self::$configs = new Data([$fileName => Di::get(Loader::class)->setup($setup)->load()]);
+ $data = $this->loadConfig($setup);
+
+ if (!$this->configs) {
+ $this->configs = new Data([$fileName => $data]);
} else {
- self::$configs->import([$fileName => Di::get(Loader::class)->setup($setup)->load()]);
+ $this->configs->import([$fileName => $data]);
}
}
@@ -87,8 +75,8 @@ public function import(Setup $setup): void
*/
public function get(string $key, $default = null)
{
- if (self::$configs && self::$configs->has($key)) {
- return self::$configs->get($key);
+ if ($this->configs && $this->configs->has($key)) {
+ return $this->configs->get($key);
}
return $default;
@@ -99,7 +87,7 @@ public function get(string $key, $default = null)
*/
public function all(): ?Data
{
- return self::$configs;
+ return $this->configs;
}
/**
@@ -107,7 +95,7 @@ public function all(): ?Data
*/
public function has(string $key): bool
{
- return self::$configs && !empty(self::$configs->has($key));
+ return $this->configs && !empty($this->configs->has($key));
}
/**
@@ -115,10 +103,10 @@ public function has(string $key): bool
*/
public function set(string $key, $value): void
{
- if (!self::$configs) {
- self::$configs = new Data([$key => $value]);
+ if (!$this->configs) {
+ $this->configs = new Data([$key => $value]);
} else {
- self::$configs->set($key, $value);
+ $this->configs->set($key, $value);
}
}
@@ -127,7 +115,7 @@ public function set(string $key, $value): void
*/
public function delete(string $key): void
{
- self::$configs && self::$configs->remove($key);
+ $this->configs && $this->configs->remove($key);
}
/**
@@ -135,6 +123,19 @@ public function delete(string $key): void
*/
public function flush(): void
{
- self::$configs = null;
+ $this->configs = null;
+ }
+
+ /**
+ * @return array
+ * @throws DiException|LoaderException|ReflectionException
+ */
+ private function loadConfig(Setup $setup): array
+ {
+ if (!Di::isRegistered(Loader::class)) {
+ Di::register(Loader::class);
+ }
+
+ return Di::get(Loader::class)->setup($setup)->load();
}
}
diff --git a/src/Config/Helpers/config.php b/src/Config/Helpers/config.php
index 877f549c9..a039f587a 100644
--- a/src/Config/Helpers/config.php
+++ b/src/Config/Helpers/config.php
@@ -13,11 +13,18 @@
*/
use Quantum\Config\Config;
+use Quantum\Di\Di;
+use Quantum\Di\Exceptions\DiException;
/**
* Config facade
+ * @throws DiException|ReflectionException
*/
function config(): Config
{
- return Config::getInstance();
+ if (!Di::isRegistered(Config::class)) {
+ Di::register(Config::class);
+ }
+
+ return Di::get(Config::class);
}
diff --git a/src/Console/Commands/CronRunCommand.php b/src/Console/Commands/CronRunCommand.php
index e60aac9a9..c6c22c50f 100644
--- a/src/Console/Commands/CronRunCommand.php
+++ b/src/Console/Commands/CronRunCommand.php
@@ -16,9 +16,14 @@
namespace Quantum\Console\Commands;
+use Quantum\Config\Exceptions\ConfigException;
use Quantum\Cron\Exceptions\CronException;
+use Quantum\App\Exceptions\BaseException;
+use Quantum\Di\Exceptions\DiException;
use Quantum\Console\QtCommand;
use Quantum\Cron\CronManager;
+use ReflectionException;
+use Throwable;
/**
* Class CronRunCommand
@@ -70,13 +75,14 @@ public function exec(): void
}
} catch (CronException $e) {
$this->error($e->getMessage());
- } catch (\Throwable $e) {
+ } catch (Throwable $e) {
$this->error('Unexpected error: ' . $e->getMessage());
}
}
/**
* Run all due tasks
+ * @throws CronException|ConfigException|DiException|BaseException|ReflectionException
*/
private function runAllDueTasks(CronManager $manager, bool $force): void
{
@@ -111,7 +117,7 @@ private function runAllDueTasks(CronManager $manager, bool $force): void
/**
* Run a specific task
- * @throws CronException
+ * @throws CronException|ConfigException|DiException|BaseException|ReflectionException
*/
private function runSpecificTask(CronManager $manager, string $taskName, bool $force): void
{
diff --git a/src/Console/Commands/InstallToolkitCommand.php b/src/Console/Commands/InstallToolkitCommand.php
index 82ab3878c..8f0fcd38a 100644
--- a/src/Console/Commands/InstallToolkitCommand.php
+++ b/src/Console/Commands/InstallToolkitCommand.php
@@ -20,8 +20,11 @@
use Quantum\Environment\Exceptions\EnvException;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Input\ArrayInput;
-use Quantum\Environment\Environment;
+use Quantum\Config\Exceptions\ConfigException;
+use Quantum\App\Exceptions\BaseException;
+use Quantum\Di\Exceptions\DiException;
use Quantum\Console\QtCommand;
+use ReflectionException;
use RuntimeException;
/**
@@ -60,8 +63,7 @@ class InstallToolkitCommand extends QtCommand
/**
* Executes the command
- * @throws ExceptionInterface
- * @throws EnvException
+ * @throws EnvException|ConfigException|BaseException|DiException|ExceptionInterface|ReflectionException
*/
public function exec(): void
{
@@ -69,7 +71,7 @@ public function exec(): void
$password = $this->getArgument('password');
- $env = Environment::getInstance();
+ $env = environment();
$env->setMutable(true);
diff --git a/src/Console/Commands/KeyGenerateCommand.php b/src/Console/Commands/KeyGenerateCommand.php
index 2a99090d9..e18c8b344 100644
--- a/src/Console/Commands/KeyGenerateCommand.php
+++ b/src/Console/Commands/KeyGenerateCommand.php
@@ -17,7 +17,6 @@
namespace Quantum\Console\Commands;
use Quantum\Environment\Exceptions\EnvException;
-use Quantum\Environment\Environment;
use Quantum\Console\QtCommand;
use Exception;
@@ -57,14 +56,16 @@ class KeyGenerateCommand extends QtCommand
*/
public function exec(): void
{
- if (Environment::getInstance()->hasKey('APP_KEY') && env('APP_KEY') !== '' && !$this->getOption('yes')) {
+ $environment = environment();
+
+ if ($environment->hasKey('APP_KEY') && $environment->getValue('APP_KEY') !== '' && !$this->getOption('yes')) {
if (!$this->confirm('The operation will remove the existing key and will create new one. Continue?')) {
$this->info('Operation was canceled!');
return;
}
}
- Environment::getInstance()
+ $environment
->setMutable(true)
->updateRow('APP_KEY', $this->generateRandomKey());
diff --git a/src/Console/Commands/MigrationGenerateCommand.php b/src/Console/Commands/MigrationGenerateCommand.php
index 4740d9de6..1cb21f8e3 100644
--- a/src/Console/Commands/MigrationGenerateCommand.php
+++ b/src/Console/Commands/MigrationGenerateCommand.php
@@ -17,7 +17,6 @@
namespace Quantum\Console\Commands;
use Quantum\Migration\Exceptions\MigrationException;
-use Quantum\Lang\Exceptions\LangException;
use Quantum\Migration\MigrationManager;
use Quantum\Console\QtCommand;
@@ -48,7 +47,6 @@ class MigrationGenerateCommand extends QtCommand
/**
* Executes the command
- * @throws LangException
* @throws MigrationException
*/
public function exec(): void
diff --git a/src/Console/Commands/MigrationMigrateCommand.php b/src/Console/Commands/MigrationMigrateCommand.php
index c001edbf8..57e1d3299 100644
--- a/src/Console/Commands/MigrationMigrateCommand.php
+++ b/src/Console/Commands/MigrationMigrateCommand.php
@@ -18,11 +18,8 @@
use Quantum\Migration\Exceptions\MigrationException;
use Quantum\Database\Exceptions\DatabaseException;
-use Quantum\Config\Exceptions\ConfigException;
-use Quantum\Lang\Exceptions\LangException;
use Quantum\App\Exceptions\BaseException;
use Quantum\Migration\MigrationManager;
-use Quantum\Di\Exceptions\DiException;
use Quantum\Console\QtCommand;
/**
@@ -59,11 +56,7 @@ class MigrationMigrateCommand extends QtCommand
/**
* Executes the command
- * @throws BaseException
- * @throws ConfigException
- * @throws DatabaseException
- * @throws DiException
- * @throws LangException
+ * @throws DatabaseException|BaseException
*/
public function exec(): void
{
diff --git a/src/Console/Commands/OpenApiCommand.php b/src/Console/Commands/OpenApiCommand.php
index 5df57383e..856fb3e42 100644
--- a/src/Console/Commands/OpenApiCommand.php
+++ b/src/Console/Commands/OpenApiCommand.php
@@ -89,15 +89,15 @@ public function __construct()
/**
* Executes the command and generate Open API specifications
- * @throws BaseException
- * @throws ModuleException
- * @throws RouteException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ModuleException|RouteException|DiException|BaseException|ReflectionException
*/
public function exec(): void
{
- $moduleLoader = ModuleLoader::getInstance();
+ if (!Di::isRegistered(ModuleLoader::class)) {
+ Di::register(ModuleLoader::class);
+ }
+
+ $moduleLoader = Di::get(ModuleLoader::class);
$builder = new RouteBuilder();
diff --git a/src/Console/Commands/ResourceCacheClearCommand.php b/src/Console/Commands/ResourceCacheClearCommand.php
index 631b135f9..25ccebb59 100644
--- a/src/Console/Commands/ResourceCacheClearCommand.php
+++ b/src/Console/Commands/ResourceCacheClearCommand.php
@@ -85,9 +85,6 @@ public function __construct()
$this->fs = FileSystemFactory::get();
}
- /**
- * @throws BaseException|ReflectionException
- */
public function exec(): void
{
try {
@@ -133,9 +130,7 @@ private function importModules(): void
}
/**
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException|LoaderException
+ * @throws LoaderException|ConfigException|DiException|ReflectionException
*/
private function importConfig(): void
{
diff --git a/src/Console/Commands/RouteListCommand.php b/src/Console/Commands/RouteListCommand.php
index a1db75eca..40005c6de 100644
--- a/src/Console/Commands/RouteListCommand.php
+++ b/src/Console/Commands/RouteListCommand.php
@@ -25,6 +25,7 @@
use Quantum\Module\ModuleLoader;
use Quantum\Console\QtCommand;
use Quantum\Router\Route;
+use ReflectionException;
use Quantum\Di\Di;
/**
@@ -53,12 +54,16 @@ class RouteListCommand extends QtCommand
/**
* Executes the command
- * @throws DiException
+ * @throws DiException|ReflectionException
*/
public function exec(): void
{
try {
- $moduleLoader = ModuleLoader::getInstance();
+ if (!Di::isRegistered(ModuleLoader::class)) {
+ Di::register(ModuleLoader::class);
+ }
+
+ $moduleLoader = Di::get(ModuleLoader::class);
$builder = new RouteBuilder();
$routeCollection = $builder->build(
diff --git a/src/Console/Commands/VersionCommand.php b/src/Console/Commands/VersionCommand.php
index c5a341d15..dbae807d1 100644
--- a/src/Console/Commands/VersionCommand.php
+++ b/src/Console/Commands/VersionCommand.php
@@ -16,14 +16,8 @@
namespace Quantum\Console\Commands;
-use Quantum\Environment\Exceptions\EnvException;
-use Quantum\App\Exceptions\BaseException;
-use Quantum\Di\Exceptions\DiException;
-use Quantum\Environment\Environment;
use Quantum\Console\QtCommand;
use Povils\Figlet\Figlet;
-use Quantum\Loader\Setup;
-use ReflectionException;
/**
* Class VersionCommand
@@ -48,24 +42,20 @@ class VersionCommand extends QtCommand
/**
* Executes the command and prints greetings into the terminal
- * @throws DiException
- * @throws EnvException
- * @throws BaseException
- * @throws ReflectionException
*/
public function exec(): void
{
- Environment::getInstance()->load(new Setup('config', 'env'));
+ $version = config()->get('app.version', 'UNKNOWN');
$figlet = new Figlet();
$renderedFiglet = $figlet
->setFontDir(assets_dir() . DS . 'shared' . DS . 'fonts' . DS . 'figlet' . DS)
->setFont('slant')
- ->render('QUANTUM PHP ' . env('APP_VERSION'));
+ ->render('QUANTUM PHP ' . $version);
$this->info($renderedFiglet);
- $this->info('- - - Q U A N T U M P H P F R A M E W O R K ' . env('APP_VERSION') . ' I N S T A L L E D - - -');
+ $this->info('- - - Q U A N T U M P H P F R A M E W O R K ' . $version . ' I N S T A L L E D - - -');
}
}
diff --git a/src/Cookie/Cookie.php b/src/Cookie/Cookie.php
index 174d1e219..bc45c1a33 100644
--- a/src/Cookie/Cookie.php
+++ b/src/Cookie/Cookie.php
@@ -29,34 +29,14 @@ class Cookie implements CookieStorageInterface
* Cookie storage
* @var array
*/
- private static array $storage = [];
+ private array $storage;
/**
- * Cookie instance
- */
- private static ?Cookie $instance = null;
-
- /**
- * Cookie constructor.
- */
- private function __construct()
- {
- // Preventing to create a new object through constructor
- }
-
- /**
- * Gets the cookie instance
* @param array $storage
*/
- public static function getInstance(array &$storage): Cookie
+ public function __construct(array &$storage)
{
- self::$storage = &$storage;
-
- if (self::$instance === null) {
- self::$instance = new self();
- }
-
- return self::$instance;
+ $this->storage = &$storage;
}
/**
@@ -68,7 +48,7 @@ public function all(): array
{
$allCookies = [];
- foreach (self::$storage as $key => $value) {
+ foreach ($this->storage as $key => $value) {
$allCookies[$key] = crypto_decode($value);
}
@@ -80,7 +60,7 @@ public function all(): array
*/
public function has(string $key): bool
{
- return isset(self::$storage[$key]) && !empty(self::$storage[$key]);
+ return isset($this->storage[$key]) && !empty($this->storage[$key]);
}
/**
@@ -89,7 +69,7 @@ public function has(string $key): bool
*/
public function get(string $key)
{
- return $this->has($key) ? crypto_decode(self::$storage[$key]) : null;
+ return $this->has($key) ? crypto_decode($this->storage[$key]) : null;
}
/**
@@ -98,7 +78,7 @@ public function get(string $key)
*/
public function set(string $key, $value = '', int $time = 0, string $path = '/', string $domain = '', bool $secure = false, bool $httponly = false): void
{
- self::$storage[$key] = crypto_encode($value);
+ $this->storage[$key] = crypto_encode($value);
setcookie($key, crypto_encode($value), ['expires' => $time !== 0 ? time() + $time : $time, 'path' => $path, 'domain' => $domain, 'secure' => $secure, 'httponly' => $httponly]);
}
@@ -108,7 +88,7 @@ public function set(string $key, $value = '', int $time = 0, string $path = '/',
public function delete(string $key, string $path = '/'): void
{
if ($this->has($key)) {
- unset(self::$storage[$key]);
+ unset($this->storage[$key]);
setcookie($key, '', ['expires' => time() - 3600, 'path' => $path]);
}
}
@@ -118,8 +98,8 @@ public function delete(string $key, string $path = '/'): void
*/
public function flush(): void
{
- if (count(self::$storage)) {
- foreach (array_keys(self::$storage) as $key) {
+ if (count($this->storage)) {
+ foreach (array_keys($this->storage) as $key) {
$this->delete($key, '/');
}
}
diff --git a/src/Cookie/Helpers/cookie.php b/src/Cookie/Helpers/cookie.php
index 5ab4748dc..5e72a212c 100644
--- a/src/Cookie/Helpers/cookie.php
+++ b/src/Cookie/Helpers/cookie.php
@@ -12,12 +12,19 @@
* @since 3.0.0
*/
+use Quantum\Di\Exceptions\DiException;
use Quantum\Cookie\Cookie;
+use Quantum\Di\Di;
/**
* Gets cookie handler
+ * @throws DiException|ReflectionException
*/
function cookie(): Cookie
{
- return Cookie::getInstance($_COOKIE);
+ if (!Di::has(Cookie::class)) {
+ Di::set(Cookie::class, new Cookie($_COOKIE));
+ }
+
+ return Di::get(Cookie::class);
}
diff --git a/src/Cron/CronLock.php b/src/Cron/CronLock.php
index 5e55841f9..862f4f449 100644
--- a/src/Cron/CronLock.php
+++ b/src/Cron/CronLock.php
@@ -38,7 +38,7 @@ class CronLock
private const DEFAULT_MAX_LOCK_AGE = 86400;
/**
- * @throws BaseException|ConfigException|CronException|DiException|ReflectionException
+ * @throws CronException|ConfigException|DiException|BaseException|ReflectionException
*/
public function __construct(string $taskName, ?string $lockDirectory = null, ?int $maxLockAge = null)
{
@@ -104,10 +104,7 @@ public function getTimestamp(): int
}
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public function release(): bool
{
@@ -131,10 +128,7 @@ public function release(): bool
/**
* Check if another process currently holds the lock.
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public function isLocked(): bool
{
@@ -184,11 +178,7 @@ private function getDefaultLockDirectory(): string
}
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws CronException
- * @throws DiException
- * @throws ReflectionException
+ * @throws CronException|ConfigException|DiException|BaseException|ReflectionException
*/
private function ensureLockDirectoryExists(): void
{
@@ -204,11 +194,7 @@ private function ensureLockDirectoryExists(): void
}
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws CronException
- * @throws DiException
- * @throws ReflectionException
+ * @throws CronException|ConfigException|DiException|BaseException|ReflectionException
*/
private function createDirectory(string $directory): void
{
@@ -228,10 +214,7 @@ private function createDirectory(string $directory): void
}
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
private function cleanupStaleLocks(): void
{
diff --git a/src/Cron/CronManager.php b/src/Cron/CronManager.php
index f4576708b..87275b936 100644
--- a/src/Cron/CronManager.php
+++ b/src/Cron/CronManager.php
@@ -24,6 +24,7 @@
use Quantum\Di\Exceptions\DiException;
use Quantum\Logger\Enums\LoggerType;
use ReflectionException;
+use Throwable;
/**
* Class CronManager
@@ -56,8 +57,8 @@ class CronManager
];
/**
- * CronManager constructor
- */
+ * @throws DiException|ReflectionException
+ */
public function __construct(?string $cronDirectory = null)
{
$configuredPath = $cronDirectory ?? cron_config('path');
@@ -66,10 +67,6 @@ public function __construct(?string $cronDirectory = null)
/**
* Load tasks from the cron directory
- * @return void
- * @throws CronException
- */
- /**
* @throws CronException|BaseException|ConfigException|DiException|ReflectionException
*/
public function loadTasks(): void
@@ -133,7 +130,7 @@ private function createTaskFromArray(array $definition): CronTask
*/
/**
* @return array|int[]
- * @throws BaseException|ConfigException|CronException|DiException|ReflectionException
+ * @throws CronException|ConfigException|DiException|BaseException|ReflectionException
*/
public function runDueTasks(bool $force = false): array
{
@@ -152,7 +149,7 @@ public function runDueTasks(bool $force = false): array
/**
* Run a specific task by name
- * @throws BaseException|ConfigException|CronException|DiException|ReflectionException
+ * @throws CronException|ConfigException|DiException|BaseException|ReflectionException
*/
public function runTaskByName(string $taskName, bool $force = false): void
{
@@ -167,7 +164,7 @@ public function runTaskByName(string $taskName, bool $force = false): void
/**
* Run a single task
- * @throws BaseException|ConfigException|CronException|DiException|ReflectionException
+ * @throws CronException|ConfigException|DiException|BaseException|ReflectionException
*/
private function runTask(CronTaskInterface $task, bool $force = false): void
{
@@ -187,7 +184,7 @@ private function runTask(CronTaskInterface $task, bool $force = false): void
$duration = round(microtime(true) - $startTime, 2);
$this->stats['executed']++;
$this->log('info', "Task \"{$task->getName()}\" completed in {$duration}s");
- } catch (\Throwable $e) {
+ } catch (Throwable $e) {
$this->stats['failed']++;
$this->log('error', "Task \"{$task->getName()}\" failed: " . $e->getMessage(), [
'exception' => get_class($e),
@@ -236,7 +233,7 @@ private function log(string $level, string $message, array $context = []): void
try {
$logger = LoggerFactory::get(LoggerType::SINGLE);
$logger->log($level, '[CRON] ' . $message, $context);
- } catch (\Throwable $exception) {
+ } catch (Throwable $exception) {
error_log(sprintf('[CRON] [%s] %s', strtoupper($level), $message));
}
}
diff --git a/src/Cron/CronTask.php b/src/Cron/CronTask.php
index de942111e..efa9ad4ab 100644
--- a/src/Cron/CronTask.php
+++ b/src/Cron/CronTask.php
@@ -19,6 +19,7 @@
use Quantum\Cron\Contracts\CronTaskInterface;
use Quantum\Cron\Exceptions\CronException;
use Cron\CronExpression;
+use Exception;
/**
* Class CronTask
@@ -53,7 +54,7 @@ public function __construct(string $name, string $expression, callable $callback
try {
$this->cronExpression = new CronExpression($expression);
- } catch (\Exception $e) {
+ } catch (Exception $e) {
throw CronException::invalidExpression($expression);
}
}
@@ -100,6 +101,7 @@ public function getNextRunDate(): \DateTime
/**
* Get the previous run date
+ * @throws Exception
*/
public function getPreviousRunDate(): \DateTime
{
diff --git a/src/Cron/Helpers/cron.php b/src/Cron/Helpers/cron.php
index feb3c925f..b83d57f69 100644
--- a/src/Cron/Helpers/cron.php
+++ b/src/Cron/Helpers/cron.php
@@ -12,6 +12,8 @@
* @since 3.0.0
*/
+use Quantum\Cron\Exceptions\CronException;
+use Quantum\Di\Exceptions\DiException;
use Quantum\Cron\CronManager;
use Quantum\Cron\CronTask;
use Quantum\Cron\Schedule;
@@ -21,7 +23,8 @@
/**
* Resolve cron configuration value
* @param mixed $default
- * @return mixed|null
+ * @return mixed
+ * @throws DiException|ReflectionException
*/
function cron_config(string $key, $default = null)
{
@@ -32,7 +35,7 @@ function cron_config(string $key, $default = null)
if (!config()->has('cron')) {
config()->import(new Setup('config', 'cron'));
}
- } catch (\Throwable $exception) {
+ } catch (Throwable $exception) {
// Ignore missing cron config file and rely on defaults
}
@@ -56,7 +59,7 @@ function cron_manager(?string $cronDirectory = null): CronManager
if (!function_exists('cron_task')) {
/**
* Create a new cron task
- * @throws \Quantum\Cron\Exceptions\CronException
+ * @throws CronException
*/
function cron_task(string $name, string $expression, callable $callback): CronTask
{
diff --git a/src/Csrf/Csrf.php b/src/Csrf/Csrf.php
index e4614afec..5c47589ef 100644
--- a/src/Csrf/Csrf.php
+++ b/src/Csrf/Csrf.php
@@ -41,8 +41,6 @@ class Csrf
*/
public const TOKEN_KEY = 'csrf-token';
- private static ?Csrf $instance = null;
-
private Session $storage;
private Hasher $hasher;
@@ -53,24 +51,12 @@ class Csrf
* @throws ReflectionException
* @throws BaseException
*/
- private function __construct()
+ public function __construct()
{
$this->storage = session();
$this->hasher = new Hasher();
}
- /**
- * Csrf instance
- */
- public static function getInstance(): Csrf
- {
- if (self::$instance === null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
-
/**
* Generates the CSRF token or returns the previously generated one
*/
diff --git a/src/Csrf/Helpers/csrf.php b/src/Csrf/Helpers/csrf.php
index ccce8dba6..9047e57d9 100644
--- a/src/Csrf/Helpers/csrf.php
+++ b/src/Csrf/Helpers/csrf.php
@@ -15,13 +15,18 @@
use Quantum\App\Exceptions\BaseException;
use Quantum\App\Exceptions\AppException;
use Quantum\Csrf\Csrf;
+use Quantum\Di\Di;
/**
* Gets the Csrf instance
*/
function csrf(): Csrf
{
- return Csrf::getInstance();
+ if (!Di::isRegistered(Csrf::class)) {
+ Di::register(Csrf::class);
+ }
+
+ return Di::get(Csrf::class);
}
/**
diff --git a/src/Database/Adapters/Idiorm/IdiormDbal.php b/src/Database/Adapters/Idiorm/IdiormDbal.php
index 1106fd415..056564226 100644
--- a/src/Database/Adapters/Idiorm/IdiormDbal.php
+++ b/src/Database/Adapters/Idiorm/IdiormDbal.php
@@ -30,6 +30,8 @@
use InvalidArgumentException;
use ORM;
use PDO;
+use Quantum\Di\Exceptions\DiException;
+use ReflectionException;
/**
* Class IdiormDbal
@@ -257,6 +259,7 @@ protected function updateOrmModel(ORM $ormModel)
/**
* @param array $config
* @return array
+ * @throws DiException|ReflectionException
*/
protected static function getBaseConfig(string $driver, array $config): array
{
diff --git a/src/Database/Adapters/Idiorm/IdiormPatch.php b/src/Database/Adapters/Idiorm/IdiormPatch.php
index 008635ae4..3bca280ce 100644
--- a/src/Database/Adapters/Idiorm/IdiormPatch.php
+++ b/src/Database/Adapters/Idiorm/IdiormPatch.php
@@ -16,8 +16,8 @@
namespace Quantum\Database\Adapters\Idiorm;
-use ORM;
use RuntimeException;
+use ORM;
/**
* Class IdiormPatch
diff --git a/src/Database/Adapters/Idiorm/Statements/Criteria.php b/src/Database/Adapters/Idiorm/Statements/Criteria.php
index 8f09c4cae..a24a905ee 100644
--- a/src/Database/Adapters/Idiorm/Statements/Criteria.php
+++ b/src/Database/Adapters/Idiorm/Statements/Criteria.php
@@ -18,6 +18,7 @@
use Quantum\Database\Exceptions\DatabaseException;
use Quantum\Database\Contracts\DbalInterface;
+use Quantum\App\Exceptions\BaseException;
/**
* Trait Criteria
@@ -27,7 +28,7 @@ trait Criteria
{
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public function criteria(string $column, string $operator, $value = null): DbalInterface
{
@@ -41,7 +42,7 @@ public function criteria(string $column, string $operator, $value = null): DbalI
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public function criterias(...$criterias): DbalInterface
{
@@ -58,7 +59,7 @@ public function criterias(...$criterias): DbalInterface
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public function having(string $column, string $operator, ?string $value = null): DbalInterface
{
@@ -73,7 +74,7 @@ public function having(string $column, string $operator, ?string $value = null):
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public function isNull(string $column): DbalInterface
{
@@ -83,7 +84,7 @@ public function isNull(string $column): DbalInterface
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public function isNotNull(string $column): DbalInterface
{
@@ -94,8 +95,8 @@ public function isNotNull(string $column): DbalInterface
/**
* Adds Criteria
* @param mixed $value
- * @throws DatabaseException
* @return void
+ * @throws DatabaseException|BaseException
*/
protected function addCriteria(string $column, string $operator, $value, ?string $func = null)
{
@@ -111,8 +112,8 @@ protected function addCriteria(string $column, string $operator, $value, ?string
/**
* Adds one or more OR criteria in brackets
* @param array $orCriterias
- * @throws DatabaseException
* @return void
+ * @throws DatabaseException|BaseException
*/
protected function orCriteria(array $orCriterias)
{
diff --git a/src/Database/Adapters/Idiorm/Statements/Join.php b/src/Database/Adapters/Idiorm/Statements/Join.php
index ddb1dd446..a366c0789 100644
--- a/src/Database/Adapters/Idiorm/Statements/Join.php
+++ b/src/Database/Adapters/Idiorm/Statements/Join.php
@@ -77,8 +77,7 @@ public function rightJoin(string $table, array $constraint, ?string $tableAlias
/**
* @inheritDoc
- * @throws BaseException
- * @throws ModelException
+ * @throws ModelException|BaseException
*/
public function joinTo(DbModel $relatedModel, bool $switch = true): DbalInterface
{
diff --git a/src/Database/Adapters/Idiorm/Statements/Model.php b/src/Database/Adapters/Idiorm/Statements/Model.php
index 425704220..175762a1e 100644
--- a/src/Database/Adapters/Idiorm/Statements/Model.php
+++ b/src/Database/Adapters/Idiorm/Statements/Model.php
@@ -16,6 +16,7 @@
namespace Quantum\Database\Adapters\Idiorm\Statements;
+use Quantum\App\Exceptions\BaseException;
use Quantum\Database\Exceptions\DatabaseException;
use Quantum\Database\Contracts\DbalInterface;
@@ -27,7 +28,7 @@ trait Model
{
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public function create(): DbalInterface
{
diff --git a/src/Database/Adapters/Idiorm/Statements/Query.php b/src/Database/Adapters/Idiorm/Statements/Query.php
index 15557a987..db553b5cc 100644
--- a/src/Database/Adapters/Idiorm/Statements/Query.php
+++ b/src/Database/Adapters/Idiorm/Statements/Query.php
@@ -17,6 +17,7 @@
namespace Quantum\Database\Adapters\Idiorm\Statements;
use Quantum\Database\Exceptions\DatabaseException;
+use Quantum\App\Exceptions\BaseException;
use PDOStatement;
use PDOException;
@@ -28,7 +29,7 @@ trait Query
{
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public static function execute(string $query, array $parameters = []): bool
{
@@ -48,7 +49,7 @@ public static function execute(string $query, array $parameters = []): bool
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public static function query(string $query, array $parameters = []): array
{
@@ -70,7 +71,7 @@ public static function query(string $query, array $parameters = []): array
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public static function lastQuery(): ?string
{
@@ -83,7 +84,7 @@ public static function lastQuery(): ?string
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public static function lastStatement(): object
{
@@ -96,7 +97,7 @@ public static function lastStatement(): object
/**
* @inheritDoc
- * @throws DatabaseException
+ * @throws DatabaseException|BaseException
*/
public static function queryLog(): array
{
@@ -109,8 +110,8 @@ public static function queryLog(): array
/**
* Fetches columns of the table
- * @throws DatabaseException
* @return array
+ * @throws DatabaseException|BaseException
*/
public static function fetchColumns(string $table): array
{
diff --git a/src/Database/Adapters/Sleekdb/SleekDbal.php b/src/Database/Adapters/Sleekdb/SleekDbal.php
index 9e2e6af5a..1cd37d493 100644
--- a/src/Database/Adapters/Sleekdb/SleekDbal.php
+++ b/src/Database/Adapters/Sleekdb/SleekDbal.php
@@ -120,7 +120,7 @@ class SleekDbal implements DbalInterface
* Hidden fields
* @var array
*/
- public $hidden = [];
+ public array $hidden = [];
/**
* ORM Model
diff --git a/src/Database/Adapters/Sleekdb/Statements/Model.php b/src/Database/Adapters/Sleekdb/Statements/Model.php
index 5bd430a7a..46496aa73 100644
--- a/src/Database/Adapters/Sleekdb/Statements/Model.php
+++ b/src/Database/Adapters/Sleekdb/Statements/Model.php
@@ -82,7 +82,7 @@ public function save(): bool
* @throws DatabaseException
* @throws IOException
* @throws InvalidArgumentException
- * @throws InvalidConfigurationException
+ * @throws InvalidConfigurationException|BaseException
*/
public function delete(): bool
{
@@ -96,7 +96,7 @@ public function delete(): bool
* @throws IOException
* @throws InvalidArgumentException
* @throws InvalidConfigurationException
- * @throws ModelException
+ * @throws ModelException|BaseException
*/
public function deleteMany(): bool
{
diff --git a/src/Database/Database.php b/src/Database/Database.php
index c0a1e546a..0b6c2c1a0 100644
--- a/src/Database/Database.php
+++ b/src/Database/Database.php
@@ -50,11 +50,6 @@ class Database
*/
private $configs;
- /**
- * Database instance
- */
- private static ?Database $instance = null;
-
private string $ormClass;
/**
@@ -63,7 +58,7 @@ class Database
* @throws DiException
* @throws ReflectionException
*/
- private function __construct()
+ public function __construct()
{
if (!config()->has('database')) {
config()->import(new Setup('config', 'database'));
@@ -80,18 +75,6 @@ private function __construct()
}
}
- /**
- * Get Instance
- */
- public static function getInstance(): Database
- {
- if (self::$instance === null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
-
/**
* Gets the ORM class
*/
diff --git a/src/Database/Factories/TableFactory.php b/src/Database/Factories/TableFactory.php
index e083b4168..8439f250c 100644
--- a/src/Database/Factories/TableFactory.php
+++ b/src/Database/Factories/TableFactory.php
@@ -19,6 +19,7 @@
use Quantum\Database\Exceptions\DatabaseException;
use Quantum\Database\Schemas\Table;
use Quantum\Database\Database;
+use Exception;
/**
* Class TableFactory
@@ -87,7 +88,7 @@ public function checkTableExists(string $name): bool
{
try {
Database::query('SELECT 1 FROM ' . $name);
- } catch (DatabaseException $e) {
+ } catch (Exception $e) {
return false;
}
diff --git a/src/Database/Traits/RelationalTrait.php b/src/Database/Traits/RelationalTrait.php
index 2b2f05371..efabbc259 100644
--- a/src/Database/Traits/RelationalTrait.php
+++ b/src/Database/Traits/RelationalTrait.php
@@ -16,7 +16,10 @@
namespace Quantum\Database\Traits;
-use Quantum\Database\Exceptions\DatabaseException;
+use Quantum\Database\Database;
+use Quantum\Di\Di;
+use Quantum\Di\Exceptions\DiException;
+use ReflectionException;
/**
* Trait RelationalTrait
@@ -27,7 +30,7 @@ trait RelationalTrait
/**
* Raw execute
* @param array $parameters
- * @throws DatabaseException
+ * @throws DiException|ReflectionException
*/
public static function execute(string $query, array $parameters = []): bool
{
@@ -38,7 +41,7 @@ public static function execute(string $query, array $parameters = []): bool
* Raw query
* @param array $parameters
* @return array
- * @throws DatabaseException
+ * @throws DiException|ReflectionException
*/
public static function query(string $query, array $parameters = []): array
{
@@ -49,7 +52,7 @@ public static function query(string $query, array $parameters = []): array
* Fetches table columns
* @param array $parameters
* @return array
- * @throws DatabaseException
+ * @throws DiException|ReflectionException
*/
public static function fetchColumns(string $query, array $parameters = []): array
{
@@ -58,7 +61,7 @@ public static function fetchColumns(string $query, array $parameters = []): arra
/**
* Gets the last query executed
- * @throws DatabaseException
+ * @throws DiException|ReflectionException
*/
public static function lastQuery(): ?string
{
@@ -69,7 +72,7 @@ public static function lastQuery(): ?string
* Get an array containing all the queries
* run on a specified connection up to now.
* @return array
- * @throws DatabaseException
+ * @throws DiException|ReflectionException
*/
public static function queryLog(): array
{
@@ -80,10 +83,14 @@ public static function queryLog(): array
* Resolves the requested query
* @param array $parameters
* @return mixed
- * @throws DatabaseException
+ * @throws DiException|ReflectionException
*/
protected static function resolveQuery(string $method, string $query = '', array $parameters = [])
{
- return self::getInstance()->getOrmClass()::$method($query, $parameters);
+ if (!Di::isRegistered(Database::class)) {
+ Di::register(Database::class);
+ }
+
+ return Di::get(Database::class)->getOrmClass()::$method($query, $parameters);
}
}
diff --git a/src/Database/Traits/TransactionTrait.php b/src/Database/Traits/TransactionTrait.php
index d243e7cfe..c88e63569 100644
--- a/src/Database/Traits/TransactionTrait.php
+++ b/src/Database/Traits/TransactionTrait.php
@@ -18,6 +18,9 @@
use Quantum\Database\Exceptions\DatabaseException;
use Quantum\App\Exceptions\BaseException;
+use Quantum\Database\Database;
+use ReflectionException;
+use Quantum\Di\Di;
use Throwable;
/**
@@ -28,7 +31,7 @@ trait TransactionTrait
{
/**
* Begins a transaction
- * @throws BaseException
+ * @throws BaseException|ReflectionException
*/
public static function beginTransaction(): void
{
@@ -47,7 +50,7 @@ public static function commit(): void
/**
* Rolls back a transaction
- * @throws BaseException
+ * @throws BaseException|ReflectionException
*/
public static function rollback(): void
{
@@ -57,11 +60,15 @@ public static function rollback(): void
/**
* Resolves the transaction method call
* @return mixed
- * @throws BaseException
+ * @throws BaseException|ReflectionException
*/
protected static function resolveTransaction(string $method)
{
- $db = self::getInstance()->getOrmClass();
+ if (!Di::isRegistered(Database::class)) {
+ Di::register(Database::class);
+ }
+
+ $db = Di::get(Database::class)->getOrmClass();
if (!method_exists($db, $method)) {
throw DatabaseException::methodNotSupported($method, self::class);
diff --git a/src/Debugger/Debugger.php b/src/Debugger/Debugger.php
index 8f2419e64..0c28d770f 100644
--- a/src/Debugger/Debugger.php
+++ b/src/Debugger/Debugger.php
@@ -21,8 +21,10 @@
use DebugBar\DataCollector\MessagesCollector;
use DebugBar\DataCollector\PhpInfoCollector;
use DebugBar\DataCollector\MemoryCollector;
+use Quantum\Di\Exceptions\DiException;
use DebugBar\JavascriptRenderer;
use DebugBar\DebugBarException;
+use ReflectionException;
use DebugBar\DebugBar;
/**
@@ -62,8 +64,6 @@ class Debugger
*/
private DebuggerStore $store;
- private static ?Debugger $instance = null;
-
/**
* DebugBar instance
*/
@@ -80,39 +80,24 @@ class Debugger
private string $customCss = 'custom_debugbar.css';
/**
- * Debugger constructor.
* @param array $collectors
* @throws DebugBarException
*/
- public function __construct(DebuggerStore $store, DebugBar $debugBar, array $collectors = [])
+ public function __construct(?DebuggerStore $store = null, ?DebugBar $debugBar = null, array $collectors = [])
{
- $this->store = $store;
- $this->debugBar = $debugBar;
+ $this->store = $store ?? new DebuggerStore();
+ $this->debugBar = $debugBar ?? new DebugBar();
+
+ $collectors = $collectors ?: self::getDefaultCollectors();
foreach ($collectors as $collector) {
$this->debugBar->addCollector($collector);
}
}
- /**
- * @param array $collectors
- * @throws DebugBarException
- */
- public static function getInstance(?DebuggerStore $store = null, ?DebugBar $debugBar = null, ?array $collectors = []): Debugger
- {
- if (self::$instance === null) {
- $debugBar ??= new DebugBar();
- $store ??= new DebuggerStore();
- $collectors = $collectors ?: self::getDefaultCollectors();
-
- self::$instance = new self($store, $debugBar, $collectors);
- }
-
- return self::$instance;
- }
-
/**
* Checks if debug bar enabled
+ * @throws DiException|ReflectionException
*/
public function isEnabled(): bool
{
@@ -179,7 +164,6 @@ public function render(): string
/**
* Creates a tab
- * @return void
* @throws DebugBarException
*/
protected function createTab(string $type): void
diff --git a/src/Di/Di.php b/src/Di/Di.php
index 03798c074..bb2aab9f8 100644
--- a/src/Di/Di.php
+++ b/src/Di/Di.php
@@ -17,301 +17,48 @@
namespace Quantum\Di;
use Quantum\Di\Exceptions\DiException;
+use Quantum\App\App;
use ReflectionException;
-use ReflectionParameter;
-use ReflectionFunction;
-use ReflectionMethod;
-use ReflectionClass;
-use Closure;
/**
* Di Class
+ *
+ * Static facade that delegates all calls to the DiContainer
+ * owned by AppContext. Preserves the existing static API
+ * for full backward compatibility.
+ *
* @package Quantum/Di
+ * @method static void registerDependencies(array $dependencies)
+ * @method static void register(string $concrete, ?string $abstract = null)
+ * @method static bool isRegistered(string $abstract)
+ * @method static bool has(string $abstract)
+ * @method static void set(string $abstract, object $instance, bool $override = true)
+ * @method static mixed get(string $dependency, array $args = [])
+ * @method static mixed create(string $dependency, array $args = [])
+ * @method static array autowire(callable $entry, array $args = [])
+ * @method static void resetContainer()
*/
class Di
{
/**
- * @var array
- */
- private static array $dependencies = [];
-
- /**
- * @var array
- */
- private static array $container = [];
-
- /**
- * @var array
- */
- private static array $resolving = [];
-
- /**
- * Register dependencies
- * @param array $dependencies
- * @throws DiException
- */
- public static function registerDependencies(array $dependencies): void
- {
- foreach ($dependencies as $abstract => $concrete) {
- if (!self::isRegistered($abstract)) {
- self::register($concrete, $abstract);
- }
- }
- }
-
- /**
- * Registers new dependency
- * @throws DiException
- */
- public static function register(string $concrete, ?string $abstract = null): void
- {
- $key = $abstract ?? $concrete;
-
- if (isset(self::$dependencies[$key])) {
- throw DiException::dependencyAlreadyRegistered($key);
- }
-
- if (!class_exists($concrete)) {
- throw DiException::dependencyNotInstantiable($concrete);
- }
-
- if ($abstract !== null && !class_exists($abstract) && !interface_exists($abstract)) {
- throw DiException::invalidAbstractDependency($abstract);
- }
-
- self::$dependencies[$key] = $concrete;
- }
-
- /**
- * Checks if a dependency registered
- */
- public static function isRegistered(string $abstract): bool
- {
- return isset(self::$dependencies[$abstract]);
- }
-
- /**
- * Sets an instance into container
- * @template T of object
- * @param class-string $abstract
- * @param T $instance
- * @throws DiException
- */
- public static function set(string $abstract, object $instance, bool $override = true): void
- {
- if (!class_exists($abstract) && !interface_exists($abstract)) {
- throw DiException::invalidAbstractDependency($abstract);
- }
-
- if (!is_a($instance, $abstract)) {
- throw DiException::invalidAbstractDependency($abstract);
- }
-
- if (isset(self::$container[$abstract])) {
- throw DiException::dependencyAlreadyRegistered($abstract);
- }
-
- if (!$override && isset(self::$dependencies[$abstract])) {
- throw DiException::dependencyAlreadyRegistered($abstract);
- }
-
- if (!isset(self::$dependencies[$abstract])) {
- self::$dependencies[$abstract] = get_class($instance);
- }
-
- self::$container[$abstract] = $instance;
- }
-
- /**
- * Retrieves a shared instance of the given dependency.
- * @template T of object
- * @param class-string $dependency
- * @param array $args
- * @return T
- * @throws DiException|ReflectionException
+ * Gets the current container instance from AppContext
*/
- public static function get(string $dependency, array $args = [])
+ public static function getCurrent(): DiContainer
{
- if (!self::isRegistered($dependency)) {
- throw DiException::dependencyNotRegistered($dependency);
- }
-
- return self::resolve($dependency, $args, true);
- }
-
- /**
- * Creates new instance of the given dependency.
- * @template T of object
- * @param class-string $dependency
- * @param array $args
- * @return T
- * @throws DiException|ReflectionException
- */
- public static function create(string $dependency, array $args = [])
- {
- if (!self::isRegistered($dependency)) {
- self::register($dependency);
- }
-
- return self::resolve($dependency, $args, false);
+ return App::getContext()->getContainer();
}
/**
- * Autowire callable parameters
- * @param array $args
- * @return array
- * @throws DiException
- * @throws ReflectionException
- */
- public static function autowire(callable $entry, array $args = []): array
- {
- if ($entry instanceof Closure) {
- $reflection = new ReflectionFunction($entry);
- } elseif (is_array($entry)) {
- [$target, $method] = $entry;
- $reflection = new ReflectionMethod($target, $method);
- } else {
- throw DiException::invalidCallable();
- }
-
- return self::resolveParameters($reflection->getParameters(), $args);
- }
-
- public static function reset(): void
- {
- self::$dependencies = [];
- self::resetContainer();
- }
-
- public static function resetContainer(): void
- {
- self::$container = [];
- self::$resolving = [];
- }
-
- /**
- * Resolves the dependency
- * @param array $args
- * @return mixed|object
- * @throws DiException|ReflectionException
- */
- private static function resolve(string $abstract, array $args = [], bool $singleton = true)
- {
- self::checkCircularDependency($abstract);
- self::$resolving[$abstract] = true;
-
- try {
- $concrete = self::$dependencies[$abstract];
-
- if ($singleton) {
- if (!isset(self::$container[$abstract])) {
- self::$container[$abstract] = self::instantiate($concrete, $args);
- }
- return self::$container[$abstract];
- }
-
- return self::instantiate($concrete, $args);
-
- } finally {
- unset(self::$resolving[$abstract]);
- }
- }
-
- /**
- * Instantiates the dependency
- * @param class-string $concrete
- * @param array $args
+ * @param array $arguments
* @return mixed
- * @throws ReflectionException|DiException
- */
- private static function instantiate(string $concrete, array $args = [])
- {
- $class = new ReflectionClass($concrete);
- $constructor = $class->getConstructor();
-
- $params = $constructor
- ? self::resolveParameters($constructor->getParameters(), $args)
- : [];
-
- return new $concrete(...$params);
- }
-
- /**
- * Resolve parameter list
- * @param array $parameters
- * @param array $args
- * @return array
- * @throws DiException
- */
- private static function resolveParameters(array $parameters, array &$args = []): array
- {
- $resolved = [];
-
- foreach ($parameters as $param) {
- $resolved[] = self::resolveParameter($param, $args);
- }
-
- return $resolved;
- }
-
- /**
- * Resolve single parameter
- * @param array $args
- * @return array|mixed|object|null
* @throws DiException|ReflectionException
*/
- private static function resolveParameter(ReflectionParameter $param, array &$args = [])
+ public static function __callStatic(string $method, array $arguments)
{
- $type = null;
-
- if ($param->getType() instanceof \ReflectionNamedType) {
- $type = $param->getType()->getName();
- }
-
- // prefer registered dependency
- if ($type !== null && isset(self::$dependencies[$type])) {
- /** @var class-string $type */
- return self::get($type);
+ if (!method_exists(self::getCurrent(), $method)) {
+ throw DiException::invalidCallable($method);
}
- // fallback instantiable class
- if ($type !== null && self::instantiable($type)) {
- /** @var class-string $type */
- return self::create($type);
- }
-
- // array param receives remaining args
- if ($type === 'array') {
- return $args;
- }
-
- // positional args fallback
- if ($args !== []) {
- return array_shift($args);
- }
-
- return $param->isDefaultValueAvailable()
- ? $param->getDefaultValue()
- : null;
- }
-
- /**
- * Checks if the class is instantiable
- */
- protected static function instantiable(string $class): bool
- {
- return class_exists($class)
- && (new ReflectionClass($class))->isInstantiable();
- }
-
- /**
- * @throws DiException
- */
- private static function checkCircularDependency(string $abstract): void
- {
- if (isset(self::$resolving[$abstract])) {
- $chain = implode(' -> ', array_keys(self::$resolving)) . ' -> ' . $abstract;
- throw DiException::circularDependency($chain);
- }
+ return self::getCurrent()->$method(...$arguments);
}
}
diff --git a/src/Di/DiContainer.php b/src/Di/DiContainer.php
new file mode 100644
index 000000000..a93fa4da0
--- /dev/null
+++ b/src/Di/DiContainer.php
@@ -0,0 +1,324 @@
+
+ * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
+ * @link http://quantum.softberg.org/
+ * @since 3.0.0
+ */
+
+namespace Quantum\Di;
+
+use Quantum\Di\Exceptions\DiException;
+use ReflectionException;
+use ReflectionParameter;
+use ReflectionFunction;
+use ReflectionMethod;
+use ReflectionClass;
+use Closure;
+
+/**
+ * DiContainer Class
+ *
+ * Instance-based dependency injection container.
+ * Holds all dependency registrations and resolved instances for a single application execution.
+ *
+ * @package Quantum/Di
+ */
+class DiContainer
+{
+ /**
+ * @var array
+ */
+ private array $dependencies = [];
+
+ /**
+ * @var array
+ */
+ private array $container = [];
+
+ /**
+ * @var array
+ */
+ private array $resolving = [];
+
+ /**
+ * Register dependencies
+ * @param array $dependencies
+ * @throws DiException
+ */
+ public function registerDependencies(array $dependencies): void
+ {
+ foreach ($dependencies as $abstract => $concrete) {
+ if (!$this->isRegistered($abstract)) {
+ $this->register($concrete, $abstract);
+ }
+ }
+ }
+
+ /**
+ * Registers new dependency
+ * @throws DiException
+ */
+ public function register(string $concrete, ?string $abstract = null): void
+ {
+ $key = $abstract ?? $concrete;
+
+ if (isset($this->dependencies[$key])) {
+ throw DiException::dependencyAlreadyRegistered($key);
+ }
+
+ if (!class_exists($concrete)) {
+ throw DiException::dependencyNotInstantiable($concrete);
+ }
+
+ if ($abstract !== null && !class_exists($abstract) && !interface_exists($abstract)) {
+ throw DiException::invalidAbstractDependency($abstract);
+ }
+
+ $this->dependencies[$key] = $concrete;
+ }
+
+ /**
+ * Checks if a dependency registered
+ */
+ public function isRegistered(string $abstract): bool
+ {
+ return isset($this->dependencies[$abstract]);
+ }
+
+ /**
+ * Checks if an instance exists in the container
+ */
+ public function has(string $abstract): bool
+ {
+ return isset($this->container[$abstract]);
+ }
+
+ /**
+ * Sets an instance into container
+ * @template T of object
+ * @param class-string $abstract
+ * @param T $instance
+ * @throws DiException
+ */
+ public function set(string $abstract, object $instance, bool $override = true): void
+ {
+ if (!class_exists($abstract) && !interface_exists($abstract)) {
+ throw DiException::invalidAbstractDependency($abstract);
+ }
+
+ if (!is_a($instance, $abstract)) {
+ throw DiException::invalidAbstractDependency($abstract);
+ }
+
+ if (isset($this->container[$abstract])) {
+ throw DiException::dependencyAlreadyRegistered($abstract);
+ }
+
+ if (!$override && isset($this->dependencies[$abstract])) {
+ throw DiException::dependencyAlreadyRegistered($abstract);
+ }
+
+ if (!isset($this->dependencies[$abstract])) {
+ $this->dependencies[$abstract] = get_class($instance);
+ }
+
+ $this->container[$abstract] = $instance;
+ }
+
+ /**
+ * Retrieves a shared instance of the given dependency.
+ * @template T of object
+ * @param class-string $dependency
+ * @param array $args
+ * @return T
+ * @throws DiException|ReflectionException
+ */
+ public function get(string $dependency, array $args = [])
+ {
+ if (!$this->isRegistered($dependency)) {
+ throw DiException::dependencyNotRegistered($dependency);
+ }
+
+ return $this->resolve($dependency, $args, true);
+ }
+
+ /**
+ * Creates new instance of the given dependency.
+ * @template T of object
+ * @param class-string $dependency
+ * @param array $args
+ * @return T
+ * @throws DiException|ReflectionException
+ */
+ public function create(string $dependency, array $args = [])
+ {
+ if (!$this->isRegistered($dependency)) {
+ $this->register($dependency);
+ }
+
+ return $this->resolve($dependency, $args, false);
+ }
+
+ /**
+ * Autowire callable parameters
+ * @param array $args
+ * @return array
+ * @throws DiException|ReflectionException
+ */
+ public function autowire(callable $entry, array $args = []): array
+ {
+ if ($entry instanceof Closure) {
+ $reflection = new ReflectionFunction($entry);
+ } elseif (is_array($entry)) {
+ [$target, $method] = $entry;
+ $reflection = new ReflectionMethod($target, $method);
+ } else {
+ throw DiException::invalidCallable();
+ }
+
+ return $this->resolveParameters($reflection->getParameters(), $args);
+ }
+
+ public function reset(): void
+ {
+ $this->dependencies = [];
+ $this->resetContainer();
+ }
+
+ public function resetContainer(): void
+ {
+ $this->container = [];
+ $this->resolving = [];
+ }
+
+ /**
+ * Resolves the dependency
+ * @param array $args
+ * @return mixed|object
+ * @throws DiException|ReflectionException
+ */
+ private function resolve(string $abstract, array $args = [], bool $singleton = true)
+ {
+ $this->checkCircularDependency($abstract);
+ $this->resolving[$abstract] = true;
+
+ try {
+ $concrete = $this->dependencies[$abstract];
+
+ if ($singleton) {
+ if (!isset($this->container[$abstract])) {
+ $this->container[$abstract] = $this->instantiate($concrete, $args);
+ }
+ return $this->container[$abstract];
+ }
+
+ return $this->instantiate($concrete, $args);
+
+ } finally {
+ unset($this->resolving[$abstract]);
+ }
+ }
+
+ /**
+ * Instantiates the dependency
+ * @param class-string $concrete
+ * @param array $args
+ * @return mixed
+ * @throws ReflectionException|DiException
+ */
+ private function instantiate(string $concrete, array $args = [])
+ {
+ $class = new ReflectionClass($concrete);
+ $constructor = $class->getConstructor();
+
+ $params = $constructor
+ ? $this->resolveParameters($constructor->getParameters(), $args)
+ : [];
+
+ return new $concrete(...$params);
+ }
+
+ /**
+ * Resolve parameter list
+ * @param array $parameters
+ * @param array $args
+ * @return array
+ * @throws DiException|ReflectionException
+ */
+ private function resolveParameters(array $parameters, array &$args = []): array
+ {
+ $resolved = [];
+
+ foreach ($parameters as $param) {
+ $resolved[] = $this->resolveParameter($param, $args);
+ }
+
+ return $resolved;
+ }
+
+ /**
+ * Resolve single parameter
+ * @param array $args
+ * @return array|mixed|object|null
+ * @throws DiException|ReflectionException
+ */
+ private function resolveParameter(ReflectionParameter $param, array &$args = [])
+ {
+ $type = null;
+
+ if ($param->getType() instanceof \ReflectionNamedType) {
+ $type = $param->getType()->getName();
+ }
+
+ if ($type !== null && isset($this->dependencies[$type])) {
+ /** @var class-string $type */
+ return $this->get($type);
+ }
+
+ if ($type !== null && $this->instantiable($type)) {
+ /** @var class-string $type */
+ return $this->create($type);
+ }
+
+ if ($type === 'array') {
+ return $args;
+ }
+
+ if ($args !== []) {
+ return array_shift($args);
+ }
+
+ return $param->isDefaultValueAvailable()
+ ? $param->getDefaultValue()
+ : null;
+ }
+
+ /**
+ * Checks if the class is instantiable
+ */
+ private function instantiable(string $class): bool
+ {
+ return class_exists($class)
+ && (new ReflectionClass($class))->isInstantiable();
+ }
+
+ /**
+ * @throws DiException
+ */
+ private function checkCircularDependency(string $abstract): void
+ {
+ if (isset($this->resolving[$abstract])) {
+ $chain = implode(' -> ', array_keys($this->resolving)) . ' -> ' . $abstract;
+ throw DiException::circularDependency($chain);
+ }
+ }
+}
diff --git a/src/Encryption/Adapters/AsymmetricEncryptionAdapter.php b/src/Encryption/Adapters/AsymmetricEncryptionAdapter.php
index d42d01047..0953e500c 100644
--- a/src/Encryption/Adapters/AsymmetricEncryptionAdapter.php
+++ b/src/Encryption/Adapters/AsymmetricEncryptionAdapter.php
@@ -36,15 +36,9 @@ class AsymmetricEncryptionAdapter implements EncryptionInterface
*/
public const KEY_BITS = 1024;
- /**
- * @var string
- */
- private $publicKey;
+ private ?string $publicKey = null;
- /**
- * @var string
- */
- private $privateKey;
+ private ?string $privateKey = null;
/**
* @throws BaseException
diff --git a/src/Encryption/Adapters/SymmetricEncryptionAdapter.php b/src/Encryption/Adapters/SymmetricEncryptionAdapter.php
index 5d1aed224..2596000e8 100644
--- a/src/Encryption/Adapters/SymmetricEncryptionAdapter.php
+++ b/src/Encryption/Adapters/SymmetricEncryptionAdapter.php
@@ -20,6 +20,7 @@
use Quantum\Encryption\Exceptions\CryptorException;
use Quantum\App\Exceptions\BaseException;
use Quantum\App\Exceptions\AppException;
+use ReflectionException;
/**
* Class SymmetricEncryptionAdapter
@@ -32,13 +33,10 @@ class SymmetricEncryptionAdapter implements EncryptionInterface
*/
public const CIPHER_METHOD = 'aes-256-cbc';
- /**
- * @var string
- */
- private $appKey;
+ private string $appKey;
/**
- * @throws BaseException
+ * @throws BaseException|ReflectionException
*/
public function __construct()
{
@@ -53,6 +51,7 @@ public function __construct()
/**
* Encrypts the string
+ * @throws CryptorException
*/
public function encrypt(string $plain): string
{
@@ -97,6 +96,7 @@ public function decrypt(string $encrypted): string
/**
* Generates initialization vector
+ * @throws CryptorException
*/
private function generateIV(): string
{
diff --git a/src/Encryption/Factories/CryptorFactory.php b/src/Encryption/Factories/CryptorFactory.php
index a91293146..6a9609e5f 100644
--- a/src/Encryption/Factories/CryptorFactory.php
+++ b/src/Encryption/Factories/CryptorFactory.php
@@ -22,6 +22,8 @@
use Quantum\App\Exceptions\BaseException;
use Quantum\Encryption\Enums\CryptorType;
use Quantum\Encryption\Cryptor;
+use ReflectionException;
+use Quantum\Di\Di;
/**
* Class Cryptor
@@ -29,9 +31,6 @@
*/
class CryptorFactory
{
- /**
- * Supported adapters
- */
public const ADAPTERS = [
CryptorType::SYMMETRIC => SymmetricEncryptionAdapter::class,
CryptorType::ASYMMETRIC => AsymmetricEncryptionAdapter::class,
@@ -40,24 +39,36 @@ class CryptorFactory
/**
* @var array
*/
- private static array $instances = [];
+ private array $instances = [];
/**
- * @throws BaseException
+ * @throws BaseException|ReflectionException
*/
public static function get(string $type = CryptorType::SYMMETRIC): Cryptor
{
- if (!isset(self::$instances[$type])) {
- self::$instances[$type] = self::createInstance($type);
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve($type);
+ }
+
+ /**
+ * @throws BaseException
+ */
+ public function resolve(string $type = CryptorType::SYMMETRIC): Cryptor
+ {
+ if (!isset($this->instances[$type])) {
+ $this->instances[$type] = $this->createInstance($type);
}
- return self::$instances[$type];
+ return $this->instances[$type];
}
/**
* @throws BaseException
*/
- private static function createInstance(string $type): Cryptor
+ private function createInstance(string $type): Cryptor
{
if (!isset(self::ADAPTERS[$type])) {
throw CryptorException::adapterNotSupported($type);
diff --git a/src/Encryption/Helpers/encryption.php b/src/Encryption/Helpers/encryption.php
index e8194c25a..39b9bdefd 100644
--- a/src/Encryption/Helpers/encryption.php
+++ b/src/Encryption/Helpers/encryption.php
@@ -19,7 +19,7 @@
/**
* Encodes the data cryptographically
* @param mixed $data
- * @throws BaseException
+ * @throws BaseException|ReflectionException
*/
function crypto_encode($data, string $type = CryptorType::SYMMETRIC): string
{
@@ -30,7 +30,7 @@ function crypto_encode($data, string $type = CryptorType::SYMMETRIC): string
/**
* @return mixed|string
- * @throws BaseException
+ * @throws BaseException|ReflectionException
*/
function crypto_decode(string $encryptedData, string $type = CryptorType::SYMMETRIC)
{
diff --git a/src/Environment/Environment.php b/src/Environment/Environment.php
index ce4afe5c2..eaf6628e7 100644
--- a/src/Environment/Environment.php
+++ b/src/Environment/Environment.php
@@ -50,24 +50,7 @@ class Environment
private bool $loaded = false;
- private static string $appEnv = Env::PRODUCTION;
-
- /**
- * Instance of Environment
- */
- private static ?Environment $instance = null;
-
- /**
- * GetInstance
- */
- public static function getInstance(): Environment
- {
- if (self::$instance === null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
+ private string $appEnv = Env::PRODUCTION;
public function setMutable(bool $isMutable): Environment
{
@@ -77,10 +60,7 @@ public function setMutable(bool $isMutable): Environment
/**
* Loads environment variables from file
- * @throws BaseException
- * @throws EnvException
- * @throws DiException
- * @throws ReflectionException
+ * @throws EnvException|DiException|BaseException|ReflectionException
*/
public function load(Setup $setup): void
{
@@ -88,20 +68,24 @@ public function load(Setup $setup): void
return;
}
+ if (!Di::isRegistered(Loader::class)) {
+ Di::register(Loader::class);
+ }
+
$envConfig = Di::get(Loader::class)->setup($setup)->load();
$appEnv = $envConfig['app_env'] ?? Env::PRODUCTION;
$this->envFile = '.env' . ($appEnv !== Env::PRODUCTION ? ".$appEnv" : '');
- if (!fs()->exists($this->getEnvFilePath())) {
+ if (!file_exists($this->getEnvFilePath())) {
throw EnvException::fileNotFound($this->envFile);
}
$this->envContent = $this->loadDotenvFile();
$this->loaded = true;
- self::$appEnv = $appEnv;
+ $this->appEnv = $appEnv;
}
/**
@@ -109,7 +93,32 @@ public function load(Setup $setup): void
*/
public function getAppEnv(): string
{
- return self::$appEnv;
+ return $this->appEnv;
+ }
+
+ public function isProduction(): bool
+ {
+ return $this->appEnv === Env::PRODUCTION;
+ }
+
+ public function isStaging(): bool
+ {
+ return $this->appEnv === Env::STAGING;
+ }
+
+ public function isDevelopment(): bool
+ {
+ return $this->appEnv === Env::DEVELOPMENT;
+ }
+
+ public function isTesting(): bool
+ {
+ return $this->appEnv === Env::TESTING;
+ }
+
+ public function isLocal(): bool
+ {
+ return $this->appEnv === Env::LOCAL;
}
/**
@@ -136,7 +145,7 @@ public function getValue(string $key, $default = null)
*/
public function hasKey(string $key): bool
{
- return $this->findKeyRow($key) !== null;
+ return array_key_exists($key, $this->envContent);
}
/**
@@ -144,16 +153,16 @@ public function hasKey(string $key): bool
*/
public function getRow(string $key): ?string
{
- return $this->findKeyRow($key);
+ if (!array_key_exists($key, $this->envContent)) {
+ return null;
+ }
+
+ return $key . '=' . $this->envContent[$key];
}
/**
* Creates or updates the row in .env
- * @throws BaseException
- * @throws DiException
- * @throws EnvException
- * @throws ReflectionException
- * @throws ConfigException
+ * @throws EnvException|ConfigException|DiException|BaseException|ReflectionException
*/
public function updateRow(string $key, ?string $value): void
{
@@ -166,16 +175,16 @@ public function updateRow(string $key, ?string $value): void
}
$envFilePath = $this->getEnvFilePath();
- $row = $this->getRow($key);
- if ($row) {
+ if (array_key_exists($key, $this->envContent)) {
$envFileContent = fs()->get($envFilePath);
if (!is_string($envFileContent)) {
throw EnvException::fileNotFound($this->envFile);
}
- $envFileContent = preg_replace('/^' . preg_quote($row, '/') . '/m', $key . '=' . $value, $envFileContent);
+ $pattern = '/^' . preg_quote($key . '=' . $this->envContent[$key], '/') . '/m';
+ $envFileContent = preg_replace($pattern, $key . '=' . $value, $envFileContent);
fs()->put($envFilePath, (string) $envFileContent);
} else {
@@ -185,32 +194,12 @@ public function updateRow(string $key, ?string $value): void
$this->envContent[$key] = $value;
}
- /**
- * Finds the row by provided key
- */
- private function findKeyRow(string $key): ?string
- {
- foreach ($this->envContent as $index => $row) {
- if (preg_match('/^' . $key . '/', $index)) {
- return $key . '=' . preg_quote($row, '/');
- }
- }
-
- return null;
- }
-
/**
* @return array
*/
- private function loadDotenvFile(bool $forceMutableReload = false): array
+ private function loadDotenvFile(): array
{
- $baseDir = App::getBaseDir();
-
- $dotenv = ($forceMutableReload || $this->isMutable)
- ? Dotenv::createMutable($baseDir, $this->envFile)
- : Dotenv::createImmutable($baseDir, $this->envFile);
-
- $loadedVars = $dotenv->load();
+ $loadedVars = Dotenv::createArrayBacked(App::getBaseDir(), $this->envFile)->load();
return is_array($loadedVars) ? $loadedVars : [];
}
diff --git a/src/Environment/Helpers/env.php b/src/Environment/Helpers/env.php
index 6b8c259af..ed3967934 100644
--- a/src/Environment/Helpers/env.php
+++ b/src/Environment/Helpers/env.php
@@ -13,16 +13,31 @@
*/
use Quantum\Environment\Exceptions\EnvException;
+use Quantum\Di\Exceptions\DiException;
use Quantum\Environment\Environment;
+use Quantum\Di\Di;
+
+/**
+ * Gets the Environment instance from DI
+ * @throws DiException|\ReflectionException
+ */
+function environment(): Environment
+{
+ if (!Di::isRegistered(Environment::class)) {
+ Di::register(Environment::class);
+ }
+
+ return Di::get(Environment::class);
+}
/**
* Gets the value of an environment variable
* @param string $var
* @param mixed|null $default
* @return mixed
- * @throws EnvException
+ * @throws EnvException|DiException|\ReflectionException
*/
function env(string $var, $default = null)
{
- return Environment::getInstance()->getValue($var, $default);
+ return environment()->getValue($var, $default);
}
diff --git a/src/Environment/Helpers/server.php b/src/Environment/Helpers/server.php
index 652fce035..f8486b808 100644
--- a/src/Environment/Helpers/server.php
+++ b/src/Environment/Helpers/server.php
@@ -12,34 +12,35 @@
* @since 3.0.0
*/
+use Quantum\Di\Exceptions\DiException;
use Quantum\Environment\Server;
+use Quantum\Di\Di;
/**
- * Gets Server instance
+ * @throws DiException|ReflectionException
*/
function server(): Server
{
- return Server::getInstance();
+ if (!Di::isRegistered(Server::class)) {
+ Di::register(Server::class);
+ }
+
+ return Di::get(Server::class);
}
-/**
- * Gets user IP
- */
function get_user_ip(): ?string
{
- return Server::getInstance()->ip();
+ return server()->ip();
}
if (!function_exists('getallheaders')) {
/**
- * Get all headers
- * Built-in PHP function synonym of apache_request_headers()
- * Declaring here for Nginx server
* @return array
+ * @throws DiException|ReflectionException
*/
function getallheaders(): array
{
- return Server::getInstance()->getAllHeaders();
+ return server()->getAllHeaders();
}
}
diff --git a/src/Environment/Server.php b/src/Environment/Server.php
index 9cbc50b77..5128cd620 100644
--- a/src/Environment/Server.php
+++ b/src/Environment/Server.php
@@ -27,28 +27,11 @@ class Server
*/
private array $server;
- private static ?Server $instance = null;
-
- /**
- * Server constructor.
- */
- private function __construct()
+ public function __construct()
{
$this->server = $_SERVER;
}
- /**
- * Get Instance
- */
- public static function getInstance(): Server
- {
- if (self::$instance === null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
-
/**
* Flushes the server params
*/
@@ -74,10 +57,7 @@ public function get(string $key)
return $this->server[$key] ?? null;
}
- /**
- * @param string $key
- */
- public function has($key): bool
+ public function has(string $key): bool
{
return array_key_exists($key, $this->server);
}
diff --git a/src/Hook/Helpers/hook.php b/src/Hook/Helpers/hook.php
index 3a4d1b115..709d283ed 100644
--- a/src/Hook/Helpers/hook.php
+++ b/src/Hook/Helpers/hook.php
@@ -12,12 +12,19 @@
* @since 3.0.0
*/
+use Quantum\Di\Exceptions\DiException;
use Quantum\Hook\HookManager;
+use Quantum\Di\Di;
/**
* Gets the HookManager instance
+ * @throws DiException|ReflectionException
*/
function hook(): HookManager
{
- return HookManager::getInstance();
+ if (!Di::isRegistered(HookManager::class)) {
+ Di::register(HookManager::class);
+ }
+
+ return Di::get(HookManager::class);
}
diff --git a/src/Hook/HookManager.php b/src/Hook/HookManager.php
index 0a159c1ea..11f3c54f3 100644
--- a/src/Hook/HookManager.php
+++ b/src/Hook/HookManager.php
@@ -38,17 +38,12 @@ class HookManager
* Registered hooks store
* @var array>
*/
- private static array $store = [];
-
- private static ?HookManager $instance = null;
+ private array $store = [];
/**
- * @throws HookException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException|LoaderException
+ * @throws HookException|ConfigException|DiException|LoaderException|ReflectionException
*/
- private function __construct()
+ public function __construct()
{
if (!config()->has('hooks')) {
config()->import(new Setup('config', 'hooks'));
@@ -61,18 +56,6 @@ private function __construct()
}
}
- /**
- * HookManager instance
- */
- public static function getInstance(): HookManager
- {
- if (self::$instance == null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
-
/**
* Adds a new listener for a given hook
* @throws HookException
@@ -83,7 +66,7 @@ public function on(string $name, callable $function): void
throw HookException::unregisteredHookName($name);
}
- self::$store[$name][] = $function;
+ $this->store[$name][] = $function;
}
/**
@@ -97,8 +80,8 @@ public function fire(string $name, ?array $args = null): void
throw HookException::unregisteredHookName($name);
}
- foreach (self::$store[$name] as $index => $fn) {
- unset(self::$store[$name][$index]);
+ foreach ($this->store[$name] as $index => $fn) {
+ unset($this->store[$name][$index]);
$fn($args);
}
}
@@ -107,14 +90,13 @@ public function fire(string $name, ?array $args = null): void
* Gets all registered hooks
* @return array>
*/
- public static function getRegistered(): array
+ public function getRegistered(): array
{
- return self::$store;
+ return $this->store;
}
/**
* Registers new hook
- * @return void
* @throws HookException
*/
protected function register(string $name): void
@@ -123,7 +105,7 @@ protected function register(string $name): void
throw HookException::hookDuplicateName($name);
}
- self::$store[$name] = [];
+ $this->store[$name] = [];
}
/**
@@ -131,6 +113,6 @@ protected function register(string $name): void
*/
protected function exists(string $name): bool
{
- return array_key_exists($name, self::$store);
+ return array_key_exists($name, $this->store);
}
}
diff --git a/src/Http/Helpers/http.php b/src/Http/Helpers/http.php
index cb6bf96b5..2832d5db2 100644
--- a/src/Http/Helpers/http.php
+++ b/src/Http/Helpers/http.php
@@ -12,15 +12,42 @@
* @since 3.0.0
*/
+use Quantum\App\Exceptions\StopExecutionException;
use Quantum\Config\Exceptions\ConfigException;
use Quantum\App\Exceptions\BaseException;
use Quantum\Di\Exceptions\DiException;
use Quantum\App\Enums\ReservedKeys;
use Quantum\Http\Enums\ContentType;
use Quantum\Http\Enums\StatusCode;
-use DebugBar\DebugBarException;
use Quantum\Http\Response;
use Quantum\Http\Request;
+use Quantum\Di\Di;
+
+/**
+ * Gets the Request instance from DI
+ * @throws DiException|ReflectionException
+ */
+function request(): Request
+{
+ if (!Di::isRegistered(Request::class)) {
+ Di::register(Request::class);
+ }
+
+ return Di::get(Request::class);
+}
+
+/**
+ * Gets the Response instance from DI
+ * @throws DiException|ReflectionException
+ */
+function response(): Response
+{
+ if (!Di::isRegistered(Response::class)) {
+ Di::register(Response::class);
+ }
+
+ return Di::get(Response::class);
+}
/**
* Gets the base url
@@ -29,46 +56,42 @@
*/
function base_url(bool $withModulePrefix = false): string
{
- return Request::getBaseUrl($withModulePrefix);
+ return request()->getBaseUrl($withModulePrefix);
}
/**
* Gets the current url
+ * @throws DiException|ReflectionException
*/
function current_url(): string
{
- return Request::getCurrentUrl();
+ return request()->getCurrentUrl();
}
/**
* Redirect
+ * @throws StopExecutionException|DiException|ReflectionException
*/
function redirect(string $url, int $code = StatusCode::FOUND): void
{
- Response::redirect($url, $code);
+ response()->redirect($url, $code);
}
/**
* Redirect with data
* @param array $data
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function redirectWith(string $url, array $data, int $code = StatusCode::FOUND): void
{
session()->set(ReservedKeys::PREV_REQUEST, $data);
- Response::redirect($url, $code);
+ response()->redirect($url, $code);
}
/**
* Gets old input values after redirect
* @return mixed|null
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
- * @throws BaseException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function old(string $key)
{
@@ -92,33 +115,30 @@ function old(string $key)
/**
* Gets the referrer
+ * @throws DiException|ReflectionException
*/
function get_referrer(): ?string
{
- return Request::getReferrer();
+ return request()->getReferrer();
}
/**
* Handles page not found
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
- * @throws DebugBarException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function page_not_found(): void
{
- $acceptHeader = Response::getHeader('Accept');
+ $acceptHeader = response()->getHeader('Accept');
$isJson = $acceptHeader === ContentType::JSON;
if ($isJson) {
- Response::json(
+ response()->json(
['status' => 'error', 'message' => 'Page not found',],
StatusCode::NOT_FOUND
);
} else {
- Response::html(
+ response()->html(
partial('errors' . DS . StatusCode::NOT_FOUND),
StatusCode::NOT_FOUND
);
diff --git a/src/Http/Request.php b/src/Http/Request.php
index cd10eb0ce..daa4e6b4d 100644
--- a/src/Http/Request.php
+++ b/src/Http/Request.php
@@ -16,68 +16,245 @@
namespace Quantum\Http;
-use Quantum\Http\Request\HttpRequest;
+use Quantum\Config\Exceptions\ConfigException;
+use Quantum\Http\Exceptions\HttpException;
+use Quantum\App\Exceptions\BaseException;
+use Quantum\Http\Traits\Request\RawInput;
+use Quantum\Http\Traits\Request\Internal;
+use Quantum\Http\Traits\Request\Header;
+use Quantum\Http\Traits\Request\Params;
+use Quantum\Di\Exceptions\DiException;
+use Quantum\Http\Traits\Request\Query;
+use Quantum\Http\Traits\Request\Route;
+use Quantum\Http\Traits\Request\Body;
+use Quantum\Http\Traits\Request\File;
+use Quantum\Http\Traits\Request\Url;
+use Quantum\Environment\Server;
+use ReflectionException;
+use Quantum\Csrf\Csrf;
/**
* Class Request
* @package Quantum\Http
- * @method static void create(string $method, string $url, array $params = [], array $headers = [], array $file = null)
- * @method static void flush()
- * @method static string|null getMethod()
- * @method static void setMethod(string $method)
- * @method static bool isMethod(string $method)
- * @method static string getProtocol()
- * @method static void setProtocol($protocol)
- * @method static string getHost()
- * @method static void setHost($host)
- * @method static string getPort()
- * @method static void setPort($port)
- * @method static string|null getUri()
- * @method static void setUri($uri)
- * @method static string getQuery()
- * @method static string|null getQueryParam(string $key)
- * @method static void setQueryParam(string $key, string $value)
- * @method static void setQuery($query)
- * @method static bool has(string $key)
- * @method static mixed get(string $key, string $default = null, bool $raw = false)
- * @method static void set(string $key, $value)
- * @method static array all()
- * @method static void delete(string $key)
- * @method static bool hasFile(string $key)
- * @method static mixed getFile(string $key)
- * @method static bool hasHeader(string $key)
- * @method static string|null getHeader(string $key)
- * @method static void setHeader(string $key, $value)
- * @method static array allHeaders()
- * @method static void deleteHeader(string $key)
- * @method static string|null getSegment(int $number)
- * @method static array getAllSegments()
- * @method static string|null getCsrfToken()
- * @method static string|null getAuthorizationBearer()
- * @method static array|null getBasicAuthCredentials()
- * @method static bool isAjax()
- * @method static string|null getReferrer()
- * @mixin HttpRequest
*/
class Request
{
+ use Route;
+ use Header;
+ use Body;
+ use Url;
+ use Query;
+ use Params;
+ use File;
+ use RawInput;
+ use Internal;
+
+ /**
+ * Available methods
+ */
+ public const METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
+
+ /**
+ * Default port for HTTP
+ */
+ public const DEFAULT_HTTP_PORT = 80;
+
+ /**
+ * Default port for HTTPS
+ */
+ public const DEFAULT_HTTPS_PORT = 443;
+
+ /**
+ * Request method
+ */
+ private ?string $__method = null;
+
+ protected Server $server;
+
+ /**
+ * @throws ConfigException|DiException|BaseException|ReflectionException
+ */
+ public function __construct(?Server $server = null)
+ {
+ $this->server = $server ?? server();
+ $this->populateFromServer();
+ }
+
+ /**
+ * Flushes the request header, body and files
+ */
+ public function flush(): void
+ {
+ $this->__headers = [];
+ $this->__request = [];
+ $this->__files = [];
+ $this->__protocol = null;
+ $this->__host = null;
+ $this->__port = null;
+ $this->__uri = null;
+ $this->__query = null;
+ }
+
+ /**
+ * Re-reads method, headers, params and files from the current server state.
+ * @throws ConfigException|DiException|BaseException|ReflectionException
+ */
+ protected function populateFromServer(): void
+ {
+ $this->setServerInfo();
+ $this->setContentType();
+ $this->setRequestHeaders();
+
+ ['params' => $rawInputParams, 'files' => $rawInputFiles] = $this->getRawInputParams();
+
+ $this->setRequestParams($rawInputParams);
+ $this->setUploadedFiles($rawInputFiles);
+ }
+
+ /**
+ * Sets the merged request parameters
+ * @param array $params
+ */
+ public function setRequestParams(array $params): void
+ {
+ $this->__request = array_merge(
+ $this->getParams(),
+ $this->postParams(),
+ $this->jsonPayloadParams(),
+ $this->urlEncodedParams(),
+ $params
+ );
+ }
+
+ /**
+ * Sets the uploaded files array merging handled $_FILES and parsed files
+ * @param array $files
+ * @throws BaseException
+ * @throws ReflectionException
+ */
+ public function setUploadedFiles(array $files): void
+ {
+ $this->__files = array_merge(
+ $this->handleFiles($_FILES),
+ $files
+ );
+ }
+
+ /**
+ * Gets the request method
+ */
+ public function getMethod(): ?string
+ {
+ return $this->__method;
+ }
+
+ /**
+ * Sets the request method
+ * @throws BaseException
+ */
+ public function setMethod(string $method): void
+ {
+ if (!in_array(strtoupper($method), self::METHODS)) {
+ throw HttpException::requestMethodNotAvailable($method);
+ }
+
+ $this->__method = $method;
+ }
+
+ /**
+ * Checks if the current method matches the given method
+ */
+ public function isMethod(string $method): bool
+ {
+ return strcasecmp($method, $this->__method ?? '') === 0;
+ }
+
+ /**
+ * Gets Cross Site Request Forgery Token
+ */
+ public function getCsrfToken(): ?string
+ {
+ $csrfToken = null;
+
+ if ($this->has(Csrf::TOKEN_KEY)) {
+ $csrfToken = (string) $this->get(Csrf::TOKEN_KEY);
+ } elseif ($this->hasHeader('X-' . Csrf::TOKEN_KEY)) {
+ $csrfToken = $this->getHeader('X-' . Csrf::TOKEN_KEY);
+ }
+
+ return $csrfToken;
+ }
+
+ /**
+ * Gets the base url
+ * @throws DiException|ReflectionException
+ */
+ public function getBaseUrl(bool $withModulePrefix = false): string
+ {
+ $baseUrl = config()->get('app.base_url');
+
+ $prefix = route_prefix();
+ $modulePrefix = ($withModulePrefix && !in_array($prefix, [null, '', '0'], true)) ? '/' . $prefix : '';
+
+ if ($baseUrl) {
+ return $baseUrl . $modulePrefix;
+ }
+
+ return $this->getHostPrefix() . $modulePrefix;
+ }
+
+ /**
+ * Gets the current url
+ */
+ public function getCurrentUrl(): string
+ {
+ $uri = $this->getUri();
+ $query = $this->getQuery();
+ $queryPart = $query ? '?' . $query : '';
+
+ return $this->getHostPrefix() . '/' . $uri . $queryPart;
+ }
+
+ /**
+ * Gets the protocol, host, and optional port part of the URL.
+ */
+ private function getHostPrefix(): string
+ {
+ $protocol = $this->getProtocol();
+ $host = $this->getHost();
+ $port = $this->getPort();
+
+ $defaultPort = $protocol === 'https' ? self::DEFAULT_HTTPS_PORT : self::DEFAULT_HTTP_PORT;
+
+ $portPart = ($port && $port != $defaultPort) ? ':' . $port : '';
+
+ return $protocol . '://' . $host . $portPart;
+ }
+
+ /**
+ * Sets server data (method, protocol, host, port, uri, query).
+ */
+ private function setServerInfo(): void
+ {
+ foreach (['method', 'protocol', 'host', 'port', 'uri', 'query'] as $name) {
+ $this->{"__{$name}"} = $this->server->$name();
+ }
+ }
+
/**
- * @param string $function The function name
- * @param array $arguments
- * @return mixed
+ * Sets the normalized request content type.
*/
- public function __call(string $function, array $arguments)
+ private function setContentType(): void
{
- return HttpRequest::$function(...$arguments);
+ $this->__contentType = $this->server->contentType(true);
}
/**
- * @param string $function The function name
- * @param array $arguments
- * @return mixed
+ * Sets request headers, normalizing keys to lowercase.
+ * @throws DiException|ReflectionException
*/
- public static function __callStatic(string $function, array $arguments)
+ private function setRequestHeaders(): void
{
- return HttpRequest::$function(...$arguments);
+ $this->__headers = array_change_key_case(getallheaders());
}
}
diff --git a/src/Http/Request/HttpRequest.php b/src/Http/Request/HttpRequest.php
deleted file mode 100644
index 4369f68cb..000000000
--- a/src/Http/Request/HttpRequest.php
+++ /dev/null
@@ -1,267 +0,0 @@
-
- * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
- * @link http://quantum.softberg.org/
- * @since 3.0.0
- */
-
-namespace Quantum\Http\Request;
-
-use Quantum\Config\Exceptions\ConfigException;
-use Quantum\Http\Exceptions\HttpException;
-use Quantum\App\Exceptions\BaseException;
-use Quantum\Http\Traits\Request\RawInput;
-use Quantum\Http\Traits\Request\Internal;
-use Quantum\Http\Traits\Request\Header;
-use Quantum\Http\Traits\Request\Params;
-use Quantum\Di\Exceptions\DiException;
-use Quantum\Http\Traits\Request\Query;
-use Quantum\Http\Traits\Request\Route;
-use Quantum\Http\Traits\Request\Body;
-use Quantum\Http\Traits\Request\File;
-use Quantum\Http\Traits\Request\Url;
-use Quantum\Environment\Server;
-use ReflectionException;
-use Quantum\Csrf\Csrf;
-
-/**
- * Class HttpRequest
- * @package Quantum\Http
- */
-abstract class HttpRequest
-{
- use Route;
- use Header;
- use Body;
- use Url;
- use Query;
- use Params;
- use File;
- use RawInput;
- use Internal;
-
- /**
- * Available methods
- */
- public const METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
-
- /**
- * Default port for HTTP
- */
- public const DEFAULT_HTTP_PORT = 80;
-
- /**
- * Default port for HTTPS
- */
- public const DEFAULT_HTTPS_PORT = 443;
-
- /**
- * Request method
- */
- private static ?string $__method = null;
-
- protected static Server $server;
-
- private static bool $initialized = false;
-
- /**
- * Initializes the request static properties using the server instance.
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
- */
- public static function init(Server $server): void
- {
- if (self::$initialized) {
- return;
- }
-
- self::flush();
-
- self::$server = $server;
-
- self::setServerInfo();
- self::setContentType();
- self::setRequestHeaders();
-
- ['params' => $rawInputParams, 'files' => $rawInputFiles] = self::getRawInputParams();
-
- self::setRequestParams($rawInputParams);
- self::setUploadedFiles($rawInputFiles);
-
- self::$initialized = true;
- }
-
- /**
- * Flushes the request header , body and files
- */
- public static function flush(): void
- {
- self::$__headers = [];
- self::$__request = [];
- self::$__files = [];
- self::$__protocol = null;
- self::$__host = null;
- self::$__port = null;
- self::$__uri = null;
- self::$__query = null;
-
- self::$initialized = false;
- }
-
- /**
- * Sets the merged request parameters
- * @param array $params
- */
- public static function setRequestParams(array $params): void
- {
- self::$__request = array_merge(
- self::getParams(),
- self::postParams(),
- self::jsonPayloadParams(),
- self::urlEncodedParams(),
- $params
- );
- }
-
- /**
- * Sets the uploaded files array merging handled $_FILES and parsed files
- * @param array $files
- * @throws BaseException
- * @throws ReflectionException
- */
- public static function setUploadedFiles(array $files): void
- {
- self::$__files = array_merge(
- self::handleFiles($_FILES),
- $files
- );
- }
-
- /**
- * Gets the request method
- */
- public static function getMethod(): ?string
- {
- return self::$__method;
- }
-
- /**
- * Sets the request method
- * @throws BaseException
- */
- public static function setMethod(string $method): void
- {
- if (!in_array(strtoupper($method), self::METHODS)) {
- throw HttpException::requestMethodNotAvailable($method);
- }
-
- self::$__method = $method;
- }
-
- /**
- * Checks if the current method matches the given method
- */
- public static function isMethod(string $method): bool
- {
- return strcasecmp($method, self::$__method ?? '') === 0;
- }
-
- /**
- * Gets Cross Site Request Forgery Token
- */
- public static function getCsrfToken(): ?string
- {
- $csrfToken = null;
-
- if (self::has(Csrf::TOKEN_KEY)) {
- $csrfToken = (string) self::get(Csrf::TOKEN_KEY);
- } elseif (self::hasHeader('X-' . Csrf::TOKEN_KEY)) {
- $csrfToken = self::getHeader('X-' . Csrf::TOKEN_KEY);
- }
-
- return $csrfToken;
- }
-
- /**
- * Gets the base url
- * @throws DiException|ReflectionException
- */
- public static function getBaseUrl(bool $withModulePrefix = false): string
- {
- $baseUrl = config()->get('app.base_url');
-
- $prefix = route_prefix();
- $modulePrefix = ($withModulePrefix && !in_array($prefix, [null, '', '0'], true)) ? '/' . $prefix : '';
-
- if ($baseUrl) {
- return $baseUrl . $modulePrefix;
- }
-
- return self::getHostPrefix() . $modulePrefix;
- }
-
- /**
- * Gets the current url
- */
- public static function getCurrentUrl(): string
- {
- $uri = self::getUri();
- $query = self::getQuery();
- $queryPart = $query ? '?' . $query : '';
-
- return self::getHostPrefix() . '/' . $uri . $queryPart;
- }
-
- /**
- * Gets the protocol, host, and optional port part of the URL.
- */
- private static function getHostPrefix(): string
- {
- $protocol = self::getProtocol();
- $host = self::getHost();
- $port = self::getPort();
-
- $defaultPort = $protocol === 'https' ? self::DEFAULT_HTTPS_PORT : self::DEFAULT_HTTP_PORT;
-
- $portPart = ($port && $port != $defaultPort) ? ':' . $port : '';
-
- return $protocol . '://' . $host . $portPart;
- }
-
- /**
- * Sets server data (method, protocol, host, port, uri, query).
- */
- private static function setServerInfo(): void
- {
- foreach (['method', 'protocol', 'host', 'port', 'uri', 'query'] as $name) {
- self::${"__{$name}"} = self::$server->$name();
- }
- }
-
- /**
- * Sets the normalized request content type.
- */
- private static function setContentType(): void
- {
- self::$__contentType = self::$server->contentType(true);
- }
-
- /**
- * Sets request headers, normalizing keys to lowercase.
- */
- private static function setRequestHeaders(): void
- {
- self::$__headers = array_change_key_case(getallheaders());
- }
-}
diff --git a/src/Http/Response.php b/src/Http/Response.php
index 38bea3c96..5a452b35b 100644
--- a/src/Http/Response.php
+++ b/src/Http/Response.php
@@ -16,55 +16,64 @@
namespace Quantum\Http;
-use Quantum\Http\Response\HttpResponse;
+use Quantum\Http\Traits\Response\Header;
+use Quantum\Http\Traits\Response\Status;
+use Quantum\Http\Traits\Response\Body;
+use Quantum\Http\Enums\StatusCode;
+use Exception;
/**
* Class Response
* @package Quantum\Http
- * @method static void init()
- * @method static void flush()
- * @method static void send()
- * @method static string getContent()
- * @method static void setStatusCode(int $code)
- * @method static int getStatusCode()
- * @method static string getStatusText()
- * @method static void redirect(string $url, int $code = null)
- * @method static void json(array $data = null, int $code = null)
- * @method static void xml(array $data = null, $root = '', int $code = null)
- * @method static void html(string $html, int $code = null)
- * @method static bool has(string $key)
- * @method static mixed get(string $key, string $default = null)
- * @method static void set(string $key, $value)
- * @method static array all()
- * @method static void delete(string $key)
- * @method static bool hasHeader(string $key))
- * @method static string|null getHeader(string $key)
- * @method static void setHeader(string $key, string $value)
- * @method static array allHeaders()
- * @method static void deleteHeader(string $key)
- * @method static void setContentType(string $contentType)
- * @method static string|null getContentType()
- * @mixin HttpResponse
*/
class Response
{
+ use Header;
+ use Body;
+ use Status;
+
+ /**
+ * XML root element
+ * @var string
+ */
+ private string $xmlRoot = '';
+
+ /**
+ * Callback function
+ * @var string
+ */
+ private string $callbackFunction = '';
+
/**
- * @param string $function The function name
- * @param array $arguments
- * @return mixed
+ * Flushes the response header and body
*/
- public function __call(string $function, array $arguments)
+ public function flush(): void
{
- return HttpResponse::$function(...$arguments);
+ $this->__statusCode = StatusCode::OK;
+ $this->__headers = [];
+ $this->__response = [];
+ $this->xmlRoot = '';
+ $this->callbackFunction = '';
}
/**
- * @param string $function The function name
- * @param array $arguments
- * @return mixed
+ * Sends all response data to the client and finishes the request.
+ * @throws Exception
*/
- public static function __callStatic(string $function, array $arguments)
+ public function send(): void
{
- return HttpResponse::$function(...$arguments);
+ if (!environment()->isTesting()) {
+ while (ob_get_level() > 0) {
+ ob_end_clean();
+ }
+ }
+
+ foreach ($this->__headers as $key => $value) {
+ header($key . ': ' . $value);
+ }
+
+ http_response_code($this->getStatusCode());
+
+ echo $this->getContent();
}
}
diff --git a/src/Http/Response/HttpResponse.php b/src/Http/Response/HttpResponse.php
deleted file mode 100644
index 4aaaa2f77..000000000
--- a/src/Http/Response/HttpResponse.php
+++ /dev/null
@@ -1,98 +0,0 @@
-
- * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
- * @link http://quantum.softberg.org/
- * @since 3.0.0
- */
-
-namespace Quantum\Http\Response;
-
-use Quantum\Http\Traits\Response\Header;
-use Quantum\Http\Traits\Response\Status;
-use Quantum\Http\Traits\Response\Body;
-use Quantum\Environment\Environment;
-use Quantum\Environment\Enums\Env;
-use Quantum\Http\Enums\StatusCode;
-use Exception;
-
-/**
- * Class HttpResponse
- * @package Quantum\Http\Response
- */
-abstract class HttpResponse
-{
- use Header;
- use Body;
- use Status;
-
- /**
- * XML root element
- * @var string
- */
- private static $xmlRoot = '';
-
- /**
- * Callback function
- * @var string
- */
- private static $callbackFunction = '';
-
- private static bool $initialized = false;
-
- /**
- * Initialize the Response
- */
- public static function init(): void
- {
- if (self::$initialized) {
- return;
- }
-
- self::flush();
-
- self::$initialized = true;
- }
-
- /**
- * Flushes the response header and body
- */
- public static function flush(): void
- {
- self::$__statusCode = StatusCode::OK;
- self::$__headers = [];
- self::$__response = [];
- self::$xmlRoot = '';
- self::$callbackFunction = '';
- self::$initialized = false;
- }
-
- /**
- * Sends all response data to the client and finishes the request.
- * @throws Exception
- */
- public static function send(): void
- {
- if (Environment::getInstance()->getAppEnv() !== Env::TESTING) {
- while (ob_get_level() > 0) {
- ob_end_clean();
- }
- }
-
- foreach (self::$__headers as $key => $value) {
- header($key . ': ' . $value);
- }
-
- http_response_code(self::getStatusCode());
-
- echo self::getContent();
- }
-}
diff --git a/src/Http/Traits/Request/Body.php b/src/Http/Traits/Request/Body.php
index 62ae24539..3678c29ce 100644
--- a/src/Http/Traits/Request/Body.php
+++ b/src/Http/Traits/Request/Body.php
@@ -29,27 +29,27 @@ trait Body
* Request body
* @var array
*/
- private static array $__request = [];
+ private array $__request = [];
/**
* Checks if request contains a data by given key
*/
- public static function has(string $key): bool
+ public function has(string $key): bool
{
- return isset(self::$__request[$key]);
+ return isset($this->__request[$key]);
}
/**
* Retrieves data from request by given key
* @return mixed
*/
- public static function get(string $key, ?string $default = null, bool $raw = false)
+ public function get(string $key, ?string $default = null, bool $raw = false)
{
- if (!self::has($key)) {
+ if (!$this->has($key)) {
return $default;
}
- $value = self::$__request[$key];
+ $value = $this->__request[$key];
if ($raw) {
return $value;
@@ -64,31 +64,31 @@ public static function get(string $key, ?string $default = null, bool $raw = fal
* Sets new key/value pair into request
* @param mixed $value
*/
- public static function set(string $key, $value): void
+ public function set(string $key, $value): void
{
if ($key === ReservedKeys::RENDERED_VIEW) {
throw new InvalidArgumentException("Cannot set reserved key: `$key`");
}
- self::$__request[$key] = $value;
+ $this->__request[$key] = $value;
}
/**
* Gets all request parameters
* @return array
*/
- public static function all(): array
+ public function all(): array
{
- return array_merge(self::$__request, self::$__files);
+ return array_merge($this->__request, $this->__files);
}
/**
* Deletes the element from request by given key
*/
- public static function delete(string $key): void
+ public function delete(string $key): void
{
- if (self::has($key)) {
- unset(self::$__request[$key]);
+ if ($this->has($key)) {
+ unset($this->__request[$key]);
}
}
}
diff --git a/src/Http/Traits/Request/File.php b/src/Http/Traits/Request/File.php
index f91727eee..703efd46b 100644
--- a/src/Http/Traits/Request/File.php
+++ b/src/Http/Traits/Request/File.php
@@ -31,23 +31,23 @@ trait File
* Files
* @var array
*/
- private static array $__files = [];
+ private array $__files = [];
/**
* Checks to see if request contains file
*/
- public static function hasFile(string $key): bool
+ public function hasFile(string $key): bool
{
- if (!isset(self::$__files[$key])) {
+ if (!isset($this->__files[$key])) {
return false;
}
- if (!is_array(self::$__files[$key]) && self::$__files[$key]->getErrorCode() != UPLOAD_ERR_OK) {
+ if (!is_array($this->__files[$key]) && $this->__files[$key]->getErrorCode() != UPLOAD_ERR_OK) {
return false;
}
- if (is_array(self::$__files[$key])) {
- foreach (self::$__files[$key] as $file) {
+ if (is_array($this->__files[$key])) {
+ foreach ($this->__files[$key] as $file) {
if ($file->getErrorCode() != UPLOAD_ERR_OK) {
return false;
}
@@ -63,13 +63,13 @@ public static function hasFile(string $key): bool
* @return mixed
* @throws BaseException
*/
- public static function getFile(string $key)
+ public function getFile(string $key)
{
- if (!self::hasFile($key)) {
+ if (!$this->hasFile($key)) {
throw FileUploadException::fileNotFound($key);
}
- return self::$__files[$key];
+ return $this->__files[$key];
}
/**
@@ -79,7 +79,7 @@ public static function getFile(string $key)
* @throws BaseException
* @throws ReflectionException
*/
- public static function handleFiles(array $files): array
+ public function handleFiles(array $files): array
{
if (!count($files)) {
return [];
diff --git a/src/Http/Traits/Request/Header.php b/src/Http/Traits/Request/Header.php
index fbf86f953..aa0b12b32 100644
--- a/src/Http/Traits/Request/Header.php
+++ b/src/Http/Traits/Request/Header.php
@@ -26,26 +26,26 @@ trait Header
* Request headers
* @var array
*/
- private static array $__headers = [];
+ private array $__headers = [];
/**
* Checks the request header existence by given key
*/
- public static function hasHeader(string $key): bool
+ public function hasHeader(string $key): bool
{
- [$keyWithHyphens, $keyWithUnderscores] = self::normalizeHeaderKey($key);
+ [$keyWithHyphens, $keyWithUnderscores] = $this->normalizeHeaderKey($key);
- return isset(self::$__headers[$keyWithHyphens]) || isset(self::$__headers[$keyWithUnderscores]);
+ return isset($this->__headers[$keyWithHyphens]) || isset($this->__headers[$keyWithUnderscores]);
}
/**
* Gets the request header by given key
*/
- public static function getHeader(string $key): ?string
+ public function getHeader(string $key): ?string
{
- if (self::hasHeader($key)) {
- [$keyWithHyphens, $keyWithUnderscores] = self::normalizeHeaderKey($key);
- return self::$__headers[$keyWithHyphens] ?? self::$__headers[$keyWithUnderscores];
+ if ($this->hasHeader($key)) {
+ [$keyWithHyphens, $keyWithUnderscores] = $this->normalizeHeaderKey($key);
+ return $this->__headers[$keyWithHyphens] ?? $this->__headers[$keyWithUnderscores];
}
return null;
@@ -55,40 +55,40 @@ public static function getHeader(string $key): ?string
* Sets the request header
* @param mixed $value
*/
- public static function setHeader(string $key, $value): void
+ public function setHeader(string $key, $value): void
{
- self::$__headers[strtolower($key)] = $value;
+ $this->__headers[strtolower($key)] = $value;
}
/**
* Gets all request headers
* @return array
*/
- public static function allHeaders(): array
+ public function allHeaders(): array
{
- return self::$__headers;
+ return $this->__headers;
}
/**
* Deletes the header by given key
*/
- public static function deleteHeader(string $key): void
+ public function deleteHeader(string $key): void
{
- if (self::hasHeader($key)) {
- unset(self::$__headers[strtolower($key)]);
+ if ($this->hasHeader($key)) {
+ unset($this->__headers[strtolower($key)]);
}
}
/**
* Gets Authorization Bearer token
*/
- public static function getAuthorizationBearer(): ?string
+ public function getAuthorizationBearer(): ?string
{
$bearerToken = null;
- $authorization = (string) self::getHeader('Authorization');
+ $authorization = (string) $this->getHeader('Authorization');
- if (self::hasHeader('Authorization') && preg_match('/Bearer\s(\S+)/', $authorization, $matches)) {
+ if ($this->hasHeader('Authorization') && preg_match('/Bearer\s(\S+)/', $authorization, $matches)) {
$bearerToken = $matches[1];
}
@@ -99,20 +99,20 @@ public static function getAuthorizationBearer(): ?string
* Gets Basic Auth Credentials
* @return array|null
*/
- public static function getBasicAuthCredentials(): ?array
+ public function getBasicAuthCredentials(): ?array
{
- if (self::$server->has('PHP_AUTH_USER') && static::$server->has('PHP_AUTH_PW')) {
+ if ($this->server->has('PHP_AUTH_USER') && $this->server->has('PHP_AUTH_PW')) {
return [
- 'username' => self::$server->get('PHP_AUTH_USER'),
- 'password' => self::$server->get('PHP_AUTH_PW'),
+ 'username' => $this->server->get('PHP_AUTH_USER'),
+ 'password' => $this->server->get('PHP_AUTH_PW'),
];
}
- if (!self::hasHeader('Authorization')) {
+ if (!$this->hasHeader('Authorization')) {
return null;
}
- $authorization = (string) self::getHeader('Authorization');
+ $authorization = (string) $this->getHeader('Authorization');
if (preg_match('/Basic\s(\S+)/', $authorization, $matches)) {
$decoded = base64_decode($matches[1], true);
@@ -129,23 +129,23 @@ public static function getBasicAuthCredentials(): ?array
/**
* Checks to see if request was AJAX request
*/
- public static function isAjax(): bool
+ public function isAjax(): bool
{
- return self::hasHeader('X-REQUESTED-WITH') || self::$server->ajax();
+ return $this->hasHeader('X-REQUESTED-WITH') || $this->server->ajax();
}
/**
* Gets the referrer
*/
- public static function getReferrer(): ?string
+ public function getReferrer(): ?string
{
- return self::$server->referrer();
+ return $this->server->referrer();
}
/**
* @return array
*/
- private static function normalizeHeaderKey(string $key): array
+ private function normalizeHeaderKey(string $key): array
{
$keyWithHyphens = str_replace('_', '-', strtolower($key));
$keyWithUnderscores = str_replace('-', '_', $key);
diff --git a/src/Http/Traits/Request/Internal.php b/src/Http/Traits/Request/Internal.php
index 92c2e35a2..156c1e2fb 100644
--- a/src/Http/Traits/Request/Internal.php
+++ b/src/Http/Traits/Request/Internal.php
@@ -36,12 +36,9 @@ trait Internal
* @param array $params
* @param array $headers
* @param array $files
- * @throws BaseException
- * @throws ReflectionException
- * @throws ConfigException
- * @throws DiException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
- public static function create(
+ public function create(
string $method,
string $url,
array $params = [],
@@ -50,7 +47,7 @@ public static function create(
): void {
$parsed = parse_url($url);
- $server = Server::getInstance();
+ $server = server();
$server->flush();
@@ -82,32 +79,32 @@ public static function create(
$server->set('QUERY_STRING', '');
}
- self::detectAndSetContentType($server, $params, $files);
+ $this->detectAndSetContentType($server, $params, $files);
foreach ($headers as $name => $value) {
$server->set('HTTP_' . strtoupper(str_replace('-', '_', $name)), $value);
}
- self::flush();
+ $this->flush();
- self::init($server);
+ $this->server = $server;
+ $this->populateFromServer();
if ($params !== []) {
- self::setRequestParams($params);
+ $this->setRequestParams($params);
}
if ($files !== []) {
- self::setUploadedFiles(self::handleFiles($files));
+ $this->setUploadedFiles($this->handleFiles($files));
}
}
/**
* Detects the content type
- * @param Server $server
* @param array|null $data
* @param array|null $files
*/
- protected static function detectAndSetContentType($server, ?array $data = null, ?array $files = null): void
+ protected function detectAndSetContentType(Server $server, ?array $data = null, ?array $files = null): void
{
if ($files && count($files) > 0) {
$server->set('CONTENT_TYPE', ContentType::FORM_DATA);
diff --git a/src/Http/Traits/Request/Params.php b/src/Http/Traits/Request/Params.php
index 6c050ce67..e1a8be60d 100644
--- a/src/Http/Traits/Request/Params.php
+++ b/src/Http/Traits/Request/Params.php
@@ -32,13 +32,13 @@ trait Params
* Request content type
* @var string|null
*/
- private static ?string $__contentType;
+ private ?string $__contentType = null;
/**
* Gets the GET params.
* @return array
*/
- private static function getParams(): array
+ private function getParams(): array
{
if ($_GET === []) {
return [];
@@ -51,7 +51,7 @@ private static function getParams(): array
* Gets the POST params.
* @return array
*/
- private static function postParams(): array
+ private function postParams(): array
{
if ($_POST === []) {
return [];
@@ -64,32 +64,32 @@ private static function postParams(): array
* Parses and returns JSON payload parameters.
* @return array
*/
- private static function jsonPayloadParams(): array
+ private function jsonPayloadParams(): array
{
if (
- !in_array(self::$__method, ['PUT', 'PATCH', 'POST'], true) ||
- self::$__contentType !== ContentType::JSON
+ !in_array($this->__method, ['PUT', 'PATCH', 'POST'], true) ||
+ $this->__contentType !== ContentType::JSON
) {
return [];
}
- return json_decode(self::getRawInput(), true) ?: [];
+ return json_decode($this->getRawInput(), true) ?: [];
}
/**
* Parses and returns URL-encoded parameters.
* @return array
*/
- private static function urlEncodedParams(): array
+ private function urlEncodedParams(): array
{
if (
- !in_array(self::$__method, ['PUT', 'PATCH', 'POST'], true) ||
- self::$__contentType !== ContentType::URL_ENCODED
+ !in_array($this->__method, ['PUT', 'PATCH', 'POST'], true) ||
+ $this->__contentType !== ContentType::URL_ENCODED
) {
return [];
}
- parse_str(urldecode(self::getRawInput()), $result);
+ parse_str(urldecode($this->getRawInput()), $result);
return $result; /** @phpstan-ignore return.type */
}
@@ -97,27 +97,24 @@ private static function urlEncodedParams(): array
/**
* Parses and returns multipart form data parameters.
* @return array
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
- private static function getRawInputParams(): array
+ private function getRawInputParams(): array
{
if (
- !in_array(self::$__method, ['PUT', 'PATCH', 'POST'], true) ||
- self::$__contentType !== ContentType::FORM_DATA
+ !in_array($this->__method, ['PUT', 'PATCH', 'POST'], true) ||
+ $this->__contentType !== ContentType::FORM_DATA
) {
return ['params' => [], 'files' => []];
}
- return self::parse(self::getRawInput());
+ return $this->parse($this->getRawInput());
}
/**
* Retrieves the raw HTTP request body as a string.
*/
- private static function getRawInput(): string
+ private function getRawInput(): string
{
return file_get_contents('php://input') ?: '';
}
diff --git a/src/Http/Traits/Request/Query.php b/src/Http/Traits/Request/Query.php
index feef85c37..f3408ad2b 100644
--- a/src/Http/Traits/Request/Query.php
+++ b/src/Http/Traits/Request/Query.php
@@ -25,34 +25,34 @@ trait Query
/**
* Query string
*/
- private static ?string $__query = null;
+ private ?string $__query = null;
/**
* Gets the query string
*/
- public static function getQuery(): ?string
+ public function getQuery(): ?string
{
- return self::$__query;
+ return $this->__query;
}
/**
* Sets the query string
*/
- public static function setQuery(string $query): void
+ public function setQuery(string $query): void
{
- self::$__query = $query;
+ $this->__query = $query;
}
/**
* Gets the query param
*/
- public static function getQueryParam(string $key): ?string
+ public function getQueryParam(string $key): ?string
{
- if (self::$__query === null) {
+ if ($this->__query === null) {
return null;
}
- $query = explode('&', self::$__query);
+ $query = explode('&', $this->__query);
foreach ($query as $items) {
$item = explode('=', $items);
@@ -67,10 +67,10 @@ public static function getQueryParam(string $key): ?string
/**
* Sets the query param
*/
- public static function setQueryParam(string $key, string $value): void
+ public function setQueryParam(string $key, string $value): void
{
- $queryParams = self::$__query ? explode('&', self::$__query) : [];
+ $queryParams = $this->__query ? explode('&', $this->__query) : [];
$queryParams[] = $key . '=' . $value;
- self::$__query = implode('&', $queryParams);
+ $this->__query = implode('&', $queryParams);
}
}
diff --git a/src/Http/Traits/Request/RawInput.php b/src/Http/Traits/Request/RawInput.php
index de81eff7a..9c5707c32 100644
--- a/src/Http/Traits/Request/RawInput.php
+++ b/src/Http/Traits/Request/RawInput.php
@@ -22,7 +22,6 @@
use Quantum\Di\Exceptions\DiException;
use Quantum\Http\Enums\ContentType;
use Quantum\Storage\UploadedFile;
-use Quantum\Environment\Server;
use ReflectionException;
/**
@@ -34,30 +33,27 @@ trait RawInput
/**
* Parses raw input data and returns parsed parameters and files
* @return array
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
- public static function parse(string $rawInput): array
+ public function parse(string $rawInput): array
{
- $boundary = self::getBoundary();
+ $boundary = $this->getBoundary();
if (!$boundary) {
return ['params' => [], 'files' => []];
}
- $blocks = self::getBlocks($boundary, $rawInput);
+ $blocks = $this->getBlocks($boundary, $rawInput);
- return self::processBlocks($blocks);
+ return $this->processBlocks($blocks);
}
/**
* Extracts boundary string from Content-Type header
*/
- private static function getBoundary(): ?string
+ private function getBoundary(): ?string
{
- $contentType = Server::getInstance()->contentType();
+ $contentType = server()->contentType();
if (!$contentType) {
return null;
@@ -72,7 +68,7 @@ private static function getBoundary(): ?string
* Splits raw input into multipart blocks
* @return array
*/
- private static function getBlocks(string $boundary, string $rawInput): array
+ private function getBlocks(string $boundary, string $rawInput): array
{
$result = preg_split("/-+$boundary/", $rawInput);
@@ -89,12 +85,9 @@ private static function getBlocks(string $boundary, string $rawInput): array
* Processes multipart blocks and extracts parameters and files
* @param array $blocks
* @return array
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
- private static function processBlocks(array $blocks): array
+ private function processBlocks(array $blocks): array
{
$params = [];
$files = [];
@@ -106,11 +99,11 @@ private static function processBlocks(array $blocks): array
continue;
}
- $type = self::detectBlockType($block);
+ $type = $this->detectBlockType($block);
switch ($type) {
case 'file':
- $parsed = self::getParsedFile($block);
+ $parsed = $this->getParsedFile($block);
if ($parsed === null) {
continue 2;
@@ -118,16 +111,16 @@ private static function processBlocks(array $blocks): array
[$nameParam, $file] = $parsed;
- self::addFileToCollection($files, $nameParam, $file);
+ $this->addFileToCollection($files, $nameParam, $file);
break;
case 'stream':
- $params += self::getParsedStream($block);
+ $params += $this->getParsedStream($block);
break;
case 'param':
default:
- $params += self::getParsedParameter($block);
+ $params += $this->getParsedParameter($block);
break;
}
}
@@ -139,9 +132,9 @@ private static function processBlocks(array $blocks): array
* Adds a parsed file to the files collection
* @param array $files
*/
- private static function addFileToCollection(array &$files, string $nameParam, UploadedFile $file): void
+ private function addFileToCollection(array &$files, string $nameParam, UploadedFile $file): void
{
- $arrayParam = self::arrayParam($nameParam);
+ $arrayParam = $this->arrayParam($nameParam);
if (is_array($arrayParam)) {
[$name, $key] = $arrayParam;
@@ -160,7 +153,7 @@ private static function addFileToCollection(array &$files, string $nameParam, Up
* Detects the block type as a string identifier.
* @return string One of 'file', 'stream', 'param'
*/
- private static function detectBlockType(string $block): string
+ private function detectBlockType(string $block): string
{
if (strpos($block, 'filename') !== false) {
return 'file';
@@ -177,7 +170,7 @@ private static function detectBlockType(string $block): string
* Gets the parsed param
* @return array
*/
- private static function getParsedStream(string $block): array
+ private function getParsedStream(string $block): array
{
preg_match('/name=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/s', $block, $match);
@@ -187,14 +180,11 @@ private static function getParsedStream(string $block): array
/**
* Gets the parsed file
* @return array{string, UploadedFile}|null
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
- private static function getParsedFile(string $block): ?array
+ private function getParsedFile(string $block): ?array
{
- [$name, $filename, $type, $content] = self::parseFileData($block);
+ [$name, $filename, $type, $content] = $this->parseFileData($block);
if (!$content) {
return null;
@@ -223,7 +213,7 @@ private static function getParsedFile(string $block): ?array
* Parses a file block into metadata and binary content
* @return array{string, string, string, string}
*/
- private static function parseFileData(string $block): array
+ private function parseFileData(string $block): array
{
$block = ltrim($block, "\r\n");
@@ -235,7 +225,7 @@ private static function parseFileData(string $block): array
[$rawHeaders, $content] = $parts;
- [$name, $filename, $contentType] = self::parseHeaders($rawHeaders);
+ [$name, $filename, $contentType] = $this->parseHeaders($rawHeaders);
$content = substr($content, 0, strlen($content) - 2);
@@ -251,7 +241,7 @@ private static function parseFileData(string $block): array
* Parses a block and extracts normal form parameters
* @return array
*/
- private static function getParsedParameter(string $block): array
+ private function getParsedParameter(string $block): array
{
$data = [];
@@ -272,7 +262,7 @@ private static function getParsedParameter(string $block): array
* Extracts name, filename, and content type from header lines
* @return array{string, string, string}
*/
- private static function parseHeaders(string $rawHeaders): array
+ private function parseHeaders(string $rawHeaders): array
{
$name = '-unknown-';
$filename = '-unknown-';
@@ -304,7 +294,7 @@ private static function parseHeaders(string $rawHeaders): array
* Parses array-like parameter names
* @return array|string
*/
- private static function arrayParam(string $parameter)
+ private function arrayParam(string $parameter)
{
if (strpos($parameter, '[') !== false && preg_match('/^([^[]*)\[([^]]*)\](.*)$/', $parameter, $match)) {
return [$match[1], $match[2]];
diff --git a/src/Http/Traits/Request/Route.php b/src/Http/Traits/Request/Route.php
index b941e0b88..413b83ff5 100644
--- a/src/Http/Traits/Request/Route.php
+++ b/src/Http/Traits/Request/Route.php
@@ -24,16 +24,16 @@
*/
trait Route
{
- private static ?MatchedRoute $route = null;
+ private ?MatchedRoute $route = null;
- public static function setMatchedRoute(?MatchedRoute $route): void
+ public function setMatchedRoute(?MatchedRoute $route): void
{
- self::$route = $route;
+ $this->route = $route;
}
- public static function getMatchedRoute(): ?MatchedRoute
+ public function getMatchedRoute(): ?MatchedRoute
{
- return self::$route;
+ return $this->route;
}
}
diff --git a/src/Http/Traits/Request/Url.php b/src/Http/Traits/Request/Url.php
index 878760391..f91ac0375 100644
--- a/src/Http/Traits/Request/Url.php
+++ b/src/Http/Traits/Request/Url.php
@@ -25,96 +25,96 @@ trait Url
/**
* Scheme
*/
- private static ?string $__protocol = null;
+ private ?string $__protocol = null;
/**
* Host name
*/
- private static ?string $__host = null;
+ private ?string $__host = null;
/**
* Server port
*/
- private static ?string $__port = null;
+ private ?string $__port = null;
/**
* Request URI
*/
- private static ?string $__uri = null;
+ private ?string $__uri = null;
/**
* Gets the protocol
* @return string
*/
- public static function getProtocol(): ?string
+ public function getProtocol(): ?string
{
- return self::$__protocol;
+ return $this->__protocol;
}
/**
* Sets the protocol
*/
- public static function setProtocol(string $protocol): void
+ public function setProtocol(string $protocol): void
{
- self::$__protocol = $protocol;
+ $this->__protocol = $protocol;
}
/**
* Gets the host name
* @return string
*/
- public static function getHost(): ?string
+ public function getHost(): ?string
{
- return self::$__host;
+ return $this->__host;
}
/**
* Sets the host name
*/
- public static function setHost(string $host): void
+ public function setHost(string $host): void
{
- self::$__host = $host;
+ $this->__host = $host;
}
/**
* Gets the port
* @return string
*/
- public static function getPort(): ?string
+ public function getPort(): ?string
{
- return self::$__port;
+ return $this->__port;
}
/**
* Sets the port
*/
- public static function setPort(string $port): void
+ public function setPort(string $port): void
{
- self::$__port = $port;
+ $this->__port = $port;
}
/**
* Gets the URI
*/
- public static function getUri(): ?string
+ public function getUri(): ?string
{
- return self::$__uri;
+ return $this->__uri;
}
/**
* Sets the URI
*/
- public static function setUri(string $uri): void
+ public function setUri(string $uri): void
{
- self::$__uri = ltrim($uri, '/');
+ $this->__uri = ltrim($uri, '/');
}
/**
* Returns the URI segment at the specified index.
*/
- public static function getSegment(int $index): ?string
+ public function getSegment(int $index): ?string
{
- $segments = self::getAllSegments();
+ $segments = $this->getAllSegments();
return $segments[$index] ?? null;
}
@@ -123,13 +123,13 @@ public static function getSegment(int $index): ?string
* Gets all URI segments as an array.
* @return array
*/
- public static function getAllSegments(): array
+ public function getAllSegments(): array
{
- if (self::$__uri === null) {
+ if ($this->__uri === null) {
return ['zero_segment'];
}
- $parsed = parse_url(self::$__uri);
+ $parsed = parse_url($this->__uri);
$segments = explode('/', trim(is_array($parsed) ? ($parsed['path'] ?? '') : '', '/'));
array_unshift($segments, 'zero_segment');
return $segments;
diff --git a/src/Http/Traits/Response/Body.php b/src/Http/Traits/Response/Body.php
index b322efb5c..3d21fcba1 100644
--- a/src/Http/Traits/Response/Body.php
+++ b/src/Http/Traits/Response/Body.php
@@ -33,12 +33,12 @@ trait Body
* Response
* @var array
*/
- private static array $__response = [];
+ private array $__response = [];
/**
* @var string[]
*/
- private static array $formatters = [
+ private array $formatters = [
ContentType::HTML => 'formatHtml',
ContentType::XML => 'formatXml',
ContentType::JSON => 'formatJson',
@@ -48,45 +48,45 @@ trait Body
/**
* Checks if response contains a data by given key
*/
- public static function has(string $key): bool
+ public function has(string $key): bool
{
- return isset(self::$__response[$key]);
+ return isset($this->__response[$key]);
}
/**
* Gets the data from response by given key
* @return mixed
*/
- public static function get(string $key, ?string $default = null)
+ public function get(string $key, ?string $default = null)
{
- return self::has($key) ? self::$__response[$key] : $default;
+ return $this->has($key) ? $this->__response[$key] : $default;
}
/**
* Sets new key/value pair into response
* @param mixed $value
*/
- public static function set(string $key, $value): void
+ public function set(string $key, $value): void
{
- self::$__response[$key] = $value;
+ $this->__response[$key] = $value;
}
/**
* Gets all response parameters
* @return array
*/
- public static function all(): array
+ public function all(): array
{
- return self::$__response;
+ return $this->__response;
}
/**
* Deletes the element from response by given key
*/
- public static function delete(string $key): void
+ public function delete(string $key): void
{
- if (self::has($key)) {
- unset(self::$__response[$key]);
+ if ($this->has($key)) {
+ unset($this->__response[$key]);
}
}
@@ -94,36 +94,35 @@ public static function delete(string $key): void
* Prepares the JSON response
* @param array|null $data
*/
- public static function json(?array $data = null, ?int $code = null): void
+ public function json(?array $data = null, ?int $code = null): void
{
- self::setContentType(ContentType::JSON);
+ $this->setContentType(ContentType::JSON);
if (!is_null($code)) {
- self::setStatusCode($code);
+ $this->setStatusCode($code);
}
if ($data) {
- self::$__response = array_merge(self::$__response, $data);
+ $this->__response = array_merge($this->__response, $data);
}
}
/**
* Prepares the JSONP response
- * @param string $callback
* @param array|null $data
*/
- public static function jsonp(string $callback, ?array $data = null, ?int $code = null): void
+ public function jsonp(string $callback, ?array $data = null, ?int $code = null): void
{
- self::setContentType(ContentType::JSONP);
+ $this->setContentType(ContentType::JSONP);
- self::$callbackFunction = $callback;
+ $this->callbackFunction = $callback;
if (!is_null($code)) {
- self::setStatusCode($code);
+ $this->setStatusCode($code);
}
if ($data) {
- self::$__response = array_merge(self::$__response, $data);
+ $this->__response = array_merge($this->__response, $data);
}
}
@@ -131,9 +130,9 @@ public static function jsonp(string $callback, ?array $data = null, ?int $code =
* Returns response with function
* @param array $data
*/
- public static function getJsonPData(array $data): string
+ public function getJsonPData(array $data): string
{
- return self::$callbackFunction . '(' . json_encode($data) . ')';
+ return $this->callbackFunction . '(' . json_encode($data) . ')';
}
/**
@@ -141,50 +140,50 @@ public static function getJsonPData(array $data): string
* @param array|null $data
* @param string $root
*/
- public static function xml(?array $data = null, $root = '', ?int $code = null): void
+ public function xml(?array $data = null, $root = '', ?int $code = null): void
{
- self::setContentType(ContentType::XML);
+ $this->setContentType(ContentType::XML);
if (!is_null($code)) {
- self::setStatusCode($code);
+ $this->setStatusCode($code);
}
- self::$xmlRoot = $root;
+ $this->xmlRoot = $root;
if ($data) {
- self::$__response = array_merge(self::$__response, $data);
+ $this->__response = array_merge($this->__response, $data);
}
}
/**
* Prepares the HTML content
*/
- public static function html(string $html, ?int $code = null): void
+ public function html(string $html, ?int $code = null): void
{
- self::setContentType(ContentType::HTML);
+ $this->setContentType(ContentType::HTML);
if (!is_null($code)) {
- self::setStatusCode($code);
+ $this->setStatusCode($code);
}
- self::$__response[ReservedKeys::RENDERED_VIEW] = $html;
+ $this->__response[ReservedKeys::RENDERED_VIEW] = $html;
}
/**
* Gets the response content
* @throws HttpException
*/
- public static function getContent(): string
+ public function getContent(): string
{
- $contentType = self::getContentType();
+ $contentType = $this->getContentType();
- if (!isset(self::$formatters[$contentType])) {
+ if (!isset($this->formatters[$contentType])) {
throw new HttpException("Unsupported content type: {$contentType}");
}
- $formatterMethod = self::$formatters[$contentType];
+ $formatterMethod = $this->formatters[$contentType];
- return self::$formatterMethod();
+ return $this->$formatterMethod();
}
/**
@@ -192,10 +191,10 @@ public static function getContent(): string
* @param array $arr
* @throws Exception
*/
- private static function arrayToXML(array $arr): string
+ private function arrayToXML(array $arr): string
{
- $simpleXML = new SimpleXMLElement(self::$xmlRoot);
- self::composeXML($arr, $simpleXML);
+ $simpleXML = new SimpleXMLElement($this->xmlRoot);
+ $this->composeXML($arr, $simpleXML);
$dom = new DOMDocument();
$xml = $simpleXML->asXML();
@@ -213,7 +212,7 @@ private static function arrayToXML(array $arr): string
* Compose XML
* @param array $arr
*/
- private static function composeXML(array $arr, SimpleXMLElement &$simpleXML): void
+ private function composeXML(array $arr, SimpleXMLElement &$simpleXML): void
{
foreach ($arr as $key => $value) {
if (is_numeric($key)) {
@@ -236,7 +235,7 @@ private static function composeXML(array $arr, SimpleXMLElement &$simpleXML): vo
}
}
- self::composeXML($value, $child);
+ $this->composeXML($value, $child);
} else {
$child = $simpleXML->addChild($tag, htmlspecialchars((string) $value));
@@ -252,33 +251,33 @@ private static function composeXML(array $arr, SimpleXMLElement &$simpleXML): vo
/**
* Formats data as JSON
*/
- private static function formatJson(): string
+ private function formatJson(): string
{
- return json_encode(self::all(), JSON_UNESCAPED_UNICODE) ?: '';
+ return json_encode($this->all(), JSON_UNESCAPED_UNICODE) ?: '';
}
/**
* Formats data as XML
* @throws Exception
*/
- private static function formatXml(): string
+ private function formatXml(): string
{
- return self::arrayToXml(self::all());
+ return $this->arrayToXML($this->all());
}
/**
* Formats data as HTML
*/
- private static function formatHtml(): string
+ private function formatHtml(): string
{
- return self::get(ReservedKeys::RENDERED_VIEW) ?? '';
+ return $this->get(ReservedKeys::RENDERED_VIEW) ?? '';
}
/**
* Formats data as JSONP
*/
- private static function formatJsonp(): string
+ private function formatJsonp(): string
{
- return self::getJsonPData(self::all());
+ return $this->getJsonPData($this->all());
}
}
diff --git a/src/Http/Traits/Response/Header.php b/src/Http/Traits/Response/Header.php
index 7f7abd789..d02c57cc1 100644
--- a/src/Http/Traits/Response/Header.php
+++ b/src/Http/Traits/Response/Header.php
@@ -29,75 +29,75 @@ trait Header
* Response headers
* @var array
*/
- private static array $__headers = [];
+ private array $__headers = [];
/**
* Checks the response header existence by given key
*/
- public static function hasHeader(string $key): bool
+ public function hasHeader(string $key): bool
{
- return isset(self::$__headers[$key]);
+ return isset($this->__headers[$key]);
}
/**
* Gets the response header by given key
*/
- public static function getHeader(string $key): ?string
+ public function getHeader(string $key): ?string
{
- return self::hasHeader($key) ? self::$__headers[$key] : null;
+ return $this->hasHeader($key) ? $this->__headers[$key] : null;
}
/**
* Sets the response header
*/
- public static function setHeader(string $key, string $value): void
+ public function setHeader(string $key, string $value): void
{
- self::$__headers[$key] = $value;
+ $this->__headers[$key] = $value;
}
/**
* Get all response headers
* @return array
*/
- public static function allHeaders(): array
+ public function allHeaders(): array
{
- return self::$__headers;
+ return $this->__headers;
}
/**
* Deletes the header by given key
*/
- public static function deleteHeader(string $key): void
+ public function deleteHeader(string $key): void
{
- if (self::hasHeader($key)) {
- unset(self::$__headers[$key]);
+ if ($this->hasHeader($key)) {
+ unset($this->__headers[$key]);
}
}
/**
* Sets the content type
*/
- public static function setContentType(string $contentType): void
+ public function setContentType(string $contentType): void
{
- self::setHeader('Content-Type', $contentType);
+ $this->setHeader('Content-Type', $contentType);
}
/**
* Gets the content type
*/
- public static function getContentType(): string
+ public function getContentType(): string
{
- return self::getHeader('Content-Type') ?? ContentType::HTML;
+ return $this->getHeader('Content-Type') ?? ContentType::HTML;
}
/**
* Redirect
* @throws StopExecutionException
*/
- public static function redirect(string $url, int $code = 302): void
+ public function redirect(string $url, int $code = 302): void
{
- self::setStatusCode($code);
- self::setHeader('Location', $url);
+ $this->setStatusCode($code);
+ $this->setHeader('Location', $url);
stop();
}
}
diff --git a/src/Http/Traits/Response/Status.php b/src/Http/Traits/Response/Status.php
index 62cbd83e6..a4c13b4ad 100644
--- a/src/Http/Traits/Response/Status.php
+++ b/src/Http/Traits/Response/Status.php
@@ -28,13 +28,13 @@ trait Status
/**
* Status code
*/
- private static int $__statusCode = StatusCode::OK;
+ private int $__statusCode = StatusCode::OK;
/**
* Status texts
* @var string[]
*/
- private static array $texts = [
+ private array $texts = [
StatusCode::CONTINUE => 'Continue',
StatusCode::SWITCHING_PROTOCOLS => 'Switching Protocols',
StatusCode::PROCESSING => 'Processing',
@@ -106,40 +106,40 @@ trait Status
/**
* Gets the reason phrase for a given HTTP status code.
*/
- public static function getText(int $code): string
+ public function getText(int $code): string
{
- if (!isset(self::$texts[$code])) {
+ if (!isset($this->texts[$code])) {
throw new InvalidArgumentException("Unknown HTTP status code: {$code}");
}
- return self::$texts[$code];
+ return $this->texts[$code];
}
/**
* Sets the status code
*/
- public static function setStatusCode(int $code): void
+ public function setStatusCode(int $code): void
{
- if (!isset(self::$texts[$code])) {
+ if (!isset($this->texts[$code])) {
throw new InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code));
}
- self::$__statusCode = $code;
+ $this->__statusCode = $code;
}
/**
* Gets the status code
*/
- public static function getStatusCode(): int
+ public function getStatusCode(): int
{
- return self::$__statusCode;
+ return $this->__statusCode;
}
/**
* Gets the status text
*/
- public static function getStatusText(): string
+ public function getStatusText(): string
{
- return self::getText(self::$__statusCode);
+ return $this->getText($this->__statusCode);
}
}
diff --git a/src/HttpClient/HttpClient.php b/src/HttpClient/HttpClient.php
index 98431f5c5..9125ec104 100644
--- a/src/HttpClient/HttpClient.php
+++ b/src/HttpClient/HttpClient.php
@@ -174,7 +174,7 @@ public function isMultiRequest(): bool
/**
* Starts the request
* @throws ErrorException
- * @throws HttpClientException
+ * @throws HttpClientException|BaseException
*/
public function start(): HttpClient
{
diff --git a/src/Jwt/JwtToken.php b/src/Jwt/JwtToken.php
index 608059625..f97bcfb58 100644
--- a/src/Jwt/JwtToken.php
+++ b/src/Jwt/JwtToken.php
@@ -57,9 +57,8 @@ public function __construct(?string $key = null)
/**
* Sets extra leeway time
- * @param int $leeway
*/
- public function setLeeway($leeway): JwtToken
+ public function setLeeway(int $leeway): JwtToken
{
parent::$leeway = $leeway;
return $this;
diff --git a/src/Lang/Factories/LangFactory.php b/src/Lang/Factories/LangFactory.php
index f176b5c67..7a4c0b7ea 100644
--- a/src/Lang/Factories/LangFactory.php
+++ b/src/Lang/Factories/LangFactory.php
@@ -17,13 +17,14 @@
namespace Quantum\Lang\Factories;
use Quantum\Config\Exceptions\ConfigException;
+use Quantum\Loader\Exceptions\LoaderException;
use Quantum\Lang\Exceptions\LangException;
use Quantum\Di\Exceptions\DiException;
use Quantum\Lang\Translator;
-use Quantum\Http\Request;
use Quantum\Loader\Setup;
use ReflectionException;
use Quantum\Lang\Lang;
+use Quantum\Di\Di;
/**
* Class LangFactory
@@ -31,40 +32,43 @@
*/
class LangFactory
{
+ private ?Lang $instance = null;
+
/**
- * @var Lang|null Cached Lang instance
+ * @throws LangException|ConfigException|LoaderException|DiException|ReflectionException
*/
- private static ?Lang $instance = null;
+ public static function get(): Lang
+ {
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve();
+ }
/**
- * @throws ConfigException
- * @throws LangException
- * @throws DiException
- * @throws ReflectionException
+ * @throws LangException|ConfigException|DiException|ReflectionException|LoaderException
*/
- public static function get(): Lang
+ public function resolve(): Lang
{
- if (self::$instance !== null) {
- return self::$instance;
+ if ($this->instance !== null) {
+ return $this->instance;
}
- [$isEnabled, $supported, $default] = self::loadLangConfig();
+ [$isEnabled, $supported, $default] = $this->loadLangConfig();
- $lang = self::detectLanguage($supported, $default);
+ $lang = $this->detectLanguage($supported, $default);
$translator = new Translator($lang);
- return self::$instance = new Lang($lang, $isEnabled, $translator);
-
+ return $this->instance = new Lang($lang, $isEnabled, $translator);
}
/**
* @return array{0: bool, 1: array, 2: string}
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws LoaderException|ConfigException|DiException|ReflectionException
*/
- private static function loadLangConfig(): array
+ private function loadLangConfig(): array
{
if (!config()->has('lang')) {
config()->import(new Setup('config', 'lang'));
@@ -79,18 +83,18 @@ private static function loadLangConfig(): array
/**
* @param array $supported
- * @throws LangException
+ * @throws LangException|DiException|ReflectionException
*/
- private static function detectLanguage(array $supported, ?string $default): string
+ private function detectLanguage(array $supported, ?string $default): string
{
- $lang = self::getLangFromQuery($supported);
+ $lang = $this->getLangFromQuery($supported);
if (in_array($lang, [null, '', '0'], true)) {
- $lang = self::getLangFromUrlSegment($supported);
+ $lang = $this->getLangFromUrlSegment($supported);
}
if (in_array($lang, [null, '', '0'], true)) {
- $lang = self::getLangFromHeader($supported);
+ $lang = $this->getLangFromHeader($supported);
}
if (in_array($lang, [null, '', '0'], true)) {
@@ -107,17 +111,18 @@ private static function detectLanguage(array $supported, ?string $default): stri
/**
* @param array $supported
*/
- private static function getLangFromQuery(array $supported): ?string
+ private function getLangFromQuery(array $supported): ?string
{
- $queryLang = Request::getQueryParam('lang');
+ $queryLang = request()->getQueryParam('lang');
return $queryLang && in_array($queryLang, $supported) ? $queryLang : null;
}
/**
* @param array $supported
+ * @throws DiException|ReflectionException
*/
- private static function getLangFromUrlSegment(array $supported): ?string
+ private function getLangFromUrlSegment(array $supported): ?string
{
$segmentIndex = (int) config()->get('lang.url_segment');
@@ -125,15 +130,16 @@ private static function getLangFromUrlSegment(array $supported): ?string
$segmentIndex++;
}
- $segmentLang = Request::getSegment($segmentIndex);
+ $segmentLang = request()->getSegment($segmentIndex);
return $segmentLang && in_array($segmentLang, $supported) ? $segmentLang : null;
}
/**
* @param array $supported
+ * @throws DiException|ReflectionException
*/
- private static function getLangFromHeader(array $supported): ?string
+ private function getLangFromHeader(array $supported): ?string
{
$acceptedLang = server()->acceptedLang();
diff --git a/src/Lang/Helpers/lang.php b/src/Lang/Helpers/lang.php
index d61675bd1..c0fef0129 100644
--- a/src/Lang/Helpers/lang.php
+++ b/src/Lang/Helpers/lang.php
@@ -13,16 +13,14 @@
*/
use Quantum\Config\Exceptions\ConfigException;
+use Quantum\Loader\Exceptions\LoaderException;
use Quantum\Lang\Exceptions\LangException;
use Quantum\Lang\Factories\LangFactory;
use Quantum\Di\Exceptions\DiException;
/**
* Gets the current lang
- * @throws ConfigException
- * @throws DiException
- * @throws LangException
- * @throws ReflectionException
+ * @throws LangException|LoaderException|ConfigException|DiException|ReflectionException
*/
function current_lang(): ?string
{
@@ -31,12 +29,8 @@ function current_lang(): ?string
/**
* Gets translation
- * @param string $key
* @param array|string|null $params
- * @throws ConfigException
- * @throws ReflectionException
- * @throws DiException
- * @throws LangException
+ * @throws LangException|LoaderException|ConfigException|DiException|ReflectionException
*/
function t(string $key, $params = null): ?string
{
@@ -46,10 +40,7 @@ function t(string $key, $params = null): ?string
/**
* Outputs the translation
* @param array|string|null $params
- * @throws ConfigException
- * @throws DiException
- * @throws LangException
- * @throws ReflectionException
+ * @throws LangException|LoaderException|ConfigException|DiException|ReflectionException
*/
function _t(string $key, $params = null): void
{
diff --git a/src/Lang/Lang.php b/src/Lang/Lang.php
index c473177f0..f8380a3ae 100644
--- a/src/Lang/Lang.php
+++ b/src/Lang/Lang.php
@@ -17,6 +17,8 @@
namespace Quantum\Lang;
use Quantum\Config\Exceptions\ConfigException;
+use Quantum\Loader\Exceptions\LoaderException;
+use Quantum\Lang\Exceptions\LangException;
use Quantum\App\Exceptions\BaseException;
use Quantum\Di\Exceptions\DiException;
use ReflectionException;
@@ -68,11 +70,7 @@ public function isEnabled(): bool
/**
* Load translations
- * @throws Exceptions\LangException
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws LangException|LoaderException|ConfigException|DiException|BaseException|ReflectionException
*/
public function load(): void
{
diff --git a/src/Lang/Translator.php b/src/Lang/Translator.php
index 3d5202eb8..be07408cd 100644
--- a/src/Lang/Translator.php
+++ b/src/Lang/Translator.php
@@ -17,6 +17,7 @@
namespace Quantum\Lang;
use Quantum\Config\Exceptions\ConfigException;
+use Quantum\Loader\Exceptions\LoaderException;
use Quantum\Lang\Exceptions\LangException;
use Quantum\App\Exceptions\BaseException;
use Quantum\Di\Exceptions\DiException;
@@ -40,11 +41,7 @@ public function __construct(string $lang)
/**
* Load translation files
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws LangException
- * @throws ReflectionException
+ * @throws LangException|LoaderException|ConfigException|DiException|BaseException|ReflectionException
*/
public function loadTranslations(): void
{
@@ -79,10 +76,7 @@ public function loadTranslations(): void
/**
* Load translations
* @param array $files
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
private function loadFiles(array $files): void
{
diff --git a/src/Loader/Setup.php b/src/Loader/Setup.php
index dabfbe4c3..1b8a76ac1 100644
--- a/src/Loader/Setup.php
+++ b/src/Loader/Setup.php
@@ -36,7 +36,6 @@ class Setup
protected string $exceptionMessage;
/**
- * Setup constructor.
* @throws DiException|ReflectionException
*/
public function __construct(?string $pathPrefix = null, ?string $fileName = null, bool $hierarchical = true, ?string $module = null, ?string $exceptionMessage = null)
diff --git a/src/Logger/Adapters/DailyAdapter.php b/src/Logger/Adapters/DailyAdapter.php
index 4bb390973..bb9ac97bf 100644
--- a/src/Logger/Adapters/DailyAdapter.php
+++ b/src/Logger/Adapters/DailyAdapter.php
@@ -36,11 +36,7 @@ class DailyAdapter implements ReportableInterface
/**
* DailyAdapter constructor
* @param array $params
- * @throws BaseException
- * @throws LoggerException
- * @throws DiException
- * @throws ConfigException
- * @throws ReflectionException
+ * @throws LoggerException|ConfigException|DiException|BaseException|ReflectionException
*/
public function __construct(array $params)
{
diff --git a/src/Logger/Adapters/MessageAdapter.php b/src/Logger/Adapters/MessageAdapter.php
index 15ac4a3f5..f880e4669 100644
--- a/src/Logger/Adapters/MessageAdapter.php
+++ b/src/Logger/Adapters/MessageAdapter.php
@@ -17,8 +17,11 @@
namespace Quantum\Logger\Adapters;
use Quantum\Logger\Contracts\ReportableInterface;
+use Quantum\Di\Exceptions\DiException;
use DebugBar\DebugBarException;
use Quantum\Debugger\Debugger;
+use ReflectionException;
+use Quantum\Di\Di;
/**
* Class MessageAdapter
@@ -30,11 +33,19 @@ class MessageAdapter implements ReportableInterface
* @param array|null $context
* @throws DebugBarException
*/
+
+ /**
+ * @throws DiException|ReflectionException
+ */
public function report(string $level, string $message, ?array $context = []): void
{
$tab = $context['tab'] ?? Debugger::MESSAGES;
- $debugger = Debugger::getInstance();
+ if (!Di::isRegistered(Debugger::class)) {
+ Di::register(Debugger::class);
+ }
+
+ $debugger = Di::get(Debugger::class);
if ($debugger->isEnabled()) {
$debugger->addToStoreCell($tab, $level, $message);
diff --git a/src/Logger/Adapters/SingleAdapter.php b/src/Logger/Adapters/SingleAdapter.php
index 2c9d669d0..2d042a7a5 100644
--- a/src/Logger/Adapters/SingleAdapter.php
+++ b/src/Logger/Adapters/SingleAdapter.php
@@ -33,16 +33,10 @@ class SingleAdapter implements ReportableInterface
{
use LoggerTrait;
- /**
- * @throws BaseException
- * @throws LoggerException
- * @throws DiException
- * @throws ConfigException
- * @throws ReflectionException
- */
/**
* SingleAdapter constructor
* @param array $params
+ * @throws LoggerException|ConfigException|DiException|BaseException|ReflectionException
*/
public function __construct(array $params)
{
diff --git a/src/Logger/Contracts/ReportableInterface.php b/src/Logger/Contracts/ReportableInterface.php
index 699a2f7ce..5f5da1638 100644
--- a/src/Logger/Contracts/ReportableInterface.php
+++ b/src/Logger/Contracts/ReportableInterface.php
@@ -24,9 +24,7 @@ interface ReportableInterface
{
/**
* Reports a message
- * @param string $message
* @param array|null $context
- * @return void
*/
public function report(string $level, string $message, ?array $context = []): void;
diff --git a/src/Logger/Factories/LoggerFactory.php b/src/Logger/Factories/LoggerFactory.php
index 1feaf289e..b8884c5e1 100644
--- a/src/Logger/Factories/LoggerFactory.php
+++ b/src/Logger/Factories/LoggerFactory.php
@@ -29,6 +29,7 @@
use Quantum\Logger\Logger;
use Quantum\Loader\Setup;
use ReflectionException;
+use Quantum\Di\Di;
/**
* Class LoggerFactory
@@ -36,9 +37,6 @@
*/
class LoggerFactory
{
- /**
- * Supported adapters
- */
public const ADAPTERS = [
LoggerType::SINGLE => SingleAdapter::class,
LoggerType::DAILY => DailyAdapter::class,
@@ -48,15 +46,24 @@ class LoggerFactory
/**
* @var array
*/
- private static array $instances = [];
+ private array $instances = [];
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public static function get(?string $adapter = null): Logger
+ {
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve($adapter);
+ }
+
+ /**
+ * @throws ConfigException|DiException|BaseException|ReflectionException
+ */
+ public function resolve(?string $adapter = null): Logger
{
if (!config()->has('logging')) {
config()->import(new Setup('config', 'logging'));
@@ -70,20 +77,23 @@ public static function get(?string $adapter = null): Logger
$adapter = $isDebug ? LoggerType::MESSAGE : ($adapter ?? config()->get('logging.default'));
- $adapterClass = self::getAdapterClass($adapter);
+ $adapterClass = $this->getAdapterClass($adapter);
$logLevel = config()->get('logging.' . $adapter . '.level', 'error');
LoggerConfig::setAppLogLevel($logLevel);
- if (!isset(self::$instances[$adapter])) {
- self::$instances[$adapter] = self::createInstance($adapterClass, $adapter);
+ if (!isset($this->instances[$adapter])) {
+ $this->instances[$adapter] = $this->createInstance($adapterClass, $adapter);
}
- return self::$instances[$adapter];
+ return $this->instances[$adapter];
}
- private static function createInstance(string $adapterClass, string $adapter): Logger
+ /**
+ * @throws DiException|BaseException|ReflectionException
+ */
+ private function createInstance(string $adapterClass, string $adapter): Logger
{
if ($adapter === LoggerType::MESSAGE) {
return new Logger(new MessageAdapter());
@@ -101,7 +111,7 @@ private static function createInstance(string $adapterClass, string $adapter): L
/**
* @throws BaseException
*/
- private static function getAdapterClass(string $adapter): string
+ private function getAdapterClass(string $adapter): string
{
if (!array_key_exists($adapter, self::ADAPTERS)) {
throw LoggerException::adapterNotSupported($adapter);
diff --git a/src/Logger/Helpers/logger.php b/src/Logger/Helpers/logger.php
index 5a7d01d45..4131900d7 100644
--- a/src/Logger/Helpers/logger.php
+++ b/src/Logger/Helpers/logger.php
@@ -19,10 +19,7 @@
use Quantum\Logger\Logger;
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function logger(?string $adapter = null): Logger
{
@@ -31,12 +28,8 @@ function logger(?string $adapter = null): Logger
/**
* Reports error
- * @param string $var
* @param array $context
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function error(string $var, array $context = []): void
{
@@ -45,12 +38,8 @@ function error(string $var, array $context = []): void
/**
* Reports warning
- * @param string $var
* @param array $context
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function warning(string $var, array $context = []): void
{
@@ -59,12 +48,8 @@ function warning(string $var, array $context = []): void
/**
* Reports notice
- * @param string $var
* @param array $context
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function notice(string $var, array $context = []): void
{
@@ -73,12 +58,8 @@ function notice(string $var, array $context = []): void
/**
* Reports info
- * @param string $var
* @param array $context
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function info(string $var, array $context = []): void
{
@@ -87,12 +68,8 @@ function info(string $var, array $context = []): void
/**
* Reports debug
- * @param string $var
* @param array $context
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function debug(string $var, array $context = []): void
{
diff --git a/src/Logger/Traits/LoggerTrait.php b/src/Logger/Traits/LoggerTrait.php
index 19159edd6..593017b2a 100644
--- a/src/Logger/Traits/LoggerTrait.php
+++ b/src/Logger/Traits/LoggerTrait.php
@@ -25,15 +25,9 @@
*/
trait LoggerTrait
{
- /**
- * @var FileSystem
- */
- protected $fs;
+ protected FileSystem $fs;
- /**
- * @var string
- */
- protected $logFile;
+ protected string $logFile;
/**
* Initialize the logger
@@ -43,7 +37,6 @@ abstract protected function initialize(array $params): void;
/**
* Reports a log message
- * @param string $message
* @param array|null $context
*/
public function report(string $level, string $message, ?array $context = []): void
diff --git a/src/Mailer/Adapters/MailgunAdapter.php b/src/Mailer/Adapters/MailgunAdapter.php
index e4dccb628..1ae1c7624 100644
--- a/src/Mailer/Adapters/MailgunAdapter.php
+++ b/src/Mailer/Adapters/MailgunAdapter.php
@@ -31,10 +31,7 @@ class MailgunAdapter implements MailerInterface
public string $name = 'Mailgun';
- /**
- * @var string
- */
- private $apiKey;
+ private string $apiKey;
private string $apiUrl = 'https://api.mailgun.net/v3/';
diff --git a/src/Mailer/Adapters/MandrillAdapter.php b/src/Mailer/Adapters/MandrillAdapter.php
index 1b7c87975..e34b3400e 100644
--- a/src/Mailer/Adapters/MandrillAdapter.php
+++ b/src/Mailer/Adapters/MandrillAdapter.php
@@ -29,10 +29,7 @@ class MandrillAdapter implements MailerInterface
{
use MailerTrait;
- /**
- * @var string
- */
- public $name = 'Mandrill';
+ public string $name = 'Mandrill';
private string $apiUrl = 'https://mandrillapp.com/api/1.0/messages/send.json';
diff --git a/src/Mailer/Adapters/ResendAdapter.php b/src/Mailer/Adapters/ResendAdapter.php
index 51400ae02..50c4bce78 100644
--- a/src/Mailer/Adapters/ResendAdapter.php
+++ b/src/Mailer/Adapters/ResendAdapter.php
@@ -33,10 +33,7 @@ class ResendAdapter implements MailerInterface
private HttpClient $httpClient;
- /**
- * @var string|null
- */
- private $apiKey;
+ private string $apiKey;
private string $apiUrl = 'https://api.resend.com/emails';
diff --git a/src/Mailer/Adapters/SendgridAdapter.php b/src/Mailer/Adapters/SendgridAdapter.php
index 8201d7a0a..7e4e0a9b9 100644
--- a/src/Mailer/Adapters/SendgridAdapter.php
+++ b/src/Mailer/Adapters/SendgridAdapter.php
@@ -31,10 +31,7 @@ class SendgridAdapter implements MailerInterface
public string $name = 'Sendgrid';
- /**
- * @var string
- */
- private $apiKey;
+ private string $apiKey;
private string $apiUrl = 'https://api.sendgrid.com/v3/mail/send';
diff --git a/src/Mailer/Adapters/SendinblueAdapter.php b/src/Mailer/Adapters/SendinblueAdapter.php
index bf0e9368e..0ee1f30b5 100644
--- a/src/Mailer/Adapters/SendinblueAdapter.php
+++ b/src/Mailer/Adapters/SendinblueAdapter.php
@@ -31,10 +31,7 @@ class SendinblueAdapter implements MailerInterface
public string $name = 'Sendinblue';
- /**
- * @var string
- */
- private $apiKey;
+ private string $apiKey;
private string $apiUrl = 'https://api.sendinblue.com/v3/smtp/email';
diff --git a/src/Mailer/Adapters/SmtpAdapter.php b/src/Mailer/Adapters/SmtpAdapter.php
index 85c8cee52..fba991716 100644
--- a/src/Mailer/Adapters/SmtpAdapter.php
+++ b/src/Mailer/Adapters/SmtpAdapter.php
@@ -17,10 +17,12 @@
namespace Quantum\Mailer\Adapters;
use Quantum\Mailer\Contracts\MailerInterface;
+use Quantum\Di\Exceptions\DiException;
use Quantum\Mailer\Traits\MailerTrait;
use PHPMailer\PHPMailer\PHPMailer;
use Quantum\Debugger\Debugger;
use PHPMailer\PHPMailer\SMTP;
+use ReflectionException;
use Exception;
/**
@@ -38,6 +40,7 @@ class SmtpAdapter implements MailerInterface
/**
* SmtpAdapter constructor
* @param array $params
+ * @throws DiException|ReflectionException
*/
public function __construct(array $params)
{
diff --git a/src/Mailer/Factories/MailerFactory.php b/src/Mailer/Factories/MailerFactory.php
index 65a2d2933..e98e48fbb 100644
--- a/src/Mailer/Factories/MailerFactory.php
+++ b/src/Mailer/Factories/MailerFactory.php
@@ -31,6 +31,7 @@
use Quantum\Mailer\Mailer;
use Quantum\Loader\Setup;
use ReflectionException;
+use Quantum\Di\Di;
/**
* class MailerFactory
@@ -38,9 +39,6 @@
*/
class MailerFactory
{
- /**
- * Supported adapters
- */
public const ADAPTERS = [
MailerType::SMTP => SmtpAdapter::class,
MailerType::MAILGUN => MailgunAdapter::class,
@@ -53,15 +51,24 @@ class MailerFactory
/**
* @var array
*/
- private static array $instances = [];
+ private array $instances = [];
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public static function get(?string $adapter = null): Mailer
+ {
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve($adapter);
+ }
+
+ /**
+ * @throws ConfigException|DiException|BaseException|ReflectionException
+ */
+ public function resolve(?string $adapter = null): Mailer
{
if (!config()->has('mailer')) {
config()->import(new Setup('config', 'mailer'));
@@ -69,19 +76,19 @@ public static function get(?string $adapter = null): Mailer
$adapter ??= config()->get('mailer.default');
- $adapterClass = self::getAdapterClass($adapter);
+ $adapterClass = $this->getAdapterClass($adapter);
- if (!isset(self::$instances[$adapter])) {
- self::$instances[$adapter] = self::createInstance($adapterClass, $adapter);
+ if (!isset($this->instances[$adapter])) {
+ $this->instances[$adapter] = $this->createInstance($adapterClass, $adapter);
}
- return self::$instances[$adapter];
+ return $this->instances[$adapter];
}
/**
- * @throws MailerException
+ * @throws DiException|BaseException|ReflectionException
*/
- private static function createInstance(string $adapterClass, string $adapter): Mailer
+ private function createInstance(string $adapterClass, string $adapter): Mailer
{
$adapterInstance = new $adapterClass(config()->get('mailer.' . $adapter));
@@ -95,7 +102,7 @@ private static function createInstance(string $adapterClass, string $adapter): M
/**
* @throws BaseException
*/
- private static function getAdapterClass(string $adapter): string
+ private function getAdapterClass(string $adapter): string
{
if (!array_key_exists($adapter, self::ADAPTERS)) {
throw MailerException::adapterNotSupported($adapter);
diff --git a/src/Mailer/MailTrap.php b/src/Mailer/MailTrap.php
index dd275c560..67ff8efe9 100644
--- a/src/Mailer/MailTrap.php
+++ b/src/Mailer/MailTrap.php
@@ -42,8 +42,6 @@ class MailTrap
*/
private $message;
- private static ?MailTrap $instance = null;
-
private string $emailsDirectory;
/**
@@ -52,25 +50,13 @@ class MailTrap
* @throws DiException
* @throws ReflectionException
*/
- private function __construct()
+ public function __construct()
{
$this->fs = FileSystemFactory::get();
$this->parser = new MessageParser();
$this->emailsDirectory = base_dir() . DS . 'shared' . DS . 'emails';
}
- /**
- * Get Instance
- */
- public static function getInstance(): MailTrap
- {
- if (self::$instance === null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
-
/**
* Saves the message on the local file
*/
diff --git a/src/Mailer/Traits/MailerTrait.php b/src/Mailer/Traits/MailerTrait.php
index 9f8d0e0d3..942e8a329 100644
--- a/src/Mailer/Traits/MailerTrait.php
+++ b/src/Mailer/Traits/MailerTrait.php
@@ -21,6 +21,7 @@
use Quantum\Debugger\Debugger;
use Quantum\Mailer\MailTrap;
use ReflectionException;
+use Quantum\Di\Di;
use Exception;
/**
@@ -266,7 +267,11 @@ private function saveEmail(): bool
return false;
}
- return MailTrap::getInstance()->saveMessage($messageId, $this->getMessageContent());
+ if (!Di::isRegistered(MailTrap::class)) {
+ Di::register(MailTrap::class);
+ }
+
+ return Di::get(MailTrap::class)->saveMessage($messageId, $this->getMessageContent());
}
/**
diff --git a/src/Middleware/MiddlewareManager.php b/src/Middleware/MiddlewareManager.php
index 201306794..19e817771 100644
--- a/src/Middleware/MiddlewareManager.php
+++ b/src/Middleware/MiddlewareManager.php
@@ -17,6 +17,7 @@
namespace Quantum\Middleware;
use Quantum\Middleware\Exceptions\MiddlewareException;
+use Quantum\App\Exceptions\BaseException;
use Quantum\Router\MatchedRoute;
use Quantum\Http\Response;
use Quantum\Http\Request;
@@ -49,7 +50,7 @@ public function __construct(MatchedRoute $matchedRoute)
/**
* Apply Middlewares
* @return array{0: Request, 1: Response}
- * @throws MiddlewareException
+ * @throws MiddlewareException|BaseException
*/
public function applyMiddlewares(Request $request, Response $response): array
{
@@ -69,7 +70,7 @@ public function applyMiddlewares(Request $request, Response $response): array
/**
* Loads and gets the current middleware instance
- * @throws MiddlewareException
+ * @throws MiddlewareException|BaseException
*/
private function getMiddleware(Request $request, Response $response): QtMiddleware
{
diff --git a/src/Migration/MigrationManager.php b/src/Migration/MigrationManager.php
index 34e707549..aef60cb04 100644
--- a/src/Migration/MigrationManager.php
+++ b/src/Migration/MigrationManager.php
@@ -23,12 +23,12 @@
use Quantum\Storage\Factories\FileSystemFactory;
use Quantum\Config\Exceptions\ConfigException;
use Quantum\Database\Factories\TableFactory;
-use Quantum\Lang\Exceptions\LangException;
use Quantum\App\Exceptions\BaseException;
use Quantum\Di\Exceptions\DiException;
use Quantum\Storage\FileSystem;
use Quantum\Database\Database;
use ReflectionException;
+use Quantum\Di\Di;
/**
* Class MigrationManager
@@ -71,17 +71,17 @@ class MigrationManager
private Database $db;
/**
- * @throws BaseException
- * @throws DiException
- * @throws FileSystemException
- * @throws ConfigException
- * @throws ReflectionException
+ * @throws BaseException|ConfigException|DiException|FileSystemException|ReflectionException
*/
public function __construct()
{
$this->fs = FileSystemFactory::get();
- $this->db = Database::getInstance();
+ if (!Di::isRegistered(Database::class)) {
+ Di::register(Database::class);
+ }
+
+ $this->db = Di::get(Database::class);
$this->tableFactory = new TableFactory();
@@ -95,7 +95,6 @@ public function __construct()
/**
* Generates new migration file
* @throws MigrationException
- * @throws LangException
*/
public function generateMigration(string $table, string $action): string
{
@@ -114,10 +113,7 @@ public function generateMigration(string $table, string $action): string
/**
* Applies migrations
- * @throws BaseException
- * @throws DatabaseException
- * @throws LangException
- * @throws MigrationException
+ * @throws MigrationException|DatabaseException|BaseException|DiException|ReflectionException
*/
public function applyMigrations(string $direction, ?int $step = null): ?int
{
@@ -144,8 +140,7 @@ public function applyMigrations(string $direction, ?int $step = null): ?int
/**
* Runs up migrations
- * @throws DatabaseException
- * @throws MigrationException
+ * @throws MigrationException|DatabaseException|DiException|ReflectionException
*/
private function upgrade(): int
{
@@ -182,8 +177,7 @@ private function upgrade(): int
/**
* Runs down migrations
- * @throws DatabaseException
- * @throws MigrationException
+ * @throws MigrationException|DatabaseException|DiException|ReflectionException
*/
private function downgrade(?int $step): int
{
@@ -222,9 +216,7 @@ private function downgrade(?int $step): int
/**
* Prepares up migrations
- * @throws MigrationException
- * @throws DatabaseException
- *
+ * @throws MigrationException|DiException|ReflectionException
*/
private function prepareUpMigrations(): void
{
@@ -249,8 +241,7 @@ private function prepareUpMigrations(): void
/**
* Prepares down migrations
- * @throws DatabaseException
- * @throws MigrationException
+ * @throws MigrationException|DiException|ReflectionException
*/
private function prepareDownMigrations(?int $step = null): void
{
@@ -295,7 +286,7 @@ private function getMigrationFiles(): array
/**
* Gets migrated entries from migrations table
* @return array
- * @throws DatabaseException
+ * @throws DiException|ReflectionException
*/
private function getMigratedEntries(): array
{
@@ -305,7 +296,7 @@ private function getMigratedEntries(): array
/**
* Adds migrated entries to migrations table
* @param array $entries
- * @throws DatabaseException
+ * @throws DiException|ReflectionException
*/
private function addMigratedEntries(array $entries): void
{
@@ -317,7 +308,7 @@ private function addMigratedEntries(array $entries): void
/**
* Removes migrated entries from migrations table
* @param array $entries
- * @throws DatabaseException
+ * @throws DiException|ReflectionException
*/
private function removeMigratedEntries(array $entries): void
{
diff --git a/src/Model/DbModel.php b/src/Model/DbModel.php
index 49820ba77..300c3a50f 100644
--- a/src/Model/DbModel.php
+++ b/src/Model/DbModel.php
@@ -214,7 +214,7 @@ public function hydrateFromOrm(array $data): self
/**
* @param array $args
* @return mixed
- * @throws ModelException
+ * @throws ModelException|BaseException
*/
public function __call(string $method, array $args = [])
{
diff --git a/src/Model/Factories/ModelFactory.php b/src/Model/Factories/ModelFactory.php
index b0f75189d..f7ad35fe1 100644
--- a/src/Model/Factories/ModelFactory.php
+++ b/src/Model/Factories/ModelFactory.php
@@ -18,9 +18,13 @@
use Quantum\Database\Contracts\DbalInterface;
use Quantum\Model\Exceptions\ModelException;
+use Quantum\App\Exceptions\BaseException;
+use Quantum\Di\Exceptions\DiException;
use Quantum\Database\Database;
use Quantum\Model\DbModel;
use Quantum\Model\Model;
+use ReflectionException;
+use Quantum\Di\Di;
/**
* Class ModelFactory
@@ -33,7 +37,7 @@ class ModelFactory
* @template T of Model
* @param class-string $modelClass
* @return T
- * @throws ModelException
+ * @throws ModelException|BaseException|ReflectionException
*/
public static function get(string $modelClass): Model
{
@@ -66,6 +70,7 @@ public static function get(string $modelClass): Model
* Creates anonymous dynamic model
* @param array $foreignKeys
* @param array $hidden
+ * @throws DiException|BaseException|ReflectionException
*/
public static function createDynamicModel(
string $table,
@@ -92,6 +97,7 @@ public static function createDynamicModel(
/**
* @param array $foreignKeys
* @param array $hidden
+ * @throws DiException|BaseException|ReflectionException
*/
protected static function createOrmInstance(
string $table,
@@ -100,7 +106,11 @@ protected static function createOrmInstance(
array $foreignKeys = [],
array $hidden = []
): DbalInterface {
- $ormClass = Database::getInstance()->getOrmClass();
+ if (!Di::isRegistered(Database::class)) {
+ Di::register(Database::class);
+ }
+
+ $ormClass = Di::get(Database::class)->getOrmClass();
$instance = new $ormClass(
$table,
diff --git a/src/Model/Helpers/model.php b/src/Model/Helpers/model.php
index 9341f90cb..4d7ed4686 100644
--- a/src/Model/Helpers/model.php
+++ b/src/Model/Helpers/model.php
@@ -14,6 +14,7 @@
use Quantum\Database\Contracts\DbalInterface;
use Quantum\Model\Exceptions\ModelException;
+use Quantum\App\Exceptions\BaseException;
use Quantum\Model\Factories\ModelFactory;
use Quantum\Model\DbModel;
use Quantum\Model\Model;
@@ -22,7 +23,7 @@
* Gets the model instance
* @param class-string $modelClass
* @return T
- * @throws ModelException
+ * @throws ModelException|BaseException|ReflectionException
* @template T of Model
*/
function model(string $modelClass): Model
@@ -53,7 +54,7 @@ function dynamicModel(
/**
* Wraps the orm instance into model
- * @throws ModelException
+ * @throws ModelException|BaseException
*/
function wrapToModel(?DbalInterface $ormInstance, string $modelClass): ?DbModel
{
diff --git a/src/Model/Traits/SoftDeletes.php b/src/Model/Traits/SoftDeletes.php
index ee1ee2708..afacfc6e7 100644
--- a/src/Model/Traits/SoftDeletes.php
+++ b/src/Model/Traits/SoftDeletes.php
@@ -132,8 +132,8 @@ public function findOne(int $id): ?DbModel
/**
* Find one record by column and value, excluding soft deleted unless withTrashed() is called.
- * @param $value
- * @throws BaseException
+ * @param mixed $value
+ * @throws ModelException|BaseException
*/
public function findOneBy(string $column, $value): ?DbModel
{
diff --git a/src/Module/ModuleLoader.php b/src/Module/ModuleLoader.php
index 72be6b718..fcb839ab2 100644
--- a/src/Module/ModuleLoader.php
+++ b/src/Module/ModuleLoader.php
@@ -37,55 +37,40 @@ class ModuleLoader
/**
* @var array>
*/
- private static array $moduleDependencies = [];
+ private array $moduleDependencies = [];
/**
* @var array>
*/
- private static array $moduleConfigs = [];
+ private array $moduleConfigs = [];
/** @var array */
- private static array $moduleRouteClosures = [];
+ private array $moduleRouteClosures = [];
private FileSystem $fs;
- private static ?ModuleLoader $instance = null;
-
/**
- * @throws BaseException
- * @throws DiException
- * @throws ConfigException
- * @throws ReflectionException|ModuleException
+ * @throws ModuleException|ConfigException|DiException|BaseException|ReflectionException
*/
- private function __construct()
+ public function __construct()
{
$this->fs = FileSystemFactory::get();
Di::registerDependencies($this->loadModulesDependencies());
}
- public static function getInstance(): ModuleLoader
- {
- if (self::$instance === null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
-
/**
* @return array
- * @throws ModuleException
- * @throws RouteException
+ * @throws ModuleException|RouteException
*/
public function loadModulesRoutes(): array
{
- if (empty(self::$moduleConfigs)) {
+ if (empty($this->moduleConfigs)) {
$this->loadModuleConfig();
}
$modulesRoutes = [];
- foreach (self::$moduleConfigs as $module => $options) {
+ foreach ($this->moduleConfigs as $module => $options) {
if (!$this->isModuleEnabled($options)) {
continue;
}
@@ -97,13 +82,12 @@ public function loadModulesRoutes(): array
}
/**
- * @throws ModuleException
- * @throws RouteException
+ * @throws ModuleException|RouteException
*/
private function getModuleRouteDefinitions(string $module): Closure
{
- if (isset(self::$moduleRouteClosures[$module])) {
- return self::$moduleRouteClosures[$module];
+ if (isset($this->moduleRouteClosures[$module])) {
+ return $this->moduleRouteClosures[$module];
}
$moduleRoutesPath = modules_dir() . DS . $module . DS . 'routes' . DS . 'routes.php';
@@ -112,13 +96,13 @@ private function getModuleRouteDefinitions(string $module): Closure
throw ModuleException::moduleRoutesNotFound($module);
}
- $closure = $this->fs->require($moduleRoutesPath, true);
+ $closure = $this->fs->require($moduleRoutesPath);
if (!$closure instanceof Closure) {
throw RouteException::notClosure();
}
- return self::$moduleRouteClosures[$module] = $closure;
+ return $this->moduleRouteClosures[$module] = $closure;
}
/**
@@ -127,13 +111,13 @@ private function getModuleRouteDefinitions(string $module): Closure
*/
public function loadModulesDependencies(): array
{
- if (empty(self::$moduleConfigs)) {
+ if (empty($this->moduleConfigs)) {
$this->loadModuleConfig();
}
$modulesDependencies = [];
- foreach (self::$moduleConfigs as $module => $options) {
+ foreach ($this->moduleConfigs as $module => $options) {
$modulesDependencies = array_merge($modulesDependencies, $this->getModuleDependencies($module));
}
@@ -145,19 +129,19 @@ public function loadModulesDependencies(): array
*/
public function getModuleDependencies(string $module): array
{
- if (!isset(self::$moduleDependencies[$module])) {
+ if (!isset($this->moduleDependencies[$module])) {
$file = modules_dir() . DS . $module . DS . 'config' . DS . 'dependencies.php';
if ($this->fs->exists($file)) {
$deps = $this->fs->require($file);
- self::$moduleDependencies[$module] = is_array($deps) ? $deps : [];
+ $this->moduleDependencies[$module] = is_array($deps) ? $deps : [];
} else {
- self::$moduleDependencies[$module] = [];
+ $this->moduleDependencies[$module] = [];
}
}
- return self::$moduleDependencies[$module];
+ return $this->moduleDependencies[$module];
}
/**
@@ -171,7 +155,7 @@ private function loadModuleConfig(): void
throw ModuleException::moduleConfigNotFound();
}
- self::$moduleConfigs = $this->fs->require($configPath);
+ $this->moduleConfigs = $this->fs->require($configPath);
}
/**
@@ -180,11 +164,11 @@ private function loadModuleConfig(): void
*/
public function getModuleConfigs(): array
{
- if (empty(self::$moduleConfigs)) {
+ if (empty($this->moduleConfigs)) {
$this->loadModuleConfig();
}
- return self::$moduleConfigs;
+ return $this->moduleConfigs;
}
/**
diff --git a/src/Module/ModuleManager.php b/src/Module/ModuleManager.php
index 435c7da88..df9fc92c0 100644
--- a/src/Module/ModuleManager.php
+++ b/src/Module/ModuleManager.php
@@ -24,6 +24,7 @@
use Quantum\Di\Exceptions\DiException;
use Quantum\Storage\FileSystem;
use ReflectionException;
+use Quantum\Di\Di;
use Exception;
/**
@@ -53,10 +54,7 @@ class ModuleManager
private string $modulesConfigPath;
/**
- * @throws BaseException
- * @throws DiException
- * @throws ConfigException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public function __construct(string $moduleName, string $template, bool $enabled, bool $withAssets = false)
{
@@ -80,9 +78,7 @@ public function getModuleName(): string
}
/**
- * @throws ModuleException
- * @throws ExceptionInterface
- * @throws Exception
+ * @throws ModuleException|ExceptionInterface|Exception
*/
public function addModuleConfig(): void
{
@@ -90,7 +86,11 @@ public function addModuleConfig(): void
throw ModuleException::missingModuleDirectory();
}
- $moduleConfigs = ModuleLoader::getInstance()->getModuleConfigs();
+ if (!Di::isRegistered(ModuleLoader::class)) {
+ Di::register(ModuleLoader::class);
+ }
+
+ $moduleConfigs = Di::get(ModuleLoader::class)->getModuleConfigs();
foreach ($moduleConfigs as $module => $options) {
if ($module == $this->moduleName || $options['prefix'] == strtolower($this->moduleName)) {
diff --git a/src/Module/Templates/DemoWeb/src/Controllers/BaseController.php.tpl b/src/Module/Templates/DemoWeb/src/Controllers/BaseController.php.tpl
index 6fcecf557..941a3e660 100644
--- a/src/Module/Templates/DemoWeb/src/Controllers/BaseController.php.tpl
+++ b/src/Module/Templates/DemoWeb/src/Controllers/BaseController.php.tpl
@@ -16,7 +16,6 @@ namespace {{MODULE_NAMESPACE}}\Controllers;
use Quantum\View\Factories\ViewFactory;
use Quantum\Asset\Asset;
-use Quantum\Http\Request;
use Quantum\View\QtView;
/**
@@ -33,7 +32,7 @@ abstract class BaseController
public function __before()
{
- if (Request::isMethod('get')) {
+ if (request()->isMethod('get')) {
$this->view = ViewFactory::get();
$this->view->setLayout(static::LAYOUT, [
diff --git a/src/Module/Templates/DemoWeb/src/Controllers/PostController.php.tpl b/src/Module/Templates/DemoWeb/src/Controllers/PostController.php.tpl
index 261351792..a00b87883 100644
--- a/src/Module/Templates/DemoWeb/src/Controllers/PostController.php.tpl
+++ b/src/Module/Templates/DemoWeb/src/Controllers/PostController.php.tpl
@@ -72,7 +72,7 @@ class PostController extends BaseController
'title' => t('common.posts') . ' | ' . config()->get('app.name'),
'posts' => $this->postService->transformData($paginatedPosts->data()->all()),
'pagination' => $paginatedPosts,
- 'referer' => nav_ref_encode(Request::getQuery())
+ 'referer' => nav_ref_encode(request()->getQuery())
]);
$response->html($this->view->render('post/post'));
diff --git a/src/Module/Templates/Toolkit/src/Services/EmailService.php.tpl b/src/Module/Templates/Toolkit/src/Services/EmailService.php.tpl
index 67167d5a8..df3a33b8d 100644
--- a/src/Module/Templates/Toolkit/src/Services/EmailService.php.tpl
+++ b/src/Module/Templates/Toolkit/src/Services/EmailService.php.tpl
@@ -19,10 +19,11 @@ use Quantum\Storage\Exceptions\FileSystemException;
use Quantum\Paginator\Factories\PaginatorFactory;
use Quantum\Paginator\Enums\PaginatorType;
use Quantum\App\Exceptions\BaseException;
-use Quantum\Mailer\MailTrap;
use Quantum\Paginator\Paginator;
use Quantum\Service\QtService;
+use Quantum\Mailer\MailTrap;
use ReflectionException;
+use Quantum\Di\Di;
/**
* Class EmailService
@@ -50,7 +51,7 @@ class EmailService extends QtService
*/
public function getEmails(int $perPage, int $currentPage): Paginator
{
- $mailTrap = MailTrap::getInstance();
+ $mailTrap = Di::get(MailTrap::class);
$emailFiles = fs()->listDirectory($this->emailsDirectory);
@@ -87,7 +88,7 @@ class EmailService extends QtService
*/
public function getEmail(string $emailId): MailTrap
{
- $mailTrap = MailTrap::getInstance();
+ $mailTrap = Di::get(MailTrap::class);
return $mailTrap->parseMessage($emailId);
}
diff --git a/src/Paginator/Adapters/ArrayPaginator.php b/src/Paginator/Adapters/ArrayPaginator.php
index 38f5b411e..43725791a 100644
--- a/src/Paginator/Adapters/ArrayPaginator.php
+++ b/src/Paginator/Adapters/ArrayPaginator.php
@@ -18,6 +18,8 @@
use Quantum\Paginator\Contracts\PaginatorInterface;
use Quantum\Paginator\Traits\PaginatorTrait;
+use Quantum\Di\Exceptions\DiException;
+use ReflectionException;
/**
* Class ArrayPaginator
@@ -34,6 +36,7 @@ class ArrayPaginator implements PaginatorInterface
/**
* @param array $items
+ * @throws DiException|ReflectionException
*/
public function __construct(array $items, int $perPage, int $page = 1)
{
diff --git a/src/Paginator/Adapters/ModelPaginator.php b/src/Paginator/Adapters/ModelPaginator.php
index 59bf30e88..b4bac85c3 100644
--- a/src/Paginator/Adapters/ModelPaginator.php
+++ b/src/Paginator/Adapters/ModelPaginator.php
@@ -19,9 +19,11 @@
use Quantum\Paginator\Contracts\PaginatorInterface;
use Quantum\Paginator\Traits\PaginatorTrait;
use Quantum\App\Exceptions\BaseException;
+use Quantum\Di\Exceptions\DiException;
use Quantum\Model\ModelCollection;
use Quantum\Model\DbModel;
use Quantum\Model\Model;
+use ReflectionException;
/**
* Class ModelPaginator
@@ -35,6 +37,9 @@ class ModelPaginator implements PaginatorInterface
private DbModel $model;
+ /**
+ * @throws DiException|ReflectionException
+ */
public function __construct(DbModel $model, int $perPage, int $page = 1)
{
$this->initialize($perPage, $page);
diff --git a/src/Paginator/Traits/PaginatorTrait.php b/src/Paginator/Traits/PaginatorTrait.php
index 00dd0c0b0..460032a82 100644
--- a/src/Paginator/Traits/PaginatorTrait.php
+++ b/src/Paginator/Traits/PaginatorTrait.php
@@ -17,6 +17,7 @@
namespace Quantum\Paginator\Traits;
use Quantum\Config\Exceptions\ConfigException;
+use Quantum\Loader\Exceptions\LoaderException;
use Quantum\Lang\Exceptions\LangException;
use Quantum\Paginator\Enums\Pagination;
use Quantum\Di\Exceptions\DiException;
@@ -105,6 +106,7 @@ public function lastPageNumber(): int
/**
* Get the current page link
+ * @throws DiException|ReflectionException
*/
public function currentPageLink(bool $withBaseUrl = false): ?string
{
@@ -113,6 +115,7 @@ public function currentPageLink(bool $withBaseUrl = false): ?string
/**
* Get first page link
+ * @throws DiException|ReflectionException
*/
public function firstPageLink(bool $withBaseUrl = false): ?string
{
@@ -121,6 +124,7 @@ public function firstPageLink(bool $withBaseUrl = false): ?string
/**
* Get previous page link
+ * @throws DiException|ReflectionException
*/
public function previousPageLink(bool $withBaseUrl = false): ?string
{
@@ -129,6 +133,7 @@ public function previousPageLink(bool $withBaseUrl = false): ?string
/**
* Get next page link
+ * @throws DiException|ReflectionException
*/
public function nextPageLink(bool $withBaseUrl = false): ?string
{
@@ -137,6 +142,7 @@ public function nextPageLink(bool $withBaseUrl = false): ?string
/**
* Get last page link
+ * @throws DiException|ReflectionException
*/
public function lastPageLink(bool $withBaseUrl = false): ?string
{
@@ -154,6 +160,7 @@ public function perPage(): int
/**
* Get all page links
* @return array
+ * @throws DiException|ReflectionException
*/
public function links(bool $withBaseUrl = false): array
{
@@ -240,7 +247,7 @@ protected function getPageLink(?int $pageNumber, bool $withBaseUrl = false): ?st
/**
* Get next page item HTML
- * @throws DiException|ReflectionException|ConfigException|LangException
+ * @throws LoaderException|ConfigException|DiException|ReflectionException|LangException
*/
protected function getNextPageItem(?string $nextPageLink): string
{
@@ -260,7 +267,7 @@ protected function getNextPageItem(?string $nextPageLink): string
*/
/**
* Get previous page item HTML
- * @throws ConfigException|DiException|LangException|ReflectionException
+ * @throws LoaderException|ConfigException|DiException|LangException|ReflectionException
*/
protected function getPreviousPageItem(?string $previousPageLink): string
{
diff --git a/src/Renderer/Adapters/HtmlAdapter.php b/src/Renderer/Adapters/HtmlAdapter.php
index 1b1082c16..6f20982dc 100644
--- a/src/Renderer/Adapters/HtmlAdapter.php
+++ b/src/Renderer/Adapters/HtmlAdapter.php
@@ -40,10 +40,7 @@ class HtmlAdapter implements TemplateRendererInterface
/**
* @param array|null $configs
- * @throws BaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws ConfigException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public function __construct(?array $configs = [])
{
diff --git a/src/Renderer/Adapters/TwigAdapter.php b/src/Renderer/Adapters/TwigAdapter.php
index 4a5a52ba4..5c18dc0c3 100644
--- a/src/Renderer/Adapters/TwigAdapter.php
+++ b/src/Renderer/Adapters/TwigAdapter.php
@@ -46,10 +46,7 @@ class TwigAdapter implements TemplateRendererInterface
/**
* @param array|null $configs
- * @throws BaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws ConfigException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public function __construct(?array $configs = [])
{
@@ -61,7 +58,7 @@ public function __construct(?array $configs = [])
/**
* Renders the view
* @param array $params
- * @throws DiException|LoaderError|ReflectionException|RendererException|RuntimeError|SyntaxError
+ * @throws RendererException|LoaderError|DiException|BaseException|ReflectionException|RuntimeError|SyntaxError
*/
public function render(string $view, array $params = []): string
{
@@ -75,7 +72,7 @@ public function render(string $view, array $params = []): string
}
/**
- * @throws RendererException|DiException|ReflectionException
+ * @throws RendererException|DiException|BaseException|ReflectionException
*/
private function getLoader(string $view): FilesystemLoader
{
diff --git a/src/Renderer/Factories/RendererFactory.php b/src/Renderer/Factories/RendererFactory.php
index 4112f888f..4da6c59ff 100644
--- a/src/Renderer/Factories/RendererFactory.php
+++ b/src/Renderer/Factories/RendererFactory.php
@@ -27,6 +27,7 @@
use Quantum\Renderer\Renderer;
use Quantum\Loader\Setup;
use ReflectionException;
+use Quantum\Di\Di;
/**
* Class RendererFactory
@@ -34,9 +35,6 @@
*/
class RendererFactory
{
- /**
- * Supported adapters
- */
public const ADAPTERS = [
RendererType::HTML => HtmlAdapter::class,
RendererType::TWIG => TwigAdapter::class,
@@ -45,15 +43,24 @@ class RendererFactory
/**
* @var array
*/
- private static array $instances = [];
+ private array $instances = [];
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|BaseException|DiException|ReflectionException
*/
public static function get(?string $adapter = null): Renderer
+ {
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve($adapter);
+ }
+
+ /**
+ * @throws ConfigException|BaseException|DiException|ReflectionException
+ */
+ public function resolve(?string $adapter = null): Renderer
{
if (!config()->has('view')) {
config()->import(new Setup('config', 'view'));
@@ -61,19 +68,19 @@ public static function get(?string $adapter = null): Renderer
$adapter ??= config()->get('view.default');
- $adapterClass = self::getAdapterClass($adapter);
+ $adapterClass = $this->getAdapterClass($adapter);
- if (!isset(self::$instances[$adapter])) {
- self::$instances[$adapter] = self::createInstance($adapterClass, $adapter);
+ if (!isset($this->instances[$adapter])) {
+ $this->instances[$adapter] = $this->createInstance($adapterClass, $adapter);
}
- return self::$instances[$adapter];
+ return $this->instances[$adapter];
}
/**
- * @throws RendererException
+ * @throws RendererException|BaseException|ReflectionException
*/
- private static function createInstance(string $adapterClass, string $adapter): Renderer
+ private function createInstance(string $adapterClass, string $adapter): Renderer
{
$adapterInstance = new $adapterClass(config()->get('view.' . $adapter));
@@ -87,7 +94,7 @@ private static function createInstance(string $adapterClass, string $adapter): R
/**
* @throws BaseException
*/
- private static function getAdapterClass(string $adapter): string
+ private function getAdapterClass(string $adapter): string
{
if (!array_key_exists($adapter, self::ADAPTERS)) {
throw RendererException::adapterNotSupported($adapter);
diff --git a/src/ResourceCache/ViewCache.php b/src/ResourceCache/ViewCache.php
index 35fe75517..41fdb9615 100644
--- a/src/ResourceCache/ViewCache.php
+++ b/src/ResourceCache/ViewCache.php
@@ -16,11 +16,9 @@
namespace Quantum\ResourceCache;
-use Quantum\Loader\Exceptions\LoaderException;
use Quantum\ResourceCache\Exceptions\ResourceCacheException;
-use Quantum\Database\Exceptions\DatabaseException;
-use Quantum\Session\Exceptions\SessionException;
use Quantum\Storage\Factories\FileSystemFactory;
+use Quantum\Loader\Exceptions\LoaderException;
use Quantum\Config\Exceptions\ConfigException;
use Quantum\App\Exceptions\BaseException;
use Quantum\Di\Exceptions\DiException;
@@ -39,10 +37,7 @@ class ViewCache
{
private ?string $cacheDir = null;
- /**
- * @var int
- */
- private $ttl = 300;
+ private int $ttl = 300;
private bool $isEnabled;
@@ -50,17 +45,6 @@ class ViewCache
private FileSystem $fs;
- private static ?ViewCache $instance = null;
-
- public static function getInstance(): ViewCache
- {
- if (self::$instance === null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
-
/**
* @throws DiException
* @throws Exception
@@ -83,7 +67,7 @@ public function setup(): void
$this->cacheDir = $this->getCacheDir();
- $this->ttl = config()->get('view_cache.ttl', $this->ttl);
+ $this->ttl = (int) config()->get('view_cache.ttl', $this->ttl);
$this->minification = filter_var(config()->get('view_cache.minify', $this->minification), FILTER_VALIDATE_BOOLEAN);
@@ -93,12 +77,7 @@ public function setup(): void
}
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DatabaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws SessionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public function serveCachedView(string $uri, Response $response): bool
{
@@ -114,10 +93,7 @@ public function serveCachedView(string $uri, Response $response): bool
}
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public function set(string $key, string $content): ViewCache
{
@@ -131,12 +107,7 @@ public function set(string $key, string $content): ViewCache
}
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DatabaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws SessionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public function get(string $key): ?string
{
@@ -165,10 +136,7 @@ public function delete(string $key): void
}
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public function exists(string $key): bool
{
@@ -196,9 +164,6 @@ public function enableMinification(bool $state): void
$this->minification = $state;
}
- /**
- * @param $cacheFile
- */
private function isExpired(string $cacheFile): bool
{
if (time() > ($this->fs->lastModified($cacheFile) + $this->ttl)) {
@@ -209,6 +174,9 @@ private function isExpired(string $cacheFile): bool
return false;
}
+ /**
+ * @throws DiException|ReflectionException
+ */
private function getCacheDir(): string
{
$configCacheDir = config()->get('view_cache.cache_dir', 'cache');
@@ -223,10 +191,7 @@ private function getCacheDir(): string
}
/**
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
- * @throws BaseException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
private function getCacheFile(string $key): string
{
diff --git a/src/Router/Helpers/router.php b/src/Router/Helpers/router.php
index d2261c2a8..beeba8096 100644
--- a/src/Router/Helpers/router.php
+++ b/src/Router/Helpers/router.php
@@ -13,7 +13,6 @@
*/
use Quantum\Di\Exceptions\DiException;
-use Quantum\Environment\Environment;
use Quantum\Router\RouteCollection;
use Quantum\Router\Route;
use Quantum\Http\Request;
@@ -26,8 +25,7 @@
*/
function current_middlewares(): ?array
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? $matchedRoute->getRoute()->getMiddlewares() : null;
}
@@ -39,8 +37,11 @@ function current_middlewares(): ?array
*/
function current_module(): ?string
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ if (!Di::has(Request::class)) {
+ return null;
+ }
+
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? $matchedRoute->getRoute()->getModule() : null;
}
@@ -52,8 +53,7 @@ function current_module(): ?string
*/
function current_controller(): ?string
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? $matchedRoute->getRoute()->getController() : null;
}
@@ -65,8 +65,7 @@ function current_controller(): ?string
*/
function current_action(): ?string
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? $matchedRoute->getRoute()->getAction() : null;
}
@@ -78,8 +77,7 @@ function current_action(): ?string
*/
function route_callback(): ?Closure
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? $matchedRoute->getRoute()->getClosure() : null;
}
@@ -91,8 +89,7 @@ function route_callback(): ?Closure
*/
function current_route(): ?string
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? $matchedRoute->getRoute()->getPattern() : null;
}
@@ -104,8 +101,7 @@ function current_route(): ?string
*/
function route_pattern(): string
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? ($matchedRoute->getRoute()->getCompiledPattern() ?? '') : '';
}
@@ -117,8 +113,7 @@ function route_pattern(): string
*/
function route_params(): array
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? $matchedRoute->getParams() : [];
}
@@ -142,8 +137,7 @@ function route_param(string $name)
*/
function route_method(): string
{
- $request = Di::get(Request::class);
- return $request->getMethod() ?? '';
+ return request()->getMethod() ?? '';
}
/**
@@ -153,8 +147,7 @@ function route_method(): string
*/
function route_uri(): ?string
{
- $request = Di::get(Request::class);
- return $request->getUri();
+ return request()->getUri();
}
/**
@@ -164,8 +157,7 @@ function route_uri(): ?string
*/
function route_cache_settings(): ?array
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? $matchedRoute->getRoute()->getCache() : null;
}
@@ -176,8 +168,7 @@ function route_cache_settings(): ?array
*/
function route_name(): ?string
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? $matchedRoute->getRoute()->getName() : null;
}
@@ -188,8 +179,7 @@ function route_name(): ?string
*/
function route_prefix(): ?string
{
- $request = Di::get(Request::class);
- $matchedRoute = $request->getMatchedRoute();
+ $matchedRoute = request()->getMatchedRoute();
return $matchedRoute ? $matchedRoute->getRoute()->getPrefix() : null;
}
@@ -249,7 +239,7 @@ function route_group_exists(string $name, string $module): bool
*/
function module_base_namespace(): string
{
- return Environment::getInstance()->getAppEnv() === 'testing'
+ return environment()->isTesting()
? 'Quantum\\Tests\\_root\\modules'
: 'Modules';
}
diff --git a/src/Session/Adapters/Database/DatabaseSessionAdapter.php b/src/Session/Adapters/Database/DatabaseSessionAdapter.php
index cc268df08..22482bc47 100644
--- a/src/Session/Adapters/Database/DatabaseSessionAdapter.php
+++ b/src/Session/Adapters/Database/DatabaseSessionAdapter.php
@@ -16,11 +16,14 @@
namespace Quantum\Session\Adapters\Database;
-use Quantum\Model\Exceptions\ModelException;
use Quantum\Session\Contracts\SessionStorageInterface;
use Quantum\Session\Exceptions\SessionException;
+use Quantum\Model\Exceptions\ModelException;
use Quantum\Model\Factories\ModelFactory;
+use Quantum\App\Exceptions\BaseException;
use Quantum\Session\Traits\SessionTrait;
+use Quantum\Di\Exceptions\DiException;
+use ReflectionException;
/**
* Class Session
@@ -49,7 +52,7 @@ class DatabaseSessionAdapter implements SessionStorageInterface
/**
* @param array|null $params
- * @throws SessionException|ModelException
+ * @throws SessionException|ModelException|BaseException|DiException|ReflectionException
*/
public function __construct(?array $params = null)
{
@@ -58,7 +61,7 @@ public function __construct(?array $params = null)
/**
* @param array|null $params
- * @throws SessionException|ModelException
+ * @throws SessionException|ModelException|BaseException|DiException|ReflectionException
*/
protected function initializeSession(?array $params = null): void
{
diff --git a/src/Session/Factories/SessionFactory.php b/src/Session/Factories/SessionFactory.php
index 8a104cf88..6d31abb33 100644
--- a/src/Session/Factories/SessionFactory.php
+++ b/src/Session/Factories/SessionFactory.php
@@ -27,6 +27,7 @@
use Quantum\Session\Session;
use Quantum\Loader\Setup;
use ReflectionException;
+use Quantum\Di\Di;
/**
* Class SessionFactory
@@ -34,9 +35,6 @@
*/
class SessionFactory
{
- /**
- * Supported adapters
- */
public const ADAPTERS = [
SessionType::NATIVE => NativeSessionAdapter::class,
SessionType::DATABASE => DatabaseSessionAdapter::class,
@@ -45,15 +43,24 @@ class SessionFactory
/**
* @var array
*/
- private static array $instances = [];
+ private array $instances = [];
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public static function get(?string $adapter = null): Session
+ {
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve($adapter);
+ }
+
+ /**
+ * @throws ConfigException|DiException|BaseException|ReflectionException
+ */
+ public function resolve(?string $adapter = null): Session
{
if (!config()->has('session')) {
config()->import(new Setup('config', 'session'));
@@ -61,16 +68,19 @@ public static function get(?string $adapter = null): Session
$adapter ??= config()->get('session.default');
- $adapterClass = self::getAdapterClass($adapter);
+ $adapterClass = $this->getAdapterClass($adapter);
- if (!isset(self::$instances[$adapter])) {
- self::$instances[$adapter] = self::createInstance($adapterClass, $adapter);
+ if (!isset($this->instances[$adapter])) {
+ $this->instances[$adapter] = $this->createInstance($adapterClass, $adapter);
}
- return self::$instances[$adapter];
+ return $this->instances[$adapter];
}
- private static function createInstance(string $adapterClass, string $adapter): Session
+ /**
+ * @throws BaseException|DiException|ReflectionException
+ */
+ private function createInstance(string $adapterClass, string $adapter): Session
{
$adapterInstance = new $adapterClass(config()->get('session.' . $adapter));
@@ -84,7 +94,7 @@ private static function createInstance(string $adapterClass, string $adapter): S
/**
* @throws BaseException
*/
- private static function getAdapterClass(string $adapter): string
+ private function getAdapterClass(string $adapter): string
{
if (!array_key_exists($adapter, self::ADAPTERS)) {
throw SessionException::adapterNotSupported($adapter);
diff --git a/src/Session/Helpers/session.php b/src/Session/Helpers/session.php
index d1318931d..87b561625 100644
--- a/src/Session/Helpers/session.php
+++ b/src/Session/Helpers/session.php
@@ -19,10 +19,7 @@
use Quantum\Session\Session;
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|BaseException|DiException|ReflectionException
*/
function session(?string $adapter = null): Session
{
diff --git a/src/Session/Traits/SessionTrait.php b/src/Session/Traits/SessionTrait.php
index 789e79335..239581998 100644
--- a/src/Session/Traits/SessionTrait.php
+++ b/src/Session/Traits/SessionTrait.php
@@ -16,8 +16,11 @@
namespace Quantum\Session\Traits;
+use Quantum\App\Exceptions\BaseException;
+use Quantum\Di\Exceptions\DiException;
use Quantum\Session\Exceptions\SessionException;
use Quantum\Model\Exceptions\ModelException;
+use ReflectionException;
/**
* Traits SessionTrait
@@ -28,6 +31,7 @@ trait SessionTrait
/**
* @inheritDoc
* @return array
+ * @throws BaseException|ReflectionException
*/
public function all(): array
{
@@ -120,7 +124,7 @@ public function getId(): ?string
/**
* @inheritDoc
- * @throws SessionException|ModelException
+ * @throws SessionException|ModelException|DiException|BaseException|ReflectionException
*/
public function regenerateId(): bool
{
diff --git a/src/Storage/Contracts/TokenServiceInterface.php b/src/Storage/Contracts/TokenServiceInterface.php
index f17a53296..34626bec6 100644
--- a/src/Storage/Contracts/TokenServiceInterface.php
+++ b/src/Storage/Contracts/TokenServiceInterface.php
@@ -27,5 +27,4 @@ public function getAccessToken(): string;
public function getRefreshToken(): string;
public function saveTokens(string $accessToken, ?string $refreshToken = null): bool;
-
}
diff --git a/src/Storage/Factories/FileSystemFactory.php b/src/Storage/Factories/FileSystemFactory.php
index aff8bcbca..3c20a8ee6 100644
--- a/src/Storage/Factories/FileSystemFactory.php
+++ b/src/Storage/Factories/FileSystemFactory.php
@@ -35,6 +35,7 @@
use Quantum\Storage\FileSystem;
use Quantum\Loader\Setup;
use ReflectionException;
+use Quantum\Di\Di;
/**
* Class FileSystemFactory
@@ -42,18 +43,12 @@
*/
class FileSystemFactory
{
- /**
- * Supported adapters
- */
public const ADAPTERS = [
FileSystemType::LOCAL => LocalFileSystemAdapter::class,
FileSystemType::DROPBOX => DropboxFileSystemAdapter::class,
FileSystemType::GDRIVE => GoogleDriveFileSystemAdapter::class,
];
- /**
- * Supported apps
- */
public const APPS = [
FileSystemType::DROPBOX => DropboxApp::class,
FileSystemType::GDRIVE => GoogleDriveApp::class,
@@ -62,15 +57,24 @@ class FileSystemFactory
/**
* @var array
*/
- private static array $instances = [];
+ private array $instances = [];
/**
- * @throws BaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws ConfigException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public static function get(?string $adapter = null): FileSystem
+ {
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve($adapter);
+ }
+
+ /**
+ * @throws ConfigException|DiException|BaseException|ReflectionException
+ */
+ public function resolve(?string $adapter = null): FileSystem
{
if (!config()->has('fs')) {
config()->import(new Setup('config', 'fs'));
@@ -78,24 +82,21 @@ public static function get(?string $adapter = null): FileSystem
$adapter ??= config()->get('fs.default');
- $adapterClass = self::getAdapterClass($adapter);
+ $adapterClass = $this->getAdapterClass($adapter);
- if (!isset(self::$instances[$adapter])) {
- self::$instances[$adapter] = self::createInstance($adapterClass, $adapter);
+ if (!isset($this->instances[$adapter])) {
+ $this->instances[$adapter] = $this->createInstance($adapterClass, $adapter);
}
- return self::$instances[$adapter];
+ return $this->instances[$adapter];
}
/**
- * @throws BaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws ServiceException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
- private static function createInstance(string $adapterClass, string $adapter): FileSystem
+ private function createInstance(string $adapterClass, string $adapter): FileSystem
{
- $fsAdapter = new $adapterClass(self::createCloudApp($adapter));
+ $fsAdapter = new $adapterClass($this->createCloudApp($adapter));
if (!$fsAdapter instanceof FilesystemAdapterInterface) {
throw FileSystemException::adapterNotSupported($adapter);
@@ -107,7 +108,7 @@ private static function createInstance(string $adapterClass, string $adapter): F
/**
* @throws BaseException
*/
- private static function getAdapterClass(string $adapter): string
+ private function getAdapterClass(string $adapter): string
{
if (!array_key_exists($adapter, self::ADAPTERS)) {
throw FileSystemException::adapterNotSupported($adapter);
@@ -117,12 +118,9 @@ private static function getAdapterClass(string $adapter): string
}
/**
- * @throws BaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws ServiceException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
- private static function createCloudApp(string $adapter): ?CloudAppInterface
+ private function createCloudApp(string $adapter): ?CloudAppInterface
{
if ($adapter === FileSystemType::LOCAL || !isset(self::APPS[$adapter])) {
return null;
@@ -133,21 +131,15 @@ private static function createCloudApp(string $adapter): ?CloudAppInterface
return new $cloudAppClass(
config()->get('fs.' . $adapter . '.params.app_key'),
config()->get('fs.' . $adapter . '.params.app_secret'),
- self::createTokenService($adapter),
+ $this->createTokenService($adapter),
new HttpClient()
);
}
/**
- * Creates token service instance
- * @param string $adapter
- * @return TokenServiceInterface
- * @throws BaseException
- * @throws DiException
- * @throws ReflectionException
- * @throws ServiceException
+ * @throws ServiceException|DiException|BaseException|ReflectionException
*/
- private static function createTokenService(string $adapter): TokenServiceInterface
+ private function createTokenService(string $adapter): TokenServiceInterface
{
$serviceClass = (string) config()->get('fs.' . $adapter . '.service');
diff --git a/src/Storage/Helpers/fs.php b/src/Storage/Helpers/fs.php
index e7d602b95..16a9cc904 100644
--- a/src/Storage/Helpers/fs.php
+++ b/src/Storage/Helpers/fs.php
@@ -20,10 +20,7 @@
/**
* Gets the FileSystem handler
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function fs(?string $adapter = null): FileSystem
{
diff --git a/src/Storage/Traits/CloudAppTrait.php b/src/Storage/Traits/CloudAppTrait.php
index 33635f6a1..5a4c6d669 100644
--- a/src/Storage/Traits/CloudAppTrait.php
+++ b/src/Storage/Traits/CloudAppTrait.php
@@ -30,9 +30,7 @@ trait CloudAppTrait
* @inheritDoc
* @param array|string|null $data
* @param array $headers
- * @throws BaseException
- * @throws HttpException
- * @throws Exception
+ * @throws HttpException|BaseException|Exception
*/
public function sendRequest(string $uri, $data = null, array $headers = [], string $method = 'POST')
{
diff --git a/src/Storage/UploadedFile.php b/src/Storage/UploadedFile.php
index b8313c6ad..c56497af8 100644
--- a/src/Storage/UploadedFile.php
+++ b/src/Storage/UploadedFile.php
@@ -20,7 +20,7 @@
use Quantum\Storage\Contracts\FilesystemAdapterInterface;
use Quantum\Storage\Exceptions\FileSystemException;
use Quantum\Storage\Exceptions\FileUploadException;
-use Quantum\Environment\Exceptions\EnvException;
+use Quantum\Loader\Exceptions\LoaderException;
use Quantum\Config\Exceptions\ConfigException;
use Quantum\Lang\Exceptions\LangException;
use Quantum\App\Exceptions\BaseException;
@@ -115,10 +115,7 @@ class UploadedFile extends SplFileInfo
/**
* @param array $meta
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
public function __construct(array $meta)
{
@@ -268,11 +265,10 @@ public function getDimensions(): array
/**
* Save the uploaded file
- * @throws BaseException
- * @throws FileSystemException
- * @throws FileUploadException
- * @throws ImageResizeException
- * @throws EnvException
+ * @param string $dest
+ * @param bool $overwrite
+ * @return bool
+ * @throws FileUploadException|FileSystemException|ImageResizeException|BaseException
*/
public function save(string $dest, bool $overwrite = false): bool
{
@@ -318,9 +314,7 @@ public function save(string $dest, bool $overwrite = false): bool
/**
* Sets modification function on image
* @param array $params
- * @throws BaseException
- * @throws FileUploadException
- * @throws LangException
+ * @throws FileUploadException|LangException|BaseException
*/
public function modify(string $funcName, array $params): UploadedFile
{
@@ -364,9 +358,8 @@ public function isUploaded(): bool
/**
* Checks if the given file is image
- * @param string $filePath
*/
- public function isImage($filePath): bool
+ public function isImage(string $filePath): bool
{
return (bool) getimagesize($filePath);
}
@@ -399,14 +392,15 @@ protected function allowed(string $extension, string $mimeType): bool
/**
* Loads allowed mime types from config (shared/config/uploads.php) if present.
- * @throws ConfigException
- * @throws DiException
- * @throws FileUploadException
- * @throws ReflectionException
+ * @throws FileUploadException|LoaderException|ConfigException|DiException|ReflectionException
*/
protected function loadAllowedMimeTypesFromConfig(): void
{
if (!config()->has('uploads')) {
+ if (!Di::isRegistered(Loader::class)) {
+ Di::register(Loader::class);
+ }
+
$loader = Di::get(Loader::class);
$setup = new Setup('config', 'uploads');
$loader->setup($setup);
diff --git a/src/Tracer/ErrorHandler.php b/src/Tracer/ErrorHandler.php
index 0e29de983..5c4ed3b85 100644
--- a/src/Tracer/ErrorHandler.php
+++ b/src/Tracer/ErrorHandler.php
@@ -25,12 +25,12 @@
use Quantum\Di\Exceptions\DiException;
use DebugBar\DebugBarException;
use Quantum\Logger\Logger;
-use Quantum\Http\Response;
use ReflectionException;
use Psr\Log\LogLevel;
use ErrorException;
use ParseError;
use Throwable;
+use Exception;
/**
* Class ErrorHandler
@@ -64,27 +64,11 @@ class ErrorHandler
private ?Logger $logger = null;
- private static ?ErrorHandler $instance = null;
-
- private function __construct()
- {
- // Prevent direct instantiation
- }
-
private function __clone()
{
// Prevent cloning
}
- public static function getInstance(): ErrorHandler
- {
- if (self::$instance === null) {
- self::$instance = new self();
- }
-
- return self::$instance;
- }
-
public function setup(Logger $logger): void
{
$this->logger = $logger;
@@ -106,12 +90,7 @@ public function handleError(int $severity, string $message, string $file, int $l
}
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
- * @throws RendererException
- * @throws DebugBarException
+ * @throws ConfigException|RendererException|DebugBarException|DiException|BaseException|ReflectionException
*/
public function handleException(Throwable $throwable): void
{
@@ -129,11 +108,7 @@ private function handleCliException(Throwable $throwable): void
}
/**
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
- * @throws DebugBarException
+ * @throws ConfigException|RendererException|DiException|BaseException|ReflectionException|Exception
*/
private function handleWebException(Throwable $throwable): void
{
@@ -151,8 +126,8 @@ private function handleWebException(Throwable $throwable): void
$this->logError($throwable, $errorType);
}
- Response::html($errorPage);
- Response::send();
+ response()->html($errorPage);
+ response()->send();
}
private function logError(Throwable $e, string $errorType): void
@@ -169,10 +144,7 @@ private function logError(Throwable $e, string $errorType): void
/**
* Composes the stack trace
* @return array
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|RendererException|DiException|BaseException|ReflectionException
*/
private function composeStackTrace(Throwable $e): array
{
@@ -199,10 +171,7 @@ private function composeStackTrace(Throwable $e): array
/**
* Gets the source code where the error happens
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|RendererException|DiException|BaseException|ReflectionException
*/
private function getSourceCode(string $filename, int $lineNumber, string $className): string
{
diff --git a/src/Validation/Traits/General.php b/src/Validation/Traits/General.php
index 41d59e9c2..46de926d8 100644
--- a/src/Validation/Traits/General.php
+++ b/src/Validation/Traits/General.php
@@ -211,8 +211,7 @@ protected function same($value, string $otherField): bool
/**
* Validates uniqueness
* @param mixed $value
- * @throws BaseException
- * @throws ModelException
+ * @throws ModelException|BaseException|ReflectionException
*/
protected function unique($value, string $className, string $columnName): bool
{
@@ -227,8 +226,7 @@ protected function unique($value, string $className, string $columnName): bool
/**
* Validates record existence
* @param mixed $value
- * @throws BaseException
- * @throws ModelException
+ * @throws ModelException|BaseException|ReflectionException
*/
protected function exists($value, string $className, string $columnName): bool
{
@@ -243,10 +241,7 @@ protected function exists($value, string $className, string $columnName): bool
/**
* Check Captcha
* @param mixed $value
- * @throws BaseException
- * @throws ConfigException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
protected function captcha($value): bool
{
diff --git a/src/Validation/Validator.php b/src/Validation/Validator.php
index 94df7b626..dc23e0b98 100644
--- a/src/Validation/Validator.php
+++ b/src/Validation/Validator.php
@@ -18,6 +18,7 @@
use Quantum\Config\Exceptions\ConfigException;
use Quantum\Lang\Exceptions\LangException;
+use Quantum\Loader\Exceptions\LoaderException;
use Quantum\Validation\Traits\Resource;
use Quantum\Di\Exceptions\DiException;
use Quantum\Validation\Traits\General;
@@ -194,10 +195,7 @@ public function addRule(string $rule, Closure $function): void
/**
* Gets validation errors with translations
* @return array>
- * @throws ConfigException
- * @throws DiException
- * @throws LangException
- * @throws ReflectionException
+ * @throws ConfigException|LoaderException|LangException|DiException|ReflectionException
*/
public function getErrors(): array
{
diff --git a/src/View/Factories/ViewFactory.php b/src/View/Factories/ViewFactory.php
index 675d9a352..f1d3d652a 100644
--- a/src/View/Factories/ViewFactory.php
+++ b/src/View/Factories/ViewFactory.php
@@ -17,15 +17,14 @@
namespace Quantum\View\Factories;
use Quantum\Renderer\Factories\RendererFactory;
-use Quantum\ResourceCache\ViewCache;
use Quantum\Config\Exceptions\ConfigException;
use Quantum\App\Exceptions\BaseException;
use Quantum\Di\Exceptions\DiException;
-use DebugBar\DebugBarException;
-use Quantum\Asset\AssetManager;
+use Quantum\ResourceCache\ViewCache;
use Quantum\Debugger\Debugger;
use Quantum\View\QtView;
use ReflectionException;
+use Quantum\Di\Di;
/**
* Class ViewFactory
@@ -34,30 +33,38 @@
*/
class ViewFactory
{
+ private ?QtView $instance = null;
+
/**
- * Instance of QtView
+ * @throws ConfigException|BaseException|DiException|ReflectionException
*/
- private static ?QtView $instance = null;
+ public static function get(): QtView
+ {
+ if (!Di::isRegistered(self::class)) {
+ Di::register(self::class);
+ }
+
+ return Di::get(self::class)->resolve();
+ }
/**
- * QtView instance
- * @throws DebugBarException
- * @throws DiException
- * @throws BaseException
- * @throws ConfigException
- * @throws ReflectionException
+ * @throws ConfigException|BaseException|DiException|ReflectionException
*/
- public static function get(): QtView
+ public function resolve(): QtView
{
- if (self::$instance === null) {
- self::$instance = new QtView(
+ if ($this->instance === null) {
+ if (!Di::isRegistered(ViewCache::class)) {
+ Di::register(ViewCache::class);
+ }
+
+ $this->instance = new QtView(
RendererFactory::get(),
- AssetManager::getInstance(),
- Debugger::getInstance(),
- ViewCache::getInstance()
+ asset(),
+ Di::get(Debugger::class),
+ Di::get(ViewCache::class)
);
}
- return self::$instance;
+ return $this->instance;
}
}
diff --git a/src/View/Helpers/view.php b/src/View/Helpers/view.php
index a0721730c..6a11df00b 100644
--- a/src/View/Helpers/view.php
+++ b/src/View/Helpers/view.php
@@ -24,15 +24,11 @@
use DebugBar\DebugBarException;
use Quantum\Debugger\Debugger;
use Quantum\View\RawParam;
+use Quantum\Di\Di;
/**
* Rendered view
- * @throws BaseException
- * @throws ConfigException
- * @throws DebugBarException
- * @throws DiException
- * @throws ReflectionException
- * @throws ViewException
+ * @throws ViewException|ConfigException|DiException|BaseException|ReflectionException
*/
function view(): ?string
{
@@ -42,11 +38,7 @@ function view(): ?string
/**
* Rendered partial
* @param array $args
- * @throws BaseException
- * @throws ConfigException
- * @throws DebugBarException
- * @throws DiException
- * @throws ReflectionException
+ * @throws ConfigException|DiException|BaseException|ReflectionException
*/
function partial(string $partial, array $args = []): string
{
@@ -58,7 +50,6 @@ function partial(string $partial, array $args = []): string
* @return mixed|null
* @throws BaseException
* @throws ConfigException
- * @throws DebugBarException
* @throws DiException
* @throws ReflectionException
*/
@@ -78,11 +69,15 @@ function raw_param($value): RawParam
/**
* Rendered debug bar
- * @throws DebugBarException
+ * @throws DebugBarException|DiException|ReflectionException
*/
function debugbar(): ?string
{
- $debugger = Debugger::getInstance();
+ if (!Di::isRegistered(Debugger::class)) {
+ Di::register(Debugger::class);
+ }
+
+ $debugger = Di::get(Debugger::class);
if ($debugger->isEnabled()) {
return $debugger->render();
diff --git a/src/View/QtView.php b/src/View/QtView.php
index 030626775..0af6a736a 100644
--- a/src/View/QtView.php
+++ b/src/View/QtView.php
@@ -283,8 +283,7 @@ private function sanitizeHtml(string $value): string
}
/**
- * @throws ReflectionException
- * @throws DiException
+ * @throws ReflectionException|DiException
*/
private function updateDebugger(string $viewFile): void
{
diff --git a/tests/Helpers/functions.php b/tests/Helpers/functions.php
index ab608e89e..eb244ddb4 100644
--- a/tests/Helpers/functions.php
+++ b/tests/Helpers/functions.php
@@ -1,13 +1,16 @@
makePartial();
$applicationMock->shouldReceive('getName')->andReturn('Qt Console Application');
$applicationMock->shouldReceive('run')->andReturn(0);
@@ -33,13 +30,14 @@ public function setUp(): void
public function tearDown(): void
{
config()->flush();
+ $this->clearAppContext();
}
public function testConsoleAppAdapterStartSuccessfully(): void
{
$_SERVER['argv'] = ['qt', 'list', '--quiet'];
- $this->consoleAppAdapter->__construct();
+ $this->consoleAppAdapter->__construct($this->createContext());
$result = $this->consoleAppAdapter->start();
@@ -50,7 +48,7 @@ public function testConsoleAppAdapterStartFails(): void
{
$_SERVER['argv'] = ['qt', 'unknown', '--quiet'];
- $this->consoleAppAdapter->__construct();
+ $this->consoleAppAdapter->__construct($this->createContext());
$this->expectException(Exception::class);
diff --git a/tests/Unit/App/Adapters/WebAppAdapterTest.php b/tests/Unit/App/Adapters/WebAppAdapterTest.php
index 4ce612469..95b8e7fd3 100644
--- a/tests/Unit/App/Adapters/WebAppAdapterTest.php
+++ b/tests/Unit/App/Adapters/WebAppAdapterTest.php
@@ -3,32 +3,26 @@
namespace Quantum\Tests\Unit\App\Adapters;
use Quantum\App\Adapters\WebAppAdapter;
-use PHPUnit\Framework\TestCase;
-use Quantum\Http\Request;
-use Quantum\App\App;
-use Quantum\Di\Di;
+use Quantum\Tests\Unit\AppTestCase;
-class WebAppAdapterTest extends TestCase
+class WebAppAdapterTest extends AppTestCase
{
private WebAppAdapter $webAppAdapter;
public function setUp(): void
{
- App::setBaseDir(PROJECT_ROOT);
-
- $this->webAppAdapter = new WebAppAdapter();
+ $this->webAppAdapter = new WebAppAdapter($this->createContext());
}
public function tearDown(): void
{
config()->flush();
- Di::reset();
+ $this->clearAppContext();
}
public function testWebAppAdapterStartSuccessfully(): void
{
- $request = Di::get(Request::class);
- $request->create('GET', '/test/am/tests');
+ request()->create('GET', '/test/am/tests');
ob_start();
$result = $this->webAppAdapter->start();
@@ -39,8 +33,7 @@ public function testWebAppAdapterStartSuccessfully(): void
public function testWebAppAdapterStartFails(): void
{
- $request = Di::get(Request::class);
- $request->create('POST', '');
+ request()->create('POST', '');
ob_start();
$result = $this->webAppAdapter->start();
@@ -51,8 +44,7 @@ public function testWebAppAdapterStartFails(): void
public function testWebAppAdapterHandlesPageNotFoundGracefully(): void
{
- $request = Di::get(Request::class);
- $request->create('GET', '/non-existing-uri');
+ request()->create('GET', '/non-existing-uri');
ob_start();
$result = $this->webAppAdapter->start();
diff --git a/tests/Unit/App/AppContextTest.php b/tests/Unit/App/AppContextTest.php
new file mode 100644
index 000000000..bdbb16ab6
--- /dev/null
+++ b/tests/Unit/App/AppContextTest.php
@@ -0,0 +1,86 @@
+assertSame('/my/base/dir', $context->getBaseDir());
+ }
+
+ public function testAppContextContainer(): void
+ {
+ $container = new DiContainer();
+ $context = new AppContext('/tmp', $container);
+
+ $this->assertSame($container, $context->getContainer());
+ }
+
+ public function testAppContextGetEnvironment(): void
+ {
+ $container = new DiContainer();
+ $environment = Mockery::mock(Environment::class);
+ $container->set(Environment::class, $environment);
+
+ $context = new AppContext('/tmp', $container);
+
+ $this->assertSame($environment, $context->getEnvironment());
+ }
+
+ public function testAppContextGetConfig(): void
+ {
+ $container = new DiContainer();
+ $config = Mockery::mock(Config::class);
+ $container->set(Config::class, $config);
+
+ $context = new AppContext('/tmp', $container);
+
+ $this->assertSame($config, $context->getConfig());
+ }
+
+ public function testAppContextGetRequest(): void
+ {
+ $container = new DiContainer();
+ $request = Mockery::mock(Request::class);
+ $container->set(Request::class, $request);
+
+ $context = new AppContext('/tmp', $container);
+
+ $this->assertSame($request, $context->getRequest());
+ }
+
+ public function testAppContextGetResponse(): void
+ {
+ $container = new DiContainer();
+ $response = Mockery::mock(Response::class);
+ $container->set(Response::class, $response);
+
+ $context = new AppContext('/tmp', $container);
+
+ $this->assertSame($response, $context->getResponse());
+ }
+
+ public function testAppContextGetRoutes(): void
+ {
+ $container = new DiContainer();
+ $routes = new RouteCollection();
+ $container->set(RouteCollection::class, $routes);
+
+ $context = new AppContext('/tmp', $container);
+
+ $this->assertSame($routes, $context->getRoutes());
+ }
+}
diff --git a/tests/Unit/App/AppTest.php b/tests/Unit/App/AppTest.php
index 28e26c5f2..fcb480e93 100644
--- a/tests/Unit/App/AppTest.php
+++ b/tests/Unit/App/AppTest.php
@@ -6,34 +6,29 @@
use Quantum\App\Exceptions\AppException;
use Quantum\App\Adapters\WebAppAdapter;
use Quantum\App\Contracts\AppInterface;
-use PHPUnit\Framework\TestCase;
-use Quantum\Http\Request;
+use Quantum\Tests\Unit\AppTestCase;
use Quantum\App\App;
-use Quantum\Di\Di;
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
-class AppTest extends TestCase
+class AppTest extends AppTestCase
{
public function setUp(): void
{
- parent::setUp();
-
- Di::reset();
-
- App::setBaseDir(PROJECT_ROOT);
+ $this->createContext();
}
public function tearDown(): void
{
config()->flush();
+ $this->clearAppContext();
}
public function testAppGetAdapter(): void
{
- $app = new App(new WebAppAdapter());
+ $app = new App(new WebAppAdapter($this->createContext()));
$this->assertInstanceOf(WebAppAdapter::class, $app->getAdapter());
@@ -41,7 +36,7 @@ public function testAppGetAdapter(): void
config()->flush();
- $app = new App(new ConsoleAppAdapter());
+ $app = new App(new ConsoleAppAdapter($this->createContext()));
$this->assertInstanceOf(ConsoleAppAdapter::class, $app->getAdapter());
@@ -50,10 +45,9 @@ public function testAppGetAdapter(): void
public function testAppCallingValidMethod(): void
{
- $app = new App(new WebAppAdapter());
+ $app = new App(new WebAppAdapter($this->createContext()));
- $request = Di::get(Request::class);
- $request->create('GET', '/test/am/tests');
+ request()->create('GET', '/test/am/tests');
ob_start();
$this->assertEquals(0, $app->start());
@@ -62,7 +56,7 @@ public function testAppCallingValidMethod(): void
public function testAppCallingInvalidMethod(): void
{
- $app = new App(new WebAppAdapter());
+ $app = new App(new WebAppAdapter($this->createContext()));
$this->expectException(AppException::class);
diff --git a/tests/Unit/App/BootPipelineTest.php b/tests/Unit/App/BootPipelineTest.php
new file mode 100644
index 000000000..f425fdae1
--- /dev/null
+++ b/tests/Unit/App/BootPipelineTest.php
@@ -0,0 +1,96 @@
+createStage(function () use (&$log) {
+ $log[] = 'first';
+ });
+
+ $stage2 = $this->createStage(function () use (&$log) {
+ $log[] = 'second';
+ });
+
+ $stage3 = $this->createStage(function () use (&$log) {
+ $log[] = 'third';
+ });
+
+ $pipeline = new BootPipeline([$stage1, $stage2, $stage3]);
+ $pipeline->run(new AppContext('', new DiContainer()));
+
+ $this->assertSame(['first', 'second', 'third'], $log);
+ }
+
+ public function testEmptyPipelineRunsWithoutError(): void
+ {
+ $pipeline = new BootPipeline([]);
+ $pipeline->run(new AppContext('', new DiContainer()));
+
+ $this->assertTrue(true);
+ }
+
+ public function testPipelinePassesContextToStages(): void
+ {
+ $receivedBaseDir = null;
+
+ $stage = $this->createStage(function (AppContext $context) use (&$receivedBaseDir) {
+ $receivedBaseDir = $context->getBaseDir();
+ });
+
+ $pipeline = new BootPipeline([$stage]);
+ $pipeline->run(new AppContext('/test/dir', new DiContainer()));
+
+ $this->assertSame('/test/dir', $receivedBaseDir);
+ }
+
+ public function testPipelinePropagatesException(): void
+ {
+ $stage = $this->createStage(function () {
+ throw new RuntimeException('Stage failed');
+ });
+
+ $this->expectException(RuntimeException::class);
+ $this->expectExceptionMessage('Stage failed');
+
+ $pipeline = new BootPipeline([$stage]);
+ $pipeline->run(new AppContext('', new DiContainer()));
+ }
+
+ public function testPipelineRejectsInvalidStage(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('All stages must implement');
+
+ new BootPipeline([new \stdClass()]);
+ }
+
+ private function createStage(callable $callback): BootStageInterface
+ {
+ return new class ($callback) implements BootStageInterface {
+ private $callback;
+
+ public function __construct(callable $callback)
+ {
+ $this->callback = $callback;
+ }
+
+ public function process(AppContext $context): void
+ {
+ ($this->callback)($context);
+ }
+ };
+ }
+}
diff --git a/tests/Unit/App/Factories/AppFactoryTest.php b/tests/Unit/App/Factories/AppFactoryTest.php
index 7482cea6a..5a5b657c9 100644
--- a/tests/Unit/App/Factories/AppFactoryTest.php
+++ b/tests/Unit/App/Factories/AppFactoryTest.php
@@ -10,6 +10,7 @@
use PHPUnit\Framework\TestCase;
use Quantum\App\Enums\AppType;
use Quantum\App\App;
+use Quantum\Di\Di;
class AppFactoryTest extends TestCase
{
@@ -77,4 +78,17 @@ public function testAppFactoryDestroy(): void
$this->assertNotSame($app1, $app2);
}
+
+ public function testAppFactoryResetsContainerOnCreate(): void
+ {
+ AppFactory::destroy(AppType::WEB);
+
+ Di::register(\stdClass::class);
+
+ $this->assertTrue(Di::isRegistered(\stdClass::class));
+
+ AppFactory::create(AppType::WEB, PROJECT_ROOT);
+
+ $this->assertFalse(Di::isRegistered(\stdClass::class));
+ }
}
diff --git a/tests/Unit/App/Stages/LoadAppConfigStageTest.php b/tests/Unit/App/Stages/LoadAppConfigStageTest.php
new file mode 100644
index 000000000..e9deebba2
--- /dev/null
+++ b/tests/Unit/App/Stages/LoadAppConfigStageTest.php
@@ -0,0 +1,48 @@
+context = $this->createContext();
+
+ (new LoadHelpersStage())->process($this->context);
+ (new LoadEnvironmentStage())->process($this->context);
+ }
+
+ public function tearDown(): void
+ {
+ config()->flush();
+ $this->clearAppContext();
+ }
+
+ public function testLoadAppConfigStageImportsAppConfig(): void
+ {
+ $this->assertFalse(config()->has('app'));
+
+ $stage = new LoadAppConfigStage();
+ $stage->process($this->context);
+
+ $this->assertTrue(config()->has('app'));
+ }
+
+ public function testLoadAppConfigStageSkipsIfAlreadyLoaded(): void
+ {
+ $stage = new LoadAppConfigStage();
+
+ $stage->process($this->context);
+
+ $this->assertTrue(config()->has('app'));
+
+ $stage->process($this->context);
+
+ $this->assertTrue(config()->has('app'));
+ }
+}
diff --git a/tests/Unit/App/Stages/LoadEnvironmentStageTest.php b/tests/Unit/App/Stages/LoadEnvironmentStageTest.php
new file mode 100644
index 000000000..18977ae52
--- /dev/null
+++ b/tests/Unit/App/Stages/LoadEnvironmentStageTest.php
@@ -0,0 +1,30 @@
+context = $this->createContext();
+
+ (new LoadHelpersStage())->process($this->context);
+ }
+
+ public function tearDown(): void
+ {
+ $this->clearAppContext();
+ }
+
+ public function testLoadEnvironmentStageLoadsEnvVars(): void
+ {
+ $stage = new LoadEnvironmentStage();
+ $stage->process($this->context);
+
+ $this->assertNotEmpty(env('APP_KEY'));
+ }
+}
diff --git a/tests/Unit/App/Stages/LoadHelpersStageTest.php b/tests/Unit/App/Stages/LoadHelpersStageTest.php
new file mode 100644
index 000000000..dc9244635
--- /dev/null
+++ b/tests/Unit/App/Stages/LoadHelpersStageTest.php
@@ -0,0 +1,29 @@
+context = $this->createContext();
+ }
+
+ public function tearDown(): void
+ {
+ $this->clearAppContext();
+ }
+
+ public function testLoadHelpersStageLoadsComponentHelpers(): void
+ {
+ $stage = new LoadHelpersStage();
+ $stage->process($this->context);
+
+ $this->assertTrue(function_exists('config'));
+ $this->assertTrue(function_exists('env'));
+ $this->assertTrue(function_exists('base_dir'));
+ }
+}
diff --git a/tests/Unit/App/Stages/SetupErrorHandlerStageTest.php b/tests/Unit/App/Stages/SetupErrorHandlerStageTest.php
new file mode 100644
index 000000000..d5049c02c
--- /dev/null
+++ b/tests/Unit/App/Stages/SetupErrorHandlerStageTest.php
@@ -0,0 +1,41 @@
+context = $this->createContext();
+
+ (new LoadHelpersStage())->process($this->context);
+ (new LoadEnvironmentStage())->process($this->context);
+ (new LoadAppConfigStage())->process($this->context);
+ }
+
+ public function tearDown(): void
+ {
+ restore_error_handler();
+ restore_exception_handler();
+ config()->flush();
+ $this->clearAppContext();
+ }
+
+ public function testSetupErrorHandlerStageRegistersHandlers(): void
+ {
+ $stage = new SetupErrorHandlerStage();
+ $stage->process($this->context);
+
+ $errorHandler = set_error_handler(function () {
+ });
+ restore_error_handler();
+
+ $this->assertNotNull($errorHandler);
+ }
+}
diff --git a/tests/Unit/AppTestCase.php b/tests/Unit/AppTestCase.php
index 89893cdb7..09bed980e 100644
--- a/tests/Unit/AppTestCase.php
+++ b/tests/Unit/AppTestCase.php
@@ -4,41 +4,66 @@
use Quantum\Storage\Factories\FileSystemFactory;
use Quantum\App\Factories\AppFactory;
-use Quantum\Environment\Environment;
use Quantum\Router\MatchedRoute;
+use Quantum\Storage\FileSystem;
use PHPUnit\Framework\TestCase;
use Quantum\Debugger\Debugger;
use Quantum\App\Enums\AppType;
+use Quantum\Di\DiContainer;
+use Quantum\App\AppContext;
+use Quantum\Config\Config;
use Quantum\Router\Route;
-use Quantum\Http\Request;
-use Quantum\Loader\Setup;
use ReflectionClass;
+use Quantum\App\App;
use Quantum\Di\Di;
+use ReflectionProperty;
abstract class AppTestCase extends TestCase
{
+ protected AppContext $context;
+
+ /** @var FileSystem */
protected $fs;
public function setUp(): void
{
AppFactory::create(AppType::WEB, PROJECT_ROOT);
- Environment::getInstance()
- ->setMutable(true)
- ->load(new Setup('config', 'env'));
+ environment()->setMutable(true);
$this->fs = FileSystemFactory::get();
}
public function tearDown(): void
{
- Request::setMatchedRoute(null);
- Request::flush();
+ request()->setMatchedRoute(null);
+ request()->flush();
AppFactory::destroy(AppType::WEB);
- config()->flush();
- Debugger::getInstance()->resetStore();
- Di::reset();
+
+ if (Di::isRegistered(Config::class)) {
+ config()->flush();
+ }
+ if (Di::isRegistered(Debugger::class)) {
+ Di::get(Debugger::class)->resetStore();
+ }
+
+ $this->clearAppContext();
+ }
+
+ protected function createContext(): AppContext
+ {
+ $context = new AppContext(PROJECT_ROOT, new DiContainer());
+ App::setContext($context);
+
+ return $context;
+ }
+
+ protected function clearAppContext(): void
+ {
+ $prop = new ReflectionProperty(App::class, 'context');
+ $prop->setAccessible(true);
+ $prop->setValue(null, null);
}
protected function setPrivateProperty($object, $property, $value): void
@@ -46,7 +71,12 @@ protected function setPrivateProperty($object, $property, $value): void
$reflection = new ReflectionClass($object);
$property = $reflection->getProperty($property);
$property->setAccessible(true);
- $property->setValue($object, $value);
+
+ if (is_string($object)) {
+ $property->setValue(null, $value);
+ } else {
+ $property->setValue($object, $value);
+ }
}
protected function getPrivateProperty($object, $property)
@@ -75,9 +105,7 @@ protected function testRequest(
array $body = [],
array $headers = []
) {
- $request = new Request();
-
- $request->create($method, $uri, $body, $headers);
+ request()->create($method, $uri, $body, $headers);
$route = new Route(
[$method],
@@ -88,10 +116,6 @@ protected function testRequest(
$route->module('Test');
$matchedRoute = new MatchedRoute($route, []);
- Request::setMatchedRoute($matchedRoute);
-
- if (!Di::isRegistered(Request::class)) {
- Di::set(Request::class, $request);
- }
+ request()->setMatchedRoute($matchedRoute);
}
}
diff --git a/tests/Unit/Asset/AssetManagerTest.php b/tests/Unit/Asset/AssetManagerTest.php
index bf922e899..da3f5b482 100644
--- a/tests/Unit/Asset/AssetManagerTest.php
+++ b/tests/Unit/Asset/AssetManagerTest.php
@@ -16,7 +16,7 @@ public function setUp(): void
config()->set('app.base_url', 'http://mydomain.com');
- $this->assetManager = AssetManager::getInstance();
+ $this->assetManager = asset();
}
public function testRegisterPublishDump(): void
diff --git a/tests/Unit/Asset/Helpers/AssetHelperFunctionsTest.php b/tests/Unit/Asset/Helpers/AssetHelperFunctionsTest.php
index c48dbbcdd..37df2682b 100644
--- a/tests/Unit/Asset/Helpers/AssetHelperFunctionsTest.php
+++ b/tests/Unit/Asset/Helpers/AssetHelperFunctionsTest.php
@@ -12,7 +12,7 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(AssetManager::class, 'instance', null);
+ asset()->flush();
}
public function testAssetHelper(): void
diff --git a/tests/Unit/Auth/AuthTestCase.php b/tests/Unit/Auth/AuthTestCase.php
index 5706fdc4a..6c40c0983 100644
--- a/tests/Unit/Auth/AuthTestCase.php
+++ b/tests/Unit/Auth/AuthTestCase.php
@@ -10,8 +10,8 @@ function random_number(int $length = 10): int
namespace Quantum\Tests\Unit\Auth {
+ use Quantum\Auth\Contracts\AuthServiceInterface;
use Quantum\Database\Adapters\Sleekdb\SleekDbal;
- use Quantum\Environment\Environment;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Mailer\Mailer;
use Quantum\Loader\Setup;
@@ -84,9 +84,7 @@ public function setUp(): void
SleekDbal::connect(config()->get('database.sleekdb'));
- Environment::getInstance()->load(new Setup('config', 'env'));
-
- $this->authService = Mockery::mock(\Quantum\Auth\Contracts\AuthServiceInterface::class);
+ $this->authService = Mockery::mock(AuthServiceInterface::class);
$this->authService->shouldReceive('userSchema')->andReturn($this->userSchema);
diff --git a/tests/Unit/Auth/Factories/AuthFactoryTest.php b/tests/Unit/Auth/Factories/AuthFactoryTest.php
index 37a3521a3..4fd3de8fe 100644
--- a/tests/Unit/Auth/Factories/AuthFactoryTest.php
+++ b/tests/Unit/Auth/Factories/AuthFactoryTest.php
@@ -9,6 +9,7 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Auth\Enums\AuthType;
use Quantum\Auth\Auth;
+use Quantum\Di\Di;
class AuthFactoryTest extends AppTestCase
{
@@ -16,7 +17,7 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(AuthFactory::class, 'instances', []);
+ $this->resetAuthFactory();
}
public function testAuthFactoryInstance(): void
@@ -65,4 +66,14 @@ public function testAuthFactoryReturnsSameInstance(): void
$this->assertSame($auth1, $auth2);
}
+
+ private function resetAuthFactory(): void
+ {
+ if (!Di::isRegistered(AuthFactory::class)) {
+ Di::register(AuthFactory::class);
+ }
+
+ $factory = Di::get(AuthFactory::class);
+ $this->setPrivateProperty($factory, 'instances', []);
+ }
}
diff --git a/tests/Unit/Cache/Factories/CacheFactoryTest.php b/tests/Unit/Cache/Factories/CacheFactoryTest.php
index 7bed8d839..ef6dbf3e2 100644
--- a/tests/Unit/Cache/Factories/CacheFactoryTest.php
+++ b/tests/Unit/Cache/Factories/CacheFactoryTest.php
@@ -11,6 +11,7 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Cache\Enums\CacheType;
use Quantum\Cache\Cache;
+use Quantum\Di\Di;
class CacheFactoryTest extends AppTestCase
{
@@ -18,7 +19,7 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(CacheFactory::class, 'instances', []);
+ $this->resetCacheFactory();
}
public function testCacheFactoryInstance(): void
@@ -79,4 +80,14 @@ public function testCacheFactoryReturnsSameInstance(): void
$this->assertSame($cache1, $cache2);
}
+
+ private function resetCacheFactory(): void
+ {
+ if (!Di::isRegistered(CacheFactory::class)) {
+ Di::register(CacheFactory::class);
+ }
+
+ $factory = Di::get(CacheFactory::class);
+ $this->setPrivateProperty($factory, 'instances', []);
+ }
}
diff --git a/tests/Unit/Captcha/Adapters/HcaptchaAdapterTest.php b/tests/Unit/Captcha/Adapters/HcaptchaAdapterTest.php
index 6d0b80bba..d5f33b926 100644
--- a/tests/Unit/Captcha/Adapters/HcaptchaAdapterTest.php
+++ b/tests/Unit/Captcha/Adapters/HcaptchaAdapterTest.php
@@ -6,7 +6,6 @@
use Quantum\Captcha\Adapters\HcaptchaAdapter;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\HttpClient\HttpClient;
-use Quantum\Asset\AssetManager;
use Mockery;
class HcaptchaAdapterTest extends AppTestCase
@@ -31,7 +30,7 @@ public function setUp(): void
public function tearDown(): void
{
- AssetManager::getInstance()->flush();
+ asset()->flush();
Mockery::close();
}
diff --git a/tests/Unit/Captcha/Adapters/RecaptchaAdapterTest.php b/tests/Unit/Captcha/Adapters/RecaptchaAdapterTest.php
index 934a3d70c..e9821a909 100644
--- a/tests/Unit/Captcha/Adapters/RecaptchaAdapterTest.php
+++ b/tests/Unit/Captcha/Adapters/RecaptchaAdapterTest.php
@@ -6,7 +6,6 @@
use Quantum\Captcha\Adapters\RecaptchaAdapter;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\HttpClient\HttpClient;
-use Quantum\Asset\AssetManager;
use Exception;
use Mockery;
@@ -32,7 +31,7 @@ public function setUp(): void
public function tearDown(): void
{
- AssetManager::getInstance()->flush();
+ asset()->flush();
Mockery::close();
}
diff --git a/tests/Unit/Captcha/Factories/CaptchaFactoryTest.php b/tests/Unit/Captcha/Factories/CaptchaFactoryTest.php
index 798f681fc..3b3f34d55 100644
--- a/tests/Unit/Captcha/Factories/CaptchaFactoryTest.php
+++ b/tests/Unit/Captcha/Factories/CaptchaFactoryTest.php
@@ -9,6 +9,7 @@
use Quantum\Captcha\Enums\CaptchaType;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Captcha\Captcha;
+use Quantum\Di\Di;
class CaptchaFactoryTest extends AppTestCase
{
@@ -16,7 +17,7 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(CaptchaFactory::class, 'instances', []);
+ $this->resetCaptchaFactory();
}
public function testCaptchaFactoryInstance(): void
@@ -63,4 +64,14 @@ public function testAuthFactoryReturnsSameInstance(): void
$this->assertSame($captcha1, $captcha2);
}
+
+ private function resetCaptchaFactory(): void
+ {
+ if (!Di::isRegistered(CaptchaFactory::class)) {
+ Di::register(CaptchaFactory::class);
+ }
+
+ $factory = Di::get(CaptchaFactory::class);
+ $this->setPrivateProperty($factory, 'instances', []);
+ }
}
diff --git a/tests/Unit/Config/ConfigTest.php b/tests/Unit/Config/ConfigTest.php
index 68315e2f4..157ffc3ea 100644
--- a/tests/Unit/Config/ConfigTest.php
+++ b/tests/Unit/Config/ConfigTest.php
@@ -11,39 +11,39 @@
class ConfigTest extends AppTestCase
{
+ private Config $config;
+
public function setUp(): void
{
parent::setUp();
config()->flush();
+
+ $this->config = new Config();
}
public function testConfigLoad(): void
{
- $config = Config::getInstance();
-
- $this->assertEmpty($config->all());
+ $this->assertEmpty($this->config->all());
- $config->load(new Setup('config', 'app'));
+ $this->config->load(new Setup('config', 'app'));
- $this->assertNotEmpty($config->all());
+ $this->assertNotEmpty($this->config->all());
- $this->assertInstanceOf(Data::class, $config->all());
+ $this->assertInstanceOf(Data::class, $this->config->all());
}
public function testConfigImport(): void
{
- $config = Config::getInstance();
+ $this->config->load(new Setup('config', 'app'));
- $config->load(new Setup('config', 'app'));
+ $this->assertNull($this->config->get('database.default'));
- $this->assertNull($config->get('database.default'));
+ $this->config->import(new Setup('config', 'database'));
- $config->import(new Setup('config', 'database'));
+ $this->assertNotNull($this->config->get('database.default'));
- $this->assertNotNull($config->get('database.default'));
-
- $this->assertEquals('sqlite', $config->get('database.default'));
+ $this->assertEquals('sqlite', $this->config->get('database.default'));
}
public function testImportingNonExistingConfigFile(): void
@@ -52,92 +52,80 @@ public function testImportingNonExistingConfigFile(): void
$this->expectExceptionMessage('File `config' . DS . 'somefile` not found!');
- Config::getInstance()->import(new Setup('config', 'somefile'));
+ $this->config->import(new Setup('config', 'somefile'));
}
public function testCollisionAtImporting(): void
{
- $config = Config::getInstance();
-
- $config->import(new Setup('config', 'app'));
+ $this->config->import(new Setup('config', 'app'));
$this->expectException(ConfigException::class);
$this->expectExceptionMessage('Config key `app` is already in use');
- $config->import(new Setup('config', 'app'));
+ $this->config->import(new Setup('config', 'app'));
}
public function testConfigHas(): void
{
- $config = Config::getInstance();
+ $this->config->import(new Setup('config', 'app'));
- $config->import(new Setup('config', 'app'));
+ $this->assertTrue($this->config->has('app.debug'));
- $this->assertTrue($config->has('app.debug'));
+ $this->assertTrue($this->config->has('app.test'));
- $this->assertTrue($config->has('app.test'));
-
- $this->assertFalse($config->has('app.none'));
+ $this->assertFalse($this->config->has('app.none'));
}
public function testConfigGet(): void
{
- $config = Config::getInstance();
-
- $config->import(new Setup('config', 'lang'));
+ $this->config->import(new Setup('config', 'lang'));
- $this->assertIsArray($config->get('lang.supported'));
+ $this->assertIsArray($this->config->get('lang.supported'));
- $this->assertEquals('Default Value', $config->get('not-exists', 'Default Value'));
+ $this->assertEquals('Default Value', $this->config->get('not-exists', 'Default Value'));
- $this->assertNull($config->get('not-exists'));
+ $this->assertNull($this->config->get('not-exists'));
}
public function testConfigSet(): void
{
- $config = Config::getInstance();
-
- $this->assertFalse($config->has('new-value'));
+ $this->assertFalse($this->config->has('new-value'));
- $config->set('new-value', 'New Value');
+ $this->config->set('new-value', 'New Value');
- $this->assertTrue($config->has('new-value'));
+ $this->assertTrue($this->config->has('new-value'));
- $this->assertEquals('New Value', $config->get('new-value'));
+ $this->assertEquals('New Value', $this->config->get('new-value'));
- $config->set('other.nested', 'Nested Value');
+ $this->config->set('other.nested', 'Nested Value');
- $this->assertTrue($config->has('other.nested'));
+ $this->assertTrue($this->config->has('other.nested'));
- $this->assertEquals('Nested Value', $config->get('other.nested'));
+ $this->assertEquals('Nested Value', $this->config->get('other.nested'));
}
public function testConfigDelete(): void
{
- $config = Config::getInstance();
+ $this->config->import(new Setup('config', 'app'));
- $config->import(new Setup('config', 'app'));
+ $this->assertNotNull($this->config->get('app.test'));
- $this->assertNotNull($config->get('app.test'));
+ $this->config->delete('app.test');
- $config->delete('app.test');
+ $this->assertFalse($this->config->has('app.test'));
- $this->assertFalse($config->has('app.test'));
-
- $this->assertNull($config->get('app.test'));
+ $this->assertNull($this->config->get('app.test'));
}
public function testConfigFlush(): void
{
- $config = Config::getInstance();
-
- $config->import(new Setup('config', 'app'));
+ $this->config->import(new Setup('config', 'app'));
- $this->assertNotEmpty($config->all());
+ $this->assertNotEmpty($this->config->all());
- $config->flush();
+ $this->config->flush();
- $this->assertEmpty($config->all());
+ $this->assertEmpty($this->config->all());
}
}
diff --git a/tests/Unit/Console/Commands/KeyGenerateCommandTest.php b/tests/Unit/Console/Commands/KeyGenerateCommandTest.php
index ca9c58cd3..3c960e1bc 100644
--- a/tests/Unit/Console/Commands/KeyGenerateCommandTest.php
+++ b/tests/Unit/Console/Commands/KeyGenerateCommandTest.php
@@ -6,7 +6,6 @@
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Helper\HelperSet;
use Quantum\Console\Commands\KeyGenerateCommand;
-use Quantum\Environment\Environment;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\App\App;
@@ -29,7 +28,7 @@ public function setUp(): void
$this->envFilePath = App::getBaseDir() . DS . '.env.testing';
$this->originalFileContent = (string) $this->fs->get($this->envFilePath);
- $this->originalEnvData = $this->getPrivateProperty(Environment::getInstance(), 'envContent');
+ $this->originalEnvData = $this->getPrivateProperty(environment(), 'envContent');
$this->command = new KeyGenerateCommand();
$this->command->setHelperSet(new HelperSet(['question' => new QuestionHelper()]));
@@ -39,7 +38,7 @@ public function setUp(): void
public function tearDown(): void
{
$this->fs->put($this->envFilePath, $this->originalFileContent);
- $this->setPrivateProperty(Environment::getInstance(), 'envContent', $this->originalEnvData);
+ $this->setPrivateProperty(environment(), 'envContent', $this->originalEnvData);
parent::tearDown();
}
diff --git a/tests/Unit/Cookie/CookieTest.php b/tests/Unit/Cookie/CookieTest.php
index 192e02908..de36723b9 100644
--- a/tests/Unit/Cookie/CookieTest.php
+++ b/tests/Unit/Cookie/CookieTest.php
@@ -15,12 +15,13 @@ public function setUp(): void
{
parent::setUp();
- $this->cookie = Cookie::getInstance($this->storage);
+ $this->cookie = new Cookie($this->storage);
}
public function tearDown(): void
{
$this->cookie->flush();
+ parent::tearDown();
}
public function testCookieConstructor(): void
diff --git a/tests/Unit/Csrf/CsrfTest.php b/tests/Unit/Csrf/CsrfTest.php
index 010856c6f..74367deab 100644
--- a/tests/Unit/Csrf/CsrfTest.php
+++ b/tests/Unit/Csrf/CsrfTest.php
@@ -18,9 +18,9 @@ public function setUp(): void
{
parent::setUp();
- $this->request = new Request();
+ $this->request = request();
- $this->csrf = Csrf::getInstance();
+ $this->csrf = csrf();
}
public function testGenerateToken(): void
diff --git a/tests/Unit/Csrf/Helpers/CsrfHelperFunctionsTest.php b/tests/Unit/Csrf/Helpers/CsrfHelperFunctionsTest.php
index 167eea029..8a97561b3 100644
--- a/tests/Unit/Csrf/Helpers/CsrfHelperFunctionsTest.php
+++ b/tests/Unit/Csrf/Helpers/CsrfHelperFunctionsTest.php
@@ -3,22 +3,56 @@
namespace Quantum\Tests\Unit\Csrf\Helpers;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Http\Request;
use Quantum\Csrf\Csrf;
class CsrfHelperFunctionsTest extends AppTestCase
{
- public function testCsrfHelper(): void
+ private string $key = '#321dMd3QS15%';
+
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ session()->delete(Csrf::TOKEN_KEY);
+ }
+
+ public function testCsrfHelperReturnsInstance(): void
{
$this->assertInstanceOf(Csrf::class, csrf());
}
- public function testCsrfToken(): void
+ public function testCsrfHelperReturnsSameInstance(): void
{
- $request = new Request();
+ $this->assertSame(csrf(), csrf());
+ }
+
+ public function testCsrfTokenGeneratesToken(): void
+ {
+ $token = csrf()->generateToken($this->key);
+
+ $this->assertNotEmpty($token);
+
+ $this->assertIsString($token);
- $request->create('PUT', '/update', ['title' => 'Task Title', 'csrf-token' => csrf_token()]);
+ $this->assertTrue(session()->has(Csrf::TOKEN_KEY));
+ }
+
+ public function testCsrfTokenHelperGeneratesToken(): void
+ {
+ $token = csrf_token();
+
+ $this->assertNotEmpty($token);
+
+ $this->assertIsString($token);
+
+ $this->assertTrue(session()->has(Csrf::TOKEN_KEY));
+ }
+
+ public function testCsrfTokenHelperReturnsSameTokenOnSubsequentCalls(): void
+ {
+ $token1 = csrf_token();
+ $token2 = csrf_token();
- $this->assertTrue(csrf()->checkToken($request));
+ $this->assertSame($token1, $token2);
}
}
diff --git a/tests/Unit/Database/Adapters/Idiorm/IdiormDbalTestCase.php b/tests/Unit/Database/Adapters/Idiorm/IdiormDbalTestCase.php
index 56d4f221d..f06a353d9 100644
--- a/tests/Unit/Database/Adapters/Idiorm/IdiormDbalTestCase.php
+++ b/tests/Unit/Database/Adapters/Idiorm/IdiormDbalTestCase.php
@@ -5,7 +5,6 @@
use Quantum\Tests\Unit\Database\Adapters\DatabaseSeeder;
use Quantum\Database\Adapters\Idiorm\IdiormDbal;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Database\Database;
abstract class IdiormDbalTestCase extends AppTestCase
{
@@ -23,8 +22,6 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(Database::class, 'instance', null);
-
config()->set('app.debug', true);
IdiormDbal::connect(['driver' => 'sqlite', 'database' => ':memory:']);
@@ -41,6 +38,8 @@ public function tearDown(): void
$this->deleteTables();
IdiormDbal::disconnect();
+
+ parent::tearDown();
}
private function createTables(): void
diff --git a/tests/Unit/Database/Adapters/Sleekdb/SleekDbalTestCase.php b/tests/Unit/Database/Adapters/Sleekdb/SleekDbalTestCase.php
index 6e87bc1e6..f8f58277c 100644
--- a/tests/Unit/Database/Adapters/Sleekdb/SleekDbalTestCase.php
+++ b/tests/Unit/Database/Adapters/Sleekdb/SleekDbalTestCase.php
@@ -5,7 +5,6 @@
use Quantum\Tests\Unit\Database\Adapters\DatabaseSeeder;
use Quantum\Database\Adapters\Sleekdb\SleekDbal;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Database\Database;
use Quantum\Loader\Setup;
abstract class SleekDbalTestCase extends AppTestCase
@@ -25,8 +24,6 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(Database::class, 'instance', null);
-
if (!config()->has('database')) {
config()->import(new Setup('config', 'database'));
}
@@ -45,6 +42,8 @@ public function tearDown(): void
$this->deleteTables();
SleekDbal::disconnect();
+
+ parent::tearDown();
}
public function deleteTables(): void
diff --git a/tests/Unit/Database/DatabaseTest.php b/tests/Unit/Database/DatabaseTest.php
index dff5475f4..67da7922a 100644
--- a/tests/Unit/Database/DatabaseTest.php
+++ b/tests/Unit/Database/DatabaseTest.php
@@ -6,6 +6,7 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Database\Database;
use Quantum\Loader\Setup;
+use Quantum\Di\Di;
class DatabaseTest extends AppTestCase
{
@@ -21,8 +22,6 @@ public function setUp(): void
config()->set('debug', true);
- $this->setPrivateProperty(Database::class, 'instance', null);
-
Database::execute('CREATE TABLE IF NOT EXISTS profiles (
id INTEGER PRIMARY KEY,
firstname VARCHAR(255),
@@ -36,13 +35,15 @@ public function setUp(): void
public function tearDown(): void
{
Database::execute('DROP TABLE IF EXISTS profiles');
+
+ parent::tearDown();
}
- public function testDatabaseInstance(): void
+ public function testDatabaseDiReturnsSameInstance(): void
{
- $db1 = Database::getInstance();
+ $db1 = Di::get(Database::class);
- $db2 = Database::getInstance();
+ $db2 = Di::get(Database::class);
$this->assertInstanceOf(Database::class, $db1);
@@ -51,12 +52,12 @@ public function testDatabaseInstance(): void
public function testDatabaseGetConfigs(): void
{
- $this->assertEquals(config()->get('database.sqlite'), Database::getInstance()->getConfigs());
+ $this->assertEquals(config()->get('database.sqlite'), Di::get(Database::class)->getConfigs());
}
public function testDatabaseGetOrmClass(): void
{
- $this->assertEquals(IdiormDbal::class, Database::getInstance()->getOrmClass());
+ $this->assertEquals(IdiormDbal::class, Di::get(Database::class)->getOrmClass());
}
public function testDatabaseRawQueries(): void
diff --git a/tests/Unit/Debugger/DebuggerTest.php b/tests/Unit/Debugger/DebuggerTest.php
index e1bcb4aa9..5300c794e 100644
--- a/tests/Unit/Debugger/DebuggerTest.php
+++ b/tests/Unit/Debugger/DebuggerTest.php
@@ -40,9 +40,7 @@ public function setUp(): void
->with($collector);
}
- $this->setPrivateProperty(Debugger::class, 'instance', null);
-
- $this->debugger = Debugger::getInstance($this->debuggerStore, $this->debugBarMock, $collectors);
+ $this->debugger = new Debugger($this->debuggerStore, $this->debugBarMock, $collectors);
}
public function testDebuggerIsEnabled(): void
diff --git a/tests/Unit/Di/DiContainerTest.php b/tests/Unit/Di/DiContainerTest.php
new file mode 100644
index 000000000..f263a11a9
--- /dev/null
+++ b/tests/Unit/Di/DiContainerTest.php
@@ -0,0 +1,319 @@
+container = new DiContainer();
+ }
+
+ public function testRegisterDependency(): void
+ {
+ $this->container->register(Setup::class);
+
+ $this->assertInstanceOf(Setup::class, $this->container->get(Setup::class));
+ }
+
+ public function testAttemptingToRegisterAlreadyRegisteredDependency(): void
+ {
+ $this->expectException(DiException::class);
+ $this->expectExceptionMessage('The dependency `Quantum\Loader\Setup` is already registered.');
+
+ $this->container->register(Setup::class);
+ $this->container->register(Setup::class);
+ }
+
+ public function testAttemptingToRegisterNonExistentClass(): void
+ {
+ $this->expectException(DiException::class);
+ $this->expectExceptionMessage('The dependency `NonExistentClass` is not instantiable.');
+
+ $this->container->register('NonExistentClass');
+ }
+
+ public function testAttemptingToRegisterNonExistentAbstract(): void
+ {
+ $this->expectException(DiException::class);
+ $this->expectExceptionMessage('The dependency `NonExistentInterface` is not valid abstract class.');
+
+ $this->container->register(DummyService::class, 'NonExistentInterface');
+ }
+
+ public function testIsRegistered(): void
+ {
+ $this->assertFalse($this->container->isRegistered(DummyService::class));
+
+ $this->container->register(DummyService::class);
+
+ $this->assertTrue($this->container->isRegistered(DummyService::class));
+ }
+
+ public function testHasReturnsFalseBeforeResolve(): void
+ {
+ $this->container->register(DummyService::class);
+
+ $this->assertFalse($this->container->has(DummyService::class));
+ }
+
+ public function testHasReturnsTrueAfterGet(): void
+ {
+ $this->container->register(DummyService::class);
+
+ $this->container->get(DummyService::class);
+
+ $this->assertTrue($this->container->has(DummyService::class));
+ }
+
+ public function testHasReturnsTrueAfterSet(): void
+ {
+ $instance = new DummyService();
+
+ $this->container->set(DummyServiceInterface::class, $instance);
+
+ $this->assertTrue($this->container->has(DummyServiceInterface::class));
+ }
+
+ public function testHasReturnsFalseAfterResetContainer(): void
+ {
+ $this->container->register(DummyService::class);
+ $this->container->get(DummyService::class);
+
+ $this->assertTrue($this->container->has(DummyService::class));
+
+ $this->container->resetContainer();
+
+ $this->assertFalse($this->container->has(DummyService::class));
+ }
+
+ public function testHasReturnsFalseAfterReset(): void
+ {
+ $this->container->register(DummyService::class);
+ $this->container->get(DummyService::class);
+
+ $this->assertTrue($this->container->has(DummyService::class));
+
+ $this->container->reset();
+
+ $this->assertFalse($this->container->has(DummyService::class));
+ }
+
+ public function testAbstractToConcreteBinding(): void
+ {
+ $this->container->register(DummyService::class, DummyServiceInterface::class);
+
+ $instance = $this->container->get(DummyServiceInterface::class);
+
+ $this->assertInstanceOf(DummyService::class, $instance);
+ }
+
+ public function testSetBindsInstanceToAbstract(): void
+ {
+ $instance = new DummyService();
+
+ $this->container->set(DummyServiceInterface::class, $instance);
+
+ $resolved = $this->container->get(DummyServiceInterface::class);
+
+ $this->assertSame($instance, $resolved);
+ $this->assertInstanceOf(DummyService::class, $resolved);
+ }
+
+ public function testSetWorksWithoutPriorRegister(): void
+ {
+ $instance = new DummyService();
+
+ $this->assertFalse($this->container->isRegistered(DummyServiceInterface::class));
+
+ $this->container->set(DummyServiceInterface::class, $instance);
+
+ $this->assertTrue($this->container->isRegistered(DummyServiceInterface::class));
+ $this->assertSame($instance, $this->container->get(DummyServiceInterface::class));
+ }
+
+ public function testSetRejectsWrongInstanceType(): void
+ {
+ $this->expectException(DiException::class);
+ $this->expectExceptionMessage(
+ 'The dependency `' . DummyServiceInterface::class . '` is not valid abstract class.'
+ );
+
+ $this->container->set(DummyServiceInterface::class, new \stdClass());
+ }
+
+ public function testSetRejectsInvalidAbstract(): void
+ {
+ $this->expectException(DiException::class);
+ $this->expectExceptionMessage(
+ 'The dependency `NonExistentInterface` is not valid abstract class.'
+ );
+
+ $this->container->set('NonExistentInterface', new DummyService());
+ }
+
+ public function testSetRejectsWhenAlreadyResolved(): void
+ {
+ $this->container->register(DummyService::class);
+ $this->container->get(DummyService::class);
+
+ $this->expectException(DiException::class);
+ $this->expectExceptionMessage(
+ 'The dependency `' . DummyService::class . '` is already registered.'
+ );
+
+ $this->container->set(DummyService::class, new DummyService());
+ }
+
+ public function testSetOverridesRegisteredButNotResolved(): void
+ {
+ $this->container->register(DummyService::class, DummyServiceInterface::class);
+
+ $instance = new DummyService();
+ $this->container->set(DummyServiceInterface::class, $instance);
+
+ $resolved = $this->container->get(DummyServiceInterface::class);
+
+ $this->assertSame($instance, $resolved);
+ }
+
+ public function testGetThrowsForUnregisteredInstantiableClass(): void
+ {
+ $this->assertFalse($this->container->isRegistered(DiException::class));
+
+ $this->expectException(DiException::class);
+ $this->expectExceptionMessage('The dependency `Quantum\Di\Exceptions\DiException` is not registered.');
+
+ $this->container->get(DiException::class);
+ }
+
+ public function testGetThrowsForNonInstantiableClass(): void
+ {
+ $this->expectException(DiException::class);
+ $this->expectExceptionMessage('The dependency `Quantum\Service\DummyServiceInterface` is not registered.');
+
+ $this->container->get(DummyServiceInterface::class);
+ }
+
+ public function testCircularDependencyDetectedAtResolve(): void
+ {
+ $this->expectException(DiException::class);
+ $this->expectExceptionMessage(
+ 'Circular dependency detected: `' . CircularDependencyA::class .
+ ' -> ' . CircularDependencyB::class .
+ ' -> ' . CircularDependencyA::class . '`'
+ );
+
+ $this->container->register(CircularDependencyA::class);
+ $this->container->register(CircularDependencyB::class);
+
+ $this->container->create(CircularDependencyA::class);
+ }
+
+ public function testGetReturnsSingleton(): void
+ {
+ $this->container->register(DummyService::class);
+
+ $instance1 = $this->container->get(DummyService::class);
+ $instance2 = $this->container->get(DummyService::class);
+
+ $this->assertInstanceOf(DummyService::class, $instance1);
+ $this->assertSame($instance1, $instance2);
+ }
+
+ public function testCreateReturnsNewInstance(): void
+ {
+ $this->container->register(DummyService::class);
+
+ $instance1 = $this->container->create(DummyService::class);
+ $instance2 = $this->container->create(DummyService::class);
+
+ $this->assertInstanceOf(DummyService::class, $instance1);
+ $this->assertNotSame($instance1, $instance2);
+ }
+
+ public function testAutowire(): void
+ {
+ $this->container->register(Request::class);
+ $this->container->register(Response::class);
+
+ $params = $this->container->autowire([new TestDiController(), 'index']);
+
+ $this->assertInstanceOf(Request::class, $params[0]);
+ $this->assertInstanceOf(Response::class, $params[1]);
+ $this->assertInstanceOf(ViewFactory::class, $params[2]);
+
+ $callback = function (Request $request, Response $response): void {
+ };
+
+ $params = $this->container->autowire($callback);
+
+ $this->assertInstanceOf(Request::class, $params[0]);
+ $this->assertInstanceOf(Response::class, $params[1]);
+ }
+
+ public function testAutowireWithAbstract(): void
+ {
+ $this->container->register(DummyService::class, DummyServiceInterface::class);
+
+ $controller = new TestDiController();
+
+ $params = $this->container->autowire([$controller, 'handleService']);
+
+ $this->assertInstanceOf(DummyServiceInterface::class, $params[0]);
+ $this->assertInstanceOf(DummyService::class, $params[0]);
+ }
+
+ public function testResetClearsAll(): void
+ {
+ $this->container->register(DummyService::class);
+ $this->container->get(DummyService::class);
+
+ $this->container->reset();
+
+ $this->assertFalse($this->container->isRegistered(DummyService::class));
+ $this->assertFalse($this->container->has(DummyService::class));
+ }
+
+ public function testResetContainerKeepsDependencies(): void
+ {
+ $this->container->register(DummyService::class);
+ $this->container->get(DummyService::class);
+
+ $this->container->resetContainer();
+
+ $this->assertTrue($this->container->isRegistered(DummyService::class));
+ $this->assertFalse($this->container->has(DummyService::class));
+ }
+
+ public function testContainerIsolation(): void
+ {
+ $container1 = new DiContainer();
+ $container1->register(DummyService::class);
+ $container1->get(DummyService::class);
+
+ $container2 = new DiContainer();
+
+ $this->assertTrue($container1->isRegistered(DummyService::class));
+ $this->assertTrue($container1->has(DummyService::class));
+
+ $this->assertFalse($container2->isRegistered(DummyService::class));
+ $this->assertFalse($container2->has(DummyService::class));
+ }
+}
diff --git a/tests/Unit/Di/DiTest.php b/tests/Unit/Di/DiTest.php
index e9197739d..477bb2edf 100644
--- a/tests/Unit/Di/DiTest.php
+++ b/tests/Unit/Di/DiTest.php
@@ -48,19 +48,13 @@ public function __construct(CircularDependencyA $a)
namespace Quantum\Tests\Unit\Di {
- use Quantum\Service\DummyServiceInterface;
- use Quantum\Controllers\TestDiController;
- use Quantum\Service\CircularDependencyA;
- use Quantum\Service\CircularDependencyB;
- use Quantum\View\Factories\ViewFactory;
use Quantum\Di\Exceptions\DiException;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Service\DummyService;
- use Quantum\Loader\Loader;
use Quantum\Http\Response;
use Quantum\Http\Request;
use Quantum\Loader\Setup;
- use ReflectionProperty;
+ use Quantum\App\App;
use Quantum\Di\Di;
class DiTest extends AppTestCase
@@ -70,265 +64,96 @@ public function setUp(): void
parent::setUp();
}
- public function testDiRegisterDependency(): void
- {
- Di::register(Setup::class);
-
- $this->assertInstanceOf(Setup::class, Di::get(Setup::class));
- }
-
- public function testDiAttemptingToRegisterAlreadyRegisteredDependency(): void
- {
- $this->expectException(DiException::class);
-
- $this->expectExceptionMessage('The dependency `Quantum\Loader\Setup` is already registered.');
-
- Di::register(Setup::class);
- Di::register(Setup::class);
- }
-
- public function testDiAttemptingToRegisterNonExistentClass(): void
+ public function testFacadeDelegatesToAppContextContainer(): void
{
- $this->expectException(DiException::class);
- $this->expectExceptionMessage('The dependency `NonExistentClass` is not instantiable.');
-
- Di::register('NonExistentClass');
- }
-
- public function testDiAttemptingToRegisterNonExistentAbstract(): void
- {
- $this->expectException(DiException::class);
- $this->expectExceptionMessage('The dependency `NonExistentInterface` is not valid abstract class.');
-
- Di::register(DummyService::class, 'NonExistentInterface');
- }
-
- public function testDiIsRegistered(): void
- {
- $this->assertFalse(Di::isRegistered(DummyService::class));
+ $container = App::getContext()->getContainer();
Di::register(DummyService::class);
- $this->assertTrue(Di::isRegistered(DummyService::class));
- }
-
- public function testDiAbstractToConcreteBinding(): void
- {
- Di::register(DummyService::class, DummyServiceInterface::class);
+ $this->assertTrue($container->isRegistered(DummyService::class));
- $instance = Di::get(DummyServiceInterface::class);
+ $instance = Di::get(DummyService::class);
$this->assertInstanceOf(DummyService::class, $instance);
+ $this->assertSame($instance, $container->get(DummyService::class));
}
- public function testDiSetBindsInstanceToAbstract(): void
+ public function testGetCurrentReturnsAppContextContainer(): void
{
- $instance = new DummyService();
+ $container = App::getContext()->getContainer();
- Di::set(DummyServiceInterface::class, $instance);
-
- $resolved = Di::get(DummyServiceInterface::class);
-
- $this->assertSame($instance, $resolved);
- $this->assertInstanceOf(DummyService::class, $resolved);
- }
-
- public function testDiSetWorksWithoutPriorRegister(): void
- {
- $instance = new DummyService();
-
- $this->assertFalse(Di::isRegistered(DummyServiceInterface::class));
-
- Di::set(DummyServiceInterface::class, $instance);
-
- $this->assertTrue(Di::isRegistered(DummyServiceInterface::class));
-
- $this->assertSame($instance, Di::get(DummyServiceInterface::class));
- }
-
- public function testDiSetRejectsWrongInstanceType(): void
- {
- $this->expectException(DiException::class);
- $this->expectExceptionMessage(
- 'The dependency `' . DummyServiceInterface::class . '` is not valid abstract class.'
- );
-
- Di::set(DummyServiceInterface::class, new \stdClass());
+ $this->assertSame($container, Di::getCurrent());
}
- public function testDiSetRejectsInvalidAbstract(): void
- {
- $this->expectException(DiException::class);
- $this->expectExceptionMessage(
- 'The dependency `NonExistentInterface` is not valid abstract class.'
- );
-
- Di::set('NonExistentInterface', new DummyService());
- }
-
- public function testDiSetRejectsWhenAlreadyResolved(): void
+ public function testNewContextGivesCleanContainer(): void
{
Di::register(DummyService::class);
-
Di::get(DummyService::class);
- $this->expectException(DiException::class);
- $this->expectExceptionMessage(
- 'The dependency `' . DummyService::class . '` is already registered.'
- );
-
- Di::set(DummyService::class, new DummyService());
- }
-
- public function testDiSetOverridesRegisteredButNotResolved(): void
- {
- Di::register(DummyService::class, DummyServiceInterface::class);
-
- $instance = new DummyService();
-
- Di::set(DummyServiceInterface::class, $instance);
-
- $resolved = Di::get(DummyServiceInterface::class);
-
- $this->assertSame($instance, $resolved);
- }
-
- public function testDiGetCoreDependencies(): void
- {
- $this->assertInstanceOf(Loader::class, Di::get(Loader::class));
+ $this->assertTrue(Di::isRegistered(DummyService::class));
+ $this->assertTrue(Di::has(DummyService::class));
- $this->assertInstanceOf(Request::class, Di::get(Request::class));
+ $this->createContext();
- $this->assertInstanceOf(Response::class, Di::get(Response::class));
+ $this->assertFalse(Di::isRegistered(DummyService::class));
+ $this->assertFalse(Di::has(DummyService::class));
}
- public function testDiAttemptingToGetNotRegisteredDependency(): void
+ public function testResetContainerKeepsRegistrations(): void
{
- $this->assertInstanceOf(Loader::class, Di::get(Loader::class));
+ Di::register(DummyService::class);
+ Di::get(DummyService::class);
- $this->expectException(DiException::class);
+ $this->assertTrue(Di::isRegistered(DummyService::class));
+ $this->assertTrue(Di::has(DummyService::class));
- $this->expectExceptionMessage('The dependency `Quantum\Di\Exceptions\DiException` is not registered.');
+ Di::resetContainer();
- Di::get(DiException::class);
+ $this->assertTrue(Di::isRegistered(DummyService::class));
+ $this->assertFalse(Di::has(DummyService::class));
}
- public function testDiCircularDependencyDetectedAtResolve(): void
+ public function testFacadeRegisterAndGet(): void
{
- $this->expectException(DiException::class);
-
- $this->expectExceptionMessage(
- 'Circular dependency detected: `' . CircularDependencyA::class .
- ' -> ' . CircularDependencyB::class .
- ' -> ' . CircularDependencyA::class . '`'
- );
-
- Di::register(CircularDependencyA::class);
- Di::register(CircularDependencyB::class);
+ Di::register(Setup::class);
- Di::create(CircularDependencyA::class);
+ $this->assertInstanceOf(Setup::class, Di::get(Setup::class));
}
- public function testDiGetReturnsSingleton(): void
+ public function testFacadeSet(): void
{
- Di::register(DummyService::class);
-
- $instance1 = Di::get(DummyService::class);
-
- $instance2 = Di::get(DummyService::class);
+ $instance = new DummyService();
- $this->assertInstanceOf(DummyService::class, $instance1);
+ Di::set(DummyService::class, $instance);
- $this->assertSame($instance1, $instance2);
+ $this->assertSame($instance, Di::get(DummyService::class));
}
- public function testDiCreateReturnsNewInstance(): void
+ public function testFacadeCreate(): void
{
- Di::register(DummyService::class);
-
$instance1 = Di::create(DummyService::class);
-
$instance2 = Di::create(DummyService::class);
$this->assertInstanceOf(DummyService::class, $instance1);
-
$this->assertNotSame($instance1, $instance2);
}
- public function testDiAutowire(): void
+ public function testFacadeAutowire(): void
{
- $params = Di::autowire([new TestDiController(), 'index']);
-
- $this->assertInstanceOf(Request::class, $params[0]);
-
- $this->assertInstanceOf(Response::class, $params[1]);
-
- $this->assertInstanceOf(ViewFactory::class, $params[2]);
-
$callback = function (Request $request, Response $response): void {
- // function body
};
$params = Di::autowire($callback);
$this->assertInstanceOf(Request::class, $params[0]);
-
$this->assertInstanceOf(Response::class, $params[1]);
}
- public function testDiAutowireWithAbstract(): void
+ public function testCallStaticThrowsForInvalidMethod(): void
{
- Di::register(DummyService::class, DummyServiceInterface::class);
-
- $controller = new TestDiController();
-
- $params = Di::autowire([$controller, 'handleService']);
-
- $this->assertInstanceOf(DummyServiceInterface::class, $params[0]);
-
- $this->assertInstanceOf(DummyService::class, $params[0]);
- }
-
- public function testDiReset(): void
- {
- Di::register(DummyService::class);
-
- Di::get(DummyService::class);
-
- $this->assertTrue(Di::isRegistered(DummyService::class));
-
- Di::reset();
-
- $dependenciesProperty = new ReflectionProperty(Di::class, 'dependencies');
- $dependenciesProperty->setAccessible(true);
-
- $containerProperty = new ReflectionProperty(Di::class, 'container');
- $containerProperty->setAccessible(true);
-
- $this->assertEmpty($dependenciesProperty->getValue());
-
- $this->assertEmpty($containerProperty->getValue());
- }
-
- public function testDiResetContainer(): void
- {
- Di::register(DummyService::class);
-
- Di::get(DummyService::class);
-
- $this->assertTrue(Di::isRegistered(DummyService::class));
-
- Di::resetContainer();
-
- $dependenciesProperty = new ReflectionProperty(Di::class, 'dependencies');
- $dependenciesProperty->setAccessible(true);
-
- $containerProperty = new ReflectionProperty(Di::class, 'container');
- $containerProperty->setAccessible(true);
-
- $this->assertNotEmpty($dependenciesProperty->getValue());
+ $this->expectException(DiException::class);
- $this->assertEmpty($containerProperty->getValue());
+ Di::nonExistentMethod();
}
}
}
diff --git a/tests/Unit/Environment/EnvironmentTest.php b/tests/Unit/Environment/EnvironmentTest.php
index 71ac72b80..8ee614c69 100644
--- a/tests/Unit/Environment/EnvironmentTest.php
+++ b/tests/Unit/Environment/EnvironmentTest.php
@@ -14,7 +14,7 @@ public function setUp(): void
{
parent::setUp();
- $this->env = Environment::getInstance();
+ $this->env = environment();
}
public function testEnvironmentGetAppEnv(): void
@@ -47,6 +47,36 @@ public function testEnvironmentGetRow(): void
$this->assertEquals('APP_KEY=XYZ1234567890ABCDEFG123456789HIGKLMNOPQRSTUVWXYZ0123456789abcdefgh', $this->env->getRow('APP_KEY'));
}
+ public function testEnvironmentIsTestingInTestEnv(): void
+ {
+ $this->assertTrue($this->env->isTesting());
+ $this->assertFalse($this->env->isProduction());
+ $this->assertFalse($this->env->isStaging());
+ $this->assertFalse($this->env->isDevelopment());
+ $this->assertFalse($this->env->isLocal());
+ }
+
+ public function testEnvironmentCheckMethodsWithDifferentEnvs(): void
+ {
+ $this->setPrivateProperty($this->env, 'appEnv', 'production');
+ $this->assertTrue($this->env->isProduction());
+ $this->assertFalse($this->env->isTesting());
+
+ $this->setPrivateProperty($this->env, 'appEnv', 'staging');
+ $this->assertTrue($this->env->isStaging());
+ $this->assertFalse($this->env->isProduction());
+
+ $this->setPrivateProperty($this->env, 'appEnv', 'development');
+ $this->assertTrue($this->env->isDevelopment());
+ $this->assertFalse($this->env->isProduction());
+
+ $this->setPrivateProperty($this->env, 'appEnv', 'local');
+ $this->assertTrue($this->env->isLocal());
+ $this->assertFalse($this->env->isProduction());
+
+ $this->setPrivateProperty($this->env, 'appEnv', 'testing');
+ }
+
public function testEnvironmentAddAndUpdateRow(): void
{
$envFilePath = App::getBaseDir() . DS . '.env.testing';
diff --git a/tests/Unit/Environment/Helpers/EnvHelperTest.php b/tests/Unit/Environment/Helpers/EnvHelperTest.php
index 420556847..8f0a839d8 100644
--- a/tests/Unit/Environment/Helpers/EnvHelperTest.php
+++ b/tests/Unit/Environment/Helpers/EnvHelperTest.php
@@ -2,10 +2,21 @@
namespace Quantum\Tests\Unit\Environment\Helpers;
+use Quantum\Environment\Environment;
use Quantum\Tests\Unit\AppTestCase;
class EnvHelperTest extends AppTestCase
{
+ public function testEnvironmentHelperReturnsInstance(): void
+ {
+ $this->assertInstanceOf(Environment::class, environment());
+ }
+
+ public function testEnvironmentHelperReturnsSameInstance(): void
+ {
+ $this->assertSame(environment(), environment());
+ }
+
public function testGetEnvValue(): void
{
$this->assertNotNull(env('APP_KEY'));
@@ -14,4 +25,10 @@ public function testGetEnvValue(): void
$this->assertEquals('TRUE', env('DEBUG'));
}
+
+ public function testGetEnvValueWithDefault(): void
+ {
+ $this->assertNull(env('NON_EXISTING'));
+ $this->assertEquals('fallback', env('NON_EXISTING', 'fallback'));
+ }
}
diff --git a/tests/Unit/Environment/Helpers/ServerHelperTest.php b/tests/Unit/Environment/Helpers/ServerHelperTest.php
index 520b2a0b3..7de1f9e62 100644
--- a/tests/Unit/Environment/Helpers/ServerHelperTest.php
+++ b/tests/Unit/Environment/Helpers/ServerHelperTest.php
@@ -3,7 +3,6 @@
namespace Quantum\Tests\Unit\Environment\Helpers;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Environment\Server;
class ServerHelperTest extends AppTestCase
{
@@ -11,42 +10,36 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(Server::class, 'instance', null);
+ server()->flush();
}
public function testGetUserIpFromClientIp(): void
{
- $_SERVER['HTTP_CLIENT_IP'] = '192.168.1.1';
- $_SERVER['HTTP_X_FORWARDED_FOR'] = null;
- $_SERVER['REMOTE_ADDR'] = null;
+ server()->set('HTTP_CLIENT_IP', '192.168.1.1');
$this->assertEquals('192.168.1.1', get_user_ip());
}
public function testGetUserIpFromXForwardedFor(): void
{
- $_SERVER['HTTP_CLIENT_IP'] = null;
- $_SERVER['HTTP_X_FORWARDED_FOR'] = '203.0.113.5';
- $_SERVER['REMOTE_ADDR'] = null;
+ server()->set('HTTP_X_FORWARDED_FOR', '203.0.113.5');
$this->assertEquals('203.0.113.5', get_user_ip());
}
public function testGetUserIpFromRemoteAddr(): void
{
- $_SERVER['HTTP_CLIENT_IP'] = null;
- $_SERVER['HTTP_X_FORWARDED_FOR'] = null;
- $_SERVER['REMOTE_ADDR'] = '198.51.100.1';
+ server()->set('REMOTE_ADDR', '198.51.100.1');
$this->assertEquals('198.51.100.1', get_user_ip());
}
public function testGetAllHeaders(): void
{
- $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0';
- $_SERVER['HTTP_ACCEPT'] = 'text/html';
- $_SERVER['HTTP_X_CUSTOM_HEADER'] = 'CustomValue';
- $_SERVER['SERVER_NAME'] = 'example.com';
+ server()->set('HTTP_USER_AGENT', 'Mozilla/5.0');
+ server()->set('HTTP_ACCEPT', 'text/html');
+ server()->set('HTTP_X_CUSTOM_HEADER', 'CustomValue');
+ server()->set('SERVER_NAME', 'example.com');
$headers = getallheaders();
diff --git a/tests/Unit/Environment/ServerTest.php b/tests/Unit/Environment/ServerTest.php
index 336398f06..56d5e55d3 100644
--- a/tests/Unit/Environment/ServerTest.php
+++ b/tests/Unit/Environment/ServerTest.php
@@ -4,6 +4,7 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Environment\Server;
+use Quantum\Di\Di;
class ServerTest extends AppTestCase
{
@@ -11,20 +12,20 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(Server::class, 'instance', null);
+ server()->flush();
}
- public function testServerGetInstance(): void
+ public function testServerDiReturnsSameInstance(): void
{
- $server1 = Server::getInstance();
- $server2 = Server::getInstance();
+ $server1 = Di::get(Server::class);
+ $server2 = Di::get(Server::class);
$this->assertSame($server1, $server2);
}
public function testServerAll(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('REQUEST_METHOD', 'GET');
$server->set('REQUEST_URI', '/test');
@@ -39,7 +40,7 @@ public function testServerAll(): void
public function testServerSetAndGet(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('REQUEST_METHOD', 'POST');
@@ -54,7 +55,7 @@ public function testServerSetAndGet(): void
public function testServerUri(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('REQUEST_URI', '/test/uri');
$this->assertEquals('/test/uri', $server->uri());
@@ -62,7 +63,7 @@ public function testServerUri(): void
public function testServerQuery(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('QUERY_STRING', 'foo=bar');
$this->assertEquals('foo=bar', $server->query());
@@ -70,7 +71,7 @@ public function testServerQuery(): void
public function testServerMethod(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('REQUEST_METHOD', 'PUT');
$this->assertEquals('PUT', $server->method());
@@ -78,7 +79,7 @@ public function testServerMethod(): void
public function testServerProtocol(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('HTTPS', 'on');
$server->set('SERVER_PORT', 443);
@@ -92,7 +93,7 @@ public function testServerProtocol(): void
public function testServerHost(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('SERVER_NAME', 'localhost');
$this->assertEquals('localhost', $server->host());
@@ -100,7 +101,7 @@ public function testServerHost(): void
public function testServerPort(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('SERVER_PORT', '9000');
$this->assertEquals('9000', $server->port());
@@ -108,7 +109,7 @@ public function testServerPort(): void
public function testServerContentType(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('CONTENT_TYPE', 'application/json; charset=utf-8');
$this->assertEquals('application/json; charset=utf-8', $server->contentType());
@@ -117,7 +118,7 @@ public function testServerContentType(): void
public function testServerReferrer(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('HTTP_REFERER', 'http://example.com');
$this->assertEquals('http://example.com', $server->referrer());
@@ -125,7 +126,7 @@ public function testServerReferrer(): void
public function testServerAjax(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest');
$this->assertTrue($server->ajax());
@@ -137,7 +138,7 @@ public function testServerAjax(): void
public function testServerGetUserIpFromRemoteAddr(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('HTTP_CLIENT_IP', '192.168.1.1');
$server->set('HTTP_X_FORWARDED_FOR', null);
@@ -162,7 +163,7 @@ public function testServerGetUserIpFromRemoteAddr(): void
public function testServerGetAllHeadersFromServerClass(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('HTTP_USER_AGENT', 'Mozilla/5.0');
$server->set('HTTP_ACCEPT', 'text/html');
@@ -184,7 +185,7 @@ public function testServerGetAllHeadersFromServerClass(): void
public function testServerAcceptedLang(): void
{
- $server = Server::getInstance();
+ $server = server();
$server->set('HTTP_ACCEPT_LANGUAGE', null);
$this->assertNull($server->acceptedLang());
diff --git a/tests/Unit/Hook/HookManagerTest.php b/tests/Unit/Hook/HookManagerTest.php
index 176665dc3..e9c9b9489 100644
--- a/tests/Unit/Hook/HookManagerTest.php
+++ b/tests/Unit/Hook/HookManagerTest.php
@@ -8,21 +8,9 @@
class HookManagerTest extends AppTestCase
{
- public function setUp(): void
+ public function testHookHelperReturnsInstance(): void
{
- parent::setUp();
-
- $this->setPrivateProperty(HookManager::class, 'instance', null);
- $this->setPrivateProperty(HookManager::class, 'store', []);
- }
-
- public function testGetInstanceReturnsSameObject(): void
- {
- $instance1 = HookManager::getInstance();
- $instance2 = HookManager::getInstance();
-
- $this->assertInstanceOf(HookManager::class, $instance1);
- $this->assertSame($instance1, $instance2);
+ $this->assertInstanceOf(HookManager::class, hook());
}
public function testOnAndFireOutputsCorrectly(): void
@@ -102,7 +90,7 @@ public function testGetRegisteredReturnsHookStore(): void
hook()->on('SAVE', function (): void {
});
- $store = HookManager::getRegistered();
+ $store = hook()->getRegistered();
$this->assertArrayHasKey('SAVE', $store);
$this->assertCount(1, $store['SAVE']);
diff --git a/tests/Unit/Http/Helpers/HttpHelperTest.php b/tests/Unit/Http/Helpers/HttpHelperTest.php
index c19f44db0..8cac6966c 100644
--- a/tests/Unit/Http/Helpers/HttpHelperTest.php
+++ b/tests/Unit/Http/Helpers/HttpHelperTest.php
@@ -22,16 +22,25 @@ public function setUp(): void
{
parent::setUp();
- $this->request = new Request();
+ $this->request = request();
+ $this->response = response();
+ }
- Response::init();
+ public function tearDown(): void
+ {
+ request()->flush();
+ }
- $this->response = new Response();
+ public function testRequestHelperReturnsDiInstance(): void
+ {
+ $this->assertInstanceOf(Request::class, request());
+ $this->assertSame(request(), request());
}
- public function tearDown(): void
+ public function testResponseHelperReturnsDiInstance(): void
{
- Request::flush();
+ $this->assertInstanceOf(Response::class, response());
+ $this->assertSame(response(), response());
}
public function testBaseUrlWithoutModulePrefix(): void
@@ -67,14 +76,9 @@ public function testBaseUrlWithModulePrefix(): void
$this->request->create('GET', 'https://testdomain.com/signin');
- // Register request in DI for route finding (only if not already registered)
- if (!Di::isRegistered(Request::class)) {
- Di::set(Request::class, $this->request);
- }
-
$matchedRoute = $router->find($this->request);
- Request::setMatchedRoute($matchedRoute);
+ request()->setMatchedRoute($matchedRoute);
$baseUrl = base_url(true);
diff --git a/tests/Unit/Http/RequestTest.php b/tests/Unit/Http/RequestTest.php
index f48e73846..35caf7c70 100644
--- a/tests/Unit/Http/RequestTest.php
+++ b/tests/Unit/Http/RequestTest.php
@@ -2,9 +2,7 @@
namespace Quantum\Tests\Unit\Http;
-use Quantum\Http\Request\HttpRequest;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Http\Request;
class RequestTest extends AppTestCase
{
@@ -16,12 +14,12 @@ public function setUp(): void
public function tearDown(): void
{
- HttpRequest::flush();
+ request()->flush();
}
public function testSetGetMethod(): void
{
- $request = new Request();
+ $request = request();
$request->create('GET', '/');
@@ -34,7 +32,7 @@ public function testSetGetMethod(): void
public function testIsMethod(): void
{
- $request = new Request();
+ $request = request();
$request->create('GET', '/');
@@ -53,7 +51,7 @@ public function testIsMethod(): void
public function testGetCsrfToken(): void
{
- $request = new Request();
+ $request = request();
$this->assertNull($request->getCsrfToken());
diff --git a/tests/Unit/Http/ResponseTest.php b/tests/Unit/Http/ResponseTest.php
index b4f5aed74..251f2eeae 100644
--- a/tests/Unit/Http/ResponseTest.php
+++ b/tests/Unit/Http/ResponseTest.php
@@ -4,7 +4,6 @@
use Quantum\Http\Enums\ContentType;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Http\Response;
use Throwable;
class ResponseTest extends AppTestCase
@@ -12,18 +11,16 @@ class ResponseTest extends AppTestCase
public function setUp(): void
{
parent::setUp();
-
- Response::init();
}
public function tearDown(): void
{
- Response::flush();
+ response()->flush();
}
public function testResponseContentType(): void
{
- $response = new Response();
+ $response = response();
$this->assertEquals(ContentType::HTML, $response->getContentType());
@@ -34,7 +31,7 @@ public function testResponseContentType(): void
public function testResponseRedirect(): void
{
- $response = new Response();
+ $response = response();
$this->assertFalse($response->hasHeader('Location'));
diff --git a/tests/Unit/Http/Traits/Request/HttpRawInputTest.php b/tests/Unit/Http/Traits/Request/HttpRawInputTest.php
index 62194452e..0b0adc9fd 100644
--- a/tests/Unit/Http/Traits/Request/HttpRawInputTest.php
+++ b/tests/Unit/Http/Traits/Request/HttpRawInputTest.php
@@ -4,8 +4,6 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Storage\UploadedFile;
-use Quantum\Environment\Server;
-use Quantum\Http\Request;
class HttpRawInputTest extends AppTestCase
{
@@ -21,9 +19,10 @@ public function tearDown(): void
public function testParseReturnsEmptyWhenNoBoundary(): void
{
- Server::getInstance()->set('CONTENT_TYPE', null);
+ server()->set('CONTENT_TYPE', null);
- $result = Request::parse('irrelevant-body');
+ $request = request();
+ $result = $request->parse('irrelevant-body');
$this->assertEquals(['params' => [], 'files' => []], $result);
}
@@ -37,9 +36,10 @@ public function testParseWithParameterBlock(): void
. "JohnDoe\r\n"
. "--$boundary--\r\n";
- Server::getInstance()->set('CONTENT_TYPE', "multipart/form-data; boundary=$boundary");
+ server()->set('CONTENT_TYPE', "multipart/form-data; boundary=$boundary");
- $result = Request::parse($rawInput);
+ $request = request();
+ $result = $request->parse($rawInput);
$this->assertArrayHasKey('params', $result);
@@ -57,9 +57,10 @@ public function testParseWithStreamBlock(): void
. "stream-data\r\n"
. "--$boundary--\r\n";
- Server::getInstance()->set('CONTENT_TYPE', "multipart/form-data; boundary=$boundary");
+ server()->set('CONTENT_TYPE', "multipart/form-data; boundary=$boundary");
- $result = Request::parse($rawInput);
+ $request = request();
+ $result = $request->parse($rawInput);
$this->assertArrayHasKey('params', $result);
@@ -80,9 +81,10 @@ public function testParseWithFileBlock(): void
. "$fileContent\r\n"
. "--$boundary--\r\n";
- Server::getInstance()->set('CONTENT_TYPE', "multipart/form-data; boundary=$boundary");
+ server()->set('CONTENT_TYPE', "multipart/form-data; boundary=$boundary");
- $result = Request::parse($rawInput);
+ $request = request();
+ $result = $request->parse($rawInput);
$this->assertArrayHasKey('files', $result);
diff --git a/tests/Unit/Http/Traits/Request/HttpRequestBodyTest.php b/tests/Unit/Http/Traits/Request/HttpRequestBodyTest.php
index cc3c809a0..daf9eaa27 100644
--- a/tests/Unit/Http/Traits/Request/HttpRequestBodyTest.php
+++ b/tests/Unit/Http/Traits/Request/HttpRequestBodyTest.php
@@ -3,7 +3,6 @@
namespace Quantum\Tests\Unit\Http\Traits\Request;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Http\Request;
class HttpRequestBodyTest extends AppTestCase
{
@@ -14,12 +13,12 @@ public function setUp(): void
public function tearDown(): void
{
- Request::flush();
+ request()->flush();
}
public function testRequestSetHasGetDelete(): void
{
- $request = new Request();
+ $request = request();
$this->assertFalse($request->has('name'));
@@ -52,7 +51,7 @@ public function testRequestSetHasGetDelete(): void
public function testRequestAll(): void
{
- $request = new Request();
+ $request = request();
$this->assertEmpty($request->all());
diff --git a/tests/Unit/Http/Traits/Request/HttpRequestFileTest.php b/tests/Unit/Http/Traits/Request/HttpRequestFileTest.php
index 3ffcdde0c..79d306c26 100644
--- a/tests/Unit/Http/Traits/Request/HttpRequestFileTest.php
+++ b/tests/Unit/Http/Traits/Request/HttpRequestFileTest.php
@@ -5,7 +5,6 @@
use Quantum\Storage\Exceptions\FileUploadException;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Storage\UploadedFile;
-use Quantum\Http\Request;
class HttpRequestFileTest extends AppTestCase
{
@@ -16,12 +15,12 @@ public function setUp(): void
public function tearDown(): void
{
- Request::flush();
+ request()->flush();
}
public function testHasGetFile(): void
{
- $request = new Request();
+ $request = request();
$file = [
'image' => [
@@ -62,7 +61,7 @@ public function testHasGetFile(): void
public function testGetMultipleFiles(): void
{
- $request = new Request();
+ $request = request();
$this->assertFalse($request->hasFile('image'));
diff --git a/tests/Unit/Http/Traits/Request/HttpRequestHeaderTest.php b/tests/Unit/Http/Traits/Request/HttpRequestHeaderTest.php
index 674577961..3553cb770 100644
--- a/tests/Unit/Http/Traits/Request/HttpRequestHeaderTest.php
+++ b/tests/Unit/Http/Traits/Request/HttpRequestHeaderTest.php
@@ -3,28 +3,24 @@
namespace Quantum\Tests\Unit\Http\Traits\Request;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Environment\Server;
-use Quantum\Http\Request;
class HttpRequestHeaderTest extends AppTestCase
{
public function setUp(): void
{
parent::setUp();
-
- Request::init(Server::getInstance());
}
public function tearDown(): void
{
- Request::flush();
+ request()->flush();
- Server::getInstance()->flush();
+ server()->flush();
}
public function testRequestHeaderSetHasGetDelete(): void
{
- $request = new Request();
+ $request = request();
$this->assertFalse($request->hasHeader('name'));
@@ -41,7 +37,7 @@ public function testRequestHeaderSetHasGetDelete(): void
public function testRequestHeaderAll(): void
{
- $request = new Request();
+ $request = request();
$this->assertEmpty($request->allHeaders());
@@ -54,7 +50,7 @@ public function testRequestHeaderAll(): void
public function testGetAuthorizationBearer(): void
{
- $request = new Request();
+ $request = request();
$bearerToken = md5('random');
@@ -69,9 +65,9 @@ public function testGetAuthorizationBearer(): void
public function testGetBasicAuthCredentialsFromServer(): void
{
- $request = new Request();
+ $request = request();
- $server = Server::getInstance();
+ $server = server();
$credentials = [
'username' => 'testGlobalUsername',
@@ -95,7 +91,7 @@ public function testGetBasicAuthCredentialsFromServer(): void
public function testGetBasicAuthCredentialsFromHeader(): void
{
- $request = new Request();
+ $request = request();
$username = 'testHeaderName';
@@ -118,7 +114,7 @@ public function testGetBasicAuthCredentialsFromHeader(): void
public function testIsAjaxReturnsTrueWhenHeaderIsSet(): void
{
- $request = new Request();
+ $request = request();
$this->assertFalse($request->isAjax());
@@ -129,23 +125,23 @@ public function testIsAjaxReturnsTrueWhenHeaderIsSet(): void
public function testIsAjaxReturnsTrueFromServerWhenHeaderIsMissing(): void
{
- $request = new Request();
+ $request = request();
$this->assertFalse($request->isAjax());
- Server::getInstance()->set('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest');
+ server()->set('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest');
$this->assertTrue($request->isAjax());
}
public function testGetReferrer(): void
{
- $this->assertNull(Request::getReferrer());
+ $this->assertNull(request()->getReferrer());
$referrer = 'https://example.com/page';
- Server::getInstance()->set('HTTP_REFERER', $referrer);
+ server()->set('HTTP_REFERER', $referrer);
- $this->assertEquals($referrer, Request::getReferrer());
+ $this->assertEquals($referrer, request()->getReferrer());
}
}
diff --git a/tests/Unit/Http/Traits/Request/HttpRequestInternalTest.php b/tests/Unit/Http/Traits/Request/HttpRequestInternalTest.php
index 973a1c6f4..a44ba07ae 100644
--- a/tests/Unit/Http/Traits/Request/HttpRequestInternalTest.php
+++ b/tests/Unit/Http/Traits/Request/HttpRequestInternalTest.php
@@ -2,11 +2,8 @@
namespace Quantum\Tests\Unit\Http\Traits\Request;
-use Quantum\Http\Request\HttpRequest;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Storage\UploadedFile;
-use Quantum\Environment\Server;
-use Quantum\Http\Request;
class HttpRequestInternalTest extends AppTestCase
{
@@ -17,9 +14,10 @@ public function setUp(): void
public function testCreateRequestSetsBasicServerParams(): void
{
- Request::create('GET', 'https://example.com/test/path?foo=bar');
+ $request = request();
+ $request->create('GET', 'https://example.com/test/path?foo=bar');
- $server = Server::getInstance();
+ $server = server();
$this->assertEquals('GET', $server->get('REQUEST_METHOD'));
$this->assertEquals('test/path', $server->get('REQUEST_URI'));
@@ -43,32 +41,36 @@ public function testContentTypeIsMultipartWhenFilesProvided(): void
],
];
- Request::create('POST', 'http://localhost/upload', [], [], $files);
+ $request = request();
+ $request->create('POST', 'http://localhost/upload', [], [], $files);
- $this->assertEquals('multipart/form-data', Server::getInstance()->get('CONTENT_TYPE'));
+ $this->assertEquals('multipart/form-data', server()->get('CONTENT_TYPE'));
}
public function testContentTypeIsFormUrlencodedWhenDataProvided(): void
{
- Request::create('POST', 'http://localhost/form', ['key' => 'value']);
+ $request = request();
+ $request->create('POST', 'http://localhost/form', ['key' => 'value']);
- $this->assertEquals('application/x-www-form-urlencoded', Server::getInstance()->get('CONTENT_TYPE'));
+ $this->assertEquals('application/x-www-form-urlencoded', server()->get('CONTENT_TYPE'));
}
public function testContentTypeIsTextHtmlWhenNoDataOrFiles(): void
{
- Request::create('GET', 'http://localhost');
+ $request = request();
+ $request->create('GET', 'http://localhost');
- $this->assertEquals('text/html', Server::getInstance()->get('CONTENT_TYPE'));
+ $this->assertEquals('text/html', server()->get('CONTENT_TYPE'));
}
public function testRequestParamsAreSet(): void
{
$data = ['foo' => 'bar'];
- Request::create('POST', 'http://localhost/submit', $data);
+ $request = request();
+ $request->create('POST', 'http://localhost/submit', $data);
- $this->assertEquals('bar', HttpRequest::get('foo'));
+ $this->assertEquals('bar', $request->get('foo'));
}
public function testUploadedFilesAreSet(): void
@@ -83,7 +85,7 @@ public function testUploadedFilesAreSet(): void
],
];
- $request = new Request();
+ $request = request();
$request->create('POST', 'http://localhost/upload', [], [], $files);
diff --git a/tests/Unit/Http/Traits/Request/HttpRequestQueryTest.php b/tests/Unit/Http/Traits/Request/HttpRequestQueryTest.php
index d1ae96cf7..e31e97d8d 100644
--- a/tests/Unit/Http/Traits/Request/HttpRequestQueryTest.php
+++ b/tests/Unit/Http/Traits/Request/HttpRequestQueryTest.php
@@ -3,7 +3,6 @@
namespace Quantum\Tests\Unit\Http\Traits\Request;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Http\Request;
class HttpRequestQueryTest extends AppTestCase
{
@@ -14,12 +13,12 @@ public function setUp(): void
public function tearDown(): void
{
- Request::flush();
+ request()->flush();
}
public function testSetGetQuery(): void
{
- $request = new Request();
+ $request = request();
$request->create('GET', 'http://test.com:8080/user?firstname=john&lastname=doe');
@@ -36,7 +35,7 @@ public function testSetGetQuery(): void
public function testSetGetQueryParam(): void
{
- $request = new Request();
+ $request = request();
$request->setQueryParam('name', 'John');
diff --git a/tests/Unit/Http/Traits/Request/HttpRequestRouteTest.php b/tests/Unit/Http/Traits/Request/HttpRequestRouteTest.php
index 1c8efcf10..7d1c86618 100644
--- a/tests/Unit/Http/Traits/Request/HttpRequestRouteTest.php
+++ b/tests/Unit/Http/Traits/Request/HttpRequestRouteTest.php
@@ -4,29 +4,21 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Router\MatchedRoute;
-use Quantum\Http\Request;
use Quantum\Router\Route;
-use Quantum\Di\Di;
class HttpRequestRouteTest extends AppTestCase
{
public function tearDown(): void
{
- Request::setMatchedRoute(null);
- Request::flush();
-
- if (Di::isRegistered(Request::class)) {
- $diRequest = Di::get(Request::class);
- $diRequest->setMatchedRoute(null);
- $diRequest->flush();
- }
+ request()->setMatchedRoute(null);
+ request()->flush();
parent::tearDown();
}
public function testGetMatchedRouteReturnsNullByDefault(): void
{
- $this->assertNull(Request::getMatchedRoute());
+ $this->assertNull(request()->getMatchedRoute());
}
public function testSetAndGetMatchedRoute(): void
@@ -40,9 +32,9 @@ public function testSetAndGetMatchedRoute(): void
$matched = new MatchedRoute($route, ['id' => 1]);
- Request::setMatchedRoute($matched);
+ request()->setMatchedRoute($matched);
- $this->assertSame($matched, Request::getMatchedRoute());
+ $this->assertSame($matched, request()->getMatchedRoute());
}
public function testSetMatchedRouteToNullResetsState(): void
@@ -56,10 +48,10 @@ public function testSetMatchedRouteToNullResetsState(): void
$matched = new MatchedRoute($route, []);
- Request::setMatchedRoute($matched);
- $this->assertNotNull(Request::getMatchedRoute());
+ request()->setMatchedRoute($matched);
+ $this->assertNotNull(request()->getMatchedRoute());
- Request::setMatchedRoute(null);
- $this->assertNull(Request::getMatchedRoute());
+ request()->setMatchedRoute(null);
+ $this->assertNull(request()->getMatchedRoute());
}
}
diff --git a/tests/Unit/Http/Traits/Request/HttpRequestUrlTest.php b/tests/Unit/Http/Traits/Request/HttpRequestUrlTest.php
index 026ed0e7c..6e0fb70e9 100644
--- a/tests/Unit/Http/Traits/Request/HttpRequestUrlTest.php
+++ b/tests/Unit/Http/Traits/Request/HttpRequestUrlTest.php
@@ -3,7 +3,6 @@
namespace Quantum\Tests\Unit\Http\Traits\Request;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Http\Request;
class HttpRequestUrlTest extends AppTestCase
{
@@ -14,12 +13,12 @@ public function setUp(): void
public function tearDown(): void
{
- Request::flush();
+ request()->flush();
}
public function testSetGetProtocol(): void
{
- $request = new Request();
+ $request = request();
$request->create('GET', 'https://test.com');
@@ -32,7 +31,7 @@ public function testSetGetProtocol(): void
public function testSetGetHost(): void
{
- $request = new Request();
+ $request = request();
$request->create('GET', 'https://test.com/dashboard');
@@ -45,7 +44,7 @@ public function testSetGetHost(): void
public function testSetGetPort(): void
{
- $request = new Request();
+ $request = request();
$request->create('GET', 'https://test.com:8080/dashboard');
@@ -58,7 +57,7 @@ public function testSetGetPort(): void
public function testSetGetUri(): void
{
- $request = new Request();
+ $request = request();
$request->create('GET', 'http://test.com/post/12');
@@ -71,7 +70,7 @@ public function testSetGetUri(): void
public function testGetSegments(): void
{
- $request = new Request();
+ $request = request();
$request->create('GET', 'post/12/notes');
diff --git a/tests/Unit/Http/Traits/Response/HttpResponseBodyTest.php b/tests/Unit/Http/Traits/Response/HttpResponseBodyTest.php
index e32beb606..829c503a1 100644
--- a/tests/Unit/Http/Traits/Response/HttpResponseBodyTest.php
+++ b/tests/Unit/Http/Traits/Response/HttpResponseBodyTest.php
@@ -3,7 +3,6 @@
namespace Quantum\Tests\Unit\Http\Traits\Response;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Http\Response;
class HttpResponseBodyTest extends AppTestCase
{
@@ -14,12 +13,12 @@ public function setUp(): void
public function tearDown(): void
{
- Response::flush();
+ response()->flush();
}
public function testResponseSetHasGetAllDelete(): void
{
- $response = new Response();
+ $response = response();
$this->assertEmpty($response->all());
@@ -44,7 +43,7 @@ public function testResponseSetHasGetAllDelete(): void
public function testResponseJsonContent(): void
{
- $response = new Response();
+ $response = response();
$response->set('firstname', 'John');
@@ -70,7 +69,7 @@ public function testResponseJsonContent(): void
public function testResponseJsonP(): void
{
- $response = new Response();
+ $response = response();
$response->set('firstname', 'John');
@@ -83,7 +82,7 @@ public function testResponseJsonP(): void
public function testResponseXmlContent(): void
{
- $response = new Response();
+ $response = response();
$response->set('firstname', 'John');
@@ -129,7 +128,7 @@ public function testResponseXmlContent(): void
public function testResponseXmlWithNestedArray(): void
{
- $response = new Response();
+ $response = response();
$response->xml([
'article' => [
@@ -151,7 +150,7 @@ public function testResponseXmlWithNestedArray(): void
public function testResponseXmlWithArguments(): void
{
- $response = new Response();
+ $response = response();
$response->xml([
'article@{"type":"post"}' => [
@@ -173,7 +172,7 @@ public function testResponseXmlWithArguments(): void
public function testResponseXmlWithCustomRoot(): void
{
- $response = new Response();
+ $response = response();
$response->xml([
'article@{"type":"post"}' => [
@@ -195,7 +194,7 @@ public function testResponseXmlWithCustomRoot(): void
public function testResponseHtmlContent(): void
{
- $response = new Response();
+ $response = response();
$response->html('John Doe
');
diff --git a/tests/Unit/Http/Traits/Response/HttpResponseHeaderTest.php b/tests/Unit/Http/Traits/Response/HttpResponseHeaderTest.php
index 71f61a8a9..bb1cb0236 100644
--- a/tests/Unit/Http/Traits/Response/HttpResponseHeaderTest.php
+++ b/tests/Unit/Http/Traits/Response/HttpResponseHeaderTest.php
@@ -3,7 +3,6 @@
namespace Quantum\Tests\Unit\Http\Traits\Response;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Http\Response;
class HttpResponseHeaderTest extends AppTestCase
{
@@ -15,7 +14,7 @@ public function setUp(): void
public function testResponseHeaderSetHasGetAllDelete(): void
{
- $response = new Response();
+ $response = response();
$this->assertEmpty($response->allHeaders());
diff --git a/tests/Unit/Http/Traits/Response/HttpResponseStatusTest.php b/tests/Unit/Http/Traits/Response/HttpResponseStatusTest.php
index 1f35302cf..a92919dba 100644
--- a/tests/Unit/Http/Traits/Response/HttpResponseStatusTest.php
+++ b/tests/Unit/Http/Traits/Response/HttpResponseStatusTest.php
@@ -3,7 +3,6 @@
namespace Quantum\Tests\Unit\Http\Traits\Response;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Http\Response;
class HttpResponseStatusTest extends AppTestCase
{
@@ -14,7 +13,7 @@ public function setUp(): void
public function testResponseStatus(): void
{
- $response = new Response();
+ $response = response();
$this->assertEquals(200, $response->getStatusCode());
@@ -27,7 +26,7 @@ public function testResponseStatus(): void
public function testHttpStatusGetText(): void
{
- $response = new Response();
+ $response = response();
$this->assertEquals('OK', $response->getText(200));
diff --git a/tests/Unit/Lang/Factories/LangFactoryTest.php b/tests/Unit/Lang/Factories/LangFactoryTest.php
index 02910fee7..e003de595 100644
--- a/tests/Unit/Lang/Factories/LangFactoryTest.php
+++ b/tests/Unit/Lang/Factories/LangFactoryTest.php
@@ -6,6 +6,7 @@
use Quantum\Lang\Factories\LangFactory;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Lang\Lang;
+use Quantum\Di\Di;
class LangFactoryTest extends AppTestCase
{
@@ -13,7 +14,7 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(LangFactory::class, 'instance', null);
+ $this->resetLangFactory();
}
public function testLangFactoryGetLangInstance(): void
@@ -87,7 +88,7 @@ public function testLangFactoryFallsBackToDefaultIfProvidedLangIsNotSupported():
$this->assertEquals('en', $lang->getLang());
- $this->setPrivateProperty(LangFactory::class, 'instance', null);
+ $this->resetLangFactory();
$this->testRequest('http://127.0.0.1/api/rest?lang=fr');
@@ -95,7 +96,7 @@ public function testLangFactoryFallsBackToDefaultIfProvidedLangIsNotSupported():
$this->assertEquals('en', $lang->getLang());
- $this->setPrivateProperty(LangFactory::class, 'instance', null);
+ $this->resetLangFactory();
$this->testRequest('http://127.0.0.1/api/rest', 'GET', [], ['Accept-Language' => 'fr, en;q=0.8, fr;q=0.6']);
@@ -121,4 +122,14 @@ public function testLangFactoryThrowsErrorIfNoDefaultLangFound(): void
LangFactory::get();
}
+
+ private function resetLangFactory(): void
+ {
+ if (!Di::isRegistered(LangFactory::class)) {
+ Di::register(LangFactory::class);
+ }
+
+ $factory = Di::get(LangFactory::class);
+ $this->setPrivateProperty($factory, 'instance', null);
+ }
}
diff --git a/tests/Unit/Lang/Helpers/LangHelperFunctionsTest.php b/tests/Unit/Lang/Helpers/LangHelperFunctionsTest.php
index 46981484f..7ad31bd2c 100644
--- a/tests/Unit/Lang/Helpers/LangHelperFunctionsTest.php
+++ b/tests/Unit/Lang/Helpers/LangHelperFunctionsTest.php
@@ -14,8 +14,6 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(LangFactory::class, 'instance', null);
-
$this->lang = LangFactory::get();
$this->lang->load();
diff --git a/tests/Unit/Lang/LangTest.php b/tests/Unit/Lang/LangTest.php
index 35141829e..18ddf628c 100644
--- a/tests/Unit/Lang/LangTest.php
+++ b/tests/Unit/Lang/LangTest.php
@@ -6,9 +6,7 @@
use Quantum\Router\MatchedRoute;
use Quantum\Lang\Translator;
use Quantum\Router\Route;
-use Quantum\Http\Request;
use Quantum\Lang\Lang;
-use Quantum\Di\Di;
class LangTest extends AppTestCase
{
@@ -30,13 +28,9 @@ public function setUp(): void
$route->module('Test');
$matchedRoute = new MatchedRoute($route, []);
- Request::setMatchedRoute($matchedRoute);
- if (!Di::isRegistered(Request::class)) {
- $request = new Request();
- $request->create('POST', '/api-signin');
- Di::set(Request::class, $request);
- }
+ request()->create('POST', '/api-signin');
+ request()->setMatchedRoute($matchedRoute);
}
public function testLangGetSet(): void
diff --git a/tests/Unit/Logger/Adapters/MessageAdapterTest.php b/tests/Unit/Logger/Adapters/MessageAdapterTest.php
index 844d8897a..65cb2c50f 100644
--- a/tests/Unit/Logger/Adapters/MessageAdapterTest.php
+++ b/tests/Unit/Logger/Adapters/MessageAdapterTest.php
@@ -3,9 +3,9 @@
namespace Quantum\Tests\Unit\Logger\Adapters;
use Quantum\Logger\Adapters\MessageAdapter;
-use Quantum\Debugger\DebuggerStore;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Debugger\Debugger;
+use Quantum\Di\Di;
class MessageAdapterTest extends AppTestCase
{
@@ -16,9 +16,11 @@ public function setUp(): void
{
parent::setUp();
- $store = new DebuggerStore();
+ if (!Di::isRegistered(Debugger::class)) {
+ Di::register(Debugger::class);
+ }
- $this->debugger = Debugger::getInstance($store);
+ $this->debugger = Di::get(Debugger::class);
$this->debugger->initStore();
diff --git a/tests/Unit/Logger/Factories/LoggerFactoryTest.php b/tests/Unit/Logger/Factories/LoggerFactoryTest.php
index edb77acd6..077d26160 100644
--- a/tests/Unit/Logger/Factories/LoggerFactoryTest.php
+++ b/tests/Unit/Logger/Factories/LoggerFactoryTest.php
@@ -11,6 +11,7 @@
use Quantum\Logger\Enums\LoggerType;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Logger\Logger;
+use Quantum\Di\Di;
class LoggerFactoryTest extends AppTestCase
{
@@ -20,7 +21,7 @@ public function setUp(): void
config()->set('app.debug', false);
- $this->setPrivateProperty(LoggerFactory::class, 'instances', []);
+ $this->resetLoggerFactory();
}
public function testLoggerFactoryInstance(): void
@@ -93,4 +94,14 @@ public function testLoggerFactoryReturnsSameInstance(): void
$this->assertSame($logger1, $logger2);
}
+
+ private function resetLoggerFactory(): void
+ {
+ if (!Di::isRegistered(LoggerFactory::class)) {
+ Di::register(LoggerFactory::class);
+ }
+
+ $factory = Di::get(LoggerFactory::class);
+ $this->setPrivateProperty($factory, 'instances', []);
+ }
}
diff --git a/tests/Unit/Logger/Helpers/LoggerHelperFunctionsTest.php b/tests/Unit/Logger/Helpers/LoggerHelperFunctionsTest.php
index e7d6713e9..9bfa50107 100644
--- a/tests/Unit/Logger/Helpers/LoggerHelperFunctionsTest.php
+++ b/tests/Unit/Logger/Helpers/LoggerHelperFunctionsTest.php
@@ -7,10 +7,10 @@
use Quantum\Logger\Adapters\SingleAdapter;
use Quantum\Logger\Adapters\DailyAdapter;
use Quantum\Logger\Enums\LoggerType;
-use Quantum\Debugger\DebuggerStore;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Debugger\Debugger;
use Quantum\Logger\Logger;
+use Quantum\Di\Di;
class LoggerHelperFunctionsTest extends AppTestCase
{
@@ -22,9 +22,11 @@ public function setUp(): void
config()->set('app.debug', true);
- $store = new DebuggerStore();
+ if (!Di::isRegistered(Debugger::class)) {
+ Di::register(Debugger::class);
+ }
- $this->debugger = Debugger::getInstance($store);
+ $this->debugger = Di::get(Debugger::class);
$this->debugger->resetStore();
}
@@ -32,6 +34,7 @@ public function setUp(): void
public function tearDown(): void
{
$this->debugger->resetStore();
+ parent::tearDown();
}
public function testLoggerHelperGetDefaultLoggerAdapter(): void
diff --git a/tests/Unit/Logger/LoggerTest.php b/tests/Unit/Logger/LoggerTest.php
index 422546a5c..49b18ca28 100644
--- a/tests/Unit/Logger/LoggerTest.php
+++ b/tests/Unit/Logger/LoggerTest.php
@@ -4,10 +4,10 @@
use Quantum\Logger\Contracts\ReportableInterface;
use Quantum\Logger\Adapters\MessageAdapter;
-use Quantum\Debugger\DebuggerStore;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Debugger\Debugger;
use Quantum\Logger\Logger;
+use Quantum\Di\Di;
class LoggerTest extends AppTestCase
{
@@ -19,9 +19,11 @@ public function setUp(): void
{
parent::setUp();
- $store = new DebuggerStore();
+ if (!Di::isRegistered(Debugger::class)) {
+ Di::register(Debugger::class);
+ }
- $this->debugger = Debugger::getInstance($store);
+ $this->debugger = Di::get(Debugger::class);
$this->debugger->initStore();
diff --git a/tests/Unit/Mailer/Factories/MailerFactoryTest.php b/tests/Unit/Mailer/Factories/MailerFactoryTest.php
index 9ad9111e0..48fd8ccf4 100644
--- a/tests/Unit/Mailer/Factories/MailerFactoryTest.php
+++ b/tests/Unit/Mailer/Factories/MailerFactoryTest.php
@@ -14,6 +14,7 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Mailer\Mailer;
use Quantum\Loader\Setup;
+use Quantum\Di\Di;
class MailerFactoryTest extends AppTestCase
{
@@ -21,7 +22,7 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(MailerFactory::class, 'instances', []);
+ $this->resetMailerFactory();
if (!config()->has('mailer')) {
config()->import(new Setup('config', 'mailer'));
@@ -100,4 +101,14 @@ public function testMailerFactoryReturnsSameInstance(): void
$this->assertSame($mailer1, $mailer2);
}
+
+ private function resetMailerFactory(): void
+ {
+ if (!Di::isRegistered(MailerFactory::class)) {
+ Di::register(MailerFactory::class);
+ }
+
+ $factory = Di::get(MailerFactory::class);
+ $this->setPrivateProperty($factory, 'instances', []);
+ }
}
diff --git a/tests/Unit/Mailer/MailTrapTest.php b/tests/Unit/Mailer/MailTrapTest.php
index c62d10861..988181d88 100644
--- a/tests/Unit/Mailer/MailTrapTest.php
+++ b/tests/Unit/Mailer/MailTrapTest.php
@@ -2,8 +2,9 @@
namespace Quantum\Tests\Unit\Mailer;
-use Quantum\Mailer\MailTrap;
use Quantum\Tests\Unit\AppTestCase;
+use Quantum\Mailer\MailTrap;
+use Quantum\Di\Di;
class MailTrapTest extends AppTestCase
{
@@ -19,7 +20,11 @@ public function setUp(): void
{
parent::setUp();
- $this->mailTrap = MailTrap::getInstance();
+ if (!Di::isRegistered(MailTrap::class)) {
+ Di::register(MailTrap::class);
+ }
+
+ $this->mailTrap = Di::get(MailTrap::class);
$this->filename = '2YILSA4zZk61tDdYEfGMw7lNznlhAQakjwNGr0QCq44';
@@ -62,6 +67,8 @@ public function setUp(): void
public function tearDown(): void
{
$this->fs->remove($this->path . DS . $this->filename . '.eml');
+
+ parent::tearDown();
}
public function testMailTrapInstance(): void
diff --git a/tests/Unit/Mailer/MailerTestCase.php b/tests/Unit/Mailer/MailerTestCase.php
index 91ac5b435..c40604e56 100644
--- a/tests/Unit/Mailer/MailerTestCase.php
+++ b/tests/Unit/Mailer/MailerTestCase.php
@@ -10,8 +10,6 @@ abstract class MailerTestCase extends AppTestCase
protected $adapter;
public function tearDown(): void
{
- parent::tearDown();
-
$coreDependencies = [
\Quantum\Loader\Loader::class => \Quantum\Loader\Loader::class,
\Quantum\Http\Request::class => \Quantum\Http\Request::class,
@@ -26,6 +24,6 @@ public function tearDown(): void
$this->fs->remove($emailFile);
}
- Di::reset();
+ parent::tearDown();
}
}
diff --git a/tests/Unit/Model/DbModelTest.php b/tests/Unit/Model/DbModelTest.php
index 83e9d6c45..5421ddf76 100644
--- a/tests/Unit/Model/DbModelTest.php
+++ b/tests/Unit/Model/DbModelTest.php
@@ -2,7 +2,6 @@
namespace Quantum\Tests\Unit\Model;
-use Quantum\Model\Model;
use Quantum\Tests\_root\shared\Models\TestProfileModel;
use Quantum\Database\Adapters\Idiorm\IdiormDbal;
use Quantum\Model\Exceptions\ModelException;
@@ -11,6 +10,7 @@
use Quantum\Model\ModelCollection;
use Quantum\Paginator\Paginator;
use Quantum\Model\DbModel;
+use Quantum\Model\Model;
class DbModelTest extends AppTestCase
{
@@ -32,6 +32,8 @@ public function setUp(): void
public function tearDown(): void
{
IdiormDbal::execute('DROP TABLE profiles');
+
+ parent::tearDown();
}
public function testDbModelInstance(): void
diff --git a/tests/Unit/Model/DbModelTimestampsTest.php b/tests/Unit/Model/DbModelTimestampsTest.php
index e90067db4..b1e388b59 100644
--- a/tests/Unit/Model/DbModelTimestampsTest.php
+++ b/tests/Unit/Model/DbModelTimestampsTest.php
@@ -27,6 +27,8 @@ public function tearDown(): void
{
IdiormDbal::execute('DROP TABLE posts');
IdiormDbal::execute('DROP TABLE posts_custom');
+
+ parent::tearDown();
}
public function testTimestampsAreNotAppliedWhenTraitIsNotUsed(): void
diff --git a/tests/Unit/Model/ModelSoftDeletesIdiOrmTest.php b/tests/Unit/Model/ModelSoftDeletesIdiOrmTest.php
index 0a8df16ef..cb3498fa8 100644
--- a/tests/Unit/Model/ModelSoftDeletesIdiOrmTest.php
+++ b/tests/Unit/Model/ModelSoftDeletesIdiOrmTest.php
@@ -2,13 +2,13 @@
namespace Quantum\Tests\Unit\Model;
-use Quantum\Model\Model;
use Quantum\Tests\_root\shared\Models\TestProductsModel;
use Quantum\Database\Adapters\Idiorm\IdiormDbal;
use Quantum\Model\Factories\ModelFactory;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Model\ModelCollection;
use Quantum\Paginator\Paginator;
+use Quantum\Model\Model;
class ModelSoftDeletesIdiOrmTest extends AppTestCase
{
@@ -30,6 +30,8 @@ public function setUp(): void
public function tearDown(): void
{
IdiormDbal::execute('DROP TABLE products ');
+
+ parent::tearDown();
}
public function testDeleteSetsDeletedAt(): void
diff --git a/tests/Unit/Model/ModelSoftDeletesSleekTest.php b/tests/Unit/Model/ModelSoftDeletesSleekTest.php
index 913ffbaeb..df9cb667c 100644
--- a/tests/Unit/Model/ModelSoftDeletesSleekTest.php
+++ b/tests/Unit/Model/ModelSoftDeletesSleekTest.php
@@ -2,15 +2,14 @@
namespace Quantum\Tests\Unit\Model;
-use Quantum\Model\Model;
use Quantum\Tests\_root\shared\Models\TestProductsModel;
use Quantum\Database\Adapters\Sleekdb\SleekDbal;
use Quantum\Model\Factories\ModelFactory;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Model\ModelCollection;
use Quantum\Paginator\Paginator;
-use Quantum\Database\Database;
use Quantum\Loader\Setup;
+use Quantum\Model\Model;
class ModelSoftDeletesSleekTest extends AppTestCase
{
@@ -20,8 +19,6 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(Database::class, 'instance', null);
-
if (!config()->has('database')) {
config()->import(new Setup('config', 'database'));
}
@@ -38,6 +35,8 @@ public function setUp(): void
public function tearDown(): void
{
ModelFactory::get(TestProductsModel::class)->truncate();
+
+ parent::tearDown();
}
public function testSleekDeleteSetsDeletedAt(): void
diff --git a/tests/Unit/Module/ModuleLoaderTest.php b/tests/Unit/Module/ModuleLoaderTest.php
index ab5161f50..d8e7abf05 100644
--- a/tests/Unit/Module/ModuleLoaderTest.php
+++ b/tests/Unit/Module/ModuleLoaderTest.php
@@ -4,6 +4,7 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Module\ModuleLoader;
+use Quantum\Di\Di;
use Closure;
class ModuleLoaderTest extends AppTestCase
@@ -13,9 +14,11 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(ModuleLoader::class, 'instance', null);
+ if (!Di::isRegistered(ModuleLoader::class)) {
+ Di::register(ModuleLoader::class);
+ }
- $this->moduleLoader = ModuleLoader::getInstance();
+ $this->moduleLoader = Di::get(ModuleLoader::class);
}
public function tearDown(): void
diff --git a/tests/Unit/Module/ModuleManagerTest.php b/tests/Unit/Module/ModuleManagerTest.php
index e01e9e64d..cf1785554 100644
--- a/tests/Unit/Module/ModuleManagerTest.php
+++ b/tests/Unit/Module/ModuleManagerTest.php
@@ -4,7 +4,6 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Module\ModuleManager;
-use Quantum\Http\Response;
use Quantum\App\App;
use Exception;
use Mockery;
@@ -38,7 +37,7 @@ public function testCreateModule(): void
$mainController = new \Quantum\Tests\_root\modules\Api\Controllers\MainController();
- $response = new Response();
+ $response = response();
$mainController->index($response);
@@ -86,8 +85,6 @@ public function testInvalidTemplate(): void
public function tearDown(): void
{
- parent::tearDown();
-
$moduleConfigs = $this->fs->require($this->modulesConfigPath);
$apiModulePath = App::getBaseDir() . DS . 'modules' . DS . 'Api';
@@ -104,5 +101,7 @@ public function tearDown(): void
if ($this->fs->isDirectory($apiModulePath)) {
deleteDirectoryWithFiles($apiModulePath);
}
+
+ parent::tearDown();
}
}
diff --git a/tests/Unit/Paginator/PaginatorTestCase.php b/tests/Unit/Paginator/PaginatorTestCase.php
index 8303c835c..381ea027e 100644
--- a/tests/Unit/Paginator/PaginatorTestCase.php
+++ b/tests/Unit/Paginator/PaginatorTestCase.php
@@ -4,7 +4,6 @@
use Quantum\Database\Adapters\Idiorm\IdiormDbal;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Database\Database;
class PaginatorTestCase extends AppTestCase
{
@@ -12,8 +11,6 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(Database::class, 'instance', null);
-
IdiormDbal::connect(['driver' => 'sqlite', 'database' => ':memory:']);
$this->_createPostTableWithData();
@@ -22,6 +19,8 @@ public function setUp(): void
public function tearDown(): void
{
IdiormDbal::execute('DROP TABLE IF EXISTS posts');
+
+ parent::tearDown();
}
private function _createPostTableWithData(): void
diff --git a/tests/Unit/Renderer/Adapters/HtmlAdapterTest.php b/tests/Unit/Renderer/Adapters/HtmlAdapterTest.php
index f76bb90b4..8ee38be68 100644
--- a/tests/Unit/Renderer/Adapters/HtmlAdapterTest.php
+++ b/tests/Unit/Renderer/Adapters/HtmlAdapterTest.php
@@ -6,8 +6,6 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Router\MatchedRoute;
use Quantum\Router\Route;
-use Quantum\Http\Request;
-use Quantum\Di\Di;
class HtmlAdapterTest extends AppTestCase
{
@@ -25,9 +23,8 @@ public function setUp(): void
$matchedRoute = new MatchedRoute($route, []);
- $request = Di::get(Request::class);
- $request->create('GET', '/test');
- Request::setMatchedRoute($matchedRoute);
+ request()->create('GET', '/test');
+ request()->setMatchedRoute($matchedRoute);
}
public function testHtmlAdapterRenderView(): void
diff --git a/tests/Unit/Renderer/Adapters/TwigAdapterTest.php b/tests/Unit/Renderer/Adapters/TwigAdapterTest.php
index 7d7e401d4..0cb032e0e 100644
--- a/tests/Unit/Renderer/Adapters/TwigAdapterTest.php
+++ b/tests/Unit/Renderer/Adapters/TwigAdapterTest.php
@@ -6,8 +6,6 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Router\MatchedRoute;
use Quantum\Router\Route;
-use Quantum\Http\Request;
-use Quantum\Di\Di;
class TwigAdapterTest extends AppTestCase
{
@@ -24,11 +22,9 @@ public function setUp(): void
$route->module('Test');
$matchedRoute = new MatchedRoute($route, []);
- Request::setMatchedRoute($matchedRoute);
- $request = Di::get(Request::class);
- $request->create('GET', '/test');
- Request::setMatchedRoute($matchedRoute);
+ request()->create('GET', '/test');
+ request()->setMatchedRoute($matchedRoute);
}
public function testHtmlAdapterRenderView(): void
diff --git a/tests/Unit/Renderer/Factories/RendererFactoryTest.php b/tests/Unit/Renderer/Factories/RendererFactoryTest.php
index e3b2858e3..3e8251184 100644
--- a/tests/Unit/Renderer/Factories/RendererFactoryTest.php
+++ b/tests/Unit/Renderer/Factories/RendererFactoryTest.php
@@ -10,6 +10,7 @@
use Quantum\Renderer\Enums\RendererType;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Renderer\Renderer;
+use Quantum\Di\Di;
class RendererFactoryTest extends AppTestCase
{
@@ -17,7 +18,7 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(RendererFactory::class, 'instances', []);
+ $this->resetRendererFactory();
}
public function testRendererFactoryInstance(): void
@@ -70,4 +71,14 @@ public function testRendererFactoryReturnsSameInstance(): void
$this->assertSame($renderer1, $renderer2);
}
+
+ private function resetRendererFactory(): void
+ {
+ if (!Di::isRegistered(RendererFactory::class)) {
+ Di::register(RendererFactory::class);
+ }
+
+ $factory = Di::get(RendererFactory::class);
+ $this->setPrivateProperty($factory, 'instances', []);
+ }
}
diff --git a/tests/Unit/Renderer/RendererTest.php b/tests/Unit/Renderer/RendererTest.php
index 7237a98ca..f0dee9364 100644
--- a/tests/Unit/Renderer/RendererTest.php
+++ b/tests/Unit/Renderer/RendererTest.php
@@ -10,8 +10,6 @@
use Quantum\Router\MatchedRoute;
use Quantum\Renderer\Renderer;
use Quantum\Router\Route;
-use Quantum\Http\Request;
-use Quantum\Di\Di;
class RendererTest extends AppTestCase
{
@@ -28,13 +26,9 @@ public function setUp(): void
$route->module('Test');
$matchedRoute = new MatchedRoute($route, []);
- Request::setMatchedRoute($matchedRoute);
- if (!Di::isRegistered(Request::class)) {
- $request = new Request();
- $request->create('GET', '/test');
- Di::set(Request::class, $request);
- }
+ request()->create('GET', '/test');
+ request()->setMatchedRoute($matchedRoute);
}
public function testRendererGetHtmlAdapter(): void
diff --git a/tests/Unit/ResourceCache/ViewCacheTest.php b/tests/Unit/ResourceCache/ViewCacheTest.php
index ab9760dd8..2c1c5c7a2 100644
--- a/tests/Unit/ResourceCache/ViewCacheTest.php
+++ b/tests/Unit/ResourceCache/ViewCacheTest.php
@@ -5,7 +5,7 @@
use Quantum\ResourceCache\Exceptions\ResourceCacheException;
use Quantum\ResourceCache\ViewCache;
use Quantum\Tests\Unit\AppTestCase;
-use Quantum\Http\Response;
+use Quantum\Di\Di;
class ViewCacheDouble extends ViewCache
{
@@ -43,7 +43,11 @@ public function setUp(): void
{
parent::setUp();
- $this->viewCache = ViewCache::getInstance();
+ if (!Di::isRegistered(ViewCache::class)) {
+ Di::register(ViewCache::class);
+ }
+
+ $this->viewCache = Di::get(ViewCache::class);
$this->viewCache->setup();
}
@@ -51,6 +55,7 @@ public function tearDown(): void
{
$this->viewCache->delete($this->route);
$this->viewCache->enableCaching(false);
+ parent::tearDown();
}
public function testServeCachedView(): void
@@ -59,7 +64,7 @@ public function testServeCachedView(): void
$this->viewCache->set($this->route, $this->content);
- $response = new Response();
+ $response = response();
$result = $this->viewCache->serveCachedView($this->route, $response);
diff --git a/tests/Unit/Router/Helpers/RouteHelpersTest.php b/tests/Unit/Router/Helpers/RouteHelpersTest.php
index 47ca61264..b99d0a278 100644
--- a/tests/Unit/Router/Helpers/RouteHelpersTest.php
+++ b/tests/Unit/Router/Helpers/RouteHelpersTest.php
@@ -6,21 +6,14 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Router\MatchedRoute;
use Quantum\Router\Route;
-use Quantum\Http\Request;
use Quantum\Di\Di;
class RouteHelpersTest extends AppTestCase
{
public function tearDown(): void
{
- Request::setMatchedRoute(null);
- Request::flush();
-
- if (Di::isRegistered(Request::class)) {
- $diRequest = Di::get(Request::class);
- $diRequest->setMatchedRoute(null);
- $diRequest->flush();
- }
+ request()->setMatchedRoute(null);
+ request()->flush();
parent::tearDown();
}
@@ -64,7 +57,7 @@ public function testHelpersReturnValuesForMatchedControllerRoute(): void
['uuid' => 'abc-123']
);
- Request::setMatchedRoute($matched);
+ request()->setMatchedRoute($matched);
$this->assertSame(['Auth', 'Editor'], current_middlewares());
$this->assertSame('Web', current_module());
@@ -94,7 +87,7 @@ public function testRouteCallbackReturnsClosureForClosureRoute(): void
$matched = new MatchedRoute($route, []);
- Request::setMatchedRoute($matched);
+ request()->setMatchedRoute($matched);
$this->assertSame($closure, route_callback());
$this->assertNull(current_controller());
@@ -146,8 +139,7 @@ public function testRouteGroupExistsDetectsGroupInModule(): void
public function testRouteMethodAndUri(): void
{
- $request = new Request();
- $request->create('POST', 'http://example.com/api/test');
+ request()->create('POST', 'http://example.com/api/test');
$this->assertSame('POST', route_method());
diff --git a/tests/Unit/Router/RouteFinderTest.php b/tests/Unit/Router/RouteFinderTest.php
index f81d474da..43794303a 100644
--- a/tests/Unit/Router/RouteFinderTest.php
+++ b/tests/Unit/Router/RouteFinderTest.php
@@ -6,7 +6,6 @@
use Quantum\Router\RouteCollection;
use Quantum\Router\MatchedRoute;
use Quantum\Router\RouteFinder;
-use Quantum\Http\Request;
use Quantum\Router\Route;
class RouteFinderTest extends AppTestCase
@@ -27,7 +26,7 @@ public function testRouteFinderFindReturnsMatchedRouteForStaticMatch(): void
$route = new Route(['GET'], 'users', 'Ctrl', 'act');
$this->collection->add($route);
- $req = new Request();
+ $req = request();
$req->create('GET', '/users');
$result = $this->finder->find($req);
@@ -42,7 +41,7 @@ public function testRouteFinderFindReturnsNullWhenNoMatch(): void
$route = new Route(['GET'], 'users', 'Ctrl', 'act');
$this->collection->add($route);
- $req = new Request();
+ $req = request();
$req->create('GET', '/posts');
$this->assertNull($this->finder->find($req));
@@ -53,7 +52,7 @@ public function testRouteFinderFindSkipsWrongHttpMethod(): void
$route = new Route(['POST'], 'users', 'Ctrl', 'act');
$this->collection->add($route);
- $req = new Request();
+ $req = request();
$req->create('GET', '/users');
$this->assertNull($this->finder->find($req));
@@ -67,7 +66,7 @@ public function testRouteFinderFindReturnsFirstMatchingRouteOnly(): void
$this->collection->add($r1);
$this->collection->add($r2);
- $req = new Request();
+ $req = request();
$req->create('GET', '/users');
$result = $this->finder->find($req);
@@ -80,7 +79,7 @@ public function testRouteFinderFindPassesExtractedParams(): void
$route = new Route(['GET'], 'users/[id=:num]', 'Ctrl', 'act');
$this->collection->add($route);
- $req = new Request();
+ $req = request();
$req->create('GET', '/users/42');
$result = $this->finder->find($req);
@@ -96,7 +95,7 @@ public function testRouteFinderFindWithMultipleRoutesOnlyOneMatches(): void
$r2 = new Route(['GET'], 'users', 'C', 'a');
$this->collection->add($r2);
- $req = new Request();
+ $req = request();
$req->create('GET', '/users');
$result = $this->finder->find($req);
diff --git a/tests/Unit/Session/Factories/SessionFactoryTest.php b/tests/Unit/Session/Factories/SessionFactoryTest.php
index 79a1bb017..93cbc6ca7 100644
--- a/tests/Unit/Session/Factories/SessionFactoryTest.php
+++ b/tests/Unit/Session/Factories/SessionFactoryTest.php
@@ -13,6 +13,7 @@
use Quantum\Tests\Unit\AppTestCase;
use Quantum\Session\Session;
use Quantum\Loader\Setup;
+use Quantum\Di\Di;
class SessionFactoryTest extends AppTestCase
{
@@ -22,7 +23,7 @@ public function setUp(): void
{
parent::setUp();
- $this->setPrivateProperty(SessionFactory::class, 'instances', []);
+ $this->resetSessionFactory();
IdiormDbal::connect(['driver' => 'sqlite', 'database' => ':memory:']);
@@ -119,4 +120,14 @@ public function testSessionFactoryReturnsSameInstance(): void
$this->assertSame($session1, $session2);
}
+
+ private function resetSessionFactory(): void
+ {
+ if (!Di::isRegistered(SessionFactory::class)) {
+ Di::register(SessionFactory::class);
+ }
+
+ $factory = Di::get(SessionFactory::class);
+ $this->setPrivateProperty($factory, 'instances', []);
+ }
}
diff --git a/tests/Unit/Tracer/ErrorHandlerTest.php b/tests/Unit/Tracer/ErrorHandlerTest.php
new file mode 100644
index 000000000..deafb5055
--- /dev/null
+++ b/tests/Unit/Tracer/ErrorHandlerTest.php
@@ -0,0 +1,95 @@
+errorHandler = new ErrorHandler();
+ }
+
+ public function tearDown(): void
+ {
+ restore_error_handler();
+ restore_exception_handler();
+ parent::tearDown();
+ }
+
+ public function testSetupRegistersErrorHandler(): void
+ {
+ $logger = Mockery::mock(Logger::class);
+
+ $this->errorHandler->setup($logger);
+
+ $currentHandler = set_error_handler(function () {
+ });
+ restore_error_handler();
+
+ $this->assertNotNull($currentHandler);
+ $this->assertIsArray($currentHandler);
+ $this->assertInstanceOf(ErrorHandler::class, $currentHandler[0]);
+ $this->assertEquals('handleError', $currentHandler[1]);
+ }
+
+ public function testSetupRegistersExceptionHandler(): void
+ {
+ $logger = Mockery::mock(Logger::class);
+
+ $this->errorHandler->setup($logger);
+
+ $currentHandler = set_exception_handler(function () {
+ });
+ restore_exception_handler();
+
+ $this->assertNotNull($currentHandler);
+ $this->assertIsArray($currentHandler);
+ $this->assertInstanceOf(ErrorHandler::class, $currentHandler[0]);
+ $this->assertEquals('handleException', $currentHandler[1]);
+ }
+
+ public function testHandleErrorThrowsErrorException(): void
+ {
+ $oldLevel = error_reporting(E_ALL);
+
+ try {
+ $this->errorHandler->handleError(E_WARNING, 'Test error', __FILE__, __LINE__);
+ $this->fail('Expected ErrorException was not thrown');
+ } catch (ErrorException $e) {
+ $this->assertEquals('Test error', $e->getMessage());
+ $this->assertEquals(E_WARNING, $e->getSeverity());
+ } finally {
+ error_reporting($oldLevel);
+ }
+ }
+
+ public function testHandleErrorReturnsFalseForSuppressedErrors(): void
+ {
+ $oldLevel = error_reporting(0);
+
+ try {
+ $result = $this->errorHandler->handleError(E_NOTICE, 'Suppressed', __FILE__, __LINE__);
+ $this->assertFalse($result);
+ } finally {
+ error_reporting($oldLevel);
+ }
+ }
+
+ public function testErrorTypesConstant(): void
+ {
+ $this->assertEquals('error', ErrorHandler::ERROR_TYPES[E_ERROR]);
+ $this->assertEquals('warning', ErrorHandler::ERROR_TYPES[E_WARNING]);
+ $this->assertEquals('notice', ErrorHandler::ERROR_TYPES[E_NOTICE]);
+ $this->assertEquals('error', ErrorHandler::ERROR_TYPES[E_PARSE]);
+ }
+}
diff --git a/tests/Unit/Validation/Traits/FileRuleTest.php b/tests/Unit/Validation/Traits/FileRuleTest.php
index 4a3d3ccc5..ed86d879a 100644
--- a/tests/Unit/Validation/Traits/FileRuleTest.php
+++ b/tests/Unit/Validation/Traits/FileRuleTest.php
@@ -16,7 +16,7 @@ public function setUp(): void
{
parent::setUp();
- $this->request = new Request();
+ $this->request = request();
$this->validator = new Validator();
diff --git a/tests/Unit/View/Factories/ViewFactoryTest.php b/tests/Unit/View/Factories/ViewFactoryTest.php
index e87edf72b..ab4c7bf0d 100644
--- a/tests/Unit/View/Factories/ViewFactoryTest.php
+++ b/tests/Unit/View/Factories/ViewFactoryTest.php
@@ -5,6 +5,7 @@
use Quantum\View\Factories\ViewFactory;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\View\QtView;
+use Quantum\Di\Di;
class ViewFactoryTest extends AppTestCase
{
@@ -14,21 +15,44 @@ public function setUp(): void
{
parent::setUp();
- $this->viewFactory = new ViewFactory();
+ $this->resetViewFactory();
+
+ if (!Di::isRegistered(ViewFactory::class)) {
+ Di::register(ViewFactory::class);
+ }
+
+ $this->viewFactory = Di::get(ViewFactory::class);
}
public function testGetInstance(): void
{
- $this->assertInstanceOf(QtView::class, $this->viewFactory->get());
+ $this->assertInstanceOf(QtView::class, ViewFactory::get());
+ }
+
+ public function testResolveReturnsSameInstance(): void
+ {
+ $view1 = $this->viewFactory->resolve();
+ $view2 = $this->viewFactory->resolve();
+
+ $this->assertSame($view1, $view2);
}
public function testProxyCalls(): void
{
- $view = $this->viewFactory->get();
+ $view = ViewFactory::get();
$view->setParam('key', 'Value');
$this->assertEquals('Value', $view->getParam('key'));
}
+ private function resetViewFactory(): void
+ {
+ if (!Di::isRegistered(ViewFactory::class)) {
+ Di::register(ViewFactory::class);
+ }
+
+ $factory = Di::get(ViewFactory::class);
+ $this->setPrivateProperty($factory, 'instance', null);
+ }
}
diff --git a/tests/Unit/View/Helpers/ViewHelperTest.php b/tests/Unit/View/Helpers/ViewHelperTest.php
index ca3e0790d..a03277d3d 100644
--- a/tests/Unit/View/Helpers/ViewHelperTest.php
+++ b/tests/Unit/View/Helpers/ViewHelperTest.php
@@ -5,8 +5,6 @@
use Quantum\View\Factories\ViewFactory;
use Quantum\Router\MatchedRoute;
use Quantum\Router\Route;
-use Quantum\Http\Request;
-use Quantum\Di\Di;
use Quantum\Tests\Unit\AppTestCase;
use Quantum\View\QtView;
@@ -27,11 +25,9 @@ public function setUp(): void
$route->module('Test');
$matchedRoute = new MatchedRoute($route, []);
- Request::setMatchedRoute($matchedRoute);
- $request = Di::get(Request::class);
- $request->create('POST', '/test');
- Request::setMatchedRoute($matchedRoute);
+ request()->create('POST', '/test');
+ request()->setMatchedRoute($matchedRoute);
$this->view = ViewFactory::get();
}
diff --git a/tests/Unit/View/QtViewTest.php b/tests/Unit/View/QtViewTest.php
index d1d181f5b..a2047dcde 100644
--- a/tests/Unit/View/QtViewTest.php
+++ b/tests/Unit/View/QtViewTest.php
@@ -9,7 +9,6 @@
use Quantum\View\QtView;
use Quantum\View\RawParam;
use Quantum\Router\Route;
-use Quantum\Http\Request;
use Quantum\Di\Di;
class QtViewTest extends AppTestCase
@@ -29,11 +28,9 @@ public function setUp(): void
$route->module('Test');
$matchedRoute = new MatchedRoute($route, []);
- Request::setMatchedRoute($matchedRoute);
- $request = Di::get(Request::class);
- $request->create('GET', '/test');
- Request::setMatchedRoute($matchedRoute);
+ request()->create('GET', '/test');
+ request()->setMatchedRoute($matchedRoute);
$this->view = ViewFactory::get();
}
@@ -171,7 +168,8 @@ public function testRenderPartial(): void
public function testRenderViewWithTwig(): void
{
- $this->setPrivateProperty(ViewFactory::class, 'instance', null);
+ $factory = Di::get(ViewFactory::class);
+ $this->setPrivateProperty($factory, 'instance', null);
config()->set('view.default', 'twig');
config()->set('view.twig', ['autoescape' => false]);
diff --git a/tests/_root/.env.testing b/tests/_root/.env.testing
new file mode 100644
index 000000000..cdb4d2e02
--- /dev/null
+++ b/tests/_root/.env.testing
@@ -0,0 +1,2 @@
+APP_KEY=XYZ1234567890ABCDEFG123456789HIGKLMNOPQRSTUVWXYZ0123456789abcdefgh
+DEBUG=TRUE
\ No newline at end of file
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 8f8fefceb..ccada9cec 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -14,8 +14,10 @@
require_once __DIR__ . DS . 'Helpers' . DS . 'functions.php';
-createEnvFile();
+$envFileCreated = createEnvFile();
-register_shutdown_function(function (): void {
- removeEnvFile();
-});
+if ($envFileCreated) {
+ register_shutdown_function(function (): void {
+ removeEnvFile();
+ });
+}