PluginProbe ʕ •ᴥ•ʔ
FrontBlocks for Gutenberg/GeneratePress / 1.5.2
FrontBlocks for Gutenberg/GeneratePress v1.5.2
1.5.2 1.5.1 1.4.0 1.5.0 trunk 0.2.0 0.2.1 0.2.2 0.2.3 0.2.4 0.2.5 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 ci-artifacts
frontblocks / includes / Admin / ReviewNotice.php
frontblocks / includes / Admin Last commit date
RedundantPlugins.php 3 days ago ReviewNotice.php 5 days ago Settings.php 3 days ago UI.php 2 months ago
ReviewNotice.php
152 lines
1 <?php
2 /**
3 * Admin Review Notice
4 *
5 * @package FrontBlocks
6 * @author Closemarketing
7 * @copyright 2026 Closemarketing
8 * @version 1.0.0
9 */
10
11 namespace FrontBlocks\Admin;
12
13 defined( 'ABSPATH' ) || exit;
14
15 /**
16 * Shows a dismissible admin notice asking users to review the plugin,
17 * a set number of days after it was first activated.
18 */
19 class ReviewNotice {
20
21 /**
22 * Days to wait after activation before showing the notice.
23 *
24 * @var int
25 */
26 const DAYS_UNTIL_NOTICE = 14;
27
28 /**
29 * Constructor.
30 */
31 public function __construct() {
32 add_action( 'admin_notices', array( $this, 'review_notice' ) );
33 add_action( 'wp_ajax_frbl_dismiss_review_notice', array( $this, 'dismiss_review_notice' ) );
34 }
35
36 /**
37 * Display admin notice to remind users to leave a review on WordPress.org.
38 *
39 * @return void
40 */
41 public function review_notice() {
42 $debug = defined( 'FRBL_DEBUG_NOTICES' ) && FRBL_DEBUG_NOTICES;
43
44 if ( ! current_user_can( 'manage_options' ) ) {
45 return;
46 }
47
48 $screen = get_current_screen();
49 if ( ! $screen ) {
50 return;
51 }
52
53 if ( ! $debug ) {
54 $allowed_screens = array( 'appearance_page_frontblocks-settings', 'dashboard' );
55 if ( ! in_array( $screen->id, $allowed_screens, true ) && false === strpos( $screen->id, 'frontblocks' ) ) {
56 return;
57 }
58 }
59
60 $dismissed = get_user_meta( get_current_user_id(), 'frbl_review_notice_dismissed', true );
61 if ( ! $debug && $dismissed ) {
62 return;
63 }
64
65 $activation_date = get_option( 'frbl_activation_date' );
66 if ( ! $activation_date ) {
67 update_option( 'frbl_activation_date', time(), false );
68 if ( ! $debug ) {
69 return;
70 }
71 }
72
73 if ( ! $debug ) {
74 $days_active = ( time() - (int) $activation_date ) / DAY_IN_SECONDS;
75 if ( self::DAYS_UNTIL_NOTICE > $days_active ) {
76 return;
77 }
78 }
79
80 $review_url = 'https://wordpress.org/support/plugin/frontblocks/reviews/#new-post';
81
82 $notice_title = esc_html__( 'Enjoying FrontBlocks?', 'frontblocks' );
83
84 $notice_message = sprintf(
85 /* translators: %s is the review URL. */
86 __( 'Thank you for using FrontBlocks! If you find it helpful, please take a moment to <a href="%s" target="_blank" rel="noopener noreferrer">leave a review on WordPress.org</a>. It really helps the plugin grow!', 'frontblocks' ),
87 esc_url( $review_url )
88 );
89
90 echo '<div id="frbl-review-notice" class="notice notice-info is-dismissible">';
91 echo '<p><strong>' . esc_html( $notice_title ) . '</strong></p>';
92 $allowed_tags = array(
93 'a' => array(
94 'href' => array(),
95 'target' => array(),
96 'rel' => array(),
97 ),
98 );
99 echo '<p>' . wp_kses( $notice_message, $allowed_tags ) . '</p>';
100 echo '<p>';
101 echo '<a href="' . esc_url( $review_url ) . '" target="_blank" rel="noopener noreferrer" class="button button-primary">' . esc_html__( 'Leave a Review', 'frontblocks' ) . '</a>';
102 echo '&nbsp;&nbsp;';
103 echo '<a href="#" id="frbl-dismiss-review" class="button button-secondary">' . esc_html__( 'No thanks', 'frontblocks' ) . '</a>';
104 echo '</p>';
105 echo '</div>';
106
107 $this->enqueue_script();
108 }
109
110 /**
111 * Enqueue the JS needed to handle dismissal.
112 *
113 * @return void
114 */
115 private function enqueue_script() {
116 wp_enqueue_script(
117 'frbl-review-notice',
118 FRBL_PLUGIN_URL . 'assets/admin/review-notice.js',
119 array(),
120 FRBL_VERSION,
121 true
122 );
123
124 wp_localize_script(
125 'frbl-review-notice',
126 'frblReviewNotice',
127 array(
128 'ajaxurl' => admin_url( 'admin-ajax.php' ),
129 'nonce' => wp_create_nonce( 'frbl_dismiss_review' ),
130 )
131 );
132 }
133
134 /**
135 * AJAX handler to persist the notice dismissal for the current user.
136 *
137 * @return void
138 */
139 public function dismiss_review_notice() {
140 if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'frbl_dismiss_review' ) ) {
141 wp_die( esc_html__( 'Security check failed.', 'frontblocks' ), '', array( 'response' => 403 ) );
142 }
143
144 if ( ! current_user_can( 'manage_options' ) ) {
145 wp_die( esc_html__( 'You do not have permission to do this.', 'frontblocks' ), '', array( 'response' => 403 ) );
146 }
147
148 update_user_meta( get_current_user_id(), 'frbl_review_notice_dismissed', true );
149 wp_die();
150 }
151 }
152