Skip to content

Commit

Permalink
Feature/various fixes (#203)
Browse files Browse the repository at this point in the history
* Update 'fromUrl' method, add 'syncUploadFromUrl' method

* Add method to load secure signature

* Remove deplrecated methods

* Minor copy fixes

---------

Co-authored-by: Roman Sedykh <[email protected]>
  • Loading branch information
andrew72ru and rsedykh authored Mar 21, 2023
1 parent e715c00 commit e633940
Show file tree
Hide file tree
Showing 12 changed files with 95 additions and 97 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ The format is based now on [Keep a
Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to
[Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [4.1.0]
### Breaking changes
- `Uploadcare\Interfaces\UploaderInterface::checkStatus(string $token)` now returns `Uploadcare\Interfaces\File\FileInfoInterface`
### Added
- `Uploadcare\Interfaces\UploaderInterface::syncUploadFromUrl` method for synchronically uploading a file from a remote URL
- `Uploadcare\Interfaces\UploaderInterface::getSignature` method for get signature to use in third-party uploaders
### Removed
- `Uploadcare\Interfaces\Api\GroupApiInterface::storeGroup($id)`
- `Uploadcare\Group::store()`

## [4.0.2]
### Added
- Method `removeKey` to remove medatada keys
Expand Down
26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,21 @@ $url = 'https://httpbin.org/image/jpeg';
$result = $uploader->fromUrl($url, 'image/jpeg'); // If success, $result will be string to check upload status (see below)
```

You can upload files from URL **synchronically**,

```php
$url = 'https://httpbin.org/image/jpeg';
$result = $uploader->syncUploadFromUrl($url, 'image/jpeg'); // $result is Uploadcare\Interfaces\File\FileInfoInterface
```

Check an uploading file status,

```php
$url = 'https://httpbin.org/image/jpeg';
$result = $uploader->fromUrl($url, 'image/jpeg');
$status = $uploader->checkStatus($result); // Instance of Uploadcare\Interfaces\File\FileInfoInterface with isReady() === false until file is not uploaded.
```

Another way of uploading files is by using **a path**,

```php
Expand All @@ -143,12 +158,15 @@ $path = __DIR__ . '/squirrel.jpg';
$result = $uploader->fromContent(\file_get_contents($path), 'image/jpeg');
```

Check upload file status:
Secure signature. If you are using secure uploads, you can use `getSignature` method to fetch an instance of `SignatureInterface`. For example:

```php
$url = 'https://httpbin.org/image/jpeg';
$result = $uploader->fromUrl($url, 'image/jpeg');
$status = $uploader->checkStatus($result); // Will be 'waiting', 'progress', 'success', 'error' or 'unknown'
$configuration = \Uploadcare\Configuration::create($_ENV['UPLOADCARE_PUBLIC_KEY'], $_ENV['UPLOADCARE_SECRET_KEY']);
$uploader = (new \Uploadcare\Api($configuration))->uploader();
$signature = $uploader->getSignature();

$key = $signature->getSignature(); // Sign string
$expired = $signature->getExpire()->getTimestamp(); // Time when secure signature will expire
```

#### File metadata
Expand Down
19 changes: 2 additions & 17 deletions src/Apis/GroupApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function createGroup(iterable $files): GroupInterface
throw new \RuntimeException('Unable to deserialize response. Call to support');
}

return (new GroupDecorator($result, $this))->setConfiguration($this->configuration);
return (new GroupDecorator($result))->setConfiguration($this->configuration);
}

/**
Expand Down Expand Up @@ -98,22 +98,7 @@ public function groupInfo(string $id): GroupInterface
throw new \RuntimeException('Unable to deserialize response. Call to support');
}

return (new GroupDecorator($result, $this))->setConfiguration($this->configuration);
}

/**
* {@inheritDoc}
*
* @deprecated since Uploadcare API 0.7.0
* @see https://uploadcare.com/api-refs/rest-api/v0.7.0/#tag/Changelog
*/
public function storeGroup($id): GroupInterface
{
\trigger_deprecation('uploadcare/uploadcare-php', '4.0.1', 'This parameter was removed from Uploadcare API');

$result = $id instanceof GroupInterface ? $id : (new Group())->setId($id);

return (new GroupDecorator($result, $this))->setConfiguration($this->configuration);
return (new GroupDecorator($result))->setConfiguration($this->configuration);
}

public function removeGroup($id): void
Expand Down
2 changes: 1 addition & 1 deletion src/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/
final class Configuration implements ConfigurationInterface
{
public const LIBRARY_VERSION = 'v4.0.2';
public const LIBRARY_VERSION = 'v4.1.0';
public const API_VERSION = '0.7';
public const API_BASE_URL = 'api.uploadcare.com';
public const USER_AGENT_TEMPLATE = 'PHPUploadcare/{lib-version}/{publicKey} (PHP/{lang-version})';
Expand Down
4 changes: 2 additions & 2 deletions src/Exception/HttpException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class HttpException extends \RuntimeException
{
public function __construct(string $message = '', int $code = 0, \Exception $previous = null)
public function __construct(string $message = '', int $code = 0, \Throwable $previous = null)
{
if ($previous !== null) {
$message = $this->makeMessage($previous, $message);
Expand All @@ -16,7 +16,7 @@ public function __construct(string $message = '', int $code = 0, \Exception $pre
parent::__construct($message, $code, $previous);
}

protected function makeMessage(\Exception $exception, string $message = ''): string
protected function makeMessage(\Throwable $exception, string $message = ''): string
{
$messages = [];
if (!empty($message)) {
Expand Down
15 changes: 1 addition & 14 deletions src/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Uploadcare;

use Uploadcare\Apis\{FileApi, GroupApi};
use Uploadcare\Exception\HttpException;
use Uploadcare\Interfaces\File\CollectionInterface;
use Uploadcare\Interfaces\{ConfigurationInterface, GroupInterface};

Expand All @@ -14,14 +13,11 @@ final class Group implements GroupInterface
{
private GroupInterface $inner;

private GroupApi $api;

private ?ConfigurationInterface $configuration = null;

public function __construct(GroupInterface $inner, GroupApi $api)
public function __construct(GroupInterface $inner)
{
$this->inner = $inner;
$this->api = $api;
}

public function setConfiguration(ConfigurationInterface $configuration): self
Expand All @@ -31,15 +27,6 @@ public function setConfiguration(ConfigurationInterface $configuration): self
return $this;
}

public function store(): GroupInterface
{
if (($id = $this->inner->getId()) === null) {
throw new HttpException();
}

return $this->api->storeGroup($id);
}

public function getId(): ?string
{
return $this->inner->getId();
Expand Down
2 changes: 1 addition & 1 deletion src/GroupCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ private function decorateElements(): void
{
foreach ($this->inner->toArray() as $k => $el) {
if ($el instanceof GroupInterface) {
$this->elements[$k] = new Group($el, $this->api);
$this->elements[$k] = new Group($el);
}
}
}
Expand Down
11 changes: 0 additions & 11 deletions src/Interfaces/Api/GroupApiInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,6 @@ public function listGroups(int $limit, bool $asc = true): ListResponseInterface;
*/
public function groupInfo(string $id): GroupInterface;

/**
* Mark all files in a group as stored.
*
* @param string|GroupInterface $id Group UUID
*
* @throws HttpException
*
* @deprecated
*/
public function storeGroup($id): GroupInterface;

/**
* Delete a file group.
* The operation only removes the group object itself. All the files that were part of the group are left as is.
Expand Down
17 changes: 15 additions & 2 deletions src/Interfaces/UploaderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Uploadcare\Interfaces;

use Uploadcare\Exception\HttpException;
use Uploadcare\Exception\InvalidArgumentException;
use Uploadcare\Interfaces\File\FileInfoInterface;

Expand All @@ -14,6 +15,11 @@ interface UploaderInterface
public const UPLOADCARE_EXPIRE_KEY = 'expire';
public const UPLOADCARE_DEFAULT_STORE = 'auto';

/**
* Get signature to use outside of this library.
*/
public function getSignature(): SignatureInterface;

/**
* Upload file from local path.
*
Expand All @@ -28,6 +34,13 @@ public function fromPath(string $path, string $mimeType = null, string $filename
*/
public function fromUrl(string $url, string $mimeType = null, string $filename = null, string $store = 'auto', array $metadata = []): string;

/**
* Synchronically upload a file from a remote URL. Returns FileInfoInterface.
*
* @throws InvalidArgumentException|HttpException
*/
public function syncUploadFromUrl(string $url, string $mimeType = null, string $filename = null, string $store = 'auto', array $metadata = []): FileInfoInterface;

/**
* Upload file from resource opened by `\fopen()`.
*
Expand All @@ -51,7 +64,7 @@ public function fromContent(string $content, string $mimeType = null, string $fi
*
* @see \Uploadcare\Interfaces\UploaderInterface::fromUrl
*
* @return string one of 'waiting', 'progress', 'success', 'error', 'unknown'
* @throws HttpException
*/
public function checkStatus(string $token): string;
public function checkStatus(string $token): FileInfoInterface;
}
46 changes: 41 additions & 5 deletions src/Uploader/AbstractUploader.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
use Uploadcare\Apis\FileApi;
use Uploadcare\Exception\Upload\{AccountException, FileTooLargeException, RequestParametersException, ThrottledException};
use Uploadcare\Exception\{HttpException, InvalidArgumentException};
use Uploadcare\File\File;
use Uploadcare\File\Metadata;
use Uploadcare\Interfaces\{ConfigurationInterface, File\FileInfoInterface, UploaderInterface};
use Uploadcare\Interfaces\{ConfigurationInterface, File\FileInfoInterface, SignatureInterface, UploaderInterface};

/**
* Main Uploader.
Expand All @@ -22,6 +23,11 @@ public function __construct(ConfigurationInterface $configuration)
$this->configuration = $configuration;
}

public function getSignature(): SignatureInterface
{
return $this->configuration->getSecureSignature();
}

/**
* @param array<array-key, string> $files List of file ID's
*/
Expand Down Expand Up @@ -78,6 +84,16 @@ public function fromPath(string $path, string $mimeType = null, string $filename
return $this->fromResource(\fopen($path, 'rb'), $mimeType, $filename, $store, $metadata);
}

public function syncUploadFromUrl(string $url, string $mimeType = null, string $filename = null, string $store = 'auto', array $metadata = []): FileInfoInterface
{
$token = $this->fromUrl($url, $mimeType, $filename, $store, $metadata);
do {
$file = $this->checkStatus($token);
} while ($file->isReady() === false);

return $file;
}

/**
* Upload file from remote URL.
*
Expand All @@ -88,18 +104,20 @@ public function fromUrl(string $url, string $mimeType = null, string $filename =
$checkDuplicates = false;
$storeDuplicates = false;
if (\array_key_exists('checkDuplicates', $metadata)) {
$checkDuplicates = true;
$checkDuplicates = (bool) $metadata['checkDuplicates'];
unset($metadata['checkDuplicates']);
}
if (\array_key_exists('storeDuplicates', $metadata)) {
$storeDuplicates = true;
$storeDuplicates = (bool) $metadata['storeDuplicates'];
unset($metadata['storeDuplicates']);
}

$parameters = $this->makeMultipartParameters(\array_merge($this->getDefaultParameters(), [
'source_url' => $url,
'check_URL_duplicates' => $checkDuplicates ? '1' : '0',
'save_URL_duplicates' => $storeDuplicates ? '1' : '0',
'filename' => $filename,
'store' => $store,
'pub_key' => $this->configuration->getPublicKey(),
], $this->makeMetadataParameters($metadata)));

Expand All @@ -122,7 +140,7 @@ public function fromUrl(string $url, string $mimeType = null, string $filename =
return (string) $responseArray['token'];
}

public function checkStatus(string $token): string
public function checkStatus(string $token): FileInfoInterface
{
try {
$request = $this->sendRequest('GET', '/from_url/status/', [
Expand All @@ -137,7 +155,25 @@ public function checkStatus(string $token): string
throw new HttpException('Unable to get \'status\' key from response');
}

return (string) $response['status'];
switch ($response['status']) {
case 'waiting':
case 'progress':
case 'unknown':
default:
$result = (new File())->setIsReady(false);
break;
case 'success':
$result = $this->configuration->getSerializer()->deserialize($request, File::class);
break;
case 'error':
$errorCode = $response['error_code'] ?? '400';
throw new HttpException($response['error'] ?? 'Error in upload', (int) $errorCode);
}
if (!$result instanceof File) {
throw new \RuntimeException('Unable to deserialize response. Call to support');
}

return $result;
}

/**
Expand Down
27 changes: 0 additions & 27 deletions tests/Api/GroupApiAnswersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
use Uploadcare\Configuration;
use Uploadcare\File\File;
use Uploadcare\File\FileCollection;
use Uploadcare\File\Group;
use Uploadcare\Interfaces\ConfigurationInterface;
use Uploadcare\Interfaces\GroupInterface;
use Uploadcare\Response\GroupListResponse;
use Uploadcare\Security\Signature;
use Uploadcare\Serializer\Serializer;
Expand Down Expand Up @@ -66,31 +64,6 @@ public function testGroupInfoResponse(): void
self::assertInstanceOf(\Uploadcare\File::class, $result->getFiles()->first());
}

public function provideGroupsForStore(): array
{
return [
[\uuid_create()],
[(new Group())->setId(\uuid_create())],
];
}

/**
* @dataProvider provideGroupsForStore
*
* @param string|GroupInterface $group
*/
public function testStoreGroup($group): void
{
$answers = [
new Response(200, []),
new Response(200, [], DataFile::contents('group/group-info-response.json')),
];
$conf = $this->getConfig($answers);
$api = new GroupApi($conf);

self::assertInstanceOf(GroupInterface::class, $api->storeGroup($group));
}

public function testListGroups(): void
{
$data = DataFile::contents('group/list-groups-response.json');
Expand Down
13 changes: 0 additions & 13 deletions tests/Decorated/DecoratedGroupTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,6 @@ public function testGroupInfo(): void
self::assertInstanceOf(Group::class, $api->groupInfo(\uuid_create()));
}

public function testStoreGroup(): void
{
$api = $this->fakeApi([
new Response(200),
new Response(200, [], DataFile::contents('group/group-info-response.json')),
]);
$group = SerializerFactory::create()->deserialize(DataFile::contents('group/group-info-response.json'), \Uploadcare\File\Group::class);
/** @noinspection PhpParamsInspection */
$decorated = new Group($group, $api);

self::assertInstanceOf(Group::class, $decorated->store());
}

public function provideMethods(): array
{
return [
Expand Down

0 comments on commit e633940

Please sign in to comment.