Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"email": "jani@marketdistinctly.com"
}
],
"require": {},
"require": {
"ext-json": "*"
},
"require-dev": {
"orchestra/testbench": "^3.7"
},
Expand Down
10 changes: 10 additions & 0 deletions src/Exceptions/FileDirectoryNotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace distinctm\LaravelDataSync\Exceptions;

use Exception;

class FileDirectoryNotFoundException extends Exception
{
protected $message = 'Specified sync file directory does not exist';
}
10 changes: 10 additions & 0 deletions src/Exceptions/NoCriteriaException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace distinctm\LaravelDataSync\Exceptions;

use Exception;

class NoCriteriaException extends Exception
{
protected $message = 'No criteria/attributes detected';
}
16 changes: 16 additions & 0 deletions src/Exceptions/NoRecordsInvalidJSONException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace distinctm\LaravelDataSync\Exceptions;

use Exception;
use Throwable;

class NoRecordsInvalidJSONException extends Exception
{
public function __construct(string $message = "", int $code = 0, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);

$this->message = "No records or invalid JSON for {$message} model.";
}
}
77 changes: 48 additions & 29 deletions src/Updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@

namespace distinctm\LaravelDataSync;

use distinctm\LaravelDataSync\Exceptions\FileDirectoryNotFoundException;
use distinctm\LaravelDataSync\Exceptions\NoCriteriaException;
use distinctm\LaravelDataSync\Exceptions\NoRecordsInvalidJSONException;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Schema;

class Updater
{

/**
* Get files in sync directory
*
* @param string|null $path
* @param string|null $model
*
* @throws \distinctm\LaravelDataSync\Exceptions\FileDirectoryNotFoundException
*/
public function __construct($path = null, $model = null)
{
Expand All @@ -22,11 +27,11 @@ public function __construct($path = null, $model = null)
/**
* Execute syncModel for each file
*
* @return void
* @return mixed
*/
public function run()
{
$records = collect($this->files)->map(function($file) {
$records = collect($this->files)->map(function ($file) {
return $this->syncModel($file);
});

Expand All @@ -37,14 +42,16 @@ public function run()
* Parse each record for criteria/values and update/create model
*
* @param string $file
*
* @return \Illuminate\Support\Collection
* @throws \distinctm\LaravelDataSync\Exceptions\NoRecordsInvalidJSONException
*/
protected function syncModel(string $file)
{
$model = $this->getModel($file);
$records = $this->getRecords($file);

$records->each(function($record) use ($model) {
$records->each(function ($record) use ($model) {
$criteria = $this->resolveObjects(
$this->getCriteria($record)
);
Expand All @@ -62,15 +69,17 @@ protected function syncModel(string $file)
/**
* Get directory path for sync files
*
* @param object $record
* @param $path
*
* @return array
* @throws \distinctm\LaravelDataSync\Exceptions\FileDirectoryNotFoundException
*/
protected function getDirectory($path)
{
$directory = $path ?? config('data-sync.path', base_path('sync'));

if(!file_exists($directory)) {
throw new \Exception("Specified sync file directory does not exist");
if (!file_exists($directory)) {
throw new FileDirectoryNotFoundException;
}

return $directory;
Expand All @@ -80,16 +89,17 @@ protected function getDirectory($path)
* Get list of files in directory
*
* @param string $directory
* @param string\null $model
* @return array
* @param string|null $model
*
* @return array|string
*/
protected function getFiles(string $directory, $model)
{
if($model) {
if ($model) {
return $directory . '/' . $model . '.json';
}

return collect(File::files($directory))->map(function($path) {
return collect(File::files($directory))->map(function ($path) {
return $path->getPathname();
})->toArray();
}
Expand All @@ -98,19 +108,21 @@ protected function getFiles(string $directory, $model)
* Filter record criteria
*
* @param object $record
*
* @return array
* @throws \distinctm\LaravelDataSync\Exceptions\NoCriteriaException
*/
protected function getCriteria(object $record)
{
$criteria = collect($record)->filter(function($value, $key) {
$criteria = collect($record)->filter(function ($value, $key) {
return $this->isCriteria($key);
});

if($criteria->count() == 0) {
throw new \Exception("No criteria/attributes detected");
if ($criteria->count() == 0) {
throw new NoCriteriaException;
}

return $criteria->mapWithKeys(function($value, $key) {
return $criteria->mapWithKeys(function ($value, $key) {
return [substr($key, 1) => $value];
});
}
Expand All @@ -119,16 +131,17 @@ protected function getCriteria(object $record)
* Filter record values
*
* @param object $record
*
* @return array
*/
protected function getValues(object $record)
{
return collect($record)->reject(function($value, $key) {
if($this->isCriteria($key)) {
return collect($record)->reject(function ($value, $key) {
if ($this->isCriteria($key)) {
return true;
}

if(empty($value)) {
if (empty($value)) {
return true;
}

Expand All @@ -139,7 +152,8 @@ protected function getValues(object $record)
/**
* Returns model name for file
*
* @param string $file
* @param string $name
*
* @return string
*/
protected function getModel(string $name)
Expand All @@ -151,14 +165,16 @@ protected function getModel(string $name)
* Parses JSON from file and returns collection
*
* @param string $file
*
* @return \Illuminate\Support\Collection
* @throws \distinctm\LaravelDataSync\Exceptions\NoRecordsInvalidJSONException
*/
protected function getRecords(string $file)
{
$records = collect(json_decode(File::get($file)));

if($records->isEmpty()) {
throw new \Exception("No records or invalid JSON for {$file} model");
if ($records->isEmpty()) {
throw new NoRecordsInvalidJSONException($file);
}

return $records;
Expand All @@ -168,6 +184,7 @@ protected function getRecords(string $file)
* Check if column is criteria for a condition match
*
* @param string $key
*
* @return boolean
*/
protected function isCriteria($key)
Expand All @@ -180,15 +197,16 @@ protected function isCriteria($key)
*
* @param string $key
* @param object $values
*
* @return array
*/
protected function resolveId(string $key, object $values)
{
$model = $this->getModel($key);

$values = collect($values)->mapWithKeys(function($value, $column) {

if(is_object($value)) {
$values = collect($values)->mapWithKeys(function ($value, $column) {

if (is_object($value)) {
return $this->resolveId($column, $value);
}

Expand All @@ -201,13 +219,14 @@ protected function resolveId(string $key, object $values)
/**
* Detect nested objects and resolve them
*
* @param \Illuminate\Support\Collection $records
* @param \Illuminate\Support\Collection $record
*
* @return array
*/
protected function resolveObjects(\Illuminate\Support\Collection $record)
protected function resolveObjects(Collection $record)
{
return $record->mapWithKeys(function($value, $key) {
if(is_object($value)) {
return $record->mapWithKeys(function ($value, $key) {
if (is_object($value)) {
return $this->resolveId($key, $value);
}

Expand Down