1 month * ago, not yet dismissed) and, when they are, registers the admin_notices * and footer-scripts callbacks that render the notice and its dismiss JS. * The `admin_init` hook is always registered to handle GET-based dismissals. * * @package Complianz_Terms_Conditions * @subpackage Review * * @since 1.0.0 */ class cmplz_tc_review { // phpcs:enable PEAR.NamingConventions.ValidClassName.StartWithCapital, PEAR.NamingConventions.ValidClassName.Invalid, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound /** * Holds the single instance of this class. * * @since 1.0.0 * @access private * @var cmplz_tc_review|null */ private static $_this; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore -- Underscore prefix is part of the established singleton accessor pattern used throughout this codebase. /** * Initialises the review notice system and registers the required hooks. * * Guards against instantiating more than once (singleton). For free, * single-site installs it checks whether the activation timestamp is older * than one month and the notice has not been dismissed, then conditionally * registers the AJAX callback, admin notice, and footer-script hooks. Also * seeds the activation timestamp for users who did not have it set yet. * * @since 1.0.0 * @access public */ public function __construct() { if ( isset( self::$_this ) ) { wp_die( esc_html( sprintf( '%s is a singleton class and you cannot create a second instance.', get_class( $this ) ) ) ); } self::$_this = $this; // Uncomment the lines below to reset the notice state during local testing. // update_option('cmplz_tc_review_notice_shown', false); // phpcs:ignore Squiz.Commenting.InlineComment.InvalidEndChar -- Commented-out debug code, not a prose comment. // update_option( 'cmplz_tc_activation_time', strtotime( "-2 month" ) ); // phpcs:ignore Squiz.Commenting.InlineComment.InvalidEndChar -- Commented-out debug code, not a prose comment. // Show the review notice only to free users on single-site installs. if ( ! defined( 'cmplz_tc_premium' ) && ! is_multisite() ) { // Register notice hooks only when: not yet dismissed, activation time is set, and > 1 month has passed. if ( ! get_option( 'cmplz_tc_review_notice_shown' ) && get_option( 'cmplz_tc_activation_time' ) && get_option( 'cmplz_tc_activation_time' ) < strtotime( '-1 month' ) ) { // AJAX handler for the "Maybe later" / X dismiss buttons in the notice. add_action( 'wp_ajax_dismiss_review_notice', array( $this, 'dismiss_review_notice_callback' ) ); // Render the styled review notice in the admin area. add_action( 'admin_notices', array( $this, 'show_leave_review_notice' ) ); // Output the inline JS that wires up the AJAX dismiss interactions. add_action( 'admin_print_footer_scripts', array( $this, 'insert_dismiss_review' ) ); } // Seed the activation timestamp for existing users who do not have it stored yet. if ( ! get_option( 'cmplz_tc_activation_time' ) ) { update_option( 'cmplz_tc_activation_time', time() ); } } // Always register the GET-based dismiss handler — it is more reliable than AJAX // in environments that block or time-out XHR requests. add_action( 'admin_init', array( $this, 'process_get_review_dismiss' ) ); } /** * Returns the single instance of this class. * * @since 1.0.0 * @access public * * @return cmplz_tc_review The singleton instance. */ public static function this() { return self::$_this; } /** * Renders the "Leave a review" admin notice. * * Outputs a styled WordPress admin notice containing a message, a link to * the WordPress.org review form, a "Maybe later" link (AJAX dismiss), and a * "Don't show again" link (GET dismiss). The notice is suppressed on the * Gutenberg editor screen because the block editor strips the CSS class used * by the AJAX dismiss handler. * * Hooked to: admin_notices. * * @since 1.0.0 * @access public * * @return void */ public function show_leave_review_notice() { // Suppress the notice when the user is already in the process of dismissing via GET. if ( isset( $_GET['cmplz_tc_dismiss_review'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only check; actual dismissal is handled by process_get_review_dismiss(). return; } // Gutenberg strips the cmplz-review CSS class needed by the AJAX dismiss handler; skip there. $screen = get_current_screen(); if ( 'edit' === $screen->parent_base ) { return; } ?>
', '' ); ?>
- Complianz