Files
lucent-laravel/src/Record/RecordService.php
T

264 lines
7.4 KiB
PHP
Raw Normal View History

2023-10-02 23:10:49 +03:00
<?php
namespace Lucent\Record;
use Illuminate\Support\Str;
use Lucent\Account\AuthService;
use Lucent\Channel\ChannelService;
use Lucent\Edge\Edge;
use Lucent\Edge\EdgeCollection;
use Lucent\Edge\EdgeRepo;
use Lucent\File\FileService;
use Lucent\Id\Id;
use Lucent\LucentException;
use Lucent\Query\Query;
use Lucent\Revision\RevisionService;
use Lucent\Schema\FieldInterface;
use Lucent\Schema\Schema;
use Lucent\Schema\Validator\Validator;
use Lucent\Schema\Validator\ValidatorException;
readonly class RecordService
{
public function __construct(
private AuthService $authService,
private RevisionService $revisionService,
private ChannelService $channelService,
private Validator $recordValidator,
private Query $query,
private InputFormatter $inputFormatter
)
{
}
/**
* @throws LucentException
* @throws ValidatorException
*/
public
function create(
string $schemaName,
array $data,
?string $id = null,
array $file = [],
array $edges = [],
string $status = "draft",
string $uploadFromUrl = "",
): string
{
$schema = $this->channelService->channel->schemas->where("name", $schemaName)->first();
if (empty($schema)) {
throw new LucentException("The schema " . $schemaName . " does not exist");
}
$formattedData = $this->inputFormatter->fill($schemaName, new RecordData($data));
if (empty($formattedData["id"])) {
$formattedData["id"] = Id::new();
}
$uploadResult = FileService::create($schema, $uploadFromUrl, $file);
$uniqueEdges = collect($edges)
->map(fn($e) => (array)(new Edge(...$e)))
->map(function ($edge, $index) {
$edgeData = (array)(new Edge(...$edge));
$edgeData["rank"] = $index;
return $edgeData;
})
->unique(fn($e) => $e['field'] . $e['source'] . $e['target'] . $e['sourceSchema'])
->values()->toArray();
$uniqueEdgesCollection = EdgeCollection::fromArray($uniqueEdges);
if ($uploadResult->isDuplicate) {
EdgeRepo::update($uploadResult->duplicateId, $uniqueEdgesCollection);
return $uploadResult->duplicateId;
}
$record = new Record(
id: $id ?? Id::new(),
_sys: System::newRecord($schema, $this->authService->currentUserId(), $status),
data: $formattedData,
_file: $uploadResult->recordFile,
);
$errors = $this->recordValidator->check($schemaName, $record->data, $uniqueEdgesCollection);
if ($errors->isNotEmpty()) {
$this->recordValidator->throwException($errors);
}
RecordRepo::create($record);
EdgeRepo::update($record->id, $uniqueEdgesCollection);
$this->revisionService->create($record);
return $record->id;
}
/**
* @throws LucentException
* @throws ValidatorException
*/
public
function update(
string $id,
array $data,
string $status = "draft",
array $edges = [],
bool $updateEdges = false
): void
{
$queryResult = $this->query->filter(["id" => $id])->run();
$record = $queryResult->getQueryRecords()->records[0] ?? null;
if (empty($record)) {
throw new LucentException("Record id is missing");
}
$formattedData = $this->inputFormatter->fill($record->_sys->schema, new RecordData($data));
if ($updateEdges) {
$uniqueEdges = collect($edges)
->map(function ($edge, $index) {
$edgeData = (array)(new Edge(...$edge));
$edgeData["rank"] = $index;
return $edgeData;
})
->unique(fn($e) => $e['field'] . $e['source'] . $e['target'] . $e['sourceSchema'])
->values()->toArray();
$uniqueEdgesCollection = EdgeCollection::fromArray($uniqueEdges);
$errors = $this->recordValidator->check($record->_sys->schema, $formattedData, $uniqueEdgesCollection);
} else {
$errors = $this->recordValidator->check($record->_sys->schema, $formattedData, null);
}
$newRecord = new Record(
id: $record->id,
_sys: $record->_sys->update($this->authService->currentUserId(), $status),
data: $record->data->merge($formattedData),
_file: $record->_file,
);
if ($errors->isNotEmpty()) {
$this->recordValidator->throwException($errors);
}
RecordRepo::update($newRecord);
if ($updateEdges) {
EdgeRepo::update($newRecord->id, $uniqueEdgesCollection);
}
$this->revisionService->create($newRecord);
}
/**
*/
public
function changeStatusBulk(
string $status,
array $recordsIds,
): void
{
$recordsStatus = (new RecordStatus($status));
RecordRepo::updateStatusBulk($recordsStatus, $recordsIds);
}
/**
* @throws LucentException
* @throws ValidatorException
*/
public
function clone(
string $recordId,
): string
{
$queryResult = $this->query
->filter(["id" => $recordId])
->limit(1)
->childrenDepth(1)
->runWithCount();
$graph = $queryResult->getQueryRecords();
$record = $graph->records[0] ?? null;
if (empty($record)) {
throw new LucentException("Record id is missing");
}
$newRecordId = (string)Str::uuid();
$newEdgesData = $graph->edges
->filter(fn(Edge $edge) => $edge->source == $recordId)
->values()
->map(function (Edge $edge) use ($newRecordId) {
$edge->source = $newRecordId;
return $edge->toArray();
})->toArray();
$record->id = $newRecordId;
return $this->create(
schemaName: $record->_sys->schema,
data: $record->data->toArray(),
id: $record->id,
file: $record->_file?->toArray() ?? [],
edges: $newEdgesData,
status: "draft"
);
}
public function deleteMany(
array $recordsIds,
): void
{
RecordRepo::deleteMany($recordsIds);
}
/**
* @throws LucentException
* @throws ValidatorException
*/
public function rollback(
string $userId,
string $recordId,
int $version,
): void
{
$revision = $this->revisionService->getByRecordIdAndVersion($recordId, $version)->get();
$this->update(
userId: $userId,
id: $revision->recordId,
data: $revision->data->toArray(),
status: $revision->_sys->status,
updateEdges: false
);
}
public function createEmpty(
Schema $schema,
string $userId,
): Record
{
$defaultValues = $schema->fields->reduce(function ($carry, FieldInterface $f) {
$carry[$f->name] = $f->default ?? null;
return $carry;
}, []);
$formattedData = $this->inputFormatter->fill($schema->name, new RecordData($defaultValues));
return new Record(
id: Id::new(),
_sys: System::newRecord($schema, $userId),
data: $formattedData,
_file: null,
);
}
}