PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.10
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.10
2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 2.5.23 All 138 releases
metasync / includes / class-metasync-review-notice.php

class-metasync-review-notice.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.10, at includes/class-metasync-review-notice.php

241 lines 7.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Review Notice
4 *
5 * Handles display of admin notice asking users to rate the plugin on WordPress.org.
6 *
7 * @package Metasync
8 * @subpackage Metasync/includes
9 * @since 2.8.0
10 */
11
12 if (!defined('ABSPATH')) {
13 exit;
14 }
15
16 /**
17 * Class Metasync_Review_Notice
18 *
19 * Displays a dismissible admin notice prompting users to rate the plugin.
20 */
21 class Metasync_Review_Notice {
22
23 /**
24 * Singleton instance
25 *
26 * @var Metasync_Review_Notice|null
27 */
28 private static $instance = null;
29
30 /**
31 * Number of days after activation before showing the notice
32 *
33 * @var int
34 */
35 private const DAYS_BEFORE_SHOWING = 7;
36
37 /**
38 * Number of days to postpone when user clicks "Remind Me Later"
39 *
40 * @var int
41 */
42 private const REMIND_LATER_DAYS = 7;
43
44 /**
45 * WordPress.org review URL for the plugin
46 *
47 * @var string
48 */
49 private const REVIEW_URL = 'https://wordpress.org/support/plugin/metasync/reviews/#new-post';
50
51 /**
52 * Private constructor for singleton pattern
53 */
54 private function __construct() {
55 $this->init_hooks();
56 }
57
58 /**
59 * Get singleton instance
60 *
61 * @return Metasync_Review_Notice
62 */
63 public static function get_instance() {
64 if (self::$instance === null) {
65 self::$instance = new self();
66 }
67 return self::$instance;
68 }
69
70 /**
71 * Initialize WordPress hooks
72 */
73 private function init_hooks() {
74 add_action('admin_notices', [$this, 'display_review_notice']);
75 add_action('wp_ajax_metasync_dismiss_review_notice', [$this, 'ajax_dismiss_notice']);
76 add_action('wp_ajax_metasync_remind_later_review_notice', [$this, 'ajax_remind_later']);
77 add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']);
78 }
79
80 /**
81 * Check if the review notice should be displayed
82 *
83 * @return bool
84 */
85 private function should_display() {
86 // Don't show if whitelabel is enabled
87 if (class_exists('Metasync') && Metasync::is_whitelabel_enabled()) {
88 return false;
89 }
90
91 // Don't show if permanently dismissed
92 if (get_option('metasync_review_notice_dismissed', false)) {
93 return false;
94 }
95
96 // Check "remind me later" postponement
97 $remind_later = get_option('metasync_review_notice_remind_later', 0);
98 if ($remind_later && time() < (int) $remind_later) {
99 return false;
100 }
101
102 // Check if enough time has passed since first activation
103 $first_activation = get_option('metasync_first_activation_time', '');
104 if (empty($first_activation)) {
105 return false;
106 }
107
108 $activation_time = strtotime($first_activation);
109 if ($activation_time === false) {
110 return false;
111 }
112
113 $days_since_activation = (time() - $activation_time) / DAY_IN_SECONDS;
114 if ($days_since_activation < self::DAYS_BEFORE_SHOWING) {
115 return false;
116 }
117
118 return true;
119 }
120
121 /**
122 * Display the review notice
123 */
124 public function display_review_notice() {
125 if (!$this->should_display()) {
126 return;
127 }
128
129 if (!current_user_can('manage_options')) {
130 return;
131 }
132
133 $plugin_name = class_exists('Metasync') ? Metasync::get_effective_plugin_name() : 'Search Atlas';
134 $review_url = self::REVIEW_URL;
135 $nonce = wp_create_nonce('metasync_review_notice');
136
137 ?>
138 <div id="metasync-review-notice" class="notice notice-info" style="padding: 12px 16px; border-left-color: #f0b849;">
139 <div style="display: flex; align-items: center; gap: 14px;">
140 <div style="font-size: 28px; line-height: 1;">
141 <span class="dashicons dashicons-star-filled" style="font-size:28px;width:28px;height:28px;color:#f0b849;"></span>
142 </div>
143 <div style="flex: 1;">
144 <p style="margin: 0 0 6px 0; font-size: 14px;">
145 Enjoying <strong><?php echo esc_html($plugin_name); ?></strong>? Please consider leaving a rating to help us spread the word!
146 </p>
147 <p style="margin: 0; display: flex; gap: 10px; flex-wrap: wrap;">
148 <a href="<?php echo esc_url($review_url); ?>" target="_blank" rel="noopener noreferrer"
149 class="button button-primary metasync-review-rate-now"
150 style="background-color: #f0b849; border-color: #d9a53e; color: #1e1e1e;">
151
152 Rate Now
153 </a>
154 <button type="button" class="button metasync-review-remind-later">
155 Maybe Later
156 </button>
157 <button type="button" class="button-link metasync-review-dismiss" style="color: #646970; text-decoration: none; padding: 4px 8px;">
158 Already Did / No Thanks
159 </button>
160 </p>
161 </div>
162 </div>
163 </div>
164 <?php
165 }
166
167 /**
168 * Enqueue admin scripts for notice handling
169 *
170 * @param string $hook Current admin page hook.
171 */
172 public function enqueue_admin_scripts($hook) {
173 if (!$this->should_display()) {
174 return;
175 }
176
177 wp_add_inline_script('jquery', $this->get_notice_script(), 'after');
178 }
179
180 /**
181 * Get JavaScript for notice handling
182 *
183 * @return string JavaScript code.
184 */
185 private function get_notice_script() {
186 $nonce = wp_create_nonce('metasync_review_notice');
187
188 return "
189 jQuery(document).ready(function($) {
190 // Rate Now - dismiss permanently after clicking
191 $('#metasync-review-notice').on('click', '.metasync-review-rate-now', function() {
192 $.post(ajaxurl, {
193 action: 'metasync_dismiss_review_notice',
194 nonce: '" . esc_js($nonce) . "'
195 });
196 $('#metasync-review-notice').fadeOut();
197 });
198
199 // Maybe Later
200 $('#metasync-review-notice').on('click', '.metasync-review-remind-later', function() {
201 $.post(ajaxurl, {
202 action: 'metasync_remind_later_review_notice',
203 nonce: '" . esc_js($nonce) . "'
204 });
205 $('#metasync-review-notice').fadeOut();
206 });
207
208 // Already Did / No Thanks - dismiss permanently
209 $('#metasync-review-notice').on('click', '.metasync-review-dismiss', function() {
210 $.post(ajaxurl, {
211 action: 'metasync_dismiss_review_notice',
212 nonce: '" . esc_js($nonce) . "'
213 });
214 $('#metasync-review-notice').fadeOut();
215 });
216 });
217 ";
218 }
219
220 /**
221 * AJAX handler for permanently dismissing the review notice
222 */
223 public function ajax_dismiss_notice() {
224 check_ajax_referer('metasync_review_notice', 'nonce');
225
226 update_option('metasync_review_notice_dismissed', true);
227 wp_send_json_success(['message' => 'Notice dismissed']);
228 }
229
230 /**
231 * AJAX handler for "remind me later"
232 */
233 public function ajax_remind_later() {
234 check_ajax_referer('metasync_review_notice', 'nonce');
235
236 $remind_at = time() + (self::REMIND_LATER_DAYS * DAY_IN_SECONDS);
237 update_option('metasync_review_notice_remind_later', $remind_at);
238 wp_send_json_success(['message' => 'Reminder set']);
239 }
240 }
241