robotstxt-hello/includes/class-robotstxt-hello-plugin.php
2026-08-18 12:00:07 +00:00

314 lines
8.1 KiB
PHP

<?php
/**
* Main plugin class responsible for registering the Hello admin page
* and the Manager (by ROBOTSTXT) dependency notices.
*
* @package Robotstxt_Hello
*/
if ( ! class_exists( 'Robotstxt_Hello_Plugin' ) ) {
/**
* Handles registration of the Hello menu, page and notices.
*
* @since 1.0.0
*/
final class Robotstxt_Hello_Plugin {
/**
* Stores the menu slug used when registering the admin page.
*
* @since 1.0.4
*
* @var string
*/
const MENU_SLUG = 'robotstxt-hello';
/**
* URL of the Manager (by ROBOTSTXT) plugin page.
*
* @since 1.2.4
*
* @var string
*/
const MANAGER_PLUGIN_URL = 'https://www.robotstxt.software/plugins/robotstxt-manager/';
/**
* Option name for the "delete plugin data on uninstall" setting.
*
* @since 1.2.4
*
* @var string
*/
const OPTION_DELETE_DATA = 'robotstxt_hello_delete_data';
/**
* User meta key that stores the dismissal of the manager notice.
*
* @since 1.2.4
*
* @var string
*/
const USER_META_DISMISSED = 'robotstxt_hello_dismissed_manager_notice';
/**
* Registers WordPress hooks required by the plugin.
*
* @since 1.0.0
*
* @return void
*/
public function register() {
add_action( 'init', array( $this, 'load_textdomain' ) );
add_action( 'admin_menu', array( $this, 'register_admin_menu' ) );
add_action( 'admin_init', array( $this, 'register_settings' ) );
add_action( 'admin_notices', array( $this, 'render_manager_notice' ) );
add_action( 'network_admin_notices', array( $this, 'render_manager_notice' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
add_action( 'wp_ajax_robotstxt_hello_dismiss_manager_notice', array( $this, 'handle_dismiss' ) );
}
/**
* Loads the plugin text domain to make translations available.
*
* @since 1.0.4
*
* @return void
*/
public function load_textdomain() {
load_plugin_textdomain( 'robotstxt-hello', false, dirname( plugin_basename( ROBOTSTXT_HELLO_FILE ) ) . '/languages/' );
}
/**
* Registers the plugin setting with the Settings API.
*
* @since 1.2.4
*
* @return void
*/
public function register_settings() {
register_setting( 'robotstxt-hello', self::OPTION_DELETE_DATA, array( $this, 'sanitize_delete_data' ) );
}
/**
* Sanitizes the "delete plugin data on uninstall" checkbox value.
*
* @since 1.2.4
*
* @param mixed $value Raw submitted value.
* @return string '1' when enabled, empty string otherwise.
*/
public function sanitize_delete_data( $value ) {
return ( '1' === $value ) ? '1' : '';
}
/**
* Adds the Hello admin menu entry at the bottom of the menu list.
*
* The position is 1000: past the last core separator (99), so the item
* renders below every core entry. Positions are array keys in the
* menu array, so PHP_INT_MAX was avoided — it collides with other
* plugins using the same popular value on WordPress 4.0-6.4.
*
* @since 1.0.0
*
* @return void
*/
public function register_admin_menu() {
add_menu_page(
esc_html__( 'Hello', 'robotstxt-hello' ),
esc_html__( 'Hello', 'robotstxt-hello' ),
'manage_options',
self::MENU_SLUG,
array( $this, 'render_admin_page' ),
'dashicons-admin-site',
1000
);
}
/**
* Renders the Hello admin page content.
*
* @since 1.0.0
*
* @return void
*/
public function render_admin_page() {
echo '<div class="wrap">';
printf( '<h1>%s</h1>', esc_html__( 'Hello', 'robotstxt-hello' ) );
if ( ! $this->is_manager_active() ) {
$this->render_manager_message( false );
}
$this->render_settings_form();
echo '</div>';
}
/**
* Renders the plugin settings form.
*
* @since 1.2.4
*
* @return void
*/
private function render_settings_form() {
echo '<form method="post" action="options.php">';
settings_fields( 'robotstxt-hello' );
printf(
'<p><label for="robotstxt-hello-delete-data"><input type="checkbox" id="robotstxt-hello-delete-data" name="robotstxt_hello_delete_data" value="1"%1$s /> %2$s</label></p>',
checked( '1', get_option( self::OPTION_DELETE_DATA, '' ), false ),
esc_html__( 'Delete plugin data on uninstall', 'robotstxt-hello' )
);
printf( '<p class="description">%s</p>', esc_html__( 'All plugin data will be removed when the plugin is uninstalled.', 'robotstxt-hello' ) );
submit_button();
echo '</form>';
}
/**
* Renders the Manager (by ROBOTSTXT) notice on the plugins list page.
*
* The notice only appears on the plugins list page (single site or
* network), only while the manager plugin is not active, and only
* for users who have not dismissed it yet.
*
* @since 1.2.4
*
* @return void
*/
public function render_manager_notice() {
$screen = get_current_screen();
if ( ! $screen instanceof WP_Screen ) {
return;
}
if ( ! in_array( $screen->id, array( 'plugins', 'plugins-network' ), true ) ) {
return;
}
if ( $this->is_manager_active() || $this->is_notice_dismissed() ) {
return;
}
$this->render_manager_message( true );
}
/**
* Renders the shared Manager (by ROBOTSTXT) recommendation message.
*
* @since 1.2.4
*
* @param bool $dismissible Whether the notice can be dismissed.
* @return void
*/
private function render_manager_message( $dismissible ) {
$classes = 'notice notice-warning robotstxt-hello-manager-notice';
if ( $dismissible ) {
$classes .= ' is-dismissible';
}
printf(
'<div id="robotstxt-hello-manager-notice" class="%1$s"><p>%2$s <a href="%3$s">%4$s</a></p></div>',
esc_attr( $classes ),
esc_html__( 'To receive automatic updates, the plugin Manager (by ROBOTSTXT) must be installed and active.', 'robotstxt-hello' ),
esc_url( self::MANAGER_PLUGIN_URL ),
esc_html__( 'Get Manager (by ROBOTSTXT)', 'robotstxt-hello' )
);
}
/**
* Enqueues the dismissal script on the plugins list page.
*
* @since 1.2.4
*
* @param string $hook_suffix Current admin page hook suffix.
* @return void
*/
public function enqueue_scripts( $hook_suffix ) {
if ( 'plugins.php' !== $hook_suffix ) {
return;
}
if ( $this->is_manager_active() || $this->is_notice_dismissed() ) {
return;
}
wp_enqueue_script(
'robotstxt-hello-manager-notice',
plugins_url( 'assets/js/manager-notice.js', ROBOTSTXT_HELLO_FILE ),
array(),
ROBOTSTXT_HELLO_VERSION,
true
);
wp_localize_script(
'robotstxt-hello-manager-notice',
'robotstxthellomanagernotice',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'robotstxt-hello-manager-notice' ),
)
);
}
/**
* Persists the dismissal of the manager notice for the current user.
*
* @since 1.2.4
*
* @return void
*/
public function handle_dismiss() {
check_ajax_referer( 'robotstxt-hello-manager-notice', 'nonce' );
if ( ! current_user_can( 'activate_plugins' ) ) {
wp_die( '', '', 403 );
}
update_user_meta( get_current_user_id(), self::USER_META_DISMISSED, '1' );
wp_die( '', '', 200 );
}
/**
* Checks whether the Manager (by ROBOTSTXT) plugin is active.
*
* Detection covers both single-site and network-wide activation.
*
* @since 1.2.4
*
* @return bool True when any active plugin basename starts with 'robotstxt-manager/'.
*/
private function is_manager_active() {
$active = (array) get_option( 'active_plugins', array() );
if ( is_multisite() ) {
$active = array_merge( $active, array_keys( (array) get_site_option( 'active_sitewide_plugins', array() ) ) );
}
foreach ( $active as $basename ) {
if ( is_string( $basename ) && 0 === strpos( $basename, 'robotstxt-manager/' ) ) {
return true;
}
}
return false;
}
/**
* Checks whether the current user dismissed the manager notice.
*
* @since 1.2.4
*
* @return bool True when the notice was dismissed by the current user.
*/
private function is_notice_dismissed() {
return '1' === get_user_meta( get_current_user_id(), self::USER_META_DISMISSED, true );
}
}
}