Skip to content

Commit

Permalink
Merge pull request #114 from netgen/feature/move-action
Browse files Browse the repository at this point in the history
Feature/move action
  • Loading branch information
RandyCupic authored Dec 3, 2024
2 parents 20a85b7 + 935d6ff commit a1015fc
Show file tree
Hide file tree
Showing 13 changed files with 414 additions and 5 deletions.
4 changes: 4 additions & 0 deletions lib/API/ProviderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,12 @@ public function loadFromRemote(string $remoteId): RemoteResource;

public function store(RemoteResource $resource): RemoteResource;

public function move(RemoteResource $resource, ?Folder $destinationFolder): RemoteResource;

public function remove(RemoteResource $resource): void;

public function moveOnRemote(RemoteResource $resource, ?Folder $destinationFolder): RemoteResource;

public function deleteFromRemote(RemoteResource $resource): void;

/**
Expand Down
20 changes: 20 additions & 0 deletions lib/Core/AbstractProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,26 @@ public function store(RemoteResource $resource): RemoteResource
return $existingResource;
}

public function move(RemoteResource $resource, ?Folder $destinationFolder): RemoteResource
{
$newResource = $this->moveOnRemote($resource, $destinationFolder);

try {
$existingResource = $resource->getId() !== null
? $this->load($resource->getId())
: $this->loadByRemoteId($resource->getRemoteId());

$existingResource->refresh($newResource);

$this->store($existingResource);

return $existingResource;
} catch (RemoteResourceNotFoundException $e) {
}

return $newResource;
}

public function remove(RemoteResource $resource): void
{
$this->entityManager->remove($resource);
Expand Down
27 changes: 27 additions & 0 deletions lib/Core/Provider/Cloudinary/CloudinaryProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,33 @@ public function loadFromRemote(string $remoteId): RemoteResource
throw new RemoteResourceNotFoundException($remoteId);
}

public function moveOnRemote(RemoteResource $resource, ?Folder $destinationFolder): RemoteResource
{
if ($this->folderMode === self::FOLDER_MODE_FIXED) {
$cloudinaryRemoteId = CloudinaryRemoteId::fromRemoteId($resource->getRemoteId(), $this->folderMode);
$newCloudinaryRemoteId = (clone $cloudinaryRemoteId)->move($destinationFolder);

$this->gateway->rename($cloudinaryRemoteId, $newCloudinaryRemoteId);

return $resource->refresh(
$this->loadFromRemote($newCloudinaryRemoteId->getRemoteId()),
);
}

$options = [
'asset_folder' => $destinationFolder instanceof Folder ? $destinationFolder->getPath() : '/',
];

$this->gateway->update(
CloudinaryRemoteId::fromRemoteId($resource->getRemoteId(), $this->folderMode),
$options,
);

return $resource->refresh(
$this->loadFromRemote($resource->getRemoteId()),
);
}

public function deleteFromRemote(RemoteResource $resource): void
{
$this->gateway->delete(
Expand Down
31 changes: 27 additions & 4 deletions lib/Core/Provider/Cloudinary/CloudinaryRemoteId.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
use function count;
use function explode;
use function implode;
use function ltrim;
use function sprintf;
use function str_replace;

final class CloudinaryRemoteId
{
Expand Down Expand Up @@ -81,10 +83,7 @@ public function getResourceId(): string
public function getFolder(): ?Folder
{
if ($this->folderMode !== CloudinaryProvider::FOLDER_MODE_FIXED) {
throw new NotSupportedException(
'Cloudinary',
sprintf('fetching folder from path in "%s" folder mode', $this->folderMode),
);
throw new NotSupportedException('Cloudinary', sprintf('fetching folder from path in "%s" folder mode', $this->folderMode));
}

$resourceIdParts = explode('/', $this->resourceId);
Expand All @@ -96,4 +95,28 @@ public function getFolder(): ?Folder

return Folder::fromPath(implode('/', $resourceIdParts));
}

public function move(?Folder $folder): self
{
if ($this->folderMode !== CloudinaryProvider::FOLDER_MODE_FIXED) {
throw new NotSupportedException('Cloudinary', sprintf('moving to folder via public ID in %s folder mode', $this->folderMode));
}

$this->resourceId = $this->resolveNewResourceId($folder);

return $this;
}

private function resolveNewResourceId(?Folder $folder): string
{
$resourceId = $this->getFolder() instanceof Folder
? ltrim(str_replace($this->getFolder()->getPath(), '', $this->resourceId), '/')
: $this->resourceId;

if (!$folder instanceof Folder) {
return $resourceId;
}

return sprintf('%s/%s', $folder->getPath(), $resourceId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,14 @@ public function update(CloudinaryRemoteId $remoteId, array $options): void
$this->invalidateTagsCache();
}

public function rename(CloudinaryRemoteId $fromRemoteId, CloudinaryRemoteId $toRemoteId): void
{
$this->gateway->rename($fromRemoteId, $toRemoteId);

$this->invalidateResourceCache($fromRemoteId);
$this->invalidateResourceListCache();
}

public function removeAllTagsFromResource(CloudinaryRemoteId $remoteId): void
{
$this->gateway->removeAllTagsFromResource($remoteId);
Expand Down
22 changes: 22 additions & 0 deletions lib/Core/Provider/Cloudinary/Gateway/CloudinaryApiGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Netgen\RemoteMedia\Core\Provider\Cloudinary\Gateway;

use Cloudinary\Api\Admin\AdminApi;
use Cloudinary\Api\Exception\BadRequest as CloudinaryBadRequest;
use Cloudinary\Api\Exception\NotFound as CloudinaryNotFound;
use Cloudinary\Api\Search\SearchApi;
use Cloudinary\Api\Upload\UploadApi;
Expand Down Expand Up @@ -193,6 +194,27 @@ public function update(CloudinaryRemoteId $remoteId, array $options): void
}
}

public function rename(CloudinaryRemoteId $fromRemoteId, CloudinaryRemoteId $toRemoteId): void
{
$options = [
'type' => $toRemoteId->getType(),
'resource_type' => $toRemoteId->getResourceType(),
'invalidate' => true,
];

try {
$this->uploadApi->rename($fromRemoteId->getResourceId(), $toRemoteId->getResourceId(), $options);
} catch (CloudinaryNotFound $e) {
throw new RemoteResourceNotFoundException($fromRemoteId->getRemoteId());
} catch (CloudinaryBadRequest $e) {
try {
throw new RemoteResourceExistsException($this->get($toRemoteId));
} catch (CloudinaryNotFound $e2) {
throw $e;
}
}
}

public function removeAllTagsFromResource(CloudinaryRemoteId $remoteId): void
{
$options = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ public function update(CloudinaryRemoteId $remoteId, array $options): void
$this->gateway->update($remoteId, $options);
}

public function rename(CloudinaryRemoteId $fromRemoteId, CloudinaryRemoteId $toRemoteId): void
{
$this->logger->info("[API][FREE] rename(\"{$fromRemoteId->getRemoteId()}\", \"{$toRemoteId->getRemoteId()}\") -> Cloudinary\\Uploader::explicit(\"{$fromRemoteId->getRemoteId()}\")");

$this->gateway->rename($fromRemoteId, $toRemoteId);
}

public function removeAllTagsFromResource(CloudinaryRemoteId $remoteId): void
{
$this->logger->info("[API][FREE] removeAllTagsFromResource(\"{$remoteId->getRemoteId()}\") -> Cloudinary\\Api::remove_all_tags(\"{$remoteId->getRemoteId()}\")");
Expand Down
6 changes: 6 additions & 0 deletions lib/Core/Provider/Cloudinary/GatewayInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ public function upload(string $fileUri, array $options): RemoteResource;
*/
public function update(CloudinaryRemoteId $remoteId, array $options): void;

