Completed
Push — update/base-styles-210 ( 2e278b...ad767b )
by Jeremy
22:25 queued 13:15
created

Jetpack_Plugins::get_plugin_status()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 1
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
1
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
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
require_once 'class.jetpack-automatic-install-skin.php';
13
14
/**
15
 * Plugins management tools.
16
 */
17
class Jetpack_Plugins {
18
19
	/**
20
	 * Install and activate a plugin.
21
	 *
22
	 * @since 5.8.0
23
	 *
24
	 * @param string $slug Plugin slug.
25
	 *
26
	 * @return bool|WP_Error True if installation succeeded, error object otherwise.
27
	 */
28
	public static function install_and_activate_plugin( $slug ) {
29
		$plugin_id = self::get_plugin_id_by_slug( $slug );
30
31
		if ( ! $plugin_id ) {
32
			$installed = self::install_plugin( $slug );
33
			if ( is_wp_error( $installed ) ) {
34
				return $installed;
35
			}
36
			$plugin_id = self::get_plugin_id_by_slug( $slug );
37
		} elseif ( is_plugin_active( $plugin_id ) ) {
38
			return true; // Already installed and active.
39
		}
40
41
		if ( ! current_user_can( 'activate_plugins' ) ) {
42
			return new WP_Error( 'not_allowed', __( 'You are not allowed to activate plugins on this site.', 'jetpack' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'not_allowed'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
43
		}
44
45
		$activated = activate_plugin( $plugin_id );
46
		if ( is_wp_error( $activated ) ) {
47
			return $activated;
48
		}
49
50
		return true;
51
	}
52
53
	/**
54
	 * Install a plugin.
55
	 *
56
	 * @since 5.8.0
57
	 *
58
	 * @param string $slug Plugin slug.
59
	 *
60
	 * @return bool|WP_Error True if installation succeeded, error object otherwise.
61
	 */
62
	public static function install_plugin( $slug ) {
63
		if ( is_multisite() && ! current_user_can( 'manage_network' ) ) {
64
			return new WP_Error( 'not_allowed', __( 'You are not allowed to install plugins on this site.', 'jetpack' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'not_allowed'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
65
		}
66
67
		$skin     = new Jetpack_Automatic_Install_Skin();
68
		$upgrader = new Plugin_Upgrader( $skin );
69
		$zip_url  = self::generate_wordpress_org_plugin_download_link( $slug );
70
71
		$result = $upgrader->install( $zip_url );
72
73
		if ( is_wp_error( $result ) ) {
74
			return $result;
75
		}
76
77
		$plugin     = self::get_plugin_id_by_slug( $slug );
78
		$error_code = 'install_error';
79
		if ( ! $plugin ) {
80
			$error = __( 'There was an error installing your plugin', 'jetpack' );
81
		}
82
83
		if ( ! $result ) {
84
			$error_code = $upgrader->skin->get_main_error_code();
85
			$message    = $upgrader->skin->get_main_error_message();
86
			$error      = $message ? $message : __( 'An unknown error occurred during installation', 'jetpack' );
87
		}
88
89
		if ( ! empty( $error ) ) {
90
			if ( 'download_failed' === $error_code ) {
91
				// For backwards compatibility: versions prior to 3.9 would return no_package instead of download_failed.
92
				$error_code = 'no_package';
93
			}
94
95
			return new WP_Error( $error_code, $error, 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with $error_code.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
96
		}
97
98
		return (array) $upgrader->skin->get_upgrade_messages();
99
	}
100
101
	/**
102
	 * Get WordPress.org zip download link from a plugin slug
103
	 *
104
	 * @param string $plugin_slug Plugin slug.
105
	 */
106
	protected static function generate_wordpress_org_plugin_download_link( $plugin_slug ) {
107
		return "https://downloads.wordpress.org/plugin/$plugin_slug.latest-stable.zip";
108
	}
109
110
	/**
111
	 * Get the plugin ID (composed of the plugin slug and the name of the main plugin file) from a plugin slug.
112
	 *
113
	 * @param string $slug Plugin slug.
114
	 */
115
	public static function get_plugin_id_by_slug( $slug ) {
116
		// Check if get_plugins() function exists. This is required on the front end of the
117
		// site, since it is in a file that is normally only loaded in the admin.
118
		if ( ! function_exists( 'get_plugins' ) ) {
119
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
120
		}
121
122
		/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
123
		$plugins = apply_filters( 'all_plugins', get_plugins() );
124
		if ( ! is_array( $plugins ) ) {
125
			return false;
126
		}
127
128
		foreach ( $plugins as $plugin_file => $plugin_data ) {
129
			if ( self::get_slug_from_file_path( $plugin_file ) === $slug ) {
130
				return $plugin_file;
131
			}
132
		}
133
134
		return false;
135
	}
136
137
	/**
138
	 * Get the plugin slug from the plugin ID (composed of the plugin slug and the name of the main plugin file)
139
	 *
140
	 * @param string $plugin_file Plugin file (ID -- e.g. hello-dolly/hello.php).
141
	 */
142
	protected static function get_slug_from_file_path( $plugin_file ) {
143
		// Similar to get_plugin_slug() method.
144
		$slug = dirname( $plugin_file );
145
		if ( '.' === $slug ) {
146
			$slug = preg_replace( '/(.+)\.php$/', '$1', $plugin_file );
147
		}
148
149
		return $slug;
150
	}
151
152
	/**
153
	 * Get the activation status for a plugin.
154
	 *
155
	 * @since 8.9.0
156
	 *
157
	 * @param string $plugin_file The plugin file to check.
158
	 * @return string Either 'network-active', 'active' or 'inactive'.
159
	 */
160
	public static function get_plugin_status( $plugin_file ) {
161
		if ( is_plugin_active_for_network( $plugin_file ) ) {
162
			return 'network-active';
163
		}
164
165
		if ( is_plugin_active( $plugin_file ) ) {
166
			return 'active';
167
		}
168
169
		return 'inactive';
170
	}
171
172
	/**
173
	 * Returns a list of all plugins in the site.
174
	 *
175
	 * @since 8.9.0
176
	 * @uses get_plugins()
177
	 *
178
	 * @return array
179
	 */
180
	public static function get_plugins() {
181
		if ( ! function_exists( 'get_plugins' ) ) {
182
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
183
		}
184
		/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
185
		$plugins = apply_filters( 'all_plugins', get_plugins() );
186
187
		if ( is_array( $plugins ) && ! empty( $plugins ) ) {
188
			foreach ( $plugins as $plugin_slug => $plugin_data ) {
189
				$plugins[ $plugin_slug ]['active'] = in_array(
190
					self::get_plugin_status( $plugin_slug ),
191
					array( 'active', 'network-active' ),
192
					true
193
				);
194
			}
195
			return $plugins;
196
		}
197
198
		return array();
199
	}
200
}
201