PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / 3.3.3
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar v3.3.3
3.3.3 3.3.2 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 All 158 releases
← All changes | includes/Admin/Admin.php +575 -0 0.2.5.5 → 3.3.3 View file →
@@ -1,0 +1,575 @@
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 + /**
48 + * Oldest NotificationX Pro that ships its own copy of the Pro features the
49 + * free plugin is removing (Flashing Tab, Cart Peek, Inline). Older Pro keeps
50 + * working with this release, but loses those features once the free copies
51 + * are deleted. See docs/api/frontend-js-hooks.md.
52 + *
53 + * @since 3.3.3
54 + */
55 + const MIN_PRO_VERSION = '3.2.3';
56 +
57 + private $insights = null;
58 +
59 + /**
60 + * @var CacheBank
61 + */
62 + private static $cache_bank;
63 +
64 + /**
65 + * Initially Invoked
66 + * when its initialized.
67 + */
68 + public function __construct(){
69 + /**
70 + * Admin Dashboard Widget
71 + * For Analytics
72 + */
73 + Analytics::get_instance();
74 + ReportEmail::get_instance();
75 + RatingEmail::get_instance();
76 + ImportExport::get_instance();
77 + XSS::get_instance();
78 + InfoTooltipManager::get_instance();
79 + UsageTracker::get_instance();
80 + Maintenance::get_instance();
81 + add_action('init', [$this, 'init'], 5);
82 + add_filter('nx_rest_miscellaneous', [$this, 'handle_miscellaneous_actions'], 10, 2);
83 + add_filter('nx_builder_configs', [$this, 'add_popup_status_to_context'], 10, 1);
84 + }
85 +
86 + /**
87 + * This method is reponsible for Admin Menu of
88 + * NotificationX
89 + *
90 + * @return void
91 + */
92 + public function init(){
93 + // Usage insights/tracking must initialize regardless of Pro being
94 + // active: Pro ships no insights of its own, so gating this behind
95 + // !is_pro() left the put_do_weekly_action cron with no listener and
96 + // disabled tracking (incl. the UsageTracker payload) on every Pro site.
97 + $this->plugin_usage_insights();
98 + if( ! NotificationX::is_pro() ){
99 + $this->admin_notices();
100 + $is_embedpress_milestone_showing = get_option('is_embedpress_milestone_showing', false);
101 + if (!$is_embedpress_milestone_showing) {
102 + MilestoneNotification::get_instance();
103 + }
104 + }
105 + add_action('admin_init', [$this, 'admin_init']);
106 + add_action('admin_menu', [$this, 'menu'], 10);
107 + // all_admin_notices, not admin_notices: hide_others_plugin_admin_notice()
108 + // clears admin_notices on NotificationX screens, and this notice must
109 + // show there too.
110 + add_action('all_admin_notices', [$this, 'pro_version_notice']);
111 + Dashboard::get_instance();
112 + SetupWizard::get_instance();
113 + PostType::get_instance();
114 + Settings::get_instance()->init();
115 + Entries::get_instance();
116 + Scanner::get_instance();
117 + }
118 +
119 + /**
120 + * This method is responsible for Admin Menu of
121 + * NotificationX
122 + *
123 + * @return void
124 + */
125 + public function admin_init(){
126 + DashboardWidget::get_instance();
127 + add_action('in_admin_header', [ $this, 'hide_others_plugin_admin_notice' ], 99);
128 + }
129 +
130 + /**
131 + * This method is reponsible for Admin Menu of
132 + * NotificationX
133 + *
134 + * @return void
135 + */
136 + public function menu(){
137 + add_menu_page(
138 + 'NotificationX',
139 + 'NotificationX',
140 + 'read_notificationx', // User Permision.
141 + 'nx-admin',
142 + array( $this, 'views' ),
143 + self::ASSET_URL . 'images/logo-icon.svg',
144 + 80
145 + );
146 + add_submenu_page( 'nx-admin', __('All NotificationX', 'notificationx'), __('All NotificationX', 'notificationx'), 'read_notificationx', 'nx-admin', null, 1 );
147 + }
148 +
149 + /**
150 + * Admin Views
151 + *
152 + * @return void
153 + */
154 + public function views() {
155 + // react script included in PostType::admin_enqueue_scripts();
156 + include_once Admin::VIEWS_PATH . 'main.views.php';
157 + }
158 + /**
159 + * Get File Modification Time or URL
160 + *
161 + * @param string $file File relative path for Admin
162 + * @param boolean $url true for URL return
163 + * @return void|string|integer
164 + */
165 + public function file( $file, $url = false ){
166 + if( $url ) {
167 + return self::ASSET_URL . $file;
168 + }
169 + return filemtime( self::ASSET_PATH . $file );
170 + }
171 +
172 + /**
173 + * This method is responsible for re generating notification for single type.
174 + * @param string $current_url
175 + * @since 1.4.0
176 + */
177 + public function regenerate_notifications($params) {
178 + $post_id = intval($params['nx_id']);
179 + // @todo should not query the settings here. source and other two should be passed in param.
180 + $post = PostType::get_instance()->get_post($post_id);
181 + $source = isset($post['source']) ? $post['source'] : false;
182 + $extension = ExtensionFactory::get_instance()->get($source);
183 + if (!empty($extension) && method_exists($extension, 'get_notification_ready') && $extension->is_active()) {
184 + Entries::get_instance()->delete_entries($post_id);
185 + $result = $extension->get_notification_ready($post, $post_id);
186 + return true;
187 + }
188 + return false;
189 + }
190 +
191 + /**
192 + * This method is responsible for re generating notification for single type.
193 + * @param string $current_url
194 + * @since 1.4.0
195 + */
196 + public function reset_notifications($params) {
197 + $nx_id = null;
198 + if (!empty($entry_key)) {
199 + $nx_id = $params['entry_key'];
200 + }
201 + if (!empty($params['nx_id'])) {
202 + $nx_id = $params['nx_id'];
203 + }
204 + if (!empty($nx_id)) {
205 + return Analytics::get_instance()->delete_analytics($nx_id);
206 + }
207 + }
208 +
209 +
210 +
211 + public function admin_notices(){
212 + self::$cache_bank = CacheBank::get_instance();
213 + try {
214 + $this->notices();
215 + } catch ( \Exception $e ) {
216 + unset( $e );
217 + }
218 + // Remove OLD notice from 1.0.0 (if other WPDeveloper plugin has notice)
219 + NoticeRemover::get_instance( '1.0.0' );
220 + }
221 +
222 +
223 + /**
224 + * Whether the active NotificationX Pro is older than MIN_PRO_VERSION.
225 + *
226 + * @since 3.3.3
227 + * @param string|null $pro_version Pro version; defaults to NOTIFICATIONX_PRO_VERSION.
228 + * @return bool False when Pro is not active or its version is unknown.
229 + */
230 + public static function pro_needs_update( $pro_version = null ) {
231 + if ( null === $pro_version ) {
232 + if ( ! NotificationX::is_pro() || ! defined( 'NOTIFICATIONX_PRO_VERSION' ) ) {
233 + return false;
234 + }
235 + $pro_version = NOTIFICATIONX_PRO_VERSION;
236 + }
237 + if ( ! is_string( $pro_version ) || '' === $pro_version ) {
238 + return false;
239 + }
240 + return version_compare( $pro_version, self::MIN_PRO_VERSION, '<' );
241 + }
242 +
243 + /**
244 + * Non-dismissible notice asking to update an outdated NotificationX Pro.
245 + *
246 + * @since 3.3.3
247 + * @return void
248 + */
249 + public function pro_version_notice() {
250 + if ( ! current_user_can( 'update_plugins' ) || ! self::pro_needs_update() ) {
251 + return;
252 + }
253 + $message = sprintf(
254 + /* translators: 1: installed NotificationX Pro version, 2: required NotificationX Pro version. */
255 + __( 'You are using NotificationX Pro %1$s. Please update NotificationX Pro to version %2$s or later. Upcoming NotificationX releases move Flashing Tab, Cart Peek and Inline notifications fully into NotificationX Pro, and older Pro versions will stop showing them.', 'notificationx' ),
256 + '<strong>' . esc_html( NOTIFICATIONX_PRO_VERSION ) . '</strong>',
257 + '<strong>' . esc_html( self::MIN_PRO_VERSION ) . '</strong>'
258 + );
259 + printf(
260 + '<div class="notice notice-warning nx-pro-version-notice"><p>%1$s <a href="%2$s">%3$s</a></p></div>',
261 + wp_kses_post( $message ),
262 + esc_url( self_admin_url( 'plugins.php?plugin_status=upgrade' ) ),
263 + esc_html__( 'Go to plugin updates', 'notificationx' )
264 + );
265 + }
266 +
267 + public function hide_others_plugin_admin_notice()
268 + {
269 + $current_screen = get_current_screen();
270 + $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'];
271 + if ( $current_screen && isset( $current_screen->base ) && in_array($current_screen->base, $hide_on) ) {
272 + remove_all_actions('user_admin_notices');
273 + remove_all_actions('admin_notices');
274 + }
275 + }
276 +
277 + public function notices() {
278 + $notices = new Notices([
279 + 'id' => 'notificationx',
280 + 'store' => 'options',
281 + 'storage_key' => 'notices',
282 + 'version' => '1.0.0',
283 + 'lifetime' => 3,
284 + 'stylesheet_url' => '',
285 + 'styles' => self::ASSET_URL . 'css/wpdeveloper-review-notice.css',
286 + 'priority' => 5,
287 + // 'dev_mode' => true
288 + ]);
289 +
290 + $_review_notice = [
291 + 'thumbnail' => self::ASSET_URL . 'images/nx-icon.svg',
292 + '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>',
293 + 'links' => [
294 + 'later' => array(
295 + 'link' => 'https://wpdeveloper.com/review-notificationx',
296 + 'target' => '_blank',
297 + 'label' => __( 'Ok, you deserve it!', 'notificationx' ),
298 + 'icon_class' => 'dashicons dashicons-external',
299 + ),
300 + 'allready' => array(
301 + 'label' => __( 'I already did', 'notificationx' ),
302 + 'icon_class' => 'dashicons dashicons-smiley',
303 + 'attributes' => [
304 + 'data-dismiss' => true
305 + ],
306 + ),
307 + 'maybe_later' => array(
308 + 'label' => __( 'Maybe Later', 'notificationx' ),
309 + 'icon_class' => 'dashicons dashicons-calendar-alt',
310 + 'attributes' => [
311 + 'data-later' => true
312 + ],
313 + ),
314 + 'support' => array(
315 + 'link' => 'https://wpdeveloper.com/support',
316 + 'label' => __( 'I need help', 'notificationx' ),
317 + 'icon_class' => 'dashicons dashicons-sos',
318 + ),
319 + 'never_show_again' => array(
320 + 'label' => __( 'Never show again', 'notificationx' ),
321 + 'icon_class' => 'dashicons dashicons-dismiss',
322 + 'attributes' => [
323 + 'data-dismiss' => true
324 + ],
325 + )
326 + ]
327 + ];
328 +
329 + $notices->add(
330 + 'review',
331 + $_review_notice,
332 + [
333 + 'start' => $notices->strtotime( '+7 day' ),
334 + 'recurrence' => 30,
335 + 'dismissible' => true,
336 + 'refresh' => NOTIFICATIONX_VERSION,
337 + ]
338 + );
339 +
340 + $notices->add(
341 + 'opt_in',
342 + [ $this->insights, 'notice' ],
343 + [
344 + 'classes' => 'updated put-dismiss-notice',
345 + 'start' => $notices->strtotime( '+30 days' ),
346 + 'dismissible' => true,
347 + 'refresh' => NOTIFICATIONX_VERSION,
348 + 'do_action' => 'wpdeveloper_notice_clicked_for_notificationx',
349 + 'display_if' => ! is_array( $notices->is_installed( 'notificationx-pro/notificationx-pro.php' ) )
350 + ]
351 + );
352 +
353 + $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') );
354 +
355 + $_black_friday = [
356 + 'thumbnail' => self::ASSET_URL . 'images/nx-icon.svg',
357 + 'html' => $notice_text,
358 + ];
359 +
360 + $notices->add(
361 + 'black_friday',
362 + $_black_friday,
363 + [
364 + 'start' => $notices->time(),
365 + 'recurrence' => false,
366 + 'dismissible' => true,
367 + 'expire' => strtotime( 'Wed, 30 Nov 2022 23:59:59 GMT' ),
368 + 'display_if' => ! is_array( $notices->is_installed( 'notificationx-pro/notificationx-pro.php' ) )
369 + ]
370 + );
371 +
372 +
373 + // New Notice
374 + $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>';
375 + $_black_friday_notice = [
376 + 'thumbnail' => self::ASSET_URL . 'images/full-logo.svg',
377 + 'html' => $b_message,
378 + ];
379 +
380 + $notices->add(
381 + '6th_anniversary',
382 + $_black_friday_notice,
383 + [
384 + 'start' => $notices->time(),
385 + 'recurrence' => false,
386 + 'dismissible' => true,
387 + 'refresh' => NOTIFICATIONX_VERSION,
388 + "expire" => strtotime( '11:59:59pm 20th September, 2024' ),
389 + // 'display_if' => ! is_plugin_active( 'notificationx-pro/notificationx-pro.php' )
390 + ]
391 + );
392 +
393 + $crown = self::ASSET_URL . 'images/crown.svg';
394 + // February Deal
395 + $_february_deal = "<p>Boost trust & conversions with real-time social proof notification alerts – now <strong>Flat 20% OFF! 🎁</strong></p>
396 + <div class='nx-notice-action-button'>
397 + <a style='display: inline-flex;column-gap:5px;' class='button button-primary' href='https://notificationx.com/feb2026-admin-notice' target='_blank'>
398 + Upgrade To PRO
399 + </a>
400 + <a class='nx-notice-action-dismiss dismiss-btn' data-dismiss='true' href='#'>
401 + I’ll Grab It Later
402 + </a>
403 + </div>
404 + ";
405 + $_february_deal_html = [
406 + 'thumbnail' => self::ASSET_URL . 'images/full-logo.svg',
407 + 'html' => $_february_deal,
408 + ];
409 + $notices->add(
410 + 'nx_february_deal',
411 + $_february_deal_html,
412 + [
413 + 'start' => strtotime('11:59:59pm 9th February, 2026'),
414 + 'recurrence' => false,
415 + 'dismissible' => true,
416 + 'refresh' => NOTIFICATIONX_VERSION,
417 + 'screens' => [ 'dashboard' ],
418 + "expire" => strtotime('11:59:59pm 7th March, 2026'),
419 + 'display_if' => !is_array( $notices->is_installed( 'notificationx-pro/notificationx-pro.php' ) )
420 + ]
421 + );
422 +
423 + // Spring Campaign 2026
424 + $_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>
425 + <div class='nx-notice-action-button'>
426 + <a style='display: inline-flex;column-gap:5px;' class='button button-primary' href='https://notificationx.com/spring2026-admin-notice' target='_blank'>
427 + Upgrade To Pro Now
428 + </a>
429 + <a class='nx-notice-action-dismiss dismiss-btn' data-dismiss='true' href='#'>
430 + Maybe Later
431 + </a>
432 + </div>
433 + ";
434 + $_spring_deal_html = [
435 + 'thumbnail' => self::ASSET_URL . 'images/full-logo.svg',
436 + 'html' => $_spring_deal,
437 + ];
438 + $notices->add(
439 + 'nx_spring_deal_2026',
440 + $_spring_deal_html,
441 + [
442 + 'start' => strtotime('12:00:00am 8th April, 2026'),
443 + 'recurrence' => false,
444 + 'dismissible' => true,
445 + 'refresh' => NOTIFICATIONX_VERSION,
446 + 'screens' => [ 'dashboard' ],
447 + "expire" => strtotime('11:59:59pm 10th May, 2026'),
448 + 'display_if' => !is_array( $notices->is_installed( 'notificationx-pro/notificationx-pro.php' ) )
449 + ]
450 + );
451 +
452 + // nx_summer_deal_2026 notice
453 + $_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>
454 + <div class='nx-notice-action-button' style='display: inline-flex;column-gap:5px;align-items:center;'>
455 + <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>
456 + </div>";
457 + $_nx_summer_deal_2026 = [
458 + 'thumbnail' => self::ASSET_URL . 'images/full-logo.svg',
459 + 'html' => $_nx_summer_deal_2026_text,
460 + ];
461 + $notices->add(
462 + 'nx_summer_deal_2026',
463 + $_nx_summer_deal_2026,
464 + [
465 + 'start' => $notices->time(),
466 + 'recurrence' => false,
467 + 'dismissible' => true,
468 + 'refresh' => NOTIFICATIONX_VERSION,
469 + 'screens' => [ 'dashboard' ],
470 + "expire" => strtotime( '11:59:59pm 25th June, 2026' ),
471 + 'display_if' => !is_array( $notices->is_installed( 'notificationx-pro/notificationx-pro.php' ) )
472 + ]
473 + );
474 +
475 + // $notices->init();
476 + self::$cache_bank->create_account( $notices );
477 + self::$cache_bank->calculate_deposits( $notices );
478 + }
479 +
480 + public function plugin_usage_insights(){
481 + if ( null !== $this->insights ) {
482 + return $this->insights;
483 + }
484 + $this->insights = PluginInsights::get_instance( NOTIFICATIONX_FILE, [
485 + 'opt_in' => true,
486 + 'goodbye_form' => true,
487 + 'item_id' => '6ba8d30bc0beaddb2540'
488 + ] );
489 + $this->insights->set_notice_options(array(
490 + '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' ),
491 + 'extra_notice' => __( 'We collect non-sensitive diagnostic data and plugin usage information.
492 + Your site URL, WordPress & PHP version, plugins & themes and email address to send you the
493 + discount coupon. This data lets us make sure this plugin always stays compatible with the most
494 + popular plugins and themes. No spam, I promise.', 'notificationx' ),
495 + ));
496 + $this->insights->init();
497 +
498 + return $this->insights;
499 + }
500 +
501 + /**
502 + * Handle miscellaneous REST API actions
503 + *
504 + * @param mixed $result
505 + * @param array $params
506 + * @return mixed
507 + */
508 + public function handle_miscellaneous_actions($result, $params) {
509 + if (isset($params['action']) && $params['action'] === 'dismiss_initial_popup') {
510 + return $this->dismiss_initial_popup();
511 + }
512 + return $result;
513 + }
514 +
515 + /**
516 + * Dismiss the initial popup
517 + *
518 + * @return bool
519 + */
520 + public function dismiss_initial_popup() {
521 + // Check user permissions
522 + if (!current_user_can('manage_options')) {
523 + return false;
524 + }
525 +
526 + // Update the option to mark popup as dismissed
527 + update_option('nx_force_popup_dismissed', '1');
528 + $result = update_option('nx_initial_popup_dismissed', true);
529 +
530 + return $result;
531 + }
532 +
533 + /**
534 + * Check if popup should be shown
535 + *
536 + * @return bool
537 + */
538 + public function should_show_initial_popup() {
539 + // Don't show if already dismissed
540 + if (get_option('nx_initial_popup_dismissed', false)) {
541 + return false;
542 + }
543 +
544 + // Don't show for non-admin users
545 + if (!current_user_can('manage_options')) {
546 + return false;
547 + }
548 +
549 + // Delay the popup until 1 day after installation. Quick Setup already
550 + // handles onboarding, so this stays out of the way on the first day.
551 + $install_time = get_option('nx_initial_popup_install_time', false);
552 + if (!$install_time) {
553 + $install_time = time();
554 + update_option('nx_initial_popup_install_time', $install_time);
555 + }
556 +
557 + if ((time() - (int) $install_time) < DAY_IN_SECONDS) {
558 + return false;
559 + }
560 +
561 + return true;
562 + }
563 +
564 + /**
565 + * Add popup status to admin context
566 + *
567 + * @param array $data
568 + * @return array
569 + */
570 + public function add_popup_status_to_context($data) {
571 + $data['show_initial_popup'] = $this->should_show_initial_popup();
572 + $data['nx_admin_notice_close'] = get_option('nx_admin_notice_close', false);
573 + return $data;
574 + }
575 +}