diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2965dff --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +## [0.1.0] - 2026-07-23 +- Polymorphic form collection: a Form definition and its submissions, each scoped to any owning model via an owner morph +- Public, throttled submission endpoint that resolves a form by key and records the submission +- Pluggable, delivery-agnostic destinations (mail, webhook, Mautic, Smartpings) behind a destination contract, selectable per form +- Spam protection: honeypot fields, a minimum submit time, and per-minute rate limiting +- Typed submission columns (name, email, phone, subject, message) alongside an arbitrary payload, plus a delivery log +- A FormSubmittedEvent the host can bridge to its own workflows +- Config-driven throughout: destinations, protection thresholds, and the response formatter diff --git a/composer.json b/composer.json index 2d8413e..49eaafa 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Polymorphic form collection with pluggable, agnostic delivery destinations.", "type": "library", "license": "MIT", - "package-version": "1.0.0", + "version": "0.1.0", "authors": [ { "name": "WhileSmart", diff --git a/src/Destinations/MailDestination.php b/src/Destinations/MailDestination.php index 866e4c7..4dec4f7 100644 --- a/src/Destinations/MailDestination.php +++ b/src/Destinations/MailDestination.php @@ -12,13 +12,13 @@ class MailDestination implements FormDestination { public function deliver(FormSubmission $submission): void { - $to = optional($submission->form)->recipient_email + $recipient = optional($submission->form)->recipient_email ?? config('eloquent-forms.mail.to'); - if (empty($to)) { + if (empty($recipient)) { throw new RuntimeException('No recipient configured for the mail destination.'); } - Mail::to($to)->send(new FormSubmissionReceived($submission)); + Mail::to($recipient)->send(new FormSubmissionReceived($submission)); } } diff --git a/src/Destinations/SmartpingsDestination.php b/src/Destinations/SmartpingsDestination.php index 4a25e41..458ed63 100644 --- a/src/Destinations/SmartpingsDestination.php +++ b/src/Destinations/SmartpingsDestination.php @@ -18,7 +18,7 @@ class SmartpingsDestination implements FormDestination public function deliver(FormSubmission $submission): void { throw new RuntimeException( - 'SmartPings destination is not implemented yet. Provide SMARTPINGS_CLIENT_ID and SMARTPINGS_SECRET_ID so it can be built on smartpings/php-sdk and tested.' + 'SmartPings destination is not implemented yet. Set SMARTPINGS_CLIENT_ID and SMARTPINGS_SECRET_ID before enabling it.' ); } } diff --git a/src/Destinations/WebhookDestination.php b/src/Destinations/WebhookDestination.php index 9ecb9d9..791b442 100644 --- a/src/Destinations/WebhookDestination.php +++ b/src/Destinations/WebhookDestination.php @@ -28,7 +28,8 @@ public function deliver(FormSubmission $submission): void $body = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); $headers = ['Content-Type' => 'application/json']; - if ($secret = config('eloquent-forms.webhook.secret')) { + $secret = config('eloquent-forms.webhook.secret'); + if ($secret) { $headers['X-Forms-Signature'] = hash_hmac('sha256', $body, $secret); } diff --git a/src/Models/FormSubmission.php b/src/Models/FormSubmission.php index e56a1b0..a1bce66 100644 --- a/src/Models/FormSubmission.php +++ b/src/Models/FormSubmission.php @@ -79,18 +79,20 @@ public function submittable(): MorphTo */ public function fields(): array { - return collect($this->payload ?? []) - ->reject(fn ($value, $key) => str_starts_with((string) $key, '_')) - ->all(); + return array_filter( + $this->payload ?? [], + fn ($key) => ! str_starts_with((string) $key, '_'), + ARRAY_FILTER_USE_KEY + ); } - public function recordDelivery(string $destination, bool $ok, ?string $detail = null): void + public function recordDelivery(string $destination, bool $succeeded, ?string $detail = null): void { $log = $this->delivery_log ?? []; $log[$destination] = array_filter([ - 'ok' => $ok, + 'ok' => $succeeded, 'detail' => $detail, - ], fn ($v) => $v !== null); + ], fn ($value) => $value !== null); $this->delivery_log = $log; $this->save();