wp/lib/blobfolio/wp/bm/admin.php
public static function contributors_changed_notice() {
		// Do not display if disabled.
		if ('disabled' === get_option('bm_contributor_notice', false)) {
			return;
		}

		// We only want to display this on the plugins and update pages.
		$screen = get_current_screen();
		if (('update-core' !== $screen->id) && ('plugins' !== $screen->id)) {
			return;
		}

		// Make sure we've run remote checks before.
		if (
			(false === ($remote = get_option('bm_remote_contributors', false))) ||
			!count($remote)
		) {
			return;
		}

		// Make sure updates are checked.
		wp_update_plugins();
		$updates = get_site_transient('update_plugins');
		if (
			!isset($updates->response, $updates->checked) ||
			!is_array($updates->response) ||
			!count($updates->response)
		) {
			return;
		}

		// Look for any local/remote changes.
		$warnings = array();
		foreach ($updates->response as $k=>$v) {
			$slug = $v->slug;

			// Skip this plugin if there were no updates or remote data.
			if (!isset($updates->checked[$k], $remote[$slug])) {
				continue;
			}

			// Pull the local contributor data.
			$version = $updates->checked[$k];
			$local = static::get_local_contributors($slug, $version);
			if (!count($local)) {
				continue;
			}

			// Note the differences.
			$added = array_diff($remote[$slug], $local);
			$removed = array_diff($local, $remote[$slug]);
			if (count($added) || count($removed)) {
				$warnings[$slug] = array(
					'new'=>$added,
					'removed'=>$removed,
				);
			}
		}

		// Nothing to do?
		if (!count($warnings)) {
			return;
		}

		// Let's build some HTML for the output.
		foreach ($warnings as $k=>$v) {
			$tmp = array();

			foreach ($v['removed'] as $v2) {
				$tmp[] = '<span class="wp-ui-text-notification"><span class="dashicons dashicons-minus"></span> ' . esc_html($v2) . '</span>';
			}

			foreach ($v['new'] as $v2) {
				$tmp[] = '<span class="wp-ui-text-highlight"><span class="dashicons dashicons-plus"></span> ' . esc_html($v2) . '</span>';
			}

			$warnings[$k] = '<tr>
				<th scope="row" style="text-align: left; padding-right: 1em; vertical-align: middle;"><a href="' . esc_url("https://wordpress.org/plugins/{$k}/") . '" target="_blank" rel="noopener">' . esc_html($k) . '</a>:</th>
				<td style="vertical-align: middle;">' . implode('&nbsp;&nbsp;&nbsp;&nbsp; ', $tmp) . '</td>
			</tr>';
		}

		// Print the notice!
		?>
		<div class="notice notice-warning blob-mimes-contributor-notice">
			<?php
			echo '<p>' . sprintf(
				esc_html__('%s The list of contributors for one or more plugins has changed since you last performed updates.', 'blob-mimes'),
				'<strong>' . esc_html__('Warning', 'blob-mimes') . ':</strong>'
			) . ' <a href="javascript: alert(\'' . esc_js(esc_attr__('This can potentially pose a security threat if the new author(s) are not nice people. It is recommended you re-review the code before continuing.', 'blob-mimes')) . '\');" class="dashicons dashicons-editor-help"></a></p>';

			echo '<table style="margin: .5em 0 .5em 2em;"><tbody>' . implode('', $warnings) . '</tbody></table>';

			echo '<p class="description">' . sprintf(
				esc_html__('If you prefer not to receive these notices in the future, click %s.', 'blob-mimes'),
				'<a href="#" class="blob-mimes-contributor-notice--dismiss">' . esc_html__('here', 'blob-mimes') . '</a>'
			) . '</p>';
			?>

			<script>
				jQuery('.blob-mimes-contributor-notice--dismiss').click(function(e) {
					e.preventDefault();

					var notice = jQuery('.blob-mimes-contributor-notice'),
						data = {
							action: 'bm_ajax_disable_contributor_notice',
							n: '<?php echo wp_create_nonce('bm_ajax_disable_contributor_notice');?>'
						};

					notice.css('opacity', .5);

					jQuery.post(
						ajaxurl,
						data,
						function() {
							notice.remove();
						}
					);
				});
			</script>
		</div>
		<?php
	}
