Completed
Push — try/statically-access-asset-to... ( e50fad...74c9e7 )
by
unknown
126:59 queued 118:11
created

Plugins::on_upgrader_completion()   C

Complexity

Conditions 15
Paths 111

Size

Total Lines 80

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
nc 111
nop 2
dl 0
loc 80
rs 5.0963
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
namespace Automattic\Jetpack\Sync\Modules;
3
use Automattic\Jetpack\Constants as Jetpack_Constants;
4
5
class Plugins extends \Jetpack_Sync_Module {
6
7
	private $action_handler;
8
	private $plugin_info = array();
9
	private $plugins     = array();
10
11
	public function name() {
12
		return 'plugins';
13
	}
14
15
	public function init_listeners( $callable ) {
16
		$this->action_handler = $callable;
17
18
		add_action( 'deleted_plugin', array( $this, 'deleted_plugin' ), 10, 2 );
19
		add_action( 'activated_plugin', $callable, 10, 2 );
20
		add_action( 'deactivated_plugin', $callable, 10, 2 );
21
		add_action( 'delete_plugin', array( $this, 'delete_plugin' ) );
22
		add_filter( 'upgrader_pre_install', array( $this, 'populate_plugins' ), 10, 1 );
23
		add_action( 'upgrader_process_complete', array( $this, 'on_upgrader_completion' ), 10, 2 );
24
		add_action( 'jetpack_plugin_installed', $callable, 10, 1 );
25
		add_action( 'jetpack_plugin_update_failed', $callable, 10, 4 );
26
		add_action( 'jetpack_plugins_updated', $callable, 10, 2 );
27
		add_action( 'admin_action_update', array( $this, 'check_plugin_edit' ) );
28
		add_action( 'jetpack_edited_plugin', $callable, 10, 2 );
29
		add_action( 'wp_ajax_edit-theme-plugin-file', array( $this, 'plugin_edit_ajax' ), 0 );
30
	}
31
32
	public function init_before_send() {
33
		add_filter( 'jetpack_sync_before_send_activated_plugin', array( $this, 'expand_plugin_data' ) );
34
		add_filter( 'jetpack_sync_before_send_deactivated_plugin', array( $this, 'expand_plugin_data' ) );
35
		// Note that we don't simply 'expand_plugin_data' on the 'delete_plugin' action here because the plugin file is deleted when that action finishes
36
	}
37
	public function populate_plugins( $response ) {
38
		$this->plugins = get_plugins();
39
		return $response;
40
	}
41
	public function on_upgrader_completion( $upgrader, $details ) {
42
		if ( ! isset( $details['type'] ) ) {
43
			return;
44
		}
45
		if ( 'plugin' != $details['type'] ) {
46
			return;
47
		}
48
49
		if ( ! isset( $details['action'] ) ) {
50
			return;
51
		}
52
53
		$plugins = ( isset( $details['plugins'] ) ? $details['plugins'] : null );
54
		if ( empty( $plugins ) ) {
55
			$plugins = ( isset( $details['plugin'] ) ? array( $details['plugin'] ) : null );
56
		}
57
58
		// for plugin installer
59
		if ( empty( $plugins ) && method_exists( $upgrader, 'plugin_info' ) ) {
60
			$plugins = array( $upgrader->plugin_info() );
61
		}
62
63
		if ( empty( $plugins ) ) {
64
			return; // We shouldn't be here
65
		}
66
67
		switch ( $details['action'] ) {
68
			case 'update':
69
				$state  = array(
70
					'is_autoupdate' => Jetpack_Constants::is_true( 'JETPACK_PLUGIN_AUTOUPDATE' ),
71
				);
72
				$errors = $this->get_errors( $upgrader->skin );
73
				if ( $errors ) {
74
					foreach ( $plugins as $slug ) {
75
						/**
76
						 * Sync that a plugin update failed
77
						 *
78
						 * @since  5.8.0
79
						 *
80
						 * @module sync
81
						 *
82
						 * @param string $plugin , Plugin slug
83
						 * @param        string  Error code
84
						 * @param        string  Error message
85
						 */
86
						do_action( 'jetpack_plugin_update_failed', $this->get_plugin_info( $slug ), $errors['code'], $errors['message'], $state );
87
					}
88
89
					return;
90
				}
91
				/**
92
				 * Sync that a plugin update
93
				 *
94
				 * @since  5.8.0
95
				 *
96
				 * @module sync
97
				 *
98
				 * @param array () $plugin, Plugin Data
99
				 */
100
				do_action( 'jetpack_plugins_updated', array_map( array( $this, 'get_plugin_info' ), $plugins ), $state );
101
				break;
102
			case 'install':
103
		}
104
105
		if ( 'install' === $details['action'] ) {
106
			/**
107
			 * Signals to the sync listener that a plugin was installed and a sync action
108
			 * reflecting the installation and the plugin info should be sent
109
			 *
110
			 * @since  5.8.0
111
			 *
112
			 * @module sync
113
			 *
114
			 * @param array () $plugin, Plugin Data
115
			 */
116
			do_action( 'jetpack_plugin_installed', array_map( array( $this, 'get_plugin_info' ), $plugins ) );
117
118
			return;
119
		}
120
	}
121
122
	private function get_plugin_info( $slug ) {
123
		$plugins = get_plugins(); // Get the most up to date info
124
		if ( isset( $plugins[ $slug ] ) ) {
125
			return array_merge( array( 'slug' => $slug ), $plugins[ $slug ] );
126
		};
127
		// Try grabbing the info from before the update
128
		return isset( $this->plugins[ $slug ] ) ? array_merge( array( 'slug' => $slug ), $this->plugins[ $slug ] ) : array( 'slug' => $slug );
129
	}
130
131
	private function get_errors( $skin ) {
132
		$errors = method_exists( $skin, 'get_errors' ) ? $skin->get_errors() : null;
133
		if ( is_wp_error( $errors ) ) {
134
			$error_code = $errors->get_error_code();
135
			if ( ! empty( $error_code ) ) {
136
				return array(
137
					'code'    => $error_code,
138
					'message' => $errors->get_error_message(),
139
				);
140
			}
141
		}
142
143
		if ( isset( $skin->result ) ) {
144
			$errors = $skin->result;
145
			if ( is_wp_error( $errors ) ) {
146
				return array(
147
					'code'    => $errors->get_error_code(),
148
					'message' => $errors->get_error_message(),
149
				);
150
			}
151
152
			if ( false == $skin->result ) {
153
				return array(
154
					'code'    => 'unknown',
155
					'message' => __( 'Unknown Plugin Update Failure', 'jetpack' ),
156
				);
157
			}
158
		}
159
		return false;
160
	}
161
162
	public function check_plugin_edit() {
163
		$screen = get_current_screen();
164
		if ( 'plugin-editor' !== $screen->base ||
165
		     ! isset( $_POST['newcontent'] ) ||
166
		     ! isset( $_POST['plugin'] )
167
		) {
168
			return;
169
		}
170
171
		$plugin  = $_POST['plugin'];
172
		$plugins = get_plugins();
173
		if ( ! isset( $plugins[ $plugin ] ) ) {
174
			return;
175
		}
176
177
		/**
178
		 * Helps Sync log that a plugin was edited
179
		 *
180
		 * @since 4.9.0
181
		 *
182
		 * @param string $plugin, Plugin slug
183
		 * @param mixed $plugins[ $plugin ], Array of plugin data
184
		 */
185
		do_action( 'jetpack_edited_plugin', $plugin, $plugins[ $plugin ] );
186
	}
187
188
	public function plugin_edit_ajax() {
189
		// this validation is based on wp_edit_theme_plugin_file()
190
		$args = wp_unslash( $_POST );
191
		if ( empty( $args['file'] ) ) {
192
			return;
193
		}
194
195
		$file = $args['file'];
196
		if ( 0 !== validate_file( $file ) ) {
197
			return;
198
		}
199
200
		if ( ! isset( $args['newcontent'] ) ) {
201
			return;
202
		}
203
204
		if ( ! isset( $args['nonce'] ) ) {
205
			return;
206
		}
207
208
		if ( empty( $args['plugin'] ) ) {
209
			return;
210
		}
211
212
		$plugin = $args['plugin'];
213
		if ( ! current_user_can( 'edit_plugins' ) ) {
214
			return;
215
		}
216
217
		if ( ! wp_verify_nonce( $args['nonce'], 'edit-plugin_' . $file ) ) {
218
			return;
219
		}
220
		$plugins = get_plugins();
221
		if ( ! array_key_exists( $plugin, $plugins ) ) {
222
			return;
223
		}
224
225
		if ( 0 !== validate_file( $file, get_plugin_files( $plugin ) ) ) {
226
			return;
227
		}
228
229
		$real_file = WP_PLUGIN_DIR . '/' . $file;
230
231
		if ( ! is_writeable( $real_file ) ) {
232
			return;
233
		}
234
235
		$file_pointer = fopen( $real_file, 'w+' );
236
		if ( false === $file_pointer ) {
237
			return;
238
		}
239
		fclose( $file_pointer );
240
		/**
241
		 * This action is documented already in this file
242
		 */
243
		do_action( 'jetpack_edited_plugin', $plugin, $plugins[ $plugin ] );
244
	}
245
246
	public function delete_plugin( $plugin_path ) {
247
		$full_plugin_path = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $plugin_path;
248
249
		// Checking for file existence because some sync plugin module tests simulate plugin installation and deletion without putting file on disk
250
		if ( file_exists( $full_plugin_path ) ) {
251
			$all_plugin_data = get_plugin_data( $full_plugin_path );
252
			$data            = array(
253
				'name'    => $all_plugin_data['Name'],
254
				'version' => $all_plugin_data['Version'],
255
			);
256
		} else {
257
			$data = array(
258
				'name'    => $plugin_path,
259
				'version' => 'unknown',
260
			);
261
		}
262
263
		$this->plugin_info[ $plugin_path ] = $data;
264
	}
265
266
	public function deleted_plugin( $plugin_path, $is_deleted ) {
267
		call_user_func( $this->action_handler, $plugin_path, $is_deleted, $this->plugin_info[ $plugin_path ] );
268
		unset( $this->plugin_info[ $plugin_path ] );
269
	}
270
271
	public function expand_plugin_data( $args ) {
272
		$plugin_path = $args[0];
273
		$plugin_data = array();
274
275
		if ( ! function_exists( 'get_plugins' ) ) {
276
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
277
		}
278
		$all_plugins = get_plugins();
279
		if ( isset( $all_plugins[ $plugin_path ] ) ) {
280
			$all_plugin_data        = $all_plugins[ $plugin_path ];
281
			$plugin_data['name']    = $all_plugin_data['Name'];
282
			$plugin_data['version'] = $all_plugin_data['Version'];
283
		}
284
285
		return array(
286
			$args[0],
287
			$args[1],
288
			$plugin_data,
289
		);
290
	}
291
}
292