Completed
Push — add/changelog-55 ( 8beac4...406ec3 )
by Jeremy
15:59 queued 07:35
created

...s.jetpack-json-api-plugins-install-endpoint.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
4
include_once ABSPATH . 'wp-admin/includes/file.php';
5
6
class Jetpack_JSON_API_Plugins_Install_Endpoint extends Jetpack_JSON_API_Plugins_Endpoint {
7
8
	// POST /sites/%s/plugins/%s/install
9
	protected $needed_capabilities = 'install_plugins';
10
	protected $action              = 'install';
11
12
	protected function install() {
13
		foreach ( $this->plugins as $index => $slug ) {
14
15
			$skin      = new Jetpack_Automatic_Install_Skin();
16
			$upgrader  = new Plugin_Upgrader( $skin );
17
			$zip_url   = self::generate_wordpress_org_plugin_download_link( $slug );
18
19
			$result = $upgrader->install( $zip_url );
20
21
			if ( ! $this->bulk && is_wp_error( $result ) ) {
22
				return $result;
23
			}
24
25
			$plugin = self::get_plugin_id_by_slug( $slug );
26
			$error_code = 'install_error';
27
			if ( ! $plugin ) {
28
				$error = $this->log[ $slug ]['error'] = __( 'There was an error installing your plugin', 'jetpack' );
29
			}
30
31
			if ( ! $this->bulk && ! $result ) {
32
				$error_code = $upgrader->skin->get_main_error_code();
33
				$message = $upgrader->skin->get_main_error_message();
34
				$error = $this->log[ $slug ]['error'] = $message ? $message : __( 'An unknown error occurred during installation' , 'jetpack' );
35
			}
36
37
			$this->log[ $plugin ][] = $upgrader->skin->get_upgrade_messages();
38
		}
39
40
		if ( ! $this->bulk && isset( $error ) ) {
41
42
			if ( 'download_failed' === $error_code ) {
43
				// For backwards compatibility: versions prior to 3.9 would return no_package instead of download_failed.
44
				$error_code = 'no_package';
45
			}
46
47
			return new WP_Error( $error_code, $this->log[ $slug ]['error'], 400 );
0 ignored issues
show
The variable $slug seems to be defined by a foreach iteration on line 13. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
48
		}
49
50
		// replace the slug with the actual plugin id
51
		$this->plugins[ $index ] = $plugin;
52
53
		return true;
54
	}
55
56
	protected function validate_plugins() {
57 View Code Duplication
		if ( empty( $this->plugins ) || ! is_array( $this->plugins ) ) {
58
			return new WP_Error( 'missing_plugins', __( 'No plugins found.', 'jetpack' ) );
59
		}
60
		foreach( $this->plugins as $index => $slug ) {
61
			// make sure it is not already installed
62
			if ( self::get_plugin_id_by_slug( $slug ) ) {
63
				return new WP_Error( 'plugin_already_installed', __( 'The plugin is already installed', 'jetpack' ) );
64
			}
65
66
		}
67
		return true;
68
	}
69
70
	protected static function generate_wordpress_org_plugin_download_link( $plugin_slug ) {
71
		return "https://downloads.wordpress.org/plugin/{$plugin_slug}.latest-stable.zip";
72
	}
73
74
	protected static function get_plugin_id_by_slug( $slug ) {
75
		/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
76
		$plugins = apply_filters( 'all_plugins', get_plugins() );
77
		if ( ! is_array( $plugins ) ) {
78
			return false;
79
		}
80
		foreach( $plugins as $plugin_file => $plugin_data ) {
81
			if ( self::get_slug_from_file_path( $plugin_file ) === $slug ) {
82
				return $plugin_file;
83
			}
84
		}
85
		return false;
86
	}
87
88
	protected static function get_slug_from_file_path( $plugin_file ) {
89
		// Simular to get_plugin_slug() method.
90
		$slug = dirname( $plugin_file );
91
		if ( '.' === $slug ) {
92
			$slug = preg_replace("/(.+)\.php$/", "$1", $plugin_file );
93
		}
94
		return $slug;
95
	}
96
}
97
/**
98
 * Allows us to capture that the site doesn't have proper file system access.
99
 * In order to update the plugin.
100
 */
101
class Jetpack_Automatic_Install_Skin extends Automatic_Upgrader_Skin {
102
	/**
103
	 * Stores the last error key;
104
	 **/
105
	protected $main_error_code = 'install_error';
106
107
	/**
108
	 * Stores the last error message.
109
	 **/
110
	protected $main_error_message = 'An unknown error occurred during installation';
111
112
	/**
113
	 * Overwrites the set_upgrader to be able to tell if we e ven have the ability to write to the files.
114
	 *
115
	 * @param WP_Upgrader $upgrader
116
	 *
117
	 */
118
	public function set_upgrader( &$upgrader ) {
119
		parent::set_upgrader( $upgrader );
120
121
		// Check if we even have permission to.
122
		$result = $upgrader->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
123
		if ( ! $result ) {
124
			// set the string here since they are not available just yet
125
			$upgrader->generic_strings();
126
			$this->feedback( 'fs_unavailable' );
127
		}
128
	}
129
130
	/**
131
	 * Overwrites the error function
132
	 */
133
	public function error( $error ) {
134
		if ( is_wp_error( $error ) ) {
135
			$this->feedback( $error );
136
		}
137
	}
138
139
	private function set_main_error_code( $code ) {
140
		// Don't set the process_failed as code since it is not that helpful unless we don't have one already set.
141
		$this->main_error_code = ( $code === 'process_failed' && $this->main_error_code  ? $this->main_error_code : $code );
142
	}
143
144
	private function set_main_error_message( $message, $code ) {
145
		// Don't set the process_failed as message since it is not that helpful unless we don't have one already set.
146
		$this->main_error_message = ( $code === 'process_failed' && $this->main_error_code ? $this->main_error_code : $message );
147
	}
148
149
	public function get_main_error_code() {
150
		return $this->main_error_code;
151
	}
152
153
	public function get_main_error_message() {
154
		return $this->main_error_message;
155
	}
156
157
	/**
158
	 * Overwrites the feedback function
159
	 */
160
	public function feedback( $data ) {
161
162
		$current_error = null;
163
		if ( is_wp_error( $data ) ) {
164
			$this->set_main_error_code( $data->get_error_code() );
165
			$string = $data->get_error_message();
166
		} elseif ( is_array( $data ) ) {
167
			return;
168
		} else {
169
			$string = $data;
170
		}
171
172
		if ( ! empty( $this->upgrader->strings[ $string ] ) ) {
173
			$this->set_main_error_code( $string );
174
175
			$current_error = $string;
176
			$string = $this->upgrader->strings[ $string ];
177
		}
178
179
		if ( strpos( $string, '%' ) !== false ) {
180
			$args = func_get_args();
181
			$args = array_splice( $args, 1 );
182
			if ( ! empty( $args ) )
183
				$string = vsprintf( $string, $args );
184
		}
185
186
		$string = trim( $string );
187
		$string = wp_kses( $string, array(
188
			'a' => array(
189
				'href' => true
190
			),
191
			'br' => true,
192
			'em' => true,
193
			'strong' => true,
194
		) );
195
196
		$this->set_main_error_message( $string, $current_error );
197
		$this->messages[] = $string;
198
	}
199
}
200