Completed
Push — add/changelog-write ( e9976a...ba0b5a )
by
unknown
406:06 queued 396:12
created

Rest_Authentication::wp_rest_authenticate()   D

Complexity

Conditions 16
Paths 20

Size

Total Lines 86

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
nc 20
nop 1
dl 0
loc 86
rs 4.7587
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * The Jetpack Connection Rest Authentication file.
4
 *
5
 * @package automattic/jetpack-connection
6
 */
7
8
namespace Automattic\Jetpack\Connection;
9
10
/**
11
 * The Jetpack Connection Rest Authentication class.
12
 */
13
class Rest_Authentication {
14
15
	/**
16
	 * The rest authentication status.
17
	 *
18
	 * @since 8.9.0
19
	 * @var boolean
20
	 */
21
	private $rest_authentication_status = null;
22
23
	/**
24
	 * The Manager object.
25
	 *
26
	 * @since 8.9.0
27
	 * @var Object
28
	 */
29
	private $connection_manager = null;
30
31
	/**
32
	 * Holds the singleton instance of this class
33
	 *
34
	 * @since 8.9.0
35
	 * @var Object
36
	 */
37
	private static $instance = false;
38
39
	/**
40
	 * Flag used to avoid determine_current_user filter to enter an infinite loop
41
	 *
42
	 * @since 9.7.0
43
	 * @var boolean
44
	 */
45
	private $doing_determine_current_user_filter = false;
46
47
	/**
48
	 * The constructor.
49
	 */
50
	private function __construct() {
51
		$this->connection_manager = new Manager();
52
	}
53
54
	/**
55
	 * Controls the single instance of this class.
56
	 *
57
	 * @static
58
	 */
59
	public static function init() {
60
		if ( ! self::$instance ) {
61
			self::$instance = new self();
62
63
			add_filter( 'determine_current_user', array( self::$instance, 'wp_rest_authenticate' ) );
64
			add_filter( 'rest_authentication_errors', array( self::$instance, 'wp_rest_authentication_errors' ) );
65
		}
66
67
		return self::$instance;
68
	}
69
70
	/**
71
	 * Authenticates requests from Jetpack server to WP REST API endpoints.
72
	 * Uses the existing XMLRPC request signing implementation.
73
	 *
74
	 * @param int|bool $user User ID if one has been determined, false otherwise.
75
	 *
76
	 * @return int|null The user id or null if the request was not authenticated.
77
	 */
78
	public function wp_rest_authenticate( $user ) {
79
		if ( $this->doing_determine_current_user_filter ) {
80
			return $user;
81
		}
82
83
		$this->doing_determine_current_user_filter = true;
84
85
		try {
86
			if ( ! empty( $user ) ) {
87
				// Another authentication method is in effect.
88
				return $user;
89
			}
90
91
			add_filter(
92
				'jetpack_constant_default_value',
93
				__NAMESPACE__ . '\Utils::jetpack_api_constant_filter',
94
				10,
95
				2
96
			);
97
98
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
99
			if ( ! isset( $_GET['_for'] ) || 'jetpack' !== $_GET['_for'] ) {
100
				// Nothing to do for this authentication method.
101
				return null;
102
			}
103
104
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
105
			if ( ! isset( $_GET['token'] ) && ! isset( $_GET['signature'] ) ) {
106
				// Nothing to do for this authentication method.
107
				return null;
108
			}
109
110
			if ( ! isset( $_SERVER['REQUEST_METHOD'] ) ) {
111
				$this->rest_authentication_status = new \WP_Error(
0 ignored issues
show
Documentation Bug introduced by
It seems like new \WP_Error('rest_inva...array('status' => 400)) of type object<WP_Error> is incompatible with the declared type boolean of property $rest_authentication_status.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
112
					'rest_invalid_request',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'rest_invalid_request'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
113
					__( 'The request method is missing.', 'jetpack' ),
114
					array( 'status' => 400 )
115
				);
116
				return null;
117
			}
118
119
			// Only support specific request parameters that have been tested and
120
			// are known to work with signature verification.  A different method
121
			// can be passed to the WP REST API via the '?_method=' parameter if
122
			// needed.
123
			if ( 'GET' !== $_SERVER['REQUEST_METHOD'] && 'POST' !== $_SERVER['REQUEST_METHOD'] ) {
124
				$this->rest_authentication_status = new \WP_Error(
0 ignored issues
show
Documentation Bug introduced by
It seems like new \WP_Error('rest_inva...array('status' => 400)) of type object<WP_Error> is incompatible with the declared type boolean of property $rest_authentication_status.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
125
					'rest_invalid_request',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'rest_invalid_request'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
126
					__( 'This request method is not supported.', 'jetpack' ),
127
					array( 'status' => 400 )
128
				);
129
				return null;
130
			}
131
			if ( 'POST' !== $_SERVER['REQUEST_METHOD'] && ! empty( file_get_contents( 'php://input' ) ) ) {
132
				$this->rest_authentication_status = new \WP_Error(
0 ignored issues
show
Documentation Bug introduced by
It seems like new \WP_Error('rest_inva...array('status' => 400)) of type object<WP_Error> is incompatible with the declared type boolean of property $rest_authentication_status.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
133
					'rest_invalid_request',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'rest_invalid_request'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
134
					__( 'This request method does not support body parameters.', 'jetpack' ),
135
					array( 'status' => 400 )
136
				);
137
				return null;
138
			}
139
140
			$verified = $this->connection_manager->verify_xml_rpc_signature();
141
142
			if (
143
				$verified &&
144
				isset( $verified['type'] ) &&
145
				'user' === $verified['type'] &&
146
				! empty( $verified['user_id'] )
147
			) {
148
				// Authentication successful.
149
				$this->rest_authentication_status = true;
150
				return $verified['user_id'];
151
			}
152
153
			// Something else went wrong.  Probably a signature error.
154
			$this->rest_authentication_status = new \WP_Error(
0 ignored issues
show
Documentation Bug introduced by
It seems like new \WP_Error('rest_inva...array('status' => 400)) of type object<WP_Error> is incompatible with the declared type boolean of property $rest_authentication_status.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
155
				'rest_invalid_signature',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'rest_invalid_signature'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
156
				__( 'The request is not signed correctly.', 'jetpack' ),
157
				array( 'status' => 400 )
158
			);
159
			return null;
160
		} finally {
161
			$this->doing_determine_current_user_filter = false;
162
		}
163
	}
164
165
	/**
166
	 * Report authentication status to the WP REST API.
167
	 *
168
	 * @param  WP_Error|mixed $value Error from another authentication handler, null if we should handle it, or another value if not.
169
	 * @return WP_Error|boolean|null {@see WP_JSON_Server::check_authentication}
170
	 */
171
	public function wp_rest_authentication_errors( $value ) {
172
		if ( null !== $value ) {
173
			return $value;
174
		}
175
		return $this->rest_authentication_status;
176
	}
177
178
	/**
179
	 * Resets the saved authentication state in between testing requests.
180
	 */
181
	public function reset_saved_auth_state() {
182
		$this->rest_authentication_status = null;
183
		$this->connection_manager->reset_saved_auth_state();
184
	}
185
}
186