From 168923d3da50949733ab32b4e9f3a7c9677fed5a Mon Sep 17 00:00:00 2001 From: Victor Gonzalex Date: Tue, 17 Mar 2020 16:31:17 -0400 Subject: [PATCH] wip getting the Storage driver to work for remote json files --- src/Updater.php | 64 ++++++++++--- tests/Unit/UpdaterRemoteTest.php | 157 +++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+), 14 deletions(-) create mode 100644 tests/Unit/UpdaterRemoteTest.php diff --git a/src/Updater.php b/src/Updater.php index 15a81f9..59c8893 100644 --- a/src/Updater.php +++ b/src/Updater.php @@ -2,6 +2,7 @@ namespace nullthoughts\LaravelDataSync; +use Illuminate\Support\Facades\Storage; use nullthoughts\LaravelDataSync\Exceptions\ErrorUpdatingModelException; use nullthoughts\LaravelDataSync\Exceptions\FileDirectoryNotFoundException; use nullthoughts\LaravelDataSync\Exceptions\NoCriteriaException; @@ -13,18 +14,44 @@ use stdClass; class Updater { + /** + * @var string + */ + private $directory; + + /** + * @var \Illuminate\Support\Collection + */ + private $files; + + /** + * @var bool + */ + private $remote; + + /** + * @var string + */ + private $disk; + /** * Get files in sync directory. * - * @param string|null $path - * @param string|null $model + * @param string|null $path + * @param string|null $model + * + * @param bool $remote + * @param string $disk * * @throws \nullthoughts\LaravelDataSync\Exceptions\FileDirectoryNotFoundException */ - public function __construct($path = null, $model = null) + public function __construct($path = null, $model = null, $remote = false, $disk = 's3') { - $directory = $this->getDirectory($path); - $this->files = $this->getFiles($directory, $model); + $this->remote = $remote; + $this->disk = $disk; + + $this->directory = $this->getDirectory($path); + $this->files = $this->getFiles($this->directory, $model); } /** @@ -50,11 +77,11 @@ class Updater /** * Parse each record for criteria/values and update/create model. * - * @param string $file - * - * @throws \nullthoughts\LaravelDataSync\Exceptions\NoRecordsInvalidJSONException + * @param string $file * * @return \Illuminate\Support\Collection + * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + * @throws \nullthoughts\LaravelDataSync\Exceptions\NoRecordsInvalidJSONException */ protected function syncModel(string $file) { @@ -89,7 +116,7 @@ class Updater { $directory = $path ?? config('data-sync.path', base_path('sync')); - if (!file_exists($directory)) { + if (!file_exists($directory) && !$this->remote) { throw new FileDirectoryNotFoundException(); } @@ -110,10 +137,17 @@ class Updater return Collection::wrap($directory.'/'.$model.'.json'); } - return collect(File::files($directory)) + $files = ($this->remote) ? Storage::disk($this->disk)->files($directory) : File::files($directory); + + return collect($files) ->filter(function ($file) { return pathinfo($file, PATHINFO_EXTENSION) == 'json'; })->map(function ($path) { + + if (is_string($path)) { + return $path; + } + return $path->getPathname(); }); } @@ -204,15 +238,17 @@ class Updater /** * Parses JSON from file and returns collection. * - * @param string $file - * - * @throws \nullthoughts\LaravelDataSync\Exceptions\NoRecordsInvalidJSONException + * @param string $file * * @return \Illuminate\Support\Collection + * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + * @throws \nullthoughts\LaravelDataSync\Exceptions\NoRecordsInvalidJSONException */ protected function getRecords(string $file) { - $records = collect(json_decode(File::get($file))); + $fetchedFile = ($this->remote) ? Storage::disk($this->disk)->get($file) : File::get($file); + + $records = collect(json_decode($fetchedFile)); if ($records->isEmpty()) { throw new NoRecordsInvalidJSONException($file); diff --git a/tests/Unit/UpdaterRemoteTest.php b/tests/Unit/UpdaterRemoteTest.php new file mode 100644 index 0000000..fb50d86 --- /dev/null +++ b/tests/Unit/UpdaterRemoteTest.php @@ -0,0 +1,157 @@ +put('test-data/roles.json', File::get(__DIR__.'/../test-data/roles.json')); + foreach (File::directories(__DIR__.'/../test-data/') as $directory) { + $files = File::files($directory); + + foreach ($files as $file) { + Storage::disk('s3')->put('test-data/'.basename($directory).'/'.$file->getRelativePathname(), File::get($file->getPathname())); + } + } + } + + /** @test @group current */ + public function it_adds_roles_to_the_database() + { + $updater = new UpdaterFake('/test-data', 'roles', true, 's3'); + + $updater->run(); + + $this->assertDatabaseHas('roles', ['slug' => 'update-student-records']); + $this->assertDatabaseHas('roles', ['slug' => 'borrow-ferrari']); + $this->assertDatabaseHas('roles', ['slug' => 'destroy-ferrari']); + } + + /** @test */ + public function it_can_default_to_configuration() + { + config()->set('data-sync.path', 'test-data'); + + $updater = new UpdaterFake(null, null, true, 's3'); + + $updater->run(); + + $this->assertDatabaseHas('roles', ['slug' => 'update-student-records']); + $this->assertDatabaseHas('roles', ['slug' => 'borrow-ferrari']); + $this->assertDatabaseHas('roles', ['slug' => 'destroy-ferrari']); + } + + /** @test */ + public function it_can_update_an_existing_record() + { + config()->set('data-sync.path', 'test-data'); + (new UpdaterFake(null, null, true, 's3'))->run(); + + config()->set('data-sync.path', 'test-data/valid'); + (new UpdaterFake(null, null, true, 's3'))->run(); + + $this->assertDatabaseHas('roles', ['category' => 'changed']); + $this->assertDatabaseHas('roles', ['category' => 'changed']); + $this->assertDatabaseHas('roles', ['category' => 'changed']); + } + + /** @test */ + public function it_can_update_the_relationship() + { + $supervisor = Supervisor::create([ + 'name' => 'CEO', + ]); + + config()->set('data-sync.path', 'test-data/relationship'); + (new UpdaterFake(null, null, true, 's3'))->run(); + + $this->assertEquals($supervisor->id, Roles::first()->supervisor_id); + $this->assertTrue($supervisor->is(Roles::first()->supervisor)); + } + + /** @test */ + public function exception_is_thrown_if_the_directory_does_not_exists() + { + try { + new UpdaterFake(null, null, true, 's3'); + + $this->fail('exception was thrown'); + } catch (Exception $e) { + $this->assertEquals('Specified sync file directory does not exist', $e->getMessage()); + } + } +// +// /** @test */ +// public function invalid_json_throws_an_exception() +// { +// try { +// $updater = new UpdaterFake(__DIR__.'/../test-data/invalid-json'); +// $updater->run(); +// +// $this->fail('exception was thrown'); +// } catch (Exception $e) { +// $this->assertStringContainsString('No records or invalid JSON for', $e->getMessage()); +// } +// } +// +// /** @test */ +// public function the_json_must_contain_a_key_with_an_underscore() +// { +// try { +// $updater = new UpdaterFake(__DIR__.'/../test-data/no-criteria'); +// $updater->run(); +// +// $this->fail('exception was thrown'); +// } catch (Exception $e) { +// $this->assertEquals('No criteria/attributes detected', $e->getMessage()); +// } +// } +// +// /** @test */ +// public function order_of_imports_can_be_defined_in_config() +// { +// config()->set('data-sync.order', [ +// 'Supervisor', +// 'Roles', +// ]); +// +// $updater = new UpdaterFake(__DIR__.'/../test-data/ordered'); +// $updater->run(); +// +// $this->assertDatabaseHas('roles', ['slug' => 'update-student-records']); +// $this->assertDatabaseHas('supervisors', ['name' => 'CEO']); +// } +// +// /** @test */ +// public function exception_is_thrown_if_imports_are_in_incorrect_order() +// { +// config()->set('data-sync.order', [ +// 'Roles', +// 'Supervisor', +// ]); +// +// $this->expectException(ErrorUpdatingModelException::class); +// +// $updater = new UpdaterFake(__DIR__.'/../test-data/ordered'); +// $updater->run(); +// } +// +// /** @test */ +// public function it_ignores_non_json_files() +// { +// $updater = new UpdaterFake(__DIR__.'/../test-data/not-json'); +// $updater->run(); +// +// $this->assertDatabaseMissing('roles', ['slug' => 'update-student-records']); +// } +}