public static function contributors_changed_notice() {
		// Do not display if disabled.
		if ('disabled' === get_option('bm_contributor_notice', false)) {
			return;
		}

		// We only want to display this on the plugins and update pages.
		$screen = get_current_screen();
		if (('update-core' !== $screen->id) && ('plugins' !== $screen->id)) {
			return;
		}

		// Make sure we've run remote checks before.
		if (
			(false === ($remote = get_option('bm_remote_contributors', false))) ||
			!count($remote)
		) {
			return;
		}

		// Make sure updates are checked.
		wp_update_plugins();
		$updates = get_site_transient('update_plugins');
		if (
			!isset($updates->response, $updates->checked) ||
			!is_array($updates->response) ||
			!count($updates->response)
		) {
			return;
		}

		// Look for any local/remote changes.
		$warnings = array();
		foreach ($updates->response as $k=>$v) {
			$slug = $v->slug;

			// Skip this plugin if there were no updates or remote data.
			if (!isset($updates->checked[$k], $remote[$slug])) {
				continue;
			}

			// Pull the local contributor data.
			$version = $updates->checked[$k];
			$local = static::get_local_contributors($slug, $version);
			if (!count($local)) {
				continue;
			}

			// Note the differences.
			$added = array_diff($remote[$slug], $local);
			$removed = array_diff($local, $remote[$slug]);
			if (count($added) || count($removed)) {
				$warnings[$slug] = array(
					'new'=>$added,
					'removed'=>$removed,
				);
			}
		}

		// Nothing to do?
		if (!count($warnings)) {
			return;
		}

		// Let's build some HTML for the output.
		foreach ($warnings as $k=>$v) {
			$tmp = array();

			foreach ($v['removed'] as $v2) {
				$tmp[] = '<span class="wp-ui-text-notification"><span class="dashicons dashicons-minus"></span> ' . esc_html($v2) . '</span>';
			}

			foreach ($v['new'] as $v2) {
				$tmp[] = '<span class="wp-ui-text-highlight"><span class="dashicons dashicons-plus"></span> ' . esc_html($v2) . '</span>';
			}

			$warnings[$k] = '<tr>
				<th scope="row" style="text-align: left; padding-right: 1em; vertical-align: middle;"><a href="' . esc_url("https://wordpress.org/plugins/{$k}/") . '" target="_blank" rel="noopener">' . esc_html($k) . '</a>:</th>
				<td style="vertical-align: middle;">' . implode('&nbsp;&nbsp;&nbsp;&nbsp; ', $tmp) . '</td>
			</tr>';
		}

		// Print the notice!
		?>
		<div class="notice notice-warning blob-mimes-contributor-notice">
			<?php
			echo '<p>' . sprintf(
				esc_html__('%s The list of contributors for one or more plugins has changed since you last performed updates.', 'blob-mimes'),
				'<strong>' . esc_html__('Warning', 'blob-mimes') . ':</strong>'
			) . ' <a href="javascript: alert(\'' . esc_js(esc_attr__('This can potentially pose a security threat if the new author(s) are not nice people. It is recommended you re-review the code before continuing.', 'blob-mimes')) . '\');" class="dashicons dashicons-editor-help"></a></p>';

			echo '<table style="margin: .5em 0 .5em 2em;"><tbody>' . implode('', $warnings) . '</tbody></table>';

			echo '<p class="description">' . sprintf(
				esc_html__('If you prefer not to receive these notices in the future, click %s.', 'blob-mimes'),
				'<a href="#" class="blob-mimes-contributor-notice--dismiss">' . esc_html__('here', 'blob-mimes') . '</a>'
			) . '</p>';
			?>

			<script>
				jQuery('.blob-mimes-contributor-notice--dismiss').click(function(e) {
					e.preventDefault();

					var notice = jQuery('.blob-mimes-contributor-notice'),
						data = {
							action: 'bm_ajax_disable_contributor_notice',
							n: '<?php echo wp_create_nonce('bm_ajax_disable_contributor_notice');?>'
						};

					notice.css('opacity', .5);

					jQuery.post(
						ajaxurl,
						data,
						function() {
							notice.remove();
						}
					);
				});
			</script>
		</div>
		<?php
	}
Contributor Change Notice

Warn users if a pending plugin update has different contributors
than the version they currently have installed.

@see https://core.trac.wordpress.org/ticket/42255
@see https://meta.trac.wordpress.org/ticket/3207

@return void Nothing.