PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / trunk
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar vtrunk
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
← All changes | includes/Admin/Admin.php +517 -0 0.2.5.6trunk View file →
@@ -1,0 +1,517 @@
1 +<?php
2 +/**
3 + * Admin Class File.
4 + *
5 + * @package NotificationX\Admin
6 + */
7 +
8 +namespace NotificationX\Admin;
9 +
10 +use NotificationX\Admin\Rating\RatingEmail;
11 +use NotificationX\NotificationX;
12 +use NotificationX\Admin\Reports\ReportEmail;
13 +use NotificationX\Admin\Scanner\Scanner;
14 +use NotificationX\Core\Analytics;
15 +use NotificationX\Core\Dashboard;
16 +use NotificationX\Core\Database;
17 +use NotificationX\Core\PostType;
18 +use NotificationX\Core\SetupWizard;
19 +use NotificationX\Core\UsageTracker;
20 +use NotificationX\Core\Maintenance;
21 +use NotificationX\Core\Upgrader;
22 +use NotificationX\GetInstance;
23 +use NotificationX\Extensions\ExtensionFactory;
24 +
25 +use PriyoMukul\WPNotice\Notices;
26 +use PriyoMukul\WPNotice\Utils\CacheBank;
27 +use PriyoMukul\WPNotice\Utils\NoticeRemover;
28 +
29 +/**
30 + * Admin Class, this class is responsible for all Admin Actions
31 + * @method static Admin get_instance($args = null)
32 + */
33 +class Admin {
34 + /**
35 + * Instance of Admin
36 + *
37 + * @var Admin
38 + */
39 + use GetInstance;
40 + /**
41 + * Assets Path and URL
42 + */
43 + const ASSET_URL = NOTIFICATIONX_ASSETS . 'admin/';
44 + const ASSET_PATH = NOTIFICATIONX_ASSETS_PATH . 'admin/';
45 + const VIEWS_PATH = NOTIFICATIONX_INCLUDES . 'Admin/views/';
46 +
47 + private $insights = null;
48 +
49 + /**
50 + * @var CacheBank
51 + */
52 + private static $cache_bank;
53 +
54 + /**
55 + * Initially Invoked
56 + * when its initialized.
57 + */
58 + public function __construct(){
59 + /**
60 + * Admin Dashboard Widget
61 + * For Analytics
62 + */
63 + Analytics::get_instance();
64 + ReportEmail::get_instance();
65 + RatingEmail::get_instance();
66 + ImportExport::get_instance();
67 + XSS::get_instance();
68 + InfoTooltipManager::get_instance();
69 + UsageTracker::get_instance();
70 + Maintenance::get_instance();
71 + add_action('init', [$this, 'init'], 5);
72 + add_filter('nx_rest_miscellaneous', [$this, 'handle_miscellaneous_actions'], 10, 2);
73 + add_filter('nx_builder_configs', [$this, 'add_popup_status_to_context'], 10, 1);
74 + }
75 +
76 + /**
77 + * This method is reponsible for Admin Menu of
78 + * NotificationX
79 + *
80 + * @return void
81 + */
82 + public function init(){
83 + // Usage insights/tracking must initialize regardless of Pro being
84 + // active: Pro ships no insights of its own, so gating this behind
85 + // !is_pro() left the put_do_weekly_action cron with no listener and
86 + // disabled tracking (incl. the UsageTracker payload) on every Pro site.
87 + $this->plugin_usage_insights();
88 + if( ! NotificationX::is_pro() ){
89 + $this->admin_notices();
90 + $is_embedpress_milestone_showing = get_option('is_embedpress_milestone_showing', false);
91 + if (!$is_embedpress_milestone_showing) {
92 + MilestoneNotification::get_instance();
93 + }
94 + }
95 + add_action('admin_init', [$this, 'admin_init']);
96 + add_action('admin_menu', [$this, 'menu'], 10);
97 + Dashboard::get_instance();
98 + SetupWizard::get_instance();
99 + PostType::get_instance();
100 + Settings::get_instance()->init();
101 + Entries::get_instance();
102 + Scanner::get_instance();
103 + }
104 +
105 + /**
106 + * This method is responsible for Admin Menu of
107 + * NotificationX
108 + *
109 + * @return void
110 + */
111 + public function admin_init(){
112 + DashboardWidget::get_instance();
113 + add_action('in_admin_header', [ $this, 'hide_others_plugin_admin_notice' ], 99);
114 + }
115 +
116 + /**
117 + * This method is reponsible for Admin Menu of
118 + * NotificationX
119 + *
120 + * @return void
121 + */
122 + public function menu(){
123 + add_menu_page(
124 + 'NotificationX',
125 + 'NotificationX',
126 + 'read_notificationx', // User Permision.
127 + 'nx-admin',
128 + array( $this, 'views' ),
129 + self::ASSET_URL . 'images/logo-icon.svg',
130 + 80
131 + );
132 + add_submenu_page( 'nx-admin', __('All NotificationX', 'notificationx'), __('All NotificationX', 'notificationx'), 'read_notificationx', 'nx-admin', null, 1 );
133 + }
134 +
135 + /**
136 + * Admin Views
137 + *
138 + * @return void
139 + */
140 + public function views() {
141 + // react script included in PostType::admin_enqueue_scripts();
142 + include_once Admin::VIEWS_PATH . 'main.views.php';
143 + }
144 + /**
145 + * Get File Modification Time or URL
146 + *
147 + * @param string $file File relative path for Admin
148 + * @param boolean $url true for URL return
149 + * @return void|string|integer
150 + */
151 + public function file( $file, $url = false ){
152 + if( $url ) {
153 + return self::ASSET_URL . $file;
154 + }
155 + return filemtime( self::ASSET_PATH . $file );
156 + }
157 +
158 + /**
159 + * This method is responsible for re generating notification for single type.
160 + * @param string $current_url
161 + * @since 1.4.0
162 + */
163 + public function regenerate_notifications($params) {
164 + $post_id = intval($params['nx_id']);
165 + // @todo should not query the settings here. source and other two should be passed in param.
166 + $post = PostType::get_instance()->get_post($post_id);
167 + $source = isset($post['source']) ? $post['source'] : false;
168 + $extension = ExtensionFactory::get_instance()->get($source);
169 + if (!empty($extension) && method_exists($extension, 'get_notification_ready') && $extension->is_active()) {
170 + Entries::get_instance()->delete_entries($post_id);
171 + $result = $extension->get_notification_ready($post, $post_id);
172 + return true;
173 + }
174 + return false;
175 + }
176 +
177 + /**
178 + * This method is responsible for re generating notification for single type.
179 + * @param string $current_url
180 + * @since 1.4.0
181 + */
182 + public function reset_notifications($params) {
183 + $nx_id = null;
184 + if (!empty($entry_key)) {
185 + $nx_id = $params['entry_key'];
186 + }
187 + if (!empty($params['nx_id'])) {
188 + $nx_id = $params['nx_id'];
189 + }
190 + if (!empty($nx_id)) {
191 + return Analytics::get_instance()->delete_analytics($nx_id);
192 + }
193 + }
194 +
195 +
196 +
197 + public function admin_notices(){
198 + self::$cache_bank = CacheBank::get_instance();
199 + try {
200 + $this->notices();
201 + } catch ( \Exception $e ) {
202 + unset( $e );
203 + }
204 + // Remove OLD notice from 1.0.0 (if other WPDeveloper plugin has notice)
205 + NoticeRemover::get_instance( '1.0.0' );
206 + }
207 +
208 +
209 + public function hide_others_plugin_admin_notice()
210 + {
211 + $current_screen = get_current_screen();
212 + $hide_on = ['toplevel_page_nx-admin', 'notificationx_page_nx-dashboard', 'notificationx_page_nx-edit','notificationx_page_nx-settings','notificationx_page_nx-analytics','notificationx_page_nx-builder', 'notificationx_page_nx-feedback-entries'];
213 + if ( $current_screen && isset( $current_screen->base ) && in_array($current_screen->base, $hide_on) ) {
214 + remove_all_actions('user_admin_notices');
215 + remove_all_actions('admin_notices');
216 + }
217 + }
218 +
219 + public function notices() {
220 + $notices = new Notices([
221 + 'id' => 'notificationx',
222 + 'store' => 'options',
223 + 'storage_key' => 'notices',
224 + 'version' => '1.0.0',
225 + 'lifetime' => 3,
226 + 'stylesheet_url' => '',
227 + 'styles' => self::ASSET_URL . 'css/wpdeveloper-review-notice.css',
228 + 'priority' => 5,
229 + // 'dev_mode' => true
230 + ]);
231 +
232 + $_review_notice = [
233 + 'thumbnail' => self::ASSET_URL . 'images/nx-icon.svg',
234 + 'html' => '<p>'. __( 'We hope you\'re enjoying NotificationX! Could you please do us a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?', 'notificationx' ) .'</p>',
235 + 'links' => [
236 + 'later' => array(
237 + 'link' => 'https://wpdeveloper.com/review-notificationx',
238 + 'target' => '_blank',
239 + 'label' => __( 'Ok, you deserve it!', 'notificationx' ),
240 + 'icon_class' => 'dashicons dashicons-external',
241 + ),
242 + 'allready' => array(
243 + 'label' => __( 'I already did', 'notificationx' ),
244 + 'icon_class' => 'dashicons dashicons-smiley',
245 + 'attributes' => [
246 + 'data-dismiss' => true
247 + ],
248 + ),
249 + 'maybe_later' => array(
250 + 'label' => __( 'Maybe Later', 'notificationx' ),
251 + 'icon_class' => 'dashicons dashicons-calendar-alt',
252 + 'attributes' => [
253 + 'data-later' => true
254 + ],
255 + ),
256 + 'support' => array(
257 + 'link' => 'https://wpdeveloper.com/support',
258 + 'label' => __( 'I need help', 'notificationx' ),
259 + 'icon_class' => 'dashicons dashicons-sos',
260 + ),
261 + 'never_show_again' => array(
262 + 'label' => __( 'Never show again', 'notificationx' ),
263 + 'icon_class' => 'dashicons dashicons-dismiss',
264 + 'attributes' => [
265 + 'data-dismiss' => true
266 + ],
267 + )
268 + ]
269 + ];
270 +
271 + $notices->add(
272 + 'review',
273 + $_review_notice,
274 + [
275 + 'start' => $notices->strtotime( '+7 day' ),
276 + 'recurrence' => 30,
277 + 'dismissible' => true,
278 + 'refresh' => NOTIFICATIONX_VERSION,
279 + ]
280 + );
281 +
282 + $notices->add(
283 + 'opt_in',
284 + [ $this->insights, 'notice' ],
285 + [
286 + 'classes' => 'updated put-dismiss-notice',
287 + 'start' => $notices->strtotime( '+30 days' ),
288 + 'dismissible' => true,
289 + 'refresh' => NOTIFICATIONX_VERSION,
290 + 'do_action' => 'wpdeveloper_notice_clicked_for_notificationx',
291 + 'display_if' => ! is_array( $notices->is_installed( 'notificationx-pro/notificationx-pro.php' ) )
292 + ]
293 + );
294 +
295 + $notice_text = sprintf('<div style="display: flex; align-items: center;">%s <a class="button button-primary" style="margin-left: 10px; background: #5614d5; border-color: #5614d5;" target="_blank" href="%s">%s</a></div>', __( '<p><strong>Black Friday Exclusive:</strong> SAVE up to 40% & access to <strong>NotificationX Pro</strong> features.</p>', 'notificationx' ), esc_url( 'https://notificationx.com/#pricing' ), __('Grab The Offer', 'notificationx') );
296 +
297 + $_black_friday = [
298 + 'thumbnail' => self::ASSET_URL . 'images/nx-icon.svg',
299 + 'html' => $notice_text,
300 + ];
301 +
302 + $notices->add(
303 + 'black_friday',
304 + $_black_friday,
305 + [
306 + 'start' => $notices->time(),
307 + 'recurrence' => false,
308 + 'dismissible' => true,
309 + 'expire' => strtotime( 'Wed, 30 Nov 2022 23:59:59 GMT' ),
310 + 'display_if' => ! is_array( $notices->is_installed( 'notificationx-pro/notificationx-pro.php' ) )
311 + ]
312 + );
313 +
314 +
315 + // New Notice
316 + $b_message = '<p>6th Anniversary Sale: Unlock premium features with <strong>up to 25% discounts</strong> & skyrocket your conversions 🚀</p><a class="button button-primary" href="https://wpdeveloper.com/upgrade/notificationx-bfcm" target="_blank">Upgrade to PRO</a>';
317 + $_black_friday_notice = [
318 + 'thumbnail' => self::ASSET_URL . 'images/full-logo.svg',
319 + 'html' => $b_message,
320 + ];
321 +
322 + $notices->add(
323 + '6th_anniversary',
324 + $_black_friday_notice,
325 + [
326 + 'start' => $notices->time(),
327 + 'recurrence' => false,
328 + 'dismissible' => true,
329 + 'refresh' => NOTIFICATIONX_VERSION,
330 + "expire" => strtotime( '11:59:59pm 20th September, 2024' ),
331 + // 'display_if' => ! is_plugin_active( 'notificationx-pro/notificationx-pro.php' )
332 + ]
333 + );
334 +
335 + $crown = self::ASSET_URL . 'images/crown.svg';
336 + // February Deal
337 + $_february_deal = "<p>Boost trust & conversions with real-time social proof notification alerts – now <strong>Flat 20% OFF! 🎁</strong></p>
338 + <div class='nx-notice-action-button'>
339 + <a style='display: inline-flex;column-gap:5px;' class='button button-primary' href='https://notificationx.com/feb2026-admin-notice' target='_blank'>
340 + Upgrade To PRO
341 + </a>
342 + <a class='nx-notice-action-dismiss dismiss-btn' data-dismiss='true' href='#'>
343 + I’ll Grab It Later
344 + </a>
345 + </div>
346 + ";
347 + $_february_deal_html = [
348 + 'thumbnail' => self::ASSET_URL . 'images/full-logo.svg',
349 + 'html' => $_february_deal,
350 + ];
351 + $notices->add(
352 + 'nx_february_deal',
353 + $_february_deal_html,
354 + [
355 + 'start' => strtotime('11:59:59pm 9th February, 2026'),
356 + 'recurrence' => false,
357 + 'dismissible' => true,
358 + 'refresh' => NOTIFICATIONX_VERSION,
359 + 'screens' => [ 'dashboard' ],
360 + "expire" => strtotime('11:59:59pm 7th March, 2026'),
361 + 'display_if' => !is_array( $notices->is_installed( 'notificationx-pro/notificationx-pro.php' ) )
362 + ]
363 + );
364 +
365 + // Spring Campaign 2026
366 + $_spring_deal = "<p><strong>🌸 Spring Savings:</strong> Boost conversions with real-time social proof & AI-powered notification alerts – now <strong>Flat 25% OFF!</strong> ⚡️</p>
367 + <div class='nx-notice-action-button'>
368 + <a style='display: inline-flex;column-gap:5px;' class='button button-primary' href='https://notificationx.com/spring2026-admin-notice' target='_blank'>
369 + Upgrade To Pro Now
370 + </a>
371 + <a class='nx-notice-action-dismiss dismiss-btn' data-dismiss='true' href='#'>
372 + Maybe Later
373 + </a>
374 + </div>
375 + ";
376 + $_spring_deal_html = [
377 + 'thumbnail' => self::ASSET_URL . 'images/full-logo.svg',
378 + 'html' => $_spring_deal,
379 + ];
380 + $notices->add(
381 + 'nx_spring_deal_2026',
382 + $_spring_deal_html,
383 + [
384 + 'start' => strtotime('12:00:00am 8th April, 2026'),
385 + 'recurrence' => false,
386 + 'dismissible' => true,
387 + 'refresh' => NOTIFICATIONX_VERSION,
388 + 'screens' => [ 'dashboard' ],
389 + "expire" => strtotime('11:59:59pm 10th May, 2026'),
390 + 'display_if' => !is_array( $notices->is_installed( 'notificationx-pro/notificationx-pro.php' ) )
391 + ]
392 + );
393 +
394 + // nx_summer_deal_2026 notice
395 + $_nx_summer_deal_2026_text = "<p>🏖️ Turn visitors into buyers — faster. Launch real-time social proof & AI-powered alerts that drive conversions <strong>- up to \$150 OFF!</strong></p>
396 + <div class='nx-notice-action-button' style='display: inline-flex;column-gap:5px;align-items:center;'>
397 + <a class='button button-primary' href='https://notificationx.com/summer2026-admin-notice' target='_blank'>Upgrade To Pro Now</a> <a class='nx-notice-action-dismiss dismiss-btn' data-dismiss='true' href='#'>I Don't Want Any Discount</a>
398 + </div>";
399 + $_nx_summer_deal_2026 = [
400 + 'thumbnail' => self::ASSET_URL . 'images/full-logo.svg',
401 + 'html' => $_nx_summer_deal_2026_text,
402 + ];
403 + $notices->add(
404 + 'nx_summer_deal_2026',
405 + $_nx_summer_deal_2026,
406 + [
407 + 'start' => $notices->time(),
408 + 'recurrence' => false,
409 + 'dismissible' => true,
410 + 'refresh' => NOTIFICATIONX_VERSION,
411 + 'screens' => [ 'dashboard' ],
412 + "expire" => strtotime( '11:59:59pm 25th June, 2026' ),
413 + 'display_if' => !is_array( $notices->is_installed( 'notificationx-pro/notificationx-pro.php' ) )
414 + ]
415 + );
416 +
417 + // $notices->init();
418 + self::$cache_bank->create_account( $notices );
419 + self::$cache_bank->calculate_deposits( $notices );
420 + }
421 +
422 + public function plugin_usage_insights(){
423 + if ( null !== $this->insights ) {
424 + return $this->insights;
425 + }
426 + $this->insights = PluginInsights::get_instance( NOTIFICATIONX_FILE, [
427 + 'opt_in' => true,
428 + 'goodbye_form' => true,
429 + 'item_id' => '6ba8d30bc0beaddb2540'
430 + ] );
431 + $this->insights->set_notice_options(array(
432 + 'notice' => __( 'Want to help make <strong>NotificationX</strong> even more awesome? You can get a <strong>10% discount coupon</strong> for Premium extensions if you allow us to track the usage.', 'notificationx' ),
433 + 'extra_notice' => __( 'We collect non-sensitive diagnostic data and plugin usage information.
434 + Your site URL, WordPress & PHP version, plugins & themes and email address to send you the
435 + discount coupon. This data lets us make sure this plugin always stays compatible with the most
436 + popular plugins and themes. No spam, I promise.', 'notificationx' ),
437 + ));
438 + $this->insights->init();
439 +
440 + return $this->insights;
441 + }
442 +
443 + /**
444 + * Handle miscellaneous REST API actions
445 + *
446 + * @param mixed $result
447 + * @param array $params
448 + * @return mixed
449 + */
450 + public function handle_miscellaneous_actions($result, $params) {
451 + if (isset($params['action']) && $params['action'] === 'dismiss_initial_popup') {
452 + return $this->dismiss_initial_popup();
453 + }
454 + return $result;
455 + }
456 +
457 + /**
458 + * Dismiss the initial popup
459 + *
460 + * @return bool
461 + */
462 + public function dismiss_initial_popup() {
463 + // Check user permissions
464 + if (!current_user_can('manage_options')) {
465 + return false;
466 + }
467 +
468 + // Update the option to mark popup as dismissed
469 + update_option('nx_force_popup_dismissed', '1');
470 + $result = update_option('nx_initial_popup_dismissed', true);
471 +
472 + return $result;
473 + }
474 +
475 + /**
476 + * Check if popup should be shown
477 + *
478 + * @return bool
479 + */
480 + public function should_show_initial_popup() {
481 + // Don't show if already dismissed
482 + if (get_option('nx_initial_popup_dismissed', false)) {
483 + return false;
484 + }
485 +
486 + // Don't show for non-admin users
487 + if (!current_user_can('manage_options')) {
488 + return false;
489 + }
490 +
491 + // Delay the popup until 1 day after installation. Quick Setup already
492 + // handles onboarding, so this stays out of the way on the first day.
493 + $install_time = get_option('nx_initial_popup_install_time', false);
494 + if (!$install_time) {
495 + $install_time = time();
496 + update_option('nx_initial_popup_install_time', $install_time);
497 + }
498 +
499 + if ((time() - (int) $install_time) < DAY_IN_SECONDS) {
500 + return false;
501 + }
502 +
503 + return true;
504 + }
505 +
506 + /**
507 + * Add popup status to admin context
508 + *
509 + * @param array $data
510 + * @return array
511 + */
512 + public function add_popup_status_to_context($data) {
513 + $data['show_initial_popup'] = $this->should_show_initial_popup();
514 + $data['nx_admin_notice_close'] = get_option('nx_admin_notice_close', false);
515 + return $data;
516 + }
517 +}