Failed Conditions
Branch refactor/kernels (50d60a)
by Atanas
01:41
created

HttpKernel::getAdminPageHook()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 0
dl 0
loc 15
rs 9.9666
c 0
b 0
f 0
ccs 0
cts 0
cp 0
crap 12
1
<?php
2
/**
3
 * @package   WPEmerge
4
 * @author    Atanas Angelov <[email protected]>
5
 * @copyright 2018 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 WPEmerge\Application\Application;
14
use WPEmerge\Exceptions\ErrorHandlerInterface;
15
use WPEmerge\Facades\Response;
16
use WPEmerge\Requests\RequestInterface;
17
use WPEmerge\Routing\HasQueryFilterInterface;
18
use WPEmerge\Routing\Router;
19
20
/**
21
 * Describes how a request is handled.
22
 */
23
class HttpKernel implements HttpKernelInterface {
24
	/**
25
	 * Application.
26
	 *
27
	 * @var Application
28
	 */
29
	protected $app = null;
30
31
	/**
32
	 * Request.
33
	 *
34
	 * @var RequestInterface
35
	 */
36
	protected $request = null;
37
38
	/**
39
	 * Router.
40
	 *
41
	 * @var Router
42
	 */
43
	protected $router = null;
44
45
	/**
46
	 * Error handler.
47
	 *
48
	 * @var ErrorHandlerInterface
49
	 */
50
	protected $error_handler = null;
51
52
	/**
53
	 * Middleware available to the application.
54
	 *
55
	 * @var array<string, string>
56
	 */
57
	protected $middleware = [];
58
59
	/**
60
	 * Middleware groups.
61
	 *
62
	 * @var array<string, array<string>>
63
	 */
64
	protected $middleware_groups = [
65
		'global' => [
66
			\WPEmerge\Flash\FlashMiddleware::class,
67
			\WPEmerge\Input\OldInputMiddleware::class,
68
		],
69
70
		'web' => [
71
			'global',
72
		],
73
74
		'ajax' => [
75
			'global',
76
		],
77
	];
78
79
	/**
80
	 * Middleware sorted in order of execution.
81
	 *
82
	 * @var array<string>
83
	 */
84
	protected $middleware_priority = [];
85
86
	/**
87
	 * Constructor.
88
	 *
89
	 * @codeCoverageIgnore
90
	 * @param RequestInterface      $request
91
	 * @param Router                $router
92
	 * @param ErrorHandlerInterface $error_handler
93
	 */
94
	public function __construct( Application $app, RequestInterface $request, Router $router, ErrorHandlerInterface $error_handler ) {
95
		$this->app = $app;
96
		$this->request = $request;
97
		$this->router = $router;
98
		$this->error_handler = $error_handler;
99
	}
100
101
	/**
102
	 * {@inheritDoc}
103
	 * @codeCoverageIgnore
104
	 */
105
	public function bootstrap() {
106
		$this->router->setMiddleware( $this->middleware );
107
		$this->router->setMiddlewareGroups( $this->middleware_groups );
108
		$this->router->setMiddlewarePriority( $this->middleware_priority );
109
110
		// Web.
111
		add_action( 'request', [$this, 'filterRequest'], 1000 );
112
		add_action( 'template_include', [$this, 'filterTemplateInclude'], 1000 );
113
114 2
		// Ajax.
115 2
		add_action( 'admin_init', [$this, 'registerAjaxAction'] );
116
117
		// Admin.
118 2
		add_action( 'admin_init', [$this, 'registerAdminAction'] );
119 1
	}
120 1
121
	/**
122
	 * {@inheritDoc}
123 1
	 */
124
	public function handle( RequestInterface $request, $arguments = [] ) {
125 1
		$this->error_handler->register();
126
127
		try {
128
			$response = $this->router->execute( $request, $arguments );
129
		} catch ( Exception $exception ) {
130
			$response = $this->error_handler->getResponse( $request, $exception );
131
		}
132
133
		$this->error_handler->unregister();
134 2
135 2
		return $response;
136
	}
137 2
138 2
	/**
139 2
	 * Filter the main query vars.
140
	 *
141
	 * @param  array $query_vars
142 2
	 * @return array
143
	 */
144
	public function filterRequest( $query_vars ) {
145
		$routes = $this->router->getRoutes();
146 2
147 2
		foreach ( $routes as $route ) {
148
			if ( ! $route instanceof HasQueryFilterInterface ) {
149
				continue;
150 2
			}
151
152
			if ( ! $route->isSatisfied( $this->request ) ) {
153
				continue;
154
			}
155
156
			$query_vars = $route->applyQueryFilter( $this->request, $query_vars );
157
			break;
158
		}
159 2
160 2
		return $query_vars;
161
	}
162 2
163 1
	/**
164 1
	 * Filter the main template file.
165
	 *
166 1
	 * @param  string $view
167
	 * @return string
168
	 */
169 1
	public function filterTemplateInclude( $view ) {
170
		global $wp_query;
171
172
		$response = $this->handle( $this->request, [$view] );
173
174
		if ( $response instanceof \Psr\Http\Message\ResponseInterface ) {
175
			$container = $this->app->getContainer();
176
			$container[ WPEMERGE_RESPONSE_KEY ] = $response;
177
178
			if ( $response->getStatusCode() === 404 ) {
179
				$wp_query->set_404();
180
			}
181
182
			return WPEMERGE_DIR . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'view.php';
183
		}
184
185
		return $view;
186
	}
187
188
	/**
189
	 * Register ajax action to hook into current one.
190
	 *
191
	 * @return void
192
	 */
193
	public function registerAjaxAction() {
194
		if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
195
			return;
196
		}
197
198
		$action = $this->request->post( 'action', $this->request->get( 'action' ) );
199
		$action = sanitize_text_field( $action );
200
201
		add_action( "wp_ajax_{$action}", [$this, 'actionAjax'] );
202
		add_action( "wp_ajax_nopriv_{$action}", [$this, 'actionAjax'] );
203
	}
