WordPress 4.1
[autoinstalls/wordpress.git] / wp-admin / plugins.php
1 <?php
2 /**
3  * Plugins administration panel.
4  *
5  * @package WordPress
6  * @subpackage Administration
7  */
8
9 /** WordPress Administration Bootstrap */
10 require_once( dirname( __FILE__ ) . '/admin.php' );
11
12 if ( ! current_user_can('activate_plugins') )
13         wp_die( __( 'You do not have sufficient permissions to manage plugins for this site.' ) );
14
15 $wp_list_table = _get_list_table('WP_Plugins_List_Table');
16 $pagenum = $wp_list_table->get_pagenum();
17
18 $action = $wp_list_table->current_action();
19
20 $plugin = isset($_REQUEST['plugin']) ? $_REQUEST['plugin'] : '';
21 $s = isset($_REQUEST['s']) ? urlencode($_REQUEST['s']) : '';
22
23 // Clean up request URI from temporary args for screen options/paging uri's to work as expected.
24 $_SERVER['REQUEST_URI'] = remove_query_arg(array('error', 'deleted', 'activate', 'activate-multi', 'deactivate', 'deactivate-multi', '_error_nonce'), $_SERVER['REQUEST_URI']);
25
26 if ( $action ) {
27
28         switch ( $action ) {
29                 case 'activate':
30                         if ( ! current_user_can('activate_plugins') )
31                                 wp_die(__('You do not have sufficient permissions to activate plugins for this site.'));
32
33                         if ( is_multisite() && ! is_network_admin() && is_network_only_plugin( $plugin ) ) {
34                                 wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
35                                 exit;
36                         }
37
38                         check_admin_referer('activate-plugin_' . $plugin);
39
40                         $result = activate_plugin($plugin, self_admin_url('plugins.php?error=true&plugin=' . $plugin), is_network_admin() );
41                         if ( is_wp_error( $result ) ) {
42                                 if ( 'unexpected_output' == $result->get_error_code() ) {
43                                         $redirect = self_admin_url('plugins.php?error=true&charsout=' . strlen($result->get_error_data()) . '&plugin=' . $plugin . "&plugin_status=$status&paged=$page&s=$s");
44                                         wp_redirect(add_query_arg('_error_nonce', wp_create_nonce('plugin-activation-error_' . $plugin), $redirect));
45                                         exit;
46                                 } else {
47                                         wp_die($result);
48                                 }
49                         }
50
51                         if ( ! is_network_admin() ) {
52                                 $recent = (array) get_option( 'recently_activated' );
53                                 unset( $recent[ $plugin ] );
54                                 update_option( 'recently_activated', $recent );
55                         }
56
57                         if ( isset($_GET['from']) && 'import' == $_GET['from'] ) {
58                                 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
59                         } else {
60                                 wp_redirect( self_admin_url("plugins.php?activate=true&plugin_status=$status&paged=$page&s=$s") ); // overrides the ?error=true one above
61                         }
62                         exit;
63
64                 case 'activate-selected':
65                         if ( ! current_user_can('activate_plugins') )
66                                 wp_die(__('You do not have sufficient permissions to activate plugins for this site.'));
67
68                         check_admin_referer('bulk-plugins');
69
70                         $plugins = isset( $_POST['checked'] ) ? (array) $_POST['checked'] : array();
71
72                         if ( is_network_admin() ) {
73                                 foreach ( $plugins as $i => $plugin ) {
74                                         // Only activate plugins which are not already network activated.
75                                         if ( is_plugin_active_for_network( $plugin ) ) {
76                                                 unset( $plugins[ $i ] );
77                                         }
78                                 }
79                         } else {
80                                 foreach ( $plugins as $i => $plugin ) {
81                                         // Only activate plugins which are not already active and are not network-only when on Multisite.
82                                         if ( is_plugin_active( $plugin ) || ( is_multisite() && is_network_only_plugin( $plugin ) ) ) {
83                                                 unset( $plugins[ $i ] );
84                                         }
85                                 }
86                         }
87
88                         if ( empty($plugins) ) {
89                                 wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
90                                 exit;
91                         }
92
93                         activate_plugins($plugins, self_admin_url('plugins.php?error=true'), is_network_admin() );
94
95                         if ( ! is_network_admin() ) {
96                                 $recent = (array) get_option('recently_activated' );
97                                 foreach ( $plugins as $plugin )
98                                         unset( $recent[ $plugin ] );
99                                 update_option( 'recently_activated', $recent );
100                         }
101
102                         wp_redirect( self_admin_url("plugins.php?activate-multi=true&plugin_status=$status&paged=$page&s=$s") );
103                         exit;
104
105                 case 'update-selected' :
106
107                         check_admin_referer( 'bulk-plugins' );
108
109                         if ( isset( $_GET['plugins'] ) )
110                                 $plugins = explode( ',', $_GET['plugins'] );
111                         elseif ( isset( $_POST['checked'] ) )
112                                 $plugins = (array) $_POST['checked'];
113                         else
114                                 $plugins = array();
115
116                         $title = __( 'Update Plugins' );
117                         $parent_file = 'plugins.php';
118
119                         wp_enqueue_script( 'updates' );
120                         require_once(ABSPATH . 'wp-admin/admin-header.php');
121
122                         echo '<div class="wrap">';
123                         echo '<h2>' . esc_html( $title ) . '</h2>';
124
125                         $url = self_admin_url('update.php?action=update-selected&amp;plugins=' . urlencode( join(',', $plugins) ));
126                         $url = wp_nonce_url($url, 'bulk-update-plugins');
127
128                         echo "<iframe src='$url' style='width: 100%; height:100%; min-height:850px;'></iframe>";
129                         echo '</div>';
130                         require_once(ABSPATH . 'wp-admin/admin-footer.php');
131                         exit;
132
133                 case 'error_scrape':
134                         if ( ! current_user_can('activate_plugins') )
135                                 wp_die(__('You do not have sufficient permissions to activate plugins for this site.'));
136
137                         check_admin_referer('plugin-activation-error_' . $plugin);
138
139                         $valid = validate_plugin($plugin);
140                         if ( is_wp_error($valid) )
141                                 wp_die($valid);
142
143                         if ( ! WP_DEBUG ) {
144                                 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 );
145                         }
146
147                         @ini_set('display_errors', true); //Ensure that Fatal errors are displayed.
148                         // Go back to "sandbox" scope so we get the same errors as before
149                         function plugin_sandbox_scrape( $plugin ) {
150                                 wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin );
151                                 include( WP_PLUGIN_DIR . '/' . $plugin );
152                         }
153                         plugin_sandbox_scrape( $plugin );
154                         /** This action is documented in wp-admin/includes/plugin.php */
155                         do_action( "activate_{$plugin}" );
156                         exit;
157
158                 case 'deactivate':
159                         if ( ! current_user_can('activate_plugins') )
160                                 wp_die(__('You do not have sufficient permissions to deactivate plugins for this site.'));
161
162                         check_admin_referer('deactivate-plugin_' . $plugin);
163
164                         if ( ! is_network_admin() && is_plugin_active_for_network( $plugin ) ) {
165                                 wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
166                                 exit;
167                         }
168
169                         deactivate_plugins( $plugin, false, is_network_admin() );
170                         if ( ! is_network_admin() )
171                                 update_option( 'recently_activated', array( $plugin => time() ) + (array) get_option( 'recently_activated' ) );
172                         if ( headers_sent() )
173                                 echo "<meta http-equiv='refresh' content='" . esc_attr( "0;url=plugins.php?deactivate=true&plugin_status=$status&paged=$page&s=$s" ) . "' />";
174                         else
175                                 wp_redirect( self_admin_url("plugins.php?deactivate=true&plugin_status=$status&paged=$page&s=$s") );
176                         exit;
177
178                 case 'deactivate-selected':
179                         if ( ! current_user_can('activate_plugins') )
180                                 wp_die(__('You do not have sufficient permissions to deactivate plugins for this site.'));
181
182                         check_admin_referer('bulk-plugins');
183
184                         $plugins = isset( $_POST['checked'] ) ? (array) $_POST['checked'] : array();
185                         // Do not deactivate plugins which are already deactivated.
186                         if ( is_network_admin() ) {
187                                 $plugins = array_filter( $plugins, 'is_plugin_active_for_network' );
188                         } else {
189                                 $plugins = array_filter( $plugins, 'is_plugin_active' );
190                                 $plugins = array_diff( $plugins, array_filter( $plugins, 'is_plugin_active_for_network' ) );
191                         }
192                         if ( empty($plugins) ) {
193                                 wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
194                                 exit;
195                         }
196
197                         deactivate_plugins( $plugins, false, is_network_admin() );
198
199                         if ( ! is_network_admin() ) {
200                                 $deactivated = array();
201                                 foreach ( $plugins as $plugin )
202                                         $deactivated[ $plugin ] = time();
203                                 update_option( 'recently_activated', $deactivated + (array) get_option( 'recently_activated' ) );
204                         }
205
206                         wp_redirect( self_admin_url("plugins.php?deactivate-multi=true&plugin_status=$status&paged=$page&s=$s") );
207                         exit;
208
209                 case 'delete-selected':
210                         if ( ! current_user_can('delete_plugins') ) {
211                                 wp_die(__('You do not have sufficient permissions to delete plugins for this site.'));
212                         }
213
214                         check_admin_referer('bulk-plugins');
215
216                         //$_POST = from the plugin form; $_GET = from the FTP details screen.
217                         $plugins = isset( $_REQUEST['checked'] ) ? (array) $_REQUEST['checked'] : array();
218                         if ( empty( $plugins ) ) {
219                                 wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
220                                 exit;
221                         }
222
223                         $plugins = array_filter($plugins, 'is_plugin_inactive'); // Do not allow to delete Activated plugins.
224                         if ( empty( $plugins ) ) {
225                                 wp_redirect( self_admin_url( "plugins.php?error=true&main=true&plugin_status=$status&paged=$page&s=$s" ) );
226                                 exit;
227                         }
228
229                         include(ABSPATH . 'wp-admin/update.php');
230
231                         $parent_file = 'plugins.php';
232
233                         if ( ! isset($_REQUEST['verify-delete']) ) {
234                                 wp_enqueue_script('jquery');
235                                 require_once(ABSPATH . 'wp-admin/admin-header.php');
236                                 ?>
237                         <div class="wrap">
238                                 <?php
239                                         $files_to_delete = $plugin_info = array();
240                                         $have_non_network_plugins = false;
241                                         $plugin_translations = wp_get_installed_translations( 'plugins' );
242                                         foreach ( (array) $plugins as $plugin ) {
243                                                 $plugin_slug = dirname( $plugin );
244
245                                                 if ( '.' == $plugin_slug ) {
246                                                         $files_to_delete[] = WP_PLUGIN_DIR . '/' . $plugin;
247                                                         if ( $data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ) ) {
248                                                                 $plugin_info[ $plugin ] = $data;
249                                                                 $plugin_info[ $plugin ]['is_uninstallable'] = is_uninstallable_plugin( $plugin );
250                                                                 if ( ! $plugin_info[ $plugin ]['Network'] ) {
251                                                                         $have_non_network_plugins = true;
252                                                                 }
253                                                         }
254                                                 } else {
255                                                         // Locate all the files in that folder.
256                                                         $files = list_files( WP_PLUGIN_DIR . '/' . $plugin_slug );
257                                                         if ( $files ) {
258                                                                 $files_to_delete = array_merge( $files_to_delete, $files );
259                                                         }
260
261                                                         // Get plugins list from that folder.
262                                                         if ( $folder_plugins = get_plugins( '/' . $plugin_slug ) ) {
263                                                                 foreach( $folder_plugins as $plugin_file => $data ) {
264                                                                         $plugin_info[ $plugin_file ] = _get_plugin_data_markup_translate( $plugin_file, $data );
265                                                                         $plugin_info[ $plugin_file ]['is_uninstallable'] = is_uninstallable_plugin( $plugin );
266                                                                         if ( ! $plugin_info[ $plugin_file ]['Network'] ) {
267                                                                                 $have_non_network_plugins = true;
268                                                                         }
269                                                                 }
270                                                         }
271
272                                                         // Add translation files.
273                                                         if ( ! empty( $plugin_translations[ $plugin_slug ] ) ) {
274                                                                 $translations = $plugin_translations[ $plugin_slug ];
275
276                                                                 foreach ( $translations as $translation => $data ) {
277                                                                         $files_to_delete[] = $plugin_slug . '-' . $translation . '.po';
278                                                                         $files_to_delete[] = $plugin_slug . '-' . $translation . '.mo';
279                                                                 }
280                                                         }
281                                                 }
282                                         }
283                                         $plugins_to_delete = count( $plugin_info );
284                                         echo '<h2>' . _n( 'Delete Plugin', 'Delete Plugins', $plugins_to_delete ) . '</h2>';
285                                 ?>
286                                 <?php if ( $have_non_network_plugins && is_network_admin() ) : ?>
287                                 <div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php echo _n( 'This plugin may be active on other sites in the network.', 'These plugins may be active on other sites in the network.', $plugins_to_delete ); ?></p></div>
288                                 <?php endif; ?>
289                                 <p><?php echo _n( 'You are about to remove the following plugin:', 'You are about to remove the following plugins:', $plugins_to_delete ); ?></p>
290                                         <ul class="ul-disc">
291                                                 <?php
292                                                 $data_to_delete = false;
293                                                 foreach ( $plugin_info as $plugin ) {
294                                                         if ( $plugin['is_uninstallable'] ) {
295                                                                 /* translators: 1: plugin name, 2: plugin author */
296                                                                 echo '<li>', sprintf( __( '<strong>%1$s</strong> by <em>%2$s</em> (will also <strong>delete its data</strong>)' ), esc_html($plugin['Name']), esc_html($plugin['AuthorName']) ), '</li>';
297                                                                 $data_to_delete = true;
298                                                         } else {
299                                                                 /* translators: 1: plugin name, 2: plugin author */
300                                                                 echo '<li>', sprintf( __('<strong>%1$s</strong> by <em>%2$s</em>' ), esc_html($plugin['Name']), esc_html($plugin['AuthorName']) ), '</li>';
301                                                         }
302                                                 }
303                                                 ?>
304                                         </ul>
305                                 <p><?php
306                                 if ( $data_to_delete )
307                                         _e('Are you sure you wish to delete these files and data?');
308                                 else
309                                         _e('Are you sure you wish to delete these files?');
310                                 ?></p>
311                                 <form method="post" action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" style="display:inline;">
312                                         <input type="hidden" name="verify-delete" value="1" />
313                                         <input type="hidden" name="action" value="delete-selected" />
314                                         <?php
315                                                 foreach ( (array) $plugins as $plugin ) {
316                                                         echo '<input type="hidden" name="checked[]" value="' . esc_attr( $plugin ) . '" />';
317                                                 }
318                                         ?>
319                                         <?php wp_nonce_field('bulk-plugins') ?>
320                                         <?php submit_button( $data_to_delete ? __( 'Yes, Delete these files and data' ) : __( 'Yes, Delete these files' ), 'button', 'submit', false ); ?>
321                                 </form>
322                                 <form method="post" action="<?php echo esc_url(wp_get_referer()); ?>" style="display:inline;">
323                                         <?php submit_button( __( 'No, Return me to the plugin list' ), 'button', 'submit', false ); ?>
324                                 </form>
325
326                                 <p><a href="#" onclick="jQuery('#files-list').toggle(); return false;"><?php _e('Click to view entire list of files which will be deleted'); ?></a></p>
327                                 <div id="files-list" style="display:none;">
328                                         <ul class="code">
329                                         <?php
330                                                 foreach ( (array) $files_to_delete as $file ) {
331                                                         echo '<li>' . esc_html( str_replace( WP_PLUGIN_DIR, '', $file ) ) . '</li>';
332                                                 }
333                                         ?>
334                                         </ul>
335                                 </div>
336                         </div>
337                                 <?php
338                                 require_once(ABSPATH . 'wp-admin/admin-footer.php');
339                                 exit;
340                         } //Endif verify-delete
341                         $delete_result = delete_plugins($plugins);
342
343                         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
344                         wp_redirect( self_admin_url("plugins.php?deleted=true&plugin_status=$status&paged=$page&s=$s") );
345                         exit;
346
347                 case 'clear-recent-list':
348                         if ( ! is_network_admin() )
349                                 update_option( 'recently_activated', array() );
350                         break;
351         }
352 }
353
354 $wp_list_table->prepare_items();
355
356 wp_enqueue_script('plugin-install');
357 add_thickbox();
358
359 add_screen_option( 'per_page', array('label' => _x( 'Plugins', 'plugins per page (screen options)' ), 'default' => 999 ) );
360
361 get_current_screen()->add_help_tab( array(
362 'id'            => 'overview',
363 'title'         => __('Overview'),
364 'content'       =>
365         '<p>' . __('Plugins extend and expand the functionality of WordPress. Once a plugin is installed, you may activate it or deactivate it here.') . '</p>' .
366         '<p>' . sprintf(__('You can find additional plugins for your site by using the <a href="%1$s">Plugin Browser/Installer</a> functionality or by browsing the <a href="%2$s" target="_blank">WordPress Plugin Directory</a> directly and installing new plugins manually. To manually install a plugin you generally just need to upload the plugin file into your <code>/wp-content/plugins</code> directory. Once a plugin has been installed, you can activate it here.'), 'plugin-install.php', 'https://wordpress.org/plugins/') . '</p>'
367 ) );
368 get_current_screen()->add_help_tab( array(
369 'id'            => 'compatibility-problems',
370 'title'         => __('Troubleshooting'),
371 'content'       =>
372         '<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>' .
373         '<p>' . sprintf( __('If something goes wrong with a plugin and you can&#8217;t use WordPress, delete or rename that file in the <code>%s</code> directory and it will be automatically deactivated.'), WP_PLUGIN_DIR) . '</p>'
374 ) );
375
376 get_current_screen()->set_help_sidebar(
377         '<p><strong>' . __('For more information:') . '</strong></p>' .
378         '<p>' . __('<a href="http://codex.wordpress.org/Managing_Plugins#Plugin_Management" target="_blank">Documentation on Managing Plugins</a>') . '</p>' .
379         '<p>' . __('<a href="https://wordpress.org/support/" target="_blank">Support Forums</a>') . '</p>'
380 );
381
382 $title = __('Plugins');
383 $parent_file = 'plugins.php';
384
385 require_once(ABSPATH . 'wp-admin/admin-header.php');
386
387 $invalid = validate_active_plugins();
388 if ( !empty($invalid) )
389         foreach ( $invalid as $plugin_file => $error )
390                 echo '<div id="message" class="error"><p>' . sprintf(__('The plugin <code>%s</code> has been <strong>deactivated</strong> due to an error: %s'), esc_html($plugin_file), $error->get_error_message()) . '</p></div>';
391 ?>
392
393 <?php if ( isset($_GET['error']) ) :
394
395         if ( isset( $_GET['main'] ) )
396                 $errmsg = __( 'You cannot delete a plugin while it is active on the main site.' );
397         elseif ( isset($_GET['charsout']) )
398                 $errmsg = sprintf(__('The plugin generated %d characters of <strong>unexpected output</strong> during activation. If you notice &#8220;headers already sent&#8221; messages, problems with syndication feeds or other issues, try deactivating or removing this plugin.'), $_GET['charsout']);
399         else
400                 $errmsg = __('Plugin could not be activated because it triggered a <strong>fatal error</strong>.');
401         ?>
402         <div id="message" class="error"><p><?php echo $errmsg; ?></p>
403         <?php
404                 if ( !isset( $_GET['main'] ) && !isset($_GET['charsout']) && wp_verify_nonce($_GET['_error_nonce'], 'plugin-activation-error_' . $plugin) ) { ?>
405         <iframe style="border:0" width="100%" height="70px" src="<?php echo 'plugins.php?action=error_scrape&amp;plugin=' . esc_attr($plugin) . '&amp;_wpnonce=' . esc_attr($_GET['_error_nonce']); ?>"></iframe>
406         <?php
407                 }
408         ?>
409         </div>
410 <?php elseif ( isset($_GET['deleted']) ) :
411                 $delete_result = get_transient( 'plugins_delete_result_' . $user_ID );
412                 // Delete it once we're done.
413                 delete_transient( 'plugins_delete_result_' . $user_ID );
414
415                 if ( is_wp_error($delete_result) ) : ?>
416                 <div id="message" class="error"><p><?php printf( __('Plugin could not be deleted due to an error: %s'), $delete_result->get_error_message() ); ?></p></div>
417                 <?php else : ?>
418                 <div id="message" class="updated"><p><?php _e('The selected plugins have been <strong>deleted</strong>.'); ?></p></div>
419                 <?php endif; ?>
420 <?php elseif ( isset($_GET['activate']) ) : ?>
421         <div id="message" class="updated"><p><?php _e('Plugin <strong>activated</strong>.') ?></p></div>
422 <?php elseif (isset($_GET['activate-multi'])) : ?>
423         <div id="message" class="updated"><p><?php _e('Selected plugins <strong>activated</strong>.'); ?></p></div>
424 <?php elseif ( isset($_GET['deactivate']) ) : ?>
425         <div id="message" class="updated"><p><?php _e('Plugin <strong>deactivated</strong>.') ?></p></div>
426 <?php elseif (isset($_GET['deactivate-multi'])) : ?>
427         <div id="message" class="updated"><p><?php _e('Selected plugins <strong>deactivated</strong>.'); ?></p></div>
428 <?php elseif ( 'update-selected' == $action ) : ?>
429         <div id="message" class="updated"><p><?php _e('No out of date plugins were selected.'); ?></p></div>
430 <?php endif; ?>
431
432 <div class="wrap">
433 <h2><?php echo esc_html( $title );
434 if ( ( ! is_multisite() || is_network_admin() ) && current_user_can('install_plugins') ) { ?>
435  <a href="<?php echo self_admin_url( 'plugin-install.php' ); ?>" class="add-new-h2"><?php echo esc_html_x('Add New', 'plugin'); ?></a>
436 <?php }
437 if ( $s )
438         printf( '<span class="subtitle">' . __('Search results for &#8220;%s&#8221;') . '</span>', esc_html( $s ) ); ?>
439 </h2>
440
441 <?php
442 /**
443  * Fires before the plugins list table is rendered.
444  *
445  * This hook also fires before the plugins list table is rendered in the Network Admin.
446  *
447  * Please note: The 'active' portion of the hook name does not refer to whether the current
448  * view is for active plugins, but rather all plugins actively-installed.
449  *
450  * @since 3.0.0
451  *
452  * @param array $plugins_all An array containing all installed plugins.
453  */
454 do_action( 'pre_current_active_plugins', $plugins['all'] );
455 ?>
456
457 <?php $wp_list_table->views(); ?>
458
459 <form method="get" action="">
460 <?php $wp_list_table->search_box( __( 'Search Installed Plugins' ), 'plugin' ); ?>
461 </form>
462
463 <form method="post" action="">
464
465 <input type="hidden" name="plugin_status" value="<?php echo esc_attr($status) ?>" />
466 <input type="hidden" name="paged" value="<?php echo esc_attr($page) ?>" />
467
468 <?php $wp_list_table->display(); ?>
469 </form>
470
471 </div>
472
473 <?php
474 include(ABSPATH . 'wp-admin/admin-footer.php');