| @@ -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 | } |