PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / 3.2.10
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar v3.2.10
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
notificationx / includes / Core / SetupWizard.php

SetupWizard.php in NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar 3.2.10, at includes/Core/SetupWizard.php

206 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Setup Wizard (Onboarding) Class File.
4 *
5 * Registers a standalone, full-screen onboarding wizard under its own
6 * top-level "Setup Wizard" menu. The UI is rendered by the existing admin
7 * React SPA via the `nx-setup-wizard` route.
8 *
9 * @package NotificationX\Core
10 */
11
12 namespace NotificationX\Core;
13
14 use NotificationX\Admin\Admin;
15 use NotificationX\GetInstance;
16
17 /**
18 * @method static SetupWizard get_instance($args = null)
19 */
20 class SetupWizard {
21
22 /**
23 * Instance of SetupWizard
24 *
25 * @var SetupWizard
26 */
27 use GetInstance;
28
29 /**
30 * Page slug for the wizard.
31 */
32 const PAGE = 'nx-setup-wizard';
33
34 /**
35 * Option key that marks onboarding as finished/skipped.
36 */
37 const COMPLETED_OPTION = 'nx_onboarding_completed';
38
39 /**
40 * Initially Invoked when initialized.
41 */
42 public function __construct() {
43 add_action( 'admin_menu', [ $this, 'menu' ], 35 );
44 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_preview_styles' ] );
45 add_filter( 'admin_body_class', [ $this, 'body_class' ] );
46 add_filter( 'nx_rest_miscellaneous', [ $this, 'handle_actions' ], 10, 2 );
47 add_filter( 'nx_builder_configs', [ $this, 'add_status_to_context' ], 10, 1 );
48 }
49
50 /**
51 * Register the "Setup Wizard" submenu under the NotificationX menu.
52 *
53 * Rendered by Admin::views() (the same React SPA root) so the
54 * `nx-setup-wizard` route can take over the full screen.
55 *
56 * @return void
57 */
58 public function menu() {
59 add_submenu_page(
60 'nx-admin',
61 __( 'Setup Wizard', 'notificationx' ),
62 __( 'Setup Wizard', 'notificationx' ),
63 'read_notificationx',
64 self::PAGE,
65 [ Admin::get_instance(), 'views' ],
66 30
67 );
68 }
69
70 /**
71 * Load the real frontend notification stylesheet on the wizard page so the
72 * Welcome-screen "Live Preview" renders the actual popup/bar/announcement
73 * designs 1:1. The frontend CSS is fully scoped (no global resets), so it
74 * is safe to load inside wp-admin.
75 *
76 * @param string $hook
77 * @return void
78 */
79 public function enqueue_preview_styles( $hook ) {
80 if ( 'notificationx_page_' . self::PAGE !== $hook ) {
81 return;
82 }
83 wp_enqueue_style(
84 'notificationx-public',
85 Helper::file( 'public/css/frontend.css', true ),
86 [],
87 apply_filters( 'nx_frontend_css_version', NOTIFICATIONX_VERSION ),
88 'all'
89 );
90 }
91
92 /**
93 * Add a body class on the wizard page so the SPA can render a
94 * full-screen layout (covering the WP sidebar / admin bar).
95 *
96 * @param string $classes
97 * @return string
98 */
99 public function body_class( $classes ) {
100 if ( $this->is_wizard_page() ) {
101 $classes .= ' nx-setup-wizard-active';
102 }
103 return $classes;
104 }
105
106 /**
107 * Whether the current admin request is the wizard page.
108 *
109 * @return bool
110 */
111 protected function is_wizard_page() {
112 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
113 return is_admin() && isset( $_GET['page'] ) && self::PAGE === sanitize_key( wp_unslash( $_GET['page'] ) );
114 }
115
116 /**
117 * Handle the `complete_setup_wizard` miscellaneous REST action.
118 *
119 * Returning a non-null value makes the /miscellaneous endpoint respond
120 * with `{ success: true }`.
121 *
122 * @param mixed $result
123 * @param array $params
124 * @return mixed
125 */
126 public function handle_actions( $result, $params ) {
127 if ( isset( $params['action'] ) ) {
128 if ( 'complete_setup_wizard' === $params['action'] ) {
129 return $this->complete( $params );
130 }
131 if ( 'setup_wizard_optin' === $params['action'] ) {
132 return $this->optin_tracking();
133 }
134 }
135 return $result;
136 }
137
138 /**
139 * Opt the site into WP Insights usage tracking and send the data to the
140 * insights API immediately. Triggered when the user proceeds past the
141 * Welcome step — the in-card notice states that proceeding consents to
142 * collecting the admin email to personalise the setup.
143 *
144 * @return bool
145 */
146 public function optin_tracking() {
147 if ( ! current_user_can( 'read_notificationx' ) ) {
148 return false;
149 }
150 if (
151 class_exists( '\NotificationX\Admin\PluginInsights' )
152 && method_exists( '\NotificationX\Admin\PluginInsights', 'optin' )
153 ) {
154 \NotificationX\Admin\PluginInsights::get_instance( NOTIFICATIONX_FILE )->optin( true );
155 }
156 return true;
157 }
158
159 /**
160 * Mark onboarding as completed (also used when skipped) so the wizard
161 * is not auto-launched again, and persist the collected choices.
162 *
163 * @param array $params
164 * @return bool
165 */
166 public function complete( $params = [] ) {
167 if ( ! current_user_can( 'read_notificationx' ) ) {
168 return false;
169 }
170
171 $goals = [];
172 if ( ! empty( $params['goals'] ) ) {
173 $goals = array_filter( array_map( 'sanitize_key', explode( ',', $params['goals'] ) ) );
174 }
175
176 $data = [
177 'business_type' => isset( $params['business_type'] ) ? sanitize_key( $params['business_type'] ) : '',
178 'goals' => array_values( $goals ),
179 'completed_at' => current_time( 'mysql' ),
180 ];
181 update_option( 'nx_onboarding_data', $data );
182
183 return update_option( self::COMPLETED_OPTION, true );
184 }
185
186 /**
187 * Whether onboarding has already been completed/skipped.
188 *
189 * @return bool
190 */
191 public static function is_completed() {
192 return (bool) get_option( self::COMPLETED_OPTION, false );
193 }
194
195 /**
196 * Expose onboarding status to the admin React app.
197 *
198 * @param array $data
199 * @return array
200 */
201 public function add_status_to_context( $data ) {
202 $data['onboarding_completed'] = self::is_completed();
203 return $data;
204 }
205 }
206