From 65d2adc9f02fba5de13e2580ad7f3740da22eb45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20G=C3=B6r=C3=9F?= Date: Fri, 31 May 2024 12:16:10 +0200 Subject: [PATCH] feat: add upload and link file --- src/Enums/OnOfficeResourceType.php | 1 + src/Facades/FileRepository.php | 27 ++++ src/Facades/Testing/FileRepositoryFake.php | 18 +++ .../Testing/RecordFactories/BaseFactory.php | 12 +- .../RecordFactories/FileUploadFactory.php | 55 +++++++++ .../MarketPlaceUnlockProviderFactory.php | 12 +- src/Query/Testing/UploadBuilderFake.php | 38 ++++++ src/Query/UploadBuilder.php | 115 ++++++++++++++++++ src/Repositories/FileRepository.php | 22 ++++ tests/Query/UploadBuilderTest.php | 69 +++++++++++ tests/Stubs/LinkDataResponse.php | 55 +++++++++ tests/Stubs/UploadFileResponse.php | 55 +++++++++ tests/Testing/FileRepositoryFakeTest.php | 109 +++++++++++++++++ 13 files changed, 576 insertions(+), 12 deletions(-) create mode 100644 src/Facades/FileRepository.php create mode 100644 src/Facades/Testing/FileRepositoryFake.php create mode 100644 src/Facades/Testing/RecordFactories/FileUploadFactory.php create mode 100644 src/Query/Testing/UploadBuilderFake.php create mode 100644 src/Query/UploadBuilder.php create mode 100644 src/Repositories/FileRepository.php create mode 100644 tests/Query/UploadBuilderTest.php create mode 100644 tests/Stubs/LinkDataResponse.php create mode 100644 tests/Stubs/UploadFileResponse.php create mode 100644 tests/Testing/FileRepositoryFakeTest.php diff --git a/src/Enums/OnOfficeResourceType.php b/src/Enums/OnOfficeResourceType.php index 706ab55..09f25bc 100644 --- a/src/Enums/OnOfficeResourceType.php +++ b/src/Enums/OnOfficeResourceType.php @@ -13,4 +13,5 @@ enum OnOfficeResourceType: string case Users = 'users'; case UnlockProvider = 'unlockProvider'; case Regions = 'regions'; + case UploadFile = 'uploadfile'; } diff --git a/src/Facades/FileRepository.php b/src/Facades/FileRepository.php new file mode 100644 index 0000000..c372949 --- /dev/null +++ b/src/Facades/FileRepository.php @@ -0,0 +1,27 @@ +fakeResponses); + } +} diff --git a/src/Facades/Testing/RecordFactories/BaseFactory.php b/src/Facades/Testing/RecordFactories/BaseFactory.php index b81adcf..fc9f265 100644 --- a/src/Facades/Testing/RecordFactories/BaseFactory.php +++ b/src/Facades/Testing/RecordFactories/BaseFactory.php @@ -17,35 +17,35 @@ final public function __construct() { } - public function id(int $id): self + public function id(int $id): static { $this->id = $id; return $this; } - public function type(string $type): self + public function type(string $type): static { $this->type = $type; return $this; } - public function set(string $key, mixed $value): self + public function set(string $key, mixed $value): static { $this->elements[$key] = $value; return $this; } - public function data(array $data): self + public function data(array $data): static { $this->elements = array_merge($this->elements, $data); return $this; } - public static function make(): self + public static function make(): static { return new static(); } @@ -64,7 +64,7 @@ public function toArray(): array ]; } - public function __call(string $name, array $arguments): self + public function __call(string $name, array $arguments): static { if (str_starts_with($name, 'set')) { $key = lcfirst(substr($name, 3)); diff --git a/src/Facades/Testing/RecordFactories/FileUploadFactory.php b/src/Facades/Testing/RecordFactories/FileUploadFactory.php new file mode 100644 index 0000000..509f2dd --- /dev/null +++ b/src/Facades/Testing/RecordFactories/FileUploadFactory.php @@ -0,0 +1,55 @@ +toString(); + } + + $this->elements['tmpUploadId'] = $tmpUploadId; + + return $this; + } + + public function success(bool $success): static + { + $this->elements['success'] = $success ? 'success' : 'error'; + + return $this; + } + + public function ok(): static + { + $this->elements['success'] = 'success'; + + return $this; + } + + public function error(): static + { + $this->elements['success'] = 'error'; + + return $this; + } +} diff --git a/src/Facades/Testing/RecordFactories/MarketPlaceUnlockProviderFactory.php b/src/Facades/Testing/RecordFactories/MarketPlaceUnlockProviderFactory.php index 51376f0..7d18abc 100644 --- a/src/Facades/Testing/RecordFactories/MarketPlaceUnlockProviderFactory.php +++ b/src/Facades/Testing/RecordFactories/MarketPlaceUnlockProviderFactory.php @@ -4,36 +4,36 @@ class MarketPlaceUnlockProviderFactory extends BaseFactory { - public function id(int $id): self + public function id(int $id): static { return $this; } - public function type(string $type): self + public function type(string $type): static { return $this; } - public function elements(): self + public function elements(): static { return $this; } - public function success(bool $success): self + public function success(bool $success): static { $this->elements['success'] = $success ? 'success' : 'error'; return $this; } - public function ok(): self + public function ok(): static { $this->elements['success'] = 'success'; return $this; } - public function error(): self + public function error(): static { $this->elements['success'] = 'error'; diff --git a/src/Query/Testing/UploadBuilderFake.php b/src/Query/Testing/UploadBuilderFake.php new file mode 100644 index 0000000..91f57a3 --- /dev/null +++ b/src/Query/Testing/UploadBuilderFake.php @@ -0,0 +1,38 @@ +get()->first(); + + return data_get($record, 'elements.tmpUploadId'); + } + + /** + * @throws Throwable + */ + public function link(string $tmpUploadId, array $data = []): bool + { + $record = $this->get()->first(); + + return data_get($record, 'elements.success') === 'success'; + } + + /** + * @throws Throwable + */ + public function saveAndLink(string $fileContent, array $data = []): bool + { + $tmpUploadId = $this->save($fileContent); + + return $this->link($tmpUploadId, $data); + } +} diff --git a/src/Query/UploadBuilder.php b/src/Query/UploadBuilder.php new file mode 100644 index 0000000..a4b88b8 --- /dev/null +++ b/src/Query/UploadBuilder.php @@ -0,0 +1,115 @@ +onOfficeService->requestApi( + OnOfficeAction::Do, + OnOfficeResourceType::UploadFile, + parameters: [ + OnOfficeService::DATA => $fileContent, + ] + ); + + return $response->json('response.results.0.data.records.0.elements.tmpUploadId'); + } + + /** + * @throws OnOfficeException + */ + public function link(string $tmpUploadId, array $data = []): self + { + $data = array_replace($data, [ + 'tmpUploadId' => $tmpUploadId, + ]); + + $this->onOfficeService->requestApi( + OnOfficeAction::Do, + OnOfficeResourceType::UploadFile, + parameters: $data, + ); + + return $this; + } + + /** + * File content as base64-encoded binary data. + * Returns the temporary upload id. + * + * @throws OnOfficeException + */ + public function saveAndLink(string $fileContent, array $data = []): self + { + $tmpUploadId = $this->save($fileContent); + + return $this->link($tmpUploadId, $data); + } +} diff --git a/src/Repositories/FileRepository.php b/src/Repositories/FileRepository.php new file mode 100644 index 0000000..06d6975 --- /dev/null +++ b/src/Repositories/FileRepository.php @@ -0,0 +1,22 @@ +onOfficeService); + } +} diff --git a/tests/Query/UploadBuilderTest.php b/tests/Query/UploadBuilderTest.php new file mode 100644 index 0000000..fa15c73 --- /dev/null +++ b/tests/Query/UploadBuilderTest.php @@ -0,0 +1,69 @@ + UploadFileResponse::make(), + ]); + + $builder = new UploadBuilder(app(OnOfficeService::class)); + + $tmpUploadId = $builder->save(base64_encode('test')); + + expect($tmpUploadId)->toBe('a17ebec0-48f9-44cc-8629-f49ccc68f2d2'); + }); + + it('can link', function () { + Http::preventStrayRequests(); + + Http::fake([ + '*' => LinkDataResponse::make(), + ]); + + $builder = new UploadBuilder(app(OnOfficeService::class)); + + $builder->link('a17ebec0-48f9-44cc-8629-f49ccc68f2d2', [ + 'module' => 'estate', + 'file' => 'JPEG_example_JPG.jpg', + 'relatedRecordId' => 409, + ]); + + Http::assertSent(static function (Request $request) { + return data_get($request->data(), 'request.actions.0.parameters.tmpUploadId') === 'a17ebec0-48f9-44cc-8629-f49ccc68f2d2' + && data_get($request->data(), 'request.actions.0.parameters.relatedRecordId') === 409; + }); + }); + + it('can save and link', function () { + Http::preventStrayRequests(); + + Http::fake([ + '*' => Http::sequence([ + UploadFileResponse::make(), + LinkDataResponse::make(), + ]), + ]); + + $builder = new UploadBuilder(app(OnOfficeService::class)); + + $builder->saveAndLink(base64_encode('test'), [ + 'module' => 'estate', + 'file' => 'JPEG_example_JPG.jpg', + 'relatedRecordId' => 409, + ]); + + Http::assertSent(static function (Request $request) { + return data_get($request->data(), 'request.actions.0.parameters.tmpUploadId') === 'a17ebec0-48f9-44cc-8629-f49ccc68f2d2' + && data_get($request->data(), 'request.actions.0.parameters.relatedRecordId') === 409; + }); + }); +}); diff --git a/tests/Stubs/LinkDataResponse.php b/tests/Stubs/LinkDataResponse.php new file mode 100644 index 0000000..559b0ea --- /dev/null +++ b/tests/Stubs/LinkDataResponse.php @@ -0,0 +1,55 @@ + [ + 'code' => 200, + 'errorcode' => 0, + 'message' => 'OK', + ], + 'response' => [ + 'results' => [ + [ + 'actionid' => 'urn:onoffice-de-ns:smart:2.5:smartml:action:do', + 'resourceid' => '', + 'resourcetype' => 'uploadfile', + 'cacheable' => false, + 'identifier' => '', + 'data' => [ + 'meta' => [ + 'cntabsolute' => null, + ], + 'records' => [ + [ + 'id' => 0, + 'type' => '', + 'elements' => [ + 'filesize' => 85, + 'tmpUploadId' => $tmpUploadId, + ], + ], + ], + 'status' => [ + 'errorcode' => 0, + 'message' => 'OK', + ], + ], + ], + ], + ], + ], $data); + } +} diff --git a/tests/Stubs/UploadFileResponse.php b/tests/Stubs/UploadFileResponse.php new file mode 100644 index 0000000..ef7f1c2 --- /dev/null +++ b/tests/Stubs/UploadFileResponse.php @@ -0,0 +1,55 @@ + [ + 'code' => 200, + 'errorcode' => 0, + 'message' => 'OK', + ], + 'response' => [ + 'results' => [ + [ + 'actionid' => 'urn:onoffice-de-ns:smart:2.5:smartml:action:do', + 'resourceid' => '', + 'resourcetype' => 'uploadfile', + 'cacheable' => false, + 'identifier' => '', + 'data' => [ + 'meta' => [ + 'cntabsolute' => null, + ], + 'records' => [ + [ + 'id' => 0, + 'type' => '', + 'elements' => [ + 'filesize' => 85, + 'tmpUploadId' => $tmpUploadId, + ], + ], + ], + 'status' => [ + 'errorcode' => 0, + 'message' => 'OK', + ], + ], + ], + ], + ], + ], $data); + } +} diff --git a/tests/Testing/FileRepositoryFakeTest.php b/tests/Testing/FileRepositoryFakeTest.php new file mode 100644 index 0000000..2431843 --- /dev/null +++ b/tests/Testing/FileRepositoryFakeTest.php @@ -0,0 +1,109 @@ +toBeInstanceOf(FileRepositoryFake::class); +}); + +describe('save', function () { + it('can get a fake response', function () { + FileRepository::fake([ + [ + FileUploadFactory::make() + ->tmpUploadId('a17ebec0-48f9-44cc-8629-f49ccc68f2d2'), + ], + ]); + + $tmpUploadId = FileRepository::upload()->save(base64_encode('test')); + + expect($tmpUploadId)->toBe('a17ebec0-48f9-44cc-8629-f49ccc68f2d2'); + }); + + it('can get multiple fake responses', function () { + FileRepository::fake([ + [ + FileUploadFactory::make() + ->tmpUploadId('a17ebec0-48f9-44cc-8629-f49ccc68f2d2'), + ], + ], [ + [ + FileUploadFactory::make() + ->tmpUploadId('a17ebec0-48f9-44cc-8629-f49ccc68f2d3'), + ], + ]); + + $tmpUploadId = FileRepository::upload()->save(base64_encode('test')); + $tmpUploadId2 = FileRepository::upload()->save(base64_encode('test2')); + + expect($tmpUploadId)->toBe('a17ebec0-48f9-44cc-8629-f49ccc68f2d2') + ->and($tmpUploadId2)->toBe('a17ebec0-48f9-44cc-8629-f49ccc68f2d3'); + }); + + it('throws an exception when no more fake responses are available', function () { + FileRepository::fake([ + [ + FileUploadFactory::make() + ->tmpUploadId('a17ebec0-48f9-44cc-8629-f49ccc68f2d2'), + ], + ]); + + FileRepository::upload()->save(base64_encode('test')); + + expect(static fn () => FileRepository::upload()->save(base64_encode('test2'))) + ->toThrow('No more fake responses'); + }); +}); + +describe('link', function () { + it('can get a fake response', function () { + FileRepository::fake([ + [ + FileUploadFactory::make() + ->ok(), + ], + ]); + + $success = FileRepository::upload()->link('a17ebec0-48f9-44cc-8629-f49ccc68f2d2'); + + expect($success)->toBeTrue(); + }); + + it('can get multiple fake responses', function () { + FileRepository::fake([ + [ + FileUploadFactory::make() + ->ok(), + ], + ], [ + [ + FileUploadFactory::make() + ->error(), + ], + ]); + + $tmpUploadId = FileRepository::upload()->link('a17ebec0-48f9-44cc-8629-f49ccc68f2d2'); + $tmpUploadId2 = FileRepository::upload()->link('a17ebec0-48f9-44cc-8629-f49ccc68f2d3'); + + expect($tmpUploadId)->toBeTrue() + ->and($tmpUploadId2)->toBeFalse(); + }); + + it('throws an exception when no more fake responses are available', function () { + FileRepository::fake([ + [ + FileUploadFactory::make() + ->ok(), + ], + ]); + + FileRepository::upload()->link('a17ebec0-48f9-44cc-8629-f49ccc68f2d3'); + + expect(static fn () => FileRepository::upload()->link('a17ebec0-48f9-44cc-8629-f49ccc68f2d3')) + ->toThrow('No more fake responses'); + }); +});