diff --git a/composer.json b/composer.json index 5e78058..bca6ba6 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,8 @@ ], "require": { "php": ">=8.0", - "guzzlehttp/guzzle": "^7.10" + "guzzlehttp/guzzle": "^7.10", + "nesbot/carbon": "^3.10" }, "require-dev": { "laravel/pint": "^1.25", diff --git a/src/Contracts/HamroCDNContract.php b/src/Contracts/HamroCDNContract.php index 53a1917..a8609e1 100644 --- a/src/Contracts/HamroCDNContract.php +++ b/src/Contracts/HamroCDNContract.php @@ -4,22 +4,12 @@ namespace HamroCDN\Contracts; +use HamroCDN\Models\Upload; + /** - * @phpstan-type HamroCDNFile array{ - * url: string, - * size: int - * } - * @phpstan-type HamroCDNUser array{ - * name: string, - * email: string, - * role: string - * } - * @phpstan-type HamroCDNObject array{ - * nanoId: string, - * user: HamroCDNUser, - * delete_at: string|null, - * original: HamroCDNFile - * } + * @phpstan-import-type HamroCDNObject from Upload + * @phpstan-import-type UploadWithPagination from Upload + * * @phpstan-type HamroCDNData array{ * data: HamroCDNObject * } @@ -33,28 +23,22 @@ interface HamroCDNContract /** * List all of your files in HamroCDN. * - * @return HamroCDNObjectWithPagination + * @return UploadWithPagination */ public function index(): array; /** * Fetch a file from HamroCDN. - * - * @return HamroCDNData */ - public function fetch(string $nanoId): array; + public function fetch(string $nanoId): Upload; /** * Upload a file to HamroCDN. - * - * @return HamroCDNData */ - public function upload(string $filePath): array; + public function upload(string $filePath): Upload; /** * Upload a file to HamroCDN by URL. - * - * @return HamroCDNData */ - public function uploadByURL(string $url): array; + public function uploadByURL(string $url): Upload; } diff --git a/src/HamroCDN.php b/src/HamroCDN.php index a5f59a6..048477c 100644 --- a/src/HamroCDN.php +++ b/src/HamroCDN.php @@ -7,10 +7,12 @@ use GuzzleHttp\Client; use HamroCDN\Contracts\HamroCDNContract; use HamroCDN\Exceptions\HamroCDNException; +use HamroCDN\Models\Upload; use HamroCDN\Traits\HasConfigValues; use HamroCDN\Traits\Requestable; /** + * @phpstan-import-type HamroCDNObject from Upload * @phpstan-import-type HamroCDNData from HamroCDNContract * @phpstan-import-type HamroCDNObjectWithPagination from HamroCDNContract */ @@ -37,37 +39,46 @@ public function __construct(?string $apiKey = null, ?string $baseUrl = null, ?Cl } /** - * @return HamroCDNObjectWithPagination - * * @throws HamroCDNException */ public function index(?int $per_page = 20, ?int $page = 1): array { - /** @var HamroCDNObjectWithPagination */ - return $this->get('uploads', [ + /** @var HamroCDNObjectWithPagination $response */ + $response = $this->get('uploads', [ 'per_page' => $per_page, 'page' => $page, ]); + + return [ + 'data' => array_map( + /** @param HamroCDNObject $item */ + fn (array $item): Upload => Upload::fromArray($item), + $response['data'] + ), + 'meta' => $response['meta'], + ]; } /** * @throws HamroCDNException */ - public function fetch(string $nanoId): array + public function fetch(string $nanoId): Upload { - return $this->get("uploads/{$nanoId}"); + $response = $this->get("uploads/{$nanoId}"); + + return Upload::fromArray($response['data']); } /** * @throws HamroCDNException */ - public function upload(string $filePath): array + public function upload(string $filePath): Upload { if (! file_exists($filePath)) { throw HamroCDNException::fileError($filePath); } - return $this->post('uploads', [ + $response = $this->post('uploads', [ 'multipart' => [ [ 'name' => 'file', @@ -76,17 +87,21 @@ public function upload(string $filePath): array ], ], ]); + + return Upload::fromArray($response['data']); } /** * @throws HamroCDNException */ - public function uploadByURL(string $url): array + public function uploadByURL(string $url): Upload { - return $this->post('upload-from-url', [ + $response = $this->post('upload-from-url', [ 'json' => [ 'url' => $url, ], ]); + + return Upload::fromArray($response['data']); } } diff --git a/src/Models/File.php b/src/Models/File.php new file mode 100644 index 0000000..25ba481 --- /dev/null +++ b/src/Models/File.php @@ -0,0 +1,47 @@ +url; + } + + public function getSize(): int + { + return $this->size; + } + + /** @return HamroCDNFile */ + public function toArray(): array + { + return [ + 'url' => $this->url, + 'size' => $this->size, + ]; + } +} diff --git a/src/Models/Upload.php b/src/Models/Upload.php new file mode 100644 index 0000000..1107f98 --- /dev/null +++ b/src/Models/Upload.php @@ -0,0 +1,81 @@ +, + * meta: array{total: int, per_page: int, page: int} + * } + */ +final class Upload +{ + public function __construct( + private string $nanoId, + private ?User $user, + private ?Carbon $deleteAt, + private File $original + ) {} + + /** @param HamroCDNObject $data */ + public static function fromArray(array $data): self + { + $user = null; + if (isset($data['user'])) { + $user = User::fromArray($data['user']); + } + + $original = File::fromArray($data['original']); + + return new self( + $data['nanoId'], + $user, + isset($data['delete_at']) ? new Carbon($data['delete_at']) : null, + $original + ); + } + + public function getNanoId(): string + { + return $this->nanoId; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function getDeleteAt(): ?Carbon + { + return $this->deleteAt; + } + + public function getOriginal(): File + { + return $this->original; + } + + /** @return HamroCDNObject */ + public function toArray(): array + { + return [ + 'nanoId' => $this->nanoId, + 'user' => $this->user?->toArray(), + 'delete_at' => $this->deleteAt, + 'original' => $this->original->toArray(), + ]; + } +} diff --git a/src/Models/User.php b/src/Models/User.php new file mode 100644 index 0000000..f22b399 --- /dev/null +++ b/src/Models/User.php @@ -0,0 +1,47 @@ +name; + } + + public function getEmail(): string + { + return $this->email; + } + + /** @return HamroCDNUser */ + public function toArray(): array + { + return [ + 'name' => $this->name, + 'email' => $this->email, + ]; + } +} diff --git a/tests/UploadTest.php b/tests/UploadTest.php index d627cf8..035f6cf 100644 --- a/tests/UploadTest.php +++ b/tests/UploadTest.php @@ -4,6 +4,55 @@ use HamroCDN\Exceptions\HamroCDNException; use HamroCDN\HamroCDN; +use HamroCDN\Models\Upload; +use HamroCDN\Models\User; + +expect()->extend('toBeUploadObject', function () { + /** @var Upload $upload */ + $upload = $this->value; + + expect($upload) + ->toBeInstanceOf(Upload::class); + + expect($upload) + ->toHaveKey('nanoId') + ->toHaveKey('user') + ->toHaveKey('delete_at') + ->toHaveKey('original'); + + expect($upload->getOriginal()) + ->toHaveKey('url') + ->toHaveKey('size'); + + expect($upload->getUser()) + ->toBeInstanceOf(User::class); +}); + +it('checks the dummy data to have correct value in model', function () { + $dummyData = [ + 'nanoId' => 'abc123', + 'user' => [ + 'name' => 'John Doe', + 'email' => 'john@hamrocdn.com', + ], + 'delete_at' => null, + 'original' => [ + 'url' => 'https://hamrocdn.com/abc123.png', + 'size' => 2048, + ], + ]; + + $upload = Upload::fromArray($dummyData); + + expect($upload)->toBeUploadObject(); + + expect($upload->getNanoId())->toBe('abc123'); + expect($upload->getDeleteAt())->toBeNull(); + expect($upload->getOriginal()->getUrl())->toBe('https://hamrocdn.com/abc123.png'); + expect($upload->getOriginal()->getSize())->toBe(2048); + expect($upload->getUser()?->getName())->toBe('John Doe'); + expect($upload->getUser()?->getEmail())->toBe('john@hamrocdn.com'); +}); it('returns an array of HamroCDN objects from index', function () { $client = new HamroCDN('test-api-key', 'https://hamrocdn.com/api'); @@ -15,22 +64,14 @@ ->toHaveKey('data') ->toHaveKey('meta'); - foreach ($uploads['data'] as $upload) { - expect($upload) - ->toHaveKey('nanoId') - ->toHaveKey('user') - ->toHaveKey('delete_at') - ->toHaveKey('original'); - - expect($upload['original']) - ->toHaveKey('url') - ->toHaveKey('size'); - } - expect($uploads['meta']) ->toHaveKey('total') ->toHaveKey('per_page') ->toHaveKey('page'); + + foreach ($uploads['data'] as $upload) { + expect($upload)->toBeUploadObject(); + } }); it('uploads a file and returns a HamroCDN object', function () { @@ -38,24 +79,15 @@ $filePath = __DIR__.'/test.png'; $upload = $client->upload($filePath); - $data = $upload['data']; - expect($data) - ->toHaveKey('nanoId') - ->toHaveKey('user') - ->toHaveKey('delete_at') - ->toHaveKey('original'); + expect($upload)->toBeUploadObject(); - $fetchResponse = $client->fetch($data['nanoId']); - $fetchedData = $fetchResponse['data']; + $fetchedUpload = $client->fetch($upload->getNanoId()); - expect($fetchedData) - ->toHaveKey('nanoId') - ->toHaveKey('user') - ->toHaveKey('delete_at') - ->toHaveKey('original'); + expect($fetchedUpload) + ->toBeUploadObject(); - expect($fetchedData['nanoId'])->toBe($data['nanoId']); + expect($fetchedUpload->getNanoId())->toBe($upload->getNanoId()); }); it('uploads a file by URL and returns a HamroCDN object', function () { @@ -64,24 +96,11 @@ $fileUrl = 'https://placehold.co/1000x1000/000000/FFFFFF?text=HamroCDN'; $upload = $client->uploadByURL($fileUrl); - $data = $upload['data']; - - expect($data) - ->toHaveKey('nanoId') - ->toHaveKey('user') - ->toHaveKey('delete_at') - ->toHaveKey('original'); - - $fetchResponse = $client->fetch($data['nanoId']); - $fetchedData = $fetchResponse['data']; - - expect($fetchedData) - ->toHaveKey('nanoId') - ->toHaveKey('user') - ->toHaveKey('delete_at') - ->toHaveKey('original'); + expect($upload)->toBeUploadObject(); - expect($fetchedData['nanoId'])->toBe($data['nanoId']); + $fetchedUpload = $client->fetch($upload->getNanoId()); + expect($fetchedUpload) + ->toBeUploadObject(); }); describe('exception', function () { @@ -129,14 +148,14 @@ }); it('throws network error when Guzzle cannot connect to server. (GET)', function () { - $client = new HamroCDN('test-api-key', 'https://hamrocdn123.com/invalid-api'); + $client = new HamroCDN('test-api-key', 'https://hamrocdn.com/invalid-api'); $this->expectException(HamroCDNException::class); $client->index(); }); it('throws network error when Guzzle cannot connect to server. (POST)', function () { - $client = new HamroCDN('test-api-key', 'https://hamrocdn123.com/invalid-api'); + $client = new HamroCDN('test-api-key', 'https://hamrocdn.com/invalid-api'); $filePath = __DIR__.'/test.png';