/**
* @throws RemoteResourceNotFoundException
* @throws RemoteResourceExistsException
*/
public function rename(CloudinaryRemoteId $fromRemoteId, CloudinaryRemoteId $toRemoteId): void;

/**
* @throws RemoteResourceNotFoundException
*/
Expand Down
97 changes: 97 additions & 0 deletions tests/lib/Core/AbstractProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,103 @@ public function testStoreExistingRemoteId(): void
);
}

public function testMoveWithoutStored(): void
{
$remoteResource = new RemoteResource(
remoteId: 'media/images/test_image.jpg',
type: 'image',
url: 'https://cloudinary.com/upload/image/media/images/test_image.jpg',
md5: 'e522f43cf89aa0afd03387c37e2b6e29',
name: 'test_image.jpg',
folder: Folder::fromPath('media/images'),
size: 250,
);

$newRemoteResource = new RemoteResource(
remoteId: 'new/media/images/test_image.jpg',
type: 'image',
url: 'https://cloudinary.com/upload/image/new/media/images/test_image.jpg',
md5: 'e522f43cf89aa0afd03387c37e2b6e29',
name: 'test_image.jpg',
folder: Folder::fromPath('new/media/images'),
size: 250,
);

$this->provider
->expects(self::once())
->method('moveOnRemote')
->with($remoteResource, Folder::fromPath('new/media/images'))
->willReturn($newRemoteResource);

$this->resourceRepository
->expects(self::once())
->method('findOneBy')
->with(['remoteId' => $remoteResource->getRemoteId()])
->willReturn(null);

$returnedRemoteResource = $this->provider->move($remoteResource, Folder::fromPath('new/media/images'));

self::assertRemoteResourceSame($newRemoteResource, $returnedRemoteResource);
}

public function testMoveWithStored(): void
{
$remoteResource = new RemoteResource(
remoteId: 'media/images/test_image.jpg',
type: 'image',
url: 'https://cloudinary.com/upload/image/media/images/test_image.jpg',
md5: 'e522f43cf89aa0afd03387c37e2b6e29',
id: 5,
name: 'test_image.jpg',
folder: Folder::fromPath('media/images'),
size: 250,
);

$newRemoteResource = new RemoteResource(
remoteId: 'new/media/images/test_image.jpg',
type: 'image',
url: 'https://cloudinary.com/upload/image/new/media/images/test_image.jpg',
md5: 'e522f43cf89aa0afd03387c37e2b6e29',
id: 5,
name: 'test_image.jpg',
folder: Folder::fromPath('new/media/images'),
size: 250,
);

$this->provider
->expects(self::once())
->method('moveOnRemote')
->with($remoteResource, Folder::fromPath('new/media/images'))
->willReturn($newRemoteResource);

$this->resourceRepository
->expects(self::once())
->method('find')
->with(5)
->willReturn($remoteResource);

$dateTime = new DateTimeImmutable('now');
$newRemoteResource->setUpdatedAt($dateTime);

$this->dateTimeFactory
->expects(self::once())
->method('createCurrent')
->willReturn($dateTime);

$this->entityManager
->expects(self::once())
->method('persist')
->with($newRemoteResource);

$this->entityManager
->expects(self::once())
->method('flush');

$returnedRemoteResource = $this->provider->move($remoteResource, Folder::fromPath('new/media/images'));

self::assertRemoteResourceSame($newRemoteResource, $returnedRemoteResource);
}

public function testRemove(): void
{
$remoteResource = new RemoteResource(
Expand Down
Loading

0 comments on commit a1015fc

Please sign in to comment.