Frequently in site maintenance, we encounter plugin issues that recur for extended periods of time, across multiple plugin updates. A common problem will be a bad update or update scheme, sometimes as a consequence of poor or incomplete coding by the plugin vendor, sometimes by the development of conficts that a given vendor or even the WordPress team may be slow to address.
At other times, there might be some aspect of a given plugin implementation that you may wish to note for future reference, yours or others: a Premium plugin that’s used only for transitory convenience or very specific task, a plugin that’s currently under assessment or that’s being temporarily kept on hand for reference. In a multisite environment, it might be helpful to note specific sites where a plugin is activated.



The following custom plugin is deployed at an actually existing multisite installation.
<?php
/**
* Plugin Name: GBES Annotate Plugins
* Plugin URI: https://ckmswp.com
* Description: Selectively annotate plugins and optionally disable updates
* Version: 0.2
* Author: CK MacLeod
* Author URI: https://ckmswp.com
* @todo update this plugin or create new one that uses do_action( 'core_upgrade_preamble' ); to add notes to upgrade page
*/
function gbes_get_plugins_page_id() {
switch_to_blog( 21 ) ;
$query = new WP_Query(
array(
'post_type' => 'docs',
'title' => 'Plugin Annotations',
'post_status' => 'all',
'posts_per_page' => 1,
'no_found_rows' => true,
'ignore_sticky_posts' => true,
'update_post_term_cache' => false,
'update_post_meta_cache' => false,
'orderby' => 'post_date ID',
'order' => 'ASC',
) );
if ( ! empty( $query->post ) ) {
$page_got_by_title = $query->post;
$page_id = $page_got_by_title->ID ;
} else {
$page_id = 0 ;
}
restore_current_blog() ;
return $page_id ;
}
function gbes_get_acf_repeater_values() {
$rows = array() ;
//ACF Interface installed at GBES University site
switch_to_blog( 21 ) ;
$page_id = gbes_get_plugins_page_id() ;
if ( function_exists( 'get_field' ) ) {
$rows = get_field( 'field_693cb71d2bd54', $page_id ) ; //"plugin_handling"
}
restore_current_blog() ;
return $rows ;
}
/**
* Add annotation to row meta
* @todo figure out how to use "in_plugin_update_message-{$file}", $plugin_data, $response ) from update.php
* @param array $plugin_meta elements that appear in a row separated by '|' beneath plugin description
* @param string $plugin_file plugin-folder/plugin-main-file.php
*/
add_filter( 'plugin_row_meta', 'gbes_customize_plugin', 10, 2 ) ;
function gbes_customize_plugin( $plugin_meta, $plugin_file ) {
$rows = gbes_get_acf_repeater_values() ;
foreach( $rows as $row ) {
$plugin_note = '<b>DEVELOPER NOTE: </b>' . $row['plugin_note'] ;
if ( $row['plugin_file'] === $plugin_file ) {
array_push( $plugin_meta, $plugin_note ) ;
}
}
return $plugin_meta ;
}
/**
* Update WordPress Core Updates Page
* do_action( "update-core-custom_{$action}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
*/
add_action( 'core_upgrade_preamble', 'gbes_add_to_core_preamble' ) ;
function gbes_add_to_core_preamble() {
$rows = gbes_get_acf_repeater_values() ;
foreach ( $rows as $row ) {
$update_core = $row['add_to_core_update'] ;
if ( $update_core ) {
echo '<div class="notice notice-warning update-prevention-message">
<h4><span style="inline-block; border: 1px solid; border-radius: 3px; padding: 0 6px;">' . $row['plugin_name'] . '</span>: ' . $row['plugin_note'] . '</h4>
</div>' ;
}
}
}
/**
* Output plugin annotations table displaying plugin names, plugin main files by path, and custom plugin notes
* @dependencies ACF and GBES Plugin Annotations
* @note DataTables library and initialization, custom CSS expected
*/
add_shortcode( 'we-docs-plugin-annotations-table', 'we_docs_plugin_annotations_table_handler' ) ;
function we_docs_plugin_annotations_table_handler() {
$post_id = get_the_ID() ;
$rows = get_field( 'plugin_handling', $post_id ) ;
ob_start() ;
echo '<h3>Last Updated: ' . get_field( 'last_edited', $post_id ) . ' ET </h3>' ;
echo '<table id="we-docs-list__table" class="data-table we-docs-list__table plugin-annotations" >' ;
echo '<thead class="data-table__head">
<tr class="data-table__heading--row data-table__row">' ;
echo '<th>Plugin Name</th><th>Plugin Main File Location</th><th>Plugin Note</th><th>Core Update</th>' ;
echo '</tr></thead>' ;
echo '<tbody>' ;
foreach( $rows as $row ) {
$name = $row['plugin_name'] ;
$file = $row['plugin_file'] ;
$note = $row['plugin_note'] ;
$update = $row['add_to_core_update'] ? '<i class="bb-icon-l buddyboss bb-icon-check" aria-hidden="true"></i>' : '' ;
echo '<tr>' ;
echo '<td>' . $name . '</td>' ;
echo '<td>' . $file . '</td>' ;
echo '<td>' . $note . '</td>' ;
echo '<td>' . $update . '</td>' ;
echo '</tr>' ;
}
echo '</tbody>' ;
echo '</table>' ;
return ob_get_clean() ;
}

