create document flow
This commit is contained in:
@@ -48,7 +48,6 @@
|
|||||||
schema: record.schema,
|
schema: record.schema,
|
||||||
status: record.status,
|
status: record.status,
|
||||||
_sys: JSON.parse(JSON.stringify(record._sys)),
|
_sys: JSON.parse(JSON.stringify(record._sys)),
|
||||||
_file: JSON.parse(JSON.stringify(record._file)),
|
|
||||||
edges: JSON.parse(JSON.stringify(graph.edges)),
|
edges: JSON.parse(JSON.stringify(graph.edges)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -82,7 +81,6 @@
|
|||||||
schema: record.schema,
|
schema: record.schema,
|
||||||
status: record.status,
|
status: record.status,
|
||||||
_sys: record._sys,
|
_sys: record._sys,
|
||||||
_file: record._file,
|
|
||||||
edges: graph.edges,
|
edges: graph.edges,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ final class EdgeCollection extends Collection
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Edge ...$array
|
Edge ...$array
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
parent::__construct($array);
|
parent::__construct($array);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,9 +27,16 @@ final class EdgeCollection extends Collection
|
|||||||
|
|
||||||
public static function fromArray(array $data): EdgeCollection
|
public static function fromArray(array $data): EdgeCollection
|
||||||
{
|
{
|
||||||
$edges = array_map([Edge::class, 'fromArray'], $data);
|
$edges = collect($data)
|
||||||
|
->map([Edge::class, 'fromArray'])
|
||||||
|
->unique(fn(Edge $e) => $e->field . $e->source . $e->target);
|
||||||
return new EdgeCollection(...$edges);
|
return new EdgeCollection(...$edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function fromJson(string $data): EdgeCollection
|
||||||
|
{
|
||||||
|
return self::fromArray(json_decode($data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php namespace Lucent\Edge;
|
<?php namespace Lucent\Edge;
|
||||||
|
|
||||||
use Lucent\LucentException;
|
use Lucent\LucentException;
|
||||||
|
use PhpOption\Option;
|
||||||
|
|
||||||
class EdgeService
|
class EdgeService
|
||||||
{
|
{
|
||||||
@@ -35,9 +36,17 @@ class EdgeService
|
|||||||
return $edge;
|
return $edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(string $from, EdgeCollection $edges): void
|
/**
|
||||||
|
* @param string $from
|
||||||
|
* @param Option<EdgeCollection> $edges
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function update(string $from, Option $edges): void
|
||||||
{
|
{
|
||||||
$this->edgeRepo->update($from, $edges);
|
if($edges->isEmpty()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->edgeRepo->update($from, $edges->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findAll(): EdgeCollection
|
public function findAll(): EdgeCollection
|
||||||
|
|||||||
@@ -13,11 +13,16 @@ use Lucent\Query\Query;
|
|||||||
use Lucent\Record\Manager;
|
use Lucent\Record\Manager;
|
||||||
use Lucent\Record\QueryRecord;
|
use Lucent\Record\QueryRecord;
|
||||||
use Lucent\Record\RecordService;
|
use Lucent\Record\RecordService;
|
||||||
|
use Lucent\Record\Status;
|
||||||
use Lucent\Schema\Schema\System;
|
use Lucent\Schema\Schema\System;
|
||||||
use Lucent\Schema\Validator\ValidatorException;
|
use Lucent\Schema\Validator\ValidatorException;
|
||||||
|
use Lucent\Support\Result\Result;
|
||||||
|
use Lucent\Support\Result\Success;
|
||||||
use Lucent\Svelte\Svelte;
|
use Lucent\Svelte\Svelte;
|
||||||
|
use PhpOption\Option;
|
||||||
use function Lucent\Response\fail;
|
use function Lucent\Response\fail;
|
||||||
use function Lucent\Response\ok;
|
use function Lucent\Response\ok;
|
||||||
|
use function Lucent\Response\result;
|
||||||
|
|
||||||
class RecordController extends Controller
|
class RecordController extends Controller
|
||||||
{
|
{
|
||||||
@@ -59,8 +64,6 @@ class RecordController extends Controller
|
|||||||
|
|
||||||
$skip = data_get($urlParams, "skip") ?? 0;
|
$skip = data_get($urlParams, "skip") ?? 0;
|
||||||
$limit = 30;
|
$limit = 30;
|
||||||
$records = [];
|
|
||||||
$graphArray = null;
|
|
||||||
$graph = $this->query
|
$graph = $this->query
|
||||||
->filter($arguments)
|
->filter($arguments)
|
||||||
->limit($limit)
|
->limit($limit)
|
||||||
@@ -72,15 +75,11 @@ class RecordController extends Controller
|
|||||||
->parentsDepth(0)
|
->parentsDepth(0)
|
||||||
->runWithCount();
|
->runWithCount();
|
||||||
|
|
||||||
|
|
||||||
$records = $graph->getRootRecords()->toArray();
|
|
||||||
|
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
"schemas" => $this->channelService->channel->schemas,
|
"schemas" => $this->channelService->channel->schemas,
|
||||||
"schema" => $schema,
|
"schema" => $schema,
|
||||||
"users" => $users,
|
"users" => $users,
|
||||||
"records" => $records,
|
"records" => $graph->rootRecords,
|
||||||
"graph" => toArray($graph),
|
"graph" => toArray($graph),
|
||||||
"systemFields" => array_values(System::list()),
|
"systemFields" => array_values(System::list()),
|
||||||
"operators" => array_values(Operator::list()),
|
"operators" => array_values(Operator::list()),
|
||||||
@@ -161,15 +160,14 @@ class RecordController extends Controller
|
|||||||
|
|
||||||
$schema = $this->channelService->channel->schemas->where("name", $request->input("schema"))->first();
|
$schema = $this->channelService->channel->schemas->where("name", $request->input("schema"))->first();
|
||||||
$recordHistory = $this->recordManager->fromSession($request->session())->getRecords();
|
$recordHistory = $this->recordManager->fromSession($request->session())->getRecords();
|
||||||
$record = $this->recordService->createEmpty($schema, $this->authService->currentUserId());
|
$record = $this->recordService->createEmpty($schema);
|
||||||
$queryRecord = QueryRecord::fromRecord($record);
|
|
||||||
return $this->svelte->render(
|
return $this->svelte->render(
|
||||||
layout: "channel",
|
layout: "channel",
|
||||||
view: "recordEdit",
|
view: "recordEdit",
|
||||||
title: "New Record",
|
title: "New Record",
|
||||||
data: [
|
data: [
|
||||||
"schema" => $schema,
|
"schema" => $schema,
|
||||||
"record" => $queryRecord,
|
"record" => $record,
|
||||||
"recordHistory" => $recordHistory,
|
"recordHistory" => $recordHistory,
|
||||||
"isCreateMode" => true,
|
"isCreateMode" => true,
|
||||||
"isWritable" => in_array($record->schema, $this->accountService->currentWritableSchemas())
|
"isWritable" => in_array($record->schema, $this->accountService->currentWritableSchemas())
|
||||||
@@ -222,7 +220,7 @@ class RecordController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$record = $graph->records->first();
|
$record = $graph->rootRecords->first();
|
||||||
|
|
||||||
if (!in_array($record->schema, $this->accountService->currentReadableSchemas())) {
|
if (!in_array($record->schema, $this->accountService->currentReadableSchemas())) {
|
||||||
return $this->svelte->render(
|
return $this->svelte->render(
|
||||||
@@ -312,27 +310,26 @@ class RecordController extends Controller
|
|||||||
public function save(Request $request)
|
public function save(Request $request)
|
||||||
{
|
{
|
||||||
$recordId = $request->input("record.id");
|
$recordId = $request->input("record.id");
|
||||||
try {
|
|
||||||
|
|
||||||
if ($request->input("isCreateMode")) {
|
$res = match ($request->input("isCreateMode")) {
|
||||||
$recordId = $this->recordService->create(
|
true => $this->recordService->createDocument(
|
||||||
schemaName: $request->input("record.schema"),
|
schemaName: $request->input("record.schema"),
|
||||||
data: $request->input("record.data"),
|
data: $request->input("record.data"),
|
||||||
id: $recordId ?? "",
|
id: Option::fromValue($recordId),
|
||||||
file: $request->input("record._file") ?? [],
|
edges: Option::fromValue($request->input("edges")),
|
||||||
edges: $request->input("edges") ?? [],
|
status: Status::from($request->input("record.status")),
|
||||||
status: $request->input("record.status"),
|
),
|
||||||
uploadFromUrl: ""
|
default => $this->recordService->update(
|
||||||
);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
$this->recordService->update(
|
|
||||||
id: $request->input("record.id"),
|
id: $request->input("record.id"),
|
||||||
data: $request->input("record.data"),
|
data: $request->input("record.data"),
|
||||||
status: $request->input("record.status"),
|
status: $request->input("record.status"),
|
||||||
edges: $request->input("edges"),
|
edges: $request->input("edges"),
|
||||||
updateEdges: true,
|
updateEdges: true,
|
||||||
);
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($res->error()->isDefined()) {
|
||||||
|
return result($res);
|
||||||
}
|
}
|
||||||
|
|
||||||
$newGraph = $this->query
|
$newGraph = $this->query
|
||||||
@@ -342,12 +339,8 @@ class RecordController extends Controller
|
|||||||
->parentsDepth(1)
|
->parentsDepth(1)
|
||||||
->run();
|
->run();
|
||||||
|
|
||||||
} catch (ValidatorException $th) {
|
|
||||||
return fail($th->getValidatorErrors());
|
return result(Success::create(toArray($newGraph)));
|
||||||
} catch (LucentException $th) {
|
|
||||||
return fail($th);
|
|
||||||
}
|
|
||||||
return ok(toArray($newGraph));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,17 @@ use Lucent\File\FileService;
|
|||||||
use Lucent\LucentException;
|
use Lucent\LucentException;
|
||||||
use Lucent\Query\Query;
|
use Lucent\Query\Query;
|
||||||
use Lucent\Revision\RevisionService;
|
use Lucent\Revision\RevisionService;
|
||||||
|
use Lucent\Schema\Field\FieldDataInterface;
|
||||||
use Lucent\Schema\Field\FieldInterface;
|
use Lucent\Schema\Field\FieldInterface;
|
||||||
use Lucent\Schema\Schema\Schema;
|
use Lucent\Schema\Schema\Schema;
|
||||||
use Lucent\Schema\Validator\Validator;
|
use Lucent\Schema\Validator\Validator;
|
||||||
|
use Lucent\Schema\Validator\ValidatorError;
|
||||||
use Lucent\Schema\Validator\ValidatorException;
|
use Lucent\Schema\Validator\ValidatorException;
|
||||||
|
use Lucent\Support\Collection;
|
||||||
|
use Lucent\Support\Result\Error;
|
||||||
|
use Lucent\Support\Result\Result;
|
||||||
|
use Lucent\Support\Result\Success;
|
||||||
|
use PhpOption\Option;
|
||||||
|
|
||||||
readonly class RecordService
|
readonly class RecordService
|
||||||
{
|
{
|
||||||
@@ -34,6 +41,71 @@ readonly class RecordService
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $schemaName
|
||||||
|
* @param array $data
|
||||||
|
* @param Option<string> $id
|
||||||
|
* @param Option<array> $edges
|
||||||
|
* @param Status $status
|
||||||
|
* @return Result<string|Collection<ValidatorError>>
|
||||||
|
*/
|
||||||
|
public function createDocument(
|
||||||
|
string $schemaName,
|
||||||
|
array $data,
|
||||||
|
Option $id,
|
||||||
|
Option $edges,
|
||||||
|
Status $status = Status::DRAFT,
|
||||||
|
): Result
|
||||||
|
{
|
||||||
|
$schema = $this->channelService->getSchema($schemaName)->get();
|
||||||
|
|
||||||
|
$formattedData = $this->inputFormatter->fill($schemaName, new RecordData($data));
|
||||||
|
$newRecordId = $id->getOrElse(Id::new());
|
||||||
|
$uniqueEdges = $this->getUniqueEdges($edges, $newRecordId, $schemaName);
|
||||||
|
|
||||||
|
$record = new Document(
|
||||||
|
id: $newRecordId,
|
||||||
|
schema: $schema->name,
|
||||||
|
status: $status,
|
||||||
|
_sys: System::newRecord($this->authService->currentUserId()),
|
||||||
|
data: $formattedData,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($status === Status::PUBLISHED) {
|
||||||
|
$errors = $this->recordValidator->check($schemaName, $record->data);
|
||||||
|
if ($errors->isNotEmpty()) {
|
||||||
|
return Error::create($errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordRepo::create($record);
|
||||||
|
$this->edgeService->update($record->id, $uniqueEdges);
|
||||||
|
$this->revisionService->create($record, $uniqueEdges);
|
||||||
|
return Success::create($record->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Option<array> $edges
|
||||||
|
* @param string $recordId
|
||||||
|
* @param string $schemaName
|
||||||
|
* @return Option<EdgeCollection>
|
||||||
|
*/
|
||||||
|
private function getUniqueEdges(Option $edges, string $recordId, string $schemaName): Option
|
||||||
|
{
|
||||||
|
if($edges->isEmpty()){
|
||||||
|
return none();
|
||||||
|
}
|
||||||
|
|
||||||
|
$uniqueEdges = collect($edges)
|
||||||
|
->map(function ($edge, $index) use ($recordId, $schemaName) {
|
||||||
|
$edge['source'] = $recordId;
|
||||||
|
$edge['sourceSchema'] = $schemaName;
|
||||||
|
$edge["rank"] = $index;
|
||||||
|
return $edge;
|
||||||
|
});
|
||||||
|
return some(EdgeCollection::fromArray($uniqueEdges->toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws LucentException
|
* @throws LucentException
|
||||||
* @throws ValidatorException
|
* @throws ValidatorException
|
||||||
@@ -102,7 +174,8 @@ readonly class RecordService
|
|||||||
* @throws LucentException
|
* @throws LucentException
|
||||||
* @throws ValidatorException
|
* @throws ValidatorException
|
||||||
*/
|
*/
|
||||||
public function update(
|
public
|
||||||
|
function update(
|
||||||
string $id,
|
string $id,
|
||||||
array $data,
|
array $data,
|
||||||
string $status = "draft",
|
string $status = "draft",
|
||||||
@@ -162,7 +235,8 @@ readonly class RecordService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
public function changeStatusBulk(
|
public
|
||||||
|
function changeStatusBulk(
|
||||||
string $status,
|
string $status,
|
||||||
array $recordsIds,
|
array $recordsIds,
|
||||||
): void
|
): void
|
||||||
@@ -253,21 +327,18 @@ readonly class RecordService
|
|||||||
Schema $schema,
|
Schema $schema,
|
||||||
): Record
|
): Record
|
||||||
{
|
{
|
||||||
|
$defaultValues = $schema->getDataFields()->reduce(function ($carry, FieldDataInterface $f) {
|
||||||
$defaultValues = $schema->fields->reduce(function ($carry, FieldInterface $f) {
|
|
||||||
$carry[$f->name] = $f->default ?? null;
|
$carry[$f->name] = $f->default ?? null;
|
||||||
return $carry;
|
return $carry;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
$formattedData = $this->inputFormatter->fill($schema->name, new RecordData($defaultValues));
|
$formattedData = $this->inputFormatter->fill($schema->name, new RecordData($defaultValues));
|
||||||
|
return new Document(
|
||||||
return new Record(
|
|
||||||
id: Id::new(),
|
id: Id::new(),
|
||||||
schema: $schema->name,
|
schema: $schema->name,
|
||||||
status: Status::DRAFT,
|
status: Status::DRAFT,
|
||||||
_sys: System::newRecord($this->authService->currentUserId()),
|
_sys: System::newRecord($this->authService->currentUserId()),
|
||||||
data: $formattedData,
|
data: $formattedData,
|
||||||
_file: null,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,22 @@ namespace Lucent\Response;
|
|||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Lucent\LucentException;
|
use Lucent\LucentException;
|
||||||
|
use Lucent\Support\Result\Error;
|
||||||
|
use Lucent\Support\Result\Result;
|
||||||
|
use Lucent\Support\Result\Success;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
|
|
||||||
|
function result(Result $result, ?int $successCode = null, ?int $errorCode = null): Response
|
||||||
|
{
|
||||||
|
return match (get_class($result)) {
|
||||||
|
Success::class => response($result->success()->get(), $successCode ?? 200),
|
||||||
|
Error::class => response([
|
||||||
|
"error" => $result->error()->get()
|
||||||
|
], $errorCode ?? 400)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function fail(Throwable|string|array $error, int $code = 400): Response
|
function fail(Throwable|string|array $error, int $code = 400): Response
|
||||||
{
|
{
|
||||||
$message = "Something went wrong";
|
$message = "Something went wrong";
|
||||||
|
|||||||
@@ -8,25 +8,39 @@ use Lucent\Record\FileInfo;
|
|||||||
use Lucent\Record\Record;
|
use Lucent\Record\Record;
|
||||||
use Lucent\Record\RecordData;
|
use Lucent\Record\RecordData;
|
||||||
use Lucent\Record\System;
|
use Lucent\Record\System;
|
||||||
|
use PhpOption\Option;
|
||||||
|
|
||||||
readonly class Revision
|
readonly class Revision
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $id
|
||||||
|
* @param string $recordId
|
||||||
|
* @param string $schema
|
||||||
|
* @param System $_sys
|
||||||
|
* @param RecordData $data
|
||||||
|
* @param Option<EdgeCollection> $_edges
|
||||||
|
* @param Option<FileInfo> $_file
|
||||||
|
*/
|
||||||
function __construct(
|
function __construct(
|
||||||
public string $id,
|
public string $id,
|
||||||
public string $recordId,
|
public string $recordId,
|
||||||
public string $schema,
|
public string $schema,
|
||||||
public System $_sys,
|
public System $_sys,
|
||||||
public RecordData $data,
|
public RecordData $data,
|
||||||
public EdgeCollection $_edges,
|
public Option $_edges,
|
||||||
public ?FileInfo $_file = null,
|
public Option $_file,
|
||||||
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
public static function fromRecord(Record $record, EdgeCollection $edges): Revision
|
* @param Record $record
|
||||||
|
* @param Option<EdgeCollection> $edges
|
||||||
|
* @return Revision
|
||||||
|
*/
|
||||||
|
public static function fromRecord(Record $record, Option $edges): Revision
|
||||||
{
|
{
|
||||||
return new Revision(
|
return new Revision(
|
||||||
id: (string)Str::uuid(),
|
id: (string)Str::uuid(),
|
||||||
@@ -35,7 +49,7 @@ readonly class Revision
|
|||||||
_sys: $record->_sys,
|
_sys: $record->_sys,
|
||||||
data: $record->data,
|
data: $record->data,
|
||||||
_edges: $edges,
|
_edges: $edges,
|
||||||
_file: $record->_file
|
_file: empty($record->_file) ? none() : some($record->_file)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
namespace Lucent\Revision;
|
namespace Lucent\Revision;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Lucent\Edge\Edge;
|
|
||||||
use Lucent\Edge\EdgeCollection;
|
use Lucent\Edge\EdgeCollection;
|
||||||
use Lucent\Record\FileInfo;
|
use Lucent\Record\FileInfo;
|
||||||
use Lucent\Record\RecordData;
|
use Lucent\Record\RecordData;
|
||||||
@@ -80,23 +79,15 @@ class RevisionRepo
|
|||||||
"recordId" => $revision->recordId,
|
"recordId" => $revision->recordId,
|
||||||
"schema" => $revision->schema,
|
"schema" => $revision->schema,
|
||||||
"_sys" => json_encode($revision->_sys),
|
"_sys" => json_encode($revision->_sys),
|
||||||
"_file" => json_encode($revision->_file),
|
"_file" => $revision->_file->map(fn($v) => json_encode($v))->getOrElse(null),
|
||||||
"data" => json_encode($revision->data),
|
"data" => json_encode($revision->data),
|
||||||
"_edges" => $revision->_edges->toJson(),
|
"_edges" => $revision->_edges->getOrElse(null)->toJson(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fromDB(stdClass $data): Revision
|
public function fromDB(stdClass $data): Revision
|
||||||
{
|
{
|
||||||
$file = json_decode($data->_file, true);
|
|
||||||
if (!empty($file)) {
|
|
||||||
|
|
||||||
$file = new FileInfo(...$file);
|
|
||||||
} else {
|
|
||||||
$file = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$edges = array_map(fn($e) => Edge::fromArray($e), json_decode($data->_edges ?? "[]", true));
|
|
||||||
|
|
||||||
return new Revision(
|
return new Revision(
|
||||||
id: $data->id,
|
id: $data->id,
|
||||||
@@ -104,8 +95,8 @@ class RevisionRepo
|
|||||||
schema: $data->schema,
|
schema: $data->schema,
|
||||||
_sys: System::fromArray(json_decode($data->_sys, true)),
|
_sys: System::fromArray(json_decode($data->_sys, true)),
|
||||||
data: new RecordData(json_decode($data->data, true)),
|
data: new RecordData(json_decode($data->data, true)),
|
||||||
_edges: new EdgeCollection(...$edges),
|
_edges: Option::fromValue($data->_edges)->map([EdgeCollection::class,'fromJson']),
|
||||||
_file: $file
|
_file: Option::fromValue($data->_file)->map([FileInfo::class,'fromJSON'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,12 @@ readonly class RevisionService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function create(Record $record, EdgeCollection $edges): void
|
/**
|
||||||
|
* @param Record $record
|
||||||
|
* @param Option<EdgeCollection> $edges
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function create(Record $record, Option $edges): void
|
||||||
{
|
{
|
||||||
$schema = $this->channelService->getSchema($record->schema)->get();
|
$schema = $this->channelService->getSchema($record->schema)->get();
|
||||||
if($schema->revisions <= 0){
|
if($schema->revisions <= 0){
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Lucent\Schema\Schema;
|
|||||||
use Lucent\Schema\Field\FieldInterface;
|
use Lucent\Schema\Field\FieldInterface;
|
||||||
use Lucent\Support\Collection;
|
use Lucent\Support\Collection;
|
||||||
|
|
||||||
class BlockSchema implements Schema
|
class BlockSchema extends Schema
|
||||||
{
|
{
|
||||||
|
|
||||||
public Type $type = Type::BLOCK;
|
public Type $type = Type::BLOCK;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Lucent\Schema\Schema;
|
|||||||
use Lucent\Schema\Field\FieldInterface;
|
use Lucent\Schema\Field\FieldInterface;
|
||||||
use Lucent\Support\Collection;
|
use Lucent\Support\Collection;
|
||||||
|
|
||||||
class CollectionSchema implements Schema
|
class CollectionSchema extends Schema
|
||||||
{
|
{
|
||||||
public Type $type = Type::COLLECTION;
|
public Type $type = Type::COLLECTION;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Lucent\Schema\Schema;
|
|||||||
use Lucent\Schema\Field\FieldDataInterface;
|
use Lucent\Schema\Field\FieldDataInterface;
|
||||||
use Lucent\Support\Collection;
|
use Lucent\Support\Collection;
|
||||||
|
|
||||||
class EdgeSchema implements Schema
|
class EdgeSchema extends Schema
|
||||||
{
|
{
|
||||||
public Type $type = Type::EDGE;
|
public Type $type = Type::EDGE;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Lucent\Schema\Schema;
|
|||||||
use Lucent\Schema\Field\FieldInterface;
|
use Lucent\Schema\Field\FieldInterface;
|
||||||
use Lucent\Support\Collection;
|
use Lucent\Support\Collection;
|
||||||
|
|
||||||
class FilesSchema implements Schema
|
class FilesSchema extends Schema
|
||||||
{
|
{
|
||||||
|
|
||||||
public Type $type = Type::FILES;
|
public Type $type = Type::FILES;
|
||||||
|
|||||||
@@ -2,8 +2,21 @@
|
|||||||
|
|
||||||
namespace Lucent\Schema\Schema;
|
namespace Lucent\Schema\Schema;
|
||||||
|
|
||||||
interface Schema
|
use Lucent\Schema\Field\FieldDataInterface;
|
||||||
|
use Lucent\Schema\Field\FieldInterface;
|
||||||
|
use Lucent\Support\Collection;
|
||||||
|
|
||||||
|
abstract class Schema
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Collection<FieldInterface>
|
||||||
|
*/
|
||||||
|
public Collection $fields;
|
||||||
|
/**
|
||||||
|
* @return Collection<FieldDataInterface>
|
||||||
|
*/
|
||||||
|
public function getDataFields(): Collection{
|
||||||
|
return $this->fields->filter(fn(FieldInterface $f) => $f instanceof FieldDataInterface)->values();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
namespace Lucent\Schema\Validator;
|
namespace Lucent\Schema\Validator;
|
||||||
|
|
||||||
use Lucent\Channel\ChannelService;
|
use Lucent\Channel\ChannelService;
|
||||||
use Lucent\Edge\EdgeCollection;
|
|
||||||
use Lucent\Record\RecordData;
|
use Lucent\Record\RecordData;
|
||||||
use Lucent\Schema\Field\FieldInterface;
|
use Lucent\Schema\Field\FieldDataInterface;
|
||||||
use Lucent\Support\Collection;
|
use Lucent\Support\Collection;
|
||||||
|
use PhpOption\Option;
|
||||||
|
|
||||||
|
|
||||||
class Validator
|
class Validator
|
||||||
@@ -25,53 +25,38 @@ class Validator
|
|||||||
public function check(
|
public function check(
|
||||||
string $schemaName,
|
string $schemaName,
|
||||||
RecordData $data,
|
RecordData $data,
|
||||||
?EdgeCollection $edges,
|
|
||||||
): Collection
|
): Collection
|
||||||
{
|
{
|
||||||
|
|
||||||
$schema = $this->channelService->getSchema($schemaName)->get();
|
$schema = $this->channelService->getSchema($schemaName)->get();
|
||||||
return $schema->fields
|
return $schema->getDataFields()
|
||||||
->map(fn(FieldInterface $f) => $this->validate($f, $data, $edges))
|
->map(fn(FieldDataInterface $f) => $this->validate($f, $data))
|
||||||
->filter(fn(?ValidatorError $error) => !empty($error))
|
->filter(fn(Option $error) => $error->isDefined())
|
||||||
->values();
|
->values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function validate(FieldInterface $field, RecordData $recordData, ?EdgeCollection $edges): ?ValidatorError
|
/**
|
||||||
|
* @param FieldDataInterface $field
|
||||||
|
* @param RecordData $recordData
|
||||||
|
* @return Option<ValidatorError>
|
||||||
|
*/
|
||||||
|
public function validate(FieldDataInterface $field, RecordData $recordData): Option
|
||||||
{
|
{
|
||||||
$value = $recordData->get($field->name);
|
$value = $recordData->get($field->name);
|
||||||
if ($field instanceof RequiredInterface && $field->required && $field->failRequired($value)) {
|
|
||||||
return new ValidatorError($field->name, $field->label, "Field is required");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($field instanceof MinMaxInterface && !is_null($field->min) && $field->failMin($value)) {
|
return match (true) {
|
||||||
return new ValidatorError($field->name, $field->label, "The minimum {$field->label} can be {$field->min}");
|
$field instanceof RequiredInterface
|
||||||
}
|
&& $field->required
|
||||||
|
&& $field->failRequired($value) => some(new ValidatorError($field->name, $field->label, "Field is required")),
|
||||||
if ($field instanceof MinMaxInterface && !is_null($field->max) && $field->failMax($value)) {
|
$field instanceof MinMaxInterface
|
||||||
return new ValidatorError($field->name, $field->label, "The maximum {$field->label} can be {$field->min}");
|
&& !is_null($field->min)
|
||||||
}
|
&& $field->failMin($value) => some(new ValidatorError($field->name, $field->label, "The minimum {$field->label} can be {$field->min}")),
|
||||||
|
$field instanceof MinMaxInterface
|
||||||
return null;
|
&& !is_null($field->max)
|
||||||
}
|
&& $field->failMax($value) => some(new ValidatorError($field->name, $field->label, "The maximum {$field->label} can be {$field->min}")),
|
||||||
|
default => none()
|
||||||
/**
|
};
|
||||||
* @param Collection<ValidatorError> $errors
|
|
||||||
* @throws ValidatorException
|
|
||||||
*/
|
|
||||||
public function throwException(Collection $errors): void
|
|
||||||
{
|
|
||||||
throw new ValidatorException($this->errorsByField($errors));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Collection<ValidatorError> $errors
|
|
||||||
* @return array<string,ValidatorError>
|
|
||||||
**/
|
|
||||||
public function errorsByField(Collection $errors): array
|
|
||||||
{
|
|
||||||
|
|
||||||
return collect($errors)->keyBy("fieldName")->toArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user