PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.83
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / admin / notices / RatingNotice.php

RatingNotice.php in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.83, at includes/admin/notices/RatingNotice.php

322 lines 12.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Rating Notice for King Addons
4 * Shows an interactive star rating notice in the WordPress admin
5 */
6
7 namespace King_Addons\Admin\Notices;
8
9 if (!defined('ABSPATH')) {
10 exit;
11 }
12
13 class RatingNotice {
14
15 private const OPTION_DISMISS = 'king_addons_rating_dismiss';
16 private const OPTION_RATED = 'king_addons_rating_rated';
17 private const OPTION_LATER_TIME = 'king_addons_rating_later_time';
18 private const OPTION_ACTIVATION_TIME = 'king_addons_optionActivationTime';
19 private const DAYS_BEFORE_SHOW = 14;
20 private const DAYS_REMIND_LATER = 7;
21
22 /**
23 * Email for receiving low rating feedback
24 * Change this to your actual feedback email
25 */
26 private const FEEDBACK_EMAIL = 'starter@developer5.dev';
27
28 /**
29 * Singleton instance
30 */
31 private static ?RatingNotice $instance = null;
32
33 /**
34 * Get singleton instance
35 */
36 public static function instance(): RatingNotice {
37 if (is_null(self::$instance)) {
38 self::$instance = new self();
39 }
40 return self::$instance;
41 }
42
43 /**
44 * Constructor
45 */
46 public function __construct() {
47 if (!current_user_can('administrator')) {
48 return;
49 }
50
51 if (!empty(get_option(self::OPTION_DISMISS)) || !empty(get_option(self::OPTION_RATED))) {
52 return;
53 }
54
55 add_action('admin_init', [$this, 'check_show_notice']);
56 add_action('admin_enqueue_scripts', [$this, 'enqueue_assets']);
57
58 // AJAX handlers
59 add_action('wp_ajax_king_addons_rating_dismiss', [$this, 'ajax_dismiss']);
60 add_action('wp_ajax_king_addons_rating_later', [$this, 'ajax_later']);
61 add_action('wp_ajax_king_addons_rating_rated', [$this, 'ajax_rated']);
62 add_action('wp_ajax_king_addons_rating_feedback', [$this, 'ajax_feedback']);
63 }
64
65 /**
66 * Check if we should show the notice based on timing
67 *
68 * Logic:
69 * 1. If user clicked "Maybe Later" - check 7 days from that time
70 * 2. If user is an active free user (dismissed upgrade notice) - can show immediately
71 * 3. Otherwise - check 14 days from activation time
72 *
73 * This ensures:
74 * - New users see it after 14 days
75 * - Active free users (who dismissed upgrade notice) see it sooner
76 * - Premium users see it after 14 days (they don't have upgrade notice)
77 */
78 public function check_show_notice(): void {
79 if ($this->should_show_notice()) {
80 add_action('admin_notices', [$this, 'render_notice']);
81 }
82 }
83
84 /**
85 * Enqueue CSS and JS assets
86 */
87 public function enqueue_assets(): void {
88 if (!$this->should_show_notice()) {
89 return;
90 }
91
92 wp_enqueue_style(
93 'king-addons-rating-notice',
94 KING_ADDONS_URL . 'includes/admin/css/rating-notice.css',
95 [],
96 KING_ADDONS_VERSION
97 );
98
99 wp_enqueue_script(
100 'king-addons-rating-notice',
101 KING_ADDONS_URL . 'includes/admin/js/rating-notice.js',
102 ['jquery'],
103 KING_ADDONS_VERSION,
104 true
105 );
106
107 wp_localize_script('king-addons-rating-notice', 'KingAddonsRating', [
108 'ajaxurl' => admin_url('admin-ajax.php'),
109 'nonce' => wp_create_nonce('king-addons-rating-nonce'),
110 'wpOrgUrl' => 'https://wordpress.org/support/plugin/king-addons/reviews/?filter=5#new-post',
111 ]);
112 }
113
114 /**
115 * Check if notice should be displayed
116 *
117 * Priority logic:
118 * 1. Never show if already dismissed or rated
119 * 2. If "Maybe Later" was clicked - wait 7 days from that time
120 * 3. Premium users - show immediately (they paid, they're happy!)
121 * 4. If user dismissed upgrade notice (active free user) - can show after 3 days
122 * 5. Otherwise - wait 14 days from plugin activation
123 */
124 private function should_show_notice(): bool {
125 // Already dismissed or rated - never show
126 if (!empty(get_option(self::OPTION_DISMISS)) || !empty(get_option(self::OPTION_RATED))) {
127 return false;
128 }
129
130 $later_time = get_option(self::OPTION_LATER_TIME);
131 $activation_time = get_option(self::OPTION_ACTIVATION_TIME);
132 $user_id = get_current_user_id();
133
134 // Case 1: User clicked "Maybe Later" - check 7 days from that time
135 if ($later_time) {
136 $past_date = strtotime("-" . self::DAYS_REMIND_LATER . " days");
137 return $past_date >= $later_time;
138 }
139
140 // Case 2: Premium users - show immediately
141 // They already paid, they're clearly happy with the plugin!
142 if (function_exists('king_addons_freemius') && king_addons_freemius()->can_use_premium_code__premium_only()) {
143 return true;
144 }
145
146 // Case 3: Check if user previously dismissed the upgrade notice (active free user)
147 // This means they've been using the plugin actively
148 $upgrade_notice_dismissed_time = get_user_meta($user_id, 'king_addons_premium_notice_dismissed_time', true);
149 if ($upgrade_notice_dismissed_time) {
150 // Active user who dismissed upgrade notice - can show rating notice
151 // But let's give them at least 3 days after dismissing upgrade notice
152 $grace_period = strtotime("-3 days");
153 return $grace_period >= $upgrade_notice_dismissed_time;
154 }
155
156 // Case 4: Standard check - 14 days from activation
157 if (false === $activation_time) {
158 return false;
159 }
160
161 $past_date = strtotime("-" . self::DAYS_BEFORE_SHOW . " days");
162 return $past_date >= $activation_time;
163 }
164
165 /**
166 * Render the rating notice HTML
167 */
168 public function render_notice(): void {
169 $logo_url = KING_ADDONS_URL . 'includes/admin/img/icon-for-admin.svg';
170 ?>
171 <div class="notice king-addons-rating-notice is-dismissible">
172 <div class="king-addons-rating-notice-inner">
173 <div class="king-addons-rating-notice-logo">
174 <img src="<?php echo esc_url($logo_url); ?>" alt="King Addons">
175 </div>
176 <div class="king-addons-rating-notice-content">
177 <h3><?php esc_html_e('Enjoying King Addons for Elementor?', 'king-addons'); ?> 🎉</h3>
178 <p><?php esc_html_e('We hope you love using King Addons! Could you please take a moment to rate us? Your feedback helps us grow and improve!', 'king-addons'); ?></p>
179
180 <div class="king-addons-rating-stars" data-rating="0">
181 <?php for ($i = 1; $i <= 5; $i++): ?>
182 <span class="king-addons-star" data-star="<?php echo $i; ?>">
183 <svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
184 <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
185 </svg>
186 </span>
187 <?php endfor; ?>
188 <span class="king-addons-rating-text"></span>
189 </div>
190
191 <!-- Feedback form for low ratings -->
192 <div class="king-addons-feedback-form" style="display: none;">
193 <p><?php esc_html_e('We\'re sorry to hear that! Please tell us how we can improve:', 'king-addons'); ?></p>
194 <textarea class="king-addons-feedback-text" rows="3" placeholder="<?php esc_attr_e('Your feedback helps us make King Addons better...', 'king-addons'); ?>"></textarea>
195 <div class="king-addons-feedback-actions">
196 <button type="button" class="button button-primary king-addons-submit-feedback">
197 <?php esc_html_e('Send Feedback', 'king-addons'); ?>
198 </button>
199 <button type="button" class="button king-addons-skip-feedback">
200 <?php esc_html_e('Skip', 'king-addons'); ?>
201 </button>
202 </div>
203 </div>
204
205 <div class="king-addons-rating-actions">
206 <a href="#" class="king-addons-maybe-later">
207 <span class="dashicons dashicons-clock"></span>
208 <?php esc_html_e('Maybe Later', 'king-addons'); ?>
209 </a>
210 <a href="#" class="king-addons-already-rated">
211 <span class="dashicons dashicons-yes-alt"></span>
212 <?php esc_html_e('I Already Did', 'king-addons'); ?>
213 </a>
214 </div>
215 </div>
216 </div>
217 <button type="button" class="notice-dismiss king-addons-notice-dismiss-btn">
218 <span class="screen-reader-text"><?php esc_html_e('Dismiss this notice.', 'king-addons'); ?></span>
219 </button>
220 </div>
221 <?php
222 }
223
224 /**
225 * AJAX handler for dismissing the notice
226 */
227 public function ajax_dismiss(): void {
228 check_ajax_referer('king-addons-rating-nonce', 'nonce');
229
230 if (!current_user_can('manage_options')) {
231 wp_die();
232 }
233
234 update_option(self::OPTION_DISMISS, true);
235 wp_send_json_success();
236 }
237
238 /**
239 * AJAX handler for "Maybe Later"
240 */
241 public function ajax_later(): void {
242 check_ajax_referer('king-addons-rating-nonce', 'nonce');
243
244 if (!current_user_can('manage_options')) {
245 wp_die();
246 }
247
248 update_option(self::OPTION_LATER_TIME, time());
249 wp_send_json_success();
250 }
251
252 /**
253 * AJAX handler for "Already Rated"
254 */
255 public function ajax_rated(): void {
256 check_ajax_referer('king-addons-rating-nonce', 'nonce');
257
258 if (!current_user_can('manage_options')) {
259 wp_die();
260 }
261
262 update_option(self::OPTION_RATED, true);
263 wp_send_json_success();
264 }
265
266 /**
267 * AJAX handler for submitting feedback
268 */
269 public function ajax_feedback(): void {
270 check_ajax_referer('king-addons-rating-nonce', 'nonce');
271
272 if (!current_user_can('manage_options')) {
273 wp_die();
274 }
275
276 $rating = isset($_POST['rating']) ? absint($_POST['rating']) : 0;
277 $feedback = isset($_POST['feedback']) ? sanitize_textarea_field(wp_unslash($_POST['feedback'])) : '';
278
279 // Send email with feedback
280 $site_url = get_site_url();
281 $admin_email = get_option('admin_email');
282 $wp_version = get_bloginfo('version');
283 $plugin_version = defined('KING_ADDONS_VERSION') ? KING_ADDONS_VERSION : 'Unknown';
284
285 $subject = sprintf('[King Addons Feedback] Rating: %d star%s', $rating, $rating === 1 ? '' : 's');
286
287 $message = sprintf(
288 "New feedback received from King Addons user:\n\n" .
289 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" .
290 "Rating: %d star%s\n" .
291 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" .
292 "Site Details:\n" .
293 "• Site URL: %s\n" .
294 "• Admin Email: %s\n" .
295 "• WordPress Version: %s\n" .
296 "• Plugin Version: %s\n\n" .
297 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" .
298 "Feedback:\n" .
299 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" .
300 "%s\n\n" .
301 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n",
302 $rating,
303 $rating === 1 ? '' : 's',
304 $site_url,
305 $admin_email,
306 $wp_version,
307 $plugin_version,
308 $feedback ?: '(No feedback provided)'
309 );
310
311 $headers = [
312 'Content-Type: text/plain; charset=UTF-8',
313 'Reply-To: ' . $admin_email
314 ];
315
316 wp_mail(self::FEEDBACK_EMAIL, $subject, $message, $headers);
317
318 update_option(self::OPTION_RATED, true);
319 wp_send_json_success();
320 }
321 }
322