Skip to content

Commit

Permalink
[4.x] Remove any uploaded assets when submission silently fails or va…
Browse files Browse the repository at this point in the history
…lidation fails (#9549)
  • Loading branch information
ryanmitchell authored Feb 20, 2024
1 parent e0d10d5 commit 8193ac9
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 1 deletion.
27 changes: 26 additions & 1 deletion src/Http/Controllers/FormController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Statamic\Events\FormSubmitted;
use Statamic\Events\SubmissionCreated;
use Statamic\Exceptions\SilentFormFailureException;
use Statamic\Facades\Asset;
use Statamic\Facades\Form;
use Statamic\Facades\Site;
use Statamic\Forms\Exceptions\FileContentTypeRequiredException;
Expand Down Expand Up @@ -50,7 +51,9 @@ public function submit(FrontendFormRequest $request, $form)
try {
throw_if(Arr::get($values, $form->honeypot()), new SilentFormFailureException);

$values = array_merge($values, $submission->uploadFiles($assets));
$uploadedAssets = $submission->uploadFiles($assets);

$values = array_merge($values, $uploadedAssets);

$submission->data(
$fields->addValues($values)->process()->values()
Expand All @@ -60,8 +63,14 @@ public function submit(FrontendFormRequest $request, $form)
// If they want to add validation errors, they can throw an exception.
throw_if(FormSubmitted::dispatch($submission) === false, new SilentFormFailureException);
} catch (ValidationException $e) {
$this->removeUploadedAssets($uploadedAssets);

return $this->formFailure($params, $e->errors(), $form->handle());
} catch (SilentFormFailureException $e) {
if (isset($uploadedAssets)) {
$this->removeUploadedAssets($uploadedAssets);
}

return $this->formSuccess($params, $submission, true);
}

Expand Down Expand Up @@ -156,4 +165,20 @@ private function formSuccessRedirect($params, $submission)

return $redirect;
}

/**
* Remove any uploaded assets
*
* Triggered by a validation exception or silent failure
*/
private function removeUploadedAssets(array $assets)
{
collect($assets)
->flatten()
->each(function ($id) {
if ($asset = Asset::find($id)) {
$asset->delete();
}
});
}
}
109 changes: 109 additions & 0 deletions tests/Tags/Form/FormCreateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

namespace Tests\Tags\Form;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\ValidationException;
use Statamic\Facades\AssetContainer;
use Statamic\Facades\Form;
use Statamic\Statamic;

Expand Down Expand Up @@ -822,4 +827,108 @@ public function it_fetches_form_data()
$this->assertEquals($form['honeypot'], 'winnie');
$this->assertEquals($form['js_driver'], 'alpine');
}

/** @test */
public function it_uploads_assets()
{
Storage::fake('avatars');
AssetContainer::make('avatars')->disk('avatars')->save();

$this->createForm([
'tabs' => [
'main' => [
'sections' => [
[
'display' => 'One',
'instructions' => 'One Instructions',
'fields' => [
['handle' => 'alpha', 'field' => ['type' => 'text']],
['handle' => 'bravo', 'field' => ['type' => 'assets', 'container' => 'avatars']],
],
],
],
],
],
], 'survey');

$this
->post('/!/forms/survey', [
'alpha' => 'test',
'bravo' => UploadedFile::fake()->image('avatar.jpg'),
]);

Storage::disk('avatars')->assertExists('avatar.jpg');
}

/** @test */
public function it_removes_any_uploaded_assets_when_a_submission_silently_fails()
{
Storage::fake('avatars');
AssetContainer::make('avatars')->disk('avatars')->save();

Event::listen(function (\Statamic\Events\FormSubmitted $event) {
return false;
});

$this->createForm([
'tabs' => [
'main' => [
'sections' => [
[
'display' => 'One',
'instructions' => 'One Instructions',
'fields' => [
['handle' => 'alpha', 'field' => ['type' => 'text']],
['handle' => 'bravo', 'field' => ['type' => 'assets', 'container' => 'avatars']],
],
],
],
],
],
], 'survey');

$this
->post('/!/forms/survey', [
'alpha' => 'test',
'bravo' => UploadedFile::fake()->image('avatar.jpg'),
]);

Storage::disk('avatars')->assertMissing('avatar.jpg');
}

/** @test */
public function it_removes_any_uploaded_assets_when_a_listener_throws_a_validation_exception()
{
Storage::fake('avatars');
AssetContainer::make('avatars')->disk('avatars')->save();

Event::listen(function (\Statamic\Events\FormSubmitted $event) {
throw ValidationException::withMessages(['custom' => 'This is a custom message']);
});

$this->createForm([
'tabs' => [
'main' => [
'sections' => [
[
'display' => 'One',
'instructions' => 'One Instructions',
'fields' => [
['handle' => 'alpha', 'field' => ['type' => 'text']],
['handle' => 'bravo', 'field' => ['type' => 'assets', 'container' => 'avatars']],
],
],
],
],
],
], 'survey');

$this
->post('/!/forms/survey', [
'alpha' => 'test',
'bravo' => UploadedFile::fake()->image('avatar.jpg'),
]);

Storage::disk('avatars')->assertMissing('avatar.jpg');
}
}

0 comments on commit 8193ac9

Please sign in to comment.