← All changes
|
vendor/wpfluent/framework/src/WPFluent/Foundation/Application.php
+106
-32
1.0.98
→
2.11.0
View file →
| @@ -1,5 +1,14 @@ | ||
| 1 | 1 | <?php |
| 2 | +/** | |
| 3 | + * @package WPFluent | |
| 4 | + * @author Sheikh Heera <[email protected]> (https://heera.it) | |
| 5 | + * @author Sheikh Heera <[email protected]> | |
| 6 | + * @author Sheikh Heera <[email protected]> | |
| 7 | + * @link https://github.com/wpfluent/framework2x | |
| 8 | + * @license MIT https://opensource.org/licenses/MIT | |
| 9 | + * @license GPL-2.0-or-later https://www.gnu.org/licenses/gpl-2.0.html | |
| 10 | + */ | |
| 2 | 11 | |
| 3 | 12 | namespace FluentCommunity\Framework\Foundation; |
| 4 | 13 | |
| 5 | 14 | use InvalidArgumentException; |
| @@ -8,10 +17,35 @@ | ||
| 8 | 17 | use FluentCommunity\Framework\Http\Client; |
| 9 | 18 | use FluentCommunity\Framework\Foundation\Config; |
| 10 | 19 | use FluentCommunity\Framework\Container\Container; |
| 11 | 20 | use FluentCommunity\Framework\Foundation\ComponentBinder; |
| 12 | -use FluentCommunity\Framework\Foundation\FoundationTrait; | |
| 21 | +use FluentCommunity\Framework\Foundation\Concerns\FoundationTrait; | |
| 13 | 22 | |
| 23 | +/** | |
| 24 | + * Application — service container with magic property access via __get. | |
| 25 | + * | |
| 26 | + * Properties below are bound in {@see ComponentBinder::bindComponents()} and | |
| 27 | + * {@see Application::init()}/{@see Application::setAppLevelNamespace()}. Each | |
| 28 | + * `@property` declaration teaches PHPStan about a runtime container binding so | |
| 29 | + * `$app->view->render(...)` and similar access can be type-checked. | |
| 30 | + * | |
| 31 | + * @property \FluentCommunity\Framework\Foundation\Config $config | |
| 32 | + * @property \FluentCommunity\Framework\View\View $view | |
| 33 | + * @property \FluentCommunity\Framework\Cache\Cache $cache | |
| 34 | + * @property \FluentCommunity\Framework\Http\Router $router | |
| 35 | + * @property \FluentCommunity\Framework\Http\Request\Request $request | |
| 36 | + * @property \FluentCommunity\Framework\Http\Response\Response $response | |
| 37 | + * @property \FluentCommunity\Framework\Validator\Validator $validator | |
| 38 | + * @property \FluentCommunity\Framework\Events\Dispatcher $events | |
| 39 | + * @property \FluentCommunity\Framework\Encryption\Encrypter $encrypter | |
| 40 | + * @property \FluentCommunity\Framework\Encryption\Encrypter $crypt | |
| 41 | + * @property \FluentCommunity\Framework\Database\DatabaseManager $db | |
| 42 | + * @property \FluentCommunity\Framework\Http\URL $url | |
| 43 | + * @property \FluentCommunity\Framework\Support\Mail $mail | |
| 44 | + * @property \FluentCommunity\Framework\Support\Pipeline $pipeline | |
| 45 | + * @property string $__pluginfile__ | |
| 46 | + * @property string $__namespace__ | |
| 47 | + */ | |
| 14 | 48 | class Application extends Container |
| 15 | 49 | { |
| 16 | 50 | use FoundationTrait; |
| 17 | 51 | |
| @@ -54,9 +88,9 @@ | ||
| 54 | 88 | * Default namespace for policy handlers |
| 55 | 89 | * |
| 56 | 90 | * @var string |
| 57 | 91 | */ |
| 58 | - protected $permissionNamespace = null; | |
| 92 | + protected $policyNamespace = null; | |
| 59 | 93 | |
| 60 | 94 | /** |
| 61 | 95 | * Composer JSON |
| 62 | 96 | * |
| @@ -71,8 +105,15 @@ | ||
| 71 | 105 | */ |
| 72 | 106 | protected $onReady = []; |
| 73 | 107 | |
| 74 | 108 | /** |
| 109 | + * Flag to check if components are bound. | |
| 110 | + * | |
| 111 | + * @var boolean | |
| 112 | + */ | |
| 113 | + protected $componentsBound = false; | |
| 114 | + | |
| 115 | + /** | |
| 75 | 116 | * Construct the application instance |
| 76 | 117 | * |
| 77 | 118 | * @param string $file The main plugin file's absolute path |
| 78 | 119 | * @return null |
| @@ -99,8 +140,14 @@ | ||
| 99 | 140 | $this->basePath = plugin_dir_path($this->file); |
| 100 | 141 | $this->baseUrl = plugin_dir_url($this->file); |
| 101 | 142 | } |
| 102 | 143 | |
| 144 | + /** | |
| 145 | + * Load the environment bariables from .env file. | |
| 146 | + * | |
| 147 | + * @param string $path | |
| 148 | + * @return void | |
| 149 | + */ | |
| 103 | 150 | protected function loadEnvironmentVars($path = null) |
| 104 | 151 | { |
| 105 | 152 | $path = $path ?: $this->basePath . '.env'; |
| 106 | 153 | |
| @@ -157,11 +204,11 @@ | ||
| 157 | 204 | { |
| 158 | 205 | $this->bindAppInstance(); |
| 159 | 206 | $this->bindPathsAndUrls(); |
| 160 | 207 | $this->loadConfigIfExists(); |
| 208 | + $this->registerMiddleware(); | |
| 161 | 209 | $this->registerTextdomain(); |
| 162 | 210 | $this->bindCoreComponents(); |
| 163 | - $this->registerAsyncActions(); | |
| 164 | 211 | $this->requireCommonFiles($this); |
| 165 | 212 | $this->addRestApiInitAction($this); |
| 166 | 213 | } |
| 167 | 214 | |
| @@ -224,21 +271,52 @@ | ||
| 224 | 271 | * @return null |
| 225 | 272 | */ |
| 226 | 273 | protected function loadConfigIfExists() |
| 227 | 274 | { |
| 228 | - $data = []; | |
| 275 | + $files = []; | |
| 229 | 276 | |
| 230 | 277 | if (is_dir($this['path.config'])) { |
| 231 | 278 | foreach (glob($this['path.config'] . '*.php') as $file) { |
| 232 | - $data[basename($file, '.php')] = require($file); | |
| 279 | + // middleware.php lives under app/Http/ now; it ships closures | |
| 280 | + // that don't belong in Config storage. | |
| 281 | + if (basename($file) === 'middleware.php') { | |
| 282 | + continue; | |
| 283 | + } | |
| 284 | + $files[basename($file, '.php')] = $file; | |
| 233 | 285 | } |
| 234 | 286 | } |
| 235 | 287 | |
| 236 | - $this->instance('config', new Config($data)); | |
| 288 | + $this->instance('config', new Config([], $files)); | |
| 237 | 289 | } |
| 238 | 290 | |
| 239 | 291 | /** |
| 292 | + * Register the HTTP middleware stack as a lazy container binding. | |
| 293 | + * | |
| 294 | + * Resolves from `app/Http/middleware.php` (canonical). Falls back to | |
| 295 | + * `config/middleware.php` so un-migrated plugins keep working. | |
| 296 | + * | |
| 297 | + * @return void | |
| 298 | + */ | |
| 299 | + protected function registerMiddleware() | |
| 300 | + { | |
| 301 | + $this->singleton('http.middleware', function ($app) { | |
| 302 | + $new = $app['path.http'] . 'middleware.php'; | |
| 303 | + if (is_file($new)) { | |
| 304 | + return require $new; | |
| 305 | + } | |
| 306 | + | |
| 307 | + $legacy = $app['path.config'] . 'middleware.php'; | |
| 308 | + if (is_file($legacy)) { | |
| 309 | + return require $legacy; | |
| 310 | + } | |
| 311 | + | |
| 312 | + return []; | |
| 313 | + }); | |
| 314 | + } | |
| 315 | + | |
| 316 | + /** | |
| 240 | 317 | * Resolve the given type from the container. |
| 318 | + * This method is required for unit testing. | |
| 241 | 319 | * |
| 242 | 320 | * @param string $abstract |
| 243 | 321 | * @param array $parameters |
| 244 | 322 | * @return mixed |
| @@ -290,9 +368,12 @@ | ||
| 290 | 368 | * @return null |
| 291 | 369 | */ |
| 292 | 370 | protected function bindCoreComponents() |
| 293 | 371 | { |
| 294 | - (new ComponentBinder($this))->bindComponents(); | |
| 372 | + if (!$this->componentsBound) { | |
| 373 | + $this->componentsBound = true; | |
| 374 | + (new ComponentBinder($this))->bindComponents(); | |
| 375 | + } | |
| 295 | 376 | } |
| 296 | 377 | |
| 297 | 378 | /** |
| 298 | 379 | * Load (include) the files where hooks are registered. |
| @@ -308,11 +389,11 @@ | ||
| 308 | 389 | ); |
| 309 | 390 | |
| 310 | 391 | require_once $this->basePath . 'app/Hooks/actions.php'; |
| 311 | 392 | require_once $this->basePath . 'app/Hooks/filters.php'; |
| 312 | - | |
| 313 | - if (file_exists($includes = $this->basePath . 'app/Hooks/includes.php')) { | |
| 314 | - require_once $includes; | |
| 393 | + | |
| 394 | + if (file_exists($f = $this->basePath . 'app/Hooks/includes.php')) { | |
| 395 | + require_once $f; | |
| 315 | 396 | } |
| 316 | 397 | } |
| 317 | 398 | |
| 318 | 399 | /** |
| @@ -318,11 +399,11 @@ | ||
| 318 | 399 | /** |
| 319 | 400 | * Handler for rest_pre_serve_request filter. |
| 320 | 401 | * |
| 321 | 402 | * @param bool $served (default: false) |
| 322 | - * @param \WP_Rest_Response $result | |
| 323 | - * @param \WP_Rest_Request $request | |
| 324 | - * @param \WP_Rest_Server $server | |
| 403 | + * @param \WP_REST_Response $result | |
| 404 | + * @param \WP_REST_Request $request | |
| 405 | + * @param \WP_REST_Server $server | |
| 325 | 406 | * @return bool (false to intercept, otherwise true) |
| 326 | 407 | */ |
| 327 | 408 | public function preServeRequest($served, $result, $request, $server) |
| 328 | 409 | { |
| @@ -333,8 +414,9 @@ | ||
| 333 | 414 | if ($this->isRequestOfPlugin($route, $slug)) { |
| 334 | 415 | if ($this->isRequestForEndpoints($route)) { |
| 335 | 416 | status_header(200); |
| 336 | 417 | $result->set_status(200); |
| 418 | + // @phpstan-ignore-next-line | |
| 337 | 419 | $result->set_data($this->endpoints); |
| 338 | 420 | } else { |
| 339 | 421 | $result->set_data( |
| 340 | 422 | $this->customizeNotFoundResponse( |
| @@ -400,10 +482,10 @@ | ||
| 400 | 482 | |
| 401 | 483 | /** |
| 402 | 484 | * Prepare a custom not found response. |
| 403 | 485 | * |
| 404 | - * @param \WP_Rest_Response $result | |
| 405 | - * @param \WP_Rest_Request $request | |
| 486 | + * @param \WP_REST_Response $result | |
| 487 | + * @param \WP_REST_Request $request | |
| 406 | 488 | * |
| 407 | 489 | * @return array |
| 408 | 490 | */ |
| 409 | 491 | public function customizeNotFoundResponse($result, $request) |
| @@ -460,12 +542,13 @@ | ||
| 460 | 542 | * Register rest routes. |
| 461 | 543 | * |
| 462 | 544 | * @param \FluentCommunity\Framework\Http\Router $router |
| 463 | 545 | * |
| 464 | - * @return null | |
| 546 | + * @return void | |
| 465 | 547 | */ |
| 466 | 548 | protected function registerRestRoutes($router) |
| 467 | 549 | { |
| 550 | + // @phpstan-ignore-next-line | |
| 468 | 551 | $router->registerRoutes( |
| 469 | 552 | $this->requireRouteFile($router) |
| 470 | 553 | ); |
| 471 | 554 | } |
| @@ -481,37 +564,28 @@ | ||
| 481 | 564 | require_once $this['path.http'] . 'Routes/routes.php'; |
| 482 | 565 | } |
| 483 | 566 | |
| 484 | 567 | /** |
| 485 | - * Register plugin booted callbacks. | |
| 568 | + * Register plugin ready (booted) callbacks. | |
| 486 | 569 | * |
| 487 | 570 | * @param callable $callback |
| 488 | 571 | * @return void |
| 489 | 572 | */ |
| 490 | - protected function ready(callable $callback) | |
| 573 | + public function ready(callable $callback) | |
| 491 | 574 | { |
| 492 | 575 | $this->onReady[] = $callback; |
| 493 | 576 | } |
| 494 | 577 | |
| 495 | 578 | /** |
| 496 | - * Register Async Actions. | |
| 497 | - * | |
| 498 | - * @return void | |
| 499 | - */ | |
| 500 | - protected function registerAsyncActions() | |
| 501 | - { | |
| 502 | - Client::registerAsyncRequestHandler(); | |
| 503 | - } | |
| 504 | - | |
| 505 | - /** | |
| 506 | 579 | * Execute plugin booted callbacks. |
| 507 | 580 | * |
| 508 | - * @param callable $callback | |
| 509 | 581 | * @return void |
| 510 | 582 | */ |
| 511 | 583 | protected function callPluginReadyCallbacks() |
| 512 | 584 | { |
| 513 | - while ($callback = array_shift($this->onReady)) { | |
| 514 | - $callback($this); | |
| 515 | - } | |
| 585 | + $this->addAction('init', function() { | |
| 586 | + while ($callback = array_pop($this->onReady)) { | |
| 587 | + $callback($this); | |
| 588 | + } | |
| 589 | + }); | |
| 516 | 590 | } |
| 517 | 591 | } |