[ Root ] [ Search ] [ Index ]

PHP Cross Reference of WordPress 3.0.1

Provided by Yoast

title

Body

[close]

/wp-admin/includes/ -> plugin.php (source)

   1  <?php
   2  /**
   3   * WordPress Plugin Administration API
   4   *
   5   * @package WordPress
   6   * @subpackage Administration
   7   */
   8  
   9  /**
  10   * Parse the plugin contents to retrieve plugin's metadata.
  11   *
  12   * The metadata of the plugin's data searches for the following in the plugin's
  13   * header. All plugin data must be on its own line. For plugin description, it
  14   * must not have any newlines or only parts of the description will be displayed
  15   * and the same goes for the plugin data. The below is formatted for printing.
  16   *
  17   * <code>
  18   * /*
  19   * Plugin Name: Name of Plugin
  20   * Plugin URI: Link to plugin information
  21   * Description: Plugin Description
  22   * Author: Plugin author's name
  23   * Author URI: Link to the author's web site
  24   * Version: Must be set in the plugin for WordPress 2.3+
  25   * Text Domain: Optional. Unique identifier, should be same as the one used in
  26   *        plugin_text_domain()
  27   * Domain Path: Optional. Only useful if the translations are located in a
  28   *        folder above the plugin's base path. For example, if .mo files are
  29   *        located in the locale folder then Domain Path will be "/locale/" and
  30   *        must have the first slash. Defaults to the base folder the plugin is
  31   *        located in.
  32   * Network: Optional. Specify "Network: true" to require that a plugin is activated
  33   *        across all sites in an installation. This will prevent a plugin from being
  34   *        activated on a single site when Multisite is enabled.
  35   *  * / # Remove the space to close comment
  36   * </code>
  37   *
  38   * Plugin data returned array contains the following:
  39   *        'Name' - Name of the plugin, must be unique.
  40   *        'Title' - Title of the plugin and the link to the plugin's web site.
  41   *        'Description' - Description of what the plugin does and/or notes
  42   *        from the author.
  43   *        'Author' - The author's name
  44   *        'AuthorURI' - The authors web site address.
  45   *        'Version' - The plugin version number.
  46   *        'PluginURI' - Plugin web site address.
  47   *        'TextDomain' - Plugin's text domain for localization.
  48   *        'DomainPath' - Plugin's relative directory path to .mo files.
  49   *        'Network' - Boolean. Whether the plugin can only be activated network wide.
  50   *
  51   * Some users have issues with opening large files and manipulating the contents
  52   * for want is usually the first 1kiB or 2kiB. This function stops pulling in
  53   * the plugin contents when it has all of the required plugin data.
  54   *
  55   * The first 8kiB of the file will be pulled in and if the plugin data is not
  56   * within that first 8kiB, then the plugin author should correct their plugin
  57   * and move the plugin data headers to the top.
  58   *
  59   * The plugin file is assumed to have permissions to allow for scripts to read
  60   * the file. This is not checked however and the file is only opened for
  61   * reading.
  62   *
  63   * @link http://trac.wordpress.org/ticket/5651 Previous Optimizations.
  64   * @link http://trac.wordpress.org/ticket/7372 Further and better Optimizations.
  65   * @since 1.5.0
  66   *
  67   * @param string $plugin_file Path to the plugin file
  68   * @param bool $markup If the returned data should have HTML markup applied
  69   * @param bool $translate If the returned data should be translated
  70   * @return array See above for description.
  71   */
  72  function get_plugin_data( $plugin_file, $markup = true, $translate = true ) {
  73  
  74      $default_headers = array(
  75          'Name' => 'Plugin Name',
  76          'PluginURI' => 'Plugin URI',
  77          'Version' => 'Version',
  78          'Description' => 'Description',
  79          'Author' => 'Author',
  80          'AuthorURI' => 'Author URI',
  81          'TextDomain' => 'Text Domain',
  82          'DomainPath' => 'Domain Path',
  83          'Network' => 'Network',
  84          // Site Wide Only is deprecated in favor of Network.
  85          '_sitewide' => 'Site Wide Only',
  86      );
  87  
  88      $plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' );
  89  
  90      // Site Wide Only is the old header for Network
  91      if ( empty( $plugin_data['Network'] ) && ! empty( $plugin_data['_sitewide'] ) ) {
  92          _deprecated_argument( __FUNCTION__, '3.0', sprintf( __( 'The <code>%1$s</code> plugin header is deprecated. Use <code>%2$s</code> instead.' ), 'Site Wide Only: true', 'Network: true' ) );
  93          $plugin_data['Network'] = $plugin_data['_sitewide'];
  94      }
  95      $plugin_data['Network'] = ( 'true' == strtolower( $plugin_data['Network'] ) );
  96      unset( $plugin_data['_sitewide'] );
  97  
  98      //For backward compatibility by default Title is the same as Name.
  99      $plugin_data['Title'] = $plugin_data['Name'];
 100  
 101      if ( $markup || $translate )
 102          $plugin_data = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup, $translate );
 103  
 104      return $plugin_data;
 105  }
 106  
 107  function _get_plugin_data_markup_translate($plugin_file, $plugin_data, $markup = true, $translate = true) {
 108  
 109      //Translate fields30
 110      if ( $translate && ! empty($plugin_data['TextDomain']) ) {
 111          if ( ! empty( $plugin_data['DomainPath'] ) )
 112              load_plugin_textdomain($plugin_data['TextDomain'], false, dirname($plugin_file). $plugin_data['DomainPath']);
 113          else
 114              load_plugin_textdomain($plugin_data['TextDomain'], false, dirname($plugin_file));
 115  
 116          foreach ( array('Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version') as $field )
 117              $plugin_data[ $field ] = translate($plugin_data[ $field ], $plugin_data['TextDomain']);
 118      }
 119  
 120      //Apply Markup
 121      if ( $markup ) {
 122          if ( ! empty($plugin_data['PluginURI']) && ! empty($plugin_data['Name']) )
 123              $plugin_data['Title'] = '<a href="' . $plugin_data['PluginURI'] . '" title="' . __( 'Visit plugin homepage' ) . '">' . $plugin_data['Name'] . '</a>';
 124          else
 125              $plugin_data['Title'] = $plugin_data['Name'];
 126  
 127          if ( ! empty($plugin_data['AuthorURI']) && ! empty($plugin_data['Author']) )
 128              $plugin_data['Author'] = '<a href="' . $plugin_data['AuthorURI'] . '" title="' . __( 'Visit author homepage' ) . '">' . $plugin_data['Author'] . '</a>';
 129  
 130          $plugin_data['Description'] = wptexturize( $plugin_data['Description'] );
 131          if ( ! empty($plugin_data['Author']) )
 132              $plugin_data['Description'] .= ' <cite>' . sprintf( __('By %s'), $plugin_data['Author'] ) . '.</cite>';
 133      }
 134  
 135      $plugins_allowedtags = array('a' => array('href' => array(),'title' => array()),'abbr' => array('title' => array()),'acronym' => array('title' => array()),'code' => array(),'em' => array(),'strong' => array());
 136  
 137      // Sanitize all displayed data
 138      $plugin_data['Title']       = wp_kses($plugin_data['Title'], $plugins_allowedtags);
 139      $plugin_data['Version']     = wp_kses($plugin_data['Version'], $plugins_allowedtags);
 140      $plugin_data['Description'] = wp_kses($plugin_data['Description'], $plugins_allowedtags);
 141      $plugin_data['Author']      = wp_kses($plugin_data['Author'], $plugins_allowedtags);
 142  
 143      return $plugin_data;
 144  }
 145  
 146  /**
 147   * Get a list of a plugin's files.
 148   *
 149   * @since 2.8.0
 150   *
 151   * @param string $plugin Plugin ID
 152   * @return array List of files relative to the plugin root.
 153   */
 154  function get_plugin_files($plugin) {
 155      $plugin_file = WP_PLUGIN_DIR . '/' . $plugin;
 156      $dir = dirname($plugin_file);
 157      $plugin_files = array($plugin);
 158      if ( is_dir($dir) && $dir != WP_PLUGIN_DIR ) {
 159          $plugins_dir = @ opendir( $dir );
 160          if ( $plugins_dir ) {
 161              while (($file = readdir( $plugins_dir ) ) !== false ) {
 162                  if ( substr($file, 0, 1) == '.' )
 163                      continue;
 164                  if ( is_dir( $dir . '/' . $file ) ) {
 165                      $plugins_subdir = @ opendir( $dir . '/' . $file );
 166                      if ( $plugins_subdir ) {
 167                          while (($subfile = readdir( $plugins_subdir ) ) !== false ) {
 168                              if ( substr($subfile, 0, 1) == '.' )
 169                                  continue;
 170                              $plugin_files[] = plugin_basename("$dir/$file/$subfile");
 171                          }
 172                          @closedir( $plugins_subdir );
 173                      }
 174                  } else {
 175                      if ( plugin_basename("$dir/$file") != $plugin )
 176                          $plugin_files[] = plugin_basename("$dir/$file");
 177                  }
 178              }
 179              @closedir( $plugins_dir );
 180          }
 181      }
 182  
 183      return $plugin_files;
 184  }
 185  
 186  /**
 187   * Check the plugins directory and retrieve all plugin files with plugin data.
 188   *
 189   * WordPress only supports plugin files in the base plugins directory
 190   * (wp-content/plugins) and in one directory above the plugins directory
 191   * (wp-content/plugins/my-plugin). The file it looks for has the plugin data and
 192   * must be found in those two locations. It is recommended that do keep your
 193   * plugin files in directories.
 194   *
 195   * The file with the plugin data is the file that will be included and therefore
 196   * needs to have the main execution for the plugin. This does not mean
 197   * everything must be contained in the file and it is recommended that the file
 198   * be split for maintainability. Keep everything in one file for extreme
 199   * optimization purposes.
 200   *
 201   * @since unknown
 202   *
 203   * @param string $plugin_folder Optional. Relative path to single plugin folder.
 204   * @return array Key is the plugin file path and the value is an array of the plugin data.
 205   */
 206  function get_plugins($plugin_folder = '') {
 207  
 208      if ( ! $cache_plugins = wp_cache_get('plugins', 'plugins') )
 209          $cache_plugins = array();
 210  
 211      if ( isset($cache_plugins[ $plugin_folder ]) )
 212          return $cache_plugins[ $plugin_folder ];
 213  
 214      $wp_plugins = array ();
 215      $plugin_root = WP_PLUGIN_DIR;
 216      if ( !empty($plugin_folder) )
 217          $plugin_root .= $plugin_folder;
 218  
 219      // Files in wp-content/plugins directory
 220      $plugins_dir = @ opendir( $plugin_root);
 221      $plugin_files = array();
 222      if ( $plugins_dir ) {
 223          while (($file = readdir( $plugins_dir ) ) !== false ) {
 224              if ( substr($file, 0, 1) == '.' )
 225                  continue;
 226              if ( is_dir( $plugin_root.'/'.$file ) ) {
 227                  $plugins_subdir = @ opendir( $plugin_root.'/'.$file );
 228                  if ( $plugins_subdir ) {
 229                      while (($subfile = readdir( $plugins_subdir ) ) !== false ) {
 230                          if ( substr($subfile, 0, 1) == '.' )
 231                              continue;
 232                          if ( substr($subfile, -4) == '.php' )
 233                              $plugin_files[] = "$file/$subfile";
 234                      }
 235                  }
 236              } else {
 237                  if ( substr($file, -4) == '.php' )
 238                      $plugin_files[] = $file;
 239              }
 240          }
 241      } else {
 242          return $wp_plugins;
 243      }
 244  
 245      @closedir( $plugins_dir );
 246      @closedir( $plugins_subdir );
 247  
 248      if ( empty($plugin_files) )
 249          return $wp_plugins;
 250  
 251      foreach ( $plugin_files as $plugin_file ) {
 252          if ( !is_readable( "$plugin_root/$plugin_file" ) )
 253              continue;
 254  
 255          $plugin_data = get_plugin_data( "$plugin_root/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached.
 256  
 257          if ( empty ( $plugin_data['Name'] ) )
 258              continue;
 259  
 260          $wp_plugins[plugin_basename( $plugin_file )] = $plugin_data;
 261      }
 262  
 263      uasort( $wp_plugins, create_function( '$a, $b', 'return strnatcasecmp( $a["Name"], $b["Name"] );' ));
 264  
 265      $cache_plugins[ $plugin_folder ] = $wp_plugins;
 266      wp_cache_set('plugins', $cache_plugins, 'plugins');
 267  
 268      return $wp_plugins;
 269  }
 270  
 271  /**
 272   * Check the mu-plugins directory and retrieve all mu-plugin files with any plugin data.
 273   *
 274   * WordPress only includes mu-plugin files in the base mu-plugins directory (wp-content/mu-plugins).
 275   *
 276   * @since 3.0.0
 277   * @return array Key is the mu-plugin file path and the value is an array of the mu-plugin data.
 278   */
 279  function get_mu_plugins() {
 280      $wp_plugins = array();
 281      // Files in wp-content/mu-plugins directory
 282      $plugin_files = array();
 283  
 284      if ( ! is_dir( WPMU_PLUGIN_DIR ) )
 285          return $wp_plugins;
 286      if ( $plugins_dir = @ opendir( WPMU_PLUGIN_DIR ) ) {
 287          while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
 288              if ( substr( $file, -4 ) == '.php' )
 289                  $plugin_files[] = $file;
 290          }
 291      } else {
 292          return $wp_plugins;
 293      }
 294  
 295      @closedir( $plugins_dir );
 296  
 297      if ( empty($plugin_files) )
 298          return $wp_plugins;
 299  
 300      foreach ( $plugin_files as $plugin_file ) {
 301          if ( !is_readable( WPMU_PLUGIN_DIR . "/$plugin_file" ) )
 302              continue;
 303  
 304          $plugin_data = get_plugin_data( WPMU_PLUGIN_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached.
 305  
 306          if ( empty ( $plugin_data['Name'] ) )
 307              $plugin_data['Name'] = $plugin_file;
 308  
 309          $wp_plugins[ $plugin_file ] = $plugin_data;
 310      }
 311  
 312      if ( isset( $wp_plugins['index.php'] ) && filesize( WPMU_PLUGIN_DIR . '/index.php') <= 30 ) // silence is golden
 313          unset( $wp_plugins['index.php'] );
 314  
 315      uasort( $wp_plugins, create_function( '$a, $b', 'return strnatcasecmp( $a["Name"], $b["Name"] );' ));
 316  
 317      return $wp_plugins;
 318  }
 319  
 320  /**
 321   * Check the wp-content directory and retrieve all drop-ins with any plugin data.
 322   *
 323   * @since 3.0.0
 324   * @return array Key is the file path and the value is an array of the plugin data.
 325   */
 326  function get_dropins() {
 327      $dropins = array();
 328      $plugin_files = array();
 329  
 330      $_dropins = _get_dropins();
 331  
 332      // These exist in the wp-content directory
 333      if ( $plugins_dir = @ opendir( WP_CONTENT_DIR ) ) {
 334          while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
 335              if ( isset( $_dropins[ $file ] ) )
 336                  $plugin_files[] = $file;
 337          }
 338      } else {
 339          return $dropins;
 340      }
 341  
 342      @closedir( $plugins_dir );
 343  
 344      if ( empty($plugin_files) )
 345          return $dropins;
 346  
 347      foreach ( $plugin_files as $plugin_file ) {
 348          if ( !is_readable( WP_CONTENT_DIR . "/$plugin_file" ) )
 349              continue;
 350          $plugin_data = get_plugin_data( WP_CONTENT_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached.
 351          if ( empty( $plugin_data['Name'] ) )
 352              $plugin_data['Name'] = $plugin_file;
 353          $dropins[ $plugin_file ] = $plugin_data;
 354      }
 355  
 356      uksort( $dropins, create_function( '$a, $b', 'return strnatcasecmp( $a, $b );' ));
 357  
 358      return $dropins;
 359  }
 360  
 361  /**
 362   * Returns drop-ins that WordPress uses.
 363   *
 364   * Includes Multisite drop-ins only when is_multisite()
 365   *
 366   * @since 3.0.0
 367   * @return array Key is file name. The value is an array, with the first value the
 368   *    purpose of the drop-in and the second value the name of the constant that must be
 369   *    true for the drop-in to be used, or true if no constant is required.
 370   */
 371  function _get_dropins() {
 372      $dropins = array(
 373          'advanced-cache.php' => array( __( 'Advanced caching plugin.'       ), 'WP_CACHE' ), // WP_CACHE
 374          'db.php'             => array( __( 'Custom database class.'         ), true ), // auto on load
 375          'db-error.php'       => array( __( 'Custom database error message.' ), true ), // auto on error
 376          'install.php'        => array( __( 'Custom install script.'         ), true ), // auto on install
 377          'maintenance.php'    => array( __( 'Custom maintenance message.'    ), true ), // auto on maintenance
 378          'object-cache.php'   => array( __( 'External object cache.'         ), true ), // auto on load
 379      );
 380  
 381      if ( is_multisite() ) {
 382          $dropins['sunrise.php'       ] = array( __( 'Executed before Multisite is loaded.' ), 'SUNRISE' ); // SUNRISE
 383          $dropins['blog-deleted.php'  ] = array( __( 'Custom site deleted message.'   ), true ); // auto on deleted blog
 384          $dropins['blog-inactive.php' ] = array( __( 'Custom site inactive message.'  ), true ); // auto on inactive blog
 385          $dropins['blog-suspended.php'] = array( __( 'Custom site suspended message.' ), true ); // auto on archived or spammed blog
 386      }
 387  
 388      return $dropins;
 389  }
 390  
 391  /**
 392   * Check whether the plugin is active by checking the active_plugins list.
 393   *
 394   * @since 2.5.0
 395   *
 396   * @param string $plugin Base plugin path from plugins directory.
 397   * @return bool True, if in the active plugins list. False, not in the list.
 398   */
 399  function is_plugin_active( $plugin ) {
 400      return in_array( $plugin, (array) get_option( 'active_plugins', array() ) ) || is_plugin_active_for_network( $plugin );
 401  }
 402  
 403  /**
 404   * Check whether the plugin is active for the entire network.
 405   *
 406   * @since 3.0.0
 407   *
 408   * @param string $plugin Base plugin path from plugins directory.
 409   * @return bool True, if active for the network, otherwise false.
 410   */
 411  function is_plugin_active_for_network( $plugin ) {
 412      if ( !is_multisite() )
 413          return false;
 414  
 415      $plugins = get_site_option( 'active_sitewide_plugins');
 416      if ( isset($plugins[$plugin]) )
 417          return true;
 418  
 419      return false;
 420  }
 421  
 422  /**
 423   * Checks for "Network: true" in the plugin header to see if this should
 424   * be activated only as a network wide plugin. The plugin would also work
 425   * when Multisite is not enabled.
 426   *
 427   * Checks for "Site Wide Only: true" for backwards compatibility.
 428   *
 429   * @since 3.0.0
 430   *
 431   * @param $file Plugin to check
 432   * $return bool True if plugin is network only, false otherwise.
 433   */
 434  function is_network_only_plugin( $plugin ) {
 435      $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
 436      if ( $plugin_data )
 437          return $plugin_data['Network'];
 438      return false;
 439  }
 440  
 441  /**
 442   * Attempts activation of plugin in a "sandbox" and redirects on success.
 443   *
 444   * A plugin that is already activated will not attempt to be activated again.
 445   *
 446   * The way it works is by setting the redirection to the error before trying to
 447   * include the plugin file. If the plugin fails, then the redirection will not
 448   * be overwritten with the success message. Also, the options will not be
 449   * updated and the activation hook will not be called on plugin error.
 450   *
 451   * It should be noted that in no way the below code will actually prevent errors
 452   * within the file. The code should not be used elsewhere to replicate the
 453   * "sandbox", which uses redirection to work.
 454   * {@source 13 1}
 455   *
 456   * If any errors are found or text is outputted, then it will be captured to
 457   * ensure that the success redirection will update the error redirection.
 458   *
 459   * @since unknown
 460   *
 461   * @param string $plugin Plugin path to main plugin file with plugin data.
 462   * @param string $redirect Optional. URL to redirect to.
 463   * @param bool $network_wide Whether to enable the plugin for all sites in the network or just the current site.  Multisite only. Default is false.
 464   * @return WP_Error|null WP_Error on invalid file or null on success.
 465   */
 466  function activate_plugin( $plugin, $redirect = '', $network_wide = false) {
 467      $plugin  = plugin_basename( trim( $plugin ) );
 468  
 469      if ( is_multisite() && ( $network_wide || is_network_only_plugin($plugin) ) ) {
 470          $network_wide = true;
 471          $current = get_site_option( 'active_sitewide_plugins', array() );
 472      } else {
 473          $current = get_option( 'active_plugins', array() );
 474      }
 475  
 476      $valid = validate_plugin($plugin);
 477      if ( is_wp_error($valid) )
 478          return $valid;
 479  
 480      if ( !in_array($plugin, $current) ) {
 481          if ( !empty($redirect) )
 482              wp_redirect(add_query_arg('_error_nonce', wp_create_nonce('plugin-activation-error_' . $plugin), $redirect)); // we'll override this later if the plugin can be included without fatal error
 483          ob_start();
 484          include(WP_PLUGIN_DIR . '/' . $plugin);
 485          do_action( 'activate_plugin', trim( $plugin) );
 486          if ( $network_wide ) {
 487              $current[$plugin] = time();
 488              update_site_option( 'active_sitewide_plugins', $current );
 489          } else {
 490              $current[] = $plugin;
 491              sort($current);
 492              update_option('active_plugins', $current);
 493          }
 494          do_action( 'activate_' . trim( $plugin ) );
 495          do_action( 'activated_plugin', trim( $plugin) );
 496          if ( ob_get_length() > 0 ) {
 497              $output = ob_get_clean();
 498              return new WP_Error('unexpected_output', __('The plugin generated unexpected output.'), $output);
 499          }
 500          ob_end_clean();
 501      }
 502  
 503      return null;
 504  }
 505  
 506  /**
 507   * Deactivate a single plugin or multiple plugins.
 508   *
 509   * The deactivation hook is disabled by the plugin upgrader by using the $silent
 510   * parameter.
 511   *
 512   * @since unknown
 513   *
 514   * @param string|array $plugins Single plugin or list of plugins to deactivate.
 515   * @param bool $silent Optional, default is false. Prevent calling deactivate hook.
 516   */
 517  function deactivate_plugins( $plugins, $silent = false ) {
 518      $network_current = get_site_option( 'active_sitewide_plugins', array() );
 519      $current = get_option( 'active_plugins', array() );
 520      $do_blog = $do_network = false;
 521  
 522      foreach ( (array) $plugins as $plugin ) {
 523          $plugin = plugin_basename($plugin);
 524          if ( ! is_plugin_active($plugin) )
 525              continue;
 526          if ( ! $silent )
 527              do_action( 'deactivate_plugin', trim( $plugin ) );
 528  
 529          if ( is_plugin_active_for_network($plugin) ) {
 530              // Deactivate network wide
 531              $do_network = true;
 532              unset( $network_current[ $plugin ] );
 533          } else {
 534              // Deactivate for this blog only
 535              $key = array_search( $plugin, (array) $current );
 536              if ( false !== $key ) {
 537                  $do_blog = true;
 538                  array_splice( $current, $key, 1 );
 539              }
 540          }
 541  
 542          //Used by Plugin updater to internally deactivate plugin, however, not to notify plugins of the fact to prevent plugin output.
 543          if ( ! $silent ) {
 544              do_action( 'deactivate_' . trim( $plugin ) );
 545              do_action( 'deactivated_plugin', trim( $plugin ) );
 546          }
 547      }
 548  
 549      if ( $do_blog )
 550          update_option('active_plugins', $current);
 551      if ( $do_network )
 552          update_site_option( 'active_sitewide_plugins', $network_current );
 553  }
 554  
 555  /**
 556   * Activate multiple plugins.
 557   *
 558   * When WP_Error is returned, it does not mean that one of the plugins had
 559   * errors. It means that one or more of the plugins file path was invalid.
 560   *
 561   * The execution will be halted as soon as one of the plugins has an error.
 562   *
 563   * @since unknown
 564   *
 565   * @param string|array $plugins
 566   * @param string $redirect Redirect to page after successful activation.
 567   * @param bool $network_wide Whether to enable the plugin for all sites in the network.
 568   * @return bool|WP_Error True when finished or WP_Error if there were errors during a plugin activation.
 569   */
 570  function activate_plugins($plugins, $redirect = '', $network_wide) {
 571      if ( !is_array($plugins) )
 572          $plugins = array($plugins);
 573  
 574      $errors = array();
 575      foreach ( (array) $plugins as $plugin ) {
 576          if ( !empty($redirect) )
 577              $redirect = add_query_arg('plugin', $plugin, $redirect);
 578          $result = activate_plugin($plugin, $redirect, $network_wide);
 579          if ( is_wp_error($result) )
 580              $errors[$plugin] = $result;
 581      }
 582  
 583      if ( !empty($errors) )
 584          return new WP_Error('plugins_invalid', __('One of the plugins is invalid.'), $errors);
 585  
 586      return true;
 587  }
 588  
 589  /**
 590   * Remove directory and files of a plugin for a single or list of plugin(s).
 591   *
 592   * If the plugins parameter list is empty, false will be returned. True when
 593   * completed.
 594   *
 595   * @since unknown
 596   *
 597   * @param array $plugins List of plugin
 598   * @param string $redirect Redirect to page when complete.
 599   * @return mixed
 600   */
 601  function delete_plugins($plugins, $redirect = '' ) {
 602      global $wp_filesystem;
 603  
 604      if ( empty($plugins) )
 605          return false;
 606  
 607      $checked = array();
 608      foreach( $plugins as $plugin )
 609          $checked[] = 'checked[]=' . $plugin;
 610  
 611      ob_start();
 612      $url = wp_nonce_url('plugins.php?action=delete-selected&verify-delete=1&' . implode('&', $checked), 'bulk-manage-plugins');
 613      if ( false === ($credentials = request_filesystem_credentials($url)) ) {
 614          $data = ob_get_contents();
 615          ob_end_clean();
 616          if ( ! empty($data) ){
 617              include_once ( ABSPATH . 'wp-admin/admin-header.php');
 618              echo $data;
 619              include ( ABSPATH . 'wp-admin/admin-footer.php');
 620              exit;
 621          }
 622          return;
 623      }
 624  
 625      if ( ! WP_Filesystem($credentials) ) {
 626          request_filesystem_credentials($url, '', true); //Failed to connect, Error and request again
 627          $data = ob_get_contents();
 628          ob_end_clean();
 629          if ( ! empty($data) ){
 630              include_once ( ABSPATH . 'wp-admin/admin-header.php');
 631              echo $data;
 632              include ( ABSPATH . 'wp-admin/admin-footer.php');
 633              exit;
 634          }
 635          return;
 636      }
 637  
 638      if ( ! is_object($wp_filesystem) )
 639          return new WP_Error('fs_unavailable', __('Could not access filesystem.'));
 640  
 641      if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() )
 642          return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors);
 643  
 644      //Get the base plugin folder
 645      $plugins_dir = $wp_filesystem->wp_plugins_dir();
 646      if ( empty($plugins_dir) )
 647          return new WP_Error('fs_no_plugins_dir', __('Unable to locate WordPress Plugin directory.'));
 648  
 649      $plugins_dir = trailingslashit( $plugins_dir );
 650  
 651      $errors = array();
 652  
 653      foreach( $plugins as $plugin_file ) {
 654          // Run Uninstall hook
 655          if ( is_uninstallable_plugin( $plugin_file ) )
 656              uninstall_plugin($plugin_file);
 657  
 658          $this_plugin_dir = trailingslashit( dirname($plugins_dir . $plugin_file) );
 659          // If plugin is in its own directory, recursively delete the directory.
 660          if ( strpos($plugin_file, '/') && $this_plugin_dir != $plugins_dir ) //base check on if plugin includes directory seperator AND that its not the root plugin folder
 661              $deleted = $wp_filesystem->delete($this_plugin_dir, true);
 662          else
 663              $deleted = $wp_filesystem->delete($plugins_dir . $plugin_file);
 664  
 665          if ( ! $deleted )
 666              $errors[] = $plugin_file;
 667      }
 668  
 669      if ( ! empty($errors) )
 670          return new WP_Error('could_not_remove_plugin', sprintf(__('Could not fully remove the plugin(s) %s.'), implode(', ', $errors)) );
 671  
 672      // Force refresh of plugin update information
 673      if ( $current = get_site_transient('update_plugins') ) {
 674          unset( $current->response[ $plugin_file ] );
 675          set_site_transient('update_plugins', $current);
 676      }
 677  
 678      return true;
 679  }
 680  
 681  /**
 682   * Validate active plugins
 683   *
 684   * Validate all active plugins, deactivates invalid and
 685   * returns an array of deactivated ones.
 686   *
 687   * @since unknown
 688   * @return array invalid plugins, plugin as key, error as value
 689   */
 690  function validate_active_plugins() {
 691      $plugins = get_option( 'active_plugins', array() );
 692      // validate vartype: array
 693      if ( ! is_array( $plugins ) ) {
 694          update_option( 'active_plugins', array() );
 695          $plugins = array();
 696      }
 697  
 698      if ( is_multisite() && is_super_admin() ) {
 699          $network_plugins = (array) get_site_option( 'active_sitewide_plugins', array() );
 700          $plugins = array_merge( $plugins, array_keys( $network_plugins ) );
 701      }
 702  
 703      if ( empty( $plugins ) )
 704          return;
 705  
 706      $invalid = array();
 707  
 708      // invalid plugins get deactivated
 709      foreach ( $plugins as $plugin ) {
 710          $result = validate_plugin( $plugin );
 711          if ( is_wp_error( $result ) ) {
 712              $invalid[$plugin] = $result;
 713              deactivate_plugins( $plugin, true );
 714          }
 715      }
 716      return $invalid;
 717  }
 718  
 719  /**
 720   * Validate the plugin path.
 721   *
 722   * Checks that the file exists and {@link validate_file() is valid file}.
 723   *
 724   * @since unknown
 725   *
 726   * @param string $plugin Plugin Path
 727   * @return WP_Error|int 0 on success, WP_Error on failure.
 728   */
 729  function validate_plugin($plugin) {
 730      if ( validate_file($plugin) )
 731          return new WP_Error('plugin_invalid', __('Invalid plugin path.'));
 732      if ( ! file_exists(WP_PLUGIN_DIR . '/' . $plugin) )
 733          return new WP_Error('plugin_not_found', __('Plugin file does not exist.'));
 734  
 735      $installed_plugins = get_plugins();
 736      if ( ! isset($installed_plugins[$plugin]) )
 737          return new WP_Error('no_plugin_header', __('The plugin does not have a valid header.'));
 738      return 0;
 739  }
 740  
 741  /**
 742   * Whether the plugin can be uninstalled.
 743   *
 744   * @since 2.7.0
 745   *
 746   * @param string $plugin Plugin path to check.
 747   * @return bool Whether plugin can be uninstalled.
 748   */
 749  function is_uninstallable_plugin($plugin) {
 750      $file = plugin_basename($plugin);
 751  
 752      $uninstallable_plugins = (array) get_option('uninstall_plugins');
 753      if ( isset( $uninstallable_plugins[$file] ) || file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) )
 754          return true;
 755  
 756      return false;
 757  }
 758  
 759  /**
 760   * Uninstall a single plugin.
 761   *
 762   * Calls the uninstall hook, if it is available.
 763   *
 764   * @since 2.7.0
 765   *
 766   * @param string $plugin Relative plugin path from Plugin Directory.
 767   */
 768  function uninstall_plugin($plugin) {
 769      $file = plugin_basename($plugin);
 770  
 771      $uninstallable_plugins = (array) get_option('uninstall_plugins');
 772      if ( file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) ) {
 773          if ( isset( $uninstallable_plugins[$file] ) ) {
 774              unset($uninstallable_plugins[$file]);
 775              update_option('uninstall_plugins', $uninstallable_plugins);
 776          }
 777          unset($uninstallable_plugins);
 778  
 779          define('WP_UNINSTALL_PLUGIN', $file);
 780          include WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php';
 781  
 782          return true;
 783      }
 784  
 785      if ( isset( $uninstallable_plugins[$file] ) ) {
 786          $callable = $uninstallable_plugins[$file];
 787          unset($uninstallable_plugins[$file]);
 788          update_option('uninstall_plugins', $uninstallable_plugins);
 789          unset($uninstallable_plugins);
 790  
 791          include WP_PLUGIN_DIR . '/' . $file;
 792  
 793          add_action( 'uninstall_' . $file, $callable );
 794          do_action( 'uninstall_' . $file );
 795      }
 796  }
 797  
 798  //
 799  // Menu
 800  //
 801  
 802  /**
 803   * Add a top level menu page
 804   *
 805   * This function takes a capability which will be used to determine whether
 806   * or not a page is included in the menu.
 807   *
 808   * The function which is hooked in to handle the output of the page must check
 809   * that the user has the required capability as well.
 810   *
 811   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
 812   * @param string $menu_title The text to be used for the menu
 813   * @param string $capability The capability required for this menu to be displayed to the user.
 814   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
 815   * @param callback $function The function to be called to output the content for this page.
 816   * @param string $icon_url The url to the icon to be used for this menu
 817   * @param int $position The position in the menu order this one should appear
 818   */
 819  function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = NULL ) {
 820      global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages;
 821  
 822      $menu_slug = plugin_basename( $menu_slug );
 823  
 824      $admin_page_hooks[$menu_slug] = sanitize_title( $menu_title );
 825  
 826      $hookname = get_plugin_page_hookname( $menu_slug, '' );
 827  
 828      if ( !empty( $function ) && !empty( $hookname ) && current_user_can( $capability ) )
 829          add_action( $hookname, $function );
 830  
 831      if ( empty($icon_url) )
 832          $icon_url = esc_url( admin_url( 'images/generic.png' ) );
 833      elseif ( is_ssl() && 0 === strpos($icon_url, 'http://') )
 834          $icon_url = 'https://' . substr($icon_url, 7);
 835  
 836      $new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $hookname, $hookname, $icon_url );
 837  
 838      if ( null === $position  )
 839          $menu[] = $new_menu;
 840      else
 841          $menu[$position] = $new_menu;
 842  
 843      $_registered_pages[$hookname] = true;
 844  
 845      // No parent as top level
 846      $_parent_pages[$menu_slug] = false;
 847  
 848      return $hookname;
 849  }
 850  
 851  /**
 852   * Add a top level menu page in the 'objects' section
 853   *
 854   * This function takes a capability which will be used to determine whether
 855   * or not a page is included in the menu.
 856   *
 857   * The function which is hooked in to handle the output of the page must check
 858   * that the user has the required capability as well.
 859   *
 860   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
 861   * @param string $menu_title The text to be used for the menu
 862   * @param string $capability The capability required for this menu to be displayed to the user.
 863   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
 864   * @param callback $function The function to be called to output the content for this page.
 865   * @param string $icon_url The url to the icon to be used for this menu
 866   */
 867  function add_object_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '') {
 868      global $_wp_last_object_menu;
 869  
 870      $_wp_last_object_menu++;
 871  
 872      return add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $_wp_last_object_menu);
 873  }
 874  
 875  /**
 876   * Add a top level menu page in the 'utility' section
 877   *
 878   * This function takes a capability which will be used to determine whether
 879   * or not a page is included in the menu.
 880   *
 881   * The function which is hooked in to handle the output of the page must check
 882   * that the user has the required capability as well.
 883   *
 884   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
 885   * @param string $menu_title The text to be used for the menu
 886   * @param string $capability The capability required for this menu to be displayed to the user.
 887   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
 888   * @param callback $function The function to be called to output the content for this page.
 889   * @param string $icon_url The url to the icon to be used for this menu
 890   */
 891  function add_utility_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '') {
 892      global $_wp_last_utility_menu;
 893  
 894      $_wp_last_utility_menu++;
 895  
 896      return add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $_wp_last_utility_menu);
 897  }
 898  
 899  /**
 900   * Add a sub menu page
 901   *
 902   * This function takes a capability which will be used to determine whether
 903   * or not a page is included in the menu.
 904   *
 905   * The function which is hooked in to handle the output of the page must check
 906   * that the user has the required capability as well.
 907   *
 908   * @param string $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page)
 909   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
 910   * @param string $menu_title The text to be used for the menu
 911   * @param string $capability The capability required for this menu to be displayed to the user.
 912   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
 913   * @param callback $function The function to be called to output the content for this page.
 914   */
 915  function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
 916      global $submenu;
 917      global $menu;
 918      global $_wp_real_parent_file;
 919      global $_wp_submenu_nopriv;
 920      global $_registered_pages;
 921      global $_parent_pages;
 922  
 923      $menu_slug = plugin_basename( $menu_slug );
 924      $parent_slug = plugin_basename( $parent_slug);
 925  
 926      if ( isset( $_wp_real_parent_file[$parent_slug] ) )
 927          $parent_slug = $_wp_real_parent_file[$parent_slug];
 928  
 929      if ( !current_user_can( $capability ) ) {
 930          $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
 931          return false;
 932      }
 933  
 934      // If the parent doesn't already have a submenu, add a link to the parent
 935      // as the first item in the submenu.  If the submenu file is the same as the
 936      // parent file someone is trying to link back to the parent manually.  In
 937      // this case, don't automatically add a link back to avoid duplication.
 938      if (!isset( $submenu[$parent_slug] ) && $menu_slug != $parent_slug  ) {
 939          foreach ( (array)$menu as $parent_menu ) {
 940              if ( $parent_menu[2] == $parent_slug && current_user_can( $parent_menu[1] ) )
 941                  $submenu[$parent_slug][] = $parent_menu;
 942          }
 943      }
 944  
 945      $submenu[$parent_slug][] = array ( $menu_title, $capability, $menu_slug, $page_title );
 946  
 947      $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug);
 948      if (!empty ( $function ) && !empty ( $hookname ))
 949          add_action( $hookname, $function );
 950  
 951      $_registered_pages[$hookname] = true;
 952      // backwards-compatibility for plugins using add_management page.  See wp-admin/admin.php for redirect from edit.php to tools.php
 953      if ( 'tools.php' == $parent_slug )
 954          $_registered_pages[get_plugin_page_hookname( $menu_slug, 'edit.php')] = true;
 955  
 956      // No parent as top level
 957      $_parent_pages[$menu_slug] = $parent_slug;
 958  
 959      return $hookname;
 960  }
 961  
 962  /**
 963   * Add sub menu page to the tools main menu.
 964  *
 965   * This function takes a capability which will be used to determine whether
 966   * or not a page is included in the menu.
 967   *
 968   * The function which is hooked in to handle the output of the page must check
 969   * that the user has the required capability as well.
 970   *
 971   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
 972   * @param string $menu_title The text to be used for the menu
 973   * @param string $capability The capability required for this menu to be displayed to the user.
 974   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
 975   * @param callback $function The function to be called to output the content for this page.
 976   */
 977  function add_management_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
 978      return add_submenu_page( 'tools.php', $page_title, $menu_title, $capability, $menu_slug, $function );
 979  }
 980  
 981  /**
 982   * Add sub menu page to the options main menu.
 983  *
 984   * This function takes a capability which will be used to determine whether
 985   * or not a page is included in the menu.
 986   *
 987   * The function which is hooked in to handle the output of the page must check
 988   * that the user has the required capability as well.
 989   *
 990   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
 991   * @param string $menu_title The text to be used for the menu
 992   * @param string $capability The capability required for this menu to be displayed to the user.
 993   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
 994   * @param callback $function The function to be called to output the content for this page.
 995   */
 996  function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
 997      return add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $menu_slug, $function );
 998  }
 999  
