PluginProbe
Depicter — Popup & Slider Builder / 1.2.0
Depicter — Popup & Slider Builder v1.2.0
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / vendor / htmlburger / wpemerge / src / Kernels / HttpKernel.php

HttpKernel.php in Depicter — Popup & Slider Builder 1.2.0, at vendor/htmlburger/wpemerge/src/Kernels/HttpKernel.php

485 lines 10.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package WPEmerge
4 * @author Atanas Angelov <hi@atanas.dev>
5 * @copyright 2017-2019 Atanas Angelov
6 * @license https://www.gnu.org/licenses/gpl-2.0.html GPL-2.0
7 * @link https://wpemerge.com/
8 */
9
10 namespace WPEmerge\Kernels;
11
12 use Exception;
13 use Pimple\Container;
14 use Psr\Http\Message\ResponseInterface;
15 use WP_Query;
16 use WPEmerge\Application\GenericFactory;
17 use WPEmerge\Exceptions\ConfigurationException;
18 use WPEmerge\Exceptions\ErrorHandlerInterface;
19 use WPEmerge\Helpers\Handler;
20 use WPEmerge\Helpers\HandlerFactory;
21 use WPEmerge\Middleware\ExecutesMiddlewareTrait;
22 use WPEmerge\Middleware\HasMiddlewareDefinitionsTrait;
23 use WPEmerge\Middleware\ReadsHandlerMiddlewareTrait;
24 use WPEmerge\Requests\RequestInterface;
25 use WPEmerge\Responses\ConvertsToResponseTrait;
26 use WPEmerge\Responses\ResponseService;
27 use WPEmerge\Routing\HasQueryFilterInterface;
28 use WPEmerge\Routing\Router;
29 use WPEmerge\Routing\SortsMiddlewareTrait;
30 use WPEmerge\View\ViewService;
31
32 /**
33 * Describes how a request is handled.
34 */
35 class HttpKernel implements HttpKernelInterface {
36 use HasMiddlewareDefinitionsTrait;
37 use SortsMiddlewareTrait;
38 use ConvertsToResponseTrait;
39 use ReadsHandlerMiddlewareTrait;
40 use ExecutesMiddlewareTrait;
41
42 /**
43 * Container.
44 *
45 * @var Container
46 */
47 protected $container = null;
48
49 /**
50 * Injection factory.
51 *
52 * @var GenericFactory
53 */
54 protected $factory = null;
55
56 /**
57 * Handler factory.
58 *
59 * @var HandlerFactory
60 */
61 protected $handler_factory = null;
62
63 /**
64 * Response service.
65 *
66 * @var ResponseService
67 */
68 protected $response_service = null;
69
70 /**
71 * Request.
72 *
73 * @var RequestInterface
74 */
75 protected $request = null;
76
77 /**
78 * Router.
79 *
80 * @var Router
81 */
82 protected $router = null;
83
84 /**
85 * View Service.
86 *
87 * @var ViewService
88 */
89 protected $view_service = null;
90
91 /**
92 * Error handler.
93 *
94 * @var ErrorHandlerInterface
95 */
96 protected $error_handler = null;
97
98 /**
99 * Template WordPress attempted to load.
100 *
101 * @var string
102 */
103 protected $template = '';
104
105 /**
106 * Constructor.
107 *
108 * @codeCoverageIgnore
109 * @param Container $container
110 * @param GenericFactory $factory
111 * @param HandlerFactory $handler_factory
112 * @param ResponseService $response_service
113 * @param RequestInterface $request
114 * @param Router $router
115 * @param ViewService $view_service
116 * @param ErrorHandlerInterface $error_handler
117 */
118 public function __construct(
119 Container $container,
120 GenericFactory $factory,
121 HandlerFactory $handler_factory,
122 ResponseService $response_service,
123 RequestInterface $request,
124 Router $router,
125 ViewService $view_service,
126 ErrorHandlerInterface $error_handler
127 ) {
128 $this->container = $container;
129 $this->factory = $factory;
130 $this->handler_factory = $handler_factory;
131 $this->response_service = $response_service;
132 $this->request = $request;
133 $this->router = $router;
134 $this->view_service = $view_service;
135 $this->error_handler = $error_handler;
136 }
137
138 /**
139 * Get the current response.
140 *
141 * @codeCoverageIgnore
142 * @return ResponseInterface|null
143 */
144 protected function getResponse() {
145 return isset( $this->container[ WPEMERGE_RESPONSE_KEY ] ) ? $this->container[ WPEMERGE_RESPONSE_KEY ] : null;
146 }
147
148 /**
149 * Get a Response Service instance.
150 *
151 * @codeCoverageIgnore
152 * @return ResponseService
153 */
154 protected function getResponseService() {
155 return $this->response_service;
156 }
157
158 /**
159 * Make a middleware class instance.
160 *
161 * @codeCoverageIgnore
162 * @param string $class
163 * @return object
164 */
165 protected function makeMiddleware( $class ) {
166 return $this->factory->make( $class );
167 }
168
169 /**
170 * Execute a handler.
171 *
172 * @param Handler $handler
173 * @param array $arguments
174 * @return ResponseInterface
175 */
176 protected function executeHandler( Handler $handler, $arguments = [] ) {
177 $response = call_user_func_array( [$handler, 'execute'], array_values( $arguments ) );
178 $response = $this->toResponse( $response );
179
180 if ( ! $response instanceof ResponseInterface ) {
181 throw new ConfigurationException(
182 'Response returned by controller is not valid ' .
183 '(expected ' . ResponseInterface::class . '; received ' . gettype( $response ) . ').'
184 );
185 }
186
187 return $response;
188 }
189
190 /**
191 * {@inheritDoc}
192 */
193 public function run( RequestInterface $request, $middleware, $handler, $arguments = [] ) {
194 $this->error_handler->register();
195
196 try {
197 $handler = $handler instanceof Handler ? $handler : $this->handler_factory->make( $handler );
198
199 $middleware = array_merge( $middleware, $this->getHandlerMiddleware( $handler ) );
200 $middleware = $this->expandMiddleware( $middleware );
201 $middleware = $this->uniqueMiddleware( $middleware );
202 $middleware = $this->sortMiddleware( $middleware );
203
204 $response = $this->executeMiddleware( $middleware, $request, function () use ( $handler, $arguments ) {
205 return $this->executeHandler( $handler, $arguments );
206 } );
207 } catch ( Exception $exception ) {
208 $response = $this->error_handler->getResponse( $request, $exception );
209 }
210
211 $this->error_handler->unregister();
212
213 return $response;
214 }
215
216 /**
217 * {@inheritDoc}
218 */
219 public function handle( RequestInterface $request, $arguments = [] ) {
220 $route = $this->router->execute( $request );
221
222 if ( $route === null ) {
223 return null;
224 }
225
226 $route_arguments = $route->getArguments( $request );
227
228 $request = $request
229 ->withAttribute( 'route', $route )
230 ->withAttribute( 'route_arguments', $route_arguments );
231
232 $response = $this->run(
233 $request,
234 $route->getAttribute( 'middleware', [] ),
235 $route->getAttribute( 'handler' ),
236 array_merge(
237 [$request],
238 $arguments,
239 $route_arguments
240 )
241 );
242
243 $this->container[ WPEMERGE_RESPONSE_KEY ] = $response;
244
245 return $response;
246 }
247
248 /**
249 * Respond with the current response.
250 *
251 * @return void
252 */
253 public function respond() {
254 $response = $this->getResponse();
255
256 if ( ! $response instanceof ResponseInterface ) {
257 return;
258 }
259
260 $this->response_service->respond( $response );
261 }
262
263 /**
264 * Output the current view outside of the routing flow.
265 *
266 * @return void
267 */
268 public function compose() {
269 $view = $this->view_service->make( $this->template );
270
271 echo $view->toString();
272 }
273
274 /**
275 * {@inheritDoc}
276 * @codeCoverageIgnore
277 */
278 public function bootstrap() {
279 // Web. Use 3100 so it's high enough and has uncommonly used numbers
280 // before and after. For example, 1000 is too common and it would have 999 before it
281 // which is too common as well.).
282 add_action( 'request', [$this, 'filterRequest'], 3100 );
283 add_action( 'template_include', [$this, 'filterTemplateInclude'], 3100 );
284
285 // Ajax.
286 add_action( 'admin_init', [$this, 'registerAjaxAction'] );
287
288 // Admin.
289 add_action( 'admin_init', [$this, 'registerAdminAction'] );
290 }
291
292 /**
293 * Filter the main query vars.
294 *
295 * @param array $query_vars
296 * @return array
297 */
298 public function filterRequest( $query_vars ) {
299 $routes = $this->router->getRoutes();
300
301 foreach ( $routes as $route ) {
302 if ( ! $route instanceof HasQueryFilterInterface ) {
303 continue;
304 }
305
306 if ( ! $route->isSatisfied( $this->request ) ) {
307 continue;
308 }
309
310 $this->container[ WPEMERGE_APPLICATION_KEY ]
311 ->renderConfigExceptions( function () use ( $route, &$query_vars ) {
312 $query_vars = $route->applyQueryFilter( $this->request, $query_vars );
313 } );
314 break;
315 }
316
317 return $query_vars;
318 }
319
320 /**
321 * Filter the main template file.
322 *
323 * @param string $template
324 * @return string
325 */
326 public function filterTemplateInclude( $template ) {
327 /** @var WP_Query $wp_query */
328 global $wp_query;
329
330 $this->template = $template;
331
332 $response = $this->handle( $this->request, [$template] );
333
334 // A route has matched so we use its response.
335 if ( $response instanceof ResponseInterface ) {
336 if ( $response->getStatusCode() === 404 ) {
337 $wp_query->set_404();
338 }
339
340 add_action( 'wpemerge.kernels.http_kernel.respond', [$this, 'respond'] );
341
342 return WPEMERGE_DIR . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'view.php';
343 }
344
345 // No route has matched, but we still want to compose views.
346 $composers = $this->view_service->getComposersForView( $template );
347
348 if ( ! empty( $composers ) ) {
349 add_action( 'wpemerge.kernels.http_kernel.respond', [$this, 'compose'] );
350
351 return WPEMERGE_DIR . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'view.php';
352 }
353
354 return $template;
355 }
356
357 /**
358 * Register ajax action to hook into current one.
359 *
360 * @return void
361 */
362 public function registerAjaxAction() {
363 if ( ! wp_doing_ajax() ) {
364 return;
365 }
366
367 $action = $this->request->body( 'action', $this->request->query( 'action' ) );
368 $action = sanitize_text_field( $action );
369
370 add_action( "wp_ajax_{$action}", [$this, 'actionAjax'] );
371 add_action( "wp_ajax_nopriv_{$action}", [$this, 'actionAjax'] );
372 }
373
374 /**
375 * Act on ajax action.
376 *
377 * @return void
378 */
379 public function actionAjax() {
380 $response = $this->handle( $this->request, [''] );
381
382 if ( ! $response instanceof ResponseInterface ) {
383 return;
384 }
385
386 $this->response_service->respond( $response );
387
388 wp_die( '', '', ['response' => null] );
389 }
390
391 /**
392 * Get page hook.
393 * Slightly modified version of code from wp-admin/admin.php.
394 *
395 * @return string
396 */
397 protected function getAdminPageHook() {
398 global $pagenow, $typenow, $plugin_page;
399
400 $page_hook = '';
401
402 if ( isset( $plugin_page ) ) {
403 $the_parent = $pagenow;
404
405 if ( ! empty( $typenow ) ) {
406 $the_parent = $pagenow . '?post_type=' . $typenow;
407 }
408
409 $page_hook = get_plugin_page_hook( $plugin_page, $the_parent );
410 }
411
412 return $page_hook;
413 }
414
415 /**
416 * Get admin page hook.
417 * Slightly modified version of code from wp-admin/admin.php.
418 *
419 * @param string $page_hook
420 * @return string
421 */
422 protected function getAdminHook( $page_hook ) {
423 global $pagenow, $plugin_page;
424
425 if ( ! empty( $page_hook ) ) {
426 return $page_hook;
427 }
428
429 if ( isset( $plugin_page ) ) {
430 return $plugin_page;
431 }
432
433 if ( isset( $pagenow ) ) {
434 return $pagenow;
435 }
436
437 return '';
438 }
439
440 /**
441 * Register admin action to hook into current one.
442 *
443 * @return void
444 */
445 public function registerAdminAction() {
446 $page_hook = $this->getAdminPageHook();
447 $hook_suffix = $this->getAdminHook( $page_hook );
448
449 add_action( "load-{$hook_suffix}", [$this, 'actionAdminLoad'] );
450 add_action( $hook_suffix, [$this, 'actionAdmin'] );
451 }
452
453 /**
454 * Act on admin action load.
455 *
456 * @return void
457 */
458 public function actionAdminLoad() {
459 $response = $this->handle( $this->request, [''] );
460
461 if ( ! $response instanceof ResponseInterface ) {
462 return;
463 }
464
465 if ( ! headers_sent() ) {
466 $this->response_service->sendHeaders( $response );
467 }
468 }
469
470 /**
471 * Act on admin action.
472 *
473 * @return void
474 */
475 public function actionAdmin() {
476 $response = $this->getResponse();
477
478 if ( ! $response instanceof ResponseInterface ) {
479 return;
480 }
481
482 $this->response_service->sendBody( $response );
483 }
484 }
485