PageRenderTime 361ms CodeModel.GetById 292ms app.highlight 51ms RepoModel.GetById 2ms app.codeStats 1ms

/wp-admin/includes/plugin.php

https://bitbucket.org/acipriani/madeinapulia.com
PHP | 1897 lines | 918 code | 229 blank | 750 comment | 291 complexity | 0078443acc9a4882c3ad3da7bdd14920 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/**
   3 * WordPress Plugin Administration API
   4 *
   5 * @package WordPress
   6 * @subpackage Administration
   7 */
   8
   9/**
  10 * Parse the plugin contents to retrieve plugin's metadata.
  11 *
  12 * The metadata of the plugin's data searches for the following in the plugin's
  13 * header. All plugin data must be on its own line. For plugin description, it
  14 * must not have any newlines or only parts of the description will be displayed
  15 * and the same goes for the plugin data. The below is formatted for printing.
  16 *
  17 *     /*
  18 *     Plugin Name: Name of Plugin
  19 *     Plugin URI: Link to plugin information
  20 *     Description: Plugin Description
  21 *     Author: Plugin author's name
  22 *     Author URI: Link to the author's web site
  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
  25 *    		plugin_text_domain()
  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
  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
  30 *    		located in.
  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
  33 *    		activated on a single site when Multisite is enabled.
  34 *      * / # Remove the space to close comment
  35 *
  36 * Plugin data returned array contains the following:
  37 *
  38 * - 'Name' - Name of the plugin, must be unique.
  39 * - 'Title' - Title of the plugin and the link to the plugin's web site.
  40 * - 'Description' - Description of what the plugin does and/or notes
  41 * - from the author.
  42 * - 'Author' - The author's name
  43 * - 'AuthorURI' - The authors web site address.
  44 * - 'Version' - The plugin version number.
  45 * - 'PluginURI' - Plugin web site address.
  46 * - 'TextDomain' - Plugin's text domain for localization.
  47 * - 'DomainPath' - Plugin's relative directory path to .mo files.
  48 * - 'Network' - Boolean. Whether the plugin can only be activated network wide.
  49 *
  50 * Some users have issues with opening large files and manipulating the contents
  51 * for want is usually the first 1kiB or 2kiB. This function stops pulling in
  52 * the plugin contents when it has all of the required plugin data.
  53 *
  54 * The first 8kiB of the file will be pulled in and if the plugin data is not
  55 * within that first 8kiB, then the plugin author should correct their plugin
  56 * and move the plugin data headers to the top.
  57 *
  58 * The plugin file is assumed to have permissions to allow for scripts to read
  59 * the file. This is not checked however and the file is only opened for
  60 * reading.
  61 *
  62 * @link https://core.trac.wordpress.org/ticket/5651 Previous Optimizations.
  63 * @link https://core.trac.wordpress.org/ticket/7372 Further and better Optimizations.
  64 *
  65 * @since 1.5.0
  66 *
  67 * @param string $plugin_file Path to the plugin file
  68 * @param bool $markup Optional. If the returned data should have HTML markup applied. Defaults to true.
  69 * @param bool $translate Optional. If the returned data should be translated. Defaults to true.
  70 * @return array See above for description.
  71 */
  72function get_plugin_data( $plugin_file, $markup = true, $translate = true ) {
  73
  74	$default_headers = array(
  75		'Name' => 'Plugin Name',
  76		'PluginURI' => 'Plugin URI',
  77		'Version' => 'Version',
  78		'Description' => 'Description',
  79		'Author' => 'Author',
  80		'AuthorURI' => 'Author URI',
  81		'TextDomain' => 'Text Domain',
  82		'DomainPath' => 'Domain Path',
  83		'Network' => 'Network',
  84		// Site Wide Only is deprecated in favor of Network.
  85		'_sitewide' => 'Site Wide Only',
  86	);
  87
  88	$plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' );
  89
  90	// Site Wide Only is the old header for Network
  91	if ( ! $plugin_data['Network'] && $plugin_data['_sitewide'] ) {
  92		_deprecated_argument( __FUNCTION__, '3.0', sprintf( __( 'The <code>%1$s</code> plugin header is deprecated. Use <code>%2$s</code> instead.' ), 'Site Wide Only: true', 'Network: true' ) );
  93		$plugin_data['Network'] = $plugin_data['_sitewide'];
  94	}
  95	$plugin_data['Network'] = ( 'true' == strtolower( $plugin_data['Network'] ) );
  96	unset( $plugin_data['_sitewide'] );
  97
  98	if ( $markup || $translate ) {
  99		$plugin_data = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup, $translate );
 100	} else {
 101		$plugin_data['Title']      = $plugin_data['Name'];
 102		$plugin_data['AuthorName'] = $plugin_data['Author'];
 103	}
 104
 105	return $plugin_data;
 106}
 107
 108/**
 109 * Sanitizes plugin data, optionally adds markup, optionally translates.
 110 *
 111 * @since 2.7.0
 112 * @access private
 113 * @see get_plugin_data()
 114 */
 115function _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup = true, $translate = true ) {
 116
 117	// Sanitize the plugin filename to a WP_PLUGIN_DIR relative path
 118	$plugin_file = plugin_basename( $plugin_file );
 119
 120	// Translate fields
 121	if ( $translate ) {
 122		if ( $textdomain = $plugin_data['TextDomain'] ) {
 123			if ( $plugin_data['DomainPath'] )
 124				load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) . $plugin_data['DomainPath'] );
 125			else
 126				load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) );
 127		} elseif ( in_array( basename( $plugin_file ), array( 'hello.php', 'akismet.php' ) ) ) {
 128			$textdomain = 'default';
 129		}
 130		if ( $textdomain ) {
 131			foreach ( array( 'Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version' ) as $field )
 132				$plugin_data[ $field ] = translate( $plugin_data[ $field ], $textdomain );
 133		}
 134	}
 135
 136	// Sanitize fields
 137	$allowed_tags = $allowed_tags_in_links = array(
 138		'abbr'    => array( 'title' => true ),
 139		'acronym' => array( 'title' => true ),
 140		'code'    => true,
 141		'em'      => true,
 142		'strong'  => true,
 143	);
 144	$allowed_tags['a'] = array( 'href' => true, 'title' => true );
 145
 146	// Name is marked up inside <a> tags. Don't allow these.
 147	// Author is too, but some plugins have used <a> here (omitting Author URI).
 148	$plugin_data['Name']        = wp_kses( $plugin_data['Name'],        $allowed_tags_in_links );
 149	$plugin_data['Author']      = wp_kses( $plugin_data['Author'],      $allowed_tags );
 150
 151	$plugin_data['Description'] = wp_kses( $plugin_data['Description'], $allowed_tags );
 152	$plugin_data['Version']     = wp_kses( $plugin_data['Version'],     $allowed_tags );
 153
 154	$plugin_data['PluginURI']   = esc_url( $plugin_data['PluginURI'] );
 155	$plugin_data['AuthorURI']   = esc_url( $plugin_data['AuthorURI'] );
 156
 157	$plugin_data['Title']      = $plugin_data['Name'];
 158	$plugin_data['AuthorName'] = $plugin_data['Author'];
 159
 160	// Apply markup
 161	if ( $markup ) {
 162		if ( $plugin_data['PluginURI'] && $plugin_data['Name'] )
 163			$plugin_data['Title'] = '<a href="' . $plugin_data['PluginURI'] . '">' . $plugin_data['Name'] . '</a>';
 164
 165		if ( $plugin_data['AuthorURI'] && $plugin_data['Author'] )
 166			$plugin_data['Author'] = '<a href="' . $plugin_data['AuthorURI'] . '">' . $plugin_data['Author'] . '</a>';
 167
 168		$plugin_data['Description'] = wptexturize( $plugin_data['Description'] );
 169
 170		if ( $plugin_data['Author'] )
 171			$plugin_data['Description'] .= ' <cite>' . sprintf( __('By %s.'), $plugin_data['Author'] ) . '</cite>';
 172	}
 173
 174	return $plugin_data;
 175}
 176
 177/**
 178 * Get a list of a plugin's files.
 179 *
 180 * @since 2.8.0
 181 *
 182 * @param string $plugin Plugin ID
 183 * @return array List of files relative to the plugin root.
 184 */
 185function get_plugin_files($plugin) {
 186	$plugin_file = WP_PLUGIN_DIR . '/' . $plugin;
 187	$dir = dirname($plugin_file);
 188	$plugin_files = array($plugin);
 189	if ( is_dir($dir) && $dir != WP_PLUGIN_DIR ) {
 190		$plugins_dir = @ opendir( $dir );
 191		if ( $plugins_dir ) {
 192			while (($file = readdir( $plugins_dir ) ) !== false ) {
 193				if ( substr($file, 0, 1) == '.' )
 194					continue;
 195				if ( is_dir( $dir . '/' . $file ) ) {
 196					$plugins_subdir = @ opendir( $dir . '/' . $file );
 197					if ( $plugins_subdir ) {
 198						while (($subfile = readdir( $plugins_subdir ) ) !== false ) {
 199							if ( substr($subfile, 0, 1) == '.' )
 200								continue;
 201							$plugin_files[] = plugin_basename("$dir/$file/$subfile");
 202						}
 203						@closedir( $plugins_subdir );
 204					}
 205				} else {
 206					if ( plugin_basename("$dir/$file") != $plugin )
 207						$plugin_files[] = plugin_basename("$dir/$file");
 208				}
 209			}
 210			@closedir( $plugins_dir );
 211		}
 212	}
 213
 214	return $plugin_files;
 215}
 216
 217/**
 218 * Check the plugins directory and retrieve all plugin files with plugin data.
 219 *
 220 * WordPress only supports plugin files in the base plugins directory
 221 * (wp-content/plugins) and in one directory above the plugins directory
 222 * (wp-content/plugins/my-plugin). The file it looks for has the plugin data and
 223 * must be found in those two locations. It is recommended that do keep your
 224 * plugin files in directories.
 225 *
 226 * The file with the plugin data is the file that will be included and therefore
 227 * needs to have the main execution for the plugin. This does not mean
 228 * everything must be contained in the file and it is recommended that the file
 229 * be split for maintainability. Keep everything in one file for extreme
 230 * optimization purposes.
 231 *
 232 * @since 1.5.0
 233 *
 234 * @param string $plugin_folder Optional. Relative path to single plugin folder.
 235 * @return array Key is the plugin file path and the value is an array of the plugin data.
 236 */
 237function get_plugins($plugin_folder = '') {
 238
 239	if ( ! $cache_plugins = wp_cache_get('plugins', 'plugins') )
 240		$cache_plugins = array();
 241
 242	if ( isset($cache_plugins[ $plugin_folder ]) )
 243		return $cache_plugins[ $plugin_folder ];
 244
 245	$wp_plugins = array ();
 246	$plugin_root = WP_PLUGIN_DIR;
 247	if ( !empty($plugin_folder) )
 248		$plugin_root .= $plugin_folder;
 249
 250	// Files in wp-content/plugins directory
 251	$plugins_dir = @ opendir( $plugin_root);
 252	$plugin_files = array();
 253	if ( $plugins_dir ) {
 254		while (($file = readdir( $plugins_dir ) ) !== false ) {
 255			if ( substr($file, 0, 1) == '.' )
 256				continue;
 257			if ( is_dir( $plugin_root.'/'.$file ) ) {
 258				$plugins_subdir = @ opendir( $plugin_root.'/'.$file );
 259				if ( $plugins_subdir ) {
 260					while (($subfile = readdir( $plugins_subdir ) ) !== false ) {
 261						if ( substr($subfile, 0, 1) == '.' )
 262							continue;
 263						if ( substr($subfile, -4) == '.php' )
 264							$plugin_files[] = "$file/$subfile";
 265					}
 266					closedir( $plugins_subdir );
 267				}
 268			} else {
 269				if ( substr($file, -4) == '.php' )
 270					$plugin_files[] = $file;
 271			}
 272		}
 273		closedir( $plugins_dir );
 274	}
 275
 276	if ( empty($plugin_files) )
 277		return $wp_plugins;
 278
 279	foreach ( $plugin_files as $plugin_file ) {
 280		if ( !is_readable( "$plugin_root/$plugin_file" ) )
 281			continue;
 282
 283		$plugin_data = get_plugin_data( "$plugin_root/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached.
 284
 285		if ( empty ( $plugin_data['Name'] ) )
 286			continue;
 287
 288		$wp_plugins[plugin_basename( $plugin_file )] = $plugin_data;
 289	}
 290
 291	uasort( $wp_plugins, '_sort_uname_callback' );
 292
 293	$cache_plugins[ $plugin_folder ] = $wp_plugins;
 294	wp_cache_set('plugins', $cache_plugins, 'plugins');
 295
 296	return $wp_plugins;
 297}
 298
 299/**
 300 * Check the mu-plugins directory and retrieve all mu-plugin files with any plugin data.
 301 *
 302 * WordPress only includes mu-plugin files in the base mu-plugins directory (wp-content/mu-plugins).
 303 *
 304 * @since 3.0.0
 305 * @return array Key is the mu-plugin file path and the value is an array of the mu-plugin data.
 306 */
 307function get_mu_plugins() {
 308	$wp_plugins = array();
 309	// Files in wp-content/mu-plugins directory
 310	$plugin_files = array();
 311
 312	if ( ! is_dir( WPMU_PLUGIN_DIR ) )
 313		return $wp_plugins;
 314	if ( $plugins_dir = @ opendir( WPMU_PLUGIN_DIR ) ) {
 315		while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
 316			if ( substr( $file, -4 ) == '.php' )
 317				$plugin_files[] = $file;
 318		}
 319	} else {
 320		return $wp_plugins;
 321	}
 322
 323	@closedir( $plugins_dir );
 324
 325	if ( empty($plugin_files) )
 326		return $wp_plugins;
 327
 328	foreach ( $plugin_files as $plugin_file ) {
 329		if ( !is_readable( WPMU_PLUGIN_DIR . "/$plugin_file" ) )
 330			continue;
 331
 332		$plugin_data = get_plugin_data( WPMU_PLUGIN_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached.
 333
 334		if ( empty ( $plugin_data['Name'] ) )
 335			$plugin_data['Name'] = $plugin_file;
 336
 337		$wp_plugins[ $plugin_file ] = $plugin_data;
 338	}
 339
 340	if ( isset( $wp_plugins['index.php'] ) && filesize( WPMU_PLUGIN_DIR . '/index.php') <= 30 ) // silence is golden
 341		unset( $wp_plugins['index.php'] );
 342
 343	uasort( $wp_plugins, '_sort_uname_callback' );
 344
 345	return $wp_plugins;
 346}
 347
 348/**
 349 * Callback to sort array by a 'Name' key.
 350 *
 351 * @since 3.1.0
 352 * @access private
 353 */
 354function _sort_uname_callback( $a, $b ) {
 355	return strnatcasecmp( $a['Name'], $b['Name'] );
 356}
 357
 358/**
 359 * Check the wp-content directory and retrieve all drop-ins with any plugin data.
 360 *
 361 * @since 3.0.0
 362 * @return array Key is the file path and the value is an array of the plugin data.
 363 */
 364function get_dropins() {
 365	$dropins = array();
 366	$plugin_files = array();
 367
 368	$_dropins = _get_dropins();
 369
 370	// These exist in the wp-content directory
 371	if ( $plugins_dir = @ opendir( WP_CONTENT_DIR ) ) {
 372		while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
 373			if ( isset( $_dropins[ $file ] ) )
 374				$plugin_files[] = $file;
 375		}
 376	} else {
 377		return $dropins;
 378	}
 379
 380	@closedir( $plugins_dir );
 381
 382	if ( empty($plugin_files) )
 383		return $dropins;
 384
 385	foreach ( $plugin_files as $plugin_file ) {
 386		if ( !is_readable( WP_CONTENT_DIR . "/$plugin_file" ) )
 387			continue;
 388		$plugin_data = get_plugin_data( WP_CONTENT_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached.
 389		if ( empty( $plugin_data['Name'] ) )
 390			$plugin_data['Name'] = $plugin_file;
 391		$dropins[ $plugin_file ] = $plugin_data;
 392	}
 393
 394	uksort( $dropins, 'strnatcasecmp' );
 395
 396	return $dropins;
 397}
 398
 399/**
 400 * Returns drop-ins that WordPress uses.
 401 *
 402 * Includes Multisite drop-ins only when is_multisite()
 403 *
 404 * @since 3.0.0
 405 * @return array Key is file name. The value is an array, with the first value the
 406 *	purpose of the drop-in and the second value the name of the constant that must be
 407 *	true for the drop-in to be used, or true if no constant is required.
 408 */
 409function _get_dropins() {
 410	$dropins = array(
 411		'advanced-cache.php' => array( __( 'Advanced caching plugin.'       ), 'WP_CACHE' ), // WP_CACHE
 412		'db.php'             => array( __( 'Custom database class.'         ), true ), // auto on load
 413		'db-error.php'       => array( __( 'Custom database error message.' ), true ), // auto on error
 414		'install.php'        => array( __( 'Custom install script.'         ), true ), // auto on install
 415		'maintenance.php'    => array( __( 'Custom maintenance message.'    ), true ), // auto on maintenance
 416		'object-cache.php'   => array( __( 'External object cache.'         ), true ), // auto on load
 417	);
 418
 419	if ( is_multisite() ) {
 420		$dropins['sunrise.php'       ] = array( __( 'Executed before Multisite is loaded.' ), 'SUNRISE' ); // SUNRISE
 421		$dropins['blog-deleted.php'  ] = array( __( 'Custom site deleted message.'   ), true ); // auto on deleted blog
 422		$dropins['blog-inactive.php' ] = array( __( 'Custom site inactive message.'  ), true ); // auto on inactive blog
 423		$dropins['blog-suspended.php'] = array( __( 'Custom site suspended message.' ), true ); // auto on archived or spammed blog
 424	}
 425
 426	return $dropins;
 427}
 428
 429/**
 430 * Check whether the plugin is active by checking the active_plugins list.
 431 *
 432 * @since 2.5.0
 433 *
 434 * @param string $plugin Base plugin path from plugins directory.
 435 * @return bool True, if in the active plugins list. False, not in the list.
 436 */
 437function is_plugin_active( $plugin ) {
 438	return in_array( $plugin, (array) get_option( 'active_plugins', array() ) ) || is_plugin_active_for_network( $plugin );
 439}
 440
 441/**
 442 * Check whether the plugin is inactive.
 443 *
 444 * Reverse of is_plugin_active(). Used as a callback.
 445 *
 446 * @since 3.1.0
 447 * @see is_plugin_active()
 448 *
 449 * @param string $plugin Base plugin path from plugins directory.
 450 * @return bool True if inactive. False if active.
 451 */
 452function is_plugin_inactive( $plugin ) {
 453	return ! is_plugin_active( $plugin );
 454}
 455
 456/**
 457 * Check whether the plugin is active for the entire network.
 458 *
 459 * @since 3.0.0
 460 *
 461 * @param string $plugin Base plugin path from plugins directory.
 462 * @return bool True, if active for the network, otherwise false.
 463 */
 464function is_plugin_active_for_network( $plugin ) {
 465	if ( !is_multisite() )
 466		return false;
 467
 468	$plugins = get_site_option( 'active_sitewide_plugins');
 469	if ( isset($plugins[$plugin]) )
 470		return true;
 471
 472	return false;
 473}
 474
 475/**
 476 * Checks for "Network: true" in the plugin header to see if this should
 477 * be activated only as a network wide plugin. The plugin would also work
 478 * when Multisite is not enabled.
 479 *
 480 * Checks for "Site Wide Only: true" for backwards compatibility.
 481 *
 482 * @since 3.0.0
 483 *
 484 * @param string $plugin Plugin to check
 485 * @return bool True if plugin is network only, false otherwise.
 486 */
 487function is_network_only_plugin( $plugin ) {
 488	$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
 489	if ( $plugin_data )
 490		return $plugin_data['Network'];
 491	return false;
 492}
 493
 494/**
 495 * Attempts activation of plugin in a "sandbox" and redirects on success.
 496 *
 497 * A plugin that is already activated will not attempt to be activated again.
 498 *
 499 * The way it works is by setting the redirection to the error before trying to
 500 * include the plugin file. If the plugin fails, then the redirection will not
 501 * be overwritten with the success message. Also, the options will not be
 502 * updated and the activation hook will not be called on plugin error.
 503 *
 504 * It should be noted that in no way the below code will actually prevent errors
 505 * within the file. The code should not be used elsewhere to replicate the
 506 * "sandbox", which uses redirection to work.
 507 * {@source 13 1}
 508 *
 509 * If any errors are found or text is outputted, then it will be captured to
 510 * ensure that the success redirection will update the error redirection.
 511 *
 512 * @since 2.5.0
 513 *
 514 * @param string $plugin Plugin path to main plugin file with plugin data.
 515 * @param string $redirect Optional. URL to redirect to.
 516 * @param bool $network_wide Whether to enable the plugin for all sites in the
 517 *   network or just the current site. Multisite only. Default is false.
 518 * @param bool $silent Prevent calling activation hooks. Optional, default is false.
 519 * @return WP_Error|null WP_Error on invalid file or null on success.
 520 */
 521function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) {
 522	$plugin = plugin_basename( trim( $plugin ) );
 523
 524	if ( is_multisite() && ( $network_wide || is_network_only_plugin($plugin) ) ) {
 525		$network_wide = true;
 526		$current = get_site_option( 'active_sitewide_plugins', array() );
 527		$_GET['networkwide'] = 1; // Back compat for plugins looking for this value.
 528	} else {
 529		$current = get_option( 'active_plugins', array() );
 530	}
 531
 532	$valid = validate_plugin($plugin);
 533	if ( is_wp_error($valid) )
 534		return $valid;
 535
 536	if ( ( $network_wide && ! isset( $current[ $plugin ] ) ) || ( ! $network_wide && ! in_array( $plugin, $current ) ) ) {
 537		if ( !empty($redirect) )
 538			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
 539		ob_start();
 540		wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin );
 541		$_wp_plugin_file = $plugin;
 542		include_once( WP_PLUGIN_DIR . '/' . $plugin );
 543		$plugin = $_wp_plugin_file; // Avoid stomping of the $plugin variable in a plugin.
 544
 545		if ( ! $silent ) {
 546			/**
 547			 * Fires before a plugin is activated.
 548			 *
 549			 * If a plugin is silently activated (such as during an update),
 550			 * this hook does not fire.
 551			 *
 552			 * @since 2.9.0
 553			 *
 554			 * @param string $plugin       Plugin path to main plugin file with plugin data.
 555			 * @param bool   $network_wide Whether to enable the plugin for all sites in the network
 556			 *                             or just the current site. Multisite only. Default is false.
 557			 */
 558			do_action( 'activate_plugin', $plugin, $network_wide );
 559
 560			/**
 561			 * Fires as a specific plugin is being activated.
 562			 *
 563			 * This hook is the "activation" hook used internally by
 564			 * {@see register_activation_hook()}. The dynamic portion of the
 565			 * hook name, `$plugin`, refers to the plugin basename.
 566			 *
 567			 * If a plugin is silently activated (such as during an update),
 568			 * this hook does not fire.
 569			 *
 570			 * @since 2.0.0
 571			 *
 572			 * @param bool $network_wide Whether to enable the plugin for all sites in the network
 573			 *                           or just the current site. Multisite only. Default is false.
 574			 */
 575			do_action( 'activate_' . $plugin, $network_wide );
 576		}
 577
 578		if ( $network_wide ) {
 579			$current[$plugin] = time();
 580			update_site_option( 'active_sitewide_plugins', $current );
 581		} else {
 582			$current[] = $plugin;
 583			sort($current);
 584			update_option('active_plugins', $current);
 585		}
 586
 587		if ( ! $silent ) {
 588			/**
 589			 * Fires after a plugin has been activated.
 590			 *
 591			 * If a plugin is silently activated (such as during an update),
 592			 * this hook does not fire.
 593			 *
 594			 * @since 2.9.0
 595			 *
 596			 * @param string $plugin       Plugin path to main plugin file with plugin data.
 597			 * @param bool   $network_wide Whether to enable the plugin for all sites in the network
 598			 *                             or just the current site. Multisite only. Default is false.
 599			 */
 600			do_action( 'activated_plugin', $plugin, $network_wide );
 601		}
 602
 603		if ( ob_get_length() > 0 ) {
 604			$output = ob_get_clean();
 605			return new WP_Error('unexpected_output', __('The plugin generated unexpected output.'), $output);
 606		}
 607		ob_end_clean();
 608	}
 609
 610	return null;
 611}
 612
 613/**
 614 * Deactivate a single plugin or multiple plugins.
 615 *
 616 * The deactivation hook is disabled by the plugin upgrader by using the $silent
 617 * parameter.
 618 *
 619 * @since 2.5.0
 620 *
 621 * @param string|array $plugins Single plugin or list of plugins to deactivate.
 622 * @param bool $silent Prevent calling deactivation hooks. Default is false.
 623 * @param mixed $network_wide Whether to deactivate the plugin for all sites in the network.
 624 * 	A value of null (the default) will deactivate plugins for both the site and the network.
 625 */
 626function deactivate_plugins( $plugins, $silent = false, $network_wide = null ) {
 627	if ( is_multisite() )
 628		$network_current = get_site_option( 'active_sitewide_plugins', array() );
 629	$current = get_option( 'active_plugins', array() );
 630	$do_blog = $do_network = false;
 631
 632	foreach ( (array) $plugins as $plugin ) {
 633		$plugin = plugin_basename( trim( $plugin ) );
 634		if ( ! is_plugin_active($plugin) )
 635			continue;
 636
 637		$network_deactivating = false !== $network_wide && is_plugin_active_for_network( $plugin );
 638
 639		if ( ! $silent ) {
 640			/**
 641			 * Fires before a plugin is deactivated.
 642			 *
 643			 * If a plugin is silently deactivated (such as during an update),
 644			 * this hook does not fire.
 645			 *
 646			 * @since 2.9.0
 647			 *
 648			 * @param string $plugin               Plugin path to main plugin file with plugin data.
 649			 * @param bool   $network_deactivating Whether the plugin is deactivated for all sites in the network
 650			 *                                     or just the current site. Multisite only. Default is false.
 651			 */
 652			do_action( 'deactivate_plugin', $plugin, $network_deactivating );
 653		}
 654
 655		if ( false !== $network_wide ) {
 656			if ( is_plugin_active_for_network( $plugin ) ) {
 657				$do_network = true;
 658				unset( $network_current[ $plugin ] );
 659			} elseif ( $network_wide ) {
 660				continue;
 661			}
 662		}
 663
 664		if ( true !== $network_wide ) {
 665			$key = array_search( $plugin, $current );
 666			if ( false !== $key ) {
 667				$do_blog = true;
 668				unset( $current[ $key ] );
 669			}
 670		}
 671
 672		if ( ! $silent ) {
 673			/**
 674			 * Fires as a specific plugin is being deactivated.
 675			 *
 676			 * This hook is the "deactivation" hook used internally by
 677			 * {@see register_deactivation_hook()}. The dynamic portion of the
 678			 * hook name, `$plugin`, refers to the plugin basename.
 679			 *
 680			 * If a plugin is silently deactivated (such as during an update),
 681			 * this hook does not fire.
 682			 *
 683			 * @since 2.0.0
 684			 *
 685			 * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network
 686			 *                                   or just the current site. Multisite only. Default is false.
 687			 */
 688			do_action( 'deactivate_' . $plugin, $network_deactivating );
 689
 690			/**
 691			 * Fires after a plugin is deactivated.
 692			 *
 693			 * If a plugin is silently deactivated (such as during an update),
 694			 * this hook does not fire.
 695			 *
 696			 * @since 2.9.0
 697			 *
 698			 * @param string $plugin               Plugin basename.
 699			 * @param bool   $network_deactivating Whether the plugin is deactivated for all sites in the network
 700			 *                                     or just the current site. Multisite only. Default false.
 701			 */
 702			do_action( 'deactivated_plugin', $plugin, $network_deactivating );
 703		}
 704	}
 705
 706	if ( $do_blog )
 707		update_option('active_plugins', $current);
 708	if ( $do_network )
 709		update_site_option( 'active_sitewide_plugins', $network_current );
 710}
 711
 712/**
 713 * Activate multiple plugins.
 714 *
 715 * When WP_Error is returned, it does not mean that one of the plugins had
 716 * errors. It means that one or more of the plugins file path was invalid.
 717 *
 718 * The execution will be halted as soon as one of the plugins has an error.
 719 *
 720 * @since 2.6.0
 721 *
 722 * @param string|array $plugins Single plugin or list of plugins to activate.
 723 * @param string $redirect Redirect to page after successful activation.
 724 * @param bool $network_wide Whether to enable the plugin for all sites in the network.
 725 * @param bool $silent Prevent calling activation hooks. Default is false.
 726 * @return bool|WP_Error True when finished or WP_Error if there were errors during a plugin activation.
 727 */
 728function activate_plugins( $plugins, $redirect = '', $network_wide = false, $silent = false ) {
 729	if ( !is_array($plugins) )
 730		$plugins = array($plugins);
 731
 732	$errors = array();
 733	foreach ( $plugins as $plugin ) {
 734		if ( !empty($redirect) )
 735			$redirect = add_query_arg('plugin', $plugin, $redirect);
 736		$result = activate_plugin($plugin, $redirect, $network_wide, $silent);
 737		if ( is_wp_error($result) )
 738			$errors[$plugin] = $result;
 739	}
 740
 741	if ( !empty($errors) )
 742		return new WP_Error('plugins_invalid', __('One of the plugins is invalid.'), $errors);
 743
 744	return true;
 745}
 746
 747/**
 748 * Remove directory and files of a plugin for a list of plugins.
 749 *
 750 * @since 2.6.0
 751 *
 752 * @param array  $plugins    List of plugins to delete.
 753 * @param string $deprecated Deprecated.
 754 * @return bool|null|WP_Error True on success, false is $plugins is empty, WP_Error on failure.
 755 *                            Null if filesystem credentials are required to proceed.
 756 */
 757function delete_plugins( $plugins, $deprecated = '' ) {
 758	global $wp_filesystem;
 759
 760	if ( empty($plugins) )
 761		return false;
 762
 763	$checked = array();
 764	foreach( $plugins as $plugin )
 765		$checked[] = 'checked[]=' . $plugin;
 766
 767	ob_start();
 768	$url = wp_nonce_url('plugins.php?action=delete-selected&verify-delete=1&' . implode('&', $checked), 'bulk-plugins');
 769	if ( false === ($credentials = request_filesystem_credentials($url)) ) {
 770		$data = ob_get_contents();
 771		ob_end_clean();
 772		if ( ! empty($data) ){
 773			include_once( ABSPATH . 'wp-admin/admin-header.php');
 774			echo $data;
 775			include( ABSPATH . 'wp-admin/admin-footer.php');
 776			exit;
 777		}
 778		return;
 779	}
 780
 781	if ( ! WP_Filesystem($credentials) ) {
 782		request_filesystem_credentials($url, '', true); //Failed to connect, Error and request again
 783		$data = ob_get_contents();
 784		ob_end_clean();
 785		if ( ! empty($data) ){
 786			include_once( ABSPATH . 'wp-admin/admin-header.php');
 787			echo $data;
 788			include( ABSPATH . 'wp-admin/admin-footer.php');
 789			exit;
 790		}
 791		return;
 792	}
 793
 794	if ( ! is_object($wp_filesystem) )
 795		return new WP_Error('fs_unavailable', __('Could not access filesystem.'));
 796
 797	if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() )
 798		return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors);
 799
 800	// Get the base plugin folder.
 801	$plugins_dir = $wp_filesystem->wp_plugins_dir();
 802	if ( empty( $plugins_dir ) ) {
 803		return new WP_Error( 'fs_no_plugins_dir', __( 'Unable to locate WordPress Plugin directory.' ) );
 804	}
 805
 806	$plugins_dir = trailingslashit( $plugins_dir );
 807
 808	$translations_dir = $wp_filesystem->wp_lang_dir();
 809	$translations_dir = trailingslashit( $translations_dir );
 810
 811	$plugin_translations = wp_get_installed_translations( 'plugins' );
 812
 813	$errors = array();
 814
 815	foreach( $plugins as $plugin_file ) {
 816		// Run Uninstall hook.
 817		if ( is_uninstallable_plugin( $plugin_file ) ) {
 818			uninstall_plugin($plugin_file);
 819		}
 820
 821		$this_plugin_dir = trailingslashit( dirname( $plugins_dir . $plugin_file ) );
 822		// If plugin is in its own directory, recursively delete the directory.
 823		if ( strpos( $plugin_file, '/' ) && $this_plugin_dir != $plugins_dir ) { //base check on if plugin includes directory separator AND that it's not the root plugin folder
 824			$deleted = $wp_filesystem->delete( $this_plugin_dir, true );
 825		} else {
 826			$deleted = $wp_filesystem->delete( $plugins_dir . $plugin_file );
 827		}
 828
 829		if ( ! $deleted ) {
 830			$errors[] = $plugin_file;
 831			continue;
 832		}
 833
 834		// Remove language files, silently.
 835		$plugin_slug = dirname( $plugin_file );
 836		if ( '.' !== $plugin_slug && ! empty( $plugin_translations[ $plugin_slug ] ) ) {
 837			$translations = $plugin_translations[ $plugin_slug ];
 838
 839			foreach ( $translations as $translation => $data ) {
 840				$wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.po' );
 841				$wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.mo' );
 842			}
 843		}
 844	}
 845
 846	// Remove deleted plugins from the plugin updates list.
 847	if ( $current = get_site_transient('update_plugins') ) {
 848		// Don't remove the plugins that weren't deleted.
 849		$deleted = array_diff( $plugins, $errors );
 850
 851		foreach ( $deleted as $plugin_file ) {
 852			unset( $current->response[ $plugin_file ] );
 853		}
 854
 855		set_site_transient( 'update_plugins', $current );
 856	}
 857
 858	if ( ! empty($errors) )
 859		return new WP_Error('could_not_remove_plugin', sprintf(__('Could not fully remove the plugin(s) %s.'), implode(', ', $errors)) );
 860
 861	return true;
 862}
 863
 864/**
 865 * Validate active plugins
 866 *
 867 * Validate all active plugins, deactivates invalid and
 868 * returns an array of deactivated ones.
 869 *
 870 * @since 2.5.0
 871 * @return array invalid plugins, plugin as key, error as value
 872 */
 873function validate_active_plugins() {
 874	$plugins = get_option( 'active_plugins', array() );
 875	// Validate vartype: array.
 876	if ( ! is_array( $plugins ) ) {
 877		update_option( 'active_plugins', array() );
 878		$plugins = array();
 879	}
 880
 881	if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) {
 882		$network_plugins = (array) get_site_option( 'active_sitewide_plugins', array() );
 883		$plugins = array_merge( $plugins, array_keys( $network_plugins ) );
 884	}
 885
 886	if ( empty( $plugins ) )
 887		return;
 888
 889	$invalid = array();
 890
 891	// Invalid plugins get deactivated.
 892	foreach ( $plugins as $plugin ) {
 893		$result = validate_plugin( $plugin );
 894		if ( is_wp_error( $result ) ) {
 895			$invalid[$plugin] = $result;
 896			deactivate_plugins( $plugin, true );
 897		}
 898	}
 899	return $invalid;
 900}
 901
 902/**
 903 * Validate the plugin path.
 904 *
 905 * Checks that the file exists and {@link validate_file() is valid file}.
 906 *
 907 * @since 2.5.0
 908 *
 909 * @param string $plugin Plugin Path
 910 * @return WP_Error|int 0 on success, WP_Error on failure.
 911 */
 912function validate_plugin($plugin) {
 913	if ( validate_file($plugin) )
 914		return new WP_Error('plugin_invalid', __('Invalid plugin path.'));
 915	if ( ! file_exists(WP_PLUGIN_DIR . '/' . $plugin) )
 916		return new WP_Error('plugin_not_found', __('Plugin file does not exist.'));
 917
 918	$installed_plugins = get_plugins();
 919	if ( ! isset($installed_plugins[$plugin]) )
 920		return new WP_Error('no_plugin_header', __('The plugin does not have a valid header.'));
 921	return 0;
 922}
 923
 924/**
 925 * Whether the plugin can be uninstalled.
 926 *
 927 * @since 2.7.0
 928 *
 929 * @param string $plugin Plugin path to check.
 930 * @return bool Whether plugin can be uninstalled.
 931 */
 932function is_uninstallable_plugin($plugin) {
 933	$file = plugin_basename($plugin);
 934
 935	$uninstallable_plugins = (array) get_option('uninstall_plugins');
 936	if ( isset( $uninstallable_plugins[$file] ) || file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) )
 937		return true;
 938
 939	return false;
 940}
 941
 942/**
 943 * Uninstall a single plugin.
 944 *
 945 * Calls the uninstall hook, if it is available.
 946 *
 947 * @since 2.7.0
 948 *
 949 * @param string $plugin Relative plugin path from Plugin Directory.
 950 */
 951function uninstall_plugin($plugin) {
 952	$file = plugin_basename($plugin);
 953
 954	$uninstallable_plugins = (array) get_option('uninstall_plugins');
 955	if ( file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) ) {
 956		if ( isset( $uninstallable_plugins[$file] ) ) {
 957			unset($uninstallable_plugins[$file]);
 958			update_option('uninstall_plugins', $uninstallable_plugins);
 959		}
 960		unset($uninstallable_plugins);
 961
 962		define('WP_UNINSTALL_PLUGIN', $file);
 963		wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . dirname( $file ) );
 964		include( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' );
 965
 966		return true;
 967	}
 968
 969	if ( isset( $uninstallable_plugins[$file] ) ) {
 970		$callable = $uninstallable_plugins[$file];
 971		unset($uninstallable_plugins[$file]);
 972		update_option('uninstall_plugins', $uninstallable_plugins);
 973		unset($uninstallable_plugins);
 974
 975		wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $file );
 976		include( WP_PLUGIN_DIR . '/' . $file );
 977
 978		add_action( 'uninstall_' . $file, $callable );
 979
 980		/**
 981		 * Fires in uninstall_plugin() once the plugin has been uninstalled.
 982		 *
 983		 * The action concatenates the 'uninstall_' prefix with the basename of the
 984		 * plugin passed to {@see uninstall_plugin()} to create a dynamically-named action.
 985		 *
 986		 * @since 2.7.0
 987		 */
 988		do_action( 'uninstall_' . $file );
 989	}
 990}
 991
 992//
 993// Menu
 994//
 995
 996/**
 997 * Add a top level menu page
 998 *
 999 * This function takes a capability which will be used to determine whether
1000 * or not a page is included in the menu.
1001 *
1002 * The function which is hooked in to handle the output of the page must check
1003 * that the user has the required capability as well.
1004 *
1005 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1006 * @param string $menu_title The text to be used for the menu
1007 * @param string $capability The capability required for this menu to be displayed to the user.
1008 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1009 * @param callback $function The function to be called to output the content for this page.
1010 * @param string $icon_url The url to the icon to be used for this menu.
1011 *     * Pass a base64-encoded SVG using a data URI, which will be colored to match the color scheme.
1012 *       This should begin with 'data:image/svg+xml;base64,'.
1013 *     * Pass the name of a Dashicons helper class to use a font icon, e.g. 'dashicons-chart-pie'.
1014 *     * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS.
1015 * @param int $position The position in the menu order this one should appear
1016 *
1017 * @return string The resulting page's hook_suffix
1018 */
1019function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) {
1020	global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages;
1021
1022	$menu_slug = plugin_basename( $menu_slug );
1023
1024	$admin_page_hooks[$menu_slug] = sanitize_title( $menu_title );
1025
1026	$hookname = get_plugin_page_hookname( $menu_slug, '' );
1027
1028	if ( !empty( $function ) && !empty( $hookname ) && current_user_can( $capability ) )
1029		add_action( $hookname, $function );
1030
1031	if ( empty($icon_url) ) {
1032		$icon_url = 'dashicons-admin-generic';
1033		$icon_class = 'menu-icon-generic ';
1034	} else {
1035		$icon_url = set_url_scheme( $icon_url );
1036		$icon_class = '';
1037	}
1038
1039	$new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url );
1040
1041	if ( null === $position )
1042		$menu[] = $new_menu;
1043	else
1044		$menu[$position] = $new_menu;
1045
1046	$_registered_pages[$hookname] = true;
1047
1048	// No parent as top level
1049	$_parent_pages[$menu_slug] = false;
1050
1051	return $hookname;
1052}
1053
1054/**
1055 * Add a top level menu page in the 'objects' section
1056 *
1057 * This function takes a capability which will be used to determine whether
1058 * or not a page is included in the menu.
1059 *
1060 * The function which is hooked in to handle the output of the page must check
1061 * that the user has the required capability as well.
1062 *
1063 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1064 * @param string $menu_title The text to be used for the menu
1065 * @param string $capability The capability required for this menu to be displayed to the user.
1066 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1067 * @param callback $function The function to be called to output the content for this page.
1068 * @param string $icon_url The url to the icon to be used for this menu
1069 *
1070 * @return string The resulting page's hook_suffix
1071 */
1072function add_object_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '') {
1073	global $_wp_last_object_menu;
1074
1075	$_wp_last_object_menu++;
1076
1077	return add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $_wp_last_object_menu);
1078}
1079
1080/**
1081 * Add a top level menu page in the 'utility' section
1082 *
1083 * This function takes a capability which will be used to determine whether
1084 * or not a page is included in the menu.
1085 *
1086 * The function which is hooked in to handle the output of the page must check
1087 * that the user has the required capability as well.
1088 *
1089 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1090 * @param string $menu_title The text to be used for the menu
1091 * @param string $capability The capability required for this menu to be displayed to the user.
1092 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1093 * @param callback $function The function to be called to output the content for this page.
1094 * @param string $icon_url The url to the icon to be used for this menu
1095 *
1096 * @return string The resulting page's hook_suffix
1097 */
1098function add_utility_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '') {
1099	global $_wp_last_utility_menu;
1100
1101	$_wp_last_utility_menu++;
1102
1103	return add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $_wp_last_utility_menu);
1104}
1105
1106/**
1107 * Add a sub menu page
1108 *
1109 * This function takes a capability which will be used to determine whether
1110 * or not a page is included in the menu.
1111 *
1112 * The function which is hooked in to handle the output of the page must check
1113 * that the user has the required capability as well.
1114 *
1115 * @param string $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page)
1116 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1117 * @param string $menu_title The text to be used for the menu
1118 * @param string $capability The capability required for this menu to be displayed to the user.
1119 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1120 * @param callback $function The function to be called to output the content for this page.
1121 *
1122 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
1123 */
1124function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1125	global $submenu;
1126	global $menu;
1127	global $_wp_real_parent_file;
1128	global $_wp_submenu_nopriv;
1129	global $_registered_pages;
1130	global $_parent_pages;
1131
1132	$menu_slug = plugin_basename( $menu_slug );
1133	$parent_slug = plugin_basename( $parent_slug);
1134
1135	if ( isset( $_wp_real_parent_file[$parent_slug] ) )
1136		$parent_slug = $_wp_real_parent_file[$parent_slug];
1137
1138	if ( !current_user_can( $capability ) ) {
1139		$_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
1140		return false;
1141	}
1142
1143	/*
1144	 * If the parent doesn't already have a submenu, add a link to the parent
1145	 * as the first item in the submenu. If the submenu file is the same as the
1146	 * parent file someone is trying to link back to the parent manually. In
1147	 * this case, don't automatically add a link back to avoid duplication.
1148	 */
1149	if (!isset( $submenu[$parent_slug] ) && $menu_slug != $parent_slug ) {
1150		foreach ( (array)$menu as $parent_menu ) {
1151			if ( $parent_menu[2] == $parent_slug && current_user_can( $parent_menu[1] ) )
1152				$submenu[$parent_slug][] = array_slice( $parent_menu, 0, 4 );
1153		}
1154	}
1155
1156	$submenu[$parent_slug][] = array ( $menu_title, $capability, $menu_slug, $page_title );
1157
1158	$hookname = get_plugin_page_hookname( $menu_slug, $parent_slug);
1159	if (!empty ( $function ) && !empty ( $hookname ))
1160		add_action( $hookname, $function );
1161
1162	$_registered_pages[$hookname] = true;
1163
1164	/*
1165	 * Backward-compatibility for plugins using add_management page.
1166	 * See wp-admin/admin.php for redirect from edit.php to tools.php
1167	 */
1168	if ( 'tools.php' == $parent_slug )
1169		$_registered_pages[get_plugin_page_hookname( $menu_slug, 'edit.php')] = true;
1170
1171	// No parent as top level.
1172	$_parent_pages[$menu_slug] = $parent_slug;
1173
1174	return $hookname;
1175}
1176
1177/**
1178 * Add sub menu page to the tools main menu.
1179 *
1180 * This function takes a capability which will be used to determine whether
1181 * or not a page is included in the menu.
1182 *
1183 * The function which is hooked in to handle the output of the page must check
1184 * that the user has the required capability as well.
1185 *
1186 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1187 * @param string $menu_title The text to be used for the menu
1188 * @param string $capability The capability required for this menu to be displayed to the user.
1189 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1190 * @param callback $function The function to be called to output the content for this page.
1191 *
1192 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
1193 */
1194function add_management_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1195	return add_submenu_page( 'tools.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1196}
1197
1198/**
1199 * Add sub menu page to the options main menu.
1200 *
1201 * This function takes a capability which will be used to determine whether
1202 * or not a page is included in the menu.
1203 *
1204 * The function which is hooked in to handle the output of the page must check
1205 * that the user has the required capability as well.
1206 *
1207 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1208 * @param string $menu_title The text to be used for the menu
1209 * @param string $capability The capability required for this menu to be displayed to the user.
1210 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1211 * @param callback $function The function to be called to output the content for this page.
1212 *
1213 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
1214 */
1215function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1216	return add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1217}
1218
1219/**
1220 * Add sub menu page to the themes main menu.
1221 *
1222 * This function takes a capability which will be used to determine whether
1223 * or not a page is included in the menu.
1224 *
1225 * The function which is hooked in to handle the output of the page must check
1226 * that the user has the required capability as well.
1227 *
1228 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1229 * @param string $menu_title The text to be used for the menu
1230 * @param string $capability The capability required for this menu to be displayed to the user.
1231 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1232 * @param callback $function The function to be called to output the content for this page.
1233 *
1234 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
1235 */
1236function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1237	return add_submenu_page( 'themes.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1238}
1239
1240/**
1241 * Add sub menu page to the plugins main menu.
1242 *
1243 * This function takes a capability which will be used to determine whether
1244 * or not a page is included in the menu.
1245 *
1246 * The function which is hooked in to handle the output of the page must check
1247 * that the user has the required capability as well.
1248 *
1249 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1250 * @param string $menu_title The text to be used for the menu
1251 * @param string $capability The capability required for this menu to be displayed to the user.
1252 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1253 * @param callback $function The function to be called to output the content for this page.
1254 *
1255 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
1256 */
1257function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1258	return add_submenu_page( 'plugins.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1259}
1260
1261/**
1262 * Add sub menu page to the Users/Profile main menu.
1263 *
1264 * This function takes a capability which will be used to determine whether
1265 * or not a page is included in the menu.
1266 *
1267 * The function which is hooked in to handle the output of the page must check
1268 * that the user has the required capability as well.
1269 *
1270 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1271 * @param string $menu_title The text to be used for the menu
1272 * @param string $capability The capability required for this menu to be displayed to the user.
1273 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1274 * @param callback $function The function to be called to output the content for this page.
1275 *
1276 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
1277 */
1278function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1279	if ( current_user_can('edit_users') )
1280		$parent = 'users.php';
1281	else
1282		$parent = 'profile.php';
1283	return add_submenu_page( $parent, $page_title, $menu_title, $capability, $menu_slug, $function );
1284}
1285/**
1286 * Add sub menu page to the Dashboard main menu.
1287 *
1288 * This function takes a capability which will be used to determine whether
1289 * or not a page is included in the menu.
1290 *
1291 * The function which is hooked in to handle the output of the page must check
1292 * that the user has the required capability as well.
1293 *
1294 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1295 * @param string $menu_title The text to be used for the menu
1296 * @param string $capability The capability required for this menu to be displayed to the user.
1297 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1298 * @param callback $function The function to be called to output the content for this page.
1299 *
1300 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
1301 */
1302function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1303	return add_submenu_page( 'index.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1304}
1305
1306/**
1307 * Add sub menu page to the posts main menu.
1308 *
1309 * This function takes a capability which will be used to determine whether
1310 * or not a page is included in the menu.
1311 *
1312 * The function which is hooked in to handle the output of the page must check
1313 * that the user has the required capability as well.
1314 *
1315 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1316 * @param string $menu_title The text to be used for the menu
1317 * @param string $capability The capability required for this menu to be displayed to the user.
1318 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1319 * @param callback $function The function to be called to output the content for this page.
1320 *
1321 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
1322 */
1323function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1324	return add_submenu_page( 'edit.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1325}
1326
1327/**
1328 * Add sub menu page to the media main menu.
1329 *
1330 * This function takes a capability which will be used to determine whether
1331 * or not a page is included in the menu.
1332 *
1333 * The function which is hooked in to handle the output of the page must check
1334 * that the user has the required capability as well.
1335 *
1336 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1337 * @param string $menu_title The text to be used for the menu
1338 * @param string $capability The capability required for this menu to be displayed to the user.
1339 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1340 * @param callback $function The function to be called to output the content for this page.
1341 *
1342 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
1343 */
1344function add_media_page( $page_title, $menu_title, $capability, $menu_slug…

Large files files are truncated, but you can click here to view the full file