Completed
Push — add/connection-error-handling ( 525cd7...e29761 )
by
unknown
07:01
created

Error_Handler::get_stored_errors()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
1
<?php
2
/**
3
 * The Jetpack Connection error class file.
4
 *
5
 * @package automattic/jetpack-connection
6
 */
7
8
namespace Automattic\Jetpack\Connection;
9
10
/**
11
 * The Jetpack Connection Errors that handles errors
12
 */
13
class Error_Handler {
14
15
	/**
16
	 * The name of the option that stores the errors
17
	 *
18
	 * @var string
19
	 */
20
	const STORED_ERRORS_OPTION = 'jetpack_xmlrpc_errors';
21
22
	/**
23
	 * The prefix of the transient that controls the gate for each error code
24
	 *
25
	 * @var string
26
	 */
27
	const ERROR_REPORTING_GATE = 'jetpack_connection_error_reporting_gate_';
28
29
	/**
30
	 * Return the code and details of all known errors.
31
	 *
32
	 * @return array
33
	 */
34
	public function get_errors() {
35
36
		$errors = array(
37
			'unknown_error'   => array(
38
				'title'        => __( 'Unknown connection error', 'jetpack' ),
39
				'fix_tip'      => __( 'Unknown connection error', 'jetpack' ),
40
				'fix_url'      => '',
41
				'fix_callback' => null,
42
			),
43
44
			'malformed_token' => array(
45
				'title'        => __( 'Malformed token', 'jetpack' ),
46
				'fix_tip'      => __( 'The token used to authenticate requests between your site and WordPress.com is invalid. Try resetting the connection', 'jetpack' ),
47
				'fix_url'      => '', // The URL of a call to action button to fix it.
48
				'fix_label'    => 'Reconnect', // The label of a call to action button to fix it.
49
				'fix_callback' => array( $this, 'fix_disconnect' ), // a callback that will be invoked to try to fix the issue locally.
50
			),
51
52
			'unknown_user'    => array(
53
				'title'   => __( 'Unknown User', 'jetpack' ),
54
				'fix_tip' => __( 'There is a connection between WordPress.com and a user that no longer exists on your site. If a user was deleted, information on WordPress.com must be updated and you might need to reconnect with a different user.', 'jetpack' ),
55
				'fix_url' => '', // The URL of a call to action button to fix it.
56
				// 'fix_label'    => 'Reconnect', // The label of a call to action button to fix it.
57
				// 'fix_callback' => array( $this, 'fix_disconnect' ), // a callback that will be invoked to try to fix the issue locally.
58
			),
59
		);
60
61
		return apply_filters( 'jetpack_connection_errors', $errors );
62
63
	}
64
65
	/**
66
	 * Keep track of a connection error that was encoutered
67
	 *
68
	 * @param \WP_Error $error the error object.
69
	 * @param boolean   $force Force the report, even if should_report_error is false.
70
	 * @return void
71
	 */
72
	public function report_error( \WP_Error $error, $force = false ) {
73
		if ( $this->should_report_error( $error ) || $force ) {
74
			$this->store_error( $error );
75
			$this->inform_wpcom( $error );
76
		}
77
	}
78
79
	/**
80
	 * Checks the status of the gate
81
	 *
82
	 * This protects the site (and WPCOM) against over loads.
83
	 *
84
	 * @param \WP_Error $error the error object.
85
	 * @return boolean $should_report True if gate is open and the error should be reported.
86
	 */
87
	public function should_report_error( \WP_Error $error ) {
88
89
		if ( defined( 'JETPACK_DEV_DEBUG' ) && JETPACK_DEV_DEBUG ) {
90
			return true;
91
		}
92
93
		$transient = self::ERROR_REPORTING_GATE . $error->get_error_code();
0 ignored issues
show
Bug introduced by
The method get_error_code() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
94
95
		if ( get_transient( $transient ) ) {
96
			return false;
97
		}
98
99
		set_transient( $transient, true, HOUR_IN_SECONDS );
100
		return true;
101
	}
102
103
	/**
104
	 * Stores the error in the database so we know there is an issue and can inform the user
105
	 *
106
	 * @param \WP_Error $error the error object.
107
	 * @return boolean False if stored errors were not updated and true if stored errors were updated.
108
	 */
109
	public function store_error( \WP_Error $error ) {
110
		$stored_errors                             = $this->get_stored_errors();
111
		$stored_errors[ $error->get_error_code() ] = array(
0 ignored issues
show
Bug introduced by
The method get_error_code() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
112
			'error_code'    => $error->get_error_code(),
0 ignored issues
show
Bug introduced by
The method get_error_code() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
113
			'error_message' => $error->get_error_message(),
0 ignored issues
show
Bug introduced by
The method get_error_message() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
114
			'error_data'    => $error->get_error_data(),
0 ignored issues
show
Bug introduced by
The method get_error_data() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
115
		);
116
		return update_option( self::STORED_ERRORS_OPTION, $stored_errors );
117
	}
118
119
	/**
120
	 * Informs wpcom servers about the error
121
	 *
122
	 * @param \WP_Error $error the error object.
123
	 * @return void
124
	 */
125
	public function inform_wpcom( \WP_Error $error ) {
126
		// securely inform wpcom about the error (via sync?) so Calypso knows about it and it can trigger some self-healing routine.
127
	}
128
129
	/**
130
	 * Gets the reported errors stored in the database
131
	 *
132
	 * @return \WP_Error[] $errors
133
	 */
134
	public function get_stored_errors() {
135
		$stored_errors = get_option( self::STORED_ERRORS_OPTION );
136
		if ( ! is_array( $stored_errors ) ) {
137
			$stored_errors = array();
138
		}
139
		return array_map(
140
			function( $error ) {
141
				return new \WP_Error( $error['error_code'], $error['error_message'], $error['error_data'] );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with $error['error_code'].

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...
142
			},
143
			$stored_errors
144
		);
145
	}
146
147
	/**
148
	 * Delete the reported errors stored in the database
149
	 *
150
	 * @return boolean True, if option is successfully deleted. False on failure.
151
	 */
152
	public function delete_stored_errors() {
153
		return delete_option( self::STORED_ERRORS_OPTION );
154
	}
155
156
	/**
157
	 * Add notices to the Admin Notices section if there are known connection errors
158
	 *
159
	 * @return void
160
	 */
161
	public function admin_notices() {
162
163
		/**
164
		 * Determines whether the Connection package will display connection errors to the user.
165
		 *
166
		 * @since 8.7.0
167
		 *
168
		 * @param bool $display_error_messages Defaults to true.
169
		 */
170
		$display_error_messages = apply_filters( 'jetpack_connection_display_errors', true );
171
172
		if ( true !== $display_error_messages ) {
173
			return;
174
		}
175
176
		$errors = $this->get_stored_errors();
177
		if ( count( $errors ) ) {
178
			foreach ( $errors as $error ) {
179
180
				/**
181
				 * Determines whether the Connection package will display a specific connection error to the user.
182
				 *
183
				 * The dynamic part of the hook is the error code.
184
				 *
185
				 * @since 8.7.0
186
				 *
187
				 * @param bool $display_error_message Defaults to true.
188
				 */
189
				$error_code            = $error->get_error_code();
0 ignored issues
show
Bug introduced by
The method get_error_code() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
190
				$display_error_message = apply_filters( "jetpack_connection_display_error_{$error_code}", true );
191
192
				if ( true !== $display_error_message ) {
193
					continue;
194
				}
195
196
				require 'connection-errors-notices-template.php';
197
			}
198
		}
199
	}
200
201
}
202