Skip to content

Commit

Permalink
Merge pull request #125 from newtonjob/extensions
Browse files Browse the repository at this point in the history
Properly handle Cloudinary public IDs and extensions for media and raw resources
  • Loading branch information
joshmanders authored Aug 14, 2024
2 parents 716acb2 + 724213b commit 6f0713d
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 19 deletions.
64 changes: 45 additions & 19 deletions src/CloudinaryAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,18 @@
*/
class CloudinaryAdapter implements FilesystemAdapter
{

/** Cloudinary\Cloudinary */
/**
* @var Cloudinary
*/
protected Cloudinary $cloudinary;

/**
* The media resource extensions supported by cloudinary.
*/
public $mediaExtensions = [
'jpg', 'jpeg', 'png', 'gif', 'pdf', 'bmp', 'tiff', 'svg', 'ico', 'eps', 'psd', 'webp', 'jxr', 'wdp',
'mpeg', 'mp4', 'mkv', 'mov', 'flv', 'avi', '3gp', '3g2', 'wmv', 'webm', 'ogv', 'mxf', 'avif',
];

/**
* Constructor
Expand Down Expand Up @@ -70,28 +78,42 @@ public function write(string $path, string $contents, Config $config): void
*/
public function writeStream(string $path, $contents, Config $config): void
{
$publicId = $config->get('public_id', $path);
$publicId = $this->preparePublicId($config->get('public_id', $path));

$resourceType = $config->get('resource_type', 'auto');

$fileExtension = pathinfo($publicId, PATHINFO_EXTENSION);

$newPublicId = $fileExtension ? substr($publicId, 0, - (strlen($fileExtension) + 1)) : $publicId;

$uploadOptions = [
'public_id' => $newPublicId,
'public_id' => $publicId,
'resource_type' => $resourceType
];

$resourceMetadata = stream_get_meta_data($contents);

resolve(CloudinaryEngine::class)->upload($resourceMetadata['uri'], $uploadOptions);
$this->upload($resourceMetadata['uri'], $uploadOptions);
}

/**
* Prepare the given public ID for cloudinary.
*/
public function preparePublicId($path): string
{
$extension = pathinfo($path, PATHINFO_EXTENSION);

return str($path)
->when($this->isMedia($extension))
->beforeLast('.'.$extension);
}

/**
* Determine if the given extension is a media extension.
*/
public function isMedia($extension): bool
{
return in_array($extension, $this->mediaExtensions);
}

/**
* Rename a file.
* Paths without extensions.
*
* @param string $path
* @param string $newpath
Expand All @@ -107,14 +129,16 @@ public function rename(string $path, string $newpath): bool

$remoteNewPath = ($pathInfo['dirname'] != '.') ? $newPathInfo['dirname'] . '/' . $newPathInfo['filename'] : $newPathInfo['filename'];

$result = $this->uploadApi()->rename($remotePath, $remoteNewPath);
$result = $this->uploadApi()->rename(
$this->preparePublicId($remotePath),
$this->preparePublicId($remoteNewPath)
);

return $result['public_id'] == $newPathInfo['filename'];
}

/**
* Expose the Cloudinary v2 Upload Functionality
*
* Expose the Cloudinary v2 Upload Functionality.
*/
protected function uploadApi(): UploadApi
{
Expand Down Expand Up @@ -147,6 +171,9 @@ protected function upload(string $file, array $options = []): void
*/
public function copy(string $source, string $destination, Config $config): void
{
$source = $this->preparePublicId($source);
$destination = $this->preparePublicId($destination);

$this->uploadApi()->upload($source, ['public_id' => $destination]);
}

Expand All @@ -160,8 +187,7 @@ public function copy(string $source, string $destination, Config $config): void
public function delete(string $path): void
{
try {

$result = $this->uploadApi()->destroy($path);
$result = $this->uploadApi()->destroy($this->preparePublicId($path));
$finalResult = is_array($result) && $result['result'] == 'ok';

if ($finalResult != 'ok') {
Expand Down Expand Up @@ -221,7 +247,7 @@ public function createDirectory(string $path, Config $config): void
public function fileExists(string $path): bool
{
try {
$this->adminApi()->asset($path);
$this->adminApi()->asset($this->preparePublicId($path));
} catch (Exception) {
return false;
}
Expand Down Expand Up @@ -250,7 +276,7 @@ public function directoryExists(string $path): bool
*/
public function read(string $path): string
{
$resource = (array)$this->adminApi()->asset($path);
$resource = (array)$this->adminApi()->asset($this->preparePublicId($path));

return file_get_contents($resource['secure_url']);
}
Expand All @@ -264,7 +290,7 @@ public function read(string $path): string
*/
public function readStream(string $path): bool
{
$resource = (array)$this->adminApi()->asset($path);
$resource = (array)$this->adminApi()->asset($this->preparePublicId($path));

return fopen($resource['secure_url'], 'rb');
}
Expand Down Expand Up @@ -417,7 +443,7 @@ public function getMetadata(string $path): array
*/
public function getResource(string $path): array
{
return (array)$this->adminApi()->asset($path);
return (array)$this->adminApi()->asset($this->preparePublicId($path));
}

/**
Expand Down
13 changes: 13 additions & 0 deletions tests/Unit/CloudinaryAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,16 @@
$result = Storage::disk('cloudinary')->url($file);
expect($result)->toEqual($url);
});

it('removes extensions from media resources but not raw resources', function ($actual, $expected) {
$adapter = Storage::disk('cloudinary')->getAdapter();

expect($adapter->preparePublicId($actual))->toBe($expected);
})->with([
['file.jpg', 'file'],
['file.png', 'file'],
['file.gif', 'file'],
['file.xlsx', 'file.xlsx'],
['file.zip', 'file.zip'],
['file.csv', 'file.csv'],
]);

0 comments on commit 6f0713d

Please sign in to comment.