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
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.3.3, at includes/Core/SetupWizard.php

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