Skip to content

Commit

Permalink
Support for nested request data when using the ConvertsBase64ToFiles …
Browse files Browse the repository at this point in the history
…trait
  • Loading branch information
pascalbaljet committed Dec 23, 2020
2 parents 574bea9 + 41d521e commit 5c474ab
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 7 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,25 @@ $jpgFile = $request->file('jpg_image');
$jpgFile->getClientOriginalName();
```

This trait supports nested data as well. You can either reference the keys by a nested array, or with a [dotted notation](https://laravel.com/docs/master/helpers#method-array-dot):

```php
class ImageRequest extends FormRequest
{
use ConvertsBase64ToFiles;

protected function base64FileKeys(): array
{
return [
'company.logo' => 'Logo.jpg',
'user' => [
'avatar' => 'Avatar.jpg',
],
];
}
}
```

Want to know more about this trait? Check out the [blog post](https://protone.media/blog/convert-and-store-base64-encoded-files-in-laravel-use-validation-rules-and-access-the-decoded-files-from-the-request-instance).

### Testing
Expand Down
36 changes: 33 additions & 3 deletions src/Request/ConvertsBase64ToFiles.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
namespace ProtoneMedia\LaravelMixins\Request;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\FileBag;
use Symfony\Component\HttpFoundation\ParameterBag;

trait ConvertsBase64ToFiles
{
Expand All @@ -13,6 +16,26 @@ protected function base64FileKeys(): array
return [];
}

/**
* Helper method to get the body parameters bag.
*
* @return \Symfony\Component\HttpFoundation\ParameterBag
*/
private function bodyParametersBag(): ParameterBag
{
return $this->request;
}

/**
* Helper method to get the uploaded files bag.
*
* @return FileBag
*/
private function uploadFilesBag(): FileBag
{
return $this->files;
}

/**
* Pulls the Base64 contents for each image key and creates
* an UploadedFile instance from it and sets it on the
Expand All @@ -22,7 +45,9 @@ protected function base64FileKeys(): array
*/
protected function prepareForValidation()
{
Collection::make($this->base64FileKeys())->each(function ($filename, $key) {
$flattened = Arr::dot($this->base64FileKeys());

Collection::make($flattened)->each(function ($filename, $key) {
rescue(function () use ($key, $filename) {
$base64Contents = $this->input($key);

Expand All @@ -48,8 +73,13 @@ protected function prepareForValidation()

$uploadedFile = new UploadedFile($tempFilePath, $filename, null, null, true);

$this->request->remove($key);
$this->files->set($key, $uploadedFile);
$body = $this->bodyParametersBag()->all();
Arr::forget($body, $key);
$this->bodyParametersBag()->replace($body);

$files = $this->uploadFilesBag()->all();
Arr::set($files, $key, $uploadedFile);
$this->uploadFilesBag()->replace($files);
}, null, false);
});
}
Expand Down
73 changes: 69 additions & 4 deletions tests/Request/ConvertsBase64ToFilesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace ProtoneMedia\Mixins\Tests\Request;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Routing\Redirector;
use Orchestra\Testbench\TestCase;
use ProtoneMedia\LaravelMixins\Request\ConvertsBase64ToFiles;
use ZipArchive;
Expand All @@ -28,6 +29,30 @@ public function rules()
}
}

class NestedImageRequest extends FormRequest
{
use ConvertsBase64ToFiles;

protected function base64FileKeys(): array
{
return [
'company' => [
'logo' => 'company_logo.jpeg',
],

'user.avatar' => 'user_avatar.png',
];
}

public function rules()
{
return [
'company.logo' => ['required', 'file', 'image'],
'user.avatar' => ['required', 'file', 'image'],
];
}
}

class ZipRequest extends FormRequest
{
use ConvertsBase64ToFiles;
Expand All @@ -49,6 +74,13 @@ public function rules()

class ConvertsBase64ToFilesTest extends TestCase
{
private function validateRequest(FormRequest $request)
{
$request->setContainer($this->app);
$request->setRedirector($this->app->make(Redirector::class));
$request->validateResolved();
}

/** @test */
public function it_converts_the_base64_images_to_illuminate_file_uploads()
{
Expand All @@ -57,8 +89,7 @@ public function it_converts_the_base64_images_to_illuminate_file_uploads()
'jpeg_image' => file_get_contents(__DIR__ . '/base64_jpeg'),
]);

$request->setContainer($this->app);
$request->validateResolved();
$this->validateRequest($request);

$pngFile = $request->file('png_image');
$jpegFile = $request->file('jpeg_image');
Expand All @@ -81,15 +112,49 @@ public function it_converts_the_base64_images_to_illuminate_file_uploads()
$this->assertEquals('width="300" height="300"', $jpegSize[3]);
}

/** @test */
public function it_handles_nested_files()
{
$request = NestedImageRequest::create('/', 'POST', [
'company' => [
'logo' => file_get_contents(__DIR__ . '/base64_jpeg'),
],
'user' => [
'avatar' => file_get_contents(__DIR__ . '/base64_png'),
],
]);

$this->validateRequest($request);

$pngFile = $request->file('user.avatar');
$jpegFile = $request->file('company.logo');

$this->assertNotNull($pngFile);
$this->assertNotNull($jpegFile);

$this->assertEquals($pngFile, $request->validated()['user']['avatar']);
$this->assertEquals($jpegFile, $request->validated()['company']['logo']);

//

$pngSize = getimagesize($pngFile->getRealPath());
$jpegSize = getimagesize($jpegFile->getRealPath());

$this->assertEquals('user_avatar.png', $pngFile->getClientOriginalName());
$this->assertEquals('company_logo.jpeg', $jpegFile->getClientOriginalName());

$this->assertEquals('width="300" height="300"', $pngSize[3]);
$this->assertEquals('width="300" height="300"', $jpegSize[3]);
}

/** @test */
public function it_converts_a_base64_zip_to_an_illuminate_file_upload()
{
$request = ZipRequest::create('/', 'POST', [
'zip' => file_get_contents(__DIR__ . '/base64_zip'),
]);

$request->setContainer($this->app);
$request->validateResolved();
$this->validateRequest($request);

$zipFile = $request->file('zip');

Expand Down

0 comments on commit 5c474ab

Please sign in to comment.