run:R W Run
7.85 KB
2026-03-11 16:18:51
R W Run
3.54 KB
2026-03-11 16:18:51
R W Run
148.33 KB
2026-03-11 16:18:51
R W Run
11.45 KB
2026-03-11 16:18:51
R W Run
3.58 KB
2026-03-11 16:18:51
R W Run
2.53 KB
2026-03-11 16:18:51
R W Run
2.6 KB
2026-03-11 16:18:51
R W Run
6.59 KB
2026-03-11 16:18:51
R W Run
14.83 KB
2026-03-11 16:18:51
R W Run
21.18 KB
2026-03-11 16:18:51
R W Run
48.13 KB
2026-03-11 16:18:51
R W Run
4.07 KB
2026-03-11 16:18:51
R W Run
5.3 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
26.73 KB
2026-03-11 16:18:51
R W Run
2.8 KB
2026-03-11 16:18:51
R W Run
15.2 KB
2026-03-11 16:18:51
R W Run
192.08 KB
2026-03-11 16:18:51
R W Run
11.77 KB
2026-03-11 16:18:51
R W Run
3.2 KB
2026-03-11 16:18:51
R W Run
22.89 KB
2026-03-11 16:18:51
R W Run
12.77 KB
2026-03-11 16:18:51
R W Run
4.08 KB
2026-03-11 16:18:51
R W Run
26.27 KB
2026-03-11 16:18:51
R W Run
4.97 KB
2026-03-11 16:18:51
R W Run
5.57 KB
2026-03-11 16:18:51
R W Run
13.93 KB
2026-03-11 16:18:51
R W Run
4.09 KB
2026-03-11 16:18:51
R W Run
6.79 KB
2026-03-11 16:18:51
R W Run
60.45 KB
2026-03-11 16:18:51
R W Run
32.4 KB
2026-03-11 16:18:51
R W Run
18.24 KB
2026-03-11 16:18:51
R W Run
66.01 KB
2026-03-11 16:18:51
R W Run
23.84 KB
2026-03-11 16:18:51
R W Run
17.72 KB
2026-03-11 16:18:51
R W Run
22.71 KB
2026-03-11 16:18:51
R W Run
18.05 KB
2026-03-11 16:18:51
R W Run
22.76 KB
2026-03-11 16:18:51
R W Run
7.34 KB
2026-03-11 16:18:51
R W Run
4.51 KB
2026-03-11 16:18:51
R W Run
9.02 KB
2026-03-11 16:18:51
R W Run
1.46 KB
2026-03-11 16:18:51
R W Run
51.76 KB
2026-03-11 16:18:51
R W Run
25.29 KB
2026-03-11 16:18:51
R W Run
21.61 KB
2026-03-11 16:18:51
R W Run
27.77 KB
2026-03-11 16:18:51
R W Run
15.35 KB
2026-03-11 16:18:51
R W Run
24.54 KB
2026-03-11 16:18:51
R W Run
56.44 KB
2026-03-11 16:18:51
R W Run
1.42 KB
2026-03-11 16:18:51
R W Run
63.66 KB
2026-03-11 16:18:51
R W Run
31.9 KB
2026-03-11 16:18:51
R W Run
14.44 KB
2026-03-11 16:18:51
R W Run
36.47 KB
2026-03-11 16:18:51
R W Run
14 KB
2026-03-11 16:18:51
R W Run
121.89 KB
2026-03-11 16:18:51
R W Run
6.26 KB
2026-03-11 16:18:51
R W Run
20.73 KB
2026-03-11 16:18:51
R W Run
15.23 KB
2026-03-11 16:18:51
R W Run
10.14 KB
2026-03-11 16:18:51
R W Run
6.94 KB
2026-03-11 16:18:51
R W Run
1.44 KB
2026-03-11 16:18:51
R W Run
46.85 KB
2026-03-11 16:18:51
R W Run
18.61 KB
2026-03-11 16:18:51
R W Run
6.08 KB
2026-03-11 16:18:51
R W Run
20.06 KB
2026-03-11 16:18:51
R W Run
5.73 KB
2026-03-11 16:18:51
R W Run
68.18 KB
2026-03-11 16:18:51
R W Run
40.8 KB
2026-03-11 16:18:51
R W Run
1.44 KB
2026-03-11 16:18:51
R W Run
25.26 KB
2026-03-11 16:18:51
R W Run
95.94 KB
2026-03-11 16:18:51
R W Run
43.12 KB
2026-03-11 16:18:51
R W Run
41.73 KB
2026-03-11 16:18:51
R W Run
6.46 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
116.31 KB
2026-03-11 16:18:51
R W Run
9.39 KB
2026-03-11 16:18:51
R W Run
64.34 KB
2026-03-11 16:18:51
R W Run
44.73 KB
2026-03-11 16:18:51
R W Run
1.27 KB
2026-03-11 16:18:51
R W Run
3.68 KB
2026-03-11 16:18:51
R W Run
33.53 KB
2026-03-11 16:18:51
R W Run
48.84 KB
2026-03-11 16:18:51
R W Run
26.35 KB
2026-03-11 16:18:51
R W Run
1.12 KB
2026-03-11 16:18:51
R W Run
4.19 KB
2026-03-11 16:18:51
R W Run
38.19 KB
2026-03-11 16:18:51
R W Run
91.33 KB
2026-03-11 16:18:51
R W Run
80.39 KB
2026-03-11 16:18:51
R W Run
32.67 KB
2026-03-11 16:18:51
R W Run
16.18 KB
2026-03-11 16:18:51
R W Run
44.46 KB
2026-03-11 16:18:51
R W Run
6.23 KB
2026-03-11 16:18:51
R W Run
8.23 KB
2026-03-11 16:18:51
R W Run
96.96 KB
2026-03-11 16:18:51
R W Run
6.83 KB
2026-03-11 16:18:51
R W Run
46.62 KB
2026-03-11 16:18:51
R W Run
10.82 KB
2026-03-11 16:18:51
R W Run
68.86 KB
2026-03-11 16:18:51
R W Run
33.63 KB
2026-03-11 16:18:51
R W Run
113.3 KB
2026-03-11 16:18:51
R W Run
22.98 KB
2026-03-11 16:18:51
R W Run
10.66 KB
2026-03-11 16:18:51
R W Run
error_log
📄class-wp-plugins-list-table.php
1<?php
2/**
3 * List Table API: WP_Plugins_List_Table class
4 *
5 * @package WordPress
6 * @subpackage Administration
7 * @since 3.1.0
8 */
9
10/**
11 * Core class used to implement displaying installed plugins in a list table.
12 *
13 * @since 3.1.0
14 *
15 * @see WP_List_Table
16 */
17class WP_Plugins_List_Table extends WP_List_Table {
18 /**
19 * Whether to show the auto-updates UI.
20 *
21 * @since 5.5.0
22 *
23 * @var bool True if auto-updates UI is to be shown, false otherwise.
24 */
25 protected $show_autoupdates = true;
26
27 /**
28 * Constructor.
29 *
30 * @since 3.1.0
31 *
32 * @see WP_List_Table::__construct() for more information on default arguments.
33 *
34 * @global string $status
35 * @global int $page
36 *
37 * @param array $args An associative array of arguments.
38 */
39 public function __construct( $args = array() ) {
40 global $status, $page;
41
42 parent::__construct(
43 array(
44 'plural' => 'plugins',
45 'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
46 )
47 );
48
49 $allowed_statuses = array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search', 'paused', 'auto-update-enabled', 'auto-update-disabled' );
50
51 $status = 'all';
52 if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], $allowed_statuses, true ) ) {
53 $status = $_REQUEST['plugin_status'];
54 }
55
56 if ( isset( $_REQUEST['s'] ) ) {
57 $_SERVER['REQUEST_URI'] = add_query_arg( 's', wp_unslash( $_REQUEST['s'] ) );
58 }
59
60 $page = $this->get_pagenum();
61
62 $this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'plugin' )
63 && current_user_can( 'update_plugins' )
64 && ( ! is_multisite() || $this->screen->in_admin( 'network' ) );
65 }
66
67 /**
68 * @return array
69 */
70 protected function get_table_classes() {
71 return array( 'widefat', $this->_args['plural'] );
72 }
73
74 /**
75 * @return bool
76 */
77 public function ajax_user_can() {
78 return current_user_can( 'activate_plugins' );
79 }
80
81 /**
82 * @global string $status
83 * @global array $plugins
84 * @global array $totals
85 * @global int $page
86 * @global string $orderby
87 * @global string $order
88 * @global string $s
89 */
90 public function prepare_items() {
91 global $status, $plugins, $totals, $page, $orderby, $order, $s;
92
93 $orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : '';
94 $order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : '';
95
96 /**
97 * Filters the full array of plugins to list in the Plugins list table.
98 *
99 * @since 3.0.0
100 *
101 * @see get_plugins()
102 *
103 * @param array $all_plugins An array of plugins to display in the list table.
104 */
105 $all_plugins = apply_filters( 'all_plugins', get_plugins() );
106
107 $plugins = array(
108 'all' => $all_plugins,
109 'search' => array(),
110 'active' => array(),
111 'inactive' => array(),
112 'recently_activated' => array(),
113 'upgrade' => array(),
114 'mustuse' => array(),
115 'dropins' => array(),
116 'paused' => array(),
117 );
118 if ( $this->show_autoupdates ) {
119 $auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
120
121 $plugins['auto-update-enabled'] = array();
122 $plugins['auto-update-disabled'] = array();
123 }
124
125 $screen = $this->screen;
126
127 if ( ! is_multisite() || ( $screen->in_admin( 'network' ) && current_user_can( 'manage_network_plugins' ) ) ) {
128
129 /**
130 * Filters whether to display the advanced plugins list table.
131 *
132 * There are two types of advanced plugins - must-use and drop-ins -
133 * which can be used in a single site or Multisite network.
134 *
135 * The $type parameter allows you to differentiate between the type of advanced
136 * plugins to filter the display of. Contexts include 'mustuse' and 'dropins'.
137 *
138 * @since 3.0.0
139 *
140 * @param bool $show Whether to show the advanced plugins for the specified
141 * plugin type. Default true.
142 * @param string $type The plugin type. Accepts 'mustuse', 'dropins'.
143 */
144 if ( apply_filters( 'show_advanced_plugins', true, 'mustuse' ) ) {
145 $plugins['mustuse'] = get_mu_plugins();
146 }
147
148 /** This action is documented in wp-admin/includes/class-wp-plugins-list-table.php */
149 if ( apply_filters( 'show_advanced_plugins', true, 'dropins' ) ) {
150 $plugins['dropins'] = get_dropins();
151 }
152
153 if ( current_user_can( 'update_plugins' ) ) {
154 $current = get_site_transient( 'update_plugins' );
155 foreach ( (array) $plugins['all'] as $plugin_file => $plugin_data ) {
156 if ( isset( $current->response[ $plugin_file ] ) ) {
157 $plugins['all'][ $plugin_file ]['update'] = true;
158 $plugins['upgrade'][ $plugin_file ] = $plugins['all'][ $plugin_file ];
159 }
160 }
161 }
162 }
163
164 if ( ! $screen->in_admin( 'network' ) ) {
165 $show = current_user_can( 'manage_network_plugins' );
166 /**
167 * Filters whether to display network-active plugins alongside plugins active for the current site.
168 *
169 * This also controls the display of inactive network-only plugins (plugins with
170 * "Network: true" in the plugin header).
171 *
172 * Plugins cannot be network-activated or network-deactivated from this screen.
173 *
174 * @since 4.4.0
175 *
176 * @param bool $show Whether to show network-active plugins. Default is whether the current
177 * user can manage network plugins (ie. a Super Admin).
178 */
179 $show_network_active = apply_filters( 'show_network_active_plugins', $show );
180 }
181
182 if ( $screen->in_admin( 'network' ) ) {
183 $recently_activated = get_site_option( 'recently_activated', array() );
184 } else {
185 $recently_activated = get_option( 'recently_activated', array() );
186 }
187
188 foreach ( $recently_activated as $key => $time ) {
189 if ( $time + WEEK_IN_SECONDS < time() ) {
190 unset( $recently_activated[ $key ] );
191 }
192 }
193
194 if ( $screen->in_admin( 'network' ) ) {
195 update_site_option( 'recently_activated', $recently_activated );
196 } else {
197 update_option( 'recently_activated', $recently_activated, false );
198 }
199
200 $plugin_info = get_site_transient( 'update_plugins' );
201
202 foreach ( (array) $plugins['all'] as $plugin_file => $plugin_data ) {
203 // Extra info if known. array_merge() ensures $plugin_data has precedence if keys collide.
204 if ( isset( $plugin_info->response[ $plugin_file ] ) ) {
205 $plugin_data = array_merge( (array) $plugin_info->response[ $plugin_file ], array( 'update-supported' => true ), $plugin_data );
206 } elseif ( isset( $plugin_info->no_update[ $plugin_file ] ) ) {
207 $plugin_data = array_merge( (array) $plugin_info->no_update[ $plugin_file ], array( 'update-supported' => true ), $plugin_data );
208 } elseif ( empty( $plugin_data['update-supported'] ) ) {
209 $plugin_data['update-supported'] = false;
210 }
211
212 /*
213 * Create the payload that's used for the auto_update_plugin filter.
214 * This is the same data contained within $plugin_info->(response|no_update) however
215 * not all plugins will be contained in those keys, this avoids unexpected warnings.
216 */
217 $filter_payload = array(
218 'id' => $plugin_file,
219 'slug' => '',
220 'plugin' => $plugin_file,
221 'new_version' => '',
222 'url' => '',
223 'package' => '',
224 'icons' => array(),
225 'banners' => array(),
226 'banners_rtl' => array(),
227 'tested' => '',
228 'requires_php' => '',
229 'compatibility' => new stdClass(),
230 );
231
232 $filter_payload = (object) wp_parse_args( $plugin_data, $filter_payload );
233
234 $auto_update_forced = wp_is_auto_update_forced_for_item( 'plugin', null, $filter_payload );
235
236 if ( ! is_null( $auto_update_forced ) ) {
237 $plugin_data['auto-update-forced'] = $auto_update_forced;
238 }
239
240 $plugins['all'][ $plugin_file ] = $plugin_data;
241 // Make sure that $plugins['upgrade'] also receives the extra info since it is used on ?plugin_status=upgrade.
242 if ( isset( $plugins['upgrade'][ $plugin_file ] ) ) {
243 $plugins['upgrade'][ $plugin_file ] = $plugin_data;
244 }
245
246 // Filter into individual sections.
247 if ( is_multisite() && ! $screen->in_admin( 'network' ) && is_network_only_plugin( $plugin_file ) && ! is_plugin_active( $plugin_file ) ) {
248 if ( $show_network_active ) {
249 // On the non-network screen, show inactive network-only plugins if allowed.
250 $plugins['inactive'][ $plugin_file ] = $plugin_data;
251 } else {
252 // On the non-network screen, filter out network-only plugins as long as they're not individually active.
253 unset( $plugins['all'][ $plugin_file ] );
254 }
255 } elseif ( ! $screen->in_admin( 'network' ) && is_plugin_active_for_network( $plugin_file ) ) {
256 if ( $show_network_active ) {
257 // On the non-network screen, show network-active plugins if allowed.
258 $plugins['active'][ $plugin_file ] = $plugin_data;
259 } else {
260 // On the non-network screen, filter out network-active plugins.
261 unset( $plugins['all'][ $plugin_file ] );
262 }
263 } elseif ( ( ! $screen->in_admin( 'network' ) && is_plugin_active( $plugin_file ) )
264 || ( $screen->in_admin( 'network' ) && is_plugin_active_for_network( $plugin_file ) ) ) {
265 /*
266 * On the non-network screen, populate the active list with plugins that are individually activated.
267 * On the network admin screen, populate the active list with plugins that are network-activated.
268 */
269 $plugins['active'][ $plugin_file ] = $plugin_data;
270
271 if ( ! $screen->in_admin( 'network' ) && is_plugin_paused( $plugin_file ) ) {
272 $plugins['paused'][ $plugin_file ] = $plugin_data;
273 }
274 } else {
275 if ( isset( $recently_activated[ $plugin_file ] ) ) {
276 // Populate the recently activated list with plugins that have been recently activated.
277 $plugins['recently_activated'][ $plugin_file ] = $plugin_data;
278 }
279 // Populate the inactive list with plugins that aren't activated.
280 $plugins['inactive'][ $plugin_file ] = $plugin_data;
281 }
282
283 if ( $this->show_autoupdates ) {
284 $enabled = in_array( $plugin_file, $auto_updates, true ) && $plugin_data['update-supported'];
285 if ( isset( $plugin_data['auto-update-forced'] ) ) {
286 $enabled = (bool) $plugin_data['auto-update-forced'];
287 }
288
289 if ( $enabled ) {
290 $plugins['auto-update-enabled'][ $plugin_file ] = $plugin_data;
291 } else {
292 $plugins['auto-update-disabled'][ $plugin_file ] = $plugin_data;
293 }
294 }
295 }
296
297 if ( strlen( $s ) ) {
298 $status = 'search';
299 $plugins['search'] = array_filter( $plugins['all'], array( $this, '_search_callback' ) );
300 }
301
302 /**
303 * Filters the array of plugins for the list table.
304 *
305 * @since 6.3.0
306 *
307 * @param array[] $plugins An array of arrays of plugin data, keyed by context.
308 */
309 $plugins = apply_filters( 'plugins_list', $plugins );
310
311 $totals = array();
312 foreach ( $plugins as $type => $list ) {
313 $totals[ $type ] = count( $list );
314 }
315
316 if ( empty( $plugins[ $status ] ) && ! in_array( $status, array( 'all', 'search' ), true ) ) {
317 $status = 'all';
318 }
319
320 $this->items = array();
321 foreach ( $plugins[ $status ] as $plugin_file => $plugin_data ) {
322 // Translate, don't apply markup, sanitize HTML.
323 $this->items[ $plugin_file ] = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, false, true );
324 }
325
326 $total_this_page = $totals[ $status ];
327
328 $js_plugins = array();
329 foreach ( $plugins as $key => $list ) {
330 $js_plugins[ $key ] = array_keys( $list );
331 }
332
333 wp_localize_script(
334 'updates',
335 '_wpUpdatesItemCounts',
336 array(
337 'plugins' => $js_plugins,
338 'totals' => wp_get_update_data(),
339 )
340 );
341
342 if ( ! $orderby ) {
343 $orderby = 'Name';
344 } else {
345 $orderby = ucfirst( $orderby );
346 }
347
348 $order = strtoupper( $order );
349
350 uasort( $this->items, array( $this, '_order_callback' ) );
351
352 $plugins_per_page = $this->get_items_per_page( str_replace( '-', '_', $screen->id . '_per_page' ), 999 );
353
354 $start = ( $page - 1 ) * $plugins_per_page;
355
356 if ( $total_this_page > $plugins_per_page ) {
357 $this->items = array_slice( $this->items, $start, $plugins_per_page );
358 }
359
360 $this->set_pagination_args(
361 array(
362 'total_items' => $total_this_page,
363 'per_page' => $plugins_per_page,
364 )
365 );
366 }
367
368 /**
369 * @global string $s URL encoded search term.
370 *
371 * @param array $plugin
372 * @return bool
373 */
374 public function _search_callback( $plugin ) {
375 global $s;
376
377 foreach ( $plugin as $value ) {
378 if ( is_string( $value ) && false !== stripos( strip_tags( $value ), urldecode( $s ) ) ) {
379 return true;
380 }
381 }
382
383 return false;
384 }
385
386 /**
387 * @global string $orderby
388 * @global string $order
389 * @param array $plugin_a
390 * @param array $plugin_b
391 * @return int
392 */
393 public function _order_callback( $plugin_a, $plugin_b ) {
394 global $orderby, $order;
395
396 $a = $plugin_a[ $orderby ];
397 $b = $plugin_b[ $orderby ];
398
399 if ( $a === $b ) {
400 return 0;
401 }
402
403 if ( 'DESC' === $order ) {
404 return strcasecmp( $b, $a );
405 } else {
406 return strcasecmp( $a, $b );
407 }
408 }
409
410 /**
411 * @global array $plugins
412 */
413 public function no_items() {
414 global $plugins;
415
416 if ( ! empty( $_REQUEST['s'] ) ) {
417 $s = esc_html( urldecode( wp_unslash( $_REQUEST['s'] ) ) );
418
419 /* translators: %s: Plugin search term. */
420 printf( __( 'No plugins found for: %s.' ), '<strong>' . $s . '</strong>' );
421
422 // We assume that somebody who can install plugins in multisite is experienced enough to not need this helper link.
423 if ( ! is_multisite() && current_user_can( 'install_plugins' ) ) {
424 echo ' <a href="' . esc_url( admin_url( 'plugin-install.php?tab=search&s=' . urlencode( $s ) ) ) . '">' . __( 'Search for plugins in the WordPress Plugin Directory.' ) . '</a>';
425 }
426 } elseif ( ! empty( $plugins['all'] ) ) {
427 _e( 'No plugins found.' );
428 } else {
429 _e( 'No plugins are currently available.' );
430 }
431 }
432
433 /**
434 * Displays the search box.
435 *
436 * @since 4.6.0
437 *
438 * @param string $text The 'submit' button label.
439 * @param string $input_id ID attribute value for the search input field.
440 */
441 public function search_box( $text, $input_id ) {
442 if ( empty( $_REQUEST['s'] ) && ! $this->has_items() ) {
443 return;
444 }
445
446 $input_id = $input_id . '-search-input';
447
448 if ( ! empty( $_REQUEST['orderby'] ) ) {
449 echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
450 }
451 if ( ! empty( $_REQUEST['order'] ) ) {
452 echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
453 }
454 ?>
455 <p class="search-box">
456 <label for="<?php echo esc_attr( $input_id ); ?>"><?php echo $text; ?></label>
457 <input type="search" id="<?php echo esc_attr( $input_id ); ?>" class="wp-filter-search" name="s" value="<?php _admin_search_query(); ?>" />
458 <?php submit_button( $text, 'hide-if-js', '', false, array( 'id' => 'search-submit' ) ); ?>
459 </p>
460 <?php
461 }
462
463 /**
464 * @global string $status
465 *
466 * @return string[] Array of column titles keyed by their column name.
467 */
468 public function get_columns() {
469 global $status;
470
471 $columns = array(
472 'cb' => ! in_array( $status, array( 'mustuse', 'dropins' ), true ) ? '<input type="checkbox" />' : '',
473 'name' => __( 'Plugin' ),
474 'description' => __( 'Description' ),
475 );
476
477 if ( $this->show_autoupdates && ! in_array( $status, array( 'mustuse', 'dropins' ), true ) ) {
478 $columns['auto-updates'] = __( 'Automatic Updates' );
479 }
480
481 return $columns;
482 }
483
484 /**
485 * @return array
486 */
487 protected function get_sortable_columns() {
488 return array();
489 }
490
491 /**
492 * @global array $totals
493 * @global string $status
494 * @return array
495 */
496 protected function get_views() {
497 global $totals, $status;
498
499 $status_links = array();
500 foreach ( $totals as $type => $count ) {
501 if ( ! $count ) {
502 continue;
503 }
504
505 switch ( $type ) {
506 case 'all':
507 /* translators: %s: Number of plugins. */
508 $text = _nx(
509 'All <span class="count">(%s)</span>',
510 'All <span class="count">(%s)</span>',
511 $count,
512 'plugins'
513 );
514 break;
515 case 'active':
516 /* translators: %s: Number of plugins. */
517 $text = _n(
518 'Active <span class="count">(%s)</span>',
519 'Active <span class="count">(%s)</span>',
520 $count
521 );
522 break;
523 case 'recently_activated':
524 /* translators: %s: Number of plugins. */
525 $text = _n(
526 'Recently Active <span class="count">(%s)</span>',
527 'Recently Active <span class="count">(%s)</span>',
528 $count
529 );
530 break;
531 case 'inactive':
532 /* translators: %s: Number of plugins. */
533 $text = _n(
534 'Inactive <span class="count">(%s)</span>',
535 'Inactive <span class="count">(%s)</span>',
536 $count
537 );
538 break;
539 case 'mustuse':
540 /* translators: %s: Number of plugins. */
541 $text = _n(
542 'Must-Use <span class="count">(%s)</span>',
543 'Must-Use <span class="count">(%s)</span>',
544 $count
545 );
546 break;
547 case 'dropins':
548 /* translators: %s: Number of plugins. */
549 $text = _n(
550 'Drop-in <span class="count">(%s)</span>',
551 'Drop-ins <span class="count">(%s)</span>',
552 $count
553 );
554 break;
555 case 'paused':
556 /* translators: %s: Number of plugins. */
557 $text = _n(
558 'Paused <span class="count">(%s)</span>',
559 'Paused <span class="count">(%s)</span>',
560 $count
561 );
562 break;
563 case 'upgrade':
564 /* translators: %s: Number of plugins. */
565 $text = _n(
566 'Update Available <span class="count">(%s)</span>',
567 'Update Available <span class="count">(%s)</span>',
568 $count
569 );
570 break;
571 case 'auto-update-enabled':
572 /* translators: %s: Number of plugins. */
573 $text = _n(
574 'Auto-updates Enabled <span class="count">(%s)</span>',
575 'Auto-updates Enabled <span class="count">(%s)</span>',
576 $count
577 );
578 break;
579 case 'auto-update-disabled':
580 /* translators: %s: Number of plugins. */
581 $text = _n(
582 'Auto-updates Disabled <span class="count">(%s)</span>',
583 'Auto-updates Disabled <span class="count">(%s)</span>',
584 $count
585 );
586 break;
587 }
588
589 if ( 'search' !== $type ) {
590 $status_links[ $type ] = array(
591 'url' => add_query_arg( 'plugin_status', $type, 'plugins.php' ),
592 'label' => sprintf( $text, number_format_i18n( $count ) ),
593 'current' => $type === $status,
594 );
595 }
596 }
597
598 return $this->get_views_links( $status_links );
599 }
600
601 /**
602 * @global string $status
603 * @return array
604 */
605 protected function get_bulk_actions() {
606 global $status;
607
608 $actions = array();
609
610 if ( 'active' !== $status ) {
611 $actions['activate-selected'] = $this->screen->in_admin( 'network' ) ? _x( 'Network Activate', 'plugin' ) : _x( 'Activate', 'plugin' );
612 }
613
614 if ( 'inactive' !== $status && 'recent' !== $status ) {
615 $actions['deactivate-selected'] = $this->screen->in_admin( 'network' ) ? _x( 'Network Deactivate', 'plugin' ) : _x( 'Deactivate', 'plugin' );
616 }
617
618 if ( ! is_multisite() || $this->screen->in_admin( 'network' ) ) {
619 if ( current_user_can( 'update_plugins' ) ) {
620 $actions['update-selected'] = __( 'Update' );
621 }
622
623 if ( current_user_can( 'delete_plugins' ) && ( 'active' !== $status ) ) {
624 $actions['delete-selected'] = __( 'Delete' );
625 }
626
627 if ( $this->show_autoupdates ) {
628 if ( 'auto-update-enabled' !== $status ) {
629 $actions['enable-auto-update-selected'] = __( 'Enable Auto-updates' );
630 }
631 if ( 'auto-update-disabled' !== $status ) {
632 $actions['disable-auto-update-selected'] = __( 'Disable Auto-updates' );
633 }
634 }
635 }
636
637 return $actions;
638 }
639
640 /**
641 * @global string $status
642 * @param string $which
643 */
644 public function bulk_actions( $which = '' ) {
645 global $status;
646
647 if ( in_array( $status, array( 'mustuse', 'dropins' ), true ) ) {
648 return;
649 }
650
651 parent::bulk_actions( $which );
652 }
653
654 /**
655 * @global string $status
656 * @param string $which
657 */
658 protected function extra_tablenav( $which ) {
659 global $status;
660
661 if ( ! in_array( $status, array( 'recently_activated', 'mustuse', 'dropins' ), true ) ) {
662 return;
663 }
664
665 echo '<div class="alignleft actions">';
666
667 if ( 'recently_activated' === $status ) {
668 submit_button( __( 'Clear List' ), '', 'clear-recent-list', false );
669 } elseif ( 'top' === $which && 'mustuse' === $status ) {
670 echo '<p>' . sprintf(
671 /* translators: %s: mu-plugins directory name. */
672 __( 'Files in the %s directory are executed automatically.' ),
673 '<code>' . str_replace( ABSPATH, '/', WPMU_PLUGIN_DIR ) . '</code>'
674 ) . '</p>';
675 } elseif ( 'top' === $which && 'dropins' === $status ) {
676 echo '<p>' . sprintf(
677 /* translators: %s: wp-content directory name. */
678 __( 'Drop-ins are single files, found in the %s directory, that replace or enhance WordPress features in ways that are not possible for traditional plugins.' ),
679 '<code>' . str_replace( ABSPATH, '', WP_CONTENT_DIR ) . '</code>'
680 ) . '</p>';
681 }
682 echo '</div>';
683 }
684
685 /**
686 * @return string
687 */
688 public function current_action() {
689 if ( isset( $_POST['clear-recent-list'] ) ) {
690 return 'clear-recent-list';
691 }
692
693 return parent::current_action();
694 }
695
696 /**
697 * Generates the list table rows.
698 *
699 * @since 3.1.0
700 *
701 * @global string $status
702 */
703 public function display_rows() {
704 global $status;
705
706 if ( is_multisite() && ! $this->screen->in_admin( 'network' ) && in_array( $status, array( 'mustuse', 'dropins' ), true ) ) {
707 return;
708 }
709
710 foreach ( $this->items as $plugin_file => $plugin_data ) {
711 $this->single_row( array( $plugin_file, $plugin_data ) );
712 }
713 }
714
715 /**
716 * @global string $status
717 * @global int $page
718 * @global string $s
719 * @global array $totals
720 *
721 * @param array $item
722 */
723 public function single_row( $item ) {
724 global $status, $page, $s, $totals;
725 static $plugin_id_attrs = array();
726
727 list( $plugin_file, $plugin_data ) = $item;
728
729 $plugin_slug = isset( $plugin_data['slug'] ) ? $plugin_data['slug'] : sanitize_title( $plugin_data['Name'] );
730 $plugin_id_attr = $plugin_slug;
731
732 // Ensure the ID attribute is unique.
733 $suffix = 2;
734 while ( in_array( $plugin_id_attr, $plugin_id_attrs, true ) ) {
735 $plugin_id_attr = "$plugin_slug-$suffix";
736 ++$suffix;
737 }
738
739 $plugin_id_attrs[] = $plugin_id_attr;
740
741 $context = $status;
742 $screen = $this->screen;
743
744 // Pre-order.
745 $actions = array(
746 'deactivate' => '',
747 'activate' => '',
748 'details' => '',
749 'delete' => '',
750 );
751
752 // Do not restrict by default.
753 $restrict_network_active = false;
754 $restrict_network_only = false;
755
756 $requires_php = isset( $plugin_data['RequiresPHP'] ) ? $plugin_data['RequiresPHP'] : null;
757 $requires_wp = isset( $plugin_data['RequiresWP'] ) ? $plugin_data['RequiresWP'] : null;
758
759 $compatible_php = is_php_version_compatible( $requires_php );
760 $compatible_wp = is_wp_version_compatible( $requires_wp );
761
762 $has_dependents = WP_Plugin_Dependencies::has_dependents( $plugin_file );
763 $has_active_dependents = WP_Plugin_Dependencies::has_active_dependents( $plugin_file );
764 $has_unmet_dependencies = WP_Plugin_Dependencies::has_unmet_dependencies( $plugin_file );
765 $has_circular_dependency = WP_Plugin_Dependencies::has_circular_dependency( $plugin_file );
766
767 if ( 'mustuse' === $context ) {
768 $is_active = true;
769 } elseif ( 'dropins' === $context ) {
770 $dropins = _get_dropins();
771 $plugin_name = $plugin_file;
772
773 if ( $plugin_file !== $plugin_data['Name'] ) {
774 $plugin_name .= '<br />' . $plugin_data['Name'];
775 }
776
777 if ( true === ( $dropins[ $plugin_file ][1] ) ) { // Doesn't require a constant.
778 $is_active = true;
779 $description = '<p><strong>' . $dropins[ $plugin_file ][0] . '</strong></p>';
780 } elseif ( defined( $dropins[ $plugin_file ][1] ) && constant( $dropins[ $plugin_file ][1] ) ) { // Constant is true.
781 $is_active = true;
782 $description = '<p><strong>' . $dropins[ $plugin_file ][0] . '</strong></p>';
783 } else {
784 $is_active = false;
785 $description = '<p><strong>' . $dropins[ $plugin_file ][0] . ' <span class="error-message">' . __( 'Inactive:' ) . '</span></strong> ' .
786 sprintf(
787 /* translators: 1: Drop-in constant name, 2: wp-config.php */
788 __( 'Requires %1$s in %2$s file.' ),
789 "<code>define('" . $dropins[ $plugin_file ][1] . "', true);</code>",
790 '<code>wp-config.php</code>'
791 ) . '</p>';
792 }
793
794 if ( $plugin_data['Description'] ) {
795 $description .= '<p>' . $plugin_data['Description'] . '</p>';
796 }
797 } else {
798 if ( $screen->in_admin( 'network' ) ) {
799 $is_active = is_plugin_active_for_network( $plugin_file );
800 } else {
801 $is_active = is_plugin_active( $plugin_file );
802 $restrict_network_active = ( is_multisite() && is_plugin_active_for_network( $plugin_file ) );
803 $restrict_network_only = ( is_multisite() && is_network_only_plugin( $plugin_file ) && ! $is_active );
804 }
805
806 if ( $screen->in_admin( 'network' ) ) {
807 if ( $is_active ) {
808 if ( current_user_can( 'manage_network_plugins' ) ) {
809 if ( $has_active_dependents ) {
810 $actions['deactivate'] = __( 'Network Deactivate' ) .
811 '<span class="screen-reader-text">' .
812 __( 'You cannot deactivate this plugin as other plugins require it.' ) .
813 '</span>';
814
815 } else {
816 $deactivate_url = 'plugins.php?action=deactivate' .
817 '&amp;plugin=' . urlencode( $plugin_file ) .
818 '&amp;plugin_status=' . $context .
819 '&amp;paged=' . $page .
820 '&amp;s=' . $s;
821
822 $actions['deactivate'] = sprintf(
823 '<a href="%s" id="deactivate-%s" aria-label="%s">%s</a>',
824 wp_nonce_url( $deactivate_url, 'deactivate-plugin_' . $plugin_file ),
825 esc_attr( $plugin_id_attr ),
826 /* translators: %s: Plugin name. */
827 esc_attr( sprintf( _x( 'Network Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ),
828 _x( 'Network Deactivate', 'plugin' )
829 );
830 }
831 }
832 } else {
833 if ( current_user_can( 'manage_network_plugins' ) ) {
834 if ( $compatible_php && $compatible_wp ) {
835 if ( $has_unmet_dependencies ) {
836 $actions['activate'] = _x( 'Network Activate', 'plugin' ) .
837 '<span class="screen-reader-text">' .
838 __( 'You cannot activate this plugin as it has unmet requirements.' ) .
839 '</span>';
840 } else {
841 $activate_url = 'plugins.php?action=activate' .
842 '&amp;plugin=' . urlencode( $plugin_file ) .
843 '&amp;plugin_status=' . $context .
844 '&amp;paged=' . $page .
845 '&amp;s=' . $s;
846
847 $actions['activate'] = sprintf(
848 '<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>',
849 wp_nonce_url( $activate_url, 'activate-plugin_' . $plugin_file ),
850 esc_attr( $plugin_id_attr ),
851 /* translators: %s: Plugin name. */
852 esc_attr( sprintf( _x( 'Network Activate %s', 'plugin' ), $plugin_data['Name'] ) ),
853 _x( 'Network Activate', 'plugin' )
854 );
855 }
856 } else {
857 $actions['activate'] = sprintf(
858 '<span>%s</span>',
859 _x( 'Cannot Activate', 'plugin' )
860 );
861 }
862 }
863
864 if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) {
865 if ( $has_dependents && ! $has_circular_dependency ) {
866 $actions['delete'] = __( 'Delete' ) .
867 '<span class="screen-reader-text">' .
868 __( 'You cannot delete this plugin as other plugins require it.' ) .
869 '</span>';
870 } else {
871 $delete_url = 'plugins.php?action=delete-selected' .
872 '&amp;checked[]=' . urlencode( $plugin_file ) .
873 '&amp;plugin_status=' . $context .
874 '&amp;paged=' . $page .
875 '&amp;s=' . $s;
876
877 $actions['delete'] = sprintf(
878 '<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>',
879 wp_nonce_url( $delete_url, 'bulk-plugins' ),
880 esc_attr( $plugin_id_attr ),
881 /* translators: %s: Plugin name. */
882 esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ),
883 __( 'Delete' )
884 );
885 }
886 }
887 }
888 } else {
889 if ( $restrict_network_active ) {
890 $actions = array(
891 'network_active' => __( 'Network Active' ),
892 );
893 } elseif ( $restrict_network_only ) {
894 $actions = array(
895 'network_only' => __( 'Network Only' ),
896 );
897 } elseif ( $is_active ) {
898 if ( current_user_can( 'deactivate_plugin', $plugin_file ) ) {
899 if ( $has_active_dependents ) {
900 $actions['deactivate'] = __( 'Deactivate' ) .
901 '<span class="screen-reader-text">' .
902 __( 'You cannot deactivate this plugin as other plugins depend on it.' ) .
903 '</span>';
904 } else {
905 $deactivate_url = 'plugins.php?action=deactivate' .
906 '&amp;plugin=' . urlencode( $plugin_file ) .
907 '&amp;plugin_status=' . $context .
908 '&amp;paged=' . $page .
909 '&amp;s=' . $s;
910
911 $actions['deactivate'] = sprintf(
912 '<a href="%s" id="deactivate-%s" aria-label="%s">%s</a>',
913 wp_nonce_url( $deactivate_url, 'deactivate-plugin_' . $plugin_file ),
914 esc_attr( $plugin_id_attr ),
915 /* translators: %s: Plugin name. */
916 esc_attr( sprintf( _x( 'Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ),
917 __( 'Deactivate' )
918 );
919 }
920 }
921
922 if ( current_user_can( 'resume_plugin', $plugin_file ) && is_plugin_paused( $plugin_file ) ) {
923 $resume_url = 'plugins.php?action=resume' .
924 '&amp;plugin=' . urlencode( $plugin_file ) .
925 '&amp;plugin_status=' . $context .
926 '&amp;paged=' . $page .
927 '&amp;s=' . $s;
928
929 $actions['resume'] = sprintf(
930 '<a href="%s" id="resume-%s" class="resume-link" aria-label="%s">%s</a>',
931 wp_nonce_url( $resume_url, 'resume-plugin_' . $plugin_file ),
932 esc_attr( $plugin_id_attr ),
933 /* translators: %s: Plugin name. */
934 esc_attr( sprintf( _x( 'Resume %s', 'plugin' ), $plugin_data['Name'] ) ),
935 __( 'Resume' )
936 );
937 }
938 } else {
939 if ( current_user_can( 'activate_plugin', $plugin_file ) ) {
940 if ( $compatible_php && $compatible_wp ) {
941 if ( $has_unmet_dependencies ) {
942 $actions['activate'] = _x( 'Activate', 'plugin' ) .
943 '<span class="screen-reader-text">' .
944 __( 'You cannot activate this plugin as it has unmet requirements.' ) .
945 '</span>';
946 } else {
947 $activate_url = 'plugins.php?action=activate' .
948 '&amp;plugin=' . urlencode( $plugin_file ) .
949 '&amp;plugin_status=' . $context .
950 '&amp;paged=' . $page .
951 '&amp;s=' . $s;
952
953 $actions['activate'] = sprintf(
954 '<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>',
955 wp_nonce_url( $activate_url, 'activate-plugin_' . $plugin_file ),
956 esc_attr( $plugin_id_attr ),
957 /* translators: %s: Plugin name. */
958 esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ),
959 _x( 'Activate', 'plugin' )
960 );
961 }
962 } else {
963 $actions['activate'] = sprintf(
964 '<span>%s</span>',
965 _x( 'Cannot Activate', 'plugin' )
966 );
967 }
968 }
969
970 if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) {
971 if ( $has_dependents && ! $has_circular_dependency ) {
972 $actions['delete'] = __( 'Delete' ) .
973 '<span class="screen-reader-text">' .
974 __( 'You cannot delete this plugin as other plugins require it.' ) .
975 '</span>';
976 } else {
977 $delete_url = 'plugins.php?action=delete-selected' .
978 '&amp;checked[]=' . urlencode( $plugin_file ) .
979 '&amp;plugin_status=' . $context .
980 '&amp;paged=' . $page .
981 '&amp;s=' . $s;
982
983 $actions['delete'] = sprintf(
984 '<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>',
985 wp_nonce_url( $delete_url, 'bulk-plugins' ),
986 esc_attr( $plugin_id_attr ),
987 /* translators: %s: Plugin name. */
988 esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ),
989 __( 'Delete' )
990 );
991 }
992 }
993 } // End if $is_active.
994 } // End if $screen->in_admin( 'network' ).
995 } // End if $context.
996
997 $actions = array_filter( $actions );
998
999 if ( $screen->in_admin( 'network' ) ) {
1000
1001 /**
1002 * Filters the action links displayed for each plugin in the Network Admin Plugins list table.
1003 *
1004 * @since 3.1.0
1005 *
1006 * @param string[] $actions An array of plugin action links. By default this can include
1007 * 'activate', 'deactivate', and 'delete'.
1008 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
1009 * @param array $plugin_data An array of plugin data. See get_plugin_data()
1010 * and the {@see 'plugin_row_meta'} filter for the list
1011 * of possible values.
1012 * @param string $context The plugin context. By default this can include 'all',
1013 * 'active', 'inactive', 'recently_activated', 'upgrade',
1014 * 'mustuse', 'dropins', and 'search'.
1015 */
1016 $actions = apply_filters( 'network_admin_plugin_action_links', $actions, $plugin_file, $plugin_data, $context );
1017
1018 /**
1019 * Filters the list of action links displayed for a specific plugin in the Network Admin Plugins list table.
1020 *
1021 * The dynamic portion of the hook name, `$plugin_file`, refers to the path
1022 * to the plugin file, relative to the plugins directory.
1023 *
1024 * @since 3.1.0
1025 *
1026 * @param string[] $actions An array of plugin action links. By default this can include
1027 * 'activate', 'deactivate', and 'delete'.
1028 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
1029 * @param array $plugin_data An array of plugin data. See get_plugin_data()
1030 * and the {@see 'plugin_row_meta'} filter for the list
1031 * of possible values.
1032 * @param string $context The plugin context. By default this can include 'all',
1033 * 'active', 'inactive', 'recently_activated', 'upgrade',
1034 * 'mustuse', 'dropins', and 'search'.
1035 */
1036 $actions = apply_filters( "network_admin_plugin_action_links_{$plugin_file}", $actions, $plugin_file, $plugin_data, $context );
1037
1038 } else {
1039
1040 /**
1041 * Filters the action links displayed for each plugin in the Plugins list table.
1042 *
1043 * @since 2.5.0
1044 * @since 2.6.0 The `$context` parameter was added.
1045 * @since 4.9.0 The 'Edit' link was removed from the list of action links.
1046 *
1047 * @param string[] $actions An array of plugin action links. By default this can include
1048 * 'activate', 'deactivate', and 'delete'. With Multisite active
1049 * this can also include 'network_active' and 'network_only' items.
1050 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
1051 * @param array $plugin_data An array of plugin data. See get_plugin_data()
1052 * and the {@see 'plugin_row_meta'} filter for the list
1053 * of possible values.
1054 * @param string $context The plugin context. By default this can include 'all',
1055 * 'active', 'inactive', 'recently_activated', 'upgrade',
1056 * 'mustuse', 'dropins', and 'search'.
1057 */
1058 $actions = apply_filters( 'plugin_action_links', $actions, $plugin_file, $plugin_data, $context );
1059
1060 /**
1061 * Filters the list of action links displayed for a specific plugin in the Plugins list table.
1062 *
1063 * The dynamic portion of the hook name, `$plugin_file`, refers to the path
1064 * to the plugin file, relative to the plugins directory.
1065 *
1066 * @since 2.7.0
1067 * @since 4.9.0 The 'Edit' link was removed from the list of action links.
1068 *
1069 * @param string[] $actions An array of plugin action links. By default this can include
1070 * 'activate', 'deactivate', and 'delete'. With Multisite active
1071 * this can also include 'network_active' and 'network_only' items.
1072 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
1073 * @param array $plugin_data An array of plugin data. See get_plugin_data()
1074 * and the {@see 'plugin_row_meta'} filter for the list
1075 * of possible values.
1076 * @param string $context The plugin context. By default this can include 'all',
1077 * 'active', 'inactive', 'recently_activated', 'upgrade',
1078 * 'mustuse', 'dropins', and 'search'.
1079 */
1080 $actions = apply_filters( "plugin_action_links_{$plugin_file}", $actions, $plugin_file, $plugin_data, $context );
1081
1082 }
1083
1084 $class = $is_active ? 'active' : 'inactive';
1085 $checkbox_id = 'checkbox_' . md5( $plugin_file );
1086 $disabled = '';
1087
1088 if ( $has_dependents || $has_unmet_dependencies ) {
1089 $disabled = 'disabled';
1090 }
1091
1092 if (
1093 $restrict_network_active ||
1094 $restrict_network_only ||
1095 in_array( $status, array( 'mustuse', 'dropins' ), true ) ||
1096 ! $compatible_php
1097 ) {
1098 $checkbox = '';
1099 } else {
1100 $checkbox = sprintf(
1101 '<label class="label-covers-full-cell" for="%1$s">' .
1102 '<span class="screen-reader-text">%2$s</span></label>' .
1103 '<input type="checkbox" name="checked[]" value="%3$s" id="%1$s" ' . $disabled . '/>',
1104 $checkbox_id,
1105 /* translators: Hidden accessibility text. %s: Plugin name. */
1106 sprintf( __( 'Select %s' ), $plugin_data['Name'] ),
1107 esc_attr( $plugin_file )
1108 );
1109 }
1110
1111 if ( 'dropins' !== $context ) {
1112 $description = '<p>' . ( $plugin_data['Description'] ? $plugin_data['Description'] : '&nbsp;' ) . '</p>';
1113 $plugin_name = $plugin_data['Name'];
1114 }
1115
1116 if (
1117 ! empty( $totals['upgrade'] ) &&
1118 ! empty( $plugin_data['update'] ) ||
1119 ! $compatible_php ||
1120 ! $compatible_wp
1121 ) {
1122 $class .= ' update';
1123 }
1124
1125 $paused = ! $screen->in_admin( 'network' ) && is_plugin_paused( $plugin_file );
1126
1127 if ( $paused ) {
1128 $class .= ' paused';
1129 }
1130
1131 if ( is_uninstallable_plugin( $plugin_file ) ) {
1132 $class .= ' is-uninstallable';
1133 }
1134
1135 printf(
1136 '<tr class="%s" data-slug="%s" data-plugin="%s">',
1137 esc_attr( $class ),
1138 esc_attr( $plugin_slug ),
1139 esc_attr( $plugin_file )
1140 );
1141
1142 list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
1143
1144 $auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
1145
1146 foreach ( $columns as $column_name => $column_display_name ) {
1147 $extra_classes = '';
1148 if ( in_array( $column_name, $hidden, true ) ) {
1149 $extra_classes = ' hidden';
1150 }
1151
1152 switch ( $column_name ) {
1153 case 'cb':
1154 echo "<th scope='row' class='check-column'>$checkbox</th>";
1155 break;
1156 case 'name':
1157 echo "<td class='plugin-title column-primary'><strong>$plugin_name</strong>";
1158 echo $this->row_actions( $actions, true );
1159 echo '</td>';
1160 break;
1161 case 'description':
1162 $classes = 'column-description desc';
1163
1164 echo "<td class='$classes{$extra_classes}'>
1165 <div class='plugin-description'>$description</div>
1166 <div class='$class second plugin-version-author-uri'>";
1167
1168 $plugin_meta = array();
1169
1170 if ( ! empty( $plugin_data['Version'] ) ) {
1171 /* translators: %s: Plugin version number. */
1172 $plugin_meta[] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
1173 }
1174
1175 if ( ! empty( $plugin_data['Author'] ) ) {
1176 $author = $plugin_data['Author'];
1177
1178 if ( ! empty( $plugin_data['AuthorURI'] ) ) {
1179 $author = '<a href="' . $plugin_data['AuthorURI'] . '">' . $plugin_data['Author'] . '</a>';
1180 }
1181
1182 /* translators: %s: Plugin author name. */
1183 $plugin_meta[] = sprintf( __( 'By %s' ), $author );
1184 }
1185
1186 // Details link using API info, if available.
1187 if ( isset( $plugin_data['slug'] ) && current_user_can( 'install_plugins' ) ) {
1188 $plugin_meta[] = sprintf(
1189 '<a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s" data-title="%s">%s</a>',
1190 esc_url(
1191 network_admin_url(
1192 'plugin-install.php?tab=plugin-information&plugin=' . $plugin_data['slug'] .
1193 '&TB_iframe=true&width=600&height=550'
1194 )
1195 ),
1196 /* translators: %s: Plugin name. */
1197 esc_attr( sprintf( __( 'More information about %s' ), $plugin_name ) ),
1198 esc_attr( $plugin_name ),
1199 __( 'View details' )
1200 );
1201 } elseif ( ! empty( $plugin_data['PluginURI'] ) ) {
1202 /* translators: %s: Plugin name. */
1203 $aria_label = sprintf( __( 'Visit plugin site for %s' ), $plugin_name );
1204
1205 $plugin_meta[] = sprintf(
1206 '<a href="%s" aria-label="%s">%s</a>',
1207 esc_url( $plugin_data['PluginURI'] ),
1208 esc_attr( $aria_label ),
1209 __( 'Visit plugin site' )
1210 );
1211 }
1212
1213 /**
1214 * Filters the array of row meta for each plugin in the Plugins list table.
1215 *
1216 * @since 2.8.0
1217 *
1218 * @param string[] $plugin_meta An array of the plugin's metadata, including
1219 * the version, author, author URI, and plugin URI.
1220 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
1221 * @param array $plugin_data {
1222 * An array of plugin data.
1223 *
1224 * @type string $id Plugin ID, e.g. `w.org/plugins/[plugin-name]`.
1225 * @type string $slug Plugin slug.
1226 * @type string $plugin Plugin basename.
1227 * @type string $new_version New plugin version.
1228 * @type string $url Plugin URL.
1229 * @type string $package Plugin update package URL.
1230 * @type string[] $icons An array of plugin icon URLs.
1231 * @type string[] $banners An array of plugin banner URLs.
1232 * @type string[] $banners_rtl An array of plugin RTL banner URLs.
1233 * @type string $requires The version of WordPress which the plugin requires.
1234 * @type string $tested The version of WordPress the plugin is tested against.
1235 * @type string $requires_php The version of PHP which the plugin requires.
1236 * @type string $upgrade_notice The upgrade notice for the new plugin version.
1237 * @type bool $update-supported Whether the plugin supports updates.
1238 * @type string $Name The human-readable name of the plugin.
1239 * @type string $PluginURI Plugin URI.
1240 * @type string $Version Plugin version.
1241 * @type string $Description Plugin description.
1242 * @type string $Author Plugin author.
1243 * @type string $AuthorURI Plugin author URI.
1244 * @type string $TextDomain Plugin textdomain.
1245 * @type string $DomainPath Relative path to the plugin's .mo file(s).
1246 * @type bool $Network Whether the plugin can only be activated network-wide.
1247 * @type string $RequiresWP The version of WordPress which the plugin requires.
1248 * @type string $RequiresPHP The version of PHP which the plugin requires.
1249 * @type string $UpdateURI ID of the plugin for update purposes, should be a URI.
1250 * @type string $Title The human-readable title of the plugin.
1251 * @type string $AuthorName Plugin author's name.
1252 * @type bool $update Whether there's an available update. Default null.
1253 * }
1254 * @param string $status Status filter currently applied to the plugin list. Possible
1255 * values are: 'all', 'active', 'inactive', 'recently_activated',
1256 * 'upgrade', 'mustuse', 'dropins', 'search', 'paused',
1257 * 'auto-update-enabled', 'auto-update-disabled'.
1258 */
1259 $plugin_meta = apply_filters( 'plugin_row_meta', $plugin_meta, $plugin_file, $plugin_data, $status );
1260
1261 echo implode( ' | ', $plugin_meta );
1262
1263 echo '</div>';
1264
1265 if ( $has_dependents ) {
1266 $this->add_dependents_to_dependency_plugin_row( $plugin_file );
1267 }
1268
1269 if ( WP_Plugin_Dependencies::has_dependencies( $plugin_file ) ) {
1270 $this->add_dependencies_to_dependent_plugin_row( $plugin_file );
1271 }
1272
1273 /**
1274 * Fires after plugin row meta.
1275 *
1276 * @since 6.5.0
1277 *
1278 * @param string $plugin_file Refer to {@see 'plugin_row_meta'} filter.
1279 * @param array $plugin_data Refer to {@see 'plugin_row_meta'} filter.
1280 */
1281 do_action( 'after_plugin_row_meta', $plugin_file, $plugin_data );
1282
1283 if ( $paused ) {
1284 $notice_text = __( 'This plugin failed to load properly and is paused during recovery mode.' );
1285
1286 printf( '<p><span class="dashicons dashicons-warning"></span> <strong>%s</strong></p>', $notice_text );
1287
1288 $error = wp_get_plugin_error( $plugin_file );
1289
1290 if ( false !== $error ) {
1291 printf( '<div class="error-display"><p>%s</p></div>', wp_get_extension_error_description( $error ) );
1292 }
1293 }
1294
1295 echo '</td>';
1296 break;
1297 case 'auto-updates':
1298 if ( ! $this->show_autoupdates || in_array( $status, array( 'mustuse', 'dropins' ), true ) ) {
1299 break;
1300 }
1301
1302 echo "<td class='column-auto-updates{$extra_classes}'>";
1303
1304 $html = array();
1305
1306 if ( isset( $plugin_data['auto-update-forced'] ) ) {
1307 if ( $plugin_data['auto-update-forced'] ) {
1308 // Forced on.
1309 $text = __( 'Auto-updates enabled' );
1310 } else {
1311 $text = __( 'Auto-updates disabled' );
1312 }
1313 $action = 'unavailable';
1314 $time_class = ' hidden';
1315 } elseif ( empty( $plugin_data['update-supported'] ) ) {
1316 $text = '';
1317 $action = 'unavailable';
1318 $time_class = ' hidden';
1319 } elseif ( in_array( $plugin_file, $auto_updates, true ) ) {
1320 $text = __( 'Disable auto-updates' );
1321 $action = 'disable';
1322 $time_class = '';
1323 } else {
1324 $text = __( 'Enable auto-updates' );
1325 $action = 'enable';
1326 $time_class = ' hidden';
1327 }
1328
1329 $query_args = array(
1330 'action' => "{$action}-auto-update",
1331 'plugin' => $plugin_file,
1332 'paged' => $page,
1333 'plugin_status' => $status,
1334 );
1335
1336 $url = add_query_arg( $query_args, 'plugins.php' );
1337
1338 if ( 'unavailable' === $action ) {
1339 $html[] = '<span class="label">' . $text . '</span>';
1340 } else {
1341 $html[] = sprintf(
1342 '<a href="%s" class="toggle-auto-update aria-button-if-js" data-wp-action="%s">',
1343 wp_nonce_url( $url, 'updates' ),
1344 $action
1345 );
1346
1347 $html[] = '<span class="dashicons dashicons-update spin hidden" aria-hidden="true"></span>';
1348 $html[] = '<span class="label">' . $text . '</span>';
1349 $html[] = '</a>';
1350 }
1351
1352 if ( ! empty( $plugin_data['update'] ) ) {
1353 $html[] = sprintf(
1354 '<div class="auto-update-time%s">%s</div>',
1355 $time_class,
1356 wp_get_auto_update_message()
1357 );
1358 }
1359
1360 $html = implode( '', $html );
1361
1362 /**
1363 * Filters the HTML of the auto-updates setting for each plugin in the Plugins list table.
1364 *
1365 * @since 5.5.0
1366 *
1367 * @param string $html The HTML of the plugin's auto-update column content,
1368 * including toggle auto-update action links and
1369 * time to next update.
1370 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
1371 * @param array $plugin_data An array of plugin data. See get_plugin_data()
1372 * and the {@see 'plugin_row_meta'} filter for the list
1373 * of possible values.
1374 */
1375 echo apply_filters( 'plugin_auto_update_setting_html', $html, $plugin_file, $plugin_data );
1376
1377 wp_admin_notice(
1378 '',
1379 array(
1380 'type' => 'error',
1381 'additional_classes' => array( 'notice-alt', 'inline', 'hidden' ),
1382 )
1383 );
1384
1385 echo '</td>';
1386
1387 break;
1388 default:
1389 $classes = "$column_name column-$column_name $class";
1390
1391 echo "<td class='$classes{$extra_classes}'>";
1392
1393 /**
1394 * Fires inside each custom column of the Plugins list table.
1395 *
1396 * @since 3.1.0
1397 *
1398 * @param string $column_name Name of the column.
1399 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
1400 * @param array $plugin_data An array of plugin data. See get_plugin_data()
1401 * and the {@see 'plugin_row_meta'} filter for the list
1402 * of possible values.
1403 */
1404 do_action( 'manage_plugins_custom_column', $column_name, $plugin_file, $plugin_data );
1405
1406 echo '</td>';
1407 }
1408 }
1409
1410 echo '</tr>';
1411
1412 if ( ! $compatible_php || ! $compatible_wp ) {
1413 printf(
1414 '<tr class="plugin-update-tr"><td colspan="%s" class="plugin-update colspanchange">',
1415 esc_attr( $this->get_column_count() )
1416 );
1417
1418 $incompatible_message = '';
1419 if ( ! $compatible_php && ! $compatible_wp ) {
1420 $incompatible_message .= __( 'This plugin does not work with your versions of WordPress and PHP.' );
1421 if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
1422 $incompatible_message .= sprintf(
1423 /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
1424 ' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
1425 self_admin_url( 'update-core.php' ),
1426 esc_url( wp_get_update_php_url() )
1427 );
1428 $incompatible_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
1429 } elseif ( current_user_can( 'update_core' ) ) {
1430 $incompatible_message .= sprintf(
1431 /* translators: %s: URL to WordPress Updates screen. */
1432 ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
1433 self_admin_url( 'update-core.php' )
1434 );
1435 } elseif ( current_user_can( 'update_php' ) ) {
1436 $incompatible_message .= sprintf(
1437 /* translators: %s: URL to Update PHP page. */
1438 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
1439 esc_url( wp_get_update_php_url() )
1440 );
1441 $incompatible_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
1442 }
1443 } elseif ( ! $compatible_wp ) {
1444 $incompatible_message .= __( 'This plugin does not work with your version of WordPress.' );
1445 if ( current_user_can( 'update_core' ) ) {
1446 $incompatible_message .= sprintf(
1447 /* translators: %s: URL to WordPress Updates screen. */
1448 ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
1449 self_admin_url( 'update-core.php' )
1450 );
1451 }
1452 } elseif ( ! $compatible_php ) {
1453 $incompatible_message .= __( 'This plugin does not work with your version of PHP.' );
1454 if ( current_user_can( 'update_php' ) ) {
1455 $incompatible_message .= sprintf(
1456 /* translators: %s: URL to Update PHP page. */
1457 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
1458 esc_url( wp_get_update_php_url() )
1459 );
1460 $incompatible_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
1461 }
1462 }
1463
1464 wp_admin_notice(
1465 $incompatible_message,
1466 array(
1467 'type' => 'error',
1468 'additional_classes' => array( 'notice-alt', 'inline', 'update-message' ),
1469 )
1470 );
1471
1472 echo '</td></tr>';
1473 }
1474
1475 /**
1476 * Fires after each row in the Plugins list table.
1477 *
1478 * @since 2.3.0
1479 * @since 5.5.0 Added 'auto-update-enabled' and 'auto-update-disabled'
1480 * to possible values for `$status`.
1481 *
1482 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
1483 * @param array $plugin_data An array of plugin data. See get_plugin_data()
1484 * and the {@see 'plugin_row_meta'} filter for the list
1485 * of possible values.
1486 * @param string $status Status filter currently applied to the plugin list.
1487 * Possible values are: 'all', 'active', 'inactive',
1488 * 'recently_activated', 'upgrade', 'mustuse', 'dropins',
1489 * 'search', 'paused', 'auto-update-enabled', 'auto-update-disabled'.
1490 */
1491 do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status );
1492
1493 /**
1494 * Fires after each specific row in the Plugins list table.
1495 *
1496 * The dynamic portion of the hook name, `$plugin_file`, refers to the path
1497 * to the plugin file, relative to the plugins directory.
1498 *
1499 * @since 2.7.0
1500 * @since 5.5.0 Added 'auto-update-enabled' and 'auto-update-disabled'
1501 * to possible values for `$status`.
1502 *
1503 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
1504 * @param array $plugin_data An array of plugin data. See get_plugin_data()
1505 * and the {@see 'plugin_row_meta'} filter for the list
1506 * of possible values.
1507 * @param string $status Status filter currently applied to the plugin list.
1508 * Possible values are: 'all', 'active', 'inactive',
1509 * 'recently_activated', 'upgrade', 'mustuse', 'dropins',
1510 * 'search', 'paused', 'auto-update-enabled', 'auto-update-disabled'.
1511 */
1512 do_action( "after_plugin_row_{$plugin_file}", $plugin_file, $plugin_data, $status );
1513 }
1514
1515 /**
1516 * Gets the name of the primary column for this specific list table.
1517 *
1518 * @since 4.3.0
1519 *
1520 * @return string Unalterable name for the primary column, in this case, 'name'.
1521 */
1522 protected function get_primary_column_name() {
1523 return 'name';
1524 }
1525
1526 /**
1527 * Prints a list of other plugins that depend on the plugin.
1528 *
1529 * @since 6.5.0
1530 *
1531 * @param string $dependency The dependency's filepath, relative to the plugins directory.
1532 */
1533 protected function add_dependents_to_dependency_plugin_row( $dependency ) {
1534 $dependent_names = WP_Plugin_Dependencies::get_dependent_names( $dependency );
1535
1536 if ( empty( $dependent_names ) ) {
1537 return;
1538 }
1539
1540 $dependency_note = __( 'Note: This plugin cannot be deactivated or deleted until the plugins that require it are deactivated or deleted.' );
1541
1542 $comma = wp_get_list_item_separator();
1543 $required_by = sprintf(
1544 /* translators: %s: List of dependencies. */
1545 __( '<strong>Required by:</strong> %s' ),
1546 implode( $comma, $dependent_names )
1547 );
1548
1549 printf(
1550 '<div class="required-by"><p>%1$s</p><p>%2$s</p></div>',
1551 $required_by,
1552 $dependency_note
1553 );
1554 }
1555
1556 /**
1557 * Prints a list of other plugins that the plugin depends on.
1558 *
1559 * @since 6.5.0
1560 *
1561 * @param string $dependent The dependent plugin's filepath, relative to the plugins directory.
1562 */
1563 protected function add_dependencies_to_dependent_plugin_row( $dependent ) {
1564 $dependency_names = WP_Plugin_Dependencies::get_dependency_names( $dependent );
1565
1566 if ( array() === $dependency_names ) {
1567 return;
1568 }
1569
1570 $links = array();
1571 foreach ( $dependency_names as $slug => $name ) {
1572 $links[] = $this->get_dependency_view_details_link( $name, $slug );
1573 }
1574
1575 $is_active = is_multisite() ? is_plugin_active_for_network( $dependent ) : is_plugin_active( $dependent );
1576 $comma = wp_get_list_item_separator();
1577 $requires = sprintf(
1578 /* translators: %s: List of dependency names. */
1579 __( '<strong>Requires:</strong> %s' ),
1580 implode( $comma, $links )
1581 );
1582
1583 $notice = '';
1584 $error_message = '';
1585 if ( WP_Plugin_Dependencies::has_unmet_dependencies( $dependent ) ) {
1586 if ( $is_active ) {
1587 $error_message = __( 'This plugin is active but may not function correctly because required plugins are missing or inactive.' );
1588 } else {
1589 $error_message = __( 'This plugin cannot be activated because required plugins are missing or inactive.' );
1590 }
1591 $notice = wp_get_admin_notice(
1592 $error_message,
1593 array(
1594 'type' => 'error',
1595 'additional_classes' => array( 'inline', 'notice-alt' ),
1596 )
1597 );
1598 }
1599
1600 printf(
1601 '<div class="requires"><p>%1$s</p>%2$s</div>',
1602 $requires,
1603 $notice
1604 );
1605 }
1606
1607 /**
1608 * Returns a 'View details' like link for a dependency.
1609 *
1610 * @since 6.5.0
1611 *
1612 * @param string $name The dependency's name.
1613 * @param string $slug The dependency's slug.
1614 * @return string A 'View details' link for the dependency.
1615 */
1616 protected function get_dependency_view_details_link( $name, $slug ) {
1617 $dependency_data = WP_Plugin_Dependencies::get_dependency_data( $slug );
1618
1619 if ( false === $dependency_data
1620 || $name === $slug
1621 || $name !== $dependency_data['name']
1622 || empty( $dependency_data['version'] )
1623 ) {
1624 return $name;
1625 }
1626
1627 return $this->get_view_details_link( $name, $slug );
1628 }
1629
1630 /**
1631 * Returns a 'View details' link for the plugin.
1632 *
1633 * @since 6.5.0
1634 *
1635 * @param string $name The plugin's name.
1636 * @param string $slug The plugin's slug.
1637 * @return string A 'View details' link for the plugin.
1638 */
1639 protected function get_view_details_link( $name, $slug ) {
1640 $url = add_query_arg(
1641 array(
1642 'tab' => 'plugin-information',
1643 'plugin' => $slug,
1644 'TB_iframe' => 'true',
1645 'width' => '600',
1646 'height' => '550',
1647 ),
1648 network_admin_url( 'plugin-install.php' )
1649 );
1650
1651 $name_attr = esc_attr( $name );
1652 return sprintf(
1653 "<a href='%s' class='thickbox open-plugin-details-modal' aria-label='%s' data-title='%s'>%s</a>",
1654 esc_url( $url ),
1655 /* translators: %s: Plugin name. */
1656 sprintf( __( 'More information about %s' ), $name_attr ),
1657 $name_attr,
1658 esc_html( $name )
1659 );
1660 }
1661}
1662
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1