summaryrefslogtreecommitdiff
blob: 328919f972c27a21475dbb583a7f14b7aa929086 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<?php

include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
include_once ABSPATH . 'wp-admin/includes/file.php';

class Jetpack_JSON_API_Plugins_Install_Endpoint extends Jetpack_JSON_API_Plugins_Endpoint {

	// POST /sites/%s/plugins/%s/install
	protected $needed_capabilities = 'install_plugins';
	protected $action              = 'install';

	protected function install() {
		foreach ( $this->plugins as $index => $slug ) {

			$skin      = new Jetpack_Automatic_Plugin_Install_Skin();
			$upgrader  = new Plugin_Upgrader( $skin );
			$zip_url   = self::generate_wordpress_org_plugin_download_link( $slug );

			$result = $upgrader->install( $zip_url );

			if ( ! $this->bulk && is_wp_error( $result ) ) {
				return $result;
			}

			$plugin = self::get_plugin_id_by_slug( $slug );
			$error_code = 'install_error';
			if ( ! $plugin ) {
				$error = $this->log[ $slug ]['error'] = __( 'There was an error installing your plugin', 'jetpack' );
			}

			if ( ! $this->bulk && ! $result ) {
				$error_code = $upgrader->skin->get_main_error_code();
				$message = $upgrader->skin->get_main_error_message();
				$error = $this->log[ $slug ]['error'] = $message ? $message : __( 'An unknown error occurred during installation' , 'jetpack' );
			}

			$this->log[ $plugin ][] = $upgrader->skin->get_upgrade_messages();
		}

		if ( ! $this->bulk && isset( $error ) ) {

			if ( 'download_failed' === $error_code ) {
				// For backwards compatibility: versions prior to 3.9 would return no_package instead of download_failed.
				$error_code = 'no_package';
			}

			return new WP_Error( $error_code, $this->log[ $slug ]['error'], 400 );
		}

		// replace the slug with the actual plugin id
		$this->plugins[ $index ] = $plugin;

		return true;
	}

	protected function validate_plugins() {
		if ( empty( $this->plugins ) || ! is_array( $this->plugins ) ) {
			return new WP_Error( 'missing_plugins', __( 'No plugins found.', 'jetpack' ) );
		}
		foreach( $this->plugins as $index => $slug ) {
			// make sure it is not already installed
			if ( self::get_plugin_id_by_slug( $slug ) ) {
				return new WP_Error( 'plugin_already_installed', __( 'The plugin is already installed', 'jetpack' ) );
			}

		}
		return true;
	}

	protected static function generate_wordpress_org_plugin_download_link( $plugin_slug ) {
		return "https://downloads.wordpress.org/plugin/{$plugin_slug}.latest-stable.zip";
	}

	protected static function get_plugin_id_by_slug( $slug ) {
		/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
		$plugins = apply_filters( 'all_plugins', get_plugins() );
		if ( ! is_array( $plugins ) ) {
			return false;
		}
		foreach( $plugins as $plugin_file => $plugin_data ) {
			if ( self::get_slug_from_file_path( $plugin_file ) === $slug ) {
				return $plugin_file;
			}
		}
		return false;
	}

	protected static function get_slug_from_file_path( $plugin_file ) {
		// Simular to get_plugin_slug() method.
		$slug = dirname( $plugin_file );
		if ( '.' === $slug ) {
			$slug = preg_replace("/(.+)\.php$/", "$1", $plugin_file );
		}
		return $slug;
	}
}
/**
 * Allows us to capture that the site doesn't have proper file system access.
 * In order to update the plugin.
 */
class Jetpack_Automatic_Plugin_Install_Skin extends Automatic_Upgrader_Skin {
	/**
	 * Stores the last error key;
	 **/
	protected $main_error_code = 'install_error';

	/**
	 * Stores the last error message.
	 **/
	protected $main_error_message = 'An unknown error occurred during installation';

	/**
	 * Overwrites the set_upgrader to be able to tell if we e ven have the ability to write to the files.
	 *
	 * @param WP_Upgrader $upgrader
	 *
	 */
	public function set_upgrader( &$upgrader ) {
		parent::set_upgrader( $upgrader );

		// Check if we even have permission to.
		$result = $upgrader->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
		if ( ! $result ) {
			// set the string here since they are not available just yet
			$upgrader->generic_strings();
			$this->feedback( 'fs_unavailable' );
		}
	}

	/**
	 * Overwrites the error function
	 */
	public function error( $error ) {
		if ( is_wp_error( $error ) ) {
			$this->feedback( $error );
		}
	}

	private function set_main_error_code( $code ) {
		// Don't set the process_failed as code since it is not that helpful unless we don't have one already set.
		$this->main_error_code = ( $code === 'process_failed' && $this->main_error_code  ? $this->main_error_code : $code );
	}

	private function set_main_error_message( $message, $code ) {
		// Don't set the process_failed as message since it is not that helpful unless we don't have one already set.
		$this->main_error_message = ( $code === 'process_failed' && $this->main_error_code ? $this->main_error_code : $message );
	}

	public function get_main_error_code() {
		return $this->main_error_code;
	}

	public function get_main_error_message() {
		return $this->main_error_message;
	}

	/**
	 * Overwrites the feedback function
	 */
	public function feedback( $data ) {

		$current_error = null;
		if ( is_wp_error( $data ) ) {
			$this->set_main_error_code( $data->get_error_code() );
			$string = $data->get_error_message();
		} elseif ( is_array( $data ) ) {
			return;
		} else {
			$string = $data;
		}

		if ( ! empty( $this->upgrader->strings[ $string ] ) ) {
			$this->set_main_error_code( $string );

			$current_error = $string;
			$string = $this->upgrader->strings[ $string ];
		}

		if ( strpos( $string, '%' ) !== false ) {
			$args = func_get_args();
			$args = array_splice( $args, 1 );
			if ( ! empty( $args ) )
				$string = vsprintf( $string, $args );
		}

		$string = trim( $string );
		$string = wp_kses( $string, array(
			'a' => array(
				'href' => true
			),
			'br' => true,
			'em' => true,
			'strong' => true,
		) );

		$this->set_main_error_message( $string, $current_error );
		$this->messages[] = $string;
	}
}