diff --git a/README.md b/README.md index 3c21775..a3846d9 100644 --- a/README.md +++ b/README.md @@ -176,3 +176,23 @@ public function fields(Request $request) ``` This field sets the disk in use to `Cloudinary` and ensures the media is stored in the database field with the correct file extension. + +## Configuration + +If you want to use any of the [optional parameters](https://cloudinary.com/documentation/image_upload_api_reference#optional_parameters) of the Cloudinary Upload API, you can use the `cloudinary` method to send additional parameters. + +The following code uploads images to the images folder instead of the Cloudinary root. + +```php +use Silvanite\NovaFieldCloudinary\Fields\CloudinaryImage; + +public function fields(Request $request) +{ + return [ + ... + CloudinaryImage::make('Image')->cloudinary([ + 'folder' => 'images' + ]), + ] +} +``` diff --git a/src-php/Adapters/CloudinaryAdapter.php b/src-php/Adapters/CloudinaryAdapter.php index 6d4b0c0..1561260 100644 --- a/src-php/Adapters/CloudinaryAdapter.php +++ b/src-php/Adapters/CloudinaryAdapter.php @@ -21,14 +21,20 @@ class CloudinaryAdapter extends CloudinaryBaseAdapter */ public function writeStream($path, $resource, Config $config) { + + $cloudinary_options = $config->get('cloudinary') ?? []; + $path = pathinfo($path)['filename']; - $resource_metadata = stream_get_meta_data($resource); - $uploaded_metadata = Uploader::upload($resource_metadata['uri'], [ + // Create the options object + $options = array_merge([ 'public_id' => $path, - 'resource_type' => 'auto', - ]); - + 'resource_type' => 'auto' + ], $cloudinary_options); + + $resource_metadata = stream_get_meta_data($resource); + $uploaded_metadata = Uploader::upload($resource_metadata['uri'], $options); + return $uploaded_metadata; } diff --git a/src-php/Fields/CloudinaryAudio.php b/src-php/Fields/CloudinaryAudio.php index fe241e5..f42a397 100644 --- a/src-php/Fields/CloudinaryAudio.php +++ b/src-php/Fields/CloudinaryAudio.php @@ -20,14 +20,27 @@ public function __construct($name, $attribute = null, $disk = 'cloudinary', $sto { parent::__construct($name, $attribute, $disk, $storageCallback); - $this->storeAs(function (Request $request) { + $this->store(function(Request $request, $model, $attribute, $requestAttribute){ + + $filename = $request->file($requestAttribute)->store($this->getStorageDir(), [ + 'disk' => $this->getStorageDisk(), + 'cloudinary' => $this->cloudinaryOptions + ]); + + // If a folder is specified we ensure a trailing slash + // If no folder is specified we ensure no beginning slash + $path = array_key_exists('folder',$this->cloudinaryOptions) ? rtrim($this->cloudinaryOptions['folder'], '/') . '/' : ''; + + return $path . $filename; + + })->storeAs(function (Request $request) { $name = $request->{$this->attribute}->getClientOriginalName(); $ext = '.' . $request->{$this->attribute}->getClientOriginalExtension(); return sha1($name . time()) . $ext; })->delete(function (Request $request, $model) { $path = pathinfo($model->{$this->attribute}); - Storage::disk($this->disk)->delete($path['filename']); + Storage::disk($this->disk)->delete($path['dirname'] .'/'. $path['filename']); return $this->columnsThatShouldBeDeleted(); }); } diff --git a/src-php/Fields/CloudinaryFile.php b/src-php/Fields/CloudinaryFile.php index a0a8418..7c0730b 100644 --- a/src-php/Fields/CloudinaryFile.php +++ b/src-php/Fields/CloudinaryFile.php @@ -7,6 +7,9 @@ class CloudinaryFile extends File { + + use CloudinaryOptions; + /** * Create a new field. * @@ -20,15 +23,27 @@ public function __construct($name, $attribute = null, $disk = 'cloudinary', $sto { parent::__construct($name, $attribute, $disk, $storageCallback); - $this->storeAs(function (Request $request) { + $this->store(function(Request $request, $model, $attribute, $requestAttribute){ + + $filename = $request->file($requestAttribute)->store($this->getStorageDir(), [ + 'disk' => $this->getStorageDisk(), + 'cloudinary' => $this->cloudinaryOptions + ]); + + // If a folder is specified we ensure a trailing slash + // If no folder is specified we ensure no beginning slash + $path = array_key_exists('folder',$this->cloudinaryOptions) ? rtrim($this->cloudinaryOptions['folder'], '/') . '/' : ''; + + return $path . $filename; + + })->storeAs(function (Request $request) { $name = $request->{$this->attribute}->getClientOriginalName(); $ext = '.' . $request->{$this->attribute}->getClientOriginalExtension(); return sha1($name . time()) . $ext; })->delete(function (Request $request, $model) { $path = pathinfo($model->{$this->attribute}); - \Storage::disk($this->disk)->delete($path['filename']); - + \Storage::disk($this->disk)->delete($path['dirname'] .'/'. $path['filename']); return $this->columnsThatShouldBeDeleted(); }); } diff --git a/src-php/Fields/CloudinaryImage.php b/src-php/Fields/CloudinaryImage.php index fa4aad1..f68acf5 100644 --- a/src-php/Fields/CloudinaryImage.php +++ b/src-php/Fields/CloudinaryImage.php @@ -8,6 +8,8 @@ class CloudinaryImage extends Image { + use CloudinaryOptions; + /** * Create a new field. * @@ -21,7 +23,20 @@ public function __construct($name, $attribute = null, $disk = 'cloudinary', $sto { parent::__construct($name, $attribute, $disk, $storageCallback); - $this->thumbnail(function () { + $this->store(function(Request $request, $model, $attribute, $requestAttribute){ + + $filename = $request->file($requestAttribute)->store($this->getStorageDir(), [ + 'disk' => $this->getStorageDisk(), + 'cloudinary' => $this->cloudinaryOptions + ]); + + // If a folder is specified we ensure a trailing slash + // If no folder is specified we ensure no beginning slash + $path = array_key_exists('folder',$this->cloudinaryOptions) ? rtrim($this->cloudinaryOptions['folder'], '/') . '/' : ''; + + return $path . $filename; + + })->thumbnail(function () { return $this->value ? cloudinary_image($this->value, [ 'width' => 64, 'height' => 64, @@ -34,13 +49,26 @@ public function __construct($name, $attribute = null, $disk = 'cloudinary', $sto 'fetch_format' => 'auto', ], $this->disk) : null; })->download(function () { + + // Get Cloudinary URL of image $image_address = cloudinary_image($this->value); + + // Get filename without folders + $filename = substr( strrchr( $this->value, '/' ), 1 ); + return response()->streamDownload(function () use ($image_address) { echo file_get_contents($image_address); - }, $this->value); + }, $filename); })->delete(function (Request $request, $model) { $path = pathinfo($model->{$this->attribute}); - Storage::disk($this->disk)->delete($path['filename']); + + $deletepath = $path['filename']; + + if(array_key_exists('dirname',$path) && $path['dirname'] != '.'){ + $deletepath = $path['dirname'] .'/'.$deletepath; + } + + Storage::disk($this->disk)->delete($deletepath); return $this->columnsThatShouldBeDeleted(); }); } diff --git a/src-php/Fields/CloudinaryOptions.php b/src-php/Fields/CloudinaryOptions.php new file mode 100644 index 0000000..4ebf947 --- /dev/null +++ b/src-php/Fields/CloudinaryOptions.php @@ -0,0 +1,16 @@ +cloudinaryOptions = $options; + + return $this; + } + +} diff --git a/src-php/Fields/CloudinaryVideo.php b/src-php/Fields/CloudinaryVideo.php index 2a60c51..f606c72 100644 --- a/src-php/Fields/CloudinaryVideo.php +++ b/src-php/Fields/CloudinaryVideo.php @@ -21,14 +21,27 @@ public function __construct($name, $attribute = null, $disk = 'cloudinary', $sto { parent::__construct($name, $attribute, $disk, $storageCallback); - $this->storeAs(function (Request $request) { + $this->store(function(Request $request, $model, $attribute, $requestAttribute){ + + $filename = $request->file($requestAttribute)->store($this->getStorageDir(), [ + 'disk' => $this->getStorageDisk(), + 'cloudinary' => $this->cloudinaryOptions + ]); + + // If a folder is specified we ensure a trailing slash + // If no folder is specified we ensure no beginning slash + $path = array_key_exists('folder',$this->cloudinaryOptions) ? rtrim($this->cloudinaryOptions['folder'], '/') . '/' : ''; + + return $path . $filename; + + })->storeAs(function (Request $request) { $name = $request->{$this->attribute}->getClientOriginalName(); $ext = '.' . $request->{$this->attribute}->getClientOriginalExtension(); return sha1($name . time()) . $ext; })->delete(function (Request $request, $model) { $path = pathinfo($model->{$this->attribute}); - Storage::disk($this->disk)->delete($path['filename']); + Storage::disk($this->disk)->delete($path['dirname'] .'/'. $path['filename']); return $this->columnsThatShouldBeDeleted(); }); }