204
205
	/**
206
	 * Act on ajax action.
207
	 *
208
	 * @return void
209
	 */
210
	public function actionAjax() {
211
		$response = $this->handle( $this->request, [''] );
212
213
		if ( ! $response instanceof \Psr\Http\Message\ResponseInterface ) {
214
			return;
215
		}
216
217
		$this->app->respond( $response );
218
		wp_die( '', '', ['response' => null] );
219
	}
220
221
	/**
222
	 * Get page hook.
223
	 * Slightly modified version of code from wp-admin/admin.php.
224
	 *
225
	 * @param  string $page_hook
226
	 * @return string
227
	 */
228
	protected function getAdminPageHook() {
229
		global $pagenow, $typenow, $plugin_page;
230
231
		$page_hook = '';
232
		if ( isset( $plugin_page ) ) {
233
			if ( ! empty( $typenow ) ) {
234
				$the_parent = $pagenow . '?post_type=' . $typenow;
235
			} else {
236
				$the_parent = $pagenow;
237
			}
238
239
			$page_hook = get_plugin_page_hook( $plugin_page, $the_parent );
240
		}
241
242
		return $page_hook;
243
	}
244
245
	/**
246
	 * Get admin page hook.
247
	 * Slightly modified version of code from wp-admin/admin.php.
248
	 *
249
	 * @param  string $page_hook
250
	 * @return string
251
	 */
252
	protected function getAdminHook( $page_hook ) {
253
		global $pagenow, $plugin_page;
254
255
		$hook_suffix = '';
256
		if ( ! empty( $page_hook ) ) {
257
			$hook_suffix = $page_hook;
258
		} else if ( isset( $plugin_page ) ) {
259
			$hook_suffix = $plugin_page;
260
		} else if ( isset( $pagenow ) ) {
261
			$hook_suffix = $pagenow;
262
		}
263
264
		return $hook_suffix;
265
	}
266
267
	/**
268
	 * Register admin action to hook into current one.
269
	 *
270
	 * @return void
271
	 */
272
	public function registerAdminAction() {
273
		global $pagenow;
274
275
		if ( $pagenow !== 'admin.php' ) {
276
			return;
277
		}
278
279
		$page_hook = $this->getAdminPageHook();
280
		$hook_suffix = $this->getAdminHook( $page_hook );
281
282
		add_action( "load-{$hook_suffix}", [$this, 'actionAdminLoad'] );
283
		add_action( $hook_suffix, [$this, 'actionAdmin'] );
284
	}
285
286
	/**
287
	 * Act on admin action load.
288
	 *
289
	 * @return void
290
	 */
291
	public function actionAdminLoad() {
292
		$response = $this->handle( $this->request, [''] );
293
294
		if ( ! $response instanceof \Psr\Http\Message\ResponseInterface ) {
295
			return;
296
		}
297
298
		if ( ! headers_sent() ) {
299
			Response::sendHeaders( $response );
300
		}
301
302
		add_filter( 'wpemerge.admin.response', function () use ( $response ) {
303
			return $response;
304
		} );
305
	}
306
307
	/**
308
	 * Act on admin action.
309
	 *
310
	 * @return void
311
	 */
312
	public function actionAdmin() {
313
		$response = apply_filters( 'wpemerge.admin.response', null );
314
315
		if ( $response === null ) {
316
			return;
317
		}
318
319
		Response::sendBody( $response );
320
	}
321
}
322