PluginProbe
Plugin Report / 1.7
Plugin Report v1.7
2.2.4 trunk 1.1 1.2 1.3 1.4 1.5 1.6 1.6.1 1.7 1.8 1.8.1 1.8.2 1.8.3 1.9 1.9.1 1.9.2 1.9.3 2.0.0 2.0.1 2.0.2 2.1 2.1.1 2.2.0 2.2.1 All 27 releases
← All changes | rt-plugin-report.php +75 -244 2.2.01.7 View file →
@@ -1,14 +1,14 @@
1 1 <?php
2 2 /**
3 3 * Plugin Name: Plugin Report
4 - * Plugin URI: https://wordpress.org/plugins/plugin-report/
4 + * Plugin URI: https://roytanck.com/?p=277
5 5 * Description: Provides detailed information about currently installed plugins
6 - * Version: 2.2.0
6 + * Version: 1.7
7 7 * Requires at least: 4.6
8 8 * Requires PHP: 5.6
9 - * Author: Torsten Landsiedel
10 - * Author URI: https://torstenlandsiedel.de
9 + * Author: Roy Tanck
10 + * Author URI: https://roytanck.com
11 11 * License: GPLv3
12 12 * Network: true
13 13 */
14 14
@@ -19,11 +19,8 @@
19 19
20 20
21 21 if ( is_admin() && ! class_exists( 'RT_Plugin_Report' ) ) {
22 22
23 - /**
24 - * Plugin Report main class.
25 - */
26 23 class RT_Plugin_Report {
27 24
28 25 // CSS class constants.
29 26 const CSS_CLASS_LOW = 'pr-risk-low';
@@ -30,10 +27,10 @@
30 27 const CSS_CLASS_MED = 'pr-risk-medium';
31 28 const CSS_CLASS_HIGH = 'pr-risk-high';
32 29
33 30 // Other class constants.
34 - const PLUGIN_VERSION = '2.2.0';
35 - const COLS_PER_ROW = 9;
31 + const PLUGIN_VERSION = '1.7';
32 + const COLS_PER_ROW = 7;
36 33 const CACHE_LIFETIME = DAY_IN_SECONDS;
37 34 const CACHE_LIFETIME_NOREPO = WEEK_IN_SECONDS;
38 35
39 36 /**
@@ -69,9 +66,9 @@
69 66 public function register_settings_page() {
70 67 add_plugins_page(
71 68 esc_html_x( 'Plugin Report', 'Page and menu title', 'plugin-report' ),
72 69 esc_html_x( 'Plugin Report', 'Page and menu title', 'plugin-report' ),
73 - is_multisite() ? 'manage_sites' : 'manage_options',
70 + 'manage_options',
74 71 'plugin_report',
75 72 array( $this, 'settings_page' )
76 73 );
77 74 }
@@ -107,9 +104,9 @@
107 104 echo '<h1>' . esc_html_x( 'Plugin Report', 'Page and menu title', 'plugin-report' ) . '</h1>';
108 105 echo '<p>';
109 106 $version_temp = '<span class="' . $this->get_version_risk_classname( $wp_version, $wp_latest ) . '">' . $wp_version . '</span>';
110 107 /* translators: %1$s: Current WordPress version number, %2$s: Current PHP version number */
111 - echo sprintf( esc_html__( 'Currently running WordPress version %1$s and PHP version %2$s.', 'plugin-report' ), $version_temp, phpversion() );
108 + echo sprintf( __( 'Currently running WordPress version %1$s and PHP version %2$s.', 'plugin-report' ), $version_temp, phpversion() );
112 109 if ( version_compare( $wp_version, $wp_latest, '<' ) ) {
113 110 /* translators: %s = Available new version number */
114 111 echo sprintf( ' (' . esc_html__( 'An upgrade to %s is available', 'plugin-report' ) . ')', $wp_latest );
115 112 }
@@ -120,23 +117,22 @@
120 117 $page_url = 'network/plugins.php?page=plugin_report';
121 118 } else {
122 119 $page_url = 'plugins.php?page=plugin_report';
123 120 }
124 - echo '<a href="' . esc_attr( admin_url( $page_url . '&clear_cache=' . current_time( 'timestamp' ) ) ) . '">' . esc_html__( 'Clear cached plugin data and reload', 'plugin-report' ) . '</a>';
121 + echo '<a href="' . admin_url( $page_url . '&clear_cache=' . current_time( 'timestamp' ) ) . '">' . esc_html__( 'Clear cached plugin data and reload', 'plugin-report' ) . '</a>';
125 122 echo '</p>';
126 - echo '<h2>' . esc_html__( 'Currently installed plugins', 'plugin-report' ) . '</h2>';
123 + echo '<h3>' . esc_html__( 'Currently installed plugins', 'plugin-report' ) . '</h3>';
127 124 echo '<p id="plugin-report-progress"></p>';
125 + echo '<p>';
128 126
129 127 // The report's main table.
130 128 echo '<table id="plugin-report-table" class="wp-list-table widefat fixed striped">';
131 129 echo '<thead>';
132 130 echo '<tr>';
133 - echo '<th data-sort-default>' . esc_html__( 'Name', 'plugin-report' ) . '</th>';
131 + echo '<th>' . esc_html__( 'Name', 'plugin-report' ) . '</th>';
134 132 echo '<th>' . esc_html__( 'Author', 'plugin-report' ) . '</th>';
135 - echo '<th>' . esc_html__( 'Repository', 'plugin-report' ) . '</th>';
136 133 echo '<th>' . esc_html__( 'Activated', 'plugin-report' ) . '</th>';
137 134 echo '<th data-sort-method="none" class="no-sort">' . esc_html__( 'Installed version', 'plugin-report' ) . '</th>';
138 - echo '<th>' . esc_html__( 'Auto-update', 'plugin-report' ) . '</th>';
139 135 echo '<th>' . esc_html__( 'Last update', 'plugin-report' ) . '</th>';
140 136 echo '<th data-sort-method="dotsep">' . esc_html__( 'Tested up to WP version', 'plugin-report' ) . '</th>';
141 137 echo '<th data-sort-method="number">' . esc_html__( 'Rating', 'plugin-report' ) . '</th>';
142 138 echo '</tr>';
@@ -151,14 +147,15 @@
151 147 // Use the cached report to create a table row.
152 148 echo $this->render_table_row( $cache );
153 149 } else {
154 150 // Render a special table row that's used as a signal to the front-end js that new data is needed.
155 - echo '<tr class="plugin-report-row-temp-' . esc_attr( $slug ) . '"><td colspan="' . (int) self::COLS_PER_ROW . '">' . esc_html__( 'Loading...', 'plugin-report' ) . '</td></tr>';
151 + echo '<tr class="plugin-report-row-temp-' . $slug . '"><td colspan="' . self::COLS_PER_ROW . '">' . esc_html__( 'Loading...', 'plugin-report' ) . '</td></tr>';
156 152 }
157 153 }
158 154
159 155 echo '</tbody>';
160 156 echo '</table>';
157 + echo '</p>';
161 158
162 159 echo '<p id="plugin-report-buttons"></p>';
163 160
164 161 // Wrap up.
@@ -167,10 +164,8 @@
167 164
168 165
169 166 /**
170 167 * Enqueue admin javascript
171 - *
172 - * @param string $hook Screen hook.
173 168 */
174 169 public function enqueue_assets( $hook ) {
175 170 // Check if we're on the right screen.
176 171 if ( 'plugins_page_plugin_report' !== $hook ) {
@@ -177,11 +172,11 @@
177 172 return;
178 173 }
179 174 // Register the plugin's admin js, and require jquery.
180 175 wp_enqueue_script( 'plugin-report-js', plugins_url( '/js/plugin-report.js', __FILE__ ), array( 'jquery', 'plugin-report-tablesort-js' ), self::PLUGIN_VERSION );
181 - wp_enqueue_script( 'plugin-report-tablesort-js', plugins_url( '/js/tablesort.min.js', __FILE__ ), array( 'jquery' ), '5.6.0' );
182 - wp_enqueue_script( 'plugin-report-tablesort-number-js', plugins_url( '/js/tablesort.number.min.js', __FILE__ ), array( 'plugin-report-tablesort-js' ), '5.6.0' );
183 - wp_enqueue_script( 'plugin-report-tablesort-dotsep-js', plugins_url( '/js/tablesort.dotsep.min.js', __FILE__ ), array( 'plugin-report-tablesort-js' ), '5.6.0' );
176 + wp_enqueue_script( 'plugin-report-tablesort-js', plugins_url( '/js/tablesort.min.js', __FILE__ ), array( 'jquery' ), '5.1.0' );
177 + wp_enqueue_script( 'plugin-report-tablesort-number-js', plugins_url( '/js/tablesort.number.min.js', __FILE__ ), array( 'plugin-report-tablesort-js' ), '5.1.0' );
178 + wp_enqueue_script( 'plugin-report-tablesort-dotsep-js', plugins_url( '/js/tablesort.dotsep.min.js', __FILE__ ), array( 'plugin-report-tablesort-js' ), '5.1.0' );
184 179 // Add some variables to the page, to be used by the javascript.
185 180 $slugs = $this->get_plugin_slugs();
186 181 $slugs_str = implode( ',', $slugs );
187 182 $vars = array(
@@ -210,11 +205,9 @@
210 205 }
211 206
212 207
213 208 /**
214 - * Convert a plugin's file path into its slug.
215 - *
216 - * @param string $file Plugin file path.
209 + * Convert a plugin's file path into its slug
217 210 */
218 211 private function get_plugin_slug( $file ) {
219 212 if ( strpos( $file, '/' ) !== false ) {
220 213 $parts = explode( '/', $file );
@@ -242,16 +235,12 @@
242 235 }
243 236
244 237 // Check if get_plugins() function exists.
245 238 if ( ! function_exists( 'plugins_api' ) ) {
246 - require_once get_home_path() . 'wp-admin/includes/plugin-install.php';
239 + require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
247 240 }
248 241
249 - if ( isset( $_POST['slug'] ) ) {
250 - $slug = sanitize_title( wp_unslash( $_POST['slug'] ) );
251 - } else {
252 - $slug = ''; // Set value to an empty string.
253 - }
242 + $slug = sanitize_title( $_POST['slug'] );
254 243
255 244 $report = $this->assemble_plugin_report( $slug );
256 245
257 246 if ( $report ) {
@@ -273,19 +262,16 @@
273 262
274 263
275 264 /**
276 265 * Gather all the info we can get about a plugin.
277 - * Uses transient caching to avoid doing repo API calls on every page visit.
278 - *
279 - * @param string $slug Plugin slug.
266 + * Uses transient caching to avoid doing repo API calls on every page visit
280 267 */
281 268 private function assemble_plugin_report( $slug ) {
282 269 if ( ! empty( $slug ) ) {
283 - $report = array();
284 - $cache_key = $this->create_cache_key( $slug );
285 - $cache = get_site_transient( $cache_key );
286 - $plugins = get_plugins();
287 - $auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
270 + $report = array();
271 + $cache_key = $this->create_cache_key( $slug );
272 + $cache = get_site_transient( $cache_key );
273 + $plugins = get_plugins();
288 274
289 275 if ( empty( $cache ) ) {
290 276
291 277 // Add the plugin's slug to the report.
@@ -290,39 +276,13 @@
290 276
291 277 // Add the plugin's slug to the report.
292 278 $report['slug'] = $slug;
293 279
294 - // Get the locally available info, and add it to the report.
280 + // Get the locally available info, and add it to the report.
295 281 foreach ( $plugins as $key => $plugin ) {
296 - if ( $this->get_plugin_slug( $key ) === $slug ) {
297 -
298 - // Translate plugin data.
299 - $textdomain = $plugin['TextDomain'];
300 - if ( $textdomain ) {
301 - if ( ! is_textdomain_loaded( $textdomain ) ) {
302 - if ( $plugin['DomainPath'] ) {
303 - load_plugin_textdomain( $textdomain, false, dirname( $key ) . $plugin['DomainPath'] );
304 - } else {
305 - load_plugin_textdomain( $textdomain, false, dirname( $key ) );
306 - }
307 - }
308 - } elseif ( 'hello.php' === basename( $key ) ) {
309 - $textdomain = 'default';
310 - }
311 - if ( $textdomain ) {
312 - foreach ( array( 'Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version' ) as $field ) {
313 - // phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain
314 - $plugin[ $field ] = translate( $plugin[ $field ], $textdomain );
315 - }
316 - }
317 -
318 - $report['local_info'] = $plugin;
319 - $report['file_path'] = $key;
320 - $report['auto-update'] = in_array( $key, $auto_updates, true );
321 -
322 - // Change any whitespace to default space.
323 - $report['local_info']['Name'] = preg_replace( '/\s+/u', ' ', $report['local_info']['Name'] );
324 -
282 + if ( $this->get_plugin_slug( $key ) == $slug ) {
283 + $report['local_info'] = $plugin;
284 + $report['file_path'] = $key;
325 285 break;
326 286 }
327 287 }
328 288
@@ -340,31 +300,21 @@
340 300 'compatibility' => true,
341 301 'author' => true,
342 302 ),
343 303 );
304 + $returned_object = plugins_api( 'plugin_information', $args );
344 305
345 - // Check wordpress.org only if "Update URI" plugin header is not set or set to wordpress.org.
346 - $parsed_repo_url = wp_parse_url( $report['local_info']['UpdateURI'] );
347 - $repo_host = isset( $parsed_repo_url['host'] ) ? $parsed_repo_url['host'] : null;
348 - if ( empty( $repo_host ) || strtolower( $repo_host ) === 'w.org' || strtolower( $repo_host ) === 'wordpress.org' ) {
349 - $returned_object = plugins_api( 'plugin_information', $args );
350 - }
351 -
352 306 // Add the repo info to the report.
353 - if ( isset( $returned_object ) ) {
354 - if ( ! is_wp_error( $returned_object ) ) {
355 - $report['repo_info'] = $returned_object;
356 - // Cache the report.
357 - set_site_transient( $cache_key, $report, self::CACHE_LIFETIME );
358 - } else {
359 - // Store the error code and message in the report.
360 - $report['repo_error_code'] = $returned_object->get_error_code();
361 - $report['repo_error_message'] = $returned_object->get_error_message();
362 - // Because the plugin is not found in the wordpress.org repo, check if it exists in SVN.
363 - $report['exists_in_svn'] = $this->check_exists_in_svn( $slug );
364 - // Cache for an extra long time when the plugin is not in the repo.
365 - set_site_transient( $cache_key, $report, self::CACHE_LIFETIME_NOREPO );
366 - }
307 + if ( ! is_wp_error( $returned_object ) ) {
308 + $report['repo_info'] = maybe_unserialize( $returned_object );
309 + // Cache the report.
310 + set_site_transient( $cache_key, $report, self::CACHE_LIFETIME );
311 + } else {
312 + // Store the error code and message in the report.
313 + $report['repo_error_code'] = $returned_object->get_error_code();
314 + $report['repo_error_message'] = $returned_object->get_error_message();
315 + // Cache for an extra long time when the plugin is not in the repo.
316 + set_site_transient( $cache_key, $report, self::CACHE_LIFETIME_NOREPO );
367 317 }
368 318 } else {
369 319 $report = $cache;
370 320 }
@@ -378,52 +328,19 @@
378 328 }
379 329
380 330
381 331 /**
382 - * Check if the plugin is present in WordPress's SVN repository.
383 - *
384 - * Function adapted from the 'Enhanced Plugin Admin' plugin by Marios Alexandrou.
385 - * See: https://plugins.trac.wordpress.org/browser/enhanced-plugin-admin/trunk/enhanced-plugin-admin.php
386 - *
387 - * @param string $slug The plugin's slug.
388 - *
389 - * @return boolean True if found, false if not.
332 + * From a report, generate an HTML table row with relevant data for the plugin
390 333 */
391 - private function check_exists_in_svn( $slug ) {
392 - // Attempt to load the plugin's SVN repo page.
393 - $response = wp_remote_get( 'http://svn.wp-plugins.org/' . $slug . '/' );
394 - // If the return value was a WP_Error, assume the answer is no.
395 - if ( is_wp_error( $response ) ) {
396 - return false;
397 - } else {
398 - // If the returned HTTP code is 200, the page was found, so return true.
399 - $response_code = wp_remote_retrieve_response_code( $response );
400 - if ( 200 === $response_code ) {
401 - return true;
402 - }
403 - }
404 - // In all other cases, assume the plugin was not found.
405 - return false;
406 - }
407 -
408 -
409 - /**
410 - * From a report, generate an HTML table row with relevant data for the plugin.
411 - *
412 - * @param array|false $report Report of plugin.
413 - */
414 334 private function render_table_row( $report ) {
415 - // Get the current WP version number.
416 - global $wp_version;
417 335 // Get the latest WP release version number.
418 336 $wp_latest = $this->check_core_updates();
419 337 // Check if the report is valid.
420 - if ( false === $report ) {
338 + if ( $report == null ) {
421 339 $html = $this->render_error_row( esc_html__( 'No plugin data available.', 'plugin-report' ) );
422 340 } else {
423 341 // Start the new table row.
424 342 $html = '<tr class="plugin-report-row-' . $report['slug'] . '">';
425 -
426 343 // Name.
427 344 if ( isset( $report['local_info']['PluginURI'] ) && ! empty( $report['local_info']['PluginURI'] ) ) {
428 345 $html .= '<td><a href="' . $report['local_info']['PluginURI'] . '"><strong>' . $report['local_info']['Name'] . '</strong></a></td>';
429 346 } else {
@@ -428,9 +345,8 @@
428 345 $html .= '<td><a href="' . $report['local_info']['PluginURI'] . '"><strong>' . $report['local_info']['Name'] . '</strong></a></td>';
429 346 } else {
430 347 $html .= '<td><strong>' . $report['local_info']['Name'] . '</strong></td>';
431 348 }
432 -
433 349 // Author.
434 350 if ( isset( $report['local_info']['AuthorURI'] ) && ! empty( $report['local_info']['AuthorURI'] ) ) {
435 351 $html .= '<td><a href="' . $report['local_info']['AuthorURI'] . '">' . $report['local_info']['Author'] . '</a></td>';
436 352 } else {
@@ -435,55 +351,19 @@
435 351 $html .= '<td><a href="' . $report['local_info']['AuthorURI'] . '">' . $report['local_info']['Author'] . '</a></td>';
436 352 } else {
437 353 $html .= '<td>' . $report['local_info']['Author'] . '</td>';
438 354 }
439 -
440 - // Repository.
441 - if ( isset( $report['local_info']['UpdateURI'] ) ) {
442 - // Parse the UpdateURI's value to get the host.
443 - $parsed_repo_url = wp_parse_url( $report['local_info']['UpdateURI'] );
444 - // If the URI is valid, extract the host, otherwise we'll use the header value.
445 - $repo_host = isset( $parsed_repo_url['host'] ) ? $parsed_repo_url['host'] : $report['local_info']['UpdateURI'];
446 - // Check if the plugin is supposed to be hosted on wp.org.
447 - if ( empty( $repo_host ) || strtolower( $repo_host ) === 'w.org' || strtolower( $repo_host ) === 'wordpress.org' ) {
448 - // Plugin should be available on wp.org, check if we got a 'not found' error.
449 - if ( isset( $report['repo_error_code'] ) && $report['repo_error_code'] === 'plugins_api_failed' ) {
450 - // Plugin is not available in the wp.org repo.
451 - if ( isset( $report['exists_in_svn'] ) && $report['exists_in_svn'] === true ) {
452 - $html .= '<td class="' . self::CSS_CLASS_HIGH . '">' . __( 'wordpress.org, plugin closed', 'plugin-report' ) . '</td>';
453 - } else {
454 - $html .= '<td class="' . self::CSS_CLASS_HIGH . '">' . __( 'wordpress.org, plugin not found', 'plugin-report' ) . '</td>';
455 - }
456 - } else {
457 - // Plugin is available on wp.org.
458 - $html .= '<td class="' . self::CSS_CLASS_LOW . '">wordpress.org</td>';
459 - }
460 - } else {
461 - if ( $parsed_repo_url && isset( $parsed_repo_url['host'] ) ) {
462 - // Update URI is a valid URL, display the host.
463 - $html .= '<td class="' . self::CSS_CLASS_MED . '">' . $repo_host . '</td>';
464 - } else {
465 - // Some other value (like 'false'), so assume updates are disabled.
466 - $html .= '<td class="' . self::CSS_CLASS_MED . '">' . __( 'Updates disabled', 'plugin-report' ) . '</td>';
467 - }
468 - }
469 - } elseif ( version_compare( $wp_version, '5.8', '<' ) ) {
470 - $html .= $this->render_error_cell( esc_html__( 'Only available in WP 5.8+', 'plugin-report' ) );
471 - } else {
472 - $html .= $this->render_error_cell();
473 - }
474 -
475 355 // Activated.
476 - $active = __( 'Please clear cache to update', 'plugin-report' );
356 + $active = __( 'Please clear cache to update', 'plugin-report' );
477 357 $css_class = self::CSS_CLASS_MED;
478 358 if ( is_multisite() ) {
479 359 $activation_status = $this->get_multisite_activation( $report['file_path'] );
480 360 if ( true === $activation_status['network'] ) {
481 361 $css_class = self::CSS_CLASS_LOW;
482 - $html .= '<td class="' . $css_class . '">' . __( 'Network activated', 'plugin-report' ) . '</td>';
362 + $html .= '<td class="' . $css_class . '">' . __( 'Network activated', 'plugin-report' ) . '</td>';
483 363 } else {
484 364 $css_class = ( $activation_status['active'] > 0 ) ? self::CSS_CLASS_LOW : self::CSS_CLASS_HIGH;
485 - $html .= '<td class="' . $css_class . '">' . $activation_status['active'] . '/' . $activation_status['sites'] . '</td>';
365 + $html .= '<td class="' . $css_class . '">' . $activation_status['active'] . '/' . $activation_status['sites'] . '</td>';
486 366 }
487 367 } else {
488 368 if ( isset( $report['file_path'] ) ) {
489 369 $active = is_plugin_active( $report['file_path'] ) ? __( 'Yes', 'plugin-report' ) : __( 'No', 'plugin-report' );
@@ -490,31 +370,31 @@
490 370 $css_class = is_plugin_active( $report['file_path'] ) ? self::CSS_CLASS_LOW : self::CSS_CLASS_HIGH;
491 371 }
492 372 $html .= '<td class="' . $css_class . '">' . $active . '</td>';
493 373 }
494 -
495 374 // Installed / available version.
496 375 if ( isset( $report['repo_info'] ) ) {
497 376 $css_class = $this->get_version_risk_classname( $report['local_info']['Version'], $report['repo_info']->version );
498 - $html .= '<td class="' . $css_class . '">';
499 - $html .= $report['local_info']['Version'];
500 - if ( $report['local_info']['Version'] !== $report['repo_info']->version ) {
377 + $html .= '<td class="' . $css_class . '">';
378 + $html .= $report['local_info']['Version'];
379 + if ( $report['local_info']['Version'] != $report['repo_info']->version ) {
501 380 // Any platform upgrades needed?
381 + global $wp_version;
502 382 $needs_php_upgrade = isset( $report['repo_info']->requires_php ) ? version_compare( phpversion(), $report['repo_info']->requires_php, '<' ) : false;
503 383 $needs_wp_upgrade = isset( $report['repo_info']->requires ) ? version_compare( $wp_version, $report['repo_info']->requires, '<' ) : false;
504 384 // Create the additional message.
505 385 if ( $needs_wp_upgrade && $needs_php_upgrade ) {
506 386 /* translators: %1$s: Plugin version number, %2$s: WP version number, %3$s: PHP version number */
507 - $html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires WP %2$s and PHP %3$s)', 'plugin-report' ), $report['repo_info']->version, $report['repo_info']->requires, $report['repo_info']->requires_php ) . '</span>';
387 + $html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires WP %2$s and PHP %3$s)', 'plugin-report'), $report['repo_info']->version, $report['repo_info']->requires, $report['repo_info']->requires_php ) . '</span>';
508 388 } elseif ( $needs_wp_upgrade ) {
509 389 /* translators: %1$s: Plugin version number, %2$s: WP version number. */
510 - $html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires WP %2$s)', 'plugin-report' ), $report['repo_info']->version, $report['repo_info']->requires ) . '</span>';
390 + $html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires WP %2$s)', 'plugin-report'), $report['repo_info']->version, $report['repo_info']->requires ) . '</span>';
511 391 } elseif ( $needs_php_upgrade ) {
512 392 /* translators: %1$s: Plugin version number, %2$s: PHP version number. */
513 - $html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires PHP %2$s)', 'plugin-report' ), $report['repo_info']->version, $report['repo_info']->requires_php ) . '</span>';
393 + $html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires PHP %2$s)', 'plugin-report'), $report['repo_info']->version, $report['repo_info']->requires_php ) . '</span>';
514 394 } else {
515 395 /* translators: %s: Plugin version number. */
516 - $html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%s available)', 'plugin-report' ), $report['repo_info']->version ) . '</span>';
396 + $html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%s available)', 'plugin-report'), $report['repo_info']->version ) . '</span>';
517 397 }
518 398 }
519 399 $html .= '</td>';
520 400 } else {
@@ -519,22 +399,10 @@
519 399 $html .= '</td>';
520 400 } else {
521 401 $html .= '<td>' . $report['local_info']['Version'] . '</td>';
522 402 }
523 -
524 - // Auto-update.
525 - if ( version_compare( $wp_version, '5.5', '<' ) ) {
526 - $html .= '<td>' . __( 'Requires WordPress 5.5 or higher', 'plugin-report' ) . '</td>';
527 - } else {
528 - if ( isset( $report['auto-update'] ) && $report['auto-update'] ) {
529 - $html .= '<td class="' . self::CSS_CLASS_LOW . '">' . __( 'Enabled', 'plugin-report' ) . '</td>';
530 - } else {
531 - $html .= '<td>' . __( 'Not enabled', 'plugin-report' ) . '</td>';
532 - }
533 - }
534 -
535 403 // Last updates.
536 - if ( isset( $report['repo_info'] ) && isset( $report['repo_info']->last_updated ) ) {
404 + if ( isset( $report['repo_info'] ) ) {
537 405 $time_update = new DateTime( $report['repo_info']->last_updated );
538 406 $time_diff = human_time_diff( $time_update->getTimestamp(), current_time( 'timestamp' ) );
539 407 $css_class = $this->get_timediff_risk_classname( current_time( 'timestamp' ) - $time_update->getTimestamp() );
540 408 $html .= '<td class="' . $css_class . '" data-sort="' . $time_update->getTimestamp() . '">' . $time_diff . '</td>';
@@ -540,19 +408,17 @@
540 408 $html .= '<td class="' . $css_class . '" data-sort="' . $time_update->getTimestamp() . '">' . $time_diff . '</td>';
541 409 } else {
542 410 $html .= $this->render_error_cell();
543 411 }
544 -
545 412 // Tested up to.
546 - if ( isset( $report['repo_info'] ) && isset( $report['repo_info']->tested ) && ! empty( $report['repo_info']->tested ) ) {
547 - $css_class = $this->get_version_risk_classname( $report['repo_info']->tested, $wp_latest, true );
548 - $html .= '<td class="' . $css_class . '">' . $report['repo_info']->tested . '</td>';
413 + if ( isset( $report['repo_info'] ) ) {
414 + $css_class = $this->get_version_risk_classname( $report['repo_info']->tested, $wp_latest );
415 + $html .= '<td class="' . $css_class . '">' . $report['repo_info']->tested . '</td>';
549 416 } else {
550 417 $html .= $this->render_error_cell();
551 418 }
552 -
553 419 // Overall user rating.
554 - if ( isset( $report['repo_info'] ) && isset( $report['repo_info']->num_ratings ) && isset( $report['repo_info']->rating ) ) {
420 + if ( isset( $report['repo_info'] ) ) {
555 421 $css_class = ( intval( $report['repo_info']->num_ratings ) > 0 ) ? $this->get_percentage_risk_classname( intval( $report['repo_info']->rating ) ) : '';
556 422 $value_text = ( ( intval( $report['repo_info']->num_ratings ) > 0 ) ? $report['repo_info']->rating . '%' : esc_html__( 'No data available', 'plugin-report' ) );
557 423 $html .= '<td class="' . $css_class . '">' . $value_text . '</td>';
558 424 } else {
@@ -557,9 +423,8 @@
557 423 $html .= '<td class="' . $css_class . '">' . $value_text . '</td>';
558 424 } else {
559 425 $html .= $this->render_error_cell();
560 426 }
561 -
562 427 // Close the new table row.
563 428 $html .= '</tr>';
564 429 }
565 430 return $html;
@@ -566,11 +431,9 @@
566 431 }
567 432
568 433
569 434 /**
570 - * Format an error message as a table row, so we can return it to javascript.
571 - *
572 - * @param string $message Message to be shown.
435 + * Format an error message as a table row, so we can return it to javascript
573 436 */
574 437 private function render_error_row( $message ) {
575 438 return '<tr class="pluginreport-row-error"><td colspan="' . self::COLS_PER_ROW . '">' . $message . '</td></tr>';
576 439 }
@@ -576,46 +439,22 @@
576 439 }
577 440
578 441
579 442 /**
580 - * Format an error message as a table cell, so we can return it to javascript.
581 - *
582 - * @param string $message Message to be shown.
443 + * Format an error message as a table cell, so we can return it to javascript
583 444 */
584 445 private function render_error_cell( $message = null ) {
585 446 if ( ! $message ) {
586 447 $message = esc_html__( 'No data available', 'plugin-report' );
587 448 }
588 - return '<td class="pluginreport-cell-error" data-sort="0">' . $message . '</td>';
449 + return '<td class="pluginreport-cell-error">' . $message . '</td>';
589 450 }
590 451
591 452
592 453 /**
593 - * Return the version string with all elements beyond the second removed ("5.5.1" -> "5.5").
594 - *
595 - * @param string $version_string Complete version number.
454 + * Figure out what CSS class to use based on current and optimal version numbers
596 455 */
597 - private function get_major_version( $version_string ) {
598 - $parts = explode( '.', $version_string );
599 - array_splice( $parts, 2 );
600 - return implode( '.', $parts );
601 - }
602 -
603 -
604 - /**
605 - * Figure out what CSS class to use based on current and optimal version numbers.
606 - *
607 - * @param string $available Available version.
608 - * @param string $optimal Optimal version.
609 - * @param bool $major_only True to compare only major versions, false otherwise.
610 - */
611 - private function get_version_risk_classname( $available, $optimal, $major_only = false ) {
612 - // Use only the first two elements of the version number if $major_only is set to true.
613 - // This is used for WP version numbers, where point releases are not considered a risk.
614 - if ( $major_only ) {
615 - $available = $this->get_major_version( $available );
616 - $optimal = $this->get_major_version( $optimal );
617 - }
456 + private function get_version_risk_classname( $available, $optimal ) {
618 457 // If the version is equal or higher, indicate low risk.
619 458 if ( version_compare( $available, $optimal, '>=' ) ) {
620 459 return self::CSS_CLASS_LOW;
621 460 }
@@ -624,11 +463,9 @@
624 463 }
625 464
626 465
627 466 /**
628 - * Assess the risk associated with low ratings or poor compatibility feedback, return corresponding CSS class.
629 - *
630 - * @param int $perc Rating percentage.
467 + * Assess the risk associated with low ratings or poor compatibility feedback, return corresponding CSS class
631 468 */
632 469 private function get_percentage_risk_classname( $perc ) {
633 470 if ( $perc < 70 ) {
634 471 return self::CSS_CLASS_HIGH;
@@ -640,11 +477,9 @@
640 477 }
641 478
642 479
643 480 /**
644 - * Assess the risk associated with low ratings or poor compatibility feedback, return corresponding CSS class.
645 - *
646 - * @param int $time_diff Time difference in seconds.
481 + * Assess the risk associated with low ratings or poor compatibility feedback, return corresponding CSS class
647 482 */
648 483 private function get_timediff_risk_classname( $time_diff ) {
649 484 $days = $time_diff / ( DAY_IN_SECONDS );
650 485 if ( $days > 365 ) {
@@ -664,24 +499,22 @@
664 499 private function check_core_updates() {
665 500 global $wp_version;
666 501 $update = get_preferred_from_update_core();
667 502 // Bail out of no valid response, or false.
668 - if ( false === $update ) {
503 + if ( ! $update || $update == false ) {
669 504 return $wp_version;
670 505 }
671 506 // If latest, return current version number.
672 - if ( is_object( $update ) && 'latest' === $update->response ) {
507 + if ( $update->response == 'latest' ) {
673 508 return $wp_version;
674 509 }
675 510 // Return the preferred update's version number.
676 - return is_object( $update ) ? $update->version : $update['version'];
511 + return $update->version;
677 512 }
678 513
679 514
680 515 /**
681 - * Gather statistics about a plugin's activation on a multisite install.
682 - *
683 - * @param string $path Plugin path.
516 + * Gather statistics about a plugin's activation on a multisite install
684 517 */
685 518 private function get_multisite_activation( $path ) {
686 519 // Create an array to contain the return values.
687 520 $activation_status = array(
@@ -694,9 +527,9 @@
694 527 if ( array_key_exists( $path, $network_plugins ) ) {
695 528 $activation_status['network'] = true;
696 529 } else {
697 530 // Get a list of all sites in the multisite install.
698 - $args = array(
531 + $args = array(
699 532 'number' => 9999,
700 533 'fields' => 'ids',
701 534 );
702 535 $sites = get_sites( $args );
@@ -720,10 +553,8 @@
720 553
721 554
722 555 /**
723 556 * Create a cache key that is unique to the provided plugin slug.
724 - *
725 - * @param string $slug Plugin slug.
726 557 */
727 558 private function create_cache_key( $slug ) {
728 559 // Create a hash for the plugin slug.
729 560 $slug_hash = hash( 'sha256', $slug );
@@ -748,15 +579,15 @@
748 579 }
749 580
750 581
751 582 /**
752 - * Remove the cache item for a single plugin.
753 - *
754 - * @param string $slug Plugin slug.
583 + * Remove the cache item for a single plugin
755 584 */
756 585 private function clear_cache_item( $slug ) {
757 - $cache_key = $this->create_cache_key( $slug );
758 - delete_site_transient( $cache_key );
586 + if ( isset( $slug ) ) {
587 + $cache_key = $this->create_cache_key( $slug );
588 + delete_site_transient( $cache_key );
589 + }
759 590 }
760 591
761 592
762 593 /**