Passed
Push — master ( e29497...7ab2d6 )
by Paul
04:36
created

Router::checkAjaxRequest()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3.576

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 4
nop 1
dl 0
loc 7
ccs 3
cts 5
cp 0.6
crap 3.576
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace GeminiLabs\SiteReviews;
4
5
use GeminiLabs\SiteReviews\Application;
6
use GeminiLabs\SiteReviews\Controllers\AdminController;
7
use GeminiLabs\SiteReviews\Controllers\AjaxController;
8
use GeminiLabs\SiteReviews\Controllers\PublicController;
9
use GeminiLabs\SiteReviews\Helper;
10
11
class Router
12
{
13
	/**
14
	 * @return void
15
	 */
16 1
	public function routeAdminPostRequest()
17
	{
18 1
		$request = $this->getRequest();
19 1
		if( !$this->isValidPostRequest( $request ))return;
20
		check_admin_referer( $request['action'] );
21
		$this->routeRequest( 'admin', $request['action'], $request );
22
	}
23
24
	/**
25
	 * @return void
26
	 */
27 1
	public function routeAjaxRequest()
28
	{
29 1
		$request = $this->getRequest();
30 1
		$this->checkAjaxRequest( $request );
31 1
		$this->checkAjaxNonce( $request );
32 1
		$this->routeRequest( 'ajax', $request['action'], $request );
33
		wp_die();
34
	}
35
36
	/**
37
	 * @return void
38
	 */
39
	public function routePublicPostRequest()
40
	{
41
		if( is_admin() )return;
42
		$request = $this->getRequest();
43
		if( !$this->isValidPostRequest( $request ))return;
44
		if( !$this->isValidPublicNonce( $request ))return;
45
		$this->routeRequest( 'public', $request['action'], $request );
46
	}
47
48
	/**
49
	 * @return void
50
	 */
51 1
	protected function checkAjaxNonce( array $request )
52
	{
53 1
		if( !is_user_logged_in() )return;
54
		if( !isset( $request['nonce'] )) {
55
			$this->sendAjaxError( 'The request is missing a nonce', $request );
56
		}
57
		if( !wp_verify_nonce( $request['nonce'], $request['action'] )) {
58
			$this->sendAjaxError( 'The request failed the nonce check', $request, 403 );
59
		}
60
	}
61
62
	/**
63
	 * @return void
64
	 */
65 1
	protected function checkAjaxRequest( array $request )
66
	{
67 1
		if( !isset( $request['action'] )) {
68
			$this->sendAjaxError( 'The request must include an action', $request );
69
		}
70 1
		if( empty( $request['ajax_request'] )) {
71
			$this->sendAjaxError( 'The request is invalid', $request );
72
		}
73 1
	}
74
75
	/**
76
	 * All ajax requests in the plugin are triggered by a single action hook: glsr_action,
77
	 * while each route is determined by $_POST[request][action]
78
	 * @return array
79
	 */
80 1
	protected function getRequest()
81
	{
82 1
		$request = glsr( Helper::class )->filterInput( 'action' ) == Application::PREFIX.'action'
83 1
			? glsr( Helper::class )->filterInputArray( 'request' )
84 1
			: glsr( Helper::class )->filterInputArray( Application::ID );
85 1
		return $this->normalizeRequest( $request );
86
	}
87
88
	/**
89
	 * @return bool
90
	 */
91 1
	protected function isValidPostRequest( array $request = [] )
92
	{
93 1
		return !empty( $request['action'] ) && empty( $request['ajax_request'] );
94
	}
95
96
	/**
97
	 * @return bool
98
	 */
99
	protected function isValidPublicNonce( array $request )
100
	{
101
		if( is_user_logged_in() && !wp_verify_nonce( $request['nonce'], $request['action'] )) {
102
			glsr_log()->error( 'Nonce check failed for public request' )->info( $request );
103
			return false;
104
		}
105
		return true;
106
	}
107
108
	/**
109
	 * @return array
110
	 */
111 1
	protected function normalizeRequest( array $request )
112
	{
113 1
		if( glsr( Helper::class )->filterInput( 'action' ) == Application::PREFIX.'action' ) {
114 1
			$request['ajax_request'] = true;
115
		}
116 1
		if( glsr( Helper::class )->filterInput( 'action', $request ) == 'submit-review' ) {
117 1
			$request['recaptcha-token'] = glsr( Helper::class )->filterInput( 'g-recaptcha-response' );
118
		}
119 1
		return $request;
120
	}
121
122
	/**
123
	 * @param string $type
124
	 * @param string $action
125
	 * @return void
126
	 */
127 1
	protected function routeRequest( $type, $action, array $request = [] )
128
	{
129 1
		$actionHook = 'site-reviews/route/'.$type.'/request';
130 1
		$controller = glsr( glsr( Helper::class )->buildClassName( $type.'-controller', 'Controllers' ));
131 1
		$method = glsr( Helper::class )->buildMethodName( $action, 'router' );
132 1
		$request = apply_filters( 'site-reviews/route/request', $request, $action, $type );
133 1
		do_action( $actionHook, $action, $request );
134 1
		if( is_callable( [$controller, $method] )) {
135 1
			call_user_func( [$controller, $method], $request );
136
			return;
137
		}
138
		if( did_action( $actionHook ) === 0 ) {
139
			glsr_log( 'Unknown '.$type.' router request: '.$action );
140
		}
141
	}
142
143
	/**
144
	 * @param string $error
145
	 * @param int $statusCode
146
	 * @return void
147
	 */
148
	protected function sendAjaxError( $error, array $request, $statusCode = 400 )
149
	{
150
		glsr_log()->error( $error )->info( $request );
151
		wp_send_json_error([
152
			'message' => __( 'The form could not be submitted. Please notify the site administrator.', 'site-reviews' ),
153
			'error' => $error,
154
		], $statusCode );
155
	}
156
}
157