}>, * consent: array{purpose: string, email: array{text: string, accepted_at: string|null}|null, sms: array{text: string, accepted_at: string|null}|null}, * source: array{page_url: string, utm: array}|null} */ public static function of(Lead $lead, string $submissionId): array { $values = []; $answers = []; $consent = ['purpose' => 'request', 'email' => null, 'sms' => null]; $acceptedAt = null; $submissions = is_array($lead->capture['submissions'] ?? null) ? $lead->capture['submissions'] : []; foreach ($submissions as $id => $snapshot) { if (!is_array($snapshot)) continue; $values = array_merge($values, array_filter(is_array($snapshot['values'] ?? null) ? $snapshot['values'] : [], 'is_string')); foreach (is_array($snapshot['question_answers'] ?? null) ? $snapshot['question_answers'] : [] as $answer) { if (is_array($answer) && is_string($answer['id'] ?? null)) $answers[$answer['id']] = self::answer($answer); } $purpose = is_string($snapshot['purpose'] ?? null) ? $snapshot['purpose'] : 'request'; $at = is_string($snapshot['accepted_at'] ?? null) ? $snapshot['accepted_at'] : null; if ($purpose === 'email_marketing' || $purpose === 'sms_marketing') { $consent[$purpose === 'email_marketing' ? 'email' : 'sms'] = ['text' => (string) ($snapshot['values']['consent_text'] ?? ''), 'accepted_at' => $at]; } if ((string) $id === $submissionId) { $consent['purpose'] = $purpose; $acceptedAt = $at; break; } } if ($submissions === []) { // A snapshot already narrowed to one submission (Lead::submission()). $values = array_filter(['email' => $lead->email, 'phone' => $lead->phone, ...$lead->fields], 'is_string'); foreach ($lead->questionAnswers as $answer) { if (is_string($answer['id'] ?? null)) $answers[$answer['id']] = self::answer($answer); } $consent['purpose'] = is_string($lead->capture['purpose'] ?? null) ? $lead->capture['purpose'] : 'request'; } $recorded = $lead->capture['source'] ?? null; $source = null; if (is_array($recorded) && is_string($recorded['page_url'] ?? null)) { $utm = []; foreach (CaptureSource::UTM as $tag) $utm[$tag] = self::text($recorded['utm'][$tag] ?? null); $source = ['page_url' => $recorded['page_url'], 'utm' => $utm]; } return ['lead_id' => $lead->id, 'submission' => $submissionId, 'accepted_at' => $acceptedAt, 'contact' => ['email' => self::text($values['email'] ?? null), 'phone' => self::text($values['phone'] ?? null), 'name' => self::text($values['name'] ?? null)], 'interest' => self::text($values['interest'] ?? null), 'answers' => $answers, 'consent' => $consent, 'source' => $source]; } /** * What a test send carries: the merchant's own values, and a plausible * value for everything else. * * @param array $values * @param array}>|null $answers * @return array */ public static function sample(array $values, string $purpose, ?array $answers = null): array { $now = gmdate('Y-m-d\TH:i:s\Z'); $utm = array_fill_keys(CaptureSource::UTM, null); return ['lead_id' => '01TEST00000000000000SAMPLE', 'submission' => 'primary', 'accepted_at' => $now, 'contact' => ['email' => $values['email'] ?? 'sample@example.com', 'phone' => $values['phone'] ?? '+12025550123', 'name' => $values['name'] ?? 'Sample Person'], 'interest' => $values['interest'] ?? 'Sample interest', 'answers' => $answers ?? ['sample_question' => ['question' => __('Sample question', 'wconvert'), 'answer' => __('Sample answer', 'wconvert')]], 'consent' => ['purpose' => $purpose, 'email' => ['text' => __('Sample consent wording', 'wconvert'), 'accepted_at' => $now], 'sms' => ['text' => __('Sample consent wording', 'wconvert'), 'accepted_at' => $now]], 'source' => ['page_url' => '/sample-page?utm_source=sample', 'utm' => ['source' => 'sample'] + $utm]]; } /** * @param array $answer * @return array{question: string, answer: string|list} */ private static function answer(array $answer): array { $type = $answer['type'] ?? ''; $parts = $type === 'text' ? ($answer['values'] ?? []) : ($answer['labels'] ?? []); $parts = array_values(array_filter(is_array($parts) ? $parts : [], 'is_string')); return ['question' => is_string($answer['question'] ?? null) ? $answer['question'] : '', 'answer' => $type === 'multi' ? $parts : implode('; ', $parts)]; } private static function text(mixed $value): ?string { return is_string($value) && trim($value) !== '' ? $value : null; } }