1000  /**
1001   * Add sub menu page to the themes main menu.
1002  *
1003   * This function takes a capability which will be used to determine whether
1004   * or not a page is included in the menu.
1005   *
1006   * The function which is hooked in to handle the output of the page must check
1007   * that the user has the required capability as well.
1008   *
1009   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1010   * @param string $menu_title The text to be used for the menu
1011   * @param string $capability The capability required for this menu to be displayed to the user.
1012   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1013   * @param callback $function The function to be called to output the content for this page.
1014   */
1015  function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1016      return add_submenu_page( 'themes.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1017  }
1018  
1019  /**
1020   * Add sub menu page to the plugins main menu.
1021  *
1022   * This function takes a capability which will be used to determine whether
1023   * or not a page is included in the menu.
1024   *
1025   * The function which is hooked in to handle the output of the page must check
1026   * that the user has the required capability as well.
1027   *
1028   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1029   * @param string $menu_title The text to be used for the menu
1030   * @param string $capability The capability required for this menu to be displayed to the user.
1031   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1032   * @param callback $function The function to be called to output the content for this page.
1033   */
1034  function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1035      return add_submenu_page( 'plugins.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1036  }
1037  
1038  /**
1039   * Add sub menu page to the Users/Profile main menu.
1040  *
1041   * This function takes a capability which will be used to determine whether
1042   * or not a page is included in the menu.
1043   *
1044   * The function which is hooked in to handle the output of the page must check
1045   * that the user has the required capability as well.
1046   *
1047   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1048   * @param string $menu_title The text to be used for the menu
1049   * @param string $capability The capability required for this menu to be displayed to the user.
1050   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1051   * @param callback $function The function to be called to output the content for this page.
1052   */
1053  function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1054      if ( current_user_can('edit_users') )
1055          $parent = 'users.php';
1056      else
1057          $parent = 'profile.php';
1058      return add_submenu_page( $parent, $page_title, $menu_title, $capability, $menu_slug, $function );
1059  }
1060  /**
1061   * Add sub menu page to the Dashboard main menu.
1062  *
1063   * This function takes a capability which will be used to determine whether
1064   * or not a page is included in the menu.
1065   *
1066   * The function which is hooked in to handle the output of the page must check
1067   * that the user has the required capability as well.
1068   *
1069   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1070   * @param string $menu_title The text to be used for the menu
1071   * @param string $capability The capability required for this menu to be displayed to the user.
1072   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1073   * @param callback $function The function to be called to output the content for this page.
1074   */
1075  function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1076      return add_submenu_page( 'index.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1077  }
1078  
1079  /**
1080   * Add sub menu page to the posts main menu.
1081  *
1082   * This function takes a capability which will be used to determine whether
1083   * or not a page is included in the menu.
1084   *
1085   * The function which is hooked in to handle the output of the page must check
1086   * that the user has the required capability as well.
1087   *
1088   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1089   * @param string $menu_title The text to be used for the menu
1090   * @param string $capability The capability required for this menu to be displayed to the user.
1091   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1092   * @param callback $function The function to be called to output the content for this page.
1093   */
1094  function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1095      return add_submenu_page( 'edit.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1096  }
1097  
1098  /**
1099   * Add sub menu page to the media main menu.
1100  *
1101   * This function takes a capability which will be used to determine whether
1102   * or not a page is included in the menu.
1103   *
1104   * The function which is hooked in to handle the output of the page must check
1105   * that the user has the required capability as well.
1106   *
1107   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1108   * @param string $menu_title The text to be used for the menu
1109   * @param string $capability The capability required for this menu to be displayed to the user.
1110   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1111   * @param callback $function The function to be called to output the content for this page.
1112   */
1113  function add_media_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1114      return add_submenu_page( 'upload.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1115  }
1116  
1117  /**
1118   * Add sub menu page to the links main menu.
1119  *
1120   * This function takes a capability which will be used to determine whether
1121   * or not a page is included in the menu.
1122   *
1123   * The function which is hooked in to handle the output of the page must check
1124   * that the user has the required capability as well.
1125   *
1126   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1127   * @param string $menu_title The text to be used for the menu
1128   * @param string $capability The capability required for this menu to be displayed to the user.
1129   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1130   * @param callback $function The function to be called to output the content for this page.
1131   */
1132  function add_links_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1133      return add_submenu_page( 'link-manager.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1134  }
1135  
1136  /**
1137   * Add sub menu page to the pages main menu.
1138  *
1139   * This function takes a capability which will be used to determine whether
1140   * or not a page is included in the menu.
1141   *
1142   * The function which is hooked in to handle the output of the page must check
1143   * that the user has the required capability as well.
1144   *
1145   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1146   * @param string $menu_title The text to be used for the menu
1147   * @param string $capability The capability required for this menu to be displayed to the user.
1148   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1149   * @param callback $function The function to be called to output the content for this page.
1150   */
1151  function add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1152      return add_submenu_page( 'edit.php?post_type=page', $page_title, $menu_title, $capability, $menu_slug, $function );
1153  }
1154  
1155  /**
1156   * Add sub menu page to the comments main menu.
1157  *
1158   * This function takes a capability which will be used to determine whether
1159   * or not a page is included in the menu.
1160   *
1161   * The function which is hooked in to handle the output of the page must check
1162   * that the user has the required capability as well.
1163   *
1164   * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
1165   * @param string $menu_title The text to be used for the menu
1166   * @param string $capability The capability required for this menu to be displayed to the user.
1167   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1168   * @param callback $function The function to be called to output the content for this page.
1169   */
1170  function add_comments_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
1171      return add_submenu_page( 'edit-comments.php', $page_title, $menu_title, $capability, $menu_slug, $function );
1172  }
1173  
1174  /**
1175   * Get the url to access a particular menu page based on the slug it was registered with.
1176   *
1177   * If the slug hasn't been registered properly no url will be returned
1178   *
1179   * @since 3.0
1180   *
1181   * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
1182   * @param bool $echo Whether or not to echo the url - default is true
1183   * @return string the url
1184   */
1185  function menu_page_url($menu_slug, $echo = true) {
1186      global $_parent_pages;
1187  
1188      if ( isset( $_parent_pages[$menu_slug] ) ) {
1189          if ( $_parent_pages[$menu_slug] ) {
1190              $url = admin_url( add_query_arg( 'page', $menu_slug, $_parent_pages[$menu_slug] ) );
1191          } else {
1192              $url = admin_url('admin.php?page=' . $menu_slug);
1193          }
1194      } else {
1195          $url = '';
1196      }
1197  
1198      $url = esc_url($url);
1199  
1200      if ( $echo )
1201          echo $url;
1202  
1203      return $url;
1204  }
1205  
1206  //
1207  // Pluggable Menu Support -- Private
1208  //
1209  
1210  function get_admin_page_parent( $parent = '' ) {
1211      global $parent_file;
1212      global $menu;
1213      global $submenu;
1214      global $pagenow;
1215      global $typenow;
1216      global $plugin_page;
1217      global $_wp_real_parent_file;
1218      global $_wp_menu_nopriv;
1219      global $_wp_submenu_nopriv;
1220  
1221      if ( !empty ( $parent ) && 'admin.php' != $parent ) {
1222          if ( isset( $_wp_real_parent_file[$parent] ) )
1223              $parent = $_wp_real_parent_file[$parent];
1224          return $parent;
1225      }
1226  
1227      /*
1228      if ( !empty ( $parent_file ) ) {
1229          if ( isset( $_wp_real_parent_file[$parent_file] ) )
1230              $parent_file = $_wp_real_parent_file[$parent_file];
1231  
1232          return $parent_file;
1233      }
1234      */
1235  
1236      if ( $pagenow == 'admin.php' && isset( $plugin_page ) ) {
1237          foreach ( (array)$menu as $parent_menu ) {
1238              if ( $parent_menu[2] == $plugin_page ) {
1239                  $parent_file = $plugin_page;
1240                  if ( isset( $_wp_real_parent_file[$parent_file] ) )
1241                      $parent_file = $_wp_real_parent_file[$parent_file];
1242                  return $parent_file;
1243              }
1244          }
1245          if ( isset( $_wp_menu_nopriv[$plugin_page] ) ) {
1246              $parent_file = $plugin_page;
1247              if ( isset( $_wp_real_parent_file[$parent_file] ) )
1248                      $parent_file = $_wp_real_parent_file[$parent_file];
1249              return $parent_file;
1250          }
1251      }
1252  
1253      if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$pagenow][$plugin_page] ) ) {
1254          $parent_file = $pagenow;
1255          if ( isset( $_wp_real_parent_file[$parent_file] ) )
1256              $parent_file = $_wp_real_parent_file[$parent_file];
1257          return $parent_file;
1258      }
1259  
1260      foreach (array_keys( (array)$submenu ) as $parent) {
1261          foreach ( $submenu[$parent] as $submenu_array ) {
1262              if ( isset( $_wp_real_parent_file[$parent] ) )
1263                  $parent = $_wp_real_parent_file[$parent];
1264              if ( !empty($typenow) && ($submenu_array[2] == "$pagenow?post_type=$typenow") ) {
1265                  $parent_file = $parent;
1266                  return $parent;
1267              } elseif ( $submenu_array[2] == $pagenow && empty($typenow) && ( empty($parent_file) || false === strpos($parent_file, '?') ) ) {
1268                  $parent_file = $parent;
1269                  return $parent;
1270              } else
1271                  if ( isset( $plugin_page ) && ($plugin_page == $submenu_array[2] ) ) {
1272                      $parent_file = $parent;
1273                      return $parent;
1274                  }
1275          }
1276      }
1277  
1278      if ( empty($parent_file) )
1279          $parent_file = '';
1280      return '';
1281  }
1282  
1283  function get_admin_page_title() {
1284      global $title;
1285      global $menu;
1286      global $submenu;
1287      global $pagenow;
1288      global $plugin_page;
1289      global $typenow;
1290  
1291      if ( ! empty ( $title ) )
1292          return $title;
1293  
1294      $hook = get_plugin_page_hook( $plugin_page, $pagenow );
1295  
1296      $parent = $parent1 = get_admin_page_parent();
1297  
1298      if ( empty ( $parent) ) {
1299          foreach ( (array)$menu as $menu_array ) {
1300              if ( isset( $menu_array[3] ) ) {
1301                  if ( $menu_array[2] == $pagenow ) {
1302                      $title = $menu_array[3];
1303                      return $menu_array[3];
1304                  } else
1305                      if ( isset( $plugin_page ) && ($plugin_page == $menu_array[2] ) && ($hook == $menu_array[3] ) ) {
1306                          $title = $menu_array[3];
1307                          return $menu_array[3];
1308                      }
1309              } else {
1310                  $title = $menu_array[0];
1311                  return $title;
1312              }
1313          }
1314      } else {
1315          foreach ( array_keys( $submenu ) as $parent ) {
1316              foreach ( $submenu[$parent] as $submenu_array ) {
1317                  if ( isset( $plugin_page ) &&
1318                      ( $plugin_page == $submenu_array[2] ) &&
1319                      (
1320                          ( $parent == $pagenow ) ||
1321                          ( $parent == $plugin_page ) ||
1322                          ( $plugin_page == $hook ) ||
1323                          ( $pagenow == 'admin.php' && $parent1 != $submenu_array[2] ) ||
1324                          ( !empty($typenow) && $parent == $pagenow . '?post_type=' . $typenow)
1325                      )
1326                      ) {
1327                          $title = $submenu_array[3];
1328                          return $submenu_array[3];
1329                      }
1330  
1331                  if ( $submenu_array[2] != $pagenow || isset( $_GET['page'] ) ) // not the current page
1332                      continue;
1333  
1334                  if ( isset( $submenu_array[3] ) ) {
1335                      $title = $submenu_array[3];
1336                      return $submenu_array[3];
1337                  } else {
1338                      $title = $submenu_array[0];
1339                      return $title;
1340                  }
1341              }
1342          }
1343          if ( empty ( $title ) ) {
1344              foreach ( $menu as $menu_array ) {
1345                  if ( isset( $plugin_page ) &&
1346                      ( $plugin_page == $menu_array[2] ) &&
1347                      ( $pagenow == 'admin.php' ) &&
1348                      ( $parent1 == $menu_array[2] ) )
1349                      {
1350                          $title = $menu_array[3];
1351                          return $menu_array[3];
1352                      }
1353              }
1354          }
1355      }
1356  
1357      return $title;
1358  }
1359  
1360  function get_plugin_page_hook( $plugin_page, $parent_page ) {
1361      $hook = get_plugin_page_hookname( $plugin_page, $parent_page );
1362      if ( has_action($hook) )
1363          return $hook;
1364      else
1365          return null;
1366  }
1367  
1368  function get_plugin_page_hookname( $plugin_page, $parent_page ) {
1369      global $admin_page_hooks;
1370  
1371      $parent = get_admin_page_parent( $parent_page );
1372  
1373      $page_type = 'admin';
1374      if ( empty ( $parent_page ) || 'admin.php' == $parent_page || isset( $admin_page_hooks[$plugin_page] ) ) {
1375          if ( isset( $admin_page_hooks[$plugin_page] ) )
1376              $page_type = 'toplevel';
1377          else
1378              if ( isset( $admin_page_hooks[$parent] ))
1379                  $page_type = $admin_page_hooks[$parent];
1380      } else if ( isset( $admin_page_hooks[$parent] ) ) {
1381          $page_type = $admin_page_hooks[$parent];
1382      }
1383  
1384      $plugin_name = preg_replace( '!\.php!', '', $plugin_page );
1385  
1386      return $page_type . '_page_' . $plugin_name;
1387  }
1388  
1389  function user_can_access_admin_page() {
1390      global $pagenow;
1391      global $menu;
1392      global $submenu;
1393      global $_wp_menu_nopriv;
1394      global $_wp_submenu_nopriv;
1395      global $plugin_page;
1396      global $_registered_pages;
1397  
1398      $parent = get_admin_page_parent();
1399  
1400      if ( !isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$parent][$pagenow] ) )
1401          return false;
1402  
1403      if ( isset( $plugin_page ) ) {
1404          if ( isset( $_wp_submenu_nopriv[$parent][$plugin_page] ) )
1405              return false;
1406  
1407          $hookname = get_plugin_page_hookname($plugin_page, $parent);
1408  
1409          if ( !isset($_registered_pages[$hookname]) )
1410              return false;
1411      }
1412  
1413      if ( empty( $parent) ) {
1414          if ( isset( $_wp_menu_nopriv[$pagenow] ) )
1415              return false;
1416          if ( isset( $_wp_submenu_nopriv[$pagenow][$pagenow] ) )
1417              return false;
1418          if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$pagenow][$plugin_page] ) )
1419              return false;
1420          if ( isset( $plugin_page ) && isset( $_wp_menu_nopriv[$plugin_page] ) )
1421              return false;
1422          foreach (array_keys( $_wp_submenu_nopriv ) as $key ) {
1423              if ( isset( $_wp_submenu_nopriv[$key][$pagenow] ) )
1424                  return false;
1425              if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$key][$plugin_page] ) )
1426              return false;
1427          }
1428          return true;
1429      }
1430  
1431      if ( isset( $plugin_page ) && ( $plugin_page == $parent ) && isset( $_wp_menu_nopriv[$plugin_page] ) )
1432          return false;
1433  
1434      if ( isset( $submenu[$parent] ) ) {
1435          foreach ( $submenu[$parent] as $submenu_array ) {
1436              if ( isset( $plugin_page ) && ( $submenu_array[2] == $plugin_page ) ) {
1437                  if ( current_user_can( $submenu_array[1] ))
1438                      return true;
1439                  else
1440                      return false;
1441              } else if ( $submenu_array[2] == $pagenow ) {
1442                  if ( current_user_can( $submenu_array[1] ))
1443                      return true;
1444                  else
1445                      return false;
1446              }
1447          }
1448      }
1449  
1450      foreach ( $menu as $menu_array ) {
1451          if ( $menu_array[2] == $parent) {
1452              if ( current_user_can( $menu_array[1] ))
1453                  return true;
1454              else
1455                  return false;
1456          }
1457      }
1458  
1459      return true;
1460  }
1461  
1462  /* Whitelist functions */
1463  
1464  /**
1465   * Register a setting and its sanitization callback
1466   *
1467   * @since 2.7.0
1468   *
1469   * @param string $option_group A settings group name.  Should correspond to a whitelisted option key name.
1470   *     Default whitelisted option key names include "general," "discussion," and "reading," among others.
1471   * @param string $option_name The name of an option to sanitize and save.
1472   * @param unknown_type $sanitize_callback A callback function that sanitizes the option's value.
1473   * @return unknown
1474   */
1475  function register_setting( $option_group, $option_name, $sanitize_callback = '' ) {
1476      global $new_whitelist_options;
1477  
1478      if ( 'misc' == $option_group ) {
1479          _deprecated_argument( __FUNCTION__, '3.0', __( 'The miscellaneous options group has been removed. Use another settings group.' ) );
1480          $option_group = 'general';
1481      }
1482  
1483      $new_whitelist_options[ $option_group ][] = $option_name;
1484      if ( $sanitize_callback != '' )
1485          add_filter( "sanitize_option_{$option_name}", $sanitize_callback );
1486  }
1487  
1488  /**
1489   * Unregister a setting
1490   *
1491   * @since 2.7.0
1492   *
1493   * @param unknown_type $option_group
1494   * @param unknown_type $option_name
1495   * @param unknown_type $sanitize_callback
1496   * @return unknown
1497   */
1498  function unregister_setting( $option_group, $option_name, $sanitize_callback = '' ) {
1499      global $new_whitelist_options;
1500  
1501      if ( 'misc' == $option_group ) {
1502          _deprecated_argument( __FUNCTION__, '3.0', __( 'The miscellaneous options group has been removed. Use another settings group.' ) );
1503          $option_group = 'general';
1504      }
1505  
1506      $pos = array_search( $option_name, (array) $new_whitelist_options );
1507      if ( $pos !== false )
1508          unset( $new_whitelist_options[ $option_group ][ $pos ] );
1509      if ( $sanitize_callback != '' )
1510          remove_filter( "sanitize_option_{$option_name}", $sanitize_callback );
1511  }
1512  
1513  /**
1514   * {@internal Missing Short Description}}
1515   *
1516   * @since unknown
1517   *
1518   * @param unknown_type $options
1519   * @return unknown
1520   */
1521  function option_update_filter( $options ) {
1522      global $new_whitelist_options;
1523  
1524      if ( is_array( $new_whitelist_options ) )
1525          $options = add_option_whitelist( $new_whitelist_options, $options );
1526  
1527      return $options;
1528  }
1529  add_filter( 'whitelist_options', 'option_update_filter' );
1530  
1531  /**
1532   * {@internal Missing Short Description}}
1533   *
1534   * @since unknown
1535   *
1536   * @param unknown_type $new_options
1537   * @param unknown_type $options
1538   * @return unknown
1539   */
1540  function add_option_whitelist( $new_options, $options = '' ) {
1541      if ( $options == '' )
1542          global $whitelist_options;
1543      else
1544          $whitelist_options = $options;
1545  
1546      foreach ( $new_options as $page => $keys ) {
1547          foreach ( $keys as $key ) {
1548              if ( !isset($whitelist_options[ $page ]) || !is_array($whitelist_options[ $page ]) ) {
1549                  $whitelist_options[ $page ] = array();
1550                  $whitelist_options[ $page ][] = $key;
1551              } else {
1552                  $pos = array_search( $key, $whitelist_options[ $page ] );
1553                  if ( $pos === false )
1554                      $whitelist_options[ $page ][] = $key;
1555              }
1556          }
1557      }
1558  
1559      return $whitelist_options;
1560  }
1561  
1562  /**
1563   * {@internal Missing Short Description}}
1564   *
1565   * @since unknown
1566   *
1567   * @param unknown_type $del_options
1568   * @param unknown_type $options
1569   * @return unknown
1570   */
1571  function remove_option_whitelist( $del_options, $options = '' ) {
1572      if ( $options == '' )
1573          global $whitelist_options;
1574      else
1575          $whitelist_options = $options;
1576  
1577      foreach ( $del_options as $page => $keys ) {
1578          foreach ( $keys as $key ) {
1579              if ( isset($whitelist_options[ $page ]) && is_array($whitelist_options[ $page ]) ) {
1580                  $pos = array_search( $key, $whitelist_options[ $page ] );
1581                  if ( $pos !== false )
1582                      unset( $whitelist_options[ $page ][ $pos ] );
1583              }
1584          }
1585      }
1586  
1587      return $whitelist_options;
1588  }
1589  
1590  /**
1591   * Output nonce, action, and option_page fields for a settings page.
1592   *
1593   * @since 2.7.0
1594   *
1595   * @param string $option_group A settings group name.  This should match the group name used in register_setting().
1596   */
1597  function settings_fields($option_group) {
1598      echo "<input type='hidden' name='option_page' value='" . esc_attr($option_group) . "' />";
1599      echo '<input type="hidden" name="action" value="update" />';
1600      wp_nonce_field("$option_group-options");
1601  }
1602  
1603  ?>


Generated: Thu Oct 14 05:12:05 2010 Cross-referenced by PHPXref 0.7