wp/wp-admin/plugins.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Administration
     6  * @subpackage Administration
     7  */
     7  */
     8 
     8 
     9 /** WordPress Administration Bootstrap */
     9 /** WordPress Administration Bootstrap */
    10 require_once( dirname( __FILE__ ) . '/admin.php' );
    10 require_once __DIR__ . '/admin.php';
    11 
    11 
    12 if ( ! current_user_can( 'activate_plugins' ) ) {
    12 if ( ! current_user_can( 'activate_plugins' ) ) {
    13 	wp_die( __( 'Sorry, you are not allowed to manage plugins for this site.' ) );
    13 	wp_die( __( 'Sorry, you are not allowed to manage plugins for this site.' ) );
    14 }
    14 }
    15 
    15 
    20 
    20 
    21 $plugin = isset( $_REQUEST['plugin'] ) ? wp_unslash( $_REQUEST['plugin'] ) : '';
    21 $plugin = isset( $_REQUEST['plugin'] ) ? wp_unslash( $_REQUEST['plugin'] ) : '';
    22 $s      = isset( $_REQUEST['s'] ) ? urlencode( wp_unslash( $_REQUEST['s'] ) ) : '';
    22 $s      = isset( $_REQUEST['s'] ) ? urlencode( wp_unslash( $_REQUEST['s'] ) ) : '';
    23 
    23 
    24 // Clean up request URI from temporary args for screen options/paging uri's to work as expected.
    24 // Clean up request URI from temporary args for screen options/paging uri's to work as expected.
    25 $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'error', 'deleted', 'activate', 'activate-multi', 'deactivate', 'deactivate-multi', '_error_nonce' ), $_SERVER['REQUEST_URI'] );
    25 $query_args_to_remove = array(
       
    26 	'error',
       
    27 	'deleted',
       
    28 	'activate',
       
    29 	'activate-multi',
       
    30 	'deactivate',
       
    31 	'deactivate-multi',
       
    32 	'enabled-auto-update',
       
    33 	'disabled-auto-update',
       
    34 	'enabled-auto-update-multi',
       
    35 	'disabled-auto-update-multi',
       
    36 	'_error_nonce',
       
    37 );
       
    38 
       
    39 $_SERVER['REQUEST_URI'] = remove_query_arg( $query_args_to_remove, $_SERVER['REQUEST_URI'] );
    26 
    40 
    27 wp_enqueue_script( 'updates' );
    41 wp_enqueue_script( 'updates' );
    28 
    42 
    29 if ( $action ) {
    43 if ( $action ) {
    30 
    44 
    41 
    55 
    42 			check_admin_referer( 'activate-plugin_' . $plugin );
    56 			check_admin_referer( 'activate-plugin_' . $plugin );
    43 
    57 
    44 			$result = activate_plugin( $plugin, self_admin_url( 'plugins.php?error=true&plugin=' . urlencode( $plugin ) ), is_network_admin() );
    58 			$result = activate_plugin( $plugin, self_admin_url( 'plugins.php?error=true&plugin=' . urlencode( $plugin ) ), is_network_admin() );
    45 			if ( is_wp_error( $result ) ) {
    59 			if ( is_wp_error( $result ) ) {
    46 				if ( 'unexpected_output' == $result->get_error_code() ) {
    60 				if ( 'unexpected_output' === $result->get_error_code() ) {
    47 					$redirect = self_admin_url( 'plugins.php?error=true&charsout=' . strlen( $result->get_error_data() ) . '&plugin=' . urlencode( $plugin ) . "&plugin_status=$status&paged=$page&s=$s" );
    61 					$redirect = self_admin_url( 'plugins.php?error=true&charsout=' . strlen( $result->get_error_data() ) . '&plugin=' . urlencode( $plugin ) . "&plugin_status=$status&paged=$page&s=$s" );
    48 					wp_redirect( add_query_arg( '_error_nonce', wp_create_nonce( 'plugin-activation-error_' . $plugin ), $redirect ) );
    62 					wp_redirect( add_query_arg( '_error_nonce', wp_create_nonce( 'plugin-activation-error_' . $plugin ), $redirect ) );
    49 					exit;
    63 					exit;
    50 				} else {
    64 				} else {
    51 					wp_die( $result );
    65 					wp_die( $result );
    60 				$recent = (array) get_site_option( 'recently_activated' );
    74 				$recent = (array) get_site_option( 'recently_activated' );
    61 				unset( $recent[ $plugin ] );
    75 				unset( $recent[ $plugin ] );
    62 				update_site_option( 'recently_activated', $recent );
    76 				update_site_option( 'recently_activated', $recent );
    63 			}
    77 			}
    64 
    78 
    65 			if ( isset( $_GET['from'] ) && 'import' == $_GET['from'] ) {
    79 			if ( isset( $_GET['from'] ) && 'import' === $_GET['from'] ) {
    66 				wp_redirect( self_admin_url( 'import.php?import=' . str_replace( '-importer', '', dirname( $plugin ) ) ) ); // overrides the ?error=true one above and redirects to the Imports page, stripping the -importer suffix
    80 				// Overrides the ?error=true one above and redirects to the Imports page, stripping the -importer suffix.
    67 			} elseif ( isset( $_GET['from'] ) && 'press-this' == $_GET['from'] ) {
    81 				wp_redirect( self_admin_url( 'import.php?import=' . str_replace( '-importer', '', dirname( $plugin ) ) ) );
       
    82 			} elseif ( isset( $_GET['from'] ) && 'press-this' === $_GET['from'] ) {
    68 				wp_redirect( self_admin_url( 'press-this.php' ) );
    83 				wp_redirect( self_admin_url( 'press-this.php' ) );
    69 			} else {
    84 			} else {
    70 				wp_redirect( self_admin_url( "plugins.php?activate=true&plugin_status=$status&paged=$page&s=$s" ) ); // overrides the ?error=true one above
    85 				// Overrides the ?error=true one above.
       
    86 				wp_redirect( self_admin_url( "plugins.php?activate=true&plugin_status=$status&paged=$page&s=$s" ) );
    71 			}
    87 			}
    72 			exit;
    88 			exit;
    73 
    89 
    74 		case 'activate-selected':
    90 		case 'activate-selected':
    75 			if ( ! current_user_can( 'activate_plugins' ) ) {
    91 			if ( ! current_user_can( 'activate_plugins' ) ) {
   139 
   155 
   140 			$title       = __( 'Update Plugins' );
   156 			$title       = __( 'Update Plugins' );
   141 			$parent_file = 'plugins.php';
   157 			$parent_file = 'plugins.php';
   142 
   158 
   143 			wp_enqueue_script( 'updates' );
   159 			wp_enqueue_script( 'updates' );
   144 			require_once( ABSPATH . 'wp-admin/admin-header.php' );
   160 			require_once ABSPATH . 'wp-admin/admin-header.php';
   145 
   161 
   146 			echo '<div class="wrap">';
   162 			echo '<div class="wrap">';
   147 			echo '<h1>' . esc_html( $title ) . '</h1>';
   163 			echo '<h1>' . esc_html( $title ) . '</h1>';
   148 
   164 
   149 			$url = self_admin_url( 'update.php?action=update-selected&amp;plugins=' . urlencode( join( ',', $plugins ) ) );
   165 			$url = self_admin_url( 'update.php?action=update-selected&amp;plugins=' . urlencode( join( ',', $plugins ) ) );
   150 			$url = wp_nonce_url( $url, 'bulk-update-plugins' );
   166 			$url = wp_nonce_url( $url, 'bulk-update-plugins' );
   151 
   167 
   152 			echo "<iframe src='$url' style='width: 100%; height:100%; min-height:850px;'></iframe>";
   168 			echo "<iframe src='$url' style='width: 100%; height:100%; min-height:850px;'></iframe>";
   153 			echo '</div>';
   169 			echo '</div>';
   154 			require_once( ABSPATH . 'wp-admin/admin-footer.php' );
   170 			require_once ABSPATH . 'wp-admin/admin-footer.php';
   155 			exit;
   171 			exit;
   156 
   172 
   157 		case 'error_scrape':
   173 		case 'error_scrape':
   158 			if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
   174 			if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
   159 				wp_die( __( 'Sorry, you are not allowed to activate this plugin.' ) );
   175 				wp_die( __( 'Sorry, you are not allowed to activate this plugin.' ) );
   168 
   184 
   169 			if ( ! WP_DEBUG ) {
   185 			if ( ! WP_DEBUG ) {
   170 				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 );
   186 				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 );
   171 			}
   187 			}
   172 
   188 
   173 			@ini_set( 'display_errors', true ); //Ensure that Fatal errors are displayed.
   189 			ini_set( 'display_errors', true ); // Ensure that fatal errors are displayed.
   174 			// Go back to "sandbox" scope so we get the same errors as before
   190 			// Go back to "sandbox" scope so we get the same errors as before.
   175 			plugin_sandbox_scrape( $plugin );
   191 			plugin_sandbox_scrape( $plugin );
   176 			/** This action is documented in wp-admin/includes/plugin.php */
   192 			/** This action is documented in wp-admin/includes/plugin.php */
   177 			do_action( "activate_{$plugin}" );
   193 			do_action( "activate_{$plugin}" );
   178 			exit;
   194 			exit;
   179 
   195 
   252 				wp_die( __( 'Sorry, you are not allowed to delete plugins for this site.' ) );
   268 				wp_die( __( 'Sorry, you are not allowed to delete plugins for this site.' ) );
   253 			}
   269 			}
   254 
   270 
   255 			check_admin_referer( 'bulk-plugins' );
   271 			check_admin_referer( 'bulk-plugins' );
   256 
   272 
   257 			//$_POST = from the plugin form; $_GET = from the FTP details screen.
   273 			// $_POST = from the plugin form; $_GET = from the FTP details screen.
   258 			$plugins = isset( $_REQUEST['checked'] ) ? (array) wp_unslash( $_REQUEST['checked'] ) : array();
   274 			$plugins = isset( $_REQUEST['checked'] ) ? (array) wp_unslash( $_REQUEST['checked'] ) : array();
   259 			if ( empty( $plugins ) ) {
   275 			if ( empty( $plugins ) ) {
   260 				wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) );
   276 				wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) );
   261 				exit;
   277 				exit;
   262 			}
   278 			}
   263 
   279 
   264 			$plugins = array_filter( $plugins, 'is_plugin_inactive' ); // Do not allow to delete Activated plugins.
   280 			$plugins = array_filter( $plugins, 'is_plugin_inactive' ); // Do not allow to delete activated plugins.
   265 			if ( empty( $plugins ) ) {
   281 			if ( empty( $plugins ) ) {
   266 				wp_redirect( self_admin_url( "plugins.php?error=true&main=true&plugin_status=$status&paged=$page&s=$s" ) );
   282 				wp_redirect( self_admin_url( "plugins.php?error=true&main=true&plugin_status=$status&paged=$page&s=$s" ) );
   267 				exit;
   283 				exit;
   268 			}
   284 			}
   269 
   285 
   270 			// Bail on all if any paths are invalid.
   286 			// Bail on all if any paths are invalid.
   271 			// validate_file() returns truthy for invalid files
   287 			// validate_file() returns truthy for invalid files.
   272 			$invalid_plugin_files = array_filter( $plugins, 'validate_file' );
   288 			$invalid_plugin_files = array_filter( $plugins, 'validate_file' );
   273 			if ( $invalid_plugin_files ) {
   289 			if ( $invalid_plugin_files ) {
   274 				wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) );
   290 				wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) );
   275 				exit;
   291 				exit;
   276 			}
   292 			}
   277 
   293 
   278 			include( ABSPATH . 'wp-admin/update.php' );
   294 			require ABSPATH . 'wp-admin/update.php';
   279 
   295 
   280 			$parent_file = 'plugins.php';
   296 			$parent_file = 'plugins.php';
   281 
   297 
   282 			if ( ! isset( $_REQUEST['verify-delete'] ) ) {
   298 			if ( ! isset( $_REQUEST['verify-delete'] ) ) {
   283 				wp_enqueue_script( 'jquery' );
   299 				wp_enqueue_script( 'jquery' );
   284 				require_once( ABSPATH . 'wp-admin/admin-header.php' );
   300 				require_once ABSPATH . 'wp-admin/admin-header.php';
       
   301 
   285 				?>
   302 				?>
   286 			<div class="wrap">
   303 				<div class="wrap">
   287 				<?php
   304 				<?php
   288 					$plugin_info              = array();
   305 
   289 					$have_non_network_plugins = false;
   306 				$plugin_info              = array();
       
   307 				$have_non_network_plugins = false;
       
   308 
   290 				foreach ( (array) $plugins as $plugin ) {
   309 				foreach ( (array) $plugins as $plugin ) {
   291 					$plugin_slug = dirname( $plugin );
   310 					$plugin_slug = dirname( $plugin );
   292 
   311 
   293 					if ( '.' == $plugin_slug ) {
   312 					if ( '.' === $plugin_slug ) {
   294 						if ( $data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ) ) {
   313 						$data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
       
   314 						if ( $data ) {
   295 							$plugin_info[ $plugin ]                     = $data;
   315 							$plugin_info[ $plugin ]                     = $data;
   296 							$plugin_info[ $plugin ]['is_uninstallable'] = is_uninstallable_plugin( $plugin );
   316 							$plugin_info[ $plugin ]['is_uninstallable'] = is_uninstallable_plugin( $plugin );
   297 							if ( ! $plugin_info[ $plugin ]['Network'] ) {
   317 							if ( ! $plugin_info[ $plugin ]['Network'] ) {
   298 								$have_non_network_plugins = true;
   318 								$have_non_network_plugins = true;
   299 							}
   319 							}
   300 						}
   320 						}
   301 					} else {
   321 					} else {
   302 						// Get plugins list from that folder.
   322 						// Get plugins list from that folder.
   303 						if ( $folder_plugins = get_plugins( '/' . $plugin_slug ) ) {
   323 						$folder_plugins = get_plugins( '/' . $plugin_slug );
       
   324 						if ( $folder_plugins ) {
   304 							foreach ( $folder_plugins as $plugin_file => $data ) {
   325 							foreach ( $folder_plugins as $plugin_file => $data ) {
   305 								$plugin_info[ $plugin_file ]                     = _get_plugin_data_markup_translate( $plugin_file, $data );
   326 								$plugin_info[ $plugin_file ]                     = _get_plugin_data_markup_translate( $plugin_file, $data );
   306 								$plugin_info[ $plugin_file ]['is_uninstallable'] = is_uninstallable_plugin( $plugin );
   327 								$plugin_info[ $plugin_file ]['is_uninstallable'] = is_uninstallable_plugin( $plugin );
   307 								if ( ! $plugin_info[ $plugin_file ]['Network'] ) {
   328 								if ( ! $plugin_info[ $plugin_file ]['Network'] ) {
   308 									$have_non_network_plugins = true;
   329 									$have_non_network_plugins = true;
   309 								}
   330 								}
   310 							}
   331 							}
   311 						}
   332 						}
   312 					}
   333 					}
   313 				}
   334 				}
   314 					$plugins_to_delete = count( $plugin_info );
   335 
       
   336 				$plugins_to_delete = count( $plugin_info );
       
   337 
   315 				?>
   338 				?>
   316 				<?php if ( 1 == $plugins_to_delete ) : ?>
   339 				<?php if ( 1 === $plugins_to_delete ) : ?>
   317 					<h1><?php _e( 'Delete Plugin' ); ?></h1>
   340 					<h1><?php _e( 'Delete Plugin' ); ?></h1>
   318 					<?php if ( $have_non_network_plugins && is_network_admin() ) : ?>
   341 					<?php if ( $have_non_network_plugins && is_network_admin() ) : ?>
   319 						<div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php _e( 'This plugin may be active on other sites in the network.' ); ?></p></div>
   342 						<div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php _e( 'This plugin may be active on other sites in the network.' ); ?></p></div>
   320 					<?php endif; ?>
   343 					<?php endif; ?>
   321 					<p><?php _e( 'You are about to remove the following plugin:' ); ?></p>
   344 					<p><?php _e( 'You are about to remove the following plugin:' ); ?></p>
   326 					<?php endif; ?>
   349 					<?php endif; ?>
   327 					<p><?php _e( 'You are about to remove the following plugins:' ); ?></p>
   350 					<p><?php _e( 'You are about to remove the following plugins:' ); ?></p>
   328 				<?php endif; ?>
   351 				<?php endif; ?>
   329 					<ul class="ul-disc">
   352 					<ul class="ul-disc">
   330 						<?php
   353 						<?php
       
   354 
   331 						$data_to_delete = false;
   355 						$data_to_delete = false;
       
   356 
   332 						foreach ( $plugin_info as $plugin ) {
   357 						foreach ( $plugin_info as $plugin ) {
   333 							if ( $plugin['is_uninstallable'] ) {
   358 							if ( $plugin['is_uninstallable'] ) {
   334 								/* translators: 1: plugin name, 2: plugin author */
   359 								/* translators: 1: Plugin name, 2: Plugin author. */
   335 								echo '<li>', sprintf( __( '%1$s by %2$s (will also <strong>delete its data</strong>)' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] . '</em>' ), '</li>';
   360 								echo '<li>', sprintf( __( '%1$s by %2$s (will also <strong>delete its data</strong>)' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] . '</em>' ), '</li>';
   336 								$data_to_delete = true;
   361 								$data_to_delete = true;
   337 							} else {
   362 							} else {
   338 								/* translators: 1: plugin name, 2: plugin author */
   363 								/* translators: 1: Plugin name, 2: Plugin author. */
   339 								echo '<li>', sprintf( _x( '%1$s by %2$s', 'plugin' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] ) . '</em>', '</li>';
   364 								echo '<li>', sprintf( _x( '%1$s by %2$s', 'plugin' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] ) . '</em>', '</li>';
   340 							}
   365 							}
   341 						}
   366 						}
       
   367 
   342 						?>
   368 						?>
   343 					</ul>
   369 					</ul>
   344 				<p>
   370 				<p>
   345 				<?php
   371 				<?php
       
   372 
   346 				if ( $data_to_delete ) {
   373 				if ( $data_to_delete ) {
   347 					_e( 'Are you sure you wish to delete these files and data?' );
   374 					_e( 'Are you sure you want to delete these files and data?' );
   348 				} else {
   375 				} else {
   349 					_e( 'Are you sure you wish to delete these files?' );
   376 					_e( 'Are you sure you want to delete these files?' );
   350 				}
   377 				}
       
   378 
   351 				?>
   379 				?>
   352 				</p>
   380 				</p>
   353 				<form method="post" action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" style="display:inline;">
   381 				<form method="post" action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" style="display:inline;">
   354 					<input type="hidden" name="verify-delete" value="1" />
   382 					<input type="hidden" name="verify-delete" value="1" />
   355 					<input type="hidden" name="action" value="delete-selected" />
   383 					<input type="hidden" name="action" value="delete-selected" />
   356 					<?php
   384 					<?php
       
   385 
   357 					foreach ( (array) $plugins as $plugin ) {
   386 					foreach ( (array) $plugins as $plugin ) {
   358 						echo '<input type="hidden" name="checked[]" value="' . esc_attr( $plugin ) . '" />';
   387 						echo '<input type="hidden" name="checked[]" value="' . esc_attr( $plugin ) . '" />';
   359 					}
   388 					}
       
   389 
   360 					?>
   390 					?>
   361 					<?php wp_nonce_field( 'bulk-plugins' ); ?>
   391 					<?php wp_nonce_field( 'bulk-plugins' ); ?>
   362 					<?php submit_button( $data_to_delete ? __( 'Yes, delete these files and data' ) : __( 'Yes, delete these files' ), '', 'submit', false ); ?>
   392 					<?php submit_button( $data_to_delete ? __( 'Yes, delete these files and data' ) : __( 'Yes, delete these files' ), '', 'submit', false ); ?>
   363 				</form>
   393 				</form>
   364 				<?php
   394 				<?php
       
   395 
   365 				$referer = wp_get_referer();
   396 				$referer = wp_get_referer();
       
   397 
   366 				?>
   398 				?>
   367 				<form method="post" action="<?php echo $referer ? esc_url( $referer ) : ''; ?>" style="display:inline;">
   399 				<form method="post" action="<?php echo $referer ? esc_url( $referer ) : ''; ?>" style="display:inline;">
   368 					<?php submit_button( __( 'No, return me to the plugin list' ), '', 'submit', false ); ?>
   400 					<?php submit_button( __( 'No, return me to the plugin list' ), '', 'submit', false ); ?>
   369 				</form>
   401 				</form>
   370 			</div>
   402 				</div>
   371 				<?php
   403 				<?php
   372 				require_once( ABSPATH . 'wp-admin/admin-footer.php' );
   404 
       
   405 				require_once ABSPATH . 'wp-admin/admin-footer.php';
   373 				exit;
   406 				exit;
   374 			} else {
   407 			} else {
   375 				$plugins_to_delete = count( $plugins );
   408 				$plugins_to_delete = count( $plugins );
   376 			} // endif verify-delete
   409 			} // End if verify-delete.
   377 
   410 
   378 			$delete_result = delete_plugins( $plugins );
   411 			$delete_result = delete_plugins( $plugins );
   379 
   412 
   380 			set_transient( 'plugins_delete_result_' . $user_ID, $delete_result ); //Store the result in a cache rather than a URL param due to object type & length
   413 			// Store the result in a cache rather than a URL param due to object type & length.
       
   414 			set_transient( 'plugins_delete_result_' . $user_ID, $delete_result );
   381 			wp_redirect( self_admin_url( "plugins.php?deleted=$plugins_to_delete&plugin_status=$status&paged=$page&s=$s" ) );
   415 			wp_redirect( self_admin_url( "plugins.php?deleted=$plugins_to_delete&plugin_status=$status&paged=$page&s=$s" ) );
   382 			exit;
   416 			exit;
   383 
       
   384 		case 'clear-recent-list':
   417 		case 'clear-recent-list':
   385 			if ( ! is_network_admin() ) {
   418 			if ( ! is_network_admin() ) {
   386 				update_option( 'recently_activated', array() );
   419 				update_option( 'recently_activated', array() );
   387 			} else {
   420 			} else {
   388 				update_site_option( 'recently_activated', array() );
   421 				update_site_option( 'recently_activated', array() );
   389 			}
   422 			}
       
   423 
   390 			break;
   424 			break;
   391 
       
   392 		case 'resume':
   425 		case 'resume':
   393 			if ( is_multisite() ) {
   426 			if ( is_multisite() ) {
   394 				return;
   427 				return;
   395 			}
   428 			}
   396 
   429 
   406 				wp_die( $result );
   439 				wp_die( $result );
   407 			}
   440 			}
   408 
   441 
   409 			wp_redirect( self_admin_url( "plugins.php?resume=true&plugin_status=$status&paged=$page&s=$s" ) );
   442 			wp_redirect( self_admin_url( "plugins.php?resume=true&plugin_status=$status&paged=$page&s=$s" ) );
   410 			exit;
   443 			exit;
   411 
   444 		case 'enable-auto-update':
       
   445 		case 'disable-auto-update':
       
   446 		case 'enable-auto-update-selected':
       
   447 		case 'disable-auto-update-selected':
       
   448 			if ( ! current_user_can( 'update_plugins' ) || ! wp_is_auto_update_enabled_for_type( 'plugin' ) ) {
       
   449 				wp_die( __( 'Sorry, you are not allowed to manage plugins automatic updates.' ) );
       
   450 			}
       
   451 
       
   452 			if ( is_multisite() && ! is_network_admin() ) {
       
   453 				wp_die( __( 'Please connect to your network admin to manage plugins automatic updates.' ) );
       
   454 			}
       
   455 
       
   456 			$redirect = self_admin_url( "plugins.php?plugin_status={$status}&paged={$page}&s={$s}" );
       
   457 
       
   458 			if ( 'enable-auto-update' === $action || 'disable-auto-update' === $action ) {
       
   459 				if ( empty( $plugin ) ) {
       
   460 					wp_redirect( $redirect );
       
   461 					exit;
       
   462 				}
       
   463 
       
   464 				check_admin_referer( 'updates' );
       
   465 			} else {
       
   466 				if ( empty( $_POST['checked'] ) ) {
       
   467 					wp_redirect( $redirect );
       
   468 					exit;
       
   469 				}
       
   470 
       
   471 				check_admin_referer( 'bulk-plugins' );
       
   472 			}
       
   473 
       
   474 			$auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
       
   475 
       
   476 			if ( 'enable-auto-update' === $action ) {
       
   477 				$auto_updates[] = $plugin;
       
   478 				$auto_updates   = array_unique( $auto_updates );
       
   479 				$redirect       = add_query_arg( array( 'enabled-auto-update' => 'true' ), $redirect );
       
   480 			} elseif ( 'disable-auto-update' === $action ) {
       
   481 				$auto_updates = array_diff( $auto_updates, array( $plugin ) );
       
   482 				$redirect     = add_query_arg( array( 'disabled-auto-update' => 'true' ), $redirect );
       
   483 			} else {
       
   484 				$plugins = (array) wp_unslash( $_POST['checked'] );
       
   485 
       
   486 				if ( 'enable-auto-update-selected' === $action ) {
       
   487 					$new_auto_updates = array_merge( $auto_updates, $plugins );
       
   488 					$new_auto_updates = array_unique( $new_auto_updates );
       
   489 					$query_args       = array( 'enabled-auto-update-multi' => 'true' );
       
   490 				} else {
       
   491 					$new_auto_updates = array_diff( $auto_updates, $plugins );
       
   492 					$query_args       = array( 'disabled-auto-update-multi' => 'true' );
       
   493 				}
       
   494 
       
   495 				// Return early if all selected plugins already have auto-updates enabled or disabled.
       
   496 				// Must use non-strict comparison, so that array order is not treated as significant.
       
   497 				if ( $new_auto_updates == $auto_updates ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
       
   498 					wp_redirect( $redirect );
       
   499 					exit;
       
   500 				}
       
   501 
       
   502 				$auto_updates = $new_auto_updates;
       
   503 				$redirect     = add_query_arg( $query_args, $redirect );
       
   504 			}
       
   505 
       
   506 			/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
       
   507 			$all_items = apply_filters( 'all_plugins', get_plugins() );
       
   508 
       
   509 			// Remove plugins that don't exist or have been deleted since the option was last updated.
       
   510 			$auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
       
   511 
       
   512 			update_site_option( 'auto_update_plugins', $auto_updates );
       
   513 
       
   514 			wp_redirect( $redirect );
       
   515 			exit;
   412 		default:
   516 		default:
   413 			if ( isset( $_POST['checked'] ) ) {
   517 			if ( isset( $_POST['checked'] ) ) {
   414 				check_admin_referer( 'bulk-plugins' );
   518 				check_admin_referer( 'bulk-plugins' );
       
   519 
       
   520 				$screen   = get_current_screen()->id;
       
   521 				$sendback = wp_get_referer();
   415 				$plugins  = isset( $_POST['checked'] ) ? (array) wp_unslash( $_POST['checked'] ) : array();
   522 				$plugins  = isset( $_POST['checked'] ) ? (array) wp_unslash( $_POST['checked'] ) : array();
   416 				$sendback = wp_get_referer();
   523 
   417 
   524 				/** This action is documented in wp-admin/edit.php */
   418 				/** This action is documented in wp-admin/edit-comments.php */
   525 				$sendback = apply_filters( "handle_bulk_actions-{$screen}", $sendback, $action, $plugins ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
   419 				$sendback = apply_filters( 'handle_bulk_actions-' . get_current_screen()->id, $sendback, $action, $plugins );
       
   420 				wp_safe_redirect( $sendback );
   526 				wp_safe_redirect( $sendback );
   421 				exit;
   527 				exit;
   422 			}
   528 			}
   423 			break;
   529 			break;
   424 	}
   530 	}
   434 get_current_screen()->add_help_tab(
   540 get_current_screen()->add_help_tab(
   435 	array(
   541 	array(
   436 		'id'      => 'overview',
   542 		'id'      => 'overview',
   437 		'title'   => __( 'Overview' ),
   543 		'title'   => __( 'Overview' ),
   438 		'content' =>
   544 		'content' =>
   439 				 '<p>' . __( 'Plugins extend and expand the functionality of WordPress. Once a plugin is installed, you may activate it or deactivate it here.' ) . '</p>' .
   545 				'<p>' . __( 'Plugins extend and expand the functionality of WordPress. Once a plugin is installed, you may activate it or deactivate it here.' ) . '</p>' .
   440 				 '<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>' .
   546 				'<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>' .
   441 				'<p>' . sprintf(
   547 				'<p>' . sprintf(
   442 					/* translators: %s: WordPress Plugin Directory URL */
   548 					/* translators: %s: WordPress Plugin Directory URL. */
   443 					 __( 'If you would like to see more plugins to choose from, click on the &#8220;Add New&#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&#8217;re free!' ),
   549 					__( 'If you would like to see more plugins to choose from, click on the &#8220;Add New&#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&#8217;re free!' ),
   444 					__( 'https://wordpress.org/plugins/' )
   550 					__( 'https://wordpress.org/plugins/' )
   445 				) . '</p>',
   551 				) . '</p>',
   446 	)
   552 	)
   447 );
   553 );
   448 get_current_screen()->add_help_tab(
   554 get_current_screen()->add_help_tab(
   449 	array(
   555 	array(
   450 		'id'      => 'compatibility-problems',
   556 		'id'      => 'compatibility-problems',
   451 		'title'   => __( 'Troubleshooting' ),
   557 		'title'   => __( 'Troubleshooting' ),
   452 		'content' =>
   558 		'content' =>
   453 				 '<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>' .
   559 				'<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>' .
   454 				'<p>' . sprintf(
   560 				'<p>' . sprintf(
   455 					/* translators: WP_PLUGIN_DIR constant value */
   561 					/* translators: %s: WP_PLUGIN_DIR constant value. */
   456 					 __( 'If something goes wrong with a plugin and you can&#8217;t use WordPress, delete or rename that file in the %s directory and it will be automatically deactivated.' ),
   562 					__( 'If something goes wrong with a plugin and you can&#8217;t use WordPress, delete or rename that file in the %s directory and it will be automatically deactivated.' ),
   457 					'<code>' . WP_PLUGIN_DIR . '</code>'
   563 					'<code>' . WP_PLUGIN_DIR . '</code>'
   458 				) . '</p>',
   564 				) . '</p>',
   459 	)
   565 	)
   460 );
   566 );
   461 
   567 
       
   568 $help_sidebar_autoupdates = '';
       
   569 
       
   570 if ( current_user_can( 'update_plugins' ) && wp_is_auto_update_enabled_for_type( 'plugin' ) ) {
       
   571 	get_current_screen()->add_help_tab(
       
   572 		array(
       
   573 			'id'      => 'plugins-themes-auto-updates',
       
   574 			'title'   => __( 'Auto-updates' ),
       
   575 			'content' =>
       
   576 					'<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>' .
       
   577 					'<p>' . __( 'Auto-updates are only available for plugins recognized by WordPress.org, or that include a compatible update system.' ) . '</p>' .
       
   578 					'<p>' . __( 'Please note: Third-party themes and plugins, or custom code, may override WordPress scheduling.' ) . '</p>',
       
   579 		)
       
   580 	);
       
   581 
       
   582 	$help_sidebar_autoupdates = '<p>' . __( '<a href="https://wordpress.org/support/article/plugins-themes-auto-updates/">Learn more: Auto-updates documentation</a>' ) . '</p>';
       
   583 }
       
   584 
   462 get_current_screen()->set_help_sidebar(
   585 get_current_screen()->set_help_sidebar(
   463 	'<p><strong>' . __( 'For more information:' ) . '</strong></p>' .
   586 	'<p><strong>' . __( 'For more information:' ) . '</strong></p>' .
   464 	'<p>' . __( '<a href="https://codex.wordpress.org/Managing_Plugins#Plugin_Management">Documentation on Managing Plugins</a>' ) . '</p>' .
   587 	'<p>' . __( '<a href="https://wordpress.org/support/article/managing-plugins/">Documentation on Managing Plugins</a>' ) . '</p>' .
       
   588 	$help_sidebar_autoupdates .
   465 	'<p>' . __( '<a href="https://wordpress.org/support/">Support</a>' ) . '</p>'
   589 	'<p>' . __( '<a href="https://wordpress.org/support/">Support</a>' ) . '</p>'
   466 );
   590 );
   467 
   591 
   468 get_current_screen()->set_screen_reader_content(
   592 get_current_screen()->set_screen_reader_content(
   469 	array(
   593 	array(
   474 );
   598 );
   475 
   599 
   476 $title       = __( 'Plugins' );
   600 $title       = __( 'Plugins' );
   477 $parent_file = 'plugins.php';
   601 $parent_file = 'plugins.php';
   478 
   602 
   479 require_once( ABSPATH . 'wp-admin/admin-header.php' );
   603 require_once ABSPATH . 'wp-admin/admin-header.php';
   480 
   604 
   481 $invalid = validate_active_plugins();
   605 $invalid = validate_active_plugins();
   482 if ( ! empty( $invalid ) ) {
   606 if ( ! empty( $invalid ) ) {
   483 	foreach ( $invalid as $plugin_file => $error ) {
   607 	foreach ( $invalid as $plugin_file => $error ) {
   484 		echo '<div id="message" class="error"><p>';
   608 		echo '<div id="message" class="error"><p>';
   485 		printf(
   609 		printf(
   486 			/* translators: 1: plugin file, 2: error message */
   610 			/* translators: 1: Plugin file, 2: Error message. */
   487 			__( 'The plugin %1$s has been <strong>deactivated</strong> due to an error: %2$s' ),
   611 			__( 'The plugin %1$s has been deactivated due to an error: %2$s' ),
   488 			'<code>' . esc_html( $plugin_file ) . '</code>',
   612 			'<code>' . esc_html( $plugin_file ) . '</code>',
   489 			$error->get_error_message()
   613 			$error->get_error_message()
   490 		);
   614 		);
   491 		echo '</p></div>';
   615 		echo '</p></div>';
   492 	}
   616 	}
   493 }
   617 }
   494 ?>
   618 
   495 
       
   496 <?php
       
   497 if ( isset( $_GET['error'] ) ) :
   619 if ( isset( $_GET['error'] ) ) :
   498 
   620 
   499 	if ( isset( $_GET['main'] ) ) {
   621 	if ( isset( $_GET['main'] ) ) {
   500 		$errmsg = __( 'You cannot delete a plugin while it is active on the main site.' );
   622 		$errmsg = __( 'You cannot delete a plugin while it is active on the main site.' );
   501 	} elseif ( isset( $_GET['charsout'] ) ) {
   623 	} elseif ( isset( $_GET['charsout'] ) ) {
   502 		$errmsg  = sprintf(
   624 		$errmsg = sprintf(
       
   625 			/* translators: %d: Number of characters. */
   503 			_n(
   626 			_n(
   504 				'The plugin generated %d character of <strong>unexpected output</strong> during activation.',
   627 				'The plugin generated %d character of <strong>unexpected output</strong> during activation.',
   505 				'The plugin generated %d characters of <strong>unexpected output</strong> during activation.',
   628 				'The plugin generated %d characters of <strong>unexpected output</strong> during activation.',
   506 				$_GET['charsout']
   629 				$_GET['charsout']
   507 			),
   630 			),
   511 	} elseif ( 'resuming' === $_GET['error'] ) {
   634 	} elseif ( 'resuming' === $_GET['error'] ) {
   512 		$errmsg = __( 'Plugin could not be resumed because it triggered a <strong>fatal error</strong>.' );
   635 		$errmsg = __( 'Plugin could not be resumed because it triggered a <strong>fatal error</strong>.' );
   513 	} else {
   636 	} else {
   514 		$errmsg = __( 'Plugin could not be activated because it triggered a <strong>fatal error</strong>.' );
   637 		$errmsg = __( 'Plugin could not be activated because it triggered a <strong>fatal error</strong>.' );
   515 	}
   638 	}
       
   639 
   516 	?>
   640 	?>
   517 	<div id="message" class="error"><p><?php echo $errmsg; ?></p>
   641 	<div id="message" class="error"><p><?php echo $errmsg; ?></p>
   518 	<?php
   642 	<?php
       
   643 
   519 	if ( ! isset( $_GET['main'] ) && ! isset( $_GET['charsout'] ) && wp_verify_nonce( $_GET['_error_nonce'], 'plugin-activation-error_' . $plugin ) ) {
   644 	if ( ! isset( $_GET['main'] ) && ! isset( $_GET['charsout'] ) && wp_verify_nonce( $_GET['_error_nonce'], 'plugin-activation-error_' . $plugin ) ) {
   520 		$iframe_url = add_query_arg(
   645 		$iframe_url = add_query_arg(
   521 			array(
   646 			array(
   522 				'action'   => 'error_scrape',
   647 				'action'   => 'error_scrape',
   523 				'plugin'   => urlencode( $plugin ),
   648 				'plugin'   => urlencode( $plugin ),
   524 				'_wpnonce' => urlencode( $_GET['_error_nonce'] ),
   649 				'_wpnonce' => urlencode( $_GET['_error_nonce'] ),
   525 			),
   650 			),
   526 			admin_url( 'plugins.php' )
   651 			admin_url( 'plugins.php' )
   527 		);
   652 		);
       
   653 
   528 		?>
   654 		?>
   529 	<iframe style="border:0" width="100%" height="70px" src="<?php echo esc_url( $iframe_url ); ?>"></iframe>
   655 		<iframe style="border:0" width="100%" height="70px" src="<?php echo esc_url( $iframe_url ); ?>"></iframe>
   530 		<?php
   656 		<?php
   531 	}
   657 	}
       
   658 
   532 	?>
   659 	?>
   533 	</div>
   660 	</div>
   534 	<?php
   661 	<?php
   535 elseif ( isset( $_GET['deleted'] ) ) :
   662 elseif ( isset( $_GET['deleted'] ) ) :
   536 		$delete_result = get_transient( 'plugins_delete_result_' . $user_ID );
   663 	$delete_result = get_transient( 'plugins_delete_result_' . $user_ID );
   537 		// Delete it once we're done.
   664 	// Delete it once we're done.
   538 		delete_transient( 'plugins_delete_result_' . $user_ID );
   665 	delete_transient( 'plugins_delete_result_' . $user_ID );
   539 
   666 
   540 	if ( is_wp_error( $delete_result ) ) :
   667 	if ( is_wp_error( $delete_result ) ) :
   541 		?>
   668 		?>
   542 		<div id="message" class="error notice is-dismissible"><p><?php printf( __( 'Plugin could not be deleted due to an error: %s' ), $delete_result->get_error_message() ); ?></p></div>
   669 		<div id="message" class="error notice is-dismissible">
       
   670 			<p>
       
   671 				<?php
       
   672 				printf(
       
   673 					/* translators: %s: Error message. */
       
   674 					__( 'Plugin could not be deleted due to an error: %s' ),
       
   675 					$delete_result->get_error_message()
       
   676 				);
       
   677 				?>
       
   678 			</p>
       
   679 		</div>
   543 		<?php else : ?>
   680 		<?php else : ?>
   544 		<div id="message" class="updated notice is-dismissible">
   681 		<div id="message" class="updated notice is-dismissible">
   545 			<p>
   682 			<p>
   546 				<?php
   683 				<?php
   547 				if ( 1 == (int) $_GET['deleted'] ) {
   684 				if ( 1 === (int) $_GET['deleted'] ) {
   548 					_e( 'The selected plugin has been <strong>deleted</strong>.' );
   685 					_e( 'The selected plugin has been deleted.' );
   549 				} else {
   686 				} else {
   550 					_e( 'The selected plugins have been <strong>deleted</strong>.' );
   687 					_e( 'The selected plugins have been deleted.' );
   551 				}
   688 				}
   552 				?>
   689 				?>
   553 			</p>
   690 			</p>
   554 		</div>
   691 		</div>
   555 		<?php endif; ?>
   692 	<?php endif; ?>
   556 <?php elseif ( isset( $_GET['activate'] ) ) : ?>
   693 <?php elseif ( isset( $_GET['activate'] ) ) : ?>
   557 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin <strong>activated</strong>.' ); ?></p></div>
   694 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin activated.' ); ?></p></div>
   558 <?php elseif ( isset( $_GET['activate-multi'] ) ) : ?>
   695 <?php elseif ( isset( $_GET['activate-multi'] ) ) : ?>
   559 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins <strong>activated</strong>.' ); ?></p></div>
   696 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins activated.' ); ?></p></div>
   560 <?php elseif ( isset( $_GET['deactivate'] ) ) : ?>
   697 <?php elseif ( isset( $_GET['deactivate'] ) ) : ?>
   561 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin <strong>deactivated</strong>.' ); ?></p></div>
   698 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin deactivated.' ); ?></p></div>
   562 <?php elseif ( isset( $_GET['deactivate-multi'] ) ) : ?>
   699 <?php elseif ( isset( $_GET['deactivate-multi'] ) ) : ?>
   563 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins <strong>deactivated</strong>.' ); ?></p></div>
   700 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins deactivated.' ); ?></p></div>
   564 <?php elseif ( 'update-selected' == $action ) : ?>
   701 <?php elseif ( 'update-selected' === $action ) : ?>
   565 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'All selected plugins are up to date.' ); ?></p></div>
   702 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'All selected plugins are up to date.' ); ?></p></div>
   566 <?php elseif ( isset( $_GET['resume'] ) ) : ?>
   703 <?php elseif ( isset( $_GET['resume'] ) ) : ?>
   567 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin <strong>resumed</strong>.' ); ?></p></div>
   704 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin resumed.' ); ?></p></div>
       
   705 <?php elseif ( isset( $_GET['enabled-auto-update'] ) ) : ?>
       
   706 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin will be auto-updated.' ); ?></p></div>
       
   707 <?php elseif ( isset( $_GET['disabled-auto-update'] ) ) : ?>
       
   708 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin will no longer be auto-updated.' ); ?></p></div>
       
   709 <?php elseif ( isset( $_GET['enabled-auto-update-multi'] ) ) : ?>
       
   710 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins will be auto-updated.' ); ?></p></div>
       
   711 <?php elseif ( isset( $_GET['disabled-auto-update-multi'] ) ) : ?>
       
   712 	<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins will no longer be auto-updated.' ); ?></p></div>
   568 <?php endif; ?>
   713 <?php endif; ?>
   569 
   714 
   570 <div class="wrap">
   715 <div class="wrap">
   571 <h1 class="wp-heading-inline">
   716 <h1 class="wp-heading-inline">
   572 <?php
   717 <?php
   580 	<a href="<?php echo self_admin_url( 'plugin-install.php' ); ?>" class="page-title-action"><?php echo esc_html_x( 'Add New', 'plugin' ); ?></a>
   725 	<a href="<?php echo self_admin_url( 'plugin-install.php' ); ?>" class="page-title-action"><?php echo esc_html_x( 'Add New', 'plugin' ); ?></a>
   581 	<?php
   726 	<?php
   582 }
   727 }
   583 
   728 
   584 if ( strlen( $s ) ) {
   729 if ( strlen( $s ) ) {
   585 	/* translators: %s: search keywords */
   730 	/* translators: %s: Search query. */
   586 	printf( '<span class="subtitle">' . __( 'Search results for &#8220;%s&#8221;' ) . '</span>', esc_html( urldecode( $s ) ) );
   731 	printf( '<span class="subtitle">' . __( 'Search results for &#8220;%s&#8221;' ) . '</span>', esc_html( urldecode( $s ) ) );
   587 }
   732 }
   588 ?>
   733 ?>
   589 
   734 
   590 <hr class="wp-header-end">
   735 <hr class="wp-header-end">
   625 <?php
   770 <?php
   626 wp_print_request_filesystem_credentials_modal();
   771 wp_print_request_filesystem_credentials_modal();
   627 wp_print_admin_notice_templates();
   772 wp_print_admin_notice_templates();
   628 wp_print_update_row_templates();
   773 wp_print_update_row_templates();
   629 
   774 
   630 include( ABSPATH . 'wp-admin/admin-footer.php' );
   775 require_once ABSPATH . 'wp-admin/admin-footer.php';