changeset 9 | 177826044cd9 |
parent 7 | cf61fcea0001 |
child 16 | a86126ab1dd4 |
8:c7c34916027a | 9:177826044cd9 |
---|---|
20 * Description: Plugin Description |
20 * Description: Plugin Description |
21 * Author: Plugin author's name |
21 * Author: Plugin author's name |
22 * Author URI: Link to the author's web site |
22 * Author URI: Link to the author's web site |
23 * Version: Must be set in the plugin for WordPress 2.3+ |
23 * Version: Must be set in the plugin for WordPress 2.3+ |
24 * Text Domain: Optional. Unique identifier, should be same as the one used in |
24 * Text Domain: Optional. Unique identifier, should be same as the one used in |
25 * load_plugin_textdomain() |
25 * load_plugin_textdomain() |
26 * Domain Path: Optional. Only useful if the translations are located in a |
26 * Domain Path: Optional. Only useful if the translations are located in a |
27 * folder above the plugin's base path. For example, if .mo files are |
27 * folder above the plugin's base path. For example, if .mo files are |
28 * located in the locale folder then Domain Path will be "/locale/" and |
28 * located in the locale folder then Domain Path will be "/locale/" and |
29 * must have the first slash. Defaults to the base folder the plugin is |
29 * must have the first slash. Defaults to the base folder the plugin is |
30 * located in. |
30 * located in. |
31 * Network: Optional. Specify "Network: true" to require that a plugin is activated |
31 * Network: Optional. Specify "Network: true" to require that a plugin is activated |
32 * across all sites in an installation. This will prevent a plugin from being |
32 * across all sites in an installation. This will prevent a plugin from being |
33 * activated on a single site when Multisite is enabled. |
33 * activated on a single site when Multisite is enabled. |
34 * * / # Remove the space to close comment |
34 * * / # Remove the space to close comment |
35 * |
35 * |
36 * Some users have issues with opening large files and manipulating the contents |
36 * Some users have issues with opening large files and manipulating the contents |
37 * for want is usually the first 1kiB or 2kiB. This function stops pulling in |
37 * for want is usually the first 1kiB or 2kiB. This function stops pulling in |
38 * the plugin contents when it has all of the required plugin data. |
38 * the plugin contents when it has all of the required plugin data. |
45 * the file. This is not checked however and the file is only opened for |
45 * the file. This is not checked however and the file is only opened for |
46 * reading. |
46 * reading. |
47 * |
47 * |
48 * @since 1.5.0 |
48 * @since 1.5.0 |
49 * |
49 * |
50 * @param string $plugin_file Path to the main plugin file. |
50 * @param string $plugin_file Absolute path to the main plugin file. |
51 * @param bool $markup Optional. If the returned data should have HTML markup applied. |
51 * @param bool $markup Optional. If the returned data should have HTML markup applied. |
52 * Default true. |
52 * Default true. |
53 * @param bool $translate Optional. If the returned data should be translated. Default true. |
53 * @param bool $translate Optional. If the returned data should be translated. Default true. |
54 * @return array { |
54 * @return array { |
55 * Plugin data. Values will be empty if not supplied by the plugin. |
55 * Plugin data. Values will be empty if not supplied by the plugin. |
66 * } |
66 * } |
67 */ |
67 */ |
68 function get_plugin_data( $plugin_file, $markup = true, $translate = true ) { |
68 function get_plugin_data( $plugin_file, $markup = true, $translate = true ) { |
69 |
69 |
70 $default_headers = array( |
70 $default_headers = array( |
71 'Name' => 'Plugin Name', |
71 'Name' => 'Plugin Name', |
72 'PluginURI' => 'Plugin URI', |
72 'PluginURI' => 'Plugin URI', |
73 'Version' => 'Version', |
73 'Version' => 'Version', |
74 'Description' => 'Description', |
74 'Description' => 'Description', |
75 'Author' => 'Author', |
75 'Author' => 'Author', |
76 'AuthorURI' => 'Author URI', |
76 'AuthorURI' => 'Author URI', |
77 'TextDomain' => 'Text Domain', |
77 'TextDomain' => 'Text Domain', |
78 'DomainPath' => 'Domain Path', |
78 'DomainPath' => 'Domain Path', |
79 'Network' => 'Network', |
79 'Network' => 'Network', |
80 // Site Wide Only is deprecated in favor of Network. |
80 // Site Wide Only is deprecated in favor of Network. |
81 '_sitewide' => 'Site Wide Only', |
81 '_sitewide' => 'Site Wide Only', |
82 ); |
82 ); |
83 |
83 |
84 $plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' ); |
84 $plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' ); |
85 |
85 |
86 // Site Wide Only is the old header for Network |
86 // Site Wide Only is the old header for Network |
112 |
112 |
113 /** |
113 /** |
114 * Sanitizes plugin data, optionally adds markup, optionally translates. |
114 * Sanitizes plugin data, optionally adds markup, optionally translates. |
115 * |
115 * |
116 * @since 2.7.0 |
116 * @since 2.7.0 |
117 * |
|
118 * @see get_plugin_data() |
|
119 * |
|
117 * @access private |
120 * @access private |
118 * @see get_plugin_data() |
121 * |
122 * @param string $plugin_file Path to the main plugin file. |
|
123 * @param array $plugin_data An array of plugin data. See `get_plugin_data()`. |
|
124 * @param bool $markup Optional. If the returned data should have HTML markup applied. |
|
125 * Default true. |
|
126 * @param bool $translate Optional. If the returned data should be translated. Default true. |
|
127 * @return array { |
|
128 * Plugin data. Values will be empty if not supplied by the plugin. |
|
129 * |
|
130 * @type string $Name Name of the plugin. Should be unique. |
|
131 * @type string $Title Title of the plugin and link to the plugin's site (if set). |
|
132 * @type string $Description Plugin description. |
|
133 * @type string $Author Author's name. |
|
134 * @type string $AuthorURI Author's website address (if set). |
|
135 * @type string $Version Plugin version. |
|
136 * @type string $TextDomain Plugin textdomain. |
|
137 * @type string $DomainPath Plugins relative directory path to .mo files. |
|
138 * @type bool $Network Whether the plugin can only be activated network-wide. |
|
139 * } |
|
119 */ |
140 */ |
120 function _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup = true, $translate = true ) { |
141 function _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup = true, $translate = true ) { |
121 |
142 |
122 // Sanitize the plugin filename to a WP_PLUGIN_DIR relative path |
143 // Sanitize the plugin filename to a WP_PLUGIN_DIR relative path |
123 $plugin_file = plugin_basename( $plugin_file ); |
144 $plugin_file = plugin_basename( $plugin_file ); |
134 } |
155 } |
135 } elseif ( 'hello.php' == basename( $plugin_file ) ) { |
156 } elseif ( 'hello.php' == basename( $plugin_file ) ) { |
136 $textdomain = 'default'; |
157 $textdomain = 'default'; |
137 } |
158 } |
138 if ( $textdomain ) { |
159 if ( $textdomain ) { |
139 foreach ( array( 'Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version' ) as $field ) |
160 foreach ( array( 'Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version' ) as $field ) { |
161 // phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain |
|
140 $plugin_data[ $field ] = translate( $plugin_data[ $field ], $textdomain ); |
162 $plugin_data[ $field ] = translate( $plugin_data[ $field ], $textdomain ); |
163 } |
|
141 } |
164 } |
142 } |
165 } |
143 |
166 |
144 // Sanitize fields |
167 // Sanitize fields |
145 $allowed_tags = $allowed_tags_in_links = array( |
168 $allowed_tags_in_links = array( |
146 'abbr' => array( 'title' => true ), |
169 'abbr' => array( 'title' => true ), |
147 'acronym' => array( 'title' => true ), |
170 'acronym' => array( 'title' => true ), |
148 'code' => true, |
171 'code' => true, |
149 'em' => true, |
172 'em' => true, |
150 'strong' => true, |
173 'strong' => true, |
151 ); |
174 ); |
152 $allowed_tags['a'] = array( 'href' => true, 'title' => true ); |
175 |
176 $allowed_tags = $allowed_tags_in_links; |
|
177 $allowed_tags['a'] = array( |
|
178 'href' => true, |
|
179 'title' => true, |
|
180 ); |
|
153 |
181 |
154 // Name is marked up inside <a> tags. Don't allow these. |
182 // Name is marked up inside <a> tags. Don't allow these. |
155 // Author is too, but some plugins have used <a> here (omitting Author URI). |
183 // Author is too, but some plugins have used <a> here (omitting Author URI). |
156 $plugin_data['Name'] = wp_kses( $plugin_data['Name'], $allowed_tags_in_links ); |
184 $plugin_data['Name'] = wp_kses( $plugin_data['Name'], $allowed_tags_in_links ); |
157 $plugin_data['Author'] = wp_kses( $plugin_data['Author'], $allowed_tags ); |
185 $plugin_data['Author'] = wp_kses( $plugin_data['Author'], $allowed_tags ); |
158 |
186 |
159 $plugin_data['Description'] = wp_kses( $plugin_data['Description'], $allowed_tags ); |
187 $plugin_data['Description'] = wp_kses( $plugin_data['Description'], $allowed_tags ); |
160 $plugin_data['Version'] = wp_kses( $plugin_data['Version'], $allowed_tags ); |
188 $plugin_data['Version'] = wp_kses( $plugin_data['Version'], $allowed_tags ); |
161 |
189 |
162 $plugin_data['PluginURI'] = esc_url( $plugin_data['PluginURI'] ); |
190 $plugin_data['PluginURI'] = esc_url( $plugin_data['PluginURI'] ); |
163 $plugin_data['AuthorURI'] = esc_url( $plugin_data['AuthorURI'] ); |
191 $plugin_data['AuthorURI'] = esc_url( $plugin_data['AuthorURI'] ); |
164 |
192 |
165 $plugin_data['Title'] = $plugin_data['Name']; |
193 $plugin_data['Title'] = $plugin_data['Name']; |
166 $plugin_data['AuthorName'] = $plugin_data['Author']; |
194 $plugin_data['AuthorName'] = $plugin_data['Author']; |
167 |
195 |
168 // Apply markup |
196 // Apply markup |
169 if ( $markup ) { |
197 if ( $markup ) { |
170 if ( $plugin_data['PluginURI'] && $plugin_data['Name'] ) |
198 if ( $plugin_data['PluginURI'] && $plugin_data['Name'] ) { |
171 $plugin_data['Title'] = '<a href="' . $plugin_data['PluginURI'] . '">' . $plugin_data['Name'] . '</a>'; |
199 $plugin_data['Title'] = '<a href="' . $plugin_data['PluginURI'] . '">' . $plugin_data['Name'] . '</a>'; |
172 |
200 } |
173 if ( $plugin_data['AuthorURI'] && $plugin_data['Author'] ) |
201 |
202 if ( $plugin_data['AuthorURI'] && $plugin_data['Author'] ) { |
|
174 $plugin_data['Author'] = '<a href="' . $plugin_data['AuthorURI'] . '">' . $plugin_data['Author'] . '</a>'; |
203 $plugin_data['Author'] = '<a href="' . $plugin_data['AuthorURI'] . '">' . $plugin_data['Author'] . '</a>'; |
204 } |
|
175 |
205 |
176 $plugin_data['Description'] = wptexturize( $plugin_data['Description'] ); |
206 $plugin_data['Description'] = wptexturize( $plugin_data['Description'] ); |
177 |
207 |
178 if ( $plugin_data['Author'] ) |
208 if ( $plugin_data['Author'] ) { |
179 $plugin_data['Description'] .= ' <cite>' . sprintf( __('By %s.'), $plugin_data['Author'] ) . '</cite>'; |
209 $plugin_data['Description'] .= ' <cite>' . sprintf( __( 'By %s.' ), $plugin_data['Author'] ) . '</cite>'; |
210 } |
|
180 } |
211 } |
181 |
212 |
182 return $plugin_data; |
213 return $plugin_data; |
183 } |
214 } |
184 |
215 |
185 /** |
216 /** |
186 * Get a list of a plugin's files. |
217 * Get a list of a plugin's files. |
187 * |
218 * |
188 * @since 2.8.0 |
219 * @since 2.8.0 |
189 * |
220 * |
190 * @param string $plugin Path to the main plugin file from plugins directory. |
221 * @param string $plugin Path to the plugin file relative to the plugins directory. |
191 * @return array List of files relative to the plugin root. |
222 * @return array List of files relative to the plugin root. |
192 */ |
223 */ |
193 function get_plugin_files( $plugin ) { |
224 function get_plugin_files( $plugin ) { |
194 $plugin_file = WP_PLUGIN_DIR . '/' . $plugin; |
225 $plugin_file = WP_PLUGIN_DIR . '/' . $plugin; |
195 $dir = dirname( $plugin_file ); |
226 $dir = dirname( $plugin_file ); |
196 |
227 |
197 $plugin_files = array( plugin_basename( $plugin_file ) ); |
228 $plugin_files = array( plugin_basename( $plugin_file ) ); |
198 |
229 |
199 if ( is_dir( $dir ) && WP_PLUGIN_DIR !== $dir ) { |
230 if ( is_dir( $dir ) && WP_PLUGIN_DIR !== $dir ) { |
200 |
231 |
201 /** |
232 /** |
202 * Filters the array of excluded directories and files while scanning the folder. |
233 * Filters the array of excluded directories and files while scanning the folder. |
203 * |
234 * |
204 * @since 4.9.0 |
235 * @since 4.9.0 |
205 * |
236 * |
206 * @param array $exclusions Array of excluded directories and files. |
237 * @param string[] $exclusions Array of excluded directories and files. |
207 */ |
238 */ |
208 $exclusions = (array) apply_filters( 'plugin_files_exclusions', array( 'CVS', 'node_modules', 'vendor', 'bower_components' ) ); |
239 $exclusions = (array) apply_filters( 'plugin_files_exclusions', array( 'CVS', 'node_modules', 'vendor', 'bower_components' ) ); |
209 |
240 |
210 $list_files = list_files( $dir, 100, $exclusions ); |
241 $list_files = list_files( $dir, 100, $exclusions ); |
211 $list_files = array_map( 'plugin_basename', $list_files ); |
242 $list_files = array_map( 'plugin_basename', $list_files ); |
235 * @since 1.5.0 |
266 * @since 1.5.0 |
236 * |
267 * |
237 * @param string $plugin_folder Optional. Relative path to single plugin folder. |
268 * @param string $plugin_folder Optional. Relative path to single plugin folder. |
238 * @return array Key is the plugin file path and the value is an array of the plugin data. |
269 * @return array Key is the plugin file path and the value is an array of the plugin data. |
239 */ |
270 */ |
240 function get_plugins($plugin_folder = '') { |
271 function get_plugins( $plugin_folder = '' ) { |
241 |
272 |
242 if ( ! $cache_plugins = wp_cache_get('plugins', 'plugins') ) |
273 $cache_plugins = wp_cache_get( 'plugins', 'plugins' ); |
274 if ( ! $cache_plugins ) { |
|
243 $cache_plugins = array(); |
275 $cache_plugins = array(); |
244 |
276 } |
245 if ( isset($cache_plugins[ $plugin_folder ]) ) |
277 |
278 if ( isset( $cache_plugins[ $plugin_folder ] ) ) { |
|
246 return $cache_plugins[ $plugin_folder ]; |
279 return $cache_plugins[ $plugin_folder ]; |
247 |
280 } |
248 $wp_plugins = array (); |
281 |
282 $wp_plugins = array(); |
|
249 $plugin_root = WP_PLUGIN_DIR; |
283 $plugin_root = WP_PLUGIN_DIR; |
250 if ( !empty($plugin_folder) ) |
284 if ( ! empty( $plugin_folder ) ) { |
251 $plugin_root .= $plugin_folder; |
285 $plugin_root .= $plugin_folder; |
286 } |
|
252 |
287 |
253 // Files in wp-content/plugins directory |
288 // Files in wp-content/plugins directory |
254 $plugins_dir = @ opendir( $plugin_root); |
289 $plugins_dir = @ opendir( $plugin_root ); |
255 $plugin_files = array(); |
290 $plugin_files = array(); |
256 if ( $plugins_dir ) { |
291 if ( $plugins_dir ) { |
257 while (($file = readdir( $plugins_dir ) ) !== false ) { |
292 while ( ( $file = readdir( $plugins_dir ) ) !== false ) { |
258 if ( substr($file, 0, 1) == '.' ) |
293 if ( substr( $file, 0, 1 ) == '.' ) { |
259 continue; |
294 continue; |
260 if ( is_dir( $plugin_root.'/'.$file ) ) { |
295 } |
261 $plugins_subdir = @ opendir( $plugin_root.'/'.$file ); |
296 if ( is_dir( $plugin_root . '/' . $file ) ) { |
297 $plugins_subdir = @ opendir( $plugin_root . '/' . $file ); |
|
262 if ( $plugins_subdir ) { |
298 if ( $plugins_subdir ) { |
263 while (($subfile = readdir( $plugins_subdir ) ) !== false ) { |
299 while ( ( $subfile = readdir( $plugins_subdir ) ) !== false ) { |
264 if ( substr($subfile, 0, 1) == '.' ) |
300 if ( substr( $subfile, 0, 1 ) == '.' ) { |
265 continue; |
301 continue; |
266 if ( substr($subfile, -4) == '.php' ) |
302 } |
303 if ( substr( $subfile, -4 ) == '.php' ) { |
|
267 $plugin_files[] = "$file/$subfile"; |
304 $plugin_files[] = "$file/$subfile"; |
305 } |
|
268 } |
306 } |
269 closedir( $plugins_subdir ); |
307 closedir( $plugins_subdir ); |
270 } |
308 } |
271 } else { |
309 } else { |
272 if ( substr($file, -4) == '.php' ) |
310 if ( substr( $file, -4 ) == '.php' ) { |
273 $plugin_files[] = $file; |
311 $plugin_files[] = $file; |
312 } |
|
274 } |
313 } |
275 } |
314 } |
276 closedir( $plugins_dir ); |
315 closedir( $plugins_dir ); |
277 } |
316 } |
278 |
317 |
279 if ( empty($plugin_files) ) |
318 if ( empty( $plugin_files ) ) { |
280 return $wp_plugins; |
319 return $wp_plugins; |
320 } |
|
281 |
321 |
282 foreach ( $plugin_files as $plugin_file ) { |
322 foreach ( $plugin_files as $plugin_file ) { |
283 if ( !is_readable( "$plugin_root/$plugin_file" ) ) |
323 if ( ! is_readable( "$plugin_root/$plugin_file" ) ) { |
284 continue; |
324 continue; |
325 } |
|
285 |
326 |
286 $plugin_data = get_plugin_data( "$plugin_root/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. |
327 $plugin_data = get_plugin_data( "$plugin_root/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. |
287 |
328 |
288 if ( empty ( $plugin_data['Name'] ) ) |
329 if ( empty( $plugin_data['Name'] ) ) { |
289 continue; |
330 continue; |
290 |
331 } |
291 $wp_plugins[plugin_basename( $plugin_file )] = $plugin_data; |
332 |
333 $wp_plugins[ plugin_basename( $plugin_file ) ] = $plugin_data; |
|
292 } |
334 } |
293 |
335 |
294 uasort( $wp_plugins, '_sort_uname_callback' ); |
336 uasort( $wp_plugins, '_sort_uname_callback' ); |
295 |
337 |
296 $cache_plugins[ $plugin_folder ] = $wp_plugins; |
338 $cache_plugins[ $plugin_folder ] = $wp_plugins; |
297 wp_cache_set('plugins', $cache_plugins, 'plugins'); |
339 wp_cache_set( 'plugins', $cache_plugins, 'plugins' ); |
298 |
340 |
299 return $wp_plugins; |
341 return $wp_plugins; |
300 } |
342 } |
301 |
343 |
302 /** |
344 /** |
310 function get_mu_plugins() { |
352 function get_mu_plugins() { |
311 $wp_plugins = array(); |
353 $wp_plugins = array(); |
312 // Files in wp-content/mu-plugins directory |
354 // Files in wp-content/mu-plugins directory |
313 $plugin_files = array(); |
355 $plugin_files = array(); |
314 |
356 |
315 if ( ! is_dir( WPMU_PLUGIN_DIR ) ) |
357 if ( ! is_dir( WPMU_PLUGIN_DIR ) ) { |
316 return $wp_plugins; |
358 return $wp_plugins; |
359 } |
|
317 if ( $plugins_dir = @ opendir( WPMU_PLUGIN_DIR ) ) { |
360 if ( $plugins_dir = @ opendir( WPMU_PLUGIN_DIR ) ) { |
318 while ( ( $file = readdir( $plugins_dir ) ) !== false ) { |
361 while ( ( $file = readdir( $plugins_dir ) ) !== false ) { |
319 if ( substr( $file, -4 ) == '.php' ) |
362 if ( substr( $file, -4 ) == '.php' ) { |
320 $plugin_files[] = $file; |
363 $plugin_files[] = $file; |
364 } |
|
321 } |
365 } |
322 } else { |
366 } else { |
323 return $wp_plugins; |
367 return $wp_plugins; |
324 } |
368 } |
325 |
369 |
326 @closedir( $plugins_dir ); |
370 @closedir( $plugins_dir ); |
327 |
371 |
328 if ( empty($plugin_files) ) |
372 if ( empty( $plugin_files ) ) { |
329 return $wp_plugins; |
373 return $wp_plugins; |
374 } |
|
330 |
375 |
331 foreach ( $plugin_files as $plugin_file ) { |
376 foreach ( $plugin_files as $plugin_file ) { |
332 if ( !is_readable( WPMU_PLUGIN_DIR . "/$plugin_file" ) ) |
377 if ( ! is_readable( WPMU_PLUGIN_DIR . "/$plugin_file" ) ) { |
333 continue; |
378 continue; |
379 } |
|
334 |
380 |
335 $plugin_data = get_plugin_data( WPMU_PLUGIN_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. |
381 $plugin_data = get_plugin_data( WPMU_PLUGIN_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. |
336 |
382 |
337 if ( empty ( $plugin_data['Name'] ) ) |
383 if ( empty( $plugin_data['Name'] ) ) { |
338 $plugin_data['Name'] = $plugin_file; |
384 $plugin_data['Name'] = $plugin_file; |
385 } |
|
339 |
386 |
340 $wp_plugins[ $plugin_file ] = $plugin_data; |
387 $wp_plugins[ $plugin_file ] = $plugin_data; |
341 } |
388 } |
342 |
389 |
343 if ( isset( $wp_plugins['index.php'] ) && filesize( WPMU_PLUGIN_DIR . '/index.php') <= 30 ) // silence is golden |
390 if ( isset( $wp_plugins['index.php'] ) && filesize( WPMU_PLUGIN_DIR . '/index.php' ) <= 30 ) { // silence is golden |
344 unset( $wp_plugins['index.php'] ); |
391 unset( $wp_plugins['index.php'] ); |
392 } |
|
345 |
393 |
346 uasort( $wp_plugins, '_sort_uname_callback' ); |
394 uasort( $wp_plugins, '_sort_uname_callback' ); |
347 |
395 |
348 return $wp_plugins; |
396 return $wp_plugins; |
349 } |
397 } |
350 |
398 |
351 /** |
399 /** |
352 * Callback to sort array by a 'Name' key. |
400 * Callback to sort array by a 'Name' key. |
353 * |
401 * |
354 * @since 3.1.0 |
402 * @since 3.1.0 |
403 * |
|
355 * @access private |
404 * @access private |
405 * |
|
406 * @param array $a array with 'Name' key. |
|
407 * @param array $b array with 'Name' key. |
|
408 * @return int Return 0 or 1 based on two string comparison. |
|
356 */ |
409 */ |
357 function _sort_uname_callback( $a, $b ) { |
410 function _sort_uname_callback( $a, $b ) { |
358 return strnatcasecmp( $a['Name'], $b['Name'] ); |
411 return strnatcasecmp( $a['Name'], $b['Name'] ); |
359 } |
412 } |
360 |
413 |
363 * |
416 * |
364 * @since 3.0.0 |
417 * @since 3.0.0 |
365 * @return array Key is the file path and the value is an array of the plugin data. |
418 * @return array Key is the file path and the value is an array of the plugin data. |
366 */ |
419 */ |
367 function get_dropins() { |
420 function get_dropins() { |
368 $dropins = array(); |
421 $dropins = array(); |
369 $plugin_files = array(); |
422 $plugin_files = array(); |
370 |
423 |
371 $_dropins = _get_dropins(); |
424 $_dropins = _get_dropins(); |
372 |
425 |
373 // These exist in the wp-content directory |
426 // These exist in the wp-content directory |
374 if ( $plugins_dir = @ opendir( WP_CONTENT_DIR ) ) { |
427 if ( $plugins_dir = @ opendir( WP_CONTENT_DIR ) ) { |
375 while ( ( $file = readdir( $plugins_dir ) ) !== false ) { |
428 while ( ( $file = readdir( $plugins_dir ) ) !== false ) { |
376 if ( isset( $_dropins[ $file ] ) ) |
429 if ( isset( $_dropins[ $file ] ) ) { |
377 $plugin_files[] = $file; |
430 $plugin_files[] = $file; |
431 } |
|
378 } |
432 } |
379 } else { |
433 } else { |
380 return $dropins; |
434 return $dropins; |
381 } |
435 } |
382 |
436 |
383 @closedir( $plugins_dir ); |
437 @closedir( $plugins_dir ); |
384 |
438 |
385 if ( empty($plugin_files) ) |
439 if ( empty( $plugin_files ) ) { |
386 return $dropins; |
440 return $dropins; |
441 } |
|
387 |
442 |
388 foreach ( $plugin_files as $plugin_file ) { |
443 foreach ( $plugin_files as $plugin_file ) { |
389 if ( !is_readable( WP_CONTENT_DIR . "/$plugin_file" ) ) |
444 if ( ! is_readable( WP_CONTENT_DIR . "/$plugin_file" ) ) { |
390 continue; |
445 continue; |
446 } |
|
391 $plugin_data = get_plugin_data( WP_CONTENT_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. |
447 $plugin_data = get_plugin_data( WP_CONTENT_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. |
392 if ( empty( $plugin_data['Name'] ) ) |
448 if ( empty( $plugin_data['Name'] ) ) { |
393 $plugin_data['Name'] = $plugin_file; |
449 $plugin_data['Name'] = $plugin_file; |
450 } |
|
394 $dropins[ $plugin_file ] = $plugin_data; |
451 $dropins[ $plugin_file ] = $plugin_data; |
395 } |
452 } |
396 |
453 |
397 uksort( $dropins, 'strnatcasecmp' ); |
454 uksort( $dropins, 'strnatcasecmp' ); |
398 |
455 |
404 * |
461 * |
405 * Includes Multisite drop-ins only when is_multisite() |
462 * Includes Multisite drop-ins only when is_multisite() |
406 * |
463 * |
407 * @since 3.0.0 |
464 * @since 3.0.0 |
408 * @return array Key is file name. The value is an array, with the first value the |
465 * @return array Key is file name. The value is an array, with the first value the |
409 * purpose of the drop-in and the second value the name of the constant that must be |
466 * purpose of the drop-in and the second value the name of the constant that must be |
410 * true for the drop-in to be used, or true if no constant is required. |
467 * true for the drop-in to be used, or true if no constant is required. |
411 */ |
468 */ |
412 function _get_dropins() { |
469 function _get_dropins() { |
413 $dropins = array( |
470 $dropins = array( |
414 'advanced-cache.php' => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ), // WP_CACHE |
471 'advanced-cache.php' => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ), // WP_CACHE |
415 'db.php' => array( __( 'Custom database class.' ), true ), // auto on load |
472 'db.php' => array( __( 'Custom database class.' ), true ), // auto on load |
416 'db-error.php' => array( __( 'Custom database error message.' ), true ), // auto on error |
473 'db-error.php' => array( __( 'Custom database error message.' ), true ), // auto on error |
417 'install.php' => array( __( 'Custom installation script.' ), true ), // auto on installation |
474 'install.php' => array( __( 'Custom installation script.' ), true ), // auto on installation |
418 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance |
475 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance |
419 'object-cache.php' => array( __( 'External object cache.' ), true ), // auto on load |
476 'object-cache.php' => array( __( 'External object cache.' ), true ), // auto on load |
477 'php-error.php' => array( __( 'Custom PHP error message.' ), true ), // auto on error |
|
478 'fatal-error-handler.php' => array( __( 'Custom PHP fatal error handler.' ), true ), // auto on error |
|
420 ); |
479 ); |
421 |
480 |
422 if ( is_multisite() ) { |
481 if ( is_multisite() ) { |
423 $dropins['sunrise.php' ] = array( __( 'Executed before Multisite is loaded.' ), 'SUNRISE' ); // SUNRISE |
482 $dropins['sunrise.php'] = array( __( 'Executed before Multisite is loaded.' ), 'SUNRISE' ); // SUNRISE |
424 $dropins['blog-deleted.php' ] = array( __( 'Custom site deleted message.' ), true ); // auto on deleted blog |
483 $dropins['blog-deleted.php'] = array( __( 'Custom site deleted message.' ), true ); // auto on deleted blog |
425 $dropins['blog-inactive.php' ] = array( __( 'Custom site inactive message.' ), true ); // auto on inactive blog |
484 $dropins['blog-inactive.php'] = array( __( 'Custom site inactive message.' ), true ); // auto on inactive blog |
426 $dropins['blog-suspended.php'] = array( __( 'Custom site suspended message.' ), true ); // auto on archived or spammed blog |
485 $dropins['blog-suspended.php'] = array( __( 'Custom site suspended message.' ), true ); // auto on archived or spammed blog |
427 } |
486 } |
428 |
487 |
429 return $dropins; |
488 return $dropins; |
430 } |
489 } |
431 |
490 |
432 /** |
491 /** |
433 * Check whether a plugin is active. |
492 * Determines whether a plugin is active. |
434 * |
493 * |
435 * Only plugins installed in the plugins/ folder can be active. |
494 * Only plugins installed in the plugins/ folder can be active. |
436 * |
495 * |
437 * Plugins in the mu-plugins/ folder can't be "activated," so this function will |
496 * Plugins in the mu-plugins/ folder can't be "activated," so this function will |
438 * return false for those plugins. |
497 * return false for those plugins. |
439 * |
498 * |
499 * For more information on this and similar theme functions, check out |
|
500 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ |
|
501 * Conditional Tags} article in the Theme Developer Handbook. |
|
502 * |
|
440 * @since 2.5.0 |
503 * @since 2.5.0 |
441 * |
504 * |
442 * @param string $plugin Path to the main plugin file from plugins directory. |
505 * @param string $plugin Path to the plugin file relative to the plugins directory. |
443 * @return bool True, if in the active plugins list. False, not in the list. |
506 * @return bool True, if in the active plugins list. False, not in the list. |
444 */ |
507 */ |
445 function is_plugin_active( $plugin ) { |
508 function is_plugin_active( $plugin ) { |
446 return in_array( $plugin, (array) get_option( 'active_plugins', array() ) ) || is_plugin_active_for_network( $plugin ); |
509 return in_array( $plugin, (array) get_option( 'active_plugins', array() ) ) || is_plugin_active_for_network( $plugin ); |
447 } |
510 } |
448 |
511 |
449 /** |
512 /** |
450 * Check whether the plugin is inactive. |
513 * Determines whether the plugin is inactive. |
451 * |
514 * |
452 * Reverse of is_plugin_active(). Used as a callback. |
515 * Reverse of is_plugin_active(). Used as a callback. |
516 * |
|
517 * For more information on this and similar theme functions, check out |
|
518 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ |
|
519 * Conditional Tags} article in the Theme Developer Handbook. |
|
453 * |
520 * |
454 * @since 3.1.0 |
521 * @since 3.1.0 |
455 * @see is_plugin_active() |
522 * @see is_plugin_active() |
456 * |
523 * |
457 * @param string $plugin Path to the main plugin file from plugins directory. |
524 * @param string $plugin Path to the plugin file relative to the plugins directory. |
458 * @return bool True if inactive. False if active. |
525 * @return bool True if inactive. False if active. |
459 */ |
526 */ |
460 function is_plugin_inactive( $plugin ) { |
527 function is_plugin_inactive( $plugin ) { |
461 return ! is_plugin_active( $plugin ); |
528 return ! is_plugin_active( $plugin ); |
462 } |
529 } |
463 |
530 |
464 /** |
531 /** |
465 * Check whether the plugin is active for the entire network. |
532 * Determines whether the plugin is active for the entire network. |
466 * |
533 * |
467 * Only plugins installed in the plugins/ folder can be active. |
534 * Only plugins installed in the plugins/ folder can be active. |
468 * |
535 * |
469 * Plugins in the mu-plugins/ folder can't be "activated," so this function will |
536 * Plugins in the mu-plugins/ folder can't be "activated," so this function will |
470 * return false for those plugins. |
537 * return false for those plugins. |
471 * |
538 * |
539 * For more information on this and similar theme functions, check out |
|
540 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ |
|
541 * Conditional Tags} article in the Theme Developer Handbook. |
|
542 * |
|
472 * @since 3.0.0 |
543 * @since 3.0.0 |
473 * |
544 * |
474 * @param string $plugin Path to the main plugin file from plugins directory. |
545 * @param string $plugin Path to the plugin file relative to the plugins directory. |
475 * @return bool True, if active for the network, otherwise false. |
546 * @return bool True if active for the network, otherwise false. |
476 */ |
547 */ |
477 function is_plugin_active_for_network( $plugin ) { |
548 function is_plugin_active_for_network( $plugin ) { |
478 if ( !is_multisite() ) |
549 if ( ! is_multisite() ) { |
479 return false; |
550 return false; |
480 |
551 } |
481 $plugins = get_site_option( 'active_sitewide_plugins'); |
552 |
482 if ( isset($plugins[$plugin]) ) |
553 $plugins = get_site_option( 'active_sitewide_plugins' ); |
554 if ( isset( $plugins[ $plugin ] ) ) { |
|
483 return true; |
555 return true; |
556 } |
|
484 |
557 |
485 return false; |
558 return false; |
486 } |
559 } |
487 |
560 |
488 /** |
561 /** |
492 * |
565 * |
493 * Checks for "Site Wide Only: true" for backward compatibility. |
566 * Checks for "Site Wide Only: true" for backward compatibility. |
494 * |
567 * |
495 * @since 3.0.0 |
568 * @since 3.0.0 |
496 * |
569 * |
497 * @param string $plugin Path to the main plugin file from plugins directory. |
570 * @param string $plugin Path to the plugin file relative to the plugins directory. |
498 * @return bool True if plugin is network only, false otherwise. |
571 * @return bool True if plugin is network only, false otherwise. |
499 */ |
572 */ |
500 function is_network_only_plugin( $plugin ) { |
573 function is_network_only_plugin( $plugin ) { |
501 $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); |
574 $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); |
502 if ( $plugin_data ) |
575 if ( $plugin_data ) { |
503 return $plugin_data['Network']; |
576 return $plugin_data['Network']; |
577 } |
|
504 return false; |
578 return false; |
505 } |
579 } |
506 |
580 |
507 /** |
581 /** |
508 * Attempts activation of plugin in a "sandbox" and redirects on success. |
582 * Attempts activation of plugin in a "sandbox" and redirects on success. |
521 * |
595 * |
522 * If any errors are found or text is outputted, then it will be captured to |
596 * If any errors are found or text is outputted, then it will be captured to |
523 * ensure that the success redirection will update the error redirection. |
597 * ensure that the success redirection will update the error redirection. |
524 * |
598 * |
525 * @since 2.5.0 |
599 * @since 2.5.0 |
526 * |
600 * @since 5.2.0 Test for WordPress version and PHP version compatibility. |
527 * @param string $plugin Path to the main plugin file from plugins directory. |
601 * |
602 * @param string $plugin Path to the plugin file relative to the plugins directory. |
|
528 * @param string $redirect Optional. URL to redirect to. |
603 * @param string $redirect Optional. URL to redirect to. |
529 * @param bool $network_wide Optional. Whether to enable the plugin for all sites in the network |
604 * @param bool $network_wide Optional. Whether to enable the plugin for all sites in the network |
530 * or just the current site. Multisite only. Default false. |
605 * or just the current site. Multisite only. Default false. |
531 * @param bool $silent Optional. Whether to prevent calling activation hooks. Default false. |
606 * @param bool $silent Optional. Whether to prevent calling activation hooks. Default false. |
532 * @return WP_Error|null WP_Error on invalid file or null on success. |
607 * @return WP_Error|null WP_Error on invalid file or null on success. |
533 */ |
608 */ |
534 function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) { |
609 function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) { |
535 $plugin = plugin_basename( trim( $plugin ) ); |
610 $plugin = plugin_basename( trim( $plugin ) ); |
536 |
611 |
537 if ( is_multisite() && ( $network_wide || is_network_only_plugin($plugin) ) ) { |
612 if ( is_multisite() && ( $network_wide || is_network_only_plugin( $plugin ) ) ) { |
538 $network_wide = true; |
613 $network_wide = true; |
539 $current = get_site_option( 'active_sitewide_plugins', array() ); |
614 $current = get_site_option( 'active_sitewide_plugins', array() ); |
540 $_GET['networkwide'] = 1; // Back compat for plugins looking for this value. |
615 $_GET['networkwide'] = 1; // Back compat for plugins looking for this value. |
541 } else { |
616 } else { |
542 $current = get_option( 'active_plugins', array() ); |
617 $current = get_option( 'active_plugins', array() ); |
543 } |
618 } |
544 |
619 |
545 $valid = validate_plugin($plugin); |
620 $valid = validate_plugin( $plugin ); |
546 if ( is_wp_error($valid) ) |
621 if ( is_wp_error( $valid ) ) { |
547 return $valid; |
622 return $valid; |
623 } |
|
624 |
|
625 $requirements = validate_plugin_requirements( $plugin ); |
|
626 if ( is_wp_error( $requirements ) ) { |
|
627 return $requirements; |
|
628 } |
|
548 |
629 |
549 if ( ( $network_wide && ! isset( $current[ $plugin ] ) ) || ( ! $network_wide && ! in_array( $plugin, $current ) ) ) { |
630 if ( ( $network_wide && ! isset( $current[ $plugin ] ) ) || ( ! $network_wide && ! in_array( $plugin, $current ) ) ) { |
550 if ( !empty($redirect) ) |
631 if ( ! empty( $redirect ) ) { |
551 wp_redirect(add_query_arg('_error_nonce', wp_create_nonce('plugin-activation-error_' . $plugin), $redirect)); // we'll override this later if the plugin can be included without fatal error |
632 wp_redirect( add_query_arg( '_error_nonce', wp_create_nonce( 'plugin-activation-error_' . $plugin ), $redirect ) ); // we'll override this later if the plugin can be included without fatal error |
633 } |
|
634 |
|
552 ob_start(); |
635 ob_start(); |
553 wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin ); |
636 wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin ); |
554 $_wp_plugin_file = $plugin; |
637 $_wp_plugin_file = $plugin; |
638 if ( ! defined( 'WP_SANDBOX_SCRAPING' ) ) { |
|
639 define( 'WP_SANDBOX_SCRAPING', true ); |
|
640 } |
|
555 include_once( WP_PLUGIN_DIR . '/' . $plugin ); |
641 include_once( WP_PLUGIN_DIR . '/' . $plugin ); |
556 $plugin = $_wp_plugin_file; // Avoid stomping of the $plugin variable in a plugin. |
642 $plugin = $_wp_plugin_file; // Avoid stomping of the $plugin variable in a plugin. |
557 |
643 |
558 if ( ! $silent ) { |
644 if ( ! $silent ) { |
559 /** |
645 /** |
562 * If a plugin is silently activated (such as during an update), |
648 * If a plugin is silently activated (such as during an update), |
563 * this hook does not fire. |
649 * this hook does not fire. |
564 * |
650 * |
565 * @since 2.9.0 |
651 * @since 2.9.0 |
566 * |
652 * |
567 * @param string $plugin Path to the main plugin file from plugins directory. |
653 * @param string $plugin Path to the plugin file relative to the plugins directory. |
568 * @param bool $network_wide Whether to enable the plugin for all sites in the network |
654 * @param bool $network_wide Whether to enable the plugin for all sites in the network |
569 * or just the current site. Multisite only. Default is false. |
655 * or just the current site. Multisite only. Default is false. |
570 */ |
656 */ |
571 do_action( 'activate_plugin', $plugin, $network_wide ); |
657 do_action( 'activate_plugin', $plugin, $network_wide ); |
572 |
658 |
585 */ |
671 */ |
586 do_action( "activate_{$plugin}", $network_wide ); |
672 do_action( "activate_{$plugin}", $network_wide ); |
587 } |
673 } |
588 |
674 |
589 if ( $network_wide ) { |
675 if ( $network_wide ) { |
590 $current = get_site_option( 'active_sitewide_plugins', array() ); |
676 $current = get_site_option( 'active_sitewide_plugins', array() ); |
591 $current[$plugin] = time(); |
677 $current[ $plugin ] = time(); |
592 update_site_option( 'active_sitewide_plugins', $current ); |
678 update_site_option( 'active_sitewide_plugins', $current ); |
593 } else { |
679 } else { |
594 $current = get_option( 'active_plugins', array() ); |
680 $current = get_option( 'active_plugins', array() ); |
595 $current[] = $plugin; |
681 $current[] = $plugin; |
596 sort($current); |
682 sort( $current ); |
597 update_option('active_plugins', $current); |
683 update_option( 'active_plugins', $current ); |
598 } |
684 } |
599 |
685 |
600 if ( ! $silent ) { |
686 if ( ! $silent ) { |
601 /** |
687 /** |
602 * Fires after a plugin has been activated. |
688 * Fires after a plugin has been activated. |
604 * If a plugin is silently activated (such as during an update), |
690 * If a plugin is silently activated (such as during an update), |
605 * this hook does not fire. |
691 * this hook does not fire. |
606 * |
692 * |
607 * @since 2.9.0 |
693 * @since 2.9.0 |
608 * |
694 * |
609 * @param string $plugin Path to the main plugin file from plugins directory. |
695 * @param string $plugin Path to the plugin file relative to the plugins directory. |
610 * @param bool $network_wide Whether to enable the plugin for all sites in the network |
696 * @param bool $network_wide Whether to enable the plugin for all sites in the network |
611 * or just the current site. Multisite only. Default is false. |
697 * or just the current site. Multisite only. Default is false. |
612 */ |
698 */ |
613 do_action( 'activated_plugin', $plugin, $network_wide ); |
699 do_action( 'activated_plugin', $plugin, $network_wide ); |
614 } |
700 } |
615 |
701 |
616 if ( ob_get_length() > 0 ) { |
702 if ( ob_get_length() > 0 ) { |
617 $output = ob_get_clean(); |
703 $output = ob_get_clean(); |
618 return new WP_Error('unexpected_output', __('The plugin generated unexpected output.'), $output); |
704 return new WP_Error( 'unexpected_output', __( 'The plugin generated unexpected output.' ), $output ); |
619 } |
705 } |
620 ob_end_clean(); |
706 ob_end_clean(); |
621 } |
707 } |
622 |
708 |
623 return null; |
709 return null; |
632 * @since 2.5.0 |
718 * @since 2.5.0 |
633 * |
719 * |
634 * @param string|array $plugins Single plugin or list of plugins to deactivate. |
720 * @param string|array $plugins Single plugin or list of plugins to deactivate. |
635 * @param bool $silent Prevent calling deactivation hooks. Default is false. |
721 * @param bool $silent Prevent calling deactivation hooks. Default is false. |
636 * @param mixed $network_wide Whether to deactivate the plugin for all sites in the network. |
722 * @param mixed $network_wide Whether to deactivate the plugin for all sites in the network. |
637 * A value of null (the default) will deactivate plugins for both the site and the network. |
723 * A value of null (the default) will deactivate plugins for both the site and the network. |
638 */ |
724 */ |
639 function deactivate_plugins( $plugins, $silent = false, $network_wide = null ) { |
725 function deactivate_plugins( $plugins, $silent = false, $network_wide = null ) { |
640 if ( is_multisite() ) |
726 if ( is_multisite() ) { |
641 $network_current = get_site_option( 'active_sitewide_plugins', array() ); |
727 $network_current = get_site_option( 'active_sitewide_plugins', array() ); |
728 } |
|
642 $current = get_option( 'active_plugins', array() ); |
729 $current = get_option( 'active_plugins', array() ); |
643 $do_blog = $do_network = false; |
730 $do_blog = $do_network = false; |
644 |
731 |
645 foreach ( (array) $plugins as $plugin ) { |
732 foreach ( (array) $plugins as $plugin ) { |
646 $plugin = plugin_basename( trim( $plugin ) ); |
733 $plugin = plugin_basename( trim( $plugin ) ); |
647 if ( ! is_plugin_active($plugin) ) |
734 if ( ! is_plugin_active( $plugin ) ) { |
648 continue; |
735 continue; |
736 } |
|
649 |
737 |
650 $network_deactivating = false !== $network_wide && is_plugin_active_for_network( $plugin ); |
738 $network_deactivating = false !== $network_wide && is_plugin_active_for_network( $plugin ); |
651 |
739 |
652 if ( ! $silent ) { |
740 if ( ! $silent ) { |
653 /** |
741 /** |
656 * If a plugin is silently deactivated (such as during an update), |
744 * If a plugin is silently deactivated (such as during an update), |
657 * this hook does not fire. |
745 * this hook does not fire. |
658 * |
746 * |
659 * @since 2.9.0 |
747 * @since 2.9.0 |
660 * |
748 * |
661 * @param string $plugin Path to the main plugin file from plugins directory. |
749 * @param string $plugin Path to the plugin file relative to the plugins directory. |
662 * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network |
750 * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network |
663 * or just the current site. Multisite only. Default is false. |
751 * or just the current site. Multisite only. Default is false. |
664 */ |
752 */ |
665 do_action( 'deactivate_plugin', $plugin, $network_deactivating ); |
753 do_action( 'deactivate_plugin', $plugin, $network_deactivating ); |
666 } |
754 } |
678 $key = array_search( $plugin, $current ); |
766 $key = array_search( $plugin, $current ); |
679 if ( false !== $key ) { |
767 if ( false !== $key ) { |
680 $do_blog = true; |
768 $do_blog = true; |
681 unset( $current[ $key ] ); |
769 unset( $current[ $key ] ); |
682 } |
770 } |
771 } |
|
772 |
|
773 if ( $do_blog && wp_is_recovery_mode() ) { |
|
774 list( $extension ) = explode( '/', $plugin ); |
|
775 wp_paused_plugins()->delete( $extension ); |
|
683 } |
776 } |
684 |
777 |
685 if ( ! $silent ) { |
778 if ( ! $silent ) { |
686 /** |
779 /** |
687 * Fires as a specific plugin is being deactivated. |
780 * Fires as a specific plugin is being deactivated. |
704 * If a plugin is silently deactivated (such as during an update), |
797 * If a plugin is silently deactivated (such as during an update), |
705 * this hook does not fire. |
798 * this hook does not fire. |
706 * |
799 * |
707 * @since 2.9.0 |
800 * @since 2.9.0 |
708 * |
801 * |
709 * @param string $plugin Path to the main plugin file from plugins directory. |
802 * @param string $plugin Path to the plugin file relative to the plugins directory. |
710 * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network. |
803 * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network. |
711 * or just the current site. Multisite only. Default false. |
804 * or just the current site. Multisite only. Default false. |
712 */ |
805 */ |
713 do_action( 'deactivated_plugin', $plugin, $network_deactivating ); |
806 do_action( 'deactivated_plugin', $plugin, $network_deactivating ); |
714 } |
807 } |
715 } |
808 } |
716 |
809 |
717 if ( $do_blog ) |
810 if ( $do_blog ) { |
718 update_option('active_plugins', $current); |
811 update_option( 'active_plugins', $current ); |
719 if ( $do_network ) |
812 } |
813 if ( $do_network ) { |
|
720 update_site_option( 'active_sitewide_plugins', $network_current ); |
814 update_site_option( 'active_sitewide_plugins', $network_current ); |
815 } |
|
721 } |
816 } |
722 |
817 |
723 /** |
818 /** |
724 * Activate multiple plugins. |
819 * Activate multiple plugins. |
725 * |
820 * |
735 * @param bool $network_wide Whether to enable the plugin for all sites in the network. |
830 * @param bool $network_wide Whether to enable the plugin for all sites in the network. |
736 * @param bool $silent Prevent calling activation hooks. Default is false. |
831 * @param bool $silent Prevent calling activation hooks. Default is false. |
737 * @return bool|WP_Error True when finished or WP_Error if there were errors during a plugin activation. |
832 * @return bool|WP_Error True when finished or WP_Error if there were errors during a plugin activation. |
738 */ |
833 */ |
739 function activate_plugins( $plugins, $redirect = '', $network_wide = false, $silent = false ) { |
834 function activate_plugins( $plugins, $redirect = '', $network_wide = false, $silent = false ) { |
740 if ( !is_array($plugins) ) |
835 if ( ! is_array( $plugins ) ) { |
741 $plugins = array($plugins); |
836 $plugins = array( $plugins ); |
837 } |
|
742 |
838 |
743 $errors = array(); |
839 $errors = array(); |
744 foreach ( $plugins as $plugin ) { |
840 foreach ( $plugins as $plugin ) { |
745 if ( !empty($redirect) ) |
841 if ( ! empty( $redirect ) ) { |
746 $redirect = add_query_arg('plugin', $plugin, $redirect); |
842 $redirect = add_query_arg( 'plugin', $plugin, $redirect ); |
747 $result = activate_plugin($plugin, $redirect, $network_wide, $silent); |
843 } |
748 if ( is_wp_error($result) ) |
844 $result = activate_plugin( $plugin, $redirect, $network_wide, $silent ); |
749 $errors[$plugin] = $result; |
845 if ( is_wp_error( $result ) ) { |
750 } |
846 $errors[ $plugin ] = $result; |
751 |
847 } |
752 if ( !empty($errors) ) |
848 } |
753 return new WP_Error('plugins_invalid', __('One of the plugins is invalid.'), $errors); |
849 |
850 if ( ! empty( $errors ) ) { |
|
851 return new WP_Error( 'plugins_invalid', __( 'One of the plugins is invalid.' ), $errors ); |
|
852 } |
|
754 |
853 |
755 return true; |
854 return true; |
756 } |
855 } |
757 |
856 |
758 /** |
857 /** |
759 * Remove directory and files of a plugin for a list of plugins. |
858 * Remove directory and files of a plugin for a list of plugins. |
760 * |
859 * |
761 * @since 2.6.0 |
860 * @since 2.6.0 |
762 * |
861 * |
763 * @global WP_Filesystem_Base $wp_filesystem |
862 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. |
764 * |
863 * |
765 * @param array $plugins List of plugins to delete. |
864 * @param string[] $plugins List of plugin paths to delete, relative to the plugins directory. |
766 * @param string $deprecated Deprecated. |
865 * @param string $deprecated Not used. |
767 * @return bool|null|WP_Error True on success, false is $plugins is empty, WP_Error on failure. |
866 * @return bool|null|WP_Error True on success, false if `$plugins` is empty, `WP_Error` on failure. |
768 * Null if filesystem credentials are required to proceed. |
867 * `null` if filesystem credentials are required to proceed. |
769 */ |
868 */ |
770 function delete_plugins( $plugins, $deprecated = '' ) { |
869 function delete_plugins( $plugins, $deprecated = '' ) { |
771 global $wp_filesystem; |
870 global $wp_filesystem; |
772 |
871 |
773 if ( empty($plugins) ) |
872 if ( empty( $plugins ) ) { |
774 return false; |
873 return false; |
874 } |
|
775 |
875 |
776 $checked = array(); |
876 $checked = array(); |
777 foreach ( $plugins as $plugin ) |
877 foreach ( $plugins as $plugin ) { |
778 $checked[] = 'checked[]=' . $plugin; |
878 $checked[] = 'checked[]=' . $plugin; |
779 |
879 } |
780 $url = wp_nonce_url('plugins.php?action=delete-selected&verify-delete=1&' . implode('&', $checked), 'bulk-plugins'); |
880 |
881 $url = wp_nonce_url( 'plugins.php?action=delete-selected&verify-delete=1&' . implode( '&', $checked ), 'bulk-plugins' ); |
|
781 |
882 |
782 ob_start(); |
883 ob_start(); |
783 $credentials = request_filesystem_credentials( $url ); |
884 $credentials = request_filesystem_credentials( $url ); |
784 $data = ob_get_clean(); |
885 $data = ob_get_clean(); |
785 |
886 |
786 if ( false === $credentials ) { |
887 if ( false === $credentials ) { |
787 if ( ! empty($data) ){ |
888 if ( ! empty( $data ) ) { |
788 include_once( ABSPATH . 'wp-admin/admin-header.php'); |
889 include_once( ABSPATH . 'wp-admin/admin-header.php' ); |
789 echo $data; |
890 echo $data; |
790 include( ABSPATH . 'wp-admin/admin-footer.php'); |
891 include( ABSPATH . 'wp-admin/admin-footer.php' ); |
791 exit; |
892 exit; |
792 } |
893 } |
793 return; |
894 return; |
794 } |
895 } |
795 |
896 |
796 if ( ! WP_Filesystem( $credentials ) ) { |
897 if ( ! WP_Filesystem( $credentials ) ) { |
797 ob_start(); |
898 ob_start(); |
798 request_filesystem_credentials( $url, '', true ); // Failed to connect, Error and request again. |
899 request_filesystem_credentials( $url, '', true ); // Failed to connect, Error and request again. |
799 $data = ob_get_clean(); |
900 $data = ob_get_clean(); |
800 |
901 |
801 if ( ! empty($data) ){ |
902 if ( ! empty( $data ) ) { |
802 include_once( ABSPATH . 'wp-admin/admin-header.php'); |
903 include_once( ABSPATH . 'wp-admin/admin-header.php' ); |
803 echo $data; |
904 echo $data; |
804 include( ABSPATH . 'wp-admin/admin-footer.php'); |
905 include( ABSPATH . 'wp-admin/admin-footer.php' ); |
805 exit; |
906 exit; |
806 } |
907 } |
807 return; |
908 return; |
808 } |
909 } |
809 |
910 |
810 if ( ! is_object($wp_filesystem) ) |
911 if ( ! is_object( $wp_filesystem ) ) { |
811 return new WP_Error('fs_unavailable', __('Could not access filesystem.')); |
912 return new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) ); |
812 |
913 } |
813 if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() ) |
914 |
814 return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors); |
915 if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) { |
916 return new WP_Error( 'fs_error', __( 'Filesystem error.' ), $wp_filesystem->errors ); |
|
917 } |
|
815 |
918 |
816 // Get the base plugin folder. |
919 // Get the base plugin folder. |
817 $plugins_dir = $wp_filesystem->wp_plugins_dir(); |
920 $plugins_dir = $wp_filesystem->wp_plugins_dir(); |
818 if ( empty( $plugins_dir ) ) { |
921 if ( empty( $plugins_dir ) ) { |
819 return new WP_Error( 'fs_no_plugins_dir', __( 'Unable to locate WordPress plugin directory.' ) ); |
922 return new WP_Error( 'fs_no_plugins_dir', __( 'Unable to locate WordPress plugin directory.' ) ); |
826 $errors = array(); |
929 $errors = array(); |
827 |
930 |
828 foreach ( $plugins as $plugin_file ) { |
931 foreach ( $plugins as $plugin_file ) { |
829 // Run Uninstall hook. |
932 // Run Uninstall hook. |
830 if ( is_uninstallable_plugin( $plugin_file ) ) { |
933 if ( is_uninstallable_plugin( $plugin_file ) ) { |
831 uninstall_plugin($plugin_file); |
934 uninstall_plugin( $plugin_file ); |
832 } |
935 } |
833 |
936 |
834 /** |
937 /** |
835 * Fires immediately before a plugin deletion attempt. |
938 * Fires immediately before a plugin deletion attempt. |
836 * |
939 * |
837 * @since 4.4.0 |
940 * @since 4.4.0 |
838 * |
941 * |
839 * @param string $plugin_file Plugin file name. |
942 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
840 */ |
943 */ |
841 do_action( 'delete_plugin', $plugin_file ); |
944 do_action( 'delete_plugin', $plugin_file ); |
842 |
945 |
843 $this_plugin_dir = trailingslashit( dirname( $plugins_dir . $plugin_file ) ); |
946 $this_plugin_dir = trailingslashit( dirname( $plugins_dir . $plugin_file ) ); |
844 |
947 |
852 /** |
955 /** |
853 * Fires immediately after a plugin deletion attempt. |
956 * Fires immediately after a plugin deletion attempt. |
854 * |
957 * |
855 * @since 4.4.0 |
958 * @since 4.4.0 |
856 * |
959 * |
857 * @param string $plugin_file Plugin file name. |
960 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
858 * @param bool $deleted Whether the plugin deletion was successful. |
961 * @param bool $deleted Whether the plugin deletion was successful. |
859 */ |
962 */ |
860 do_action( 'deleted_plugin', $plugin_file, $deleted ); |
963 do_action( 'deleted_plugin', $plugin_file, $deleted ); |
861 |
964 |
862 if ( ! $deleted ) { |
965 if ( ! $deleted ) { |
870 $translations = $plugin_translations[ $plugin_slug ]; |
973 $translations = $plugin_translations[ $plugin_slug ]; |
871 |
974 |
872 foreach ( $translations as $translation => $data ) { |
975 foreach ( $translations as $translation => $data ) { |
873 $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.po' ); |
976 $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.po' ); |
874 $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.mo' ); |
977 $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.mo' ); |
978 |
|
979 $json_translation_files = glob( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '-*.json' ); |
|
980 if ( $json_translation_files ) { |
|
981 array_map( array( $wp_filesystem, 'delete' ), $json_translation_files ); |
|
982 } |
|
875 } |
983 } |
876 } |
984 } |
877 } |
985 } |
878 |
986 |
879 // Remove deleted plugins from the plugin updates list. |
987 // Remove deleted plugins from the plugin updates list. |
880 if ( $current = get_site_transient('update_plugins') ) { |
988 if ( $current = get_site_transient( 'update_plugins' ) ) { |
881 // Don't remove the plugins that weren't deleted. |
989 // Don't remove the plugins that weren't deleted. |
882 $deleted = array_diff( $plugins, $errors ); |
990 $deleted = array_diff( $plugins, $errors ); |
883 |
991 |
884 foreach ( $deleted as $plugin_file ) { |
992 foreach ( $deleted as $plugin_file ) { |
885 unset( $current->response[ $plugin_file ] ); |
993 unset( $current->response[ $plugin_file ] ); |
920 $plugins = array(); |
1028 $plugins = array(); |
921 } |
1029 } |
922 |
1030 |
923 if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) { |
1031 if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) { |
924 $network_plugins = (array) get_site_option( 'active_sitewide_plugins', array() ); |
1032 $network_plugins = (array) get_site_option( 'active_sitewide_plugins', array() ); |
925 $plugins = array_merge( $plugins, array_keys( $network_plugins ) ); |
1033 $plugins = array_merge( $plugins, array_keys( $network_plugins ) ); |
926 } |
1034 } |
927 |
1035 |
928 if ( empty( $plugins ) ) |
1036 if ( empty( $plugins ) ) { |
929 return array(); |
1037 return array(); |
1038 } |
|
930 |
1039 |
931 $invalid = array(); |
1040 $invalid = array(); |
932 |
1041 |
933 // Invalid plugins get deactivated. |
1042 // Invalid plugins get deactivated. |
934 foreach ( $plugins as $plugin ) { |
1043 foreach ( $plugins as $plugin ) { |
935 $result = validate_plugin( $plugin ); |
1044 $result = validate_plugin( $plugin ); |
936 if ( is_wp_error( $result ) ) { |
1045 if ( is_wp_error( $result ) ) { |
937 $invalid[$plugin] = $result; |
1046 $invalid[ $plugin ] = $result; |
938 deactivate_plugins( $plugin, true ); |
1047 deactivate_plugins( $plugin, true ); |
939 } |
1048 } |
940 } |
1049 } |
941 return $invalid; |
1050 return $invalid; |
942 } |
1051 } |
946 * |
1055 * |
947 * Checks that the main plugin file exists and is a valid plugin. See validate_file(). |
1056 * Checks that the main plugin file exists and is a valid plugin. See validate_file(). |
948 * |
1057 * |
949 * @since 2.5.0 |
1058 * @since 2.5.0 |
950 * |
1059 * |
951 * @param string $plugin Path to the main plugin file from plugins directory. |
1060 * @param string $plugin Path to the plugin file relative to the plugins directory. |
952 * @return WP_Error|int 0 on success, WP_Error on failure. |
1061 * @return WP_Error|int 0 on success, WP_Error on failure. |
953 */ |
1062 */ |
954 function validate_plugin($plugin) { |
1063 function validate_plugin( $plugin ) { |
955 if ( validate_file($plugin) ) |
1064 if ( validate_file( $plugin ) ) { |
956 return new WP_Error('plugin_invalid', __('Invalid plugin path.')); |
1065 return new WP_Error( 'plugin_invalid', __( 'Invalid plugin path.' ) ); |
957 if ( ! file_exists(WP_PLUGIN_DIR . '/' . $plugin) ) |
1066 } |
958 return new WP_Error('plugin_not_found', __('Plugin file does not exist.')); |
1067 if ( ! file_exists( WP_PLUGIN_DIR . '/' . $plugin ) ) { |
1068 return new WP_Error( 'plugin_not_found', __( 'Plugin file does not exist.' ) ); |
|
1069 } |
|
959 |
1070 |
960 $installed_plugins = get_plugins(); |
1071 $installed_plugins = get_plugins(); |
961 if ( ! isset($installed_plugins[$plugin]) ) |
1072 if ( ! isset( $installed_plugins[ $plugin ] ) ) { |
962 return new WP_Error('no_plugin_header', __('The plugin does not have a valid header.')); |
1073 return new WP_Error( 'no_plugin_header', __( 'The plugin does not have a valid header.' ) ); |
1074 } |
|
963 return 0; |
1075 return 0; |
964 } |
1076 } |
965 |
1077 |
966 /** |
1078 /** |
1079 * Validate the plugin requirements for WP version and PHP version. |
|
1080 * |
|
1081 * @since 5.2.0 |
|
1082 * |
|
1083 * @param string $plugin Path to the plugin file relative to the plugins directory. |
|
1084 * @return true|WP_Error True if requirements are met, WP_Error on failure. |
|
1085 */ |
|
1086 function validate_plugin_requirements( $plugin ) { |
|
1087 $readme_file = WP_PLUGIN_DIR . '/' . dirname( $plugin ) . '/readme.txt'; |
|
1088 |
|
1089 if ( file_exists( $readme_file ) ) { |
|
1090 $plugin_data = get_file_data( |
|
1091 $readme_file, |
|
1092 array( |
|
1093 'requires' => 'Requires at least', |
|
1094 'requires_php' => 'Requires PHP', |
|
1095 ), |
|
1096 'plugin' |
|
1097 ); |
|
1098 } else { |
|
1099 return true; |
|
1100 } |
|
1101 |
|
1102 $plugin_data['wp_compatible'] = is_wp_version_compatible( $plugin_data['requires'] ); |
|
1103 $plugin_data['php_compatible'] = is_php_version_compatible( $plugin_data['requires_php'] ); |
|
1104 |
|
1105 $plugin_data = array_merge( $plugin_data, get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ) ); |
|
1106 |
|
1107 if ( ! $plugin_data['wp_compatible'] && ! $plugin_data['php_compatible'] ) { |
|
1108 return new WP_Error( |
|
1109 'plugin_wp_php_incompatible', |
|
1110 sprintf( |
|
1111 /* translators: %s: plugin name */ |
|
1112 __( '<strong>Error:</strong> Current WordPress and PHP versions do not meet minimum requirements for %s.' ), |
|
1113 $plugin_data['Name'] |
|
1114 ) |
|
1115 ); |
|
1116 } elseif ( ! $plugin_data['php_compatible'] ) { |
|
1117 return new WP_Error( |
|
1118 'plugin_php_incompatible', |
|
1119 sprintf( |
|
1120 /* translators: %s: plugin name */ |
|
1121 __( '<strong>Error:</strong> Current PHP version does not meet minimum requirements for %s.' ), |
|
1122 $plugin_data['Name'] |
|
1123 ) |
|
1124 ); |
|
1125 } elseif ( ! $plugin_data['wp_compatible'] ) { |
|
1126 return new WP_Error( |
|
1127 'plugin_wp_incompatible', |
|
1128 sprintf( |
|
1129 /* translators: %s: plugin name */ |
|
1130 __( '<strong>Error:</strong> Current WordPress version does not meet minimum requirements for %s.' ), |
|
1131 $plugin_data['Name'] |
|
1132 ) |
|
1133 ); |
|
1134 } |
|
1135 |
|
1136 return true; |
|
1137 } |
|
1138 |
|
1139 /** |
|
967 * Whether the plugin can be uninstalled. |
1140 * Whether the plugin can be uninstalled. |
968 * |
1141 * |
969 * @since 2.7.0 |
1142 * @since 2.7.0 |
970 * |
1143 * |
971 * @param string $plugin Path to the main plugin file from plugins directory. |
1144 * @param string $plugin Path to the plugin file relative to the plugins directory. |
972 * @return bool Whether plugin can be uninstalled. |
1145 * @return bool Whether plugin can be uninstalled. |
973 */ |
1146 */ |
974 function is_uninstallable_plugin($plugin) { |
1147 function is_uninstallable_plugin( $plugin ) { |
975 $file = plugin_basename($plugin); |
1148 $file = plugin_basename( $plugin ); |
976 |
1149 |
977 $uninstallable_plugins = (array) get_option('uninstall_plugins'); |
1150 $uninstallable_plugins = (array) get_option( 'uninstall_plugins' ); |
978 if ( isset( $uninstallable_plugins[$file] ) || file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) ) |
1151 if ( isset( $uninstallable_plugins[ $file ] ) || file_exists( WP_PLUGIN_DIR . '/' . dirname( $file ) . '/uninstall.php' ) ) { |
979 return true; |
1152 return true; |
1153 } |
|
980 |
1154 |
981 return false; |
1155 return false; |
982 } |
1156 } |
983 |
1157 |
984 /** |
1158 /** |
986 * |
1160 * |
987 * Calls the uninstall hook, if it is available. |
1161 * Calls the uninstall hook, if it is available. |
988 * |
1162 * |
989 * @since 2.7.0 |
1163 * @since 2.7.0 |
990 * |
1164 * |
991 * @param string $plugin Path to the main plugin file from plugins directory. |
1165 * @param string $plugin Path to the plugin file relative to the plugins directory. |
992 * @return true True if a plugin's uninstall.php file has been found and included. |
1166 * @return true True if a plugin's uninstall.php file has been found and included. |
993 */ |
1167 */ |
994 function uninstall_plugin($plugin) { |
1168 function uninstall_plugin( $plugin ) { |
995 $file = plugin_basename($plugin); |
1169 $file = plugin_basename( $plugin ); |
996 |
1170 |
997 $uninstallable_plugins = (array) get_option('uninstall_plugins'); |
1171 $uninstallable_plugins = (array) get_option( 'uninstall_plugins' ); |
998 |
1172 |
999 /** |
1173 /** |
1000 * Fires in uninstall_plugin() immediately before the plugin is uninstalled. |
1174 * Fires in uninstall_plugin() immediately before the plugin is uninstalled. |
1001 * |
1175 * |
1002 * @since 4.5.0 |
1176 * @since 4.5.0 |
1003 * |
1177 * |
1004 * @param string $plugin Path to the main plugin file from plugins directory. |
1178 * @param string $plugin Path to the plugin file relative to the plugins directory. |
1005 * @param array $uninstallable_plugins Uninstallable plugins. |
1179 * @param array $uninstallable_plugins Uninstallable plugins. |
1006 */ |
1180 */ |
1007 do_action( 'pre_uninstall_plugin', $plugin, $uninstallable_plugins ); |
1181 do_action( 'pre_uninstall_plugin', $plugin, $uninstallable_plugins ); |
1008 |
1182 |
1009 if ( file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) ) { |
1183 if ( file_exists( WP_PLUGIN_DIR . '/' . dirname( $file ) . '/uninstall.php' ) ) { |
1010 if ( isset( $uninstallable_plugins[$file] ) ) { |
1184 if ( isset( $uninstallable_plugins[ $file ] ) ) { |
1011 unset($uninstallable_plugins[$file]); |
1185 unset( $uninstallable_plugins[ $file ] ); |
1012 update_option('uninstall_plugins', $uninstallable_plugins); |
1186 update_option( 'uninstall_plugins', $uninstallable_plugins ); |
1013 } |
1187 } |
1014 unset($uninstallable_plugins); |
1188 unset( $uninstallable_plugins ); |
1015 |
1189 |
1016 define('WP_UNINSTALL_PLUGIN', $file); |
1190 define( 'WP_UNINSTALL_PLUGIN', $file ); |
1017 wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $file ); |
1191 wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $file ); |
1018 include( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ); |
1192 include( WP_PLUGIN_DIR . '/' . dirname( $file ) . '/uninstall.php' ); |
1019 |
1193 |
1020 return true; |
1194 return true; |
1021 } |
1195 } |
1022 |
1196 |
1023 if ( isset( $uninstallable_plugins[$file] ) ) { |
1197 if ( isset( $uninstallable_plugins[ $file ] ) ) { |
1024 $callable = $uninstallable_plugins[$file]; |
1198 $callable = $uninstallable_plugins[ $file ]; |
1025 unset($uninstallable_plugins[$file]); |
1199 unset( $uninstallable_plugins[ $file ] ); |
1026 update_option('uninstall_plugins', $uninstallable_plugins); |
1200 update_option( 'uninstall_plugins', $uninstallable_plugins ); |
1027 unset($uninstallable_plugins); |
1201 unset( $uninstallable_plugins ); |
1028 |
1202 |
1029 wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $file ); |
1203 wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $file ); |
1030 include( WP_PLUGIN_DIR . '/' . $file ); |
1204 include( WP_PLUGIN_DIR . '/' . $file ); |
1031 |
1205 |
1032 add_action( "uninstall_{$file}", $callable ); |
1206 add_action( "uninstall_{$file}", $callable ); |
1053 * This function takes a capability which will be used to determine whether |
1227 * This function takes a capability which will be used to determine whether |
1054 * or not a page is included in the menu. |
1228 * or not a page is included in the menu. |
1055 * |
1229 * |
1056 * The function which is hooked in to handle the output of the page must check |
1230 * The function which is hooked in to handle the output of the page must check |
1057 * that the user has the required capability as well. |
1231 * that the user has the required capability as well. |
1232 * |
|
1233 * @since 1.5.0 |
|
1058 * |
1234 * |
1059 * @global array $menu |
1235 * @global array $menu |
1060 * @global array $admin_page_hooks |
1236 * @global array $admin_page_hooks |
1061 * @global array $_registered_pages |
1237 * @global array $_registered_pages |
1062 * @global array $_parent_pages |
1238 * @global array $_parent_pages |
1080 function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) { |
1256 function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) { |
1081 global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages; |
1257 global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages; |
1082 |
1258 |
1083 $menu_slug = plugin_basename( $menu_slug ); |
1259 $menu_slug = plugin_basename( $menu_slug ); |
1084 |
1260 |
1085 $admin_page_hooks[$menu_slug] = sanitize_title( $menu_title ); |
1261 $admin_page_hooks[ $menu_slug ] = sanitize_title( $menu_title ); |
1086 |
1262 |
1087 $hookname = get_plugin_page_hookname( $menu_slug, '' ); |
1263 $hookname = get_plugin_page_hookname( $menu_slug, '' ); |
1088 |
1264 |
1089 if ( !empty( $function ) && !empty( $hookname ) && current_user_can( $capability ) ) |
1265 if ( ! empty( $function ) && ! empty( $hookname ) && current_user_can( $capability ) ) { |
1090 add_action( $hookname, $function ); |
1266 add_action( $hookname, $function ); |
1091 |
1267 } |
1092 if ( empty($icon_url) ) { |
1268 |
1093 $icon_url = 'dashicons-admin-generic'; |
1269 if ( empty( $icon_url ) ) { |
1270 $icon_url = 'dashicons-admin-generic'; |
|
1094 $icon_class = 'menu-icon-generic '; |
1271 $icon_class = 'menu-icon-generic '; |
1095 } else { |
1272 } else { |
1096 $icon_url = set_url_scheme( $icon_url ); |
1273 $icon_url = set_url_scheme( $icon_url ); |
1097 $icon_class = ''; |
1274 $icon_class = ''; |
1098 } |
1275 } |
1099 |
1276 |
1100 $new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url ); |
1277 $new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url ); |
1101 |
1278 |
1102 if ( null === $position ) { |
1279 if ( null === $position ) { |
1103 $menu[] = $new_menu; |
1280 $menu[] = $new_menu; |
1104 } elseif ( isset( $menu[ "$position" ] ) ) { |
1281 } elseif ( isset( $menu[ "$position" ] ) ) { |
1105 $position = $position + substr( base_convert( md5( $menu_slug . $menu_title ), 16, 10 ) , -5 ) * 0.00001; |
1282 $position = $position + substr( base_convert( md5( $menu_slug . $menu_title ), 16, 10 ), -5 ) * 0.00001; |
1106 $menu[ "$position" ] = $new_menu; |
1283 $menu[ "$position" ] = $new_menu; |
1107 } else { |
1284 } else { |
1108 $menu[ $position ] = $new_menu; |
1285 $menu[ $position ] = $new_menu; |
1109 } |
1286 } |
1110 |
1287 |
1111 $_registered_pages[$hookname] = true; |
1288 $_registered_pages[ $hookname ] = true; |
1112 |
1289 |
1113 // No parent as top level |
1290 // No parent as top level |
1114 $_parent_pages[$menu_slug] = false; |
1291 $_parent_pages[ $menu_slug ] = false; |
1115 |
1292 |
1116 return $hookname; |
1293 return $hookname; |
1117 } |
1294 } |
1118 |
1295 |
1119 /** |
1296 /** |
1122 * This function takes a capability which will be used to determine whether |
1299 * This function takes a capability which will be used to determine whether |
1123 * or not a page is included in the menu. |
1300 * or not a page is included in the menu. |
1124 * |
1301 * |
1125 * The function which is hooked in to handle the output of the page must check |
1302 * The function which is hooked in to handle the output of the page must check |
1126 * that the user has the required capability as well. |
1303 * that the user has the required capability as well. |
1304 * |
|
1305 * @since 1.5.0 |
|
1127 * |
1306 * |
1128 * @global array $submenu |
1307 * @global array $submenu |
1129 * @global array $menu |
1308 * @global array $menu |
1130 * @global array $_wp_real_parent_file |
1309 * @global array $_wp_real_parent_file |
1131 * @global bool $_wp_submenu_nopriv |
1310 * @global bool $_wp_submenu_nopriv |
1146 */ |
1325 */ |
1147 function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { |
1326 function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { |
1148 global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, |
1327 global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, |
1149 $_registered_pages, $_parent_pages; |
1328 $_registered_pages, $_parent_pages; |
1150 |
1329 |
1151 $menu_slug = plugin_basename( $menu_slug ); |
1330 $menu_slug = plugin_basename( $menu_slug ); |
1152 $parent_slug = plugin_basename( $parent_slug); |
1331 $parent_slug = plugin_basename( $parent_slug ); |
1153 |
1332 |
1154 if ( isset( $_wp_real_parent_file[$parent_slug] ) ) |
1333 if ( isset( $_wp_real_parent_file[ $parent_slug ] ) ) { |
1155 $parent_slug = $_wp_real_parent_file[$parent_slug]; |
1334 $parent_slug = $_wp_real_parent_file[ $parent_slug ]; |
1156 |
1335 } |
1157 if ( !current_user_can( $capability ) ) { |
1336 |
1158 $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true; |
1337 if ( ! current_user_can( $capability ) ) { |
1338 $_wp_submenu_nopriv[ $parent_slug ][ $menu_slug ] = true; |
|
1159 return false; |
1339 return false; |
1160 } |
1340 } |
1161 |
1341 |
1162 /* |
1342 /* |
1163 * If the parent doesn't already have a submenu, add a link to the parent |
1343 * If the parent doesn't already have a submenu, add a link to the parent |
1164 * as the first item in the submenu. If the submenu file is the same as the |
1344 * as the first item in the submenu. If the submenu file is the same as the |
1165 * parent file someone is trying to link back to the parent manually. In |
1345 * parent file someone is trying to link back to the parent manually. In |
1166 * this case, don't automatically add a link back to avoid duplication. |
1346 * this case, don't automatically add a link back to avoid duplication. |
1167 */ |
1347 */ |
1168 if (!isset( $submenu[$parent_slug] ) && $menu_slug != $parent_slug ) { |
1348 if ( ! isset( $submenu[ $parent_slug ] ) && $menu_slug != $parent_slug ) { |
1169 foreach ( (array)$menu as $parent_menu ) { |
1349 foreach ( (array) $menu as $parent_menu ) { |
1170 if ( $parent_menu[2] == $parent_slug && current_user_can( $parent_menu[1] ) ) |
1350 if ( $parent_menu[2] == $parent_slug && current_user_can( $parent_menu[1] ) ) { |
1171 $submenu[$parent_slug][] = array_slice( $parent_menu, 0, 4 ); |
1351 $submenu[ $parent_slug ][] = array_slice( $parent_menu, 0, 4 ); |
1172 } |
1352 } |
1173 } |
1353 } |
1174 |
1354 } |
1175 $submenu[$parent_slug][] = array ( $menu_title, $capability, $menu_slug, $page_title ); |
1355 |
1176 |
1356 $submenu[ $parent_slug ][] = array( $menu_title, $capability, $menu_slug, $page_title ); |
1177 $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug); |
1357 |
1178 if (!empty ( $function ) && !empty ( $hookname )) |
1358 $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug ); |
1359 if ( ! empty( $function ) && ! empty( $hookname ) ) { |
|
1179 add_action( $hookname, $function ); |
1360 add_action( $hookname, $function ); |
1180 |
1361 } |
1181 $_registered_pages[$hookname] = true; |
1362 |
1363 $_registered_pages[ $hookname ] = true; |
|
1182 |
1364 |
1183 /* |
1365 /* |
1184 * Backward-compatibility for plugins using add_management page. |
1366 * Backward-compatibility for plugins using add_management_page(). |
1185 * See wp-admin/admin.php for redirect from edit.php to tools.php |
1367 * See wp-admin/admin.php for redirect from edit.php to tools.php. |
1186 */ |
1368 */ |
1187 if ( 'tools.php' == $parent_slug ) |
1369 if ( 'tools.php' == $parent_slug ) { |
1188 $_registered_pages[get_plugin_page_hookname( $menu_slug, 'edit.php')] = true; |
1370 $_registered_pages[ get_plugin_page_hookname( $menu_slug, 'edit.php' ) ] = true; |
1371 } |
|
1189 |
1372 |
1190 // No parent as top level. |
1373 // No parent as top level. |
1191 $_parent_pages[$menu_slug] = $parent_slug; |
1374 $_parent_pages[ $menu_slug ] = $parent_slug; |
1192 |
1375 |
1193 return $hookname; |
1376 return $hookname; |
1194 } |
1377 } |
1195 |
1378 |
1196 /** |
1379 /** |
1199 * This function takes a capability which will be used to determine whether |
1382 * This function takes a capability which will be used to determine whether |
1200 * or not a page is included in the menu. |
1383 * or not a page is included in the menu. |
1201 * |
1384 * |
1202 * The function which is hooked in to handle the output of the page must check |
1385 * The function which is hooked in to handle the output of the page must check |
1203 * that the user has the required capability as well. |
1386 * that the user has the required capability as well. |
1387 * |
|
1388 * @since 1.5.0 |
|
1204 * |
1389 * |
1205 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1390 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1206 * @param string $menu_title The text to be used for the menu. |
1391 * @param string $menu_title The text to be used for the menu. |
1207 * @param string $capability The capability required for this menu to be displayed to the user. |
1392 * @param string $capability The capability required for this menu to be displayed to the user. |
1208 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1393 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1220 * or not a page is included in the menu. |
1405 * or not a page is included in the menu. |
1221 * |
1406 * |
1222 * The function which is hooked in to handle the output of the page must check |
1407 * The function which is hooked in to handle the output of the page must check |
1223 * that the user has the required capability as well. |
1408 * that the user has the required capability as well. |
1224 * |
1409 * |
1410 * @since 1.5.0 |
|
1411 * |
|
1225 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1412 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1226 * @param string $menu_title The text to be used for the menu. |
1413 * @param string $menu_title The text to be used for the menu. |
1227 * @param string $capability The capability required for this menu to be displayed to the user. |
1414 * @param string $capability The capability required for this menu to be displayed to the user. |
1228 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1415 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1229 * @param callable $function The function to be called to output the content for this page. |
1416 * @param callable $function The function to be called to output the content for this page. |
1240 * or not a page is included in the menu. |
1427 * or not a page is included in the menu. |
1241 * |
1428 * |
1242 * The function which is hooked in to handle the output of the page must check |
1429 * The function which is hooked in to handle the output of the page must check |
1243 * that the user has the required capability as well. |
1430 * that the user has the required capability as well. |
1244 * |
1431 * |
1432 * @since 2.0.0 |
|
1433 * |
|
1245 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1434 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1246 * @param string $menu_title The text to be used for the menu. |
1435 * @param string $menu_title The text to be used for the menu. |
1247 * @param string $capability The capability required for this menu to be displayed to the user. |
1436 * @param string $capability The capability required for this menu to be displayed to the user. |
1248 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1437 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1249 * @param callable $function The function to be called to output the content for this page. |
1438 * @param callable $function The function to be called to output the content for this page. |
1260 * or not a page is included in the menu. |
1449 * or not a page is included in the menu. |
1261 * |
1450 * |
1262 * The function which is hooked in to handle the output of the page must check |
1451 * The function which is hooked in to handle the output of the page must check |
1263 * that the user has the required capability as well. |
1452 * that the user has the required capability as well. |
1264 * |
1453 * |
1454 * @since 3.0.0 |
|
1455 * |
|
1265 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1456 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1266 * @param string $menu_title The text to be used for the menu. |
1457 * @param string $menu_title The text to be used for the menu. |
1267 * @param string $capability The capability required for this menu to be displayed to the user. |
1458 * @param string $capability The capability required for this menu to be displayed to the user. |
1268 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1459 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1269 * @param callable $function The function to be called to output the content for this page. |
1460 * @param callable $function The function to be called to output the content for this page. |
1280 * or not a page is included in the menu. |
1471 * or not a page is included in the menu. |
1281 * |
1472 * |
1282 * The function which is hooked in to handle the output of the page must check |
1473 * The function which is hooked in to handle the output of the page must check |
1283 * that the user has the required capability as well. |
1474 * that the user has the required capability as well. |
1284 * |
1475 * |
1476 * @since 2.1.3 |
|
1477 * |
|
1285 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1478 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1286 * @param string $menu_title The text to be used for the menu. |
1479 * @param string $menu_title The text to be used for the menu. |
1287 * @param string $capability The capability required for this menu to be displayed to the user. |
1480 * @param string $capability The capability required for this menu to be displayed to the user. |
1288 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1481 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1289 * @param callable $function The function to be called to output the content for this page. |
1482 * @param callable $function The function to be called to output the content for this page. |
1290 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required. |
1483 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required. |
1291 */ |
1484 */ |
1292 function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { |
1485 function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { |
1293 if ( current_user_can('edit_users') ) |
1486 if ( current_user_can( 'edit_users' ) ) { |
1294 $parent = 'users.php'; |
1487 $parent = 'users.php'; |
1295 else |
1488 } else { |
1296 $parent = 'profile.php'; |
1489 $parent = 'profile.php'; |
1490 } |
|
1297 return add_submenu_page( $parent, $page_title, $menu_title, $capability, $menu_slug, $function ); |
1491 return add_submenu_page( $parent, $page_title, $menu_title, $capability, $menu_slug, $function ); |
1298 } |
1492 } |
1299 /** |
1493 /** |
1300 * Add submenu page to the Dashboard main menu. |
1494 * Add submenu page to the Dashboard main menu. |
1301 * |
1495 * |
1302 * This function takes a capability which will be used to determine whether |
1496 * This function takes a capability which will be used to determine whether |
1303 * or not a page is included in the menu. |
1497 * or not a page is included in the menu. |
1304 * |
1498 * |
1305 * The function which is hooked in to handle the output of the page must check |
1499 * The function which is hooked in to handle the output of the page must check |
1306 * that the user has the required capability as well. |
1500 * that the user has the required capability as well. |
1501 * |
|
1502 * @since 2.7.0 |
|
1307 * |
1503 * |
1308 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1504 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1309 * @param string $menu_title The text to be used for the menu. |
1505 * @param string $menu_title The text to be used for the menu. |
1310 * @param string $capability The capability required for this menu to be displayed to the user. |
1506 * @param string $capability The capability required for this menu to be displayed to the user. |
1311 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1507 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1323 * or not a page is included in the menu. |
1519 * or not a page is included in the menu. |
1324 * |
1520 * |
1325 * The function which is hooked in to handle the output of the page must check |
1521 * The function which is hooked in to handle the output of the page must check |
1326 * that the user has the required capability as well. |
1522 * that the user has the required capability as well. |
1327 * |
1523 * |
1524 * @since 2.7.0 |
|
1525 * |
|
1328 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1526 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1329 * @param string $menu_title The text to be used for the menu. |
1527 * @param string $menu_title The text to be used for the menu. |
1330 * @param string $capability The capability required for this menu to be displayed to the user. |
1528 * @param string $capability The capability required for this menu to be displayed to the user. |
1331 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1529 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1332 * @param callable $function The function to be called to output the content for this page. |
1530 * @param callable $function The function to be called to output the content for this page. |
1343 * or not a page is included in the menu. |
1541 * or not a page is included in the menu. |
1344 * |
1542 * |
1345 * The function which is hooked in to handle the output of the page must check |
1543 * The function which is hooked in to handle the output of the page must check |
1346 * that the user has the required capability as well. |
1544 * that the user has the required capability as well. |
1347 * |
1545 * |
1546 * @since 2.7.0 |
|
1547 * |
|
1348 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1548 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1349 * @param string $menu_title The text to be used for the menu. |
1549 * @param string $menu_title The text to be used for the menu. |
1350 * @param string $capability The capability required for this menu to be displayed to the user. |
1550 * @param string $capability The capability required for this menu to be displayed to the user. |
1351 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1551 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1352 * @param callable $function The function to be called to output the content for this page. |
1552 * @param callable $function The function to be called to output the content for this page. |
1363 * or not a page is included in the menu. |
1563 * or not a page is included in the menu. |
1364 * |
1564 * |
1365 * The function which is hooked in to handle the output of the page must check |
1565 * The function which is hooked in to handle the output of the page must check |
1366 * that the user has the required capability as well. |
1566 * that the user has the required capability as well. |
1367 * |
1567 * |
1568 * @since 2.7.0 |
|
1569 * |
|
1368 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1570 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1369 * @param string $menu_title The text to be used for the menu. |
1571 * @param string $menu_title The text to be used for the menu. |
1370 * @param string $capability The capability required for this menu to be displayed to the user. |
1572 * @param string $capability The capability required for this menu to be displayed to the user. |
1371 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1573 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1372 * @param callable $function The function to be called to output the content for this page. |
1574 * @param callable $function The function to be called to output the content for this page. |
1383 * or not a page is included in the menu. |
1585 * or not a page is included in the menu. |
1384 * |
1586 * |
1385 * The function which is hooked in to handle the output of the page must check |
1587 * The function which is hooked in to handle the output of the page must check |
1386 * that the user has the required capability as well. |
1588 * that the user has the required capability as well. |
1387 * |
1589 * |
1590 * @since 2.7.0 |
|
1591 * |
|
1388 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1592 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1389 * @param string $menu_title The text to be used for the menu. |
1593 * @param string $menu_title The text to be used for the menu. |
1390 * @param string $capability The capability required for this menu to be displayed to the user. |
1594 * @param string $capability The capability required for this menu to be displayed to the user. |
1391 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1595 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1392 * @param callable $function The function to be called to output the content for this page. |
1596 * @param callable $function The function to be called to output the content for this page. |
1403 * or not a page is included in the menu. |
1607 * or not a page is included in the menu. |
1404 * |
1608 * |
1405 * The function which is hooked in to handle the output of the page must check |
1609 * The function which is hooked in to handle the output of the page must check |
1406 * that the user has the required capability as well. |
1610 * that the user has the required capability as well. |
1407 * |
1611 * |
1612 * @since 2.7.0 |
|
1613 * |
|
1408 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1614 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. |
1409 * @param string $menu_title The text to be used for the menu. |
1615 * @param string $menu_title The text to be used for the menu. |
1410 * @param string $capability The capability required for this menu to be displayed to the user. |
1616 * @param string $capability The capability required for this menu to be displayed to the user. |
1411 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1617 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). |
1412 * @param callable $function The function to be called to output the content for this page. |
1618 * @param callable $function The function to be called to output the content for this page. |
1429 function remove_menu_page( $menu_slug ) { |
1635 function remove_menu_page( $menu_slug ) { |
1430 global $menu; |
1636 global $menu; |
1431 |
1637 |
1432 foreach ( $menu as $i => $item ) { |
1638 foreach ( $menu as $i => $item ) { |
1433 if ( $menu_slug == $item[2] ) { |
1639 if ( $menu_slug == $item[2] ) { |
1434 unset( $menu[$i] ); |
1640 unset( $menu[ $i ] ); |
1435 return $item; |
1641 return $item; |
1436 } |
1642 } |
1437 } |
1643 } |
1438 |
1644 |
1439 return false; |
1645 return false; |
1451 * @return array|bool The removed submenu on success, false if not found. |
1657 * @return array|bool The removed submenu on success, false if not found. |
1452 */ |
1658 */ |
1453 function remove_submenu_page( $menu_slug, $submenu_slug ) { |
1659 function remove_submenu_page( $menu_slug, $submenu_slug ) { |
1454 global $submenu; |
1660 global $submenu; |
1455 |
1661 |
1456 if ( !isset( $submenu[$menu_slug] ) ) |
1662 if ( ! isset( $submenu[ $menu_slug ] ) ) { |
1457 return false; |
1663 return false; |
1458 |
1664 } |
1459 foreach ( $submenu[$menu_slug] as $i => $item ) { |
1665 |
1666 foreach ( $submenu[ $menu_slug ] as $i => $item ) { |
|
1460 if ( $submenu_slug == $item[2] ) { |
1667 if ( $submenu_slug == $item[2] ) { |
1461 unset( $submenu[$menu_slug][$i] ); |
1668 unset( $submenu[ $menu_slug ][ $i ] ); |
1462 return $item; |
1669 return $item; |
1463 } |
1670 } |
1464 } |
1671 } |
1465 |
1672 |
1466 return false; |
1673 return false; |
1477 * |
1684 * |
1478 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) |
1685 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) |
1479 * @param bool $echo Whether or not to echo the url - default is true |
1686 * @param bool $echo Whether or not to echo the url - default is true |
1480 * @return string the url |
1687 * @return string the url |
1481 */ |
1688 */ |
1482 function menu_page_url($menu_slug, $echo = true) { |
1689 function menu_page_url( $menu_slug, $echo = true ) { |
1483 global $_parent_pages; |
1690 global $_parent_pages; |
1484 |
1691 |
1485 if ( isset( $_parent_pages[$menu_slug] ) ) { |
1692 if ( isset( $_parent_pages[ $menu_slug ] ) ) { |
1486 $parent_slug = $_parent_pages[$menu_slug]; |
1693 $parent_slug = $_parent_pages[ $menu_slug ]; |
1487 if ( $parent_slug && ! isset( $_parent_pages[$parent_slug] ) ) { |
1694 if ( $parent_slug && ! isset( $_parent_pages[ $parent_slug ] ) ) { |
1488 $url = admin_url( add_query_arg( 'page', $menu_slug, $parent_slug ) ); |
1695 $url = admin_url( add_query_arg( 'page', $menu_slug, $parent_slug ) ); |
1489 } else { |
1696 } else { |
1490 $url = admin_url( 'admin.php?page=' . $menu_slug ); |
1697 $url = admin_url( 'admin.php?page=' . $menu_slug ); |
1491 } |
1698 } |
1492 } else { |
1699 } else { |
1493 $url = ''; |
1700 $url = ''; |
1494 } |
1701 } |
1495 |
1702 |
1496 $url = esc_url($url); |
1703 $url = esc_url( $url ); |
1497 |
1704 |
1498 if ( $echo ) |
1705 if ( $echo ) { |
1499 echo $url; |
1706 echo $url; |
1707 } |
|
1500 |
1708 |
1501 return $url; |
1709 return $url; |
1502 } |
1710 } |
1503 |
1711 |
1504 // |
1712 // |
1505 // Pluggable Menu Support -- Private |
1713 // Pluggable Menu Support -- Private |
1506 // |
1714 // |
1507 /** |
1715 /** |
1508 * |
|
1509 * @global string $parent_file |
1716 * @global string $parent_file |
1510 * @global array $menu |
1717 * @global array $menu |
1511 * @global array $submenu |
1718 * @global array $submenu |
1512 * @global string $pagenow |
1719 * @global string $pagenow |
1513 * @global string $typenow |
1720 * @global string $typenow |
1514 * @global string $plugin_page |
1721 * @global string $plugin_page |
1515 * @global array $_wp_real_parent_file |
1722 * @global array $_wp_real_parent_file |
1516 * @global array $_wp_menu_nopriv |
1723 * @global array $_wp_menu_nopriv |
1517 * @global array $_wp_submenu_nopriv |
1724 * @global array $_wp_submenu_nopriv |
1725 * |
|
1726 * @return string |
|
1518 */ |
1727 */ |
1519 function get_admin_page_parent( $parent = '' ) { |
1728 function get_admin_page_parent( $parent = '' ) { |
1520 global $parent_file, $menu, $submenu, $pagenow, $typenow, |
1729 global $parent_file, $menu, $submenu, $pagenow, $typenow, |
1521 $plugin_page, $_wp_real_parent_file, $_wp_menu_nopriv, $_wp_submenu_nopriv; |
1730 $plugin_page, $_wp_real_parent_file, $_wp_menu_nopriv, $_wp_submenu_nopriv; |
1522 |
1731 |
1523 if ( !empty ( $parent ) && 'admin.php' != $parent ) { |
1732 if ( ! empty( $parent ) && 'admin.php' != $parent ) { |
1524 if ( isset( $_wp_real_parent_file[$parent] ) ) |
1733 if ( isset( $_wp_real_parent_file[ $parent ] ) ) { |
1525 $parent = $_wp_real_parent_file[$parent]; |
1734 $parent = $_wp_real_parent_file[ $parent ]; |
1735 } |
|
1526 return $parent; |
1736 return $parent; |
1527 } |
1737 } |
1528 |
1738 |
1529 if ( $pagenow == 'admin.php' && isset( $plugin_page ) ) { |
1739 if ( $pagenow == 'admin.php' && isset( $plugin_page ) ) { |
1530 foreach ( (array)$menu as $parent_menu ) { |
1740 foreach ( (array) $menu as $parent_menu ) { |
1531 if ( $parent_menu[2] == $plugin_page ) { |
1741 if ( $parent_menu[2] == $plugin_page ) { |
1532 $parent_file = $plugin_page; |
1742 $parent_file = $plugin_page; |
1533 if ( isset( $_wp_real_parent_file[$parent_file] ) ) |
1743 if ( isset( $_wp_real_parent_file[ $parent_file ] ) ) { |
1534 $parent_file = $_wp_real_parent_file[$parent_file]; |
1744 $parent_file = $_wp_real_parent_file[ $parent_file ]; |
1745 } |
|
1535 return $parent_file; |
1746 return $parent_file; |
1536 } |
1747 } |
1537 } |
1748 } |
1538 if ( isset( $_wp_menu_nopriv[$plugin_page] ) ) { |
1749 if ( isset( $_wp_menu_nopriv[ $plugin_page ] ) ) { |
1539 $parent_file = $plugin_page; |
1750 $parent_file = $plugin_page; |
1540 if ( isset( $_wp_real_parent_file[$parent_file] ) ) |
1751 if ( isset( $_wp_real_parent_file[ $parent_file ] ) ) { |
1541 $parent_file = $_wp_real_parent_file[$parent_file]; |
1752 $parent_file = $_wp_real_parent_file[ $parent_file ]; |
1753 } |
|
1542 return $parent_file; |
1754 return $parent_file; |
1543 } |
1755 } |
1544 } |
1756 } |
1545 |
1757 |
1546 if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$pagenow][$plugin_page] ) ) { |
1758 if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[ $pagenow ][ $plugin_page ] ) ) { |
1547 $parent_file = $pagenow; |
1759 $parent_file = $pagenow; |
1548 if ( isset( $_wp_real_parent_file[$parent_file] ) ) |
1760 if ( isset( $_wp_real_parent_file[ $parent_file ] ) ) { |
1549 $parent_file = $_wp_real_parent_file[$parent_file]; |
1761 $parent_file = $_wp_real_parent_file[ $parent_file ]; |
1762 } |
|
1550 return $parent_file; |
1763 return $parent_file; |
1551 } |
1764 } |
1552 |
1765 |
1553 foreach (array_keys( (array)$submenu ) as $parent) { |
1766 foreach ( array_keys( (array) $submenu ) as $parent ) { |
1554 foreach ( $submenu[$parent] as $submenu_array ) { |
1767 foreach ( $submenu[ $parent ] as $submenu_array ) { |
1555 if ( isset( $_wp_real_parent_file[$parent] ) ) |
1768 if ( isset( $_wp_real_parent_file[ $parent ] ) ) { |
1556 $parent = $_wp_real_parent_file[$parent]; |
1769 $parent = $_wp_real_parent_file[ $parent ]; |
1557 if ( !empty($typenow) && ($submenu_array[2] == "$pagenow?post_type=$typenow") ) { |
1770 } |
1771 if ( ! empty( $typenow ) && ( $submenu_array[2] == "$pagenow?post_type=$typenow" ) ) { |
|
1558 $parent_file = $parent; |
1772 $parent_file = $parent; |
1559 return $parent; |
1773 return $parent; |
1560 } elseif ( $submenu_array[2] == $pagenow && empty($typenow) && ( empty($parent_file) || false === strpos($parent_file, '?') ) ) { |
1774 } elseif ( $submenu_array[2] == $pagenow && empty( $typenow ) && ( empty( $parent_file ) || false === strpos( $parent_file, '?' ) ) ) { |
1561 $parent_file = $parent; |
1775 $parent_file = $parent; |
1562 return $parent; |
1776 return $parent; |
1563 } elseif ( isset( $plugin_page ) && ($plugin_page == $submenu_array[2] ) ) { |
1777 } elseif ( isset( $plugin_page ) && ( $plugin_page == $submenu_array[2] ) ) { |
1564 $parent_file = $parent; |
1778 $parent_file = $parent; |
1565 return $parent; |
1779 return $parent; |
1566 } |
1780 } |
1567 } |
1781 } |
1568 } |
1782 } |
1569 |
1783 |
1570 if ( empty($parent_file) ) |
1784 if ( empty( $parent_file ) ) { |
1571 $parent_file = ''; |
1785 $parent_file = ''; |
1786 } |
|
1572 return ''; |
1787 return ''; |
1573 } |
1788 } |
1574 |
1789 |
1575 /** |
1790 /** |
1576 * |
|
1577 * @global string $title |
1791 * @global string $title |
1578 * @global array $menu |
1792 * @global array $menu |
1579 * @global array $submenu |
1793 * @global array $submenu |
1580 * @global string $pagenow |
1794 * @global string $pagenow |
1581 * @global string $plugin_page |
1795 * @global string $plugin_page |
1582 * @global string $typenow |
1796 * @global string $typenow |
1797 * |
|
1798 * @return string |
|
1583 */ |
1799 */ |
1584 function get_admin_page_title() { |
1800 function get_admin_page_title() { |
1585 global $title, $menu, $submenu, $pagenow, $plugin_page, $typenow; |
1801 global $title, $menu, $submenu, $pagenow, $plugin_page, $typenow; |
1586 |
1802 |
1587 if ( ! empty ( $title ) ) |
1803 if ( ! empty( $title ) ) { |
1588 return $title; |
1804 return $title; |
1805 } |
|
1589 |
1806 |
1590 $hook = get_plugin_page_hook( $plugin_page, $pagenow ); |
1807 $hook = get_plugin_page_hook( $plugin_page, $pagenow ); |
1591 |
1808 |
1592 $parent = $parent1 = get_admin_page_parent(); |
1809 $parent = $parent1 = get_admin_page_parent(); |
1593 |
1810 |
1594 if ( empty ( $parent) ) { |
1811 if ( empty( $parent ) ) { |
1595 foreach ( (array)$menu as $menu_array ) { |
1812 foreach ( (array) $menu as $menu_array ) { |
1596 if ( isset( $menu_array[3] ) ) { |
1813 if ( isset( $menu_array[3] ) ) { |
1597 if ( $menu_array[2] == $pagenow ) { |
1814 if ( $menu_array[2] == $pagenow ) { |
1598 $title = $menu_array[3]; |
1815 $title = $menu_array[3]; |
1599 return $menu_array[3]; |
1816 return $menu_array[3]; |
1600 } elseif ( isset( $plugin_page ) && ($plugin_page == $menu_array[2] ) && ($hook == $menu_array[3] ) ) { |
1817 } elseif ( isset( $plugin_page ) && ( $plugin_page == $menu_array[2] ) && ( $hook == $menu_array[3] ) ) { |
1601 $title = $menu_array[3]; |
1818 $title = $menu_array[3]; |
1602 return $menu_array[3]; |
1819 return $menu_array[3]; |
1603 } |
1820 } |
1604 } else { |
1821 } else { |
1605 $title = $menu_array[0]; |
1822 $title = $menu_array[0]; |
1606 return $title; |
1823 return $title; |
1607 } |
1824 } |
1608 } |
1825 } |
1609 } else { |
1826 } else { |
1610 foreach ( array_keys( $submenu ) as $parent ) { |
1827 foreach ( array_keys( $submenu ) as $parent ) { |
1611 foreach ( $submenu[$parent] as $submenu_array ) { |
1828 foreach ( $submenu[ $parent ] as $submenu_array ) { |
1612 if ( isset( $plugin_page ) && |
1829 if ( isset( $plugin_page ) && |
1613 ( $plugin_page == $submenu_array[2] ) && |
1830 ( $plugin_page == $submenu_array[2] ) && |
1614 ( |
1831 ( |
1615 ( $parent == $pagenow ) || |
1832 ( $parent == $pagenow ) || |
1616 ( $parent == $plugin_page ) || |
1833 ( $parent == $plugin_page ) || |
1617 ( $plugin_page == $hook ) || |
1834 ( $plugin_page == $hook ) || |
1618 ( $pagenow == 'admin.php' && $parent1 != $submenu_array[2] ) || |
1835 ( $pagenow == 'admin.php' && $parent1 != $submenu_array[2] ) || |
1619 ( !empty($typenow) && $parent == $pagenow . '?post_type=' . $typenow) |
1836 ( ! empty( $typenow ) && $parent == $pagenow . '?post_type=' . $typenow ) |
1620 ) |
1837 ) |
1621 ) { |
1838 ) { |
1622 $title = $submenu_array[3]; |
1839 $title = $submenu_array[3]; |
1623 return $submenu_array[3]; |
1840 return $submenu_array[3]; |
1624 } |
1841 } |
1625 |
1842 |
1626 if ( $submenu_array[2] != $pagenow || isset( $_GET['page'] ) ) // not the current page |
1843 if ( $submenu_array[2] != $pagenow || isset( $_GET['page'] ) ) { // not the current page |
1627 continue; |
1844 continue; |
1845 } |
|
1628 |
1846 |
1629 if ( isset( $submenu_array[3] ) ) { |
1847 if ( isset( $submenu_array[3] ) ) { |
1630 $title = $submenu_array[3]; |
1848 $title = $submenu_array[3]; |
1631 return $submenu_array[3]; |
1849 return $submenu_array[3]; |
1632 } else { |
1850 } else { |
1633 $title = $submenu_array[0]; |
1851 $title = $submenu_array[0]; |
1634 return $title; |
1852 return $title; |
1635 } |
1853 } |
1636 } |
1854 } |
1637 } |
1855 } |
1638 if ( empty ( $title ) ) { |
1856 if ( empty( $title ) ) { |
1639 foreach ( $menu as $menu_array ) { |
1857 foreach ( $menu as $menu_array ) { |
1640 if ( isset( $plugin_page ) && |
1858 if ( isset( $plugin_page ) && |
1641 ( $plugin_page == $menu_array[2] ) && |
1859 ( $plugin_page == $menu_array[2] ) && |
1642 ( $pagenow == 'admin.php' ) && |
1860 ( $pagenow == 'admin.php' ) && |
1643 ( $parent1 == $menu_array[2] ) ) |
1861 ( $parent1 == $menu_array[2] ) ) { |
1644 { |
|
1645 $title = $menu_array[3]; |
1862 $title = $menu_array[3]; |
1646 return $menu_array[3]; |
1863 return $menu_array[3]; |
1647 } |
1864 } |
1648 } |
1865 } |
1649 } |
1866 } |
1650 } |
1867 } |
1651 |
1868 |
1652 return $title; |
1869 return $title; |
1653 } |
1870 } |
1654 |
1871 |
1655 /** |
1872 /** |
1656 * @since 2.3.0 |
1873 * @since 2.3.0 |
1657 * |
1874 * |
1658 * @param string $plugin_page |
1875 * @param string $plugin_page The slug name of the plugin page. |
1659 * @param string $parent_page |
1876 * @param string $parent_page The slug name for the parent menu (or the file name of a standard |
1660 * @return string|null |
1877 * WordPress admin page). |
1878 * @return string|null Hook attached to the plugin page, null otherwise. |
|
1661 */ |
1879 */ |
1662 function get_plugin_page_hook( $plugin_page, $parent_page ) { |
1880 function get_plugin_page_hook( $plugin_page, $parent_page ) { |
1663 $hook = get_plugin_page_hookname( $plugin_page, $parent_page ); |
1881 $hook = get_plugin_page_hookname( $plugin_page, $parent_page ); |
1664 if ( has_action($hook) ) |
1882 if ( has_action( $hook ) ) { |
1665 return $hook; |
1883 return $hook; |
1666 else |
1884 } else { |
1667 return null; |
1885 return null; |
1668 } |
1886 } |
1669 |
1887 } |
1670 /** |
1888 |
1671 * |
1889 /** |
1672 * @global array $admin_page_hooks |
1890 * @global array $admin_page_hooks |
1673 * @param string $plugin_page |
1891 * |
1674 * @param string $parent_page |
1892 * @param string $plugin_page The slug name of the plugin page. |
1893 * @param string $parent_page The slug name for the parent menu (or the file name of a standard |
|
1894 * WordPress admin page). |
|
1895 * @return string Hook name for the plugin page. |
|
1675 */ |
1896 */ |
1676 function get_plugin_page_hookname( $plugin_page, $parent_page ) { |
1897 function get_plugin_page_hookname( $plugin_page, $parent_page ) { |
1677 global $admin_page_hooks; |
1898 global $admin_page_hooks; |
1678 |
1899 |
1679 $parent = get_admin_page_parent( $parent_page ); |
1900 $parent = get_admin_page_parent( $parent_page ); |
1680 |
1901 |
1681 $page_type = 'admin'; |
1902 $page_type = 'admin'; |
1682 if ( empty ( $parent_page ) || 'admin.php' == $parent_page || isset( $admin_page_hooks[$plugin_page] ) ) { |
1903 if ( empty( $parent_page ) || 'admin.php' == $parent_page || isset( $admin_page_hooks[ $plugin_page ] ) ) { |
1683 if ( isset( $admin_page_hooks[$plugin_page] ) ) { |
1904 if ( isset( $admin_page_hooks[ $plugin_page ] ) ) { |
1684 $page_type = 'toplevel'; |
1905 $page_type = 'toplevel'; |
1685 } elseif ( isset( $admin_page_hooks[$parent] )) { |
1906 } elseif ( isset( $admin_page_hooks[ $parent ] ) ) { |
1686 $page_type = $admin_page_hooks[$parent]; |
1907 $page_type = $admin_page_hooks[ $parent ]; |
1687 } |
1908 } |
1688 } elseif ( isset( $admin_page_hooks[$parent] ) ) { |
1909 } elseif ( isset( $admin_page_hooks[ $parent ] ) ) { |
1689 $page_type = $admin_page_hooks[$parent]; |
1910 $page_type = $admin_page_hooks[ $parent ]; |
1690 } |
1911 } |
1691 |
1912 |
1692 $plugin_name = preg_replace( '!\.php!', '', $plugin_page ); |
1913 $plugin_name = preg_replace( '!\.php!', '', $plugin_page ); |
1693 |
1914 |
1694 return $page_type . '_page_' . $plugin_name; |
1915 return $page_type . '_page_' . $plugin_name; |
1695 } |
1916 } |
1696 |
1917 |
1697 /** |
1918 /** |
1698 * |
|
1699 * @global string $pagenow |
1919 * @global string $pagenow |
1700 * @global array $menu |
1920 * @global array $menu |
1701 * @global array $submenu |
1921 * @global array $submenu |
1702 * @global array $_wp_menu_nopriv |
1922 * @global array $_wp_menu_nopriv |
1703 * @global array $_wp_submenu_nopriv |
1923 * @global array $_wp_submenu_nopriv |
1704 * @global string $plugin_page |
1924 * @global string $plugin_page |
1705 * @global array $_registered_pages |
1925 * @global array $_registered_pages |
1926 * |
|
1927 * @return bool Whether the current user can access the current admin page. |
|
1706 */ |
1928 */ |
1707 function user_can_access_admin_page() { |
1929 function user_can_access_admin_page() { |
1708 global $pagenow, $menu, $submenu, $_wp_menu_nopriv, $_wp_submenu_nopriv, |
1930 global $pagenow, $menu, $submenu, $_wp_menu_nopriv, $_wp_submenu_nopriv, |
1709 $plugin_page, $_registered_pages; |
1931 $plugin_page, $_registered_pages; |
1710 |
1932 |
1711 $parent = get_admin_page_parent(); |
1933 $parent = get_admin_page_parent(); |
1712 |
1934 |
1713 if ( !isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$parent][$pagenow] ) ) |
1935 if ( ! isset( $plugin_page ) && isset( $_wp_submenu_nopriv[ $parent ][ $pagenow ] ) ) { |
1714 return false; |
1936 return false; |
1937 } |
|
1715 |
1938 |
1716 if ( isset( $plugin_page ) ) { |
1939 if ( isset( $plugin_page ) ) { |
1717 if ( isset( $_wp_submenu_nopriv[$parent][$plugin_page] ) ) |
1940 if ( isset( $_wp_submenu_nopriv[ $parent ][ $plugin_page ] ) ) { |
1718 return false; |
1941 return false; |
1719 |
1942 } |
1720 $hookname = get_plugin_page_hookname($plugin_page, $parent); |
1943 |
1721 |
1944 $hookname = get_plugin_page_hookname( $plugin_page, $parent ); |
1722 if ( !isset($_registered_pages[$hookname]) ) |
1945 |
1946 if ( ! isset( $_registered_pages[ $hookname ] ) ) { |
|
1723 return false; |
1947 return false; |
1724 } |
1948 } |
1725 |
1949 } |
1726 if ( empty( $parent) ) { |
1950 |
1727 if ( isset( $_wp_menu_nopriv[$pagenow] ) ) |
1951 if ( empty( $parent ) ) { |
1952 if ( isset( $_wp_menu_nopriv[ $pagenow ] ) ) { |
|
1728 return false; |
1953 return false; |
1729 if ( isset( $_wp_submenu_nopriv[$pagenow][$pagenow] ) ) |
1954 } |
1955 if ( isset( $_wp_submenu_nopriv[ $pagenow ][ $pagenow ] ) ) { |
|
1730 return false; |
1956 return false; |
1731 if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$pagenow][$plugin_page] ) ) |
1957 } |
1958 if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[ $pagenow ][ $plugin_page ] ) ) { |
|
1732 return false; |
1959 return false; |
1733 if ( isset( $plugin_page ) && isset( $_wp_menu_nopriv[$plugin_page] ) ) |
1960 } |
1961 if ( isset( $plugin_page ) && isset( $_wp_menu_nopriv[ $plugin_page ] ) ) { |
|
1734 return false; |
1962 return false; |
1735 foreach (array_keys( $_wp_submenu_nopriv ) as $key ) { |
1963 } |
1736 if ( isset( $_wp_submenu_nopriv[$key][$pagenow] ) ) |
1964 foreach ( array_keys( $_wp_submenu_nopriv ) as $key ) { |
1965 if ( isset( $_wp_submenu_nopriv[ $key ][ $pagenow ] ) ) { |
|
1737 return false; |
1966 return false; |
1738 if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$key][$plugin_page] ) ) |
1967 } |
1739 return false; |
1968 if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[ $key ][ $plugin_page ] ) ) { |
1969 return false; |
|
1970 } |
|
1740 } |
1971 } |
1741 return true; |
1972 return true; |
1742 } |
1973 } |
1743 |
1974 |
1744 if ( isset( $plugin_page ) && ( $plugin_page == $parent ) && isset( $_wp_menu_nopriv[$plugin_page] ) ) |
1975 if ( isset( $plugin_page ) && ( $plugin_page == $parent ) && isset( $_wp_menu_nopriv[ $plugin_page ] ) ) { |
1745 return false; |
1976 return false; |
1746 |
1977 } |
1747 if ( isset( $submenu[$parent] ) ) { |
1978 |
1748 foreach ( $submenu[$parent] as $submenu_array ) { |
1979 if ( isset( $submenu[ $parent ] ) ) { |
1980 foreach ( $submenu[ $parent ] as $submenu_array ) { |
|
1749 if ( isset( $plugin_page ) && ( $submenu_array[2] == $plugin_page ) ) { |
1981 if ( isset( $plugin_page ) && ( $submenu_array[2] == $plugin_page ) ) { |
1750 if ( current_user_can( $submenu_array[1] )) |
1982 if ( current_user_can( $submenu_array[1] ) ) { |
1751 return true; |
1983 return true; |
1752 else |
1984 } else { |
1753 return false; |
1985 return false; |
1986 } |
|
1754 } elseif ( $submenu_array[2] == $pagenow ) { |
1987 } elseif ( $submenu_array[2] == $pagenow ) { |
1755 if ( current_user_can( $submenu_array[1] )) |
1988 if ( current_user_can( $submenu_array[1] ) ) { |
1756 return true; |
1989 return true; |
1757 else |
1990 } else { |
1758 return false; |
1991 return false; |
1992 } |
|
1759 } |
1993 } |
1760 } |
1994 } |
1761 } |
1995 } |
1762 |
1996 |
1763 foreach ( $menu as $menu_array ) { |
1997 foreach ( $menu as $menu_array ) { |
1764 if ( $menu_array[2] == $parent) { |
1998 if ( $menu_array[2] == $parent ) { |
1765 if ( current_user_can( $menu_array[1] )) |
1999 if ( current_user_can( $menu_array[1] ) ) { |
1766 return true; |
2000 return true; |
1767 else |
2001 } else { |
1768 return false; |
2002 return false; |
2003 } |
|
1769 } |
2004 } |
1770 } |
2005 } |
1771 |
2006 |
1772 return true; |
2007 return true; |
1773 } |
2008 } |
1787 * @return array |
2022 * @return array |
1788 */ |
2023 */ |
1789 function option_update_filter( $options ) { |
2024 function option_update_filter( $options ) { |
1790 global $new_whitelist_options; |
2025 global $new_whitelist_options; |
1791 |
2026 |
1792 if ( is_array( $new_whitelist_options ) ) |
2027 if ( is_array( $new_whitelist_options ) ) { |
1793 $options = add_option_whitelist( $new_whitelist_options, $options ); |
2028 $options = add_option_whitelist( $new_whitelist_options, $options ); |
2029 } |
|
1794 |
2030 |
1795 return $options; |
2031 return $options; |
1796 } |
2032 } |
1797 |
2033 |
1798 /** |
2034 /** |
1805 * @param array $new_options |
2041 * @param array $new_options |
1806 * @param string|array $options |
2042 * @param string|array $options |
1807 * @return array |
2043 * @return array |
1808 */ |
2044 */ |
1809 function add_option_whitelist( $new_options, $options = '' ) { |
2045 function add_option_whitelist( $new_options, $options = '' ) { |
1810 if ( $options == '' ) |
2046 if ( $options == '' ) { |
1811 global $whitelist_options; |
2047 global $whitelist_options; |
1812 else |
2048 } else { |
1813 $whitelist_options = $options; |
2049 $whitelist_options = $options; |
2050 } |
|
1814 |
2051 |
1815 foreach ( $new_options as $page => $keys ) { |
2052 foreach ( $new_options as $page => $keys ) { |
1816 foreach ( $keys as $key ) { |
2053 foreach ( $keys as $key ) { |
1817 if ( !isset($whitelist_options[ $page ]) || !is_array($whitelist_options[ $page ]) ) { |
2054 if ( ! isset( $whitelist_options[ $page ] ) || ! is_array( $whitelist_options[ $page ] ) ) { |
1818 $whitelist_options[ $page ] = array(); |
2055 $whitelist_options[ $page ] = array(); |
1819 $whitelist_options[ $page ][] = $key; |
2056 $whitelist_options[ $page ][] = $key; |
1820 } else { |
2057 } else { |
1821 $pos = array_search( $key, $whitelist_options[ $page ] ); |
2058 $pos = array_search( $key, $whitelist_options[ $page ] ); |
1822 if ( $pos === false ) |
2059 if ( $pos === false ) { |
1823 $whitelist_options[ $page ][] = $key; |
2060 $whitelist_options[ $page ][] = $key; |
2061 } |
|
1824 } |
2062 } |
1825 } |
2063 } |
1826 } |
2064 } |
1827 |
2065 |
1828 return $whitelist_options; |
2066 return $whitelist_options; |
1838 * @param array $del_options |
2076 * @param array $del_options |
1839 * @param string|array $options |
2077 * @param string|array $options |
1840 * @return array |
2078 * @return array |
1841 */ |
2079 */ |
1842 function remove_option_whitelist( $del_options, $options = '' ) { |
2080 function remove_option_whitelist( $del_options, $options = '' ) { |
1843 if ( $options == '' ) |
2081 if ( $options == '' ) { |
1844 global $whitelist_options; |
2082 global $whitelist_options; |
1845 else |
2083 } else { |
1846 $whitelist_options = $options; |
2084 $whitelist_options = $options; |
2085 } |
|
1847 |
2086 |
1848 foreach ( $del_options as $page => $keys ) { |
2087 foreach ( $del_options as $page => $keys ) { |
1849 foreach ( $keys as $key ) { |
2088 foreach ( $keys as $key ) { |
1850 if ( isset($whitelist_options[ $page ]) && is_array($whitelist_options[ $page ]) ) { |
2089 if ( isset( $whitelist_options[ $page ] ) && is_array( $whitelist_options[ $page ] ) ) { |
1851 $pos = array_search( $key, $whitelist_options[ $page ] ); |
2090 $pos = array_search( $key, $whitelist_options[ $page ] ); |
1852 if ( $pos !== false ) |
2091 if ( $pos !== false ) { |
1853 unset( $whitelist_options[ $page ][ $pos ] ); |
2092 unset( $whitelist_options[ $page ][ $pos ] ); |
2093 } |
|
1854 } |
2094 } |
1855 } |
2095 } |
1856 } |
2096 } |
1857 |
2097 |
1858 return $whitelist_options; |
2098 return $whitelist_options; |
1863 * |
2103 * |
1864 * @since 2.7.0 |
2104 * @since 2.7.0 |
1865 * |
2105 * |
1866 * @param string $option_group A settings group name. This should match the group name used in register_setting(). |
2106 * @param string $option_group A settings group name. This should match the group name used in register_setting(). |
1867 */ |
2107 */ |
1868 function settings_fields($option_group) { |
2108 function settings_fields( $option_group ) { |
1869 echo "<input type='hidden' name='option_page' value='" . esc_attr($option_group) . "' />"; |
2109 echo "<input type='hidden' name='option_page' value='" . esc_attr( $option_group ) . "' />"; |
1870 echo '<input type="hidden" name="action" value="update" />'; |
2110 echo '<input type="hidden" name="action" value="update" />'; |
1871 wp_nonce_field("$option_group-options"); |
2111 wp_nonce_field( "$option_group-options" ); |
1872 } |
2112 } |
1873 |
2113 |
1874 /** |
2114 /** |
1875 * Clears the Plugins cache used by get_plugins() and by default, the Plugin Update cache. |
2115 * Clears the Plugins cache used by get_plugins() and by default, the Plugin Update cache. |
1876 * |
2116 * |
1877 * @since 3.7.0 |
2117 * @since 3.7.0 |
1878 * |
2118 * |
1879 * @param bool $clear_update_cache Whether to clear the Plugin updates cache |
2119 * @param bool $clear_update_cache Whether to clear the Plugin updates cache |
1880 */ |
2120 */ |
1881 function wp_clean_plugins_cache( $clear_update_cache = true ) { |
2121 function wp_clean_plugins_cache( $clear_update_cache = true ) { |
1882 if ( $clear_update_cache ) |
2122 if ( $clear_update_cache ) { |
1883 delete_site_transient( 'update_plugins' ); |
2123 delete_site_transient( 'update_plugins' ); |
2124 } |
|
1884 wp_cache_delete( 'plugins', 'plugins' ); |
2125 wp_cache_delete( 'plugins', 'plugins' ); |
1885 } |
2126 } |
1886 |
2127 |
1887 /** |
2128 /** |
1888 * Load a given plugin attempt to generate errors. |
2129 * Load a given plugin attempt to generate errors. |
1889 * |
2130 * |
1890 * @since 3.0.0 |
2131 * @since 3.0.0 |
1891 * @since 4.4.0 Function was moved into the `wp-admin/includes/plugin.php` file. |
2132 * @since 4.4.0 Function was moved into the `wp-admin/includes/plugin.php` file. |
1892 * |
2133 * |
1893 * @param string $plugin Plugin file to load. |
2134 * @param string $plugin Path to the plugin file relative to the plugins directory. |
1894 */ |
2135 */ |
1895 function plugin_sandbox_scrape( $plugin ) { |
2136 function plugin_sandbox_scrape( $plugin ) { |
2137 if ( ! defined( 'WP_SANDBOX_SCRAPING' ) ) { |
|
2138 define( 'WP_SANDBOX_SCRAPING', true ); |
|
2139 } |
|
1896 wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin ); |
2140 wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin ); |
1897 include( WP_PLUGIN_DIR . '/' . $plugin ); |
2141 include( WP_PLUGIN_DIR . '/' . $plugin ); |
1898 } |
2142 } |
1899 |
2143 |
1900 /** |
2144 /** |
1946 require_once( ABSPATH . 'wp-admin/includes/misc.php' ); |
2190 require_once( ABSPATH . 'wp-admin/includes/misc.php' ); |
1947 } |
2191 } |
1948 |
2192 |
1949 WP_Privacy_Policy_Content::add( $plugin_name, $policy_text ); |
2193 WP_Privacy_Policy_Content::add( $plugin_name, $policy_text ); |
1950 } |
2194 } |
2195 |
|
2196 /** |
|
2197 * Determines whether a plugin is technically active but was paused while |
|
2198 * loading. |
|
2199 * |
|
2200 * For more information on this and similar theme functions, check out |
|
2201 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ |
|
2202 * Conditional Tags} article in the Theme Developer Handbook. |
|
2203 * |
|
2204 * @since 5.2.0 |
|
2205 * |
|
2206 * @param string $plugin Path to the plugin file relative to the plugins directory. |
|
2207 * @return bool True, if in the list of paused plugins. False, not in the list. |
|
2208 */ |
|
2209 function is_plugin_paused( $plugin ) { |
|
2210 if ( ! isset( $GLOBALS['_paused_plugins'] ) ) { |
|
2211 return false; |
|
2212 } |
|
2213 |
|
2214 if ( ! is_plugin_active( $plugin ) ) { |
|
2215 return false; |
|
2216 } |
|
2217 |
|
2218 list( $plugin ) = explode( '/', $plugin ); |
|
2219 |
|
2220 return array_key_exists( $plugin, $GLOBALS['_paused_plugins'] ); |
|
2221 } |
|
2222 |
|
2223 /** |
|
2224 * Gets the error that was recorded for a paused plugin. |
|
2225 * |
|
2226 * @since 5.2.0 |
|
2227 * |
|
2228 * @param string $plugin Path to the plugin file relative to the plugins |
|
2229 * directory. |
|
2230 * @return array|false Array of error information as it was returned by |
|
2231 * `error_get_last()`, or false if none was recorded. |
|
2232 */ |
|
2233 function wp_get_plugin_error( $plugin ) { |
|
2234 if ( ! isset( $GLOBALS['_paused_plugins'] ) ) { |
|
2235 return false; |
|
2236 } |
|
2237 |
|
2238 list( $plugin ) = explode( '/', $plugin ); |
|
2239 |
|
2240 if ( ! array_key_exists( $plugin, $GLOBALS['_paused_plugins'] ) ) { |
|
2241 return false; |
|
2242 } |
|
2243 |
|
2244 return $GLOBALS['_paused_plugins'][ $plugin ]; |
|
2245 } |
|
2246 |
|
2247 /** |
|
2248 * Tries to resume a single plugin. |
|
2249 * |
|
2250 * If a redirect was provided, we first ensure the plugin does not throw fatal |
|
2251 * errors anymore. |
|
2252 * |
|
2253 * The way it works is by setting the redirection to the error before trying to |
|
2254 * include the plugin file. If the plugin fails, then the redirection will not |
|
2255 * be overwritten with the success message and the plugin will not be resumed. |
|
2256 * |
|
2257 * @since 5.2.0 |
|
2258 * |
|
2259 * @param string $plugin Single plugin to resume. |
|
2260 * @param string $redirect Optional. URL to redirect to. Default empty string. |
|
2261 * @return bool|WP_Error True on success, false if `$plugin` was not paused, |
|
2262 * `WP_Error` on failure. |
|
2263 */ |
|
2264 function resume_plugin( $plugin, $redirect = '' ) { |
|
2265 /* |
|
2266 * We'll override this later if the plugin could be resumed without |
|
2267 * creating a fatal error. |
|
2268 */ |
|
2269 if ( ! empty( $redirect ) ) { |
|
2270 wp_redirect( |
|
2271 add_query_arg( |
|
2272 '_error_nonce', |
|
2273 wp_create_nonce( 'plugin-resume-error_' . $plugin ), |
|
2274 $redirect |
|
2275 ) |
|
2276 ); |
|
2277 |
|
2278 // Load the plugin to test whether it throws a fatal error. |
|
2279 ob_start(); |
|
2280 plugin_sandbox_scrape( $plugin ); |
|
2281 ob_clean(); |
|
2282 } |
|
2283 |
|
2284 list( $extension ) = explode( '/', $plugin ); |
|
2285 |
|
2286 $result = wp_paused_plugins()->delete( $extension ); |
|
2287 |
|
2288 if ( ! $result ) { |
|
2289 return new WP_Error( |
|
2290 'could_not_resume_plugin', |
|
2291 __( 'Could not resume the plugin.' ) |
|
2292 ); |
|
2293 } |
|
2294 |
|
2295 return true; |
|
2296 } |
|
2297 |
|
2298 /** |
|
2299 * Renders an admin notice in case some plugins have been paused due to errors. |
|
2300 * |
|
2301 * @since 5.2.0 |
|
2302 */ |
|
2303 function paused_plugins_notice() { |
|
2304 if ( 'plugins.php' === $GLOBALS['pagenow'] ) { |
|
2305 return; |
|
2306 } |
|
2307 |
|
2308 if ( ! current_user_can( 'resume_plugins' ) ) { |
|
2309 return; |
|
2310 } |
|
2311 |
|
2312 if ( ! isset( $GLOBALS['_paused_plugins'] ) || empty( $GLOBALS['_paused_plugins'] ) ) { |
|
2313 return; |
|
2314 } |
|
2315 |
|
2316 printf( |
|
2317 '<div class="notice notice-error"><p><strong>%s</strong><br>%s</p><p><a href="%s">%s</a></p></div>', |
|
2318 __( 'One or more plugins failed to load properly.' ), |
|
2319 __( 'You can find more details and make changes on the Plugins screen.' ), |
|
2320 esc_url( admin_url( 'plugins.php?plugin_status=paused' ) ), |
|
2321 __( 'Go to the Plugins screen' ) |
|
2322 ); |
|
2323 } |