Completed
Push — add/blog-token-self-heal ( 8b31a7 )
by
unknown
66:08 queued 58:32
created

Invalid_Blog_Token::admin_notice()   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 handler class for invalid blog tokens
4
 *
5
 * @package automattic/jetpack-connection
6
 */
7
8
namespace Automattic\Jetpack\Connection\Error_Handlers;
9
10
use Automattic\Jetpack\Connection\Manager;
11
use Automattic\Jetpack\Connection\Error_Handler;
12
13
/**
14
 * This class handles all the error codes that indicates a broken blog token and
15
 * suggests the user to reconnect.
16
 *
17
 * @since 8.7.0
18
 */
19
class Invalid_Blog_Token {
20
21
	/**
22
	 * Number of times we will try to regenerate the blog token
23
	 *
24
	 * @var integer
25
	 */
26
	private $max_heal_attempts = 1000;
27
28
	/**
29
	 * Name of the option where we store the number of attempts to self heal
30
	 *
31
	 * @var string
32
	 */
33
	private $attempts_option_name = '_jetpack_connection_blog_token_heal_attempts';
34
35
	/**
36
	 * Set up hooks
37
	 *
38
	 * @since 8.7.0
39
	 *
40
	 * @param array $errors The array containing verified errors stored in the database.
41
	 */
42
	public function __construct( $errors ) {
43
44
		/**
45
		 * Filters the message to be displayed in the admin notices area when there's a invalid blog token xmlrpc error
46
		 *
47
		 * Return an empty value to disable the message.
48
		 *
49
		 * @since 8.7.0
50
		 *
51
		 * @param string $message The error message.
52
		 */
53
		$this->message = apply_filters( 'jetpack_connection_invalid_blog_token_admin_notice', __( 'Your connection with WordPress.com seems to be broken. If you\'re experiencing issues, please try reconnecting.', 'jetpack' ) );
0 ignored issues
show
Bug introduced by
The property message does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
54
55
		if ( empty( $this->message ) ) {
56
			return;
57
		}
58
59
		// In this class, we will only handle errors with the blog token, so ignoring if there are only errors with user tokens.
60
		if ( ! isset( $errors[0] ) && ! isset( $errors['invalid'] ) ) {
61
			return;
62
		}
63
64
		$this->attempts = (int) get_option( $this->attempts_option_name );
0 ignored issues
show
Bug introduced by
The property attempts does not seem to exist. Did you mean max_heal_attempts?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
65
66
		if ( $this->should_self_heal() ) {
67
			$this->refresh_blog_token();
68
		}
69
70
		add_action( 'react_connection_errors_initial_state', array( $this, 'jetpack_react_dashboard_error' ) );
71
		// do not add admin notice to the jetpack dashboard.
72
		global $pagenow;
73
		if ( 'admin.php' === $pagenow || isset( $_GET['page'] ) && 'jetpack' === $_GET['page'] ) { // phpcs:ignore
74
			return;
75
		}
76
		add_action( 'admin_notices', array( $this, 'admin_notice' ) );
77
78
	}
79
80
	/**
81
	 * Prints an admin notice for the blog token error
82
	 *
83
	 * @since 8.7.0
84
	 *
85
	 * @return void
86
	 */
87
	public function admin_notice() {
88
89
		if ( ! current_user_can( 'jetpack_connect' ) ) {
90
			return;
91
		}
92
93
		?>
94
		<div class="notice notice-error is-dismissible jetpack-message jp-connect" style="display:block !important;">
95
			<p><?php echo esc_html( $this->message ); ?></p>
96
		</div>
97
		<?php
98
	}
99
100
	/**
101
	 * Adds the error message to the Jetpack React Dashboard
102
	 *
103
	 * @param array $errors The array of errors.
104
	 * @return array
105
	 */
106
	public function jetpack_react_dashboard_error( $errors ) {
107
108
		$errors[] = array(
109
			'code'    => 'invalid_blog_token',
110
			'message' => $this->message,
111
			'action'  => 'reconnect',
112
		);
113
		return $errors;
114
	}
115
116
	/**
117
	 * Checks the number of healing attempts and returns a boolean indicating if we should
118
	 * try again or not
119
	 *
120
	 * @return boolean
121
	 */
122
	public function should_self_heal() {
123
		return $this->attempts > 0 && $this->attempts < $this->max_heal_attempts;
0 ignored issues
show
Bug introduced by
The property attempts does not seem to exist. Did you mean max_heal_attempts?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
124
	}
125
126
	/**
127
	 * Gets the number of times this blog attempted to regenerate the blog token
128
	 * and updates it in the database
129
	 *
130
	 * @return integer
131
	 */
132
	public function get_heal_attempts() {
133
		$attempts = (int) get_option( $this->attempts_option_name );
134
		$attempts ++;
135
		update_option( $this->attempts_option_name, $attempts );
136
		return $attempts;
137
	}
138
139
	/**
140
	 * Lock attempts
141
	 *
142
	 * @return void
143
	 */
144
	private function lock_attempts() {
145
		update_option( $this->attempts_option_name, -1 );
146
	}
147
148
	/**
149
	 * Unlock attempts
150
	 *
151
	 * @return void
152
	 */
153
	private function unlock_attempts() {
154
		update_option( $this->attempts_option_name, $this->attempts );
0 ignored issues
show
Bug introduced by
The property attempts does not seem to exist. Did you mean max_heal_attempts?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
155
	}
156
157
	/**
158
	 * Tries to register the site again and refresh the blog token
159
	 *
160
	 * @return void
161
	 */
162
	public function refresh_blog_token() {
163
164
		$this->lock_attempts();
165
166
		$manager = new Manager();
167
168
		$heal = $manager->register();
169
		l( $heal );
170
171
		$this->attempts ++;
0 ignored issues
show
Bug introduced by
The property attempts does not seem to exist. Did you mean max_heal_attempts?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
172
173
		if ( true === $heal ) {
174
			Error_Handler::get_instance()->delete_all_errors();
175
			delete_option( $this->attempts_option_name );
176
		} else {
177
			$this->unlock_attempts();
178
		}
179
	}
180
181
}
182