[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-admin/ -> plugins.php (source)

   1  <?php
   2  /**
   3   * Plugins administration panel.
   4   *
   5   * @package WordPress
   6   * @subpackage Administration
   7   */
   8  
   9  /** WordPress Administration Bootstrap */
  10  require_once  __DIR__ . '/admin.php';
  11  
  12  /**
  13   * @global string $status   Current plugin status view, set by WP_Plugins_List_Table.
  14   * @global int    $page     Current page number, set by WP_Plugins_List_Table.
  15   * @global array  $plugins  Set by WP_Plugins_List_Table::prepare_items().
  16   * @global int    $user_ID  ID of the current user, set during authentication.
  17   */
  18  global $status, $page, $plugins, $user_ID;
  19  
  20  if ( ! current_user_can( 'activate_plugins' ) ) {
  21      wp_die( __( 'Sorry, you are not allowed to manage plugins for this site.' ) );
  22  }
  23  
  24  $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
  25  $pagenum       = $wp_list_table->get_pagenum();
  26  
  27  $action = $wp_list_table->current_action();
  28  
  29  $plugin = isset( $_REQUEST['plugin'] ) ? wp_unslash( $_REQUEST['plugin'] ) : '';
  30  $s      = isset( $_REQUEST['s'] ) ? urlencode( wp_unslash( $_REQUEST['s'] ) ) : '';
  31  
  32  // Clean up request URI from temporary args for screen options/paging uri's to work as expected.
  33  $query_args_to_remove = array(
  34      'error',
  35      'deleted',
  36      'activate',
  37      'activate-multi',
  38      'deactivate',
  39      'deactivate-multi',
  40      'enabled-auto-update',
  41      'disabled-auto-update',
  42      'enabled-auto-update-multi',
  43      'disabled-auto-update-multi',
  44      '_error_nonce',
  45  );
  46  
  47  $_SERVER['REQUEST_URI'] = remove_query_arg( $query_args_to_remove, $_SERVER['REQUEST_URI'] );
  48  
  49  wp_enqueue_script( 'updates' );
  50  
  51  WP_Plugin_Dependencies::initialize();
  52  
  53  if ( $action ) {
  54  
  55      switch ( $action ) {
  56          case 'activate':
  57              if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
  58                  wp_die( __( 'Sorry, you are not allowed to activate this plugin.' ) );
  59              }
  60  
  61              if ( is_multisite() && ! is_network_admin() && is_network_only_plugin( $plugin ) ) {
  62                  wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) );
  63                  exit;
  64              }
  65  
  66              check_admin_referer( 'activate-plugin_' . $plugin );
  67  
  68              $result = activate_plugin( $plugin, self_admin_url( 'plugins.php?error=true&plugin=' . urlencode( $plugin ) ), is_network_admin() );
  69              if ( is_wp_error( $result ) ) {
  70                  if ( 'unexpected_output' === $result->get_error_code() ) {
  71                      $redirect = self_admin_url( 'plugins.php?error=true&charsout=' . strlen( $result->get_error_data() ) . '&plugin=' . urlencode( $plugin ) . "&plugin_status=$status&paged=$page&s=$s" );
  72                      wp_redirect( add_query_arg( '_error_nonce', wp_create_nonce( 'plugin-activation-error_' . $plugin ), $redirect ) );
  73                      exit;
  74                  } else {
  75                      wp_die( $result );
  76                  }
  77              }
  78  
  79              if ( ! is_network_admin() ) {
  80                  $recent = (array) get_option( 'recently_activated' );
  81                  unset( $recent[ $plugin ] );
  82                  update_option( 'recently_activated', $recent, false );
  83              } else {
  84                  $recent = (array) get_site_option( 'recently_activated' );
  85                  unset( $recent[ $plugin ] );
  86                  update_site_option( 'recently_activated', $recent );
  87              }
  88  
  89              if ( isset( $_GET['from'] ) && 'import' === $_GET['from'] ) {
  90                  // Overrides the ?error=true one above and redirects to the Imports page, stripping the -importer suffix.
  91                  wp_redirect( self_admin_url( 'import.php?import=' . str_replace( '-importer', '', dirname( $plugin ) ) ) );
  92              } elseif ( isset( $_GET['from'] ) && 'press-this' === $_GET['from'] ) {
  93                  wp_redirect( self_admin_url( 'press-this.php' ) );
  94              } else {
  95                  // Overrides the ?error=true one above.
  96                  wp_redirect( self_admin_url( "plugins.php?activate=true&plugin_status=$status&paged=$page&s=$s" ) );
  97              }
  98              exit;
  99  
 100          case 'activate-selected':
 101              if ( ! current_user_can( 'activate_plugins' ) ) {
 102                  wp_die( __( 'Sorry, you are not allowed to activate plugins for this site.' ) );
 103              }
 104  
 105              check_admin_referer( 'bulk-plugins' );
 106  
 107              $plugins = isset( $_POST['checked'] ) ? (array) wp_unslash( $_POST['checked'] ) : array();
 108  
 109              if ( is_network_admin() ) {
 110                  foreach ( $plugins as $i => $plugin ) {
 111                      // Only activate plugins which are not already network activated.
 112                      if ( is_plugin_active_for_network( $plugin ) ) {
 113                          unset( $plugins[ $i ] );
 114                      }
 115                  }
 116              } else {
 117                  foreach ( $plugins as $i => $plugin ) {
 118                      // Only activate plugins which are not already active and are not network-only when on Multisite.
 119                      if ( is_plugin_active( $plugin ) || ( is_multisite() && is_network_only_plugin( $plugin ) ) ) {
 120                          unset( $plugins[ $i ] );
 121                      }
 122                      // Only activate plugins which the user can activate.
 123                      if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
 124                          unset( $plugins[ $i ] );
 125                      }
 126                  }
 127              }
 128  
 129              if ( empty( $plugins ) ) {
 130                  wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) );
 131                  exit;
 132              }
 133  
 134              activate_plugins( $plugins, self_admin_url( 'plugins.php?error=true' ), is_network_admin() );
 135  
 136              if ( ! is_network_admin() ) {
 137                  $recent = (array) get_option( 'recently_activated' );
 138              } else {
 139                  $recent = (array) get_site_option( 'recently_activated' );
 140              }
 141  
 142              foreach ( $plugins as $plugin ) {
 143                  unset( $recent[ $plugin ] );
 144              }
 145  
 146              if ( ! is_network_admin() ) {
 147                  update_option( 'recently_activated', $recent, false );
 148              } else {
 149                  update_site_option( 'recently_activated', $recent );
 150              }
 151  
 152              wp_redirect( self_admin_url( "plugins.php?activate-multi=true&plugin_status=$status&paged=$page&s=$s" ) );
 153              exit;
 154  
 155          case 'update-selected':
 156              check_admin_referer( 'bulk-plugins' );
 157  
 158              if ( isset( $_GET['plugins'] ) ) {
 159                  $plugins = explode( ',', wp_unslash( $_GET['plugins'] ) );
 160              } elseif ( isset( $_POST['checked'] ) ) {
 161                  $plugins = (array) wp_unslash( $_POST['checked'] );
 162              } else {
 163                  $plugins = array();
 164              }
 165  
 166              // Used in the HTML title tag.
 167              $title       = __( 'Update Plugins' );
 168              $parent_file = 'plugins.php';
 169  
 170              wp_enqueue_script( 'updates' );
 171              require_once  ABSPATH . 'wp-admin/admin-header.php';
 172  
 173              echo '<div class="wrap">';
 174              echo '<h1>' . esc_html( $title ) . '</h1>';
 175  
 176              $url = self_admin_url( 'update.php?action=update-selected&amp;plugins=' . urlencode( implode( ',', $plugins ) ) );
 177              $url = wp_nonce_url( $url, 'bulk-update-plugins' );
 178  
 179              echo "<iframe src='$url' style='width: 100%; height:100%; min-height:850px;'></iframe>";
 180              echo '</div>';
 181              require_once  ABSPATH . 'wp-admin/admin-footer.php';
 182              exit;
 183  
 184          case 'error_scrape':
 185              if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
 186                  wp_die( __( 'Sorry, you are not allowed to activate this plugin.' ) );
 187              }
 188  
 189              check_admin_referer( 'plugin-activation-error_' . $plugin );
 190  
 191              $valid = validate_plugin( $plugin );
 192              if ( is_wp_error( $valid ) ) {
 193                  wp_die( $valid );
 194              }
 195  
 196              if ( ! WP_DEBUG ) {
 197                  error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR );
 198              }
 199  
 200              ini_set( 'display_errors', true ); // Ensure that fatal errors are displayed.
 201              // Go back to "sandbox" scope so we get the same errors as before.
 202              plugin_sandbox_scrape( $plugin );
 203              /** This action is documented in wp-admin/includes/plugin.php */
 204              do_action( "activate_{$plugin}", is_network_admin() );
 205              exit;
 206  
 207          case 'deactivate':
 208              if ( ! current_user_can( 'deactivate_plugin', $plugin ) ) {
 209                  wp_die( __( 'Sorry, you are not allowed to deactivate this plugin.' ) );
 210              }
 211  
 212              check_admin_referer( 'deactivate-plugin_' . $plugin );
 213  
 214              if ( ! is_network_admin() && is_plugin_active_for_network( $plugin ) ) {
 215                  wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) );
 216                  exit;
 217              }
 218  
 219              deactivate_plugins( $plugin, false, is_network_admin() );
 220  
 221              if ( ! is_network_admin() ) {
 222                  update_option( 'recently_activated', array( $plugin => time() ) + (array) get_option( 'recently_activated' ), false );
 223              } else {
 224                  update_site_option( 'recently_activated', array( $plugin => time() ) + (array) get_site_option( 'recently_activated' ) );
 225              }
 226  
 227              if ( headers_sent() ) {
 228                  echo "<meta http-equiv='refresh' content='" . esc_attr( "0;url=plugins.php?deactivate=true&plugin_status=$status&paged=$page&s=$s" ) . "' />";
 229              } else {
 230                  wp_redirect( self_admin_url( "plugins.php?deactivate=true&plugin_status=$status&paged=$page&s=$s" ) );
 231              }
 232              exit;
 233  
 234          case 'deactivate-selected':
 235              if ( ! current_user_can( 'deactivate_plugins' ) ) {
 236                  wp_die( __( 'Sorry, you are not allowed to deactivate plugins for this site.' ) );
 237              }
 238  
 239              check_admin_referer( 'bulk-plugins' );
 240  
 241              $plugins = isset( $_POST['checked'] ) ? (array) wp_unslash( $_POST['checked'] ) : array();
 242              // Do not deactivate plugins which are already deactivated.
 243              if ( is_network_admin() ) {
 244                  $plugins = array_filter( $plugins, 'is_plugin_active_for_network' );
 245              } else {
 246                  $plugins = array_filter( $plugins, 'is_plugin_active' );
 247                  $plugins = array_diff( $plugins, array_filter( $plugins, 'is_plugin_active_for_network' ) );
 248  
 249                  foreach ( $plugins as $i => $plugin ) {
 250                      // Only deactivate plugins which the user can deactivate.
 251                      if ( ! current_user_can( 'deactivate_plugin', $plugin ) ) {
 252                          unset( $plugins[ $i ] );
 253                      }
 254                  }
 255              }
 256              if ( empty( $plugins ) ) {
 257                  wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) );
 258                  exit;
 259              }
 260  
 261              deactivate_plugins( $plugins, false, is_network_admin() );
 262  
 263              $deactivated = array();
 264              foreach ( $plugins as $plugin ) {
 265                  $deactivated[ $plugin ] = time();
 266              }
 267  
 268              if ( ! is_network_admin() ) {
 269                  update_option( 'recently_activated', $deactivated + (array) get_option( 'recently_activated' ), false );
 270              } else {
 271                  update_site_option( 'recently_activated', $deactivated + (array) get_site_option( 'recently_activated' ) );
 272              }
 273  
 274              wp_redirect( self_admin_url( "plugins.php?deactivate-multi=true&plugin_status=$status&paged=$page&s=$s" ) );
 275              exit;
 276  
 277          case 'delete-selected':
 278              if ( ! current_user_can( 'delete_plugins' ) ) {
 279                  wp_die( __( 'Sorry, you are not allowed to delete plugins for this site.' ) );
 280              }
 281  
 282              check_admin_referer( 'bulk-plugins' );
 283  
 284              // $_POST = from the plugin form; $_GET = from the FTP details screen.
 285              $plugins = isset( $_REQUEST['checked'] ) ? (array) wp_unslash( $_REQUEST['checked'] ) : array();
 286              if ( empty( $plugins ) ) {
 287                  wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) );
 288                  exit;
 289              }
 290  
 291              $plugins = array_filter( $plugins, 'is_plugin_inactive' ); // Do not allow to delete activated plugins.
 292              if ( empty( $plugins ) ) {
 293                  wp_redirect( self_admin_url( "plugins.php?error=true&main=true&plugin_status=$status&paged=$page&s=$s" ) );
 294                  exit;
 295              }
 296  
 297              // Bail on all if any paths are invalid.
 298              // validate_file() returns truthy for invalid files.
 299              $invalid_plugin_files = array_filter( $plugins, 'validate_file' );
 300              if ( $invalid_plugin_files ) {
 301                  wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) );
 302                  exit;
 303              }
 304  
 305              require  ABSPATH . 'wp-admin/update.php';
 306  
 307              $parent_file = 'plugins.php';
 308  
 309              if ( ! isset( $_REQUEST['verify-delete'] ) ) {
 310                  wp_enqueue_script( 'jquery' );
 311                  require_once  ABSPATH . 'wp-admin/admin-header.php';
 312  
 313                  ?>
 314                  <div class="wrap">
 315                  <?php
 316  
 317                  $plugin_info              = array();
 318                  $have_non_network_plugins = false;
 319  
 320                  foreach ( (array) $plugins as $plugin ) {
 321                      $plugin_slug = dirname( $plugin );
 322  
 323                      if ( '.' === $plugin_slug ) {
 324                          $data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
 325                          if ( $data ) {
 326                              $plugin_info[ $plugin ]                     = $data;
 327                              $plugin_info[ $plugin ]['is_uninstallable'] = is_uninstallable_plugin( $plugin );
 328                              if ( ! $plugin_info[ $plugin ]['Network'] ) {
 329                                  $have_non_network_plugins = true;
 330                              }
 331                          }
 332                      } else {
 333                          // Get plugins list from that folder.
 334                          $folder_plugins = get_plugins( '/' . $plugin_slug );
 335                          if ( $folder_plugins ) {
 336                              foreach ( $folder_plugins as $plugin_file => $data ) {
 337                                  $plugin_info[ $plugin_file ]                     = _get_plugin_data_markup_translate( $plugin_file, $data );
 338                                  $plugin_info[ $plugin_file ]['is_uninstallable'] = is_uninstallable_plugin( $plugin );
 339                                  if ( ! $plugin_info[ $plugin_file ]['Network'] ) {
 340                                      $have_non_network_plugins = true;
 341                                  }
 342                              }
 343                          }
 344                      }
 345                  }
 346  
 347                  $plugins_to_delete = count( $plugin_info );
 348  
 349                  ?>
 350                  <?php if ( 1 === $plugins_to_delete ) : ?>
 351                      <h1><?php _e( 'Delete Plugin' ); ?></h1>
 352                      <?php
 353                      if ( $have_non_network_plugins && is_network_admin() ) :
 354                          $maybe_active_plugin = '<strong>' . __( 'Caution:' ) . '</strong> ' . __( 'This plugin may be active on other sites in the network.' );
 355                          wp_admin_notice(
 356                              $maybe_active_plugin,
 357                              array(
 358                                  'additional_classes' => array( 'error' ),
 359                              )
 360                          );
 361                      endif;
 362                      ?>
 363                      <p><?php _e( 'You are about to remove the following plugin:' ); ?></p>
 364                  <?php else : ?>
 365                      <h1><?php _e( 'Delete Plugins' ); ?></h1>
 366                      <?php
 367                      if ( $have_non_network_plugins && is_network_admin() ) :
 368                          $maybe_active_plugins = '<strong>' . __( 'Caution:' ) . '</strong> ' . __( 'These plugins may be active on other sites in the network.' );
 369                          wp_admin_notice(
 370                              $maybe_active_plugins,
 371                              array(
 372                                  'additional_classes' => array( 'error' ),
 373                              )
 374                          );
 375                      endif;
 376                      ?>
 377                      <p><?php _e( 'You are about to remove the following plugins:' ); ?></p>
 378                  <?php endif; ?>
 379                      <ul class="ul-disc">
 380                          <?php
 381  
 382                          $data_to_delete = false;
 383  
 384                          foreach ( $plugin_info as $plugin ) {
 385                              if ( $plugin['is_uninstallable'] ) {
 386                                  /* translators: 1: Plugin name, 2: Plugin author. */
 387                                  echo '<li>', sprintf( __( '%1$s by %2$s (will also <strong>delete its data</strong>)' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] . '</em>' ), '</li>';
 388                                  $data_to_delete = true;
 389                              } else {
 390                                  /* translators: 1: Plugin name, 2: Plugin author. */
 391                                  echo '<li>', sprintf( _x( '%1$s by %2$s', 'plugin' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] ) . '</em>', '</li>';
 392                              }
 393                          }
 394  
 395                          ?>
 396                      </ul>
 397                  <p>
 398                  <?php
 399  
 400                  if ( $data_to_delete ) {
 401                      _e( 'Are you sure you want to delete these files and data?' );
 402                  } else {
 403                      _e( 'Are you sure you want to delete these files?' );
 404                  }
 405  
 406                  ?>
 407                  </p>
 408                  <form method="post" action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" style="display:inline;">
 409                      <input type="hidden" name="verify-delete" value="1" />
 410                      <input type="hidden" name="action" value="delete-selected" />
 411                      <?php
 412  
 413                      foreach ( (array) $plugins as $plugin ) {
 414                          echo '<input type="hidden" name="checked[]" value="' . esc_attr( $plugin ) . '" />';
 415                      }
 416  
 417                      ?>
 418                      <?php wp_nonce_field( 'bulk-plugins' ); ?>
 419                      <?php submit_button( $data_to_delete ? __( 'Yes, delete these files and data' ) : __( 'Yes, delete these files' ), '', 'submit', false ); ?>
 420                  </form>
 421                  <?php
 422  
 423                  $referer = wp_get_referer();
 424  
 425                  ?>
 426                  <form method="post" action="<?php echo $referer ? esc_url( $referer ) : ''; ?>" style="display:inline;">
 427                      <?php submit_button( __( 'No, return me to the plugin list' ), '', 'submit', false ); ?>
 428                  </form>
 429                  </div>
 430                  <?php
 431  
 432                  require_once  ABSPATH . 'wp-admin/admin-footer.php';
 433                  exit;
 434              } else {
 435                  $plugins_to_delete = count( $plugins );
 436              } // End if verify-delete.
 437  
 438              $delete_result = delete_plugins( $plugins );
 439  
 440              // Store the result in an option rather than a URL param due to object type & length.
 441              // Cannot use transient/cache, as that could get flushed if any plugin flushes data on uninstall/delete.
 442              update_option( 'plugins_delete_result_' . $user_ID, $delete_result, false );
 443              wp_redirect( self_admin_url( "plugins.php?deleted=$plugins_to_delete&plugin_status=$status&paged=$page&s=$s" ) );
 444              exit;
 445          case 'clear-recent-list':
 446              if ( ! is_network_admin() ) {
 447                  update_option( 'recently_activated', array(), false );
 448              } else {
 449                  update_site_option( 'recently_activated', array() );
 450              }
 451  
 452              break;
 453          case 'resume':
 454              if ( is_multisite() ) {
 455                  return;
 456              }
 457  
 458              if ( ! current_user_can( 'resume_plugin', $plugin ) ) {
 459                  wp_die( __( 'Sorry, you are not allowed to resume this plugin.' ) );
 460              }
 461  
 462              check_admin_referer( 'resume-plugin_' . $plugin );
 463  
 464              $result = resume_plugin( $plugin, self_admin_url( "plugins.php?error=resuming&plugin_status=$status&paged=$page&s=$s" ) );
 465  
 466              if ( is_wp_error( $result ) ) {
 467                  wp_die( $result );
 468              }
 469  
 470              wp_redirect( self_admin_url( "plugins.php?resume=true&plugin_status=$status&paged=$page&s=$s" ) );
 471              exit;
 472          case 'enable-auto-update':
 473          case 'disable-auto-update':
 474          case 'enable-auto-update-selected':
 475          case 'disable-auto-update-selected':
 476              if ( ! current_user_can( 'update_plugins' ) || ! wp_is_auto_update_enabled_for_type( 'plugin' ) ) {
 477                  wp_die( __( 'Sorry, you are not allowed to manage plugins automatic updates.' ) );
 478              }
 479  
 480              if ( is_multisite() && ! is_network_admin() ) {
 481                  wp_die( __( 'Please connect to your network admin to manage plugins automatic updates.' ) );
 482              }
 483  
 484              $redirect = self_admin_url( "plugins.php?plugin_status={$status}&paged={$page}&s={$s}" );
 485  
 486              if ( 'enable-auto-update' === $action || 'disable-auto-update' === $action ) {
 487                  if ( empty( $plugin ) ) {
 488                      wp_redirect( $redirect );
 489                      exit;
 490                  }
 491  
 492                  check_admin_referer( 'updates' );
 493              } else {
 494                  if ( empty( $_POST['checked'] ) ) {
 495                      wp_redirect( $redirect );
 496                      exit;
 497                  }
 498  
 499                  check_admin_referer( 'bulk-plugins' );
 500              }
 501  
 502              $auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
 503  
 504              if ( 'enable-auto-update' === $action ) {
 505                  $auto_updates[] = $plugin;
 506                  $auto_updates   = array_unique( $auto_updates );
 507                  $redirect       = add_query_arg( array( 'enabled-auto-update' => 'true' ), $redirect );
 508              } elseif ( 'disable-auto-update' === $action ) {
 509                  $auto_updates = array_diff( $auto_updates, array( $plugin ) );
 510                  $redirect     = add_query_arg( array( 'disabled-auto-update' => 'true' ), $redirect );
 511              } else {
 512                  $plugins = (array) wp_unslash( $_POST['checked'] );
 513  
 514                  if ( 'enable-auto-update-selected' === $action ) {
 515                      $new_auto_updates = array_merge( $auto_updates, $plugins );
 516                      $new_auto_updates = array_unique( $new_auto_updates );
 517                      $query_args       = array( 'enabled-auto-update-multi' => 'true' );
 518                  } else {
 519                      $new_auto_updates = array_diff( $auto_updates, $plugins );
 520                      $query_args       = array( 'disabled-auto-update-multi' => 'true' );
 521                  }
 522  
 523                  // Return early if all selected plugins already have auto-updates enabled or disabled.
 524                  // Must use non-strict comparison, so that array order is not treated as significant.
 525                  if ( $new_auto_updates == $auto_updates ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
 526                      wp_redirect( $redirect );
 527                      exit;
 528                  }
 529  
 530                  $auto_updates = $new_auto_updates;
 531                  $redirect     = add_query_arg( $query_args, $redirect );
 532              }
 533  
 534              /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
 535              $all_items = apply_filters( 'all_plugins', get_plugins() );
 536  
 537              // Remove plugins that don't exist or have been deleted since the option was last updated.
 538              $auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
 539  
 540              update_site_option( 'auto_update_plugins', $auto_updates );
 541  
 542              wp_redirect( $redirect );
 543              exit;
 544          default:
 545              if ( isset( $_POST['checked'] ) ) {
 546                  check_admin_referer( 'bulk-plugins' );
 547  
 548                  $screen   = get_current_screen()->id;
 549                  $sendback = wp_get_referer();
 550                  $plugins  = isset( $_POST['checked'] ) ? (array) wp_unslash( $_POST['checked'] ) : array();
 551  
 552                  /** This action is documented in wp-admin/edit.php */
 553                  $sendback = apply_filters( "handle_bulk_actions-{$screen}", $sendback, $action, $plugins ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
 554                  wp_safe_redirect( $sendback );
 555                  exit;
 556              }
 557              break;
 558      }
 559  }
 560  
 561  $wp_list_table->prepare_items();
 562  
 563  wp_enqueue_script( 'plugin-install' );
 564  add_thickbox();
 565  
 566  add_screen_option( 'per_page', array( 'default' => 999 ) );
 567  
 568  get_current_screen()->add_help_tab(
 569      array(
 570          'id'      => 'overview',
 571          'title'   => __( 'Overview' ),
 572          'content' =>
 573                  '<p>' . __( 'Plugins extend and expand the functionality of WordPress. Once a plugin is installed, you may activate it or deactivate it here.' ) . '</p>' .
 574                  '<p>' . __( 'The search for installed plugins will search for terms in their name, description, or author.' ) . ' <span id="live-search-desc" class="hide-if-no-js">' . __( 'The search results will be updated as you type.' ) . '</span></p>' .
 575                  '<p>' . sprintf(
 576                      /* translators: %s: WordPress Plugin Directory URL. */
 577                      __( 'If you would like to see more plugins to choose from, click on the &#8220;Add Plugin&#8221; button and you will be able to browse or search for additional plugins from the <a href="%s">WordPress Plugin Directory</a>. Plugins in the WordPress Plugin Directory are designed and developed by third parties, and are compatible with the license WordPress uses. Oh, and they are free!' ),
 578                      __( 'https://wordpress.org/plugins/' )
 579                  ) . '</p>',
 580      )
 581  );
 582  get_current_screen()->add_help_tab(
 583      array(
 584          'id'      => 'compatibility-problems',
 585          'title'   => __( 'Troubleshooting' ),
 586          'content' =>
 587                  '<p>' . __( 'Most of the time, plugins play nicely with the core of WordPress and with other plugins. Sometimes, though, a plugin&#8217;s code will get in the way of another plugin, causing compatibility issues. If your site starts doing strange things, this may be the problem. Try deactivating all your plugins and re-activating them in various combinations until you isolate which one(s) caused the issue.' ) . '</p>' .
 588                  '<p>' . sprintf(
 589                      /* translators: %s: WP_PLUGIN_DIR constant value. */
 590                      __( 'If something goes wrong with a plugin and you cannot use WordPress, delete or rename that file in the %s directory and it will be automatically deactivated.' ),
 591                      '<code>' . WP_PLUGIN_DIR . '</code>'
 592                  ) . '</p>',
 593      )
 594  );
 595  
 596  $help_sidebar_autoupdates = '';
 597  
 598  if ( current_user_can( 'update_plugins' ) && wp_is_auto_update_enabled_for_type( 'plugin' ) ) {
 599      get_current_screen()->add_help_tab(
 600          array(
 601              'id'      => 'plugins-themes-auto-updates',
 602              'title'   => __( 'Auto-updates' ),
 603              'content' =>
 604                      '<p>' . __( 'Auto-updates can be enabled or disabled for each individual plugin. Plugins with auto-updates enabled will display the estimated date of the next auto-update. Auto-updates depends on the WP-Cron task scheduling system.' ) . '</p>' .
 605                      '<p>' . __( 'Auto-updates are only available for plugins recognized by WordPress.org, or that include a compatible update system.' ) . '</p>' .
 606                      '<p>' . __( 'Please note: Third-party themes and plugins, or custom code, may override WordPress scheduling.' ) . '</p>',
 607          )
 608      );
 609  
 610      $help_sidebar_autoupdates = '<p>' . __( '<a href="https://wordpress.org/documentation/article/plugins-themes-auto-updates/">Documentation on Auto-updates</a>' ) . '</p>';
 611  }
 612  
 613  if ( current_user_can( 'install_plugins' ) ) {
 614      get_current_screen()->add_help_tab(
 615          array(
 616              'id'      => 'plugins-dependencies',
 617              'title'   => __( 'Dependencies' ),
 618              'content' =>
 619                  '<p>' . __( 'Plugin Dependencies aims to make the process of installing and activating add-ons (dependents) and the plugins they rely on (dependencies) consistent and easy.' ) . '</p>' .
 620                  '<p>' . __( 'If a required plugin is deleted, a notice will be displayed on the Plugin administration screen informing the user that there is some missing dependencies to install and/or activate. Additionally, each plugin whose dependencies are not met will have an error notice on their plugin row.' ) . '</p>' .
 621                  '<p>' . __( 'If a dependent plugin is missing some dependencies, its activation button will be disabled until the required dependencies are activated.' ) . '</p>',
 622          )
 623      );
 624  }
 625  
 626  get_current_screen()->set_help_sidebar(
 627      '<p><strong>' . __( 'For more information:' ) . '</strong></p>' .
 628      '<p>' . __( '<a href="https://wordpress.org/documentation/article/manage-plugins/">Documentation on Managing Plugins</a>' ) . '</p>' .
 629      $help_sidebar_autoupdates .
 630      '<p>' . __( '<a href="https://wordpress.org/support/forums/">Support forums</a>' ) . '</p>'
 631  );
 632  
 633  get_current_screen()->set_screen_reader_content(
 634      array(
 635          'heading_views'      => __( 'Filter plugins list' ),
 636          'heading_pagination' => __( 'Plugins list navigation' ),
 637          'heading_list'       => __( 'Plugins list' ),
 638      )
 639  );
 640  
 641  // Used in the HTML title tag.
 642  $title       = __( 'Plugins' );
 643  $parent_file = 'plugins.php';
 644  
 645  require_once  ABSPATH . 'wp-admin/admin-header.php';
 646  
 647  $invalid = validate_active_plugins();
 648  if ( ! empty( $invalid ) ) {
 649      foreach ( $invalid as $plugin_file => $error ) {
 650          $deactivated_message = sprintf(
 651              /* translators: 1: Plugin file, 2: Error message. */
 652              __( 'The plugin %1$s has been deactivated due to an error: %2$s' ),
 653              '<code>' . esc_html( $plugin_file ) . '</code>',
 654              esc_html( $error->get_error_message() )
 655          );
 656          wp_admin_notice(
 657              $deactivated_message,
 658              array(
 659                  'id'                 => 'message',
 660                  'additional_classes' => array( 'error' ),
 661              )
 662          );
 663      }
 664  }
 665  
 666  // Used by wp_admin_notice() updated notices.
 667  $updated_notice_args = array(
 668      'id'                 => 'message',
 669      'additional_classes' => array( 'updated' ),
 670      'dismissible'        => true,
 671  );
 672  if ( isset( $_GET['error'] ) ) {
 673  
 674      if ( isset( $_GET['main'] ) ) {
 675          $errmsg = __( 'You cannot delete a plugin while it is active on the main site.' );
 676      } elseif ( isset( $_GET['charsout'] ) ) {
 677          $errmsg = sprintf(
 678              /* translators: %d: Number of characters. */
 679              _n(
 680                  'The plugin generated %d character of <strong>unexpected output</strong> during activation.',
 681                  'The plugin generated %d characters of <strong>unexpected output</strong> during activation.',
 682                  $_GET['charsout']
 683              ),
 684              $_GET['charsout']
 685          );
 686          $errmsg .= ' ' . __( 'If you notice &#8220;headers already sent&#8221; messages, problems with syndication feeds or other issues, try deactivating or removing this plugin.' );
 687      } elseif ( 'resuming' === $_GET['error'] ) {
 688          $errmsg = __( 'Plugin could not be resumed because it triggered a <strong>fatal error</strong>.' );
 689      } else {
 690          $errmsg = __( 'Plugin could not be activated because it triggered a <strong>fatal error</strong>.' );
 691      }
 692  
 693      if ( ! isset( $_GET['main'] ) && ! isset( $_GET['charsout'] )
 694          && isset( $_GET['_error_nonce'] ) && wp_verify_nonce( $_GET['_error_nonce'], 'plugin-activation-error_' . $plugin )
 695      ) {
 696          $iframe_url = add_query_arg(
 697              array(
 698                  'action'   => 'error_scrape',
 699                  'plugin'   => urlencode( $plugin ),
 700                  '_wpnonce' => urlencode( $_GET['_error_nonce'] ),
 701              ),
 702              admin_url( 'plugins.php' )
 703          );
 704  
 705          $errmsg .= '<iframe style="border:0" width="100%" height="70px" src="' . esc_url( $iframe_url ) . '"></iframe>';
 706      }
 707  
 708      wp_admin_notice(
 709          $errmsg,
 710          array(
 711              'id'                 => 'message',
 712              'additional_classes' => array( 'error' ),
 713          )
 714      );
 715  
 716  } elseif ( isset( $_GET['deleted'] ) ) {
 717      $delete_result = get_option( 'plugins_delete_result_' . $user_ID );
 718      // Delete it once we're done.
 719      delete_option( 'plugins_delete_result_' . $user_ID );
 720  
 721      if ( is_wp_error( $delete_result ) ) {
 722          $plugin_not_deleted_message = sprintf(
 723              /* translators: %s: Error message. */
 724              __( 'Plugin could not be deleted due to an error: %s' ),
 725              esc_html( $delete_result->get_error_message() )
 726          );
 727          wp_admin_notice(
 728              $plugin_not_deleted_message,
 729              array(
 730                  'id'                 => 'message',
 731                  'additional_classes' => array( 'error' ),
 732                  'dismissible'        => true,
 733              )
 734          );
 735      } else {
 736          if ( 1 === (int) $_GET['deleted'] ) {
 737              $plugins_deleted_message = __( 'The selected plugin has been deleted.' );
 738          } else {
 739              $plugins_deleted_message = __( 'The selected plugins have been deleted.' );
 740          }
 741          wp_admin_notice( $plugins_deleted_message, $updated_notice_args );
 742      }
 743  } elseif ( isset( $_GET['activate'] ) ) {
 744      wp_admin_notice( __( 'Plugin activated.' ), $updated_notice_args );
 745  } elseif ( isset( $_GET['activate-multi'] ) ) {
 746      wp_admin_notice( __( 'Selected plugins activated.' ), $updated_notice_args );
 747  } elseif ( isset( $_GET['deactivate'] ) ) {
 748      wp_admin_notice( __( 'Plugin deactivated.' ), $updated_notice_args );
 749  } elseif ( isset( $_GET['deactivate-multi'] ) ) {
 750      wp_admin_notice( __( 'Selected plugins deactivated.' ), $updated_notice_args );
 751  } elseif ( isset( $_GET['resume'] ) ) {
 752      wp_admin_notice( __( 'Plugin resumed.' ), $updated_notice_args );
 753  } elseif ( isset( $_GET['enabled-auto-update'] ) ) {
 754      wp_admin_notice( __( 'Plugin will be auto-updated.' ), $updated_notice_args );
 755  } elseif ( isset( $_GET['disabled-auto-update'] ) ) {
 756      wp_admin_notice( __( 'Plugin will no longer be auto-updated.' ), $updated_notice_args );
 757  } elseif ( isset( $_GET['enabled-auto-update-multi'] ) ) {
 758      wp_admin_notice( __( 'Selected plugins will be auto-updated.' ), $updated_notice_args );
 759  } elseif ( isset( $_GET['disabled-auto-update-multi'] ) ) {
 760      wp_admin_notice( __( 'Selected plugins will no longer be auto-updated.' ), $updated_notice_args );
 761  }
 762  ?>
 763  
 764  <?php WP_Plugin_Dependencies::display_admin_notice_for_unmet_dependencies(); ?>
 765  <?php WP_Plugin_Dependencies::display_admin_notice_for_circular_dependencies(); ?>
 766  <div class="wrap">
 767  <h1 class="wp-heading-inline">
 768  <?php
 769  echo esc_html( $title );
 770  ?>
 771  </h1>
 772  
 773  <?php
 774  if ( ( ! is_multisite() || is_network_admin() ) && current_user_can( 'install_plugins' ) ) {
 775      ?>
 776      <a href="<?php echo esc_url( self_admin_url( 'plugin-install.php' ) ); ?>" class="page-title-action"><?php echo esc_html__( 'Add Plugin' ); ?></a>
 777      <?php
 778  }
 779  
 780  if ( strlen( $s ) ) {
 781      echo '<span class="subtitle">';
 782      printf(
 783          /* translators: %s: Search query. */
 784          __( 'Search results for: %s' ),
 785          '<strong>' . esc_html( urldecode( $s ) ) . '</strong>'
 786      );
 787      echo '</span>';
 788  }
 789  ?>
 790  
 791  <hr class="wp-header-end">
 792  
 793  <?php
 794  /**
 795   * Fires before the plugins list table is rendered.
 796   *
 797   * This hook also fires before the plugins list table is rendered in the Network Admin.
 798   *
 799   * Please note: The 'active' portion of the hook name does not refer to whether the current
 800   * view is for active plugins, but rather all plugins actively-installed.
 801   *
 802   * @since 3.0.0
 803   *
 804   * @param array[] $plugins_all An array of arrays containing information on all installed plugins.
 805   */
 806  do_action( 'pre_current_active_plugins', $plugins['all'] );
 807  ?>
 808  
 809  <?php $wp_list_table->views(); ?>
 810  
 811  <form class="search-form search-plugins" method="get">
 812  <?php $wp_list_table->search_box( __( 'Search installed plugins' ), 'plugin' ); ?>
 813  </form>
 814  
 815  <form method="post" id="bulk-action-form">
 816  
 817  <input type="hidden" name="plugin_status" value="<?php echo esc_attr( $status ); ?>" />
 818  <input type="hidden" name="paged" value="<?php echo esc_attr( $page ); ?>" />
 819  
 820  <?php $wp_list_table->display(); ?>
 821  </form>
 822  
 823      <span class="spinner"></span>
 824  </div>
 825  
 826  <?php
 827  wp_print_request_filesystem_credentials_modal();
 828  wp_print_admin_notice_templates();
 829  wp_print_update_row_templates();
 830  
 831  require_once  ABSPATH . 'wp-admin/admin-footer.php';


Generated : Wed Nov 11 08:20:02 2026 Cross-referenced by PHPXref