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 +195 -84 1.31.7 View file →
@@ -2,14 +2,15 @@
2 2 /**
3 3 * Plugin Name: Plugin Report
4 4 * Plugin URI: https://roytanck.com/?p=277
5 5 * Description: Provides detailed information about currently installed plugins
6 - * Version: 1.3
6 + * Version: 1.7
7 7 * Requires at least: 4.6
8 8 * Requires PHP: 5.6
9 9 * Author: Roy Tanck
10 10 * Author URI: https://roytanck.com
11 11 * License: GPLv3
12 + * Network: true
12 13 */
13 14
14 15 // If called without WordPress, exit.
15 16 if ( ! defined( 'ABSPATH' ) ) {
@@ -20,12 +21,19 @@
20 21 if ( is_admin() && ! class_exists( 'RT_Plugin_Report' ) ) {
21 22
22 23 class RT_Plugin_Report {
23 24
24 - public $cols_per_row = 6;
25 - public $cache_lifetime = DAY_IN_SECONDS;
26 - public $cache_lifetime_norepo = WEEK_IN_SECONDS;
25 + // CSS class constants.
26 + const CSS_CLASS_LOW = 'pr-risk-low';
27 + const CSS_CLASS_MED = 'pr-risk-medium';
28 + const CSS_CLASS_HIGH = 'pr-risk-high';
27 29
30 + // Other class constants.
31 + const PLUGIN_VERSION = '1.7';
32 + const COLS_PER_ROW = 7;
33 + const CACHE_LIFETIME = DAY_IN_SECONDS;
34 + const CACHE_LIFETIME_NOREPO = WEEK_IN_SECONDS;
35 +
28 36 /**
29 37 * Constructor
30 38 */
31 39 public function __construct() {
@@ -43,13 +51,13 @@
43 51 } else {
44 52 add_action( 'admin_menu', array( $this, 'register_settings_page' ) );
45 53 }
46 54 // Hook for the admin js.
47 - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_js' ) );
55 + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
48 56 // Add the AJAX hook.
49 57 add_action( 'wp_ajax_rt_get_plugin_info', array( $this, 'get_plugin_info' ) );
50 58 // Hook into the WP Upgrader to selectively delete cache items.
51 - add_action( 'upgrader_process_complete', array( $this, 'upgrade_delete_cache_items' ), 10 ,2 );
59 + add_action( 'upgrader_process_complete', array( $this, 'upgrade_delete_cache_items' ), 10, 2 );
52 60 }
53 61
54 62
55 63 /**
@@ -56,12 +64,12 @@
56 64 * Add a new options page to the network admin
57 65 */
58 66 public function register_settings_page() {
59 67 add_plugins_page(
60 - esc_html__( 'Plugin Report', 'plugin-report' ),
61 - esc_html__( 'Plugin Report', 'plugin-report' ),
68 + esc_html_x( 'Plugin Report', 'Page and menu title', 'plugin-report' ),
69 + esc_html_x( 'Plugin Report', 'Page and menu title', 'plugin-report' ),
62 70 'manage_options',
63 - 'rt_plugin_report',
71 + 'plugin_report',
64 72 array( $this, 'settings_page' )
65 73 );
66 74 }
67 75
@@ -83,22 +91,22 @@
83 91
84 92 // Refresh the cache, but only if this is a fresh timestamp (not if the page has been refreshed with the timestamp still in the URL).
85 93 if ( isset( $_GET['clear_cache'] ) ) {
86 94 $new_timestamp = intval( $_GET['clear_cache'] );
87 - $last_timestamp = intval( get_site_transient( 'rt_plugin_report_cache_cleared' ) );
95 + $last_timestamp = intval( get_site_transient( 'plugin_report_cache_cleared' ) );
88 96 if ( ! $last_timestamp || $new_timestamp > $last_timestamp ) {
89 97 $this->clear_cache();
90 - set_site_transient( 'rt_plugin_report_cache_cleared', $new_timestamp, $this->cache_lifetime );
98 + set_site_transient( 'plugin_report_cache_cleared', $new_timestamp, self::CACHE_LIFETIME );
91 99 }
92 100 }
93 101
94 102 // Start the page's output.
95 103 echo '<div class="wrap">';
96 - echo '<h1>' . esc_html__( 'Plugin Report', 'plugin-report' ) . '</h1>';
104 + echo '<h1>' . esc_html_x( 'Plugin Report', 'Page and menu title', 'plugin-report' ) . '</h1>';
97 105 echo '<p>';
98 106 $version_temp = '<span class="' . $this->get_version_risk_classname( $wp_version, $wp_latest ) . '">' . $wp_version . '</span>';
99 - /* translators: %s = Current WordPress version number */
100 - echo sprintf( __( 'Currently running WordPress version: %s.', 'plugin-report' ), $version_temp );
107 + /* translators: %1$s: Current WordPress version number, %2$s: Current PHP version number */
108 + echo sprintf( __( 'Currently running WordPress version %1$s and PHP version %2$s.', 'plugin-report' ), $version_temp, phpversion() );
101 109 if ( version_compare( $wp_version, $wp_latest, '<' ) ) {
102 110 /* translators: %s = Available new version number */
103 111 echo sprintf( ' (' . esc_html__( 'An upgrade to %s is available', 'plugin-report' ) . ')', $wp_latest );
104 112 }
@@ -105,28 +113,29 @@
105 113 echo '</p>';
106 114 echo '<p>';
107 115 // Clear cache and reload.
108 116 if ( is_multisite() ) {
109 - $page_url = 'network/plugins.php?page=rt_plugin_report';
117 + $page_url = 'network/plugins.php?page=plugin_report';
110 118 } else {
111 - $page_url = 'plugins.php?page=rt_plugin_report';
119 + $page_url = 'plugins.php?page=plugin_report';
112 120 }
113 121 echo '<a href="' . admin_url( $page_url . '&clear_cache=' . current_time( 'timestamp' ) ) . '">' . esc_html__( 'Clear cached plugin data and reload', 'plugin-report' ) . '</a>';
114 122 echo '</p>';
115 123 echo '<h3>' . esc_html__( 'Currently installed plugins', 'plugin-report' ) . '</h3>';
116 - echo '<p id="rt-plugin-report-progress"></p>';
124 + echo '<p id="plugin-report-progress"></p>';
117 125 echo '<p>';
118 126
119 127 // The report's main table.
120 - echo '<table id="rt-plugin-report-table" class="wp-list-table widefat fixed striped">';
128 + echo '<table id="plugin-report-table" class="wp-list-table widefat fixed striped">';
121 129 echo '<thead>';
122 130 echo '<tr>';
123 131 echo '<th>' . esc_html__( 'Name', 'plugin-report' ) . '</th>';
124 132 echo '<th>' . esc_html__( 'Author', 'plugin-report' ) . '</th>';
125 - echo '<th>' . esc_html__( 'Installed version', 'plugin-report' ) . '</th>';
133 + echo '<th>' . esc_html__( 'Activated', 'plugin-report' ) . '</th>';
134 + echo '<th data-sort-method="none" class="no-sort">' . esc_html__( 'Installed version', 'plugin-report' ) . '</th>';
126 135 echo '<th>' . esc_html__( 'Last update', 'plugin-report' ) . '</th>';
127 - echo '<th>' . esc_html__( 'Tested up to WP version', 'plugin-report' ) . '</th>';
128 - echo '<th>' . esc_html__( 'Rating', 'plugin-report' ) . '</th>';
136 + echo '<th data-sort-method="dotsep">' . esc_html__( 'Tested up to WP version', 'plugin-report' ) . '</th>';
137 + echo '<th data-sort-method="number">' . esc_html__( 'Rating', 'plugin-report' ) . '</th>';
129 138 echo '</tr>';
130 139 echo '</thead>';
131 140 echo '<tbody>';
132 141
@@ -138,17 +147,19 @@
138 147 // Use the cached report to create a table row.
139 148 echo $this->render_table_row( $cache );
140 149 } else {
141 150 // Render a special table row that's used as a signal to the front-end js that new data is needed.
142 - echo '<tr class="rt-plugin-report-row-temp-' . $slug . '"><td colspan="' . $this->cols_per_row . '">loading...</td></tr>';
151 + echo '<tr class="plugin-report-row-temp-' . $slug . '"><td colspan="' . self::COLS_PER_ROW . '">' . esc_html__( 'Loading...', 'plugin-report' ) . '</td></tr>';
143 152 }
144 153 }
145 154
146 155 echo '</tbody>';
147 156 echo '</table>';
157 + echo '</p>';
148 158
159 + echo '<p id="plugin-report-buttons"></p>';
160 +
149 161 // Wrap up.
150 - echo '</p>';
151 162 echo '</div>';
152 163 }
153 164
154 165
@@ -154,25 +165,31 @@
154 165
155 166 /**
156 167 * Enqueue admin javascript
157 168 */
158 - public function enqueue_js( $hook ) {
169 + public function enqueue_assets( $hook ) {
159 170 // Check if we're on the right screen.
160 - if ( 'plugins_page_rt_plugin_report' != $hook ) {
171 + if ( 'plugins_page_plugin_report' !== $hook ) {
161 172 return;
162 173 }
163 - // register the plugin's admin js, and require jquery
164 - wp_enqueue_script( 'rt-plugin-report-js', plugins_url( '/js/rt-plugin-report.js', __FILE__ ), array( 'jquery' ) );
165 - // add some variables to the page, to be used by the javascript
174 + // Register the plugin's admin js, and require jquery.
175 + wp_enqueue_script( 'plugin-report-js', plugins_url( '/js/plugin-report.js', __FILE__ ), array( 'jquery', 'plugin-report-tablesort-js' ), self::PLUGIN_VERSION );
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' );
179 + // Add some variables to the page, to be used by the javascript.
166 180 $slugs = $this->get_plugin_slugs();
167 181 $slugs_str = implode( ',', $slugs );
168 182 $vars = array(
169 - 'plugin_slugs' => $slugs_str,
170 - 'ajax_nonce' => wp_create_nonce( 'rt_plugin_report_nonce' ),
183 + 'plugin_slugs' => $slugs_str,
184 + 'ajax_nonce' => wp_create_nonce( 'plugin_report_nonce' ),
185 + 'export_btn' => __( 'Export .csv file', 'plugin-report' ),
186 + 'plugin_url_header' => __( 'Plugin URL', 'plugin-report' ),
187 + 'author_url_header' => __( 'Author URL', 'plugin-report' ),
171 188 );
172 - wp_localize_script( 'rt-plugin-report-js', 'rt_plugin_report_vars', $vars );
189 + wp_localize_script( 'plugin-report-js', 'plugin_report_vars', $vars );
173 190 // Enqueue admin CSS file.
174 - wp_enqueue_style( 'rt-plugin-report-css', plugin_dir_url( __FILE__ ) . 'css/rt-plugin-report.css' );
191 + wp_enqueue_style( 'plugin-report-css', plugin_dir_url( __FILE__ ) . 'css/plugin-report.css', array(), self::PLUGIN_VERSION );
175 192 }
176 193
177 194
178 195 /**
@@ -207,9 +224,9 @@
207 224 */
208 225 public function get_plugin_info() {
209 226
210 227 // Check the ajax nonce, display an error if the check fails.
211 - if ( ! check_ajax_referer( 'rt_plugin_report_nonce', 'nonce', false ) ) {
228 + if ( ! check_ajax_referer( 'plugin_report_nonce', 'nonce', false ) ) {
212 229 wp_die();
213 230 }
214 231
215 232 // Check user capabilites, just to be sure.
@@ -237,9 +254,9 @@
237 254 'html' => $table_row,
238 255 'message' => 'Success!',
239 256 );
240 257 // Return the response.
241 - echo json_encode( $response );
258 + echo wp_json_encode( $response );
242 259
243 260 wp_die();
244 261 }
245 262
@@ -263,8 +280,9 @@
263 280 // Get the locally available info, and add it to the report.
264 281 foreach ( $plugins as $key => $plugin ) {
265 282 if ( $this->get_plugin_slug( $key ) == $slug ) {
266 283 $report['local_info'] = $plugin;
284 + $report['file_path'] = $key;
267 285 break;
268 286 }
269 287 }
270 288
@@ -277,8 +295,9 @@
277 295 'tags' => false,
278 296 'version' => true,
279 297 'tested' => true,
280 298 'requires' => true,
299 + 'requires_php' => true,
281 300 'compatibility' => true,
282 301 'author' => true,
283 302 ),
284 303 );
@@ -287,15 +306,15 @@
287 306 // Add the repo info to the report.
288 307 if ( ! is_wp_error( $returned_object ) ) {
289 308 $report['repo_info'] = maybe_unserialize( $returned_object );
290 309 // Cache the report.
291 - set_site_transient( $cache_key, $report, $this->cache_lifetime );
310 + set_site_transient( $cache_key, $report, self::CACHE_LIFETIME );
292 311 } else {
293 312 // Store the error code and message in the report.
294 313 $report['repo_error_code'] = $returned_object->get_error_code();
295 314 $report['repo_error_message'] = $returned_object->get_error_message();
296 315 // Cache for an extra long time when the plugin is not in the repo.
297 - set_site_transient( $cache_key, $report, $this->cache_lifetime_norepo );
316 + set_site_transient( $cache_key, $report, self::CACHE_LIFETIME_NOREPO );
298 317 }
299 318 } else {
300 319 $report = $cache;
301 320 }
@@ -317,40 +336,95 @@
317 336 $wp_latest = $this->check_core_updates();
318 337 // Check if the report is valid.
319 338 if ( $report == null ) {
320 339 $html = $this->render_error_row( esc_html__( 'No plugin data available.', 'plugin-report' ) );
321 - } elseif ( ! isset( $report['repo_info'] ) ) {
322 - // Get the error message from the report, or use a default.
323 - $error_msg = isset( $report['repo_error_message'] ) ? $report['repo_error_message'] : __( 'Unknown error', 'plugin-report' );
324 - /* translators: %s = Name of the plugin */
325 - $html = $this->render_error_row( sprintf( esc_html__( 'Error fetching info for "%s" from wordpress.org:', 'plugin-report' ), $report['local_info']['Name'] ) . ' ' . $error_msg );
326 340 } else {
327 341 // Start the new table row.
328 - $html = '<tr class="rt-plugin-report-row-' . $report['slug'] . '">';
342 + $html = '<tr class="plugin-report-row-' . $report['slug'] . '">';
329 343 // Name.
330 - $html .= '<td><a href="https://wordpress.org/plugins/' . $report['slug'] . '">' . $report['repo_info']->name . '</a></td>';
344 + if ( isset( $report['local_info']['PluginURI'] ) && ! empty( $report['local_info']['PluginURI'] ) ) {
345 + $html .= '<td><a href="' . $report['local_info']['PluginURI'] . '"><strong>' . $report['local_info']['Name'] . '</strong></a></td>';
346 + } else {
347 + $html .= '<td><strong>' . $report['local_info']['Name'] . '</strong></td>';
348 + }
331 349 // Author.
332 - $html .= '<td>' . $report['repo_info']->author . '</td>';
350 + if ( isset( $report['local_info']['AuthorURI'] ) && ! empty( $report['local_info']['AuthorURI'] ) ) {
351 + $html .= '<td><a href="' . $report['local_info']['AuthorURI'] . '">' . $report['local_info']['Author'] . '</a></td>';
352 + } else {
353 + $html .= '<td>' . $report['local_info']['Author'] . '</td>';
354 + }
355 + // Activated.
356 + $active = __( 'Please clear cache to update', 'plugin-report' );
357 + $css_class = self::CSS_CLASS_MED;
358 + if ( is_multisite() ) {
359 + $activation_status = $this->get_multisite_activation( $report['file_path'] );
360 + if ( true === $activation_status['network'] ) {
361 + $css_class = self::CSS_CLASS_LOW;
362 + $html .= '<td class="' . $css_class . '">' . __( 'Network activated', 'plugin-report' ) . '</td>';
363 + } else {
364 + $css_class = ( $activation_status['active'] > 0 ) ? self::CSS_CLASS_LOW : self::CSS_CLASS_HIGH;
365 + $html .= '<td class="' . $css_class . '">' . $activation_status['active'] . '/' . $activation_status['sites'] . '</td>';
366 + }
367 + } else {
368 + if ( isset( $report['file_path'] ) ) {
369 + $active = is_plugin_active( $report['file_path'] ) ? __( 'Yes', 'plugin-report' ) : __( 'No', 'plugin-report' );
370 + $css_class = is_plugin_active( $report['file_path'] ) ? self::CSS_CLASS_LOW : self::CSS_CLASS_HIGH;
371 + }
372 + $html .= '<td class="' . $css_class . '">' . $active . '</td>';
373 + }
333 374 // Installed / available version.
334 - $css_class = $this->get_version_risk_classname( $report['local_info']['Version'], $report['repo_info']->version );
335 - $html .= '<td class="' . $css_class . '">';
336 - $html .= $report['local_info']['Version'];
337 - if ( $report['local_info']['Version'] != $report['repo_info']->version ) {
338 - $html .= '<span class="rt-additional-info">(' . $report['repo_info']->version . ' available)</span>';
375 + if ( isset( $report['repo_info'] ) ) {
376 + $css_class = $this->get_version_risk_classname( $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 ) {
380 + // Any platform upgrades needed?
381 + global $wp_version;
382 + $needs_php_upgrade = isset( $report['repo_info']->requires_php ) ? version_compare( phpversion(), $report['repo_info']->requires_php, '<' ) : false;
383 + $needs_wp_upgrade = isset( $report['repo_info']->requires ) ? version_compare( $wp_version, $report['repo_info']->requires, '<' ) : false;
384 + // Create the additional message.
385 + if ( $needs_wp_upgrade && $needs_php_upgrade ) {
386 + /* translators: %1$s: Plugin version number, %2$s: WP version number, %3$s: PHP version number */
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>';
388 + } elseif ( $needs_wp_upgrade ) {
389 + /* translators: %1$s: Plugin version number, %2$s: WP version number. */
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>';
391 + } elseif ( $needs_php_upgrade ) {
392 + /* translators: %1$s: Plugin version number, %2$s: PHP version number. */
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>';
394 + } else {
395 + /* translators: %s: Plugin version number. */
396 + $html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%s available)', 'plugin-report'), $report['repo_info']->version ) . '</span>';
397 + }
398 + }
399 + $html .= '</td>';
400 + } else {
401 + $html .= '<td>' . $report['local_info']['Version'] . '</td>';
339 402 }
340 - $html .= '</td>';
341 403 // Last updates.
342 - $time_update = new DateTime( $report['repo_info']->last_updated );
343 - $time_diff = human_time_diff( $time_update->getTimestamp(), current_time( 'timestamp' ) );
344 - $css_class = $this->get_timediff_risk_classname( current_time( 'timestamp' ) - $time_update->getTimestamp() );
345 - $html .= '<td class="' . $css_class . '">' . $time_diff . '</td>';
404 + if ( isset( $report['repo_info'] ) ) {
405 + $time_update = new DateTime( $report['repo_info']->last_updated );
406 + $time_diff = human_time_diff( $time_update->getTimestamp(), current_time( 'timestamp' ) );
407 + $css_class = $this->get_timediff_risk_classname( current_time( 'timestamp' ) - $time_update->getTimestamp() );
408 + $html .= '<td class="' . $css_class . '" data-sort="' . $time_update->getTimestamp() . '">' . $time_diff . '</td>';
409 + } else {
410 + $html .= $this->render_error_cell();
411 + }
346 412 // Tested up to.
347 - $css_class = $this->get_version_risk_classname( $report['repo_info']->tested, $wp_latest );
348 - $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>';
416 + } else {
417 + $html .= $this->render_error_cell();
418 + }
349 419 // Overall user rating.
350 - $css_class = ( intval( $report['repo_info']->num_ratings ) > 0 ) ? $this->get_percentage_risk_classname( intval( $report['repo_info']->rating ) ) : '';
351 - $value_text = ( ( intval( $report['repo_info']->num_ratings ) > 0 ) ? $report['repo_info']->rating . '%' : esc_html__( 'No data available', 'plugin-report' ) );
352 - $html .= '<td class="' . $css_class . '">' . $value_text . '</td>';
420 + if ( isset( $report['repo_info'] ) ) {
421 + $css_class = ( intval( $report['repo_info']->num_ratings ) > 0 ) ? $this->get_percentage_risk_classname( intval( $report['repo_info']->rating ) ) : '';
422 + $value_text = ( ( intval( $report['repo_info']->num_ratings ) > 0 ) ? $report['repo_info']->rating . '%' : esc_html__( 'No data available', 'plugin-report' ) );
423 + $html .= '<td class="' . $css_class . '">' . $value_text . '</td>';
424 + } else {
425 + $html .= $this->render_error_cell();
426 + }
353 427 // Close the new table row.
354 428 $html .= '</tr>';
355 429 }
356 430 return $html;
@@ -360,26 +434,33 @@
360 434 /**
361 435 * Format an error message as a table row, so we can return it to javascript
362 436 */
363 437 private function render_error_row( $message ) {
364 - return '<tr class="rt-pluginreport-row-error"><td colspan="' . $this->cols_per_row . '">' . $message . '</td></tr>';
438 + return '<tr class="pluginreport-row-error"><td colspan="' . self::COLS_PER_ROW . '">' . $message . '</td></tr>';
365 439 }
366 440
367 441
368 442 /**
443 + * Format an error message as a table cell, so we can return it to javascript
444 + */
445 + private function render_error_cell( $message = null ) {
446 + if ( ! $message ) {
447 + $message = esc_html__( 'No data available', 'plugin-report' );
448 + }
449 + return '<td class="pluginreport-cell-error">' . $message . '</td>';
450 + }
451 +
452 +
453 + /**
369 454 * Figure out what CSS class to use based on current and optimal version numbers
370 455 */
371 456 private function get_version_risk_classname( $available, $optimal ) {
372 - // If the version match, indicate low risk.
373 - if ( version_compare( $available, $optimal, '==' ) ) {
374 - return 'rt-risk-low';
457 + // If the version is equal or higher, indicate low risk.
458 + if ( version_compare( $available, $optimal, '>=' ) ) {
459 + return self::CSS_CLASS_LOW;
375 460 }
376 - // If major version match, indicate medium risk.
377 - if ( version_compare( $this->major_release_version_nr( $available ), $this->major_release_version_nr( $optimal ), '==' ) ) {
378 - return 'rt-risk-medium';
379 - }
380 461 // Else, indicate high risk.
381 - return 'rt-risk-high';
462 + return self::CSS_CLASS_HIGH;
382 463 }
383 464
384 465
385 466 /**
@@ -386,14 +467,14 @@
386 467 * Assess the risk associated with low ratings or poor compatibility feedback, return corresponding CSS class
387 468 */
388 469 private function get_percentage_risk_classname( $perc ) {
389 470 if ( $perc < 70 ) {
390 - return 'rt-risk-high';
471 + return self::CSS_CLASS_HIGH;
391 472 }
392 473 if ( $perc < 90 ) {
393 - return 'rt-risk-medium';
474 + return self::CSS_CLASS_MED;
394 475 }
395 - return 'rt-risk-low';
476 + return self::CSS_CLASS_LOW;
396 477 }
397 478
398 479
399 480 /**
@@ -401,14 +482,14 @@
401 482 */
402 483 private function get_timediff_risk_classname( $time_diff ) {
403 484 $days = $time_diff / ( DAY_IN_SECONDS );
404 485 if ( $days > 365 ) {
405 - return 'rt-risk-high';
486 + return self::CSS_CLASS_HIGH;
406 487 }
407 488 if ( $days > 90 ) {
408 - return 'rt-risk-medium';
489 + return self::CSS_CLASS_MED;
409 490 }
410 - return 'rt-risk-low';
491 + return self::CSS_CLASS_LOW;
411 492 }
412 493
413 494
414 495 /**
@@ -431,14 +512,44 @@
431 512 }
432 513
433 514
434 515 /**
435 - * Extract the major release number from a WP version nr
516 + * Gather statistics about a plugin's activation on a multisite install
436 517 */
437 - private function major_release_version_nr( $version ) {
438 - $parts = explode( '.', $version );
439 - $parts = array_slice( $parts, 0, 2 );
440 - return implode( '.', $parts );
518 + private function get_multisite_activation( $path ) {
519 + // Create an array to contain the return values.
520 + $activation_status = array(
521 + 'network' => false,
522 + 'active' => 0,
523 + 'sites' => 1,
524 + );
525 + // Check if the plugin is network activated.
526 + $network_plugins = get_site_option( 'active_sitewide_plugins', null );
527 + if ( array_key_exists( $path, $network_plugins ) ) {
528 + $activation_status['network'] = true;
529 + } else {
530 + // Get a list of all sites in the multisite install.
531 + $args = array(
532 + 'number' => 9999,
533 + 'fields' => 'ids',
534 + );
535 + $sites = get_sites( $args );
536 + // Add the total number of sites to the return array.
537 + $activation_status['sites'] = count( $sites );
538 + // Loop through the sites to find where the plugin is active.
539 + foreach ( $sites as $site_id ) {
540 + $plugins = get_blog_option( $site_id, 'active_plugins', null );
541 + if ( $plugins ) {
542 + foreach ( $plugins as $plugin_path ) {
543 + if ( $plugin_path === $path ) {
544 + $activation_status['active']++;
545 + }
546 + }
547 + }
548 + }
549 + }
550 + // Return the data we gathered.
551 + return $activation_status;
441 552 }
442 553
443 554
444 555 /**
@@ -444,9 +555,9 @@
444 555 /**
445 556 * Create a cache key that is unique to the provided plugin slug.
446 557 */
447 558 private function create_cache_key( $slug ) {
448 - // Create a hash for the plugiin slug.
559 + // Create a hash for the plugin slug.
449 560 $slug_hash = hash( 'sha256', $slug );
450 561 // Prefix and limit the string to 40 characters to avoid issues with long keys.
451 562 $cache_key = 'rtpr_' . substr( $slug_hash, 0, 35 );
452 563 // Return the key.
@@ -474,9 +585,9 @@
474 585 private function clear_cache_item( $slug ) {
475 586 if ( isset( $slug ) ) {
476 587 $cache_key = $this->create_cache_key( $slug );
477 588 delete_site_transient( $cache_key );
478 - }
589 + }
479 590 }
480 591
481 592
482 593 /**
@@ -483,9 +594,9 @@
483 594 * Selectively delete cache for plugins that have been updated.
484 595 */
485 596 public function upgrade_delete_cache_items( $upgrader, $data ) {
486 597 // Check if plugins have been upgraded by WP.
487 - if ( isset( $data ) && is_array( $data['plugins'] ) ) {
598 + if ( isset( $data ) && isset( $data['plugins'] ) && is_array( $data['plugins'] ) ) {
488 599 // Loop through the plugins, and delete the associated cache items.
489 600 foreach ( $data['plugins'] as $key => $value ) {
490 601 $slug = $this->get_plugin_slug( $value );
491 602 $this->clear_cache_item( $slug );
@@ -495,8 +606,8 @@
495 606
496 607 }
497 608
498 609 // Instantiate the class.
499 - $rt_plugin_report_instance = new RT_Plugin_Report();
500 - $rt_plugin_report_instance->init();
610 + $plugin_report_instance = new RT_Plugin_Report();
611 + $plugin_report_instance->init();
501 612
502 613 }