wp/wp-admin/includes/plugin.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Administration
     6  * @subpackage Administration
     7  */
     7  */
     8 
     8 
     9 /**
     9 /**
    10  * Parse the plugin contents to retrieve plugin's metadata.
    10  * Parses the plugin contents to retrieve plugin's metadata.
    11  *
    11  *
    12  * The metadata of the plugin's data searches for the following in the plugin's
    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
    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
    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.
    15  * and the same goes for the plugin data. The below is formatted for printing.
    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  * 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
    36  * 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
    37  * 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.
    38  * the plugin contents when it has all of the required plugin data.
    53  *
    39  *
    54  * The first 8kiB of the file will be pulled in and if the plugin data is not
    40  * The first 8kiB of the file will be pulled in and if the plugin data is not
    57  *
    43  *
    58  * The plugin file is assumed to have permissions to allow for scripts to read
    44  * 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
    45  * the file. This is not checked however and the file is only opened for
    60  * reading.
    46  * reading.
    61  *
    47  *
    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
    48  * @since 1.5.0
    66  *
    49  *
    67  * @param string $plugin_file Path to the plugin file
    50  * @param string $plugin_file Path to the main plugin file.
    68  * @param bool $markup Optional. If the returned data should have HTML markup applied. Defaults to true.
    51  * @param bool   $markup      Optional. If the returned data should have HTML markup applied.
    69  * @param bool $translate Optional. If the returned data should be translated. Defaults to true.
    52  *                            Default true.
    70  * @return array See above for description.
    53  * @param bool   $translate   Optional. If the returned data should be translated. Default true.
       
    54  * @return array {
       
    55  *     Plugin data. Values will be empty if not supplied by the plugin.
       
    56  *
       
    57  *     @type string $Name        Name of the plugin. Should be unique.
       
    58  *     @type string $Title       Title of the plugin and link to the plugin's site (if set).
       
    59  *     @type string $Description Plugin description.
       
    60  *     @type string $Author      Author's name.
       
    61  *     @type string $AuthorURI   Author's website address (if set).
       
    62  *     @type string $Version     Plugin version.
       
    63  *     @type string $TextDomain  Plugin textdomain.
       
    64  *     @type string $DomainPath  Plugins relative directory path to .mo files.
       
    65  *     @type bool   $Network     Whether the plugin can only be activated network-wide.
       
    66  * }
    71  */
    67  */
    72 function get_plugin_data( $plugin_file, $markup = true, $translate = true ) {
    68 function get_plugin_data( $plugin_file, $markup = true, $translate = true ) {
    73 
    69 
    74 	$default_headers = array(
    70 	$default_headers = array(
    75 		'Name' => 'Plugin Name',
    71 		'Name' => 'Plugin Name',
    87 
    83 
    88 	$plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' );
    84 	$plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' );
    89 
    85 
    90 	// Site Wide Only is the old header for Network
    86 	// Site Wide Only is the old header for Network
    91 	if ( ! $plugin_data['Network'] && $plugin_data['_sitewide'] ) {
    87 	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' ) );
    88 		/* translators: 1: Site Wide Only: true, 2: Network: true */
       
    89 		_deprecated_argument( __FUNCTION__, '3.0.0', sprintf( __( 'The %1$s plugin header is deprecated. Use %2$s instead.' ), '<code>Site Wide Only: true</code>', '<code>Network: true</code>' ) );
    93 		$plugin_data['Network'] = $plugin_data['_sitewide'];
    90 		$plugin_data['Network'] = $plugin_data['_sitewide'];
    94 	}
    91 	}
    95 	$plugin_data['Network'] = ( 'true' == strtolower( $plugin_data['Network'] ) );
    92 	$plugin_data['Network'] = ( 'true' == strtolower( $plugin_data['Network'] ) );
    96 	unset( $plugin_data['_sitewide'] );
    93 	unset( $plugin_data['_sitewide'] );
       
    94 
       
    95 	// If no text domain is defined fall back to the plugin slug.
       
    96 	if ( ! $plugin_data['TextDomain'] ) {
       
    97 		$plugin_slug = dirname( plugin_basename( $plugin_file ) );
       
    98 		if ( '.' !== $plugin_slug && false === strpos( $plugin_slug, '/' ) ) {
       
    99 			$plugin_data['TextDomain'] = $plugin_slug;
       
   100 		}
       
   101 	}
    97 
   102 
    98 	if ( $markup || $translate ) {
   103 	if ( $markup || $translate ) {
    99 		$plugin_data = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup, $translate );
   104 		$plugin_data = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup, $translate );
   100 	} else {
   105 	} else {
   101 		$plugin_data['Title']      = $plugin_data['Name'];
   106 		$plugin_data['Title']      = $plugin_data['Name'];
   118 	$plugin_file = plugin_basename( $plugin_file );
   123 	$plugin_file = plugin_basename( $plugin_file );
   119 
   124 
   120 	// Translate fields
   125 	// Translate fields
   121 	if ( $translate ) {
   126 	if ( $translate ) {
   122 		if ( $textdomain = $plugin_data['TextDomain'] ) {
   127 		if ( $textdomain = $plugin_data['TextDomain'] ) {
   123 			if ( $plugin_data['DomainPath'] )
   128 			if ( ! is_textdomain_loaded( $textdomain ) ) {
   124 				load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) . $plugin_data['DomainPath'] );
   129 				if ( $plugin_data['DomainPath'] ) {
   125 			else
   130 					load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) . $plugin_data['DomainPath'] );
   126 				load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) );
   131 				} else {
   127 		} elseif ( in_array( basename( $plugin_file ), array( 'hello.php', 'akismet.php' ) ) ) {
   132 					load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) );
       
   133 				}
       
   134 			}
       
   135 		} elseif ( 'hello.php' == basename( $plugin_file ) ) {
   128 			$textdomain = 'default';
   136 			$textdomain = 'default';
   129 		}
   137 		}
   130 		if ( $textdomain ) {
   138 		if ( $textdomain ) {
   131 			foreach ( array( 'Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version' ) as $field )
   139 			foreach ( array( 'Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version' ) as $field )
   132 				$plugin_data[ $field ] = translate( $plugin_data[ $field ], $textdomain );
   140 				$plugin_data[ $field ] = translate( $plugin_data[ $field ], $textdomain );
   177 /**
   185 /**
   178  * Get a list of a plugin's files.
   186  * Get a list of a plugin's files.
   179  *
   187  *
   180  * @since 2.8.0
   188  * @since 2.8.0
   181  *
   189  *
   182  * @param string $plugin Plugin ID
   190  * @param string $plugin Path to the main plugin file from plugins directory.
   183  * @return array List of files relative to the plugin root.
   191  * @return array List of files relative to the plugin root.
   184  */
   192  */
   185 function get_plugin_files($plugin) {
   193 function get_plugin_files( $plugin ) {
   186 	$plugin_file = WP_PLUGIN_DIR . '/' . $plugin;
   194 	$plugin_file = WP_PLUGIN_DIR . '/' . $plugin;
   187 	$dir = dirname($plugin_file);
   195 	$dir = dirname( $plugin_file );
   188 	$plugin_files = array($plugin);
   196 
   189 	if ( is_dir($dir) && $dir != WP_PLUGIN_DIR ) {
   197 	$plugin_files = array( plugin_basename( $plugin_file ) );
   190 		$plugins_dir = @ opendir( $dir );
   198 
   191 		if ( $plugins_dir ) {
   199 	if ( is_dir( $dir ) && WP_PLUGIN_DIR !== $dir ) {
   192 			while (($file = readdir( $plugins_dir ) ) !== false ) {
   200 
   193 				if ( substr($file, 0, 1) == '.' )
   201 		/**
   194 					continue;
   202 		 * Filters the array of excluded directories and files while scanning the folder.
   195 				if ( is_dir( $dir . '/' . $file ) ) {
   203 		 *
   196 					$plugins_subdir = @ opendir( $dir . '/' . $file );
   204 		 * @since 4.9.0
   197 					if ( $plugins_subdir ) {
   205 		 *
   198 						while (($subfile = readdir( $plugins_subdir ) ) !== false ) {
   206 		 * @param array $exclusions Array of excluded directories and files.
   199 							if ( substr($subfile, 0, 1) == '.' )
   207 		 */
   200 								continue;
   208 		$exclusions = (array) apply_filters( 'plugin_files_exclusions', array( 'CVS', 'node_modules', 'vendor', 'bower_components' ) );
   201 							$plugin_files[] = plugin_basename("$dir/$file/$subfile");
   209 
   202 						}
   210 		$list_files = list_files( $dir, 100, $exclusions );
   203 						@closedir( $plugins_subdir );
   211 		$list_files = array_map( 'plugin_basename', $list_files );
   204 					}
   212 
   205 				} else {
   213 		$plugin_files = array_merge( $plugin_files, $list_files );
   206 					if ( plugin_basename("$dir/$file") != $plugin )
   214 		$plugin_files = array_values( array_unique( $plugin_files ) );
   207 						$plugin_files[] = plugin_basename("$dir/$file");
       
   208 				}
       
   209 			}
       
   210 			@closedir( $plugins_dir );
       
   211 		}
       
   212 	}
   215 	}
   213 
   216 
   214 	return $plugin_files;
   217 	return $plugin_files;
   215 }
   218 }
   216 
   219 
   217 /**
   220 /**
   218  * Check the plugins directory and retrieve all plugin files with plugin data.
   221  * Check the plugins directory and retrieve all plugin files with plugin data.
   219  *
   222  *
   220  * WordPress only supports plugin files in the base plugins directory
   223  * WordPress only supports plugin files in the base plugins directory
   221  * (wp-content/plugins) and in one directory above the plugins directory
   224  * (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
   225  * (wp-content/plugins/my-plugin). The file it looks for has the plugin data
   223  * must be found in those two locations. It is recommended that do keep your
   226  * and must be found in those two locations. It is recommended to keep your
   224  * plugin files in directories.
   227  * plugin files in their own directories.
   225  *
   228  *
   226  * The file with the plugin data is the file that will be included and therefore
   229  * 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
   230  * 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
   231  * 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
   232  * be split for maintainability. Keep everything in one file for extreme
   409 function _get_dropins() {
   412 function _get_dropins() {
   410 	$dropins = array(
   413 	$dropins = array(
   411 		'advanced-cache.php' => array( __( 'Advanced caching plugin.'       ), 'WP_CACHE' ), // WP_CACHE
   414 		'advanced-cache.php' => array( __( 'Advanced caching plugin.'       ), 'WP_CACHE' ), // WP_CACHE
   412 		'db.php'             => array( __( 'Custom database class.'         ), true ), // auto on load
   415 		'db.php'             => array( __( 'Custom database class.'         ), true ), // auto on load
   413 		'db-error.php'       => array( __( 'Custom database error message.' ), true ), // auto on error
   416 		'db-error.php'       => array( __( 'Custom database error message.' ), true ), // auto on error
   414 		'install.php'        => array( __( 'Custom install script.'         ), true ), // auto on install
   417 		'install.php'        => array( __( 'Custom installation script.'    ), true ), // auto on installation
   415 		'maintenance.php'    => array( __( 'Custom maintenance message.'    ), true ), // auto on maintenance
   418 		'maintenance.php'    => array( __( 'Custom maintenance message.'    ), true ), // auto on maintenance
   416 		'object-cache.php'   => array( __( 'External object cache.'         ), true ), // auto on load
   419 		'object-cache.php'   => array( __( 'External object cache.'         ), true ), // auto on load
   417 	);
   420 	);
   418 
   421 
   419 	if ( is_multisite() ) {
   422 	if ( is_multisite() ) {
   425 
   428 
   426 	return $dropins;
   429 	return $dropins;
   427 }
   430 }
   428 
   431 
   429 /**
   432 /**
   430  * Check whether the plugin is active by checking the active_plugins list.
   433  * Check whether a plugin is active.
       
   434  *
       
   435  * Only plugins installed in the plugins/ folder can be active.
       
   436  *
       
   437  * Plugins in the mu-plugins/ folder can't be "activated," so this function will
       
   438  * return false for those plugins.
   431  *
   439  *
   432  * @since 2.5.0
   440  * @since 2.5.0
   433  *
   441  *
   434  * @param string $plugin Base plugin path from plugins directory.
   442  * @param string $plugin Path to the main plugin file from plugins directory.
   435  * @return bool True, if in the active plugins list. False, not in the list.
   443  * @return bool True, if in the active plugins list. False, not in the list.
   436  */
   444  */
   437 function is_plugin_active( $plugin ) {
   445 function is_plugin_active( $plugin ) {
   438 	return in_array( $plugin, (array) get_option( 'active_plugins', array() ) ) || is_plugin_active_for_network( $plugin );
   446 	return in_array( $plugin, (array) get_option( 'active_plugins', array() ) ) || is_plugin_active_for_network( $plugin );
   439 }
   447 }
   444  * Reverse of is_plugin_active(). Used as a callback.
   452  * Reverse of is_plugin_active(). Used as a callback.
   445  *
   453  *
   446  * @since 3.1.0
   454  * @since 3.1.0
   447  * @see is_plugin_active()
   455  * @see is_plugin_active()
   448  *
   456  *
   449  * @param string $plugin Base plugin path from plugins directory.
   457  * @param string $plugin Path to the main plugin file from plugins directory.
   450  * @return bool True if inactive. False if active.
   458  * @return bool True if inactive. False if active.
   451  */
   459  */
   452 function is_plugin_inactive( $plugin ) {
   460 function is_plugin_inactive( $plugin ) {
   453 	return ! is_plugin_active( $plugin );
   461 	return ! is_plugin_active( $plugin );
   454 }
   462 }
   455 
   463 
   456 /**
   464 /**
   457  * Check whether the plugin is active for the entire network.
   465  * Check whether the plugin is active for the entire network.
   458  *
   466  *
       
   467  * Only plugins installed in the plugins/ folder can be active.
       
   468  *
       
   469  * Plugins in the mu-plugins/ folder can't be "activated," so this function will
       
   470  * return false for those plugins.
       
   471  *
   459  * @since 3.0.0
   472  * @since 3.0.0
   460  *
   473  *
   461  * @param string $plugin Base plugin path from plugins directory.
   474  * @param string $plugin Path to the main plugin file from plugins directory.
   462  * @return bool True, if active for the network, otherwise false.
   475  * @return bool True, if active for the network, otherwise false.
   463  */
   476  */
   464 function is_plugin_active_for_network( $plugin ) {
   477 function is_plugin_active_for_network( $plugin ) {
   465 	if ( !is_multisite() )
   478 	if ( !is_multisite() )
   466 		return false;
   479 		return false;
   475 /**
   488 /**
   476  * Checks for "Network: true" in the plugin header to see if this should
   489  * 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
   490  * be activated only as a network wide plugin. The plugin would also work
   478  * when Multisite is not enabled.
   491  * when Multisite is not enabled.
   479  *
   492  *
   480  * Checks for "Site Wide Only: true" for backwards compatibility.
   493  * Checks for "Site Wide Only: true" for backward compatibility.
   481  *
   494  *
   482  * @since 3.0.0
   495  * @since 3.0.0
   483  *
   496  *
   484  * @param string $plugin Plugin to check
   497  * @param string $plugin Path to the main plugin file from plugins directory.
   485  * @return bool True if plugin is network only, false otherwise.
   498  * @return bool True if plugin is network only, false otherwise.
   486  */
   499  */
   487 function is_network_only_plugin( $plugin ) {
   500 function is_network_only_plugin( $plugin ) {
   488 	$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
   501 	$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
   489 	if ( $plugin_data )
   502 	if ( $plugin_data )
   509  * If any errors are found or text is outputted, then it will be captured to
   522  * 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.
   523  * ensure that the success redirection will update the error redirection.
   511  *
   524  *
   512  * @since 2.5.0
   525  * @since 2.5.0
   513  *
   526  *
   514  * @param string $plugin Plugin path to main plugin file with plugin data.
   527  * @param string $plugin       Path to the main plugin file from plugins directory.
   515  * @param string $redirect Optional. URL to redirect to.
   528  * @param string $redirect     Optional. URL to redirect to.
   516  * @param bool $network_wide Whether to enable the plugin for all sites in the
   529  * @param bool   $network_wide Optional. Whether to enable the plugin for all sites in the network
   517  *   network or just the current site. Multisite only. Default is false.
   530  *                             or just the current site. Multisite only. Default false.
   518  * @param bool $silent Prevent calling activation hooks. Optional, default is false.
   531  * @param bool   $silent       Optional. Whether to prevent calling activation hooks. Default false.
   519  * @return WP_Error|null WP_Error on invalid file or null on success.
   532  * @return WP_Error|null WP_Error on invalid file or null on success.
   520  */
   533  */
   521 function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) {
   534 function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) {
   522 	$plugin = plugin_basename( trim( $plugin ) );
   535 	$plugin = plugin_basename( trim( $plugin ) );
   523 
   536 
   549 			 * If a plugin is silently activated (such as during an update),
   562 			 * If a plugin is silently activated (such as during an update),
   550 			 * this hook does not fire.
   563 			 * this hook does not fire.
   551 			 *
   564 			 *
   552 			 * @since 2.9.0
   565 			 * @since 2.9.0
   553 			 *
   566 			 *
   554 			 * @param string $plugin       Plugin path to main plugin file with plugin data.
   567 			 * @param string $plugin       Path to the main plugin file from plugins directory.
   555 			 * @param bool   $network_wide Whether to enable the plugin for all sites in the network
   568 			 * @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.
   569 			 *                             or just the current site. Multisite only. Default is false.
   557 			 */
   570 			 */
   558 			do_action( 'activate_plugin', $plugin, $network_wide );
   571 			do_action( 'activate_plugin', $plugin, $network_wide );
   559 
   572 
   560 			/**
   573 			/**
   561 			 * Fires as a specific plugin is being activated.
   574 			 * Fires as a specific plugin is being activated.
   562 			 *
   575 			 *
   563 			 * This hook is the "activation" hook used internally by
   576 			 * This hook is the "activation" hook used internally by register_activation_hook().
   564 			 * {@see register_activation_hook()}. The dynamic portion of the
   577 			 * The dynamic portion of the hook name, `$plugin`, refers to the plugin basename.
   565 			 * hook name, `$plugin`, refers to the plugin basename.
       
   566 			 *
   578 			 *
   567 			 * If a plugin is silently activated (such as during an update),
   579 			 * If a plugin is silently activated (such as during an update), this hook does not fire.
   568 			 * this hook does not fire.
       
   569 			 *
   580 			 *
   570 			 * @since 2.0.0
   581 			 * @since 2.0.0
   571 			 *
   582 			 *
   572 			 * @param bool $network_wide Whether to enable the plugin for all sites in the network
   583 			 * @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.
   584 			 *                           or just the current site. Multisite only. Default is false.
   574 			 */
   585 			 */
   575 			do_action( 'activate_' . $plugin, $network_wide );
   586 			do_action( "activate_{$plugin}", $network_wide );
   576 		}
   587 		}
   577 
   588 
   578 		if ( $network_wide ) {
   589 		if ( $network_wide ) {
       
   590 			$current = get_site_option( 'active_sitewide_plugins', array() );
   579 			$current[$plugin] = time();
   591 			$current[$plugin] = time();
   580 			update_site_option( 'active_sitewide_plugins', $current );
   592 			update_site_option( 'active_sitewide_plugins', $current );
   581 		} else {
   593 		} else {
       
   594 			$current = get_option( 'active_plugins', array() );
   582 			$current[] = $plugin;
   595 			$current[] = $plugin;
   583 			sort($current);
   596 			sort($current);
   584 			update_option('active_plugins', $current);
   597 			update_option('active_plugins', $current);
   585 		}
   598 		}
   586 
   599 
   591 			 * If a plugin is silently activated (such as during an update),
   604 			 * If a plugin is silently activated (such as during an update),
   592 			 * this hook does not fire.
   605 			 * this hook does not fire.
   593 			 *
   606 			 *
   594 			 * @since 2.9.0
   607 			 * @since 2.9.0
   595 			 *
   608 			 *
   596 			 * @param string $plugin       Plugin path to main plugin file with plugin data.
   609 			 * @param string $plugin       Path to the main plugin file from plugins directory.
   597 			 * @param bool   $network_wide Whether to enable the plugin for all sites in the network
   610 			 * @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.
   611 			 *                             or just the current site. Multisite only. Default is false.
   599 			 */
   612 			 */
   600 			do_action( 'activated_plugin', $plugin, $network_wide );
   613 			do_action( 'activated_plugin', $plugin, $network_wide );
   601 		}
   614 		}
   643 			 * If a plugin is silently deactivated (such as during an update),
   656 			 * If a plugin is silently deactivated (such as during an update),
   644 			 * this hook does not fire.
   657 			 * this hook does not fire.
   645 			 *
   658 			 *
   646 			 * @since 2.9.0
   659 			 * @since 2.9.0
   647 			 *
   660 			 *
   648 			 * @param string $plugin               Plugin path to main plugin file with plugin data.
   661 			 * @param string $plugin               Path to the main plugin file from plugins directory.
   649 			 * @param bool   $network_deactivating Whether the plugin is deactivated for all sites in the network
   662 			 * @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.
   663 			 *                                     or just the current site. Multisite only. Default is false.
   651 			 */
   664 			 */
   652 			do_action( 'deactivate_plugin', $plugin, $network_deactivating );
   665 			do_action( 'deactivate_plugin', $plugin, $network_deactivating );
   653 		}
   666 		}
   671 
   684 
   672 		if ( ! $silent ) {
   685 		if ( ! $silent ) {
   673 			/**
   686 			/**
   674 			 * Fires as a specific plugin is being deactivated.
   687 			 * Fires as a specific plugin is being deactivated.
   675 			 *
   688 			 *
   676 			 * This hook is the "deactivation" hook used internally by
   689 			 * This hook is the "deactivation" hook used internally by register_deactivation_hook().
   677 			 * {@see register_deactivation_hook()}. The dynamic portion of the
   690 			 * The dynamic portion of the hook name, `$plugin`, refers to the plugin basename.
   678 			 * hook name, `$plugin`, refers to the plugin basename.
       
   679 			 *
   691 			 *
   680 			 * If a plugin is silently deactivated (such as during an update),
   692 			 * If a plugin is silently deactivated (such as during an update), this hook does not fire.
   681 			 * this hook does not fire.
       
   682 			 *
   693 			 *
   683 			 * @since 2.0.0
   694 			 * @since 2.0.0
   684 			 *
   695 			 *
   685 			 * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network
   696 			 * @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.
   697 			 *                                   or just the current site. Multisite only. Default is false.
   687 			 */
   698 			 */
   688 			do_action( 'deactivate_' . $plugin, $network_deactivating );
   699 			do_action( "deactivate_{$plugin}", $network_deactivating );
   689 
   700 
   690 			/**
   701 			/**
   691 			 * Fires after a plugin is deactivated.
   702 			 * Fires after a plugin is deactivated.
   692 			 *
   703 			 *
   693 			 * If a plugin is silently deactivated (such as during an update),
   704 			 * If a plugin is silently deactivated (such as during an update),
   694 			 * this hook does not fire.
   705 			 * this hook does not fire.
   695 			 *
   706 			 *
   696 			 * @since 2.9.0
   707 			 * @since 2.9.0
   697 			 *
   708 			 *
   698 			 * @param string $plugin               Plugin basename.
   709 			 * @param string $plugin               Path to the main plugin file from plugins directory.
   699 			 * @param bool   $network_deactivating Whether the plugin is deactivated for all sites in the network
   710 			 * @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.
   711 			 *                                     or just the current site. Multisite only. Default false.
   701 			 */
   712 			 */
   702 			do_action( 'deactivated_plugin', $plugin, $network_deactivating );
   713 			do_action( 'deactivated_plugin', $plugin, $network_deactivating );
   703 		}
   714 		}
   704 	}
   715 	}
   747 /**
   758 /**
   748  * Remove directory and files of a plugin for a list of plugins.
   759  * Remove directory and files of a plugin for a list of plugins.
   749  *
   760  *
   750  * @since 2.6.0
   761  * @since 2.6.0
   751  *
   762  *
       
   763  * @global WP_Filesystem_Base $wp_filesystem
       
   764  *
   752  * @param array  $plugins    List of plugins to delete.
   765  * @param array  $plugins    List of plugins to delete.
   753  * @param string $deprecated Deprecated.
   766  * @param string $deprecated Deprecated.
   754  * @return bool|null|WP_Error True on success, false is $plugins is empty, WP_Error on failure.
   767  * @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.
   768  *                            Null if filesystem credentials are required to proceed.
   756  */
   769  */
   759 
   772 
   760 	if ( empty($plugins) )
   773 	if ( empty($plugins) )
   761 		return false;
   774 		return false;
   762 
   775 
   763 	$checked = array();
   776 	$checked = array();
   764 	foreach( $plugins as $plugin )
   777 	foreach ( $plugins as $plugin )
   765 		$checked[] = 'checked[]=' . $plugin;
   778 		$checked[] = 'checked[]=' . $plugin;
   766 
   779 
       
   780 	$url = wp_nonce_url('plugins.php?action=delete-selected&verify-delete=1&' . implode('&', $checked), 'bulk-plugins');
       
   781 
   767 	ob_start();
   782 	ob_start();
   768 	$url = wp_nonce_url('plugins.php?action=delete-selected&verify-delete=1&' . implode('&', $checked), 'bulk-plugins');
   783 	$credentials = request_filesystem_credentials( $url );
   769 	if ( false === ($credentials = request_filesystem_credentials($url)) ) {
   784 	$data = ob_get_clean();
   770 		$data = ob_get_contents();
   785 
   771 		ob_end_clean();
   786 	if ( false === $credentials ) {
   772 		if ( ! empty($data) ){
   787 		if ( ! empty($data) ){
   773 			include_once( ABSPATH . 'wp-admin/admin-header.php');
   788 			include_once( ABSPATH . 'wp-admin/admin-header.php');
   774 			echo $data;
   789 			echo $data;
   775 			include( ABSPATH . 'wp-admin/admin-footer.php');
   790 			include( ABSPATH . 'wp-admin/admin-footer.php');
   776 			exit;
   791 			exit;
   777 		}
   792 		}
   778 		return;
   793 		return;
   779 	}
   794 	}
   780 
   795 
   781 	if ( ! WP_Filesystem($credentials) ) {
   796 	if ( ! WP_Filesystem( $credentials ) ) {
   782 		request_filesystem_credentials($url, '', true); //Failed to connect, Error and request again
   797 		ob_start();
   783 		$data = ob_get_contents();
   798 		request_filesystem_credentials( $url, '', true ); // Failed to connect, Error and request again.
   784 		ob_end_clean();
   799 		$data = ob_get_clean();
       
   800 
   785 		if ( ! empty($data) ){
   801 		if ( ! empty($data) ){
   786 			include_once( ABSPATH . 'wp-admin/admin-header.php');
   802 			include_once( ABSPATH . 'wp-admin/admin-header.php');
   787 			echo $data;
   803 			echo $data;
   788 			include( ABSPATH . 'wp-admin/admin-footer.php');
   804 			include( ABSPATH . 'wp-admin/admin-footer.php');
   789 			exit;
   805 			exit;
   798 		return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors);
   814 		return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors);
   799 
   815 
   800 	// Get the base plugin folder.
   816 	// Get the base plugin folder.
   801 	$plugins_dir = $wp_filesystem->wp_plugins_dir();
   817 	$plugins_dir = $wp_filesystem->wp_plugins_dir();
   802 	if ( empty( $plugins_dir ) ) {
   818 	if ( empty( $plugins_dir ) ) {
   803 		return new WP_Error( 'fs_no_plugins_dir', __( 'Unable to locate WordPress Plugin directory.' ) );
   819 		return new WP_Error( 'fs_no_plugins_dir', __( 'Unable to locate WordPress plugin directory.' ) );
   804 	}
   820 	}
   805 
   821 
   806 	$plugins_dir = trailingslashit( $plugins_dir );
   822 	$plugins_dir = trailingslashit( $plugins_dir );
   807 
   823 
   808 	$plugin_translations = wp_get_installed_translations( 'plugins' );
   824 	$plugin_translations = wp_get_installed_translations( 'plugins' );
   809 
   825 
   810 	$errors = array();
   826 	$errors = array();
   811 
   827 
   812 	foreach( $plugins as $plugin_file ) {
   828 	foreach ( $plugins as $plugin_file ) {
   813 		// Run Uninstall hook.
   829 		// Run Uninstall hook.
   814 		if ( is_uninstallable_plugin( $plugin_file ) ) {
   830 		if ( is_uninstallable_plugin( $plugin_file ) ) {
   815 			uninstall_plugin($plugin_file);
   831 			uninstall_plugin($plugin_file);
   816 		}
   832 		}
   817 
   833 
       
   834 		/**
       
   835 		 * Fires immediately before a plugin deletion attempt.
       
   836 		 *
       
   837 		 * @since 4.4.0
       
   838 		 *
       
   839 		 * @param string $plugin_file Plugin file name.
       
   840 		 */
       
   841 		do_action( 'delete_plugin', $plugin_file );
       
   842 
   818 		$this_plugin_dir = trailingslashit( dirname( $plugins_dir . $plugin_file ) );
   843 		$this_plugin_dir = trailingslashit( dirname( $plugins_dir . $plugin_file ) );
       
   844 
   819 		// If plugin is in its own directory, recursively delete the directory.
   845 		// If plugin is in its own directory, recursively delete the directory.
   820 		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
   846 		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
   821 			$deleted = $wp_filesystem->delete( $this_plugin_dir, true );
   847 			$deleted = $wp_filesystem->delete( $this_plugin_dir, true );
   822 		} else {
   848 		} else {
   823 			$deleted = $wp_filesystem->delete( $plugins_dir . $plugin_file );
   849 			$deleted = $wp_filesystem->delete( $plugins_dir . $plugin_file );
   824 		}
   850 		}
   825 
   851 
       
   852 		/**
       
   853 		 * Fires immediately after a plugin deletion attempt.
       
   854 		 *
       
   855 		 * @since 4.4.0
       
   856 		 *
       
   857 		 * @param string $plugin_file Plugin file name.
       
   858 		 * @param bool   $deleted     Whether the plugin deletion was successful.
       
   859 		 */
       
   860 		do_action( 'deleted_plugin', $plugin_file, $deleted );
       
   861 
   826 		if ( ! $deleted ) {
   862 		if ( ! $deleted ) {
   827 			$errors[] = $plugin_file;
   863 			$errors[] = $plugin_file;
   828 			continue;
   864 			continue;
   829 		}
   865 		}
   830 
   866 
   850 		}
   886 		}
   851 
   887 
   852 		set_site_transient( 'update_plugins', $current );
   888 		set_site_transient( 'update_plugins', $current );
   853 	}
   889 	}
   854 
   890 
   855 	if ( ! empty($errors) )
   891 	if ( ! empty( $errors ) ) {
   856 		return new WP_Error('could_not_remove_plugin', sprintf(__('Could not fully remove the plugin(s) %s.'), implode(', ', $errors)) );
   892 		if ( 1 === count( $errors ) ) {
       
   893 			/* translators: %s: plugin filename */
       
   894 			$message = __( 'Could not fully remove the plugin %s.' );
       
   895 		} else {
       
   896 			/* translators: %s: comma-separated list of plugin filenames */
       
   897 			$message = __( 'Could not fully remove the plugins %s.' );
       
   898 		}
       
   899 
       
   900 		return new WP_Error( 'could_not_remove_plugin', sprintf( $message, implode( ', ', $errors ) ) );
       
   901 	}
   857 
   902 
   858 	return true;
   903 	return true;
   859 }
   904 }
   860 
   905 
   861 /**
   906 /**
   897 }
   942 }
   898 
   943 
   899 /**
   944 /**
   900  * Validate the plugin path.
   945  * Validate the plugin path.
   901  *
   946  *
   902  * Checks that the file exists and {@link validate_file() is valid file}.
   947  * Checks that the main plugin file exists and is a valid plugin. See validate_file().
   903  *
   948  *
   904  * @since 2.5.0
   949  * @since 2.5.0
   905  *
   950  *
   906  * @param string $plugin Plugin Path
   951  * @param string $plugin Path to the main plugin file from plugins directory.
   907  * @return WP_Error|int 0 on success, WP_Error on failure.
   952  * @return WP_Error|int 0 on success, WP_Error on failure.
   908  */
   953  */
   909 function validate_plugin($plugin) {
   954 function validate_plugin($plugin) {
   910 	if ( validate_file($plugin) )
   955 	if ( validate_file($plugin) )
   911 		return new WP_Error('plugin_invalid', __('Invalid plugin path.'));
   956 		return new WP_Error('plugin_invalid', __('Invalid plugin path.'));
   921 /**
   966 /**
   922  * Whether the plugin can be uninstalled.
   967  * Whether the plugin can be uninstalled.
   923  *
   968  *
   924  * @since 2.7.0
   969  * @since 2.7.0
   925  *
   970  *
   926  * @param string $plugin Plugin path to check.
   971  * @param string $plugin Path to the main plugin file from plugins directory.
   927  * @return bool Whether plugin can be uninstalled.
   972  * @return bool Whether plugin can be uninstalled.
   928  */
   973  */
   929 function is_uninstallable_plugin($plugin) {
   974 function is_uninstallable_plugin($plugin) {
   930 	$file = plugin_basename($plugin);
   975 	$file = plugin_basename($plugin);
   931 
   976 
   941  *
   986  *
   942  * Calls the uninstall hook, if it is available.
   987  * Calls the uninstall hook, if it is available.
   943  *
   988  *
   944  * @since 2.7.0
   989  * @since 2.7.0
   945  *
   990  *
   946  * @param string $plugin Relative plugin path from Plugin Directory.
   991  * @param string $plugin Path to the main plugin file from plugins directory.
       
   992  * @return true True if a plugin's uninstall.php file has been found and included.
   947  */
   993  */
   948 function uninstall_plugin($plugin) {
   994 function uninstall_plugin($plugin) {
   949 	$file = plugin_basename($plugin);
   995 	$file = plugin_basename($plugin);
   950 
   996 
   951 	$uninstallable_plugins = (array) get_option('uninstall_plugins');
   997 	$uninstallable_plugins = (array) get_option('uninstall_plugins');
       
   998 
       
   999 	/**
       
  1000 	 * Fires in uninstall_plugin() immediately before the plugin is uninstalled.
       
  1001 	 *
       
  1002 	 * @since 4.5.0
       
  1003 	 *
       
  1004 	 * @param string $plugin                Path to the main plugin file from plugins directory.
       
  1005 	 * @param array  $uninstallable_plugins Uninstallable plugins.
       
  1006 	 */
       
  1007 	do_action( 'pre_uninstall_plugin', $plugin, $uninstallable_plugins );
       
  1008 
   952 	if ( file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) ) {
  1009 	if ( file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) ) {
   953 		if ( isset( $uninstallable_plugins[$file] ) ) {
  1010 		if ( isset( $uninstallable_plugins[$file] ) ) {
   954 			unset($uninstallable_plugins[$file]);
  1011 			unset($uninstallable_plugins[$file]);
   955 			update_option('uninstall_plugins', $uninstallable_plugins);
  1012 			update_option('uninstall_plugins', $uninstallable_plugins);
   956 		}
  1013 		}
   957 		unset($uninstallable_plugins);
  1014 		unset($uninstallable_plugins);
   958 
  1015 
   959 		define('WP_UNINSTALL_PLUGIN', $file);
  1016 		define('WP_UNINSTALL_PLUGIN', $file);
   960 		wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . dirname( $file ) );
  1017 		wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $file );
   961 		include( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' );
  1018 		include( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' );
   962 
  1019 
   963 		return true;
  1020 		return true;
   964 	}
  1021 	}
   965 
  1022 
   970 		unset($uninstallable_plugins);
  1027 		unset($uninstallable_plugins);
   971 
  1028 
   972 		wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $file );
  1029 		wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $file );
   973 		include( WP_PLUGIN_DIR . '/' . $file );
  1030 		include( WP_PLUGIN_DIR . '/' . $file );
   974 
  1031 
   975 		add_action( 'uninstall_' . $file, $callable );
  1032 		add_action( "uninstall_{$file}", $callable );
   976 
  1033 
   977 		/**
  1034 		/**
   978 		 * Fires in uninstall_plugin() once the plugin has been uninstalled.
  1035 		 * Fires in uninstall_plugin() once the plugin has been uninstalled.
   979 		 *
  1036 		 *
   980 		 * The action concatenates the 'uninstall_' prefix with the basename of the
  1037 		 * The action concatenates the 'uninstall_' prefix with the basename of the
   981 		 * plugin passed to {@see uninstall_plugin()} to create a dynamically-named action.
  1038 		 * plugin passed to uninstall_plugin() to create a dynamically-named action.
   982 		 *
  1039 		 *
   983 		 * @since 2.7.0
  1040 		 * @since 2.7.0
   984 		 */
  1041 		 */
   985 		do_action( 'uninstall_' . $file );
  1042 		do_action( "uninstall_{$file}" );
   986 	}
  1043 	}
   987 }
  1044 }
   988 
  1045 
   989 //
  1046 //
   990 // Menu
  1047 // Menu
   991 //
  1048 //
   992 
  1049 
   993 /**
  1050 /**
   994  * Add a top level menu page
  1051  * Add a top-level menu page.
   995  *
  1052  *
   996  * This function takes a capability which will be used to determine whether
  1053  * This function takes a capability which will be used to determine whether
   997  * or not a page is included in the menu.
  1054  * or not a page is included in the menu.
   998  *
  1055  *
   999  * The function which is hooked in to handle the output of the page must check
  1056  * The function which is hooked in to handle the output of the page must check
  1000  * that the user has the required capability as well.
  1057  * that the user has the required capability as well.
  1001  *
  1058  *
  1002  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1059  * @global array $menu
  1003  * @param string $menu_title The text to be used for the menu
  1060  * @global array $admin_page_hooks
  1004  * @param string $capability The capability required for this menu to be displayed to the user.
  1061  * @global array $_registered_pages
  1005  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1062  * @global array $_parent_pages
  1006  * @param callback $function The function to be called to output the content for this page.
  1063  *
  1007  * @param string $icon_url The url to the icon to be used for this menu.
  1064  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1008  *     * Pass a base64-encoded SVG using a data URI, which will be colored to match the color scheme.
  1065  * @param string   $menu_title The text to be used for the menu.
  1009  *       This should begin with 'data:image/svg+xml;base64,'.
  1066  * @param string   $capability The capability required for this menu to be displayed to the user.
  1010  *     * Pass the name of a Dashicons helper class to use a font icon, e.g. 'dashicons-chart-pie'.
  1067  * @param string   $menu_slug  The slug name to refer to this menu by. Should be unique for this menu page and only
  1011  *     * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS.
  1068  *                             include lowercase alphanumeric, dashes, and underscores characters to be compatible
  1012  * @param int $position The position in the menu order this one should appear
  1069  *                             with sanitize_key().
  1013  *
  1070  * @param callable $function   The function to be called to output the content for this page.
  1014  * @return string The resulting page's hook_suffix
  1071  * @param string   $icon_url   The URL to the icon to be used for this menu.
       
  1072  *                             * Pass a base64-encoded SVG using a data URI, which will be colored to match
       
  1073  *                               the color scheme. This should begin with 'data:image/svg+xml;base64,'.
       
  1074  *                             * Pass the name of a Dashicons helper class to use a font icon,
       
  1075  *                               e.g. 'dashicons-chart-pie'.
       
  1076  *                             * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS.
       
  1077  * @param int      $position   The position in the menu order this one should appear.
       
  1078  * @return string The resulting page's hook_suffix.
  1015  */
  1079  */
  1016 function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) {
  1080 function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) {
  1017 	global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages;
  1081 	global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages;
  1018 
  1082 
  1019 	$menu_slug = plugin_basename( $menu_slug );
  1083 	$menu_slug = plugin_basename( $menu_slug );
  1033 		$icon_class = '';
  1097 		$icon_class = '';
  1034 	}
  1098 	}
  1035 
  1099 
  1036 	$new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url );
  1100 	$new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url );
  1037 
  1101 
  1038 	if ( null === $position )
  1102 	if ( null === $position ) {
  1039 		$menu[] = $new_menu;
  1103 		$menu[] = $new_menu;
  1040 	else
  1104 	} elseif ( isset( $menu[ "$position" ] ) ) {
  1041 		$menu[$position] = $new_menu;
  1105 	 	$position = $position + substr( base_convert( md5( $menu_slug . $menu_title ), 16, 10 ) , -5 ) * 0.00001;
       
  1106 		$menu[ "$position" ] = $new_menu;
       
  1107 	} else {
       
  1108 		$menu[ $position ] = $new_menu;
       
  1109 	}
  1042 
  1110 
  1043 	$_registered_pages[$hookname] = true;
  1111 	$_registered_pages[$hookname] = true;
  1044 
  1112 
  1045 	// No parent as top level
  1113 	// No parent as top level
  1046 	$_parent_pages[$menu_slug] = false;
  1114 	$_parent_pages[$menu_slug] = false;
  1047 
  1115 
  1048 	return $hookname;
  1116 	return $hookname;
  1049 }
  1117 }
  1050 
  1118 
  1051 /**
  1119 /**
  1052  * Add a top level menu page in the 'objects' section
  1120  * Add a submenu page.
  1053  *
  1121  *
  1054  * This function takes a capability which will be used to determine whether
  1122  * This function takes a capability which will be used to determine whether
  1055  * or not a page is included in the menu.
  1123  * or not a page is included in the menu.
  1056  *
  1124  *
  1057  * The function which is hooked in to handle the output of the page must check
  1125  * The function which is hooked in to handle the output of the page must check
  1058  * that the user has the required capability as well.
  1126  * that the user has the required capability as well.
  1059  *
  1127  *
  1060  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1128  * @global array $submenu
  1061  * @param string $menu_title The text to be used for the menu
  1129  * @global array $menu
  1062  * @param string $capability The capability required for this menu to be displayed to the user.
  1130  * @global array $_wp_real_parent_file
  1063  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1131  * @global bool  $_wp_submenu_nopriv
  1064  * @param callback $function The function to be called to output the content for this page.
  1132  * @global array $_registered_pages
  1065  * @param string $icon_url The url to the icon to be used for this menu
  1133  * @global array $_parent_pages
  1066  *
  1134  *
  1067  * @return string The resulting page's hook_suffix
  1135  * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard
  1068  */
  1136  *                              WordPress admin page).
  1069 function add_object_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '') {
  1137  * @param string   $page_title  The text to be displayed in the title tags of the page when the menu
  1070 	global $_wp_last_object_menu;
  1138  *                              is selected.
  1071 
  1139  * @param string   $menu_title  The text to be used for the menu.
  1072 	$_wp_last_object_menu++;
  1140  * @param string   $capability  The capability required for this menu to be displayed to the user.
  1073 
  1141  * @param string   $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
  1074 	return add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $_wp_last_object_menu);
  1142  *                              and only include lowercase alphanumeric, dashes, and underscores characters
  1075 }
  1143  *                              to be compatible with sanitize_key().
  1076 
  1144  * @param callable $function    The function to be called to output the content for this page.
  1077 /**
       
  1078  * Add a top level menu page in the 'utility' section
       
  1079  *
       
  1080  * This function takes a capability which will be used to determine whether
       
  1081  * or not a page is included in the menu.
       
  1082  *
       
  1083  * The function which is hooked in to handle the output of the page must check
       
  1084  * that the user has the required capability as well.
       
  1085  *
       
  1086  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
       
  1087  * @param string $menu_title The text to be used for the menu
       
  1088  * @param string $capability The capability required for this menu to be displayed to the user.
       
  1089  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
       
  1090  * @param callback $function The function to be called to output the content for this page.
       
  1091  * @param string $icon_url The url to the icon to be used for this menu
       
  1092  *
       
  1093  * @return string The resulting page's hook_suffix
       
  1094  */
       
  1095 function add_utility_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '') {
       
  1096 	global $_wp_last_utility_menu;
       
  1097 
       
  1098 	$_wp_last_utility_menu++;
       
  1099 
       
  1100 	return add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $_wp_last_utility_menu);
       
  1101 }
       
  1102 
       
  1103 /**
       
  1104  * Add a sub menu page
       
  1105  *
       
  1106  * This function takes a capability which will be used to determine whether
       
  1107  * or not a page is included in the menu.
       
  1108  *
       
  1109  * The function which is hooked in to handle the output of the page must check
       
  1110  * that the user has the required capability as well.
       
  1111  *
       
  1112  * @param string $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page)
       
  1113  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
       
  1114  * @param string $menu_title The text to be used for the menu
       
  1115  * @param string $capability The capability required for this menu to be displayed to the user.
       
  1116  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
       
  1117  * @param callback $function The function to be called to output the content for this page.
       
  1118  *
       
  1119  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1145  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1120  */
  1146  */
  1121 function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1147 function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1122 	global $submenu;
  1148 	global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv,
  1123 	global $menu;
  1149 		$_registered_pages, $_parent_pages;
  1124 	global $_wp_real_parent_file;
       
  1125 	global $_wp_submenu_nopriv;
       
  1126 	global $_registered_pages;
       
  1127 	global $_parent_pages;
       
  1128 
  1150 
  1129 	$menu_slug = plugin_basename( $menu_slug );
  1151 	$menu_slug = plugin_basename( $menu_slug );
  1130 	$parent_slug = plugin_basename( $parent_slug);
  1152 	$parent_slug = plugin_basename( $parent_slug);
  1131 
  1153 
  1132 	if ( isset( $_wp_real_parent_file[$parent_slug] ) )
  1154 	if ( isset( $_wp_real_parent_file[$parent_slug] ) )
  1170 
  1192 
  1171 	return $hookname;
  1193 	return $hookname;
  1172 }
  1194 }
  1173 
  1195 
  1174 /**
  1196 /**
  1175  * Add sub menu page to the tools main menu.
  1197  * Add submenu page to the Tools main menu.
  1176  *
  1198  *
  1177  * This function takes a capability which will be used to determine whether
  1199  * This function takes a capability which will be used to determine whether
  1178  * or not a page is included in the menu.
  1200  * or not a page is included in the menu.
  1179  *
  1201  *
  1180  * The function which is hooked in to handle the output of the page must check
  1202  * The function which is hooked in to handle the output of the page must check
  1181  * that the user has the required capability as well.
  1203  * that the user has the required capability as well.
  1182  *
  1204  *
  1183  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1205  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1184  * @param string $menu_title The text to be used for the menu
  1206  * @param string   $menu_title The text to be used for the menu.
  1185  * @param string $capability The capability required for this menu to be displayed to the user.
  1207  * @param string   $capability The capability required for this menu to be displayed to the user.
  1186  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1208  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1187  * @param callback $function The function to be called to output the content for this page.
  1209  * @param callable $function   The function to be called to output the content for this page.
  1188  *
       
  1189  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1210  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1190  */
  1211  */
  1191 function add_management_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1212 function add_management_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1192 	return add_submenu_page( 'tools.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1213 	return add_submenu_page( 'tools.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1193 }
  1214 }
  1194 
  1215 
  1195 /**
  1216 /**
  1196  * Add sub menu page to the options main menu.
  1217  * Add submenu page to the Settings main menu.
  1197  *
  1218  *
  1198  * This function takes a capability which will be used to determine whether
  1219  * This function takes a capability which will be used to determine whether
  1199  * or not a page is included in the menu.
  1220  * or not a page is included in the menu.
  1200  *
  1221  *
  1201  * The function which is hooked in to handle the output of the page must check
  1222  * The function which is hooked in to handle the output of the page must check
  1202  * that the user has the required capability as well.
  1223  * that the user has the required capability as well.
  1203  *
  1224  *
  1204  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1225  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1205  * @param string $menu_title The text to be used for the menu
  1226  * @param string   $menu_title The text to be used for the menu.
  1206  * @param string $capability The capability required for this menu to be displayed to the user.
  1227  * @param string   $capability The capability required for this menu to be displayed to the user.
  1207  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1228  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1208  * @param callback $function The function to be called to output the content for this page.
  1229  * @param callable $function   The function to be called to output the content for this page.
  1209  *
       
  1210  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1230  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1211  */
  1231  */
  1212 function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1232 function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1213 	return add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1233 	return add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1214 }
  1234 }
  1215 
  1235 
  1216 /**
  1236 /**
  1217  * Add sub menu page to the themes main menu.
  1237  * Add submenu page to the Appearance main menu.
  1218  *
  1238  *
  1219  * This function takes a capability which will be used to determine whether
  1239  * This function takes a capability which will be used to determine whether
  1220  * or not a page is included in the menu.
  1240  * or not a page is included in the menu.
  1221  *
  1241  *
  1222  * The function which is hooked in to handle the output of the page must check
  1242  * 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.
  1243  * that the user has the required capability as well.
  1224  *
  1244  *
  1225  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1245  * @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
  1246  * @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.
  1247  * @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)
  1248  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1229  * @param callback $function The function to be called to output the content for this page.
  1249  * @param callable $function   The function to be called to output the content for this page.
  1230  *
       
  1231  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1250  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1232  */
  1251  */
  1233 function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1252 function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1234 	return add_submenu_page( 'themes.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1253 	return add_submenu_page( 'themes.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1235 }
  1254 }
  1236 
  1255 
  1237 /**
  1256 /**
  1238  * Add sub menu page to the plugins main menu.
  1257  * Add submenu page to the Plugins main menu.
  1239  *
  1258  *
  1240  * This function takes a capability which will be used to determine whether
  1259  * This function takes a capability which will be used to determine whether
  1241  * or not a page is included in the menu.
  1260  * or not a page is included in the menu.
  1242  *
  1261  *
  1243  * The function which is hooked in to handle the output of the page must check
  1262  * The function which is hooked in to handle the output of the page must check
  1244  * that the user has the required capability as well.
  1263  * that the user has the required capability as well.
  1245  *
  1264  *
  1246  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1265  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1247  * @param string $menu_title The text to be used for the menu
  1266  * @param string   $menu_title The text to be used for the menu.
  1248  * @param string $capability The capability required for this menu to be displayed to the user.
  1267  * @param string   $capability The capability required for this menu to be displayed to the user.
  1249  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1268  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1250  * @param callback $function The function to be called to output the content for this page.
  1269  * @param callable $function   The function to be called to output the content for this page.
  1251  *
       
  1252  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1270  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1253  */
  1271  */
  1254 function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1272 function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1255 	return add_submenu_page( 'plugins.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1273 	return add_submenu_page( 'plugins.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1256 }
  1274 }
  1257 
  1275 
  1258 /**
  1276 /**
  1259  * Add sub menu page to the Users/Profile main menu.
  1277  * Add submenu page to the Users/Profile main menu.
  1260  *
  1278  *
  1261  * This function takes a capability which will be used to determine whether
  1279  * This function takes a capability which will be used to determine whether
  1262  * or not a page is included in the menu.
  1280  * or not a page is included in the menu.
  1263  *
  1281  *
  1264  * The function which is hooked in to handle the output of the page must check
  1282  * The function which is hooked in to handle the output of the page must check
  1265  * that the user has the required capability as well.
  1283  * that the user has the required capability as well.
  1266  *
  1284  *
  1267  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1285  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1268  * @param string $menu_title The text to be used for the menu
  1286  * @param string   $menu_title The text to be used for the menu.
  1269  * @param string $capability The capability required for this menu to be displayed to the user.
  1287  * @param string   $capability The capability required for this menu to be displayed to the user.
  1270  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1288  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1271  * @param callback $function The function to be called to output the content for this page.
  1289  * @param callable $function   The function to be called to output the content for this page.
  1272  *
       
  1273  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1290  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1274  */
  1291  */
  1275 function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1292 function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1276 	if ( current_user_can('edit_users') )
  1293 	if ( current_user_can('edit_users') )
  1277 		$parent = 'users.php';
  1294 		$parent = 'users.php';
  1278 	else
  1295 	else
  1279 		$parent = 'profile.php';
  1296 		$parent = 'profile.php';
  1280 	return add_submenu_page( $parent, $page_title, $menu_title, $capability, $menu_slug, $function );
  1297 	return add_submenu_page( $parent, $page_title, $menu_title, $capability, $menu_slug, $function );
  1281 }
  1298 }
  1282 /**
  1299 /**
  1283  * Add sub menu page to the Dashboard main menu.
  1300  * Add submenu page to the Dashboard main menu.
  1284  *
  1301  *
  1285  * This function takes a capability which will be used to determine whether
  1302  * This function takes a capability which will be used to determine whether
  1286  * or not a page is included in the menu.
  1303  * or not a page is included in the menu.
  1287  *
  1304  *
  1288  * The function which is hooked in to handle the output of the page must check
  1305  * The function which is hooked in to handle the output of the page must check
  1289  * that the user has the required capability as well.
  1306  * that the user has the required capability as well.
  1290  *
  1307  *
  1291  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1308  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1292  * @param string $menu_title The text to be used for the menu
  1309  * @param string   $menu_title The text to be used for the menu.
  1293  * @param string $capability The capability required for this menu to be displayed to the user.
  1310  * @param string   $capability The capability required for this menu to be displayed to the user.
  1294  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1311  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1295  * @param callback $function The function to be called to output the content for this page.
  1312  * @param callable $function   The function to be called to output the content for this page.
  1296  *
       
  1297  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1313  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1298  */
  1314  */
  1299 function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1315 function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1300 	return add_submenu_page( 'index.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1316 	return add_submenu_page( 'index.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1301 }
  1317 }
  1302 
  1318 
  1303 /**
  1319 /**
  1304  * Add sub menu page to the posts main menu.
  1320  * Add submenu page to the Posts main menu.
  1305  *
  1321  *
  1306  * This function takes a capability which will be used to determine whether
  1322  * This function takes a capability which will be used to determine whether
  1307  * or not a page is included in the menu.
  1323  * or not a page is included in the menu.
  1308  *
  1324  *
  1309  * The function which is hooked in to handle the output of the page must check
  1325  * The function which is hooked in to handle the output of the page must check
  1310  * that the user has the required capability as well.
  1326  * that the user has the required capability as well.
  1311  *
  1327  *
  1312  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1328  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1313  * @param string $menu_title The text to be used for the menu
  1329  * @param string   $menu_title The text to be used for the menu.
  1314  * @param string $capability The capability required for this menu to be displayed to the user.
  1330  * @param string   $capability The capability required for this menu to be displayed to the user.
  1315  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1331  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1316  * @param callback $function The function to be called to output the content for this page.
  1332  * @param callable $function   The function to be called to output the content for this page.
  1317  *
       
  1318  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1333  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1319  */
  1334  */
  1320 function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1335 function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1321 	return add_submenu_page( 'edit.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1336 	return add_submenu_page( 'edit.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1322 }
  1337 }
  1323 
  1338 
  1324 /**
  1339 /**
  1325  * Add sub menu page to the media main menu.
  1340  * Add submenu page to the Media main menu.
  1326  *
  1341  *
  1327  * This function takes a capability which will be used to determine whether
  1342  * This function takes a capability which will be used to determine whether
  1328  * or not a page is included in the menu.
  1343  * or not a page is included in the menu.
  1329  *
  1344  *
  1330  * The function which is hooked in to handle the output of the page must check
  1345  * The function which is hooked in to handle the output of the page must check
  1331  * that the user has the required capability as well.
  1346  * that the user has the required capability as well.
  1332  *
  1347  *
  1333  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1348  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1334  * @param string $menu_title The text to be used for the menu
  1349  * @param string   $menu_title The text to be used for the menu.
  1335  * @param string $capability The capability required for this menu to be displayed to the user.
  1350  * @param string   $capability The capability required for this menu to be displayed to the user.
  1336  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1351  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1337  * @param callback $function The function to be called to output the content for this page.
  1352  * @param callable $function   The function to be called to output the content for this page.
  1338  *
       
  1339  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1353  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1340  */
  1354  */
  1341 function add_media_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1355 function add_media_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1342 	return add_submenu_page( 'upload.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1356 	return add_submenu_page( 'upload.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1343 }
  1357 }
  1344 
  1358 
  1345 /**
  1359 /**
  1346  * Add sub menu page to the links main menu.
  1360  * Add submenu page to the Links main menu.
  1347  *
  1361  *
  1348  * This function takes a capability which will be used to determine whether
  1362  * This function takes a capability which will be used to determine whether
  1349  * or not a page is included in the menu.
  1363  * or not a page is included in the menu.
  1350  *
  1364  *
  1351  * The function which is hooked in to handle the output of the page must check
  1365  * The function which is hooked in to handle the output of the page must check
  1352  * that the user has the required capability as well.
  1366  * that the user has the required capability as well.
  1353  *
  1367  *
  1354  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1368  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1355  * @param string $menu_title The text to be used for the menu
  1369  * @param string   $menu_title The text to be used for the menu.
  1356  * @param string $capability The capability required for this menu to be displayed to the user.
  1370  * @param string   $capability The capability required for this menu to be displayed to the user.
  1357  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1371  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1358  * @param callback $function The function to be called to output the content for this page.
  1372  * @param callable $function   The function to be called to output the content for this page.
  1359  *
       
  1360  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1373  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1361  */
  1374  */
  1362 function add_links_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1375 function add_links_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1363 	return add_submenu_page( 'link-manager.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1376 	return add_submenu_page( 'link-manager.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1364 }
  1377 }
  1365 
  1378 
  1366 /**
  1379 /**
  1367  * Add sub menu page to the pages main menu.
  1380  * Add submenu page to the Pages main menu.
  1368  *
  1381  *
  1369  * 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
  1370  * or not a page is included in the menu.
  1383  * or not a page is included in the menu.
  1371  *
  1384  *
  1372  * 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
  1373  * that the user has the required capability as well.
  1386  * that the user has the required capability as well.
  1374  *
  1387  *
  1375  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1388  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1376  * @param string $menu_title The text to be used for the menu
  1389  * @param string   $menu_title The text to be used for the menu.
  1377  * @param string $capability The capability required for this menu to be displayed to the user.
  1390  * @param string   $capability The capability required for this menu to be displayed to the user.
  1378  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1391  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1379  * @param callback $function The function to be called to output the content for this page.
  1392  * @param callable $function   The function to be called to output the content for this page.
  1380  *
       
  1381  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1393  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1382 */
  1394  */
  1383 function add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1395 function add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1384 	return add_submenu_page( 'edit.php?post_type=page', $page_title, $menu_title, $capability, $menu_slug, $function );
  1396 	return add_submenu_page( 'edit.php?post_type=page', $page_title, $menu_title, $capability, $menu_slug, $function );
  1385 }
  1397 }
  1386 
  1398 
  1387 /**
  1399 /**
  1388  * Add sub menu page to the comments main menu.
  1400  * Add submenu page to the Comments main menu.
  1389  *
  1401  *
  1390  * This function takes a capability which will be used to determine whether
  1402  * This function takes a capability which will be used to determine whether
  1391  * or not a page is included in the menu.
  1403  * or not a page is included in the menu.
  1392  *
  1404  *
  1393  * The function which is hooked in to handle the output of the page must check
  1405  * The function which is hooked in to handle the output of the page must check
  1394  * that the user has the required capability as well.
  1406  * that the user has the required capability as well.
  1395  *
  1407  *
  1396  * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
  1408  * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
  1397  * @param string $menu_title The text to be used for the menu
  1409  * @param string   $menu_title The text to be used for the menu.
  1398  * @param string $capability The capability required for this menu to be displayed to the user.
  1410  * @param string   $capability The capability required for this menu to be displayed to the user.
  1399  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1411  * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
  1400  * @param callback $function The function to be called to output the content for this page.
  1412  * @param callable $function   The function to be called to output the content for this page.
  1401  *
       
  1402  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1413  * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
  1403 */
  1414  */
  1404 function add_comments_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1415 function add_comments_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
  1405 	return add_submenu_page( 'edit-comments.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1416 	return add_submenu_page( 'edit-comments.php', $page_title, $menu_title, $capability, $menu_slug, $function );
  1406 }
  1417 }
  1407 
  1418 
  1408 /**
  1419 /**
  1409  * Remove a top level admin menu
  1420  * Remove a top-level admin menu.
  1410  *
  1421  *
  1411  * @since 3.1.0
  1422  * @since 3.1.0
  1412  *
  1423  *
  1413  * @param string $menu_slug The slug of the menu
  1424  * @global array $menu
  1414  * @return array|bool The removed menu on success, False if not found
  1425  *
       
  1426  * @param string $menu_slug The slug of the menu.
       
  1427  * @return array|bool The removed menu on success, false if not found.
  1415  */
  1428  */
  1416 function remove_menu_page( $menu_slug ) {
  1429 function remove_menu_page( $menu_slug ) {
  1417 	global $menu;
  1430 	global $menu;
  1418 
  1431 
  1419 	foreach ( $menu as $i => $item ) {
  1432 	foreach ( $menu as $i => $item ) {
  1425 
  1438 
  1426 	return false;
  1439 	return false;
  1427 }
  1440 }
  1428 
  1441 
  1429 /**
  1442 /**
  1430  * Remove an admin submenu
  1443  * Remove an admin submenu.
  1431  *
  1444  *
  1432  * @since 3.1.0
  1445  * @since 3.1.0
  1433  *
  1446  *
  1434  * @param string $menu_slug The slug for the parent menu
  1447  * @global array $submenu
  1435  * @param string $submenu_slug The slug of the submenu
  1448  *
  1436  * @return array|bool The removed submenu on success, False if not found
  1449  * @param string $menu_slug    The slug for the parent menu.
       
  1450  * @param string $submenu_slug The slug of the submenu.
       
  1451  * @return array|bool The removed submenu on success, false if not found.
  1437  */
  1452  */
  1438 function remove_submenu_page( $menu_slug, $submenu_slug ) {
  1453 function remove_submenu_page( $menu_slug, $submenu_slug ) {
  1439 	global $submenu;
  1454 	global $submenu;
  1440 
  1455 
  1441 	if ( !isset( $submenu[$menu_slug] ) )
  1456 	if ( !isset( $submenu[$menu_slug] ) )
  1455  * Get the url to access a particular menu page based on the slug it was registered with.
  1470  * Get the url to access a particular menu page based on the slug it was registered with.
  1456  *
  1471  *
  1457  * If the slug hasn't been registered properly no url will be returned
  1472  * If the slug hasn't been registered properly no url will be returned
  1458  *
  1473  *
  1459  * @since 3.0.0
  1474  * @since 3.0.0
       
  1475  *
       
  1476  * @global array $_parent_pages
  1460  *
  1477  *
  1461  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1478  * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
  1462  * @param bool $echo Whether or not to echo the url - default is true
  1479  * @param bool $echo Whether or not to echo the url - default is true
  1463  * @return string the url
  1480  * @return string the url
  1464  */
  1481  */
  1485 }
  1502 }
  1486 
  1503 
  1487 //
  1504 //
  1488 // Pluggable Menu Support -- Private
  1505 // Pluggable Menu Support -- Private
  1489 //
  1506 //
  1490 
  1507 /**
       
  1508  *
       
  1509  * @global string $parent_file
       
  1510  * @global array $menu
       
  1511  * @global array $submenu
       
  1512  * @global string $pagenow
       
  1513  * @global string $typenow
       
  1514  * @global string $plugin_page
       
  1515  * @global array $_wp_real_parent_file
       
  1516  * @global array $_wp_menu_nopriv
       
  1517  * @global array $_wp_submenu_nopriv
       
  1518  */
  1491 function get_admin_page_parent( $parent = '' ) {
  1519 function get_admin_page_parent( $parent = '' ) {
  1492 	global $parent_file;
  1520 	global $parent_file, $menu, $submenu, $pagenow, $typenow,
  1493 	global $menu;
  1521 		$plugin_page, $_wp_real_parent_file, $_wp_menu_nopriv, $_wp_submenu_nopriv;
  1494 	global $submenu;
       
  1495 	global $pagenow;
       
  1496 	global $typenow;
       
  1497 	global $plugin_page;
       
  1498 	global $_wp_real_parent_file;
       
  1499 	global $_wp_menu_nopriv;
       
  1500 	global $_wp_submenu_nopriv;
       
  1501 
  1522 
  1502 	if ( !empty ( $parent ) && 'admin.php' != $parent ) {
  1523 	if ( !empty ( $parent ) && 'admin.php' != $parent ) {
  1503 		if ( isset( $_wp_real_parent_file[$parent] ) )
  1524 		if ( isset( $_wp_real_parent_file[$parent] ) )
  1504 			$parent = $_wp_real_parent_file[$parent];
  1525 			$parent = $_wp_real_parent_file[$parent];
  1505 		return $parent;
  1526 		return $parent;
  1549 	if ( empty($parent_file) )
  1570 	if ( empty($parent_file) )
  1550 		$parent_file = '';
  1571 		$parent_file = '';
  1551 	return '';
  1572 	return '';
  1552 }
  1573 }
  1553 
  1574 
       
  1575 /**
       
  1576  *
       
  1577  * @global string $title
       
  1578  * @global array $menu
       
  1579  * @global array $submenu
       
  1580  * @global string $pagenow
       
  1581  * @global string $plugin_page
       
  1582  * @global string $typenow
       
  1583  */
  1554 function get_admin_page_title() {
  1584 function get_admin_page_title() {
  1555 	global $title;
  1585 	global $title, $menu, $submenu, $pagenow, $plugin_page, $typenow;
  1556 	global $menu;
       
  1557 	global $submenu;
       
  1558 	global $pagenow;
       
  1559 	global $plugin_page;
       
  1560 	global $typenow;
       
  1561 
  1586 
  1562 	if ( ! empty ( $title ) )
  1587 	if ( ! empty ( $title ) )
  1563 		return $title;
  1588 		return $title;
  1564 
  1589 
  1565 	$hook = get_plugin_page_hook( $plugin_page, $pagenow );
  1590 	$hook = get_plugin_page_hook( $plugin_page, $pagenow );
  1625 	}
  1650 	}
  1626 
  1651 
  1627 	return $title;
  1652 	return $title;
  1628 }
  1653 }
  1629 
  1654 
       
  1655 /**
       
  1656  * @since 2.3.0
       
  1657  *
       
  1658  * @param string $plugin_page
       
  1659  * @param string $parent_page
       
  1660  * @return string|null
       
  1661  */
  1630 function get_plugin_page_hook( $plugin_page, $parent_page ) {
  1662 function get_plugin_page_hook( $plugin_page, $parent_page ) {
  1631 	$hook = get_plugin_page_hookname( $plugin_page, $parent_page );
  1663 	$hook = get_plugin_page_hookname( $plugin_page, $parent_page );
  1632 	if ( has_action($hook) )
  1664 	if ( has_action($hook) )
  1633 		return $hook;
  1665 		return $hook;
  1634 	else
  1666 	else
  1635 		return null;
  1667 		return null;
  1636 }
  1668 }
  1637 
  1669 
       
  1670 /**
       
  1671  *
       
  1672  * @global array $admin_page_hooks
       
  1673  * @param string $plugin_page
       
  1674  * @param string $parent_page
       
  1675  */
  1638 function get_plugin_page_hookname( $plugin_page, $parent_page ) {
  1676 function get_plugin_page_hookname( $plugin_page, $parent_page ) {
  1639 	global $admin_page_hooks;
  1677 	global $admin_page_hooks;
  1640 
  1678 
  1641 	$parent = get_admin_page_parent( $parent_page );
  1679 	$parent = get_admin_page_parent( $parent_page );
  1642 
  1680 
  1654 	$plugin_name = preg_replace( '!\.php!', '', $plugin_page );
  1692 	$plugin_name = preg_replace( '!\.php!', '', $plugin_page );
  1655 
  1693 
  1656 	return $page_type . '_page_' . $plugin_name;
  1694 	return $page_type . '_page_' . $plugin_name;
  1657 }
  1695 }
  1658 
  1696 
       
  1697 /**
       
  1698  *
       
  1699  * @global string $pagenow
       
  1700  * @global array $menu
       
  1701  * @global array $submenu
       
  1702  * @global array $_wp_menu_nopriv
       
  1703  * @global array $_wp_submenu_nopriv
       
  1704  * @global string $plugin_page
       
  1705  * @global array $_registered_pages
       
  1706  */
  1659 function user_can_access_admin_page() {
  1707 function user_can_access_admin_page() {
  1660 	global $pagenow;
  1708 	global $pagenow, $menu, $submenu, $_wp_menu_nopriv, $_wp_submenu_nopriv,
  1661 	global $menu;
  1709 		$plugin_page, $_registered_pages;
  1662 	global $submenu;
       
  1663 	global $_wp_menu_nopriv;
       
  1664 	global $_wp_submenu_nopriv;
       
  1665 	global $plugin_page;
       
  1666 	global $_registered_pages;
       
  1667 
  1710 
  1668 	$parent = get_admin_page_parent();
  1711 	$parent = get_admin_page_parent();
  1669 
  1712 
  1670 	if ( !isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$parent][$pagenow] ) )
  1713 	if ( !isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$parent][$pagenow] ) )
  1671 		return false;
  1714 		return false;
  1730 }
  1773 }
  1731 
  1774 
  1732 /* Whitelist functions */
  1775 /* Whitelist functions */
  1733 
  1776 
  1734 /**
  1777 /**
  1735  * Register a setting and its sanitization callback
  1778  * Refreshes the value of the options whitelist available via the 'whitelist_options' hook.
       
  1779  *
       
  1780  * See the {@see 'whitelist_options'} filter.
  1736  *
  1781  *
  1737  * @since 2.7.0
  1782  * @since 2.7.0
  1738  *
  1783  *
  1739  * @param string $option_group A settings group name. Should correspond to a whitelisted option key name.
  1784  * @global array $new_whitelist_options
  1740  * 	Default whitelisted option key names include "general," "discussion," and "reading," among others.
       
  1741  * @param string $option_name The name of an option to sanitize and save.
       
  1742  * @param callable $sanitize_callback A callback function that sanitizes the option's value.
       
  1743  */
       
  1744 function register_setting( $option_group, $option_name, $sanitize_callback = '' ) {
       
  1745 	global $new_whitelist_options;
       
  1746 
       
  1747 	if ( 'misc' == $option_group ) {
       
  1748 		_deprecated_argument( __FUNCTION__, '3.0', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'misc' ) );
       
  1749 		$option_group = 'general';
       
  1750 	}
       
  1751 
       
  1752 	if ( 'privacy' == $option_group ) {
       
  1753 		_deprecated_argument( __FUNCTION__, '3.5', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'privacy' ) );
       
  1754 		$option_group = 'reading';
       
  1755 	}
       
  1756 
       
  1757 	$new_whitelist_options[ $option_group ][] = $option_name;
       
  1758 	if ( $sanitize_callback != '' )
       
  1759 		add_filter( "sanitize_option_{$option_name}", $sanitize_callback );
       
  1760 }
       
  1761 
       
  1762 /**
       
  1763  * Unregister a setting
       
  1764  *
       
  1765  * @since 2.7.0
       
  1766  *
       
  1767  * @param string   $option_group
       
  1768  * @param string   $option_name
       
  1769  * @param callable $sanitize_callback
       
  1770  */
       
  1771 function unregister_setting( $option_group, $option_name, $sanitize_callback = '' ) {
       
  1772 	global $new_whitelist_options;
       
  1773 
       
  1774 	if ( 'misc' == $option_group ) {
       
  1775 		_deprecated_argument( __FUNCTION__, '3.0', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'misc' ) );
       
  1776 		$option_group = 'general';
       
  1777 	}
       
  1778 
       
  1779 	if ( 'privacy' == $option_group ) {
       
  1780 		_deprecated_argument( __FUNCTION__, '3.5', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'privacy' ) );
       
  1781 		$option_group = 'reading';
       
  1782 	}
       
  1783 
       
  1784 	$pos = array_search( $option_name, (array) $new_whitelist_options );
       
  1785 	if ( $pos !== false )
       
  1786 		unset( $new_whitelist_options[ $option_group ][ $pos ] );
       
  1787 	if ( $sanitize_callback != '' )
       
  1788 		remove_filter( "sanitize_option_{$option_name}", $sanitize_callback );
       
  1789 }
       
  1790 
       
  1791 /**
       
  1792  * {@internal Missing Short Description}}
       
  1793  *
       
  1794  * @since 2.7.0
       
  1795  *
  1785  *
  1796  * @param array $options
  1786  * @param array $options
  1797  * @return array
  1787  * @return array
  1798  */
  1788  */
  1799 function option_update_filter( $options ) {
  1789 function option_update_filter( $options ) {
  1802 	if ( is_array( $new_whitelist_options ) )
  1792 	if ( is_array( $new_whitelist_options ) )
  1803 		$options = add_option_whitelist( $new_whitelist_options, $options );
  1793 		$options = add_option_whitelist( $new_whitelist_options, $options );
  1804 
  1794 
  1805 	return $options;
  1795 	return $options;
  1806 }
  1796 }
  1807 add_filter( 'whitelist_options', 'option_update_filter' );
  1797 
  1808 
  1798 /**
  1809 /**
  1799  * Adds an array of options to the options whitelist.
  1810  * {@internal Missing Short Description}}
       
  1811  *
  1800  *
  1812  * @since 2.7.0
  1801  * @since 2.7.0
       
  1802  *
       
  1803  * @global array $whitelist_options
  1813  *
  1804  *
  1814  * @param array        $new_options
  1805  * @param array        $new_options
  1815  * @param string|array $options
  1806  * @param string|array $options
  1816  * @return array
  1807  * @return array
  1817  */
  1808  */
  1836 
  1827 
  1837 	return $whitelist_options;
  1828 	return $whitelist_options;
  1838 }
  1829 }
  1839 
  1830 
  1840 /**
  1831 /**
  1841  * {@internal Missing Short Description}}
  1832  * Removes a list of options from the options whitelist.
  1842  *
  1833  *
  1843  * @since 2.7.0
  1834  * @since 2.7.0
       
  1835  *
       
  1836  * @global array $whitelist_options
  1844  *
  1837  *
  1845  * @param array        $del_options
  1838  * @param array        $del_options
  1846  * @param string|array $options
  1839  * @param string|array $options
  1847  * @return array
  1840  * @return array
  1848  */
  1841  */
  1888 function wp_clean_plugins_cache( $clear_update_cache = true ) {
  1881 function wp_clean_plugins_cache( $clear_update_cache = true ) {
  1889 	if ( $clear_update_cache )
  1882 	if ( $clear_update_cache )
  1890 		delete_site_transient( 'update_plugins' );
  1883 		delete_site_transient( 'update_plugins' );
  1891 	wp_cache_delete( 'plugins', 'plugins' );
  1884 	wp_cache_delete( 'plugins', 'plugins' );
  1892 }
  1885 }
       
  1886 
       
  1887 /**
       
  1888  * Load a given plugin attempt to generate errors.
       
  1889  *
       
  1890  * @since 3.0.0
       
  1891  * @since 4.4.0 Function was moved into the `wp-admin/includes/plugin.php` file.
       
  1892  *
       
  1893  * @param string $plugin Plugin file to load.
       
  1894  */
       
  1895 function plugin_sandbox_scrape( $plugin ) {
       
  1896 	wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin );
       
  1897 	include( WP_PLUGIN_DIR . '/' . $plugin );
       
  1898 }
       
  1899 
       
  1900 /**
       
  1901  * Helper function for adding content to the Privacy Policy Guide.
       
  1902  *
       
  1903  * Plugins and themes should suggest text for inclusion in the site's privacy policy.
       
  1904  * The suggested text should contain information about any functionality that affects user privacy,
       
  1905  * and will be shown on the Privacy Policy Guide screen.
       
  1906  *
       
  1907  * A plugin or theme can use this function multiple times as long as it will help to better present
       
  1908  * the suggested policy content. For example modular plugins such as WooCommerse or Jetpack
       
  1909  * can add or remove suggested content depending on the modules/extensions that are enabled.
       
  1910  * For more information see the Plugin Handbook:
       
  1911  * https://developer.wordpress.org/plugins/privacy/suggesting-text-for-the-site-privacy-policy/.
       
  1912  *
       
  1913  * Intended for use with the `'admin_init'` action.
       
  1914  *
       
  1915  * @since 4.9.6
       
  1916  *
       
  1917  * @param string $plugin_name The name of the plugin or theme that is suggesting content for the site's privacy policy.
       
  1918  * @param string $policy_text The suggested content for inclusion in the policy.
       
  1919  */
       
  1920 function wp_add_privacy_policy_content( $plugin_name, $policy_text ) {
       
  1921 	if ( ! is_admin() ) {
       
  1922 		_doing_it_wrong(
       
  1923 			__FUNCTION__,
       
  1924 			sprintf(
       
  1925 				/* translators: %s: admin_init */
       
  1926 				__( 'The suggested privacy policy content should be added only in wp-admin by using the %s (or later) action.' ),
       
  1927 				'<code>admin_init</code>'
       
  1928 			),
       
  1929 			'4.9.7'
       
  1930 		);
       
  1931 		return;
       
  1932 	} elseif ( ! doing_action( 'admin_init' ) && ! did_action( 'admin_init' ) ) {
       
  1933 		_doing_it_wrong(
       
  1934 			__FUNCTION__,
       
  1935 			sprintf(
       
  1936 				/* translators: %s: admin_init */
       
  1937 				__( 'The suggested privacy policy content should be added by using the %s (or later) action. Please see the inline documentation.' ),
       
  1938 				'<code>admin_init</code>'
       
  1939 			),
       
  1940 			'4.9.7'
       
  1941 		);
       
  1942 		return;
       
  1943 	}
       
  1944 
       
  1945 	if ( ! class_exists( 'WP_Privacy_Policy_Content' ) ) {
       
  1946 		require_once( ABSPATH . 'wp-admin/includes/misc.php' );
       
  1947 	}
       
  1948 
       
  1949 	WP_Privacy_Policy_Content::add( $plugin_name, $policy_text );
       
  1950 }