Passed
Push — master ( 4e97bc...650bc8 )
by Paul
05:35
created

Router::checkAjaxNonce()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 10.75

Importance

Changes 0
Metric Value
cc 4
nc 5
nop 1
dl 0
loc 10
ccs 2
cts 8
cp 0.25
crap 10.75
rs 9.9332
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
		$this->checkAdminNonce( $request['action'] );
21
		$this->routeRequest( 'admin', $request['action'], $request );
22
	}
23
24
	/**
25
	 * All ajax requests in the plugin are triggered by a single action hook (i.e. "glsr_action")
26
	 * Each route is determined by the request["action"]
27
	 * @return void
28
	 */
29 1
	public function routeAjaxRequest()
30
	{
31 1
		$request = $this->getRequest();
32 1
		if( !isset( $request['action'] )) {
33
			glsr_log()->error( 'The AJAX request must include an action' )->info( $request );
34
			wp_die();
35
		}
36 1
		$this->checkAjaxNonce( $request );
37 1
		$request['ajax_request'] = true;
38 1
		$this->routeRequest( 'ajax', $request['action'], $request );
39
		wp_die();
40
	}
41
42
	/**
43
	 * @return void
44
	 */
45
	public function routePublicPostRequest()
46
	{
47
		if( is_admin() )return;
48
		$request = $this->getRequest();
49
		if( !$this->isValidPostRequest( $request ))return;
50
		if( !$this->isValidPublicNonce( $request ))return;
51
		$this->routeRequest( 'public', $request['action'], $request );
52
	}
53
54
	/**
55
	 * @return void
56
	 */
57 1
	public function routeWebhookRequest()
58
	{
59 1
		$request = filter_input( INPUT_GET, Application::PREFIX.'hook' );
60 1
		if( !$request )return;
61
		// @todo manage webhook here
62
	}
63
64
	/**
65
	 * @param string $action
66
	 * @return void
67
	 * @todo verify the $action-options
68
	 */
69
	protected function checkAdminNonce( $action )
70
	{
71
		$nonce = glsr( Helper::class )->filterInput( 'option_page' ) == $action
72
			&& glsr( Helper::class )->filterInput( 'action' ) == 'update'
73
			? $action.'-options'
74
			: $action;
75
		check_admin_referer( $nonce );
76
	}
77
78
	/**
79
	 * @return void
80
	 */
81 1
	protected function checkAjaxNonce( array $request )
82
	{
83 1
		if( !is_user_logged_in() )return;
84
		if( !isset( $request['nonce'] )) {
85
			glsr_log()->error( 'The AJAX request must include a nonce' )->info( $request );
86
			wp_die();
87
		}
88
		if( !wp_verify_nonce( $request['nonce'], $request['action'] )) {
89
			glsr_log()->error( 'Nonce check failed for ajax request' )->info( $request );
90
			wp_die( -1, 403 );
91
		}
92
	}
93
94
	/**
95
	 * @return array
96
	 */
97 1
	protected function getRequest()
98
	{
99 1
		foreach( ['request', Application::ID] as $key ) {
100 1
			$request = glsr( Helper::class )->filterInputArray( $key );
101 1
			if( !empty( $request ))break;
102
		}
103 1
		return $this->normalizeRequest( $request );
104
	}
105
106
	/**
107
	 * @return bool
108
	 */
109 1
	protected function isValidPostRequest( array $request = [] )
110
	{
111 1
		return !empty( $request['action'] ) && empty( glsr( Helper::class )->filterInput( 'ajax_request' ));
112
	}
113
114
	/**
115
	 * @return bool
116
	 */
117
	protected function isValidPublicNonce( array $request )
118
	{
119
		if( is_user_logged_in() && !wp_verify_nonce( $request['_wpnonce'], $request['action'] )) {
120
			glsr_log()->error( 'Nonce check failed for public request' )->info( $request );
121
			return false;
122
		}
123
		return true;
124
	}
125
126
	/**
127
	 * @return array
128
	 */
129 1
	protected function normalizeRequest( array $request )
130
	{
131 1
		if( isset( $request[Application::ID]['action'] )) {
132
			$request = $request[Application::ID];
133
		}
134 1
		if( glsr( Helper::class )->filterInput( 'action', $request ) == 'submit-review' ) {
135 1
			$request['recaptcha-token'] = glsr( Helper::class )->filterInput( 'g-recaptcha-response' );
136
		}
137 1
		return $request;
138
	}
139
140
	/**
141
	 * @param string $type
142
	 * @param string $action
143
	 * @return void
144
	 */
145 1
	protected function routeRequest( $type, $action, array $request = [] )
146
	{
147 1
		$actionHook = 'site-reviews/route/'.$type.'/request';
148 1
		$controller = glsr( glsr( Helper::class )->buildClassName( $type.'-controller', 'Controllers' ));
149 1
		$method = glsr( Helper::class )->buildMethodName( $action, 'router' );
150 1
		$request = apply_filters( 'site-reviews/route/request', $request, $action, $type );
151 1
		do_action( $actionHook, $action, $request );
152 1
		if( is_callable( [$controller, $method] )) {
153 1
			call_user_func( [$controller, $method], $request );
154
			return;
155
		}
156
		if( did_action( $actionHook ) === 0 ) {
157
			glsr_log( 'Unknown '.$type.' router request: '.$action );
158
		}
159
	}
160
}
161