v1.8.3
This commit is contained in:
parent
6c6a7fca00
commit
7f89e98bbc
18 changed files with 2227 additions and 1853 deletions
209
includes/Admin/ManagerNotice.php
Normal file
209
includes/Admin/ManagerNotice.php
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
<?php
|
||||
/**
|
||||
* Manager plugin dependency notice.
|
||||
*
|
||||
* Media Audit ships without a self-updater; updates are delivered by the
|
||||
* Manager (by ROBOTSTXT) plugin. This component nudges the administrator
|
||||
* when Manager is missing: a dismissible notice on the Plugins page and a
|
||||
* permanent inline notice on the plugin Settings pages.
|
||||
*
|
||||
* @package MediaRightsAudit\Admin
|
||||
*/
|
||||
|
||||
namespace MediaRightsAudit\Admin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows update-manager dependency notices.
|
||||
*/
|
||||
final class ManagerNotice {
|
||||
|
||||
/**
|
||||
* Manager plugin folder slug.
|
||||
*/
|
||||
public const MANAGER_SLUG = 'robotstxt-manager';
|
||||
|
||||
/**
|
||||
* Manager plugin page URL.
|
||||
*/
|
||||
public const MANAGER_URL = 'https://www.robotstxt.software/plugins/robotstxt-manager/';
|
||||
|
||||
/**
|
||||
* User-meta key that records a dismissed notice (per user).
|
||||
*/
|
||||
private const DISMISS_KEY = 'robotstxt_mediaaudit_manager_notice_dismissed';
|
||||
|
||||
/**
|
||||
* GET argument used by the dismiss link.
|
||||
*/
|
||||
private const DISMISS_ARG = 'robotstxt_mediaaudit_dismiss_manager_notice';
|
||||
|
||||
/**
|
||||
* Nonce action for the dismiss link.
|
||||
*/
|
||||
private const DISMISS_ACTION = 'robotstxt_mediaaudit_dismiss_manager_notice';
|
||||
|
||||
/**
|
||||
* Registers the admin hooks (site and network admin).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function register_hooks(): void {
|
||||
add_action( 'admin_notices', array( __CLASS__, 'render_plugins_page_notice' ) );
|
||||
add_action( 'network_admin_notices', array( __CLASS__, 'render_plugins_page_notice' ) );
|
||||
add_action( 'admin_init', array( __CLASS__, 'handle_dismiss' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the Manager plugin is installed and active.
|
||||
*
|
||||
* Checks site-level and network-wide activation, plus a filter so the
|
||||
* Manager itself can report its own state.
|
||||
*
|
||||
* @return bool True when Manager is active.
|
||||
*/
|
||||
public static function is_manager_active(): bool {
|
||||
if ( ! function_exists( 'is_plugin_active' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'is_plugin_active' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$active = false;
|
||||
|
||||
// Canonical main file first (fast path).
|
||||
$basename = self::MANAGER_SLUG . '/' . self::MANAGER_SLUG . '.php';
|
||||
if ( is_plugin_active( $basename ) || is_plugin_active_for_network( $basename ) ) {
|
||||
$active = true;
|
||||
}
|
||||
|
||||
// Cover any other main-file name inside the canonical folder.
|
||||
if ( ! $active && function_exists( 'get_plugins' ) ) {
|
||||
foreach ( array_keys( get_plugins( '/' . self::MANAGER_SLUG ) ) as $file ) {
|
||||
if ( is_plugin_active( self::MANAGER_SLUG . '/' . $file ) ) {
|
||||
$active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters whether the Manager (by ROBOTSTXT) plugin is active.
|
||||
*
|
||||
* @param bool $active Whether Manager is detected as active.
|
||||
*/
|
||||
return (bool) apply_filters( 'robotstxt_mediaaudit_manager_active', $active );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the dismissible notice on the Plugins page when Manager is missing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function render_plugins_page_notice(): void {
|
||||
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
|
||||
if ( ! $screen instanceof \WP_Screen || ! in_array( $screen->base, array( 'plugins', 'plugins-network' ), true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self::is_manager_active() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'install_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( '1' === get_user_meta( get_current_user_id(), self::DISMISS_KEY, true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dismiss_url = wp_nonce_url(
|
||||
add_query_arg( self::DISMISS_ARG, 1 ),
|
||||
self::DISMISS_ACTION
|
||||
);
|
||||
|
||||
echo '<div class="notice notice-warning"><p>'
|
||||
. wp_kses( self::message(), array( 'a' => array( 'href' => true ) ) )
|
||||
. ' <a href="' . esc_url( $dismiss_url ) . '" class="button button-small">' . esc_html__( 'Dismiss', 'robotstxt-mediaaudit' ) . '</a>'
|
||||
. '</p></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the permanent inline notice for the Settings pages (not dismissible).
|
||||
*
|
||||
* Used on both the site Settings page and the Network Settings page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function render_settings_notice(): void {
|
||||
if ( self::is_manager_active() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<div class="notice notice-warning inline" style="margin:16px 0;">'
|
||||
. '<p>' . wp_kses( self::message(), array( 'a' => array( 'href' => true ) ) ) . '</p>'
|
||||
. '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the dismiss link: verifies the nonce, stores the dismissal (PRG).
|
||||
*
|
||||
* Also clears a stored dismissal once Manager is active again, so the
|
||||
* notice returns if Manager is ever removed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function handle_dismiss(): void {
|
||||
$user_id = get_current_user_id();
|
||||
$dismissed = $user_id && get_user_meta( $user_id, self::DISMISS_KEY, true );
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- presence check only; state changes require the nonce below.
|
||||
if ( ! isset( $_GET[ self::DISMISS_ARG ] ) && ! $dismissed ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self::is_manager_active() ) {
|
||||
if ( $dismissed ) {
|
||||
delete_user_meta( $user_id, self::DISMISS_KEY );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no state change without the nonce check below.
|
||||
if ( ! isset( $_GET[ self::DISMISS_ARG ] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'install_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
check_admin_referer( self::DISMISS_ACTION );
|
||||
|
||||
update_user_meta( $user_id, self::DISMISS_KEY, '1' );
|
||||
|
||||
wp_safe_redirect( remove_query_arg( array( self::DISMISS_ARG, '_wpnonce' ) ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the shared notice message (translation with a link placeholder).
|
||||
*
|
||||
* The result must be passed through wp_kses() at output time.
|
||||
*
|
||||
* @return string Unescaped message HTML.
|
||||
*/
|
||||
private static function message(): string {
|
||||
return sprintf(
|
||||
/* translators: %s: Manager plugin page URL. */
|
||||
__( 'To receive plugin updates, the plugin <a href="%s">Manager (by ROBOTSTXT)</a> must be installed and active.', 'robotstxt-mediaaudit' ),
|
||||
esc_url( self::MANAGER_URL )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -963,6 +963,8 @@ class Settings {
|
|||
<div class="wrap">
|
||||
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
||||
|
||||
<?php ManagerNotice::render_settings_notice(); ?>
|
||||
|
||||
<nav class="nav-tab-wrapper">
|
||||
<?php foreach ( $tabs as $key => $label ) : ?>
|
||||
<a
|
||||
|
|
|
|||
Loading…
Reference in a new issue