Completed
Push — add/plugins-library ( 909406...f5194e )
by Bernhard
172:27 queued 155:32
created

Jetpack_Plugins::install_plugin()   D

Complexity

Conditions 9
Paths 20

Size

Total Lines 38
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 22
nc 20
nop 1
dl 0
loc 38
rs 4.909
c 0
b 0
f 0
1
<?php
2
/**
3
 * Plugins Library
4
 *
5
 * Helper functions for installing and activating plugins.
6
 *
7
 * Used by the REST API
8
 *
9
 * @autounit api plugins
10
 */
11
12
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
13
include_once ABSPATH . 'wp-admin/includes/file.php';
14
15
class Jetpack_Plugins {
16
17
	 /**
18
	 * Install a plugin.
19
	 *
20
	 * @since 5.8.0
21
	 *
22
	 * @param string $slug Plugin slug.
23
	 *
24
	 * @return bool|WP_Error True if installation succeeded, error object otherwise.
25
	 */
26
	public static function install_plugin( $slug ) {
27
		if ( is_multisite() && ! current_user_can( 'manage_network' ) ) {
28
			return new WP_Error( 'not_allowed', 'You are not allowed to install plugins on this site.' );
29
		}
30
31
		$skin     = new Jetpack_Automatic_Install_Skin();
32
		$upgrader = new Plugin_Upgrader( $skin );
33
		$zip_url  = self::generate_wordpress_org_plugin_download_link( $slug );
34
35
		$result = $upgrader->install( $zip_url );
36
37
    if ( is_wp_error( $result ) ) {
38
      return $result;
39
    }
40
41
    $plugin     = Jetpack_Plugins::get_plugin_id_by_slug( $slug );
42
    $error_code = 'install_error';
43
    if ( ! $plugin ) {
44
      $error = __( 'There was an error installing your plugin', 'jetpack' );
45
    }
46
47
    if ( ! $result ) {
48
      $error_code                         = $upgrader->skin->get_main_error_code();
49
      $message                            = $upgrader->skin->get_main_error_message();
50
      $error = $message ? $message : __( 'An unknown error occurred during installation', 'jetpack' );
51
    }
52
53
    if ( ! empty( $error ) ) {
54
			if ( 'download_failed' === $error_code ) {
55
				// For backwards compatibility: versions prior to 3.9 would return no_package instead of download_failed.
56
				$error_code = 'no_package';
57
			}
58
59
			return new WP_Error( $error_code, $error, 400 );
60
		}
61
62
    return (array) $upgrader->skin->get_upgrade_messages();
63
	}
64
65
	 protected static function generate_wordpress_org_plugin_download_link( $plugin_slug ) {
66
		return "https://downloads.wordpress.org/plugin/{$plugin_slug}.latest-stable.zip";
67
	 }
68
69
	 public static function get_plugin_id_by_slug( $slug ) {
70
		/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
71
		$plugins = apply_filters( 'all_plugins', get_plugins() );
72
		if ( ! is_array( $plugins ) ) {
73
			return false;
74
		}
75
		foreach ( $plugins as $plugin_file => $plugin_data ) {
76
			if ( self::get_slug_from_file_path( $plugin_file ) === $slug ) {
77
				return $plugin_file;
78
			}
79
		}
80
81
		return false;
82
	}
83
84
	protected static function get_slug_from_file_path( $plugin_file ) {
85
		// Similar to get_plugin_slug() method.
86
		$slug = dirname( $plugin_file );
87
		if ( '.' === $slug ) {
88
			$slug = preg_replace( "/(.+)\.php$/", "$1", $plugin_file );
89
		}
90
91
		return $slug;
92
	}
93
}
94
95
/**
96
 * Allows us to capture that the site doesn't have proper file system access.
97
 * In order to update the plugin.
98
 */
99
class Jetpack_Automatic_Install_Skin extends Automatic_Upgrader_Skin {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
100
	/**
101
	 * Stores the last error key;
102
	 **/
103
	protected $main_error_code = 'install_error';
104
105
	/**
106
	 * Stores the last error message.
107
	 **/
108
	protected $main_error_message = 'An unknown error occurred during installation';
109
110
	/**
111
	 * Overwrites the set_upgrader to be able to tell if we e ven have the ability to write to the files.
112
	 *
113
	 * @param WP_Upgrader $upgrader
114
	 *
115
	 */
116
	public function set_upgrader( &$upgrader ) {
117
		parent::set_upgrader( $upgrader );
118
119
		// Check if we even have permission to.
120
		$result = $upgrader->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
121
		if ( ! $result ) {
122
			// set the string here since they are not available just yet
123
			$upgrader->generic_strings();
124
			$this->feedback( 'fs_unavailable' );
125
		}
126
	}
127
128
	/**
129
	 * Overwrites the error function
130
	 */
131
	public function error( $error ) {
132
		if ( is_wp_error( $error ) ) {
133
			$this->feedback( $error );
134
		}
135
	}
136
137
	private function set_main_error_code( $code ) {
138
		// Don't set the process_failed as code since it is not that helpful unless we don't have one already set.
139
		$this->main_error_code = ( $code === 'process_failed' && $this->main_error_code ? $this->main_error_code : $code );
140
	}
141
142
	private function set_main_error_message( $message, $code ) {
143
		// Don't set the process_failed as message since it is not that helpful unless we don't have one already set.
144
		$this->main_error_message = ( $code === 'process_failed' && $this->main_error_code ? $this->main_error_code : $message );
145
	}
146
147
	public function get_main_error_code() {
148
		return $this->main_error_code;
149
	}
150
151
	public function get_main_error_message() {
152
		return $this->main_error_message;
153
	}
154
155
	/**
156
	 * Overwrites the feedback function
157
	 */
158
	public function feedback( $data ) {
159
160
		$current_error = null;
161
		if ( is_wp_error( $data ) ) {
162
			$this->set_main_error_code( $data->get_error_code() );
163
			$string = $data->get_error_message();
164
		} elseif ( is_array( $data ) ) {
165
			return;
166
		} else {
167
			$string = $data;
168
		}
169
170
		if ( ! empty( $this->upgrader->strings[$string] ) ) {
171
			$this->set_main_error_code( $string );
172
173
			$current_error = $string;
174
			$string        = $this->upgrader->strings[$string];
175
		}
176
177
		if ( strpos( $string, '%' ) !== false ) {
178
			$args = func_get_args();
179
			$args = array_splice( $args, 1 );
180
			if ( ! empty( $args ) ) {
181
				$string = vsprintf( $string, $args );
182
			}
183
		}
184
185
		$string = trim( $string );
186
		$string = wp_kses(
187
			$string, array(
188
			'a'      => array(
189
				'href' => true
190
			),
191
			'br'     => true,
192
			'em'     => true,
193
			'strong' => true,
194
		)
195
		);
196
197
		$this->set_main_error_message( $string, $current_error );
198
		$this->messages[] = $string;
199
	}
200
}
201