PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / trunk
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management vtrunk
1.5.1 1.5.0 1.4.0 1.3.0 trunk 0.0.1 1.0.0 1.1.0 1.1.1 1.1.2 1.2.0
suredonation / inc / onboarding.php

onboarding.php in SureDonation – Donation Forms, Fundraising Campaigns & Donor Management trunk, at inc/onboarding.php

199 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Onboarding service.
4 *
5 * Persists onboarding completion state, captured user-details, and the
6 * one-shot activation redirect that drops a freshly-activated admin onto
7 * the guided setup screen.
8 *
9 * Backed by the consolidated `suredonation_options` row via Helper so we
10 * don't create extra option rows for a single boolean.
11 *
12 * @package SureDonation
13 */
14
15 namespace SureDonation\Inc;
16
17 use SureDonation\Inc\Traits\Get_Instance;
18
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit;
21 }
22
23 /**
24 * Onboarding class.
25 *
26 * @since 1.0.0
27 */
28 class Onboarding {
29 use Get_Instance;
30
31 /**
32 * Key inside suredonation_options for the completion flag.
33 *
34 * @since 1.0.0
35 * @var string
36 */
37 private const STATUS_KEY = 'onboarding_completed';
38
39 /**
40 * Key inside suredonation_options for cached user-details capture.
41 *
42 * @since 1.0.0
43 * @var string
44 */
45 private const USER_DETAILS_KEY = 'onboarding_user_details';
46
47 /**
48 * Key inside suredonation_options recording when the onboarding lead was
49 * forwarded to the CRM. Stores a Unix timestamp; 0 means not yet sent.
50 *
51 * @since 1.1.2
52 * @var string
53 */
54 private const LEAD_SENT_KEY = 'onboarding_lead_sent_at';
55
56 /**
57 * Hidden admin page slug.
58 *
59 * @since 1.0.0
60 * @var string
61 */
62 public const PAGE_SLUG = 'suredonation-onboarding';
63
64 /**
65 * Option key set during activation to trigger the one-shot redirect.
66 *
67 * Already declared by Plugin_Loader on activation; we just consume it
68 * here.
69 *
70 * @since 1.0.0
71 * @var string
72 */
73 private const REDIRECT_FLAG = '__suredonation_do_redirect';
74
75 /**
76 * Wire up activation redirect.
77 *
78 * @since 1.0.0
79 */
80 public function __construct() {
81 add_action( 'admin_init', [ $this, 'maybe_redirect_to_onboarding' ] );
82 }
83
84 /**
85 * Read completion state.
86 *
87 * @return bool
88 * @since 1.0.0
89 */
90 public function is_completed() {
91 return 'yes' === Helper::get_suredonation_option( self::STATUS_KEY, 'no' );
92 }
93
94 /**
95 * Persist completion state.
96 *
97 * @param string $value 'yes' or 'no'.
98 * @return void
99 * @since 1.0.0
100 */
101 public function set_completed( $value = 'yes' ) {
102 Helper::update_suredonation_option( self::STATUS_KEY, 'yes' === $value ? 'yes' : 'no' );
103 }
104
105 /**
106 * Read the cached lead-capture payload.
107 *
108 * @return array<string,mixed>
109 * @since 1.0.0
110 */
111 public function get_user_details() {
112 $details = Helper::get_suredonation_option( self::USER_DETAILS_KEY, [] );
113 return is_array( $details ) ? $details : [];
114 }
115
116 /**
117 * Persist the lead-capture payload.
118 *
119 * @param array<string,mixed> $details Raw payload (already sanitised).
120 * @return void
121 * @since 1.0.0
122 */
123 public function set_user_details( array $details ) {
124 Helper::update_suredonation_option( self::USER_DETAILS_KEY, $details );
125 }
126
127 /**
128 * Whether the onboarding lead has already been forwarded to the CRM.
129 *
130 * @return bool
131 * @since 1.1.2
132 */
133 public function is_lead_sent() {
134 $sent_at = Helper::get_suredonation_option( self::LEAD_SENT_KEY, 0 );
135 return is_numeric( $sent_at ) && (int) $sent_at > 0;
136 }
137
138 /**
139 * Record that the onboarding lead has been forwarded to the CRM.
140 *
141 * @return void
142 * @since 1.1.2
143 */
144 public function mark_lead_sent() {
145 Helper::update_suredonation_option( self::LEAD_SENT_KEY, time() );
146 }
147
148 /**
149 * On the first admin pageload after activation, send the admin to the
150 * onboarding screen — but only if onboarding isn't already done.
151 *
152 * @return void
153 * @since 1.0.0
154 */
155 public function maybe_redirect_to_onboarding() {
156 if ( wp_doing_ajax() || wp_doing_cron() ) {
157 return;
158 }
159
160 // admin_init fires for REST and network-admin contexts too — neither
161 // should ever 302 to the onboarding screen.
162 if ( ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || is_network_admin() ) {
163 return;
164 }
165
166 // Only honour the redirect on the initial GET that lands the admin
167 // on a wp-admin page — a POST hitting admin_init would otherwise
168 // 302 mid-form-submission.
169 if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'GET' !== strtoupper( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) ) ) {
170 return;
171 }
172
173 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading a flag, not processing form input.
174 if ( isset( $_GET['activate-multi'] ) ) {
175 return;
176 }
177
178 if ( ! get_option( self::REDIRECT_FLAG ) ) {
179 return;
180 }
181
182 // One-shot — drop the row entirely so the option table doesn't
183 // accumulate dead flags. The activation hook will recreate it on
184 // the next plugin activation.
185 delete_option( self::REDIRECT_FLAG );
186
187 if ( ! current_user_can( 'manage_options' ) ) {
188 return;
189 }
190
191 if ( $this->is_completed() ) {
192 return;
193 }
194
195 wp_safe_redirect( admin_url( 'admin.php?page=' . self::PAGE_SLUG ) );
196 exit;
197 }
198 }
199