Files
laravel-data-sync/src/Updater.php
distinctm 82185c0e80 Switches to File facade, resolves objects for both criteria and values
- File facade allows access to directories outside of filesystem disks
2019-01-23 13:25:45 -05:00

212 lines
4.8 KiB
PHP

<?php
namespace distinctm\LaravelDataSync;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Schema;
class Updater
{
/**
* Get files in sync directory
*
* @param string|null $path
*/
public function __construct($path = null)
{
$this->files = $this->getFiles(
$this->getDirectory($path)
);
}
/**
* Execute syncModel for each file
*
* @return void
*/
public function run()
{
$records = collect($this->files)->map(function($file) {
return $this->syncModel($file);
});
return $records;
}
/**
* Parse each record for criteria/values and update/create model
*
* @param string $file
* @return \Illuminate\Support\Collection
*/
protected function syncModel(string $file)
{
$model = $this->getModel($file);
$records = $this->getRecords($file);
$records->each(function($record) use ($model) {
$record = $this->resolveObjects($record);
$criteria = $this->getCriteria($record);
$values = $this->getValues($record);
$model::updateOrCreate($criteria, $values);
});
return $records;
}
/**
* Get directory path for sync files
*
* @param object $record
* @return array
*/
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");
}
return $directory;
}
/**
* Get list of files in directory
*
* @param string $directory
* @return void
*/
protected function getFiles(string $directory)
{
return collect(File::files($directory))->map(function($path) {
return $path->getPathname();
})->toArray();
}
/**
* Filter record criteria
*
* @param \Illuminate\Support\Collection $record
* @return array
*/
protected function getCriteria(\Illuminate\Support\Collection $record)
{
$criteria = $record->filter(function($value, $key) {
return $this->isCriteria($key);
});
if($criteria->count() == 0) {
throw new \Exception("No criteria/attributes detected");
}
return $criteria->mapWithKeys(function($value, $key) {
return [substr($key, 1) => $value];
})->toArray();
}
/**
* Filter record values
*
* @param \Illuminate\Support\Collection $record
* @return array
*/
protected function getValues(\Illuminate\Support\Collection $record)
{
return $record->reject(function($value, $key) {
if($this->isCriteria($key)) {
return true;
}
if(empty($value)) {
return true;
}
return false;
})->toArray();
}
/**
* Returns model name for file
*
* @param string $file
* @return string
*/
protected function getModel(string $name)
{
return '\\App\\' . pathinfo($name, PATHINFO_FILENAME);
}
/**
* Parses JSON from file and returns collection
*
* @param string $file
* @return \Illuminate\Support\Collection
*/
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");
}
return $records;
}
/**
* Check if column is criteria for a condition match
*
* @param string $key
* @return boolean
*/
protected function isCriteria($key)
{
return substr($key, 0, 1) == '_';
}
/**
* Return ID for nested key-value pairs
*
* @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)) {
return $this->resolveId($column, $value);
}
return [$column => $value];
})->toArray();
return [$key . '_id' => $model::where($values)->first()->id];
}
/**
* Detect nested objects and resolve them
*
* @param object $records
* @return \Illuminate\Support\Collection
*/
protected function resolveObjects(object $record)
{
return collect($record)->mapWithKeys(function($value, $key) {
if(is_object($value)) {
return $this->resolveId($key, $value);
}
return [$key => $value];
});
}
}