PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / 1.1.0
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management v1.1.0
1.6.0 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
← All changes | inc/api/onboarding-api.php +12 -93 1.2.01.1.0 View file →
@@ -4,9 +4,9 @@
4 4 *
5 5 * Routes (under `suredonation/v1`):
6 6 * - GET /onboarding/get-status — return { completed: 'yes'|'no' }
7 7 * - POST /onboarding/set-status — write completion + optional analytics
8 - * - POST /onboarding/create-campaign — create a published suredonation_cmpgn
8 + * - POST /onboarding/create-campaign — create a draft suredonation_cmpgn
9 9 * - POST /onboarding/user-details — persist lead capture (free-only step)
10 10 *
11 11 * @package SureDonation
12 12 */
@@ -110,9 +110,9 @@
110 110
111 111 /**
112 112 * POST /onboarding/create-campaign.
113 113 *
114 - * Creates a published campaign post + writes its meta. Returns the new
114 + * Creates a draft campaign post + writes its meta. Returns the new
115 115 * campaign id + edit URL so the JS can persist it in onboarding state.
116 116 *
117 117 * @param WP_REST_Request $request Request.
118 118 * @return WP_REST_Response|WP_Error
@@ -144,16 +144,12 @@
144 144 if ( ! in_array( $goal_type, self::GOAL_TYPES, true ) ) {
145 145 $goal_type = 'raised_amount';
146 146 }
147 147
148 - // Publish the campaign so it behaves like one created via the normal
149 - // flow: the save_post_suredonation_cmpgn hook auto-creates its default
150 - // donation form, and the campaign becomes selectable in the Donation
151 - // Form block (whose query is limited to published campaigns).
152 148 $result = wp_insert_post(
153 149 [
154 150 'post_type' => Campaign_Cpt::POST_TYPE,
155 - 'post_status' => 'publish',
151 + 'post_status' => 'draft',
156 152 'post_title' => $name,
157 153 'post_excerpt' => $description,
158 154 'post_author' => get_current_user_id(),
159 155 ],
@@ -205,10 +201,8 @@
205 201 * @return WP_REST_Response
206 202 * @since 1.0.0
207 203 */
208 204 public function save_user_details( $request ) {
209 - $onboarding = Onboarding::get_instance();
210 -
211 205 $payload = [
212 206 'first_name' => sanitize_text_field( (string) $request->get_param( 'first_name' ) ),
213 207 'last_name' => sanitize_text_field( (string) $request->get_param( 'last_name' ) ),
214 208 'email' => sanitize_email( (string) $request->get_param( 'email' ) ),
@@ -214,22 +208,26 @@
214 208 'email' => sanitize_email( (string) $request->get_param( 'email' ) ),
215 209 'opted_in' => (bool) $request->get_param( 'opted_in' ),
216 210 ];
217 211
218 - $onboarding->set_user_details( $payload );
212 + Onboarding::get_instance()->set_user_details( $payload );
219 213
214 + // Persist the usage-tracking opt-in as its own option so other
215 + // plugin code (analytics, telemetry pings) can check it without
216 + // loading the consolidated onboarding details. Site option — the
217 + // BSF Analytics library reads it via get_site_option(), so the
218 + // write must use the same scope to stay in sync on multisite.
220 219 update_site_option(
221 220 'suredonation_usage_optin',
222 221 $payload['opted_in'] ? 'yes' : 'no'
223 222 );
224 223
225 - if ( ! $onboarding->is_lead_sent() && $this->forward_lead_to_crm( $payload ) ) {
226 - $onboarding->mark_lead_sent();
227 - }
228 -
229 224 /**
230 225 * Fires after onboarding lead-capture details are persisted.
231 226 *
227 + * Listeners (e.g. Pro analytics) can forward the payload to a
228 + * metrics endpoint when `opted_in` is true.
229 + *
232 230 * @since 1.0.0
233 231 *
234 232 * @param array<string,mixed> $payload Sanitised payload.
235 233 */
@@ -235,85 +233,6 @@
235 233 */
236 234 do_action( 'suredonation_onboarding_user_details_saved', $payload );
237 235
238 236 return new WP_REST_Response( [ 'success' => true ] );
239 - }
240 -
241 - /**
242 - * Generate lead.
243 - *
244 - * @param array<string,mixed> $payload Sanitised lead-capture payload.
245 - * @return bool True when the CRM accepted the lead, false otherwise.
246 - * @since 1.1.2
247 - */
248 - private function forward_lead_to_crm( array $payload ) {
249 - $email_raw = $payload['email'] ?? '';
250 - $email = is_string( $email_raw ) ? sanitize_email( $email_raw ) : '';
251 - if ( empty( $email ) || ! is_email( $email ) ) {
252 - return false;
253 - }
254 -
255 - $url = 'https://metrics.brainstormforce.com/wp-json/bsf-metrics-server/v1/subscribe';
256 -
257 - if ( defined( 'SUREDONATION_METRICS_ENDPOINT' ) && is_string( SUREDONATION_METRICS_ENDPOINT ) ) {
258 - $url = SUREDONATION_METRICS_ENDPOINT;
259 - }
260 -
261 - /**
262 - * Filters the endpoint.
263 - *
264 - * @since 1.1.2
265 - *
266 - * @param string $url Endpoint URL.
267 - * @param array<string,mixed> $payload Lead payload being sent.
268 - */
269 - $filtered = apply_filters( 'suredonation_metrics_subscribe_url', $url, $payload );
270 - $url = is_string( $filtered ) ? $filtered : $url;
271 -
272 - if ( '' === $url ) {
273 - return false;
274 - }
275 -
276 - $first_name = isset( $payload['first_name'] ) && is_string( $payload['first_name'] ) ? $payload['first_name'] : '';
277 - $last_name = isset( $payload['last_name'] ) && is_string( $payload['last_name'] ) ? $payload['last_name'] : '';
278 - $domain = wp_parse_url( home_url(), PHP_URL_HOST );
279 - $domain = is_string( $domain ) ? $domain : '';
280 -
281 - $body = wp_json_encode(
282 - [
283 - // Lowercase keys satisfy the current BSF Metrics REST args.
284 - 'email' => $email,
285 - 'first_name' => $first_name,
286 - 'last_name' => $last_name,
287 - 'domain' => $domain,
288 - 'source' => 'suredonation',
289 - // Legacy uppercase keys kept for backward compatibility.
290 - 'EMAIL' => $email,
291 - 'FIRSTNAME' => $first_name,
292 - 'LASTNAME' => $last_name,
293 - 'DOMAIN' => $domain,
294 - ]
295 - );
296 -
297 - if ( false === $body ) {
298 - return false;
299 - }
300 -
301 - // `source` identifies the originating plugin on the shared CRM server.
302 - // wp_safe_remote_post with WP's default 5s timeout keeps a slow or
303 - // hung endpoint from stalling onboarding completion.
304 - $response = wp_safe_remote_post(
305 - $url,
306 - [
307 - 'headers' => [ 'Content-Type' => 'application/json' ],
308 - 'body' => $body,
309 - ]
310 - );
311 -
312 - if ( is_wp_error( $response ) ) {
313 - return false;
314 - }
315 -
316 - $code = (int) wp_remote_retrieve_response_code( $response );
317 - return in_array( $code, [ 200, 201, 204 ], true );
318 237 }
319 238 }