query and graph
This commit is contained in:
+2
-1
@@ -19,7 +19,8 @@
|
||||
"symfony/yaml": "^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.8"
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"laravel/framework": "^10.10"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
Generated
+3819
-473
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ return new class extends Migration {
|
||||
$table->string('status');
|
||||
$table->jsonb('data');
|
||||
$table->jsonb('_sys');
|
||||
$table->jsonb('_file');
|
||||
$table->jsonb('_file')->nullable();
|
||||
|
||||
$table->index(['schema', 'status']);
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Lucent\Edge;
|
||||
use Lucent\LucentException;
|
||||
use Lucent\Validator\Validator as LucentValidator;
|
||||
use PhpOption\Option;
|
||||
use stdClass;
|
||||
|
||||
final class Edge
|
||||
{
|
||||
@@ -63,4 +64,20 @@ final class Edge
|
||||
depth: data_get($data, 'depth', 0),
|
||||
);
|
||||
}
|
||||
|
||||
public static function fromDB(stdClass $data): Edge
|
||||
{
|
||||
|
||||
return new Edge(
|
||||
|
||||
source: data_get($data, 'source'),
|
||||
target: data_get($data, 'target'),
|
||||
sourceSchema: data_get($data, 'sourceSchema'),
|
||||
targetSchema: data_get($data, 'targetSchema'),
|
||||
field: data_get($data, 'field'),
|
||||
data: Option::fromValue(data_get($data,"data")),
|
||||
rank: data_get($data, 'rank'),
|
||||
depth: data_get($data, 'depth', 0),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,11 @@ namespace Lucent\File;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Lucent\Channel\ChannelService;
|
||||
use Lucent\LucentException;
|
||||
use Lucent\Record\File;
|
||||
use Lucent\Record\FileInfo;
|
||||
use Lucent\Record\QueryRecord;
|
||||
use Lucent\Schema\Schema\Schema;
|
||||
use Lucent\Schema\Schema\Type;
|
||||
use Lucent\Support\Result\Result;
|
||||
|
||||
class FileService
|
||||
{
|
||||
@@ -24,6 +25,15 @@ class FileService
|
||||
return $this->channelService->channel->url. "/storage/".$file->_file->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
* @param string $uploadFromUrl
|
||||
* @return Result<FileInfo|string>
|
||||
*/
|
||||
public function createFromUrl(Schema $schema, string $uploadFromUrl): Result{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws LucentException
|
||||
*/
|
||||
@@ -48,7 +58,7 @@ class FileService
|
||||
}
|
||||
|
||||
return new FileUploadResult(
|
||||
recordFile: File::fromArray($file), duplicateId: "", isDuplicate: false
|
||||
recordFile: FileInfo::fromArray($file), duplicateId: "", isDuplicate: false
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
namespace Lucent\File;
|
||||
|
||||
use Lucent\Record\File;
|
||||
use Lucent\Record\FileInfo;
|
||||
|
||||
class FileUploadResult
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
public ?File $recordFile,
|
||||
public string $duplicateId,
|
||||
public bool $isDuplicate,
|
||||
public ?FileInfo $recordFile,
|
||||
public string $duplicateId,
|
||||
public bool $isDuplicate,
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\ImageManagerStatic;
|
||||
use Lucent\LucentException;
|
||||
use Lucent\Record\File as RecordFile;
|
||||
use Lucent\Record\FileInfo as RecordFile;
|
||||
use Lucent\Schema\Schema\Schema;
|
||||
use Spatie\ImageOptimizer\OptimizerChainFactory;
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php namespace Lucent\Http;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, ValidatesRequests;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Lucent\Http\Controller;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Lucent\Account\AuthService;
|
||||
use Lucent\Svelte\Svelte;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Lucent\Http\Controller\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Lucent\Edge\EdgeService;
|
||||
@@ -12,26 +12,26 @@ use function Lucent\Response\ok;
|
||||
|
||||
class EdgeController extends Controller
|
||||
{
|
||||
|
||||
public function create(Request $request): Response
|
||||
{
|
||||
try {
|
||||
$edge = EdgeService::create(
|
||||
source: $request->input("source"),
|
||||
target: $request->input("target"),
|
||||
sourceSchema: $request->input("sourceSchema"),
|
||||
targetSchema: $request->input("targetSchema"),
|
||||
field: $request->input("field"),
|
||||
rank: $request->input("rank") ?? "",
|
||||
);
|
||||
} catch (LucentException $th) {
|
||||
return fail($th);
|
||||
}
|
||||
|
||||
|
||||
return ok([
|
||||
"edge" => $edge,
|
||||
]);
|
||||
}
|
||||
//
|
||||
// public function create(Request $request): Response
|
||||
// {
|
||||
// try {
|
||||
// $edge = EdgeService::create(
|
||||
// source: $request->input("source"),
|
||||
// target: $request->input("target"),
|
||||
// sourceSchema: $request->input("sourceSchema"),
|
||||
// targetSchema: $request->input("targetSchema"),
|
||||
// field: $request->input("field"),
|
||||
// rank: $request->input("rank") ?? "",
|
||||
// );
|
||||
// } catch (LucentException $th) {
|
||||
// return fail($th);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// return ok([
|
||||
// "edge" => $edge,
|
||||
// ]);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
|
||||
namespace Lucent\Http\Controller\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Lucent\Account\AuthService;
|
||||
use Lucent\Channel\ChannelRepo;
|
||||
use Lucent\File\FileUploadResult;
|
||||
use Lucent\Query\Query;
|
||||
use Lucent\Record\RecordService;
|
||||
use function Lucent\File\uploadFile;
|
||||
use function Lucent\Response\fail;
|
||||
@@ -16,47 +14,46 @@ use function Lucent\Response\ok;
|
||||
|
||||
class FileController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly RecordService $recordService,
|
||||
private readonly Query $query
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function upload(Request $request)
|
||||
{
|
||||
$validator = Validator::make(request()->all(), [
|
||||
'files.*' => 'required|file|max:100000',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return fail($validator->errors()->first());
|
||||
}
|
||||
$channel = ChannelRepo::current();
|
||||
$schema = $channel->schemas->firstWhere("name", $request->input("schema"));
|
||||
$files = request()->file('files');
|
||||
|
||||
|
||||
$uploadResults = collect($files)->map(fn($file) => uploadFile($schema, $file))->toArray();
|
||||
$insertedIds = collect($uploadResults)
|
||||
->filter(fn(FileUploadResult $res) => !$res->isDuplicate)
|
||||
->values()
|
||||
->map(function (FileUploadResult $uploadResult) use ($schema, $request) {
|
||||
|
||||
|
||||
return $this->recordService->create(
|
||||
userId: AuthService::currentUserId($request),
|
||||
schemaName: $schema->name,
|
||||
data: [],
|
||||
file: (array)$uploadResult->recordFile,
|
||||
edges: [],
|
||||
status: $request->input("status") ?? "published",
|
||||
uploadFromUrl: ""
|
||||
);
|
||||
|
||||
})->toArray();
|
||||
|
||||
|
||||
return ok($insertedIds);
|
||||
}
|
||||
// public function __construct(
|
||||
// private readonly RecordService $recordService,
|
||||
// )
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// public function upload(Request $request)
|
||||
// {
|
||||
// $validator = Validator::make(request()->all(), [
|
||||
// 'files.*' => 'required|file|max:100000',
|
||||
// ]);
|
||||
//
|
||||
// if ($validator->fails()) {
|
||||
// return fail($validator->errors()->first());
|
||||
// }
|
||||
// $channel = ChannelRepo::current();
|
||||
// $schema = $channel->schemas->firstWhere("name", $request->input("schema"));
|
||||
// $files = request()->file('files');
|
||||
//
|
||||
//
|
||||
// $uploadResults = collect($files)->map(fn($file) => uploadFile($schema, $file))->toArray();
|
||||
// $insertedIds = collect($uploadResults)
|
||||
// ->filter(fn(FileUploadResult $res) => !$res->isDuplicate)
|
||||
// ->values()
|
||||
// ->map(function (FileUploadResult $uploadResult) use ($schema, $request) {
|
||||
//
|
||||
//
|
||||
// return $this->recordService->create(
|
||||
// userId: AuthService::currentUserId($request),
|
||||
// schemaName: $schema->name,
|
||||
// data: [],
|
||||
// file: (array)$uploadResult->recordFile,
|
||||
// edges: [],
|
||||
// status: $request->input("status") ?? "published",
|
||||
// uploadFromUrl: ""
|
||||
// );
|
||||
//
|
||||
// })->toArray();
|
||||
//
|
||||
//
|
||||
// return ok($insertedIds);
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Lucent\Http\Controller\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Lucent\Channel\ChannelRepo;
|
||||
use Lucent\LucentException;
|
||||
@@ -15,93 +15,93 @@ use function Lucent\Response\ok;
|
||||
|
||||
class RecordController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly RecordService $recordService,
|
||||
private readonly Query $query
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function records(Request $request)
|
||||
{
|
||||
$channel = ChannelRepo::current();
|
||||
$urlParams = $request->all();
|
||||
$sort = data_get($urlParams, "sort") ?? "-_sys.updatedAt";
|
||||
$filter = data_get($urlParams, "filter") ?? [];
|
||||
$arguments = array_merge([
|
||||
|
||||
], $filter);
|
||||
|
||||
$skip = data_get($urlParams, "skip") ?? 0;
|
||||
$limit = data_get($urlParams, "limit") ?? 15;
|
||||
$queryResult = $this->query
|
||||
->filter($arguments)
|
||||
->limit($limit)
|
||||
->skip($skip)
|
||||
->sort($sort)
|
||||
->childrenDepth($request->input("childrenDepth") ?? 1)
|
||||
->parentsDepth($request->input("parentsDepth") ?? 0)
|
||||
->runWithCount();
|
||||
|
||||
$graph = $queryResult->getQueryRecords($channel->schemas);
|
||||
$total = $queryResult->getTotal();
|
||||
|
||||
return ok([
|
||||
"graph" => $graph->toArray(),
|
||||
"sort" => $sort,
|
||||
"limit" => $limit,
|
||||
"skip" => $skip,
|
||||
"total" => $total,
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(Request $request)
|
||||
{
|
||||
|
||||
try {
|
||||
|
||||
$recordId = $this->recordService->create(
|
||||
userId: $request->input("userId"),
|
||||
schemaName: $request->input("schema"),
|
||||
data: $request->input("data") ?? [],
|
||||
file: $request->input("file") ?? [],
|
||||
edges: $request->input("edges") ?? [],
|
||||
status: $request->input("status") ?? "draft",
|
||||
uploadFromUrl: $request->input("uploadFromUrl") ?? ""
|
||||
);
|
||||
|
||||
} catch (ValidatorException $th) {
|
||||
return fail($th->getValidatorErrors());
|
||||
} catch (LucentException $th) {
|
||||
return fail($th);
|
||||
}
|
||||
return ok(["id" => $recordId]);
|
||||
}
|
||||
|
||||
public function update(Request $request)
|
||||
{
|
||||
|
||||
try {
|
||||
$this->recordService->update(
|
||||
userId: $request->input("userId"),
|
||||
id: $request->route("id"),
|
||||
data: $request->input("data"),
|
||||
status: $request->input("status"),
|
||||
edges: $request->input("edges") ?? [],
|
||||
updateEdges: false,
|
||||
);
|
||||
} catch (ValidatorException $th) {
|
||||
return fail($th->getValidatorErrors());
|
||||
} catch (LucentException $th) {
|
||||
return fail($th);
|
||||
} catch (Throwable $th) {
|
||||
if ($th->getCode() == 11000) {
|
||||
return fail("ID has to be unique in the channel");
|
||||
}
|
||||
return fail($th);
|
||||
}
|
||||
|
||||
return ok();
|
||||
}
|
||||
// public function __construct(
|
||||
// private readonly RecordService $recordService,
|
||||
// private readonly Query $query
|
||||
// )
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// public function records(Request $request)
|
||||
// {
|
||||
// $channel = ChannelRepo::current();
|
||||
// $urlParams = $request->all();
|
||||
// $sort = data_get($urlParams, "sort") ?? "-_sys.updatedAt";
|
||||
// $filter = data_get($urlParams, "filter") ?? [];
|
||||
// $arguments = array_merge([
|
||||
//
|
||||
// ], $filter);
|
||||
//
|
||||
// $skip = data_get($urlParams, "skip") ?? 0;
|
||||
// $limit = data_get($urlParams, "limit") ?? 15;
|
||||
// $queryResult = $this->query
|
||||
// ->filter($arguments)
|
||||
// ->limit($limit)
|
||||
// ->skip($skip)
|
||||
// ->sort($sort)
|
||||
// ->childrenDepth($request->input("childrenDepth") ?? 1)
|
||||
// ->parentsDepth($request->input("parentsDepth") ?? 0)
|
||||
// ->runWithCount();
|
||||
//
|
||||
// $graph = $queryResult->getQueryRecords($channel->schemas);
|
||||
// $total = $queryResult->getTotal();
|
||||
//
|
||||
// return ok([
|
||||
// "graph" => $graph->toArray(),
|
||||
// "sort" => $sort,
|
||||
// "limit" => $limit,
|
||||
// "skip" => $skip,
|
||||
// "total" => $total,
|
||||
// ]);
|
||||
// }
|
||||
//
|
||||
// public function create(Request $request)
|
||||
// {
|
||||
//
|
||||
// try {
|
||||
//
|
||||
// $recordId = $this->recordService->create(
|
||||
// userId: $request->input("userId"),
|
||||
// schemaName: $request->input("schema"),
|
||||
// data: $request->input("data") ?? [],
|
||||
// file: $request->input("file") ?? [],
|
||||
// edges: $request->input("edges") ?? [],
|
||||
// status: $request->input("status") ?? "draft",
|
||||
// uploadFromUrl: $request->input("uploadFromUrl") ?? ""
|
||||
// );
|
||||
//
|
||||
// } catch (ValidatorException $th) {
|
||||
// return fail($th->getValidatorErrors());
|
||||
// } catch (LucentException $th) {
|
||||
// return fail($th);
|
||||
// }
|
||||
// return ok(["id" => $recordId]);
|
||||
// }
|
||||
//
|
||||
// public function update(Request $request)
|
||||
// {
|
||||
//
|
||||
// try {
|
||||
// $this->recordService->update(
|
||||
// userId: $request->input("userId"),
|
||||
// id: $request->route("id"),
|
||||
// data: $request->input("data"),
|
||||
// status: $request->input("status"),
|
||||
// edges: $request->input("edges") ?? [],
|
||||
// updateEdges: false,
|
||||
// );
|
||||
// } catch (ValidatorException $th) {
|
||||
// return fail($th->getValidatorErrors());
|
||||
// } catch (LucentException $th) {
|
||||
// return fail($th);
|
||||
// } catch (Throwable $th) {
|
||||
// if ($th->getCode() == 11000) {
|
||||
// return fail("ID has to be unique in the channel");
|
||||
// }
|
||||
// return fail($th);
|
||||
// }
|
||||
//
|
||||
// return ok();
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Lucent\Http\Controller\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Lucent\Schema\SchemaService;
|
||||
use function Lucent\Response\fail;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Lucent\Http\Controller;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Contracts\Session\Session;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
@@ -2,14 +2,10 @@
|
||||
|
||||
namespace Lucent\Http\Controller;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Lucent\Channel\ChannelService;
|
||||
use Lucent\Svelte\Svelte;
|
||||
use function Lucent\Response\ok;
|
||||
|
||||
class BuildController extends Controller
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Lucent\Http\Controller;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Lucent\Channel\ChannelService;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Lucent\Http\Controller;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Lucent\Http\Controller;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Lucent\Account\AccountService;
|
||||
use Lucent\Account\AuthService;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Lucent\Http\Controller;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Lucent\Account\AccountService;
|
||||
use Lucent\Account\AuthService;
|
||||
@@ -203,7 +203,6 @@ class RecordController extends Controller
|
||||
{
|
||||
$rid = $request->route("rid");
|
||||
|
||||
|
||||
$graph = $this->query
|
||||
->filter(["id" => $rid])
|
||||
->limit(1)
|
||||
@@ -214,6 +213,7 @@ class RecordController extends Controller
|
||||
->parentsLimit(200)
|
||||
->run();
|
||||
|
||||
|
||||
if ($graph->records->isEmpty()) {
|
||||
return $this->svelte->render(
|
||||
layout: "channel",
|
||||
|
||||
@@ -2,12 +2,9 @@
|
||||
|
||||
namespace Lucent\Http\Controller;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Lucent\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Lucent\Record\RecordRepo;
|
||||
use Lucent\Revision\RevisionRepo;
|
||||
use Lucent\Revision\RevisionService;
|
||||
use function Lucent\Response\fail;
|
||||
use function Lucent\Response\ok;
|
||||
|
||||
class RevisionController extends Controller
|
||||
|
||||
@@ -2,13 +2,21 @@
|
||||
|
||||
namespace Lucent\Query\DatabaseGraph;
|
||||
|
||||
use Lucent\Edge\Edge;
|
||||
use Lucent\Query\QueryOptions;
|
||||
use Lucent\Support\Collection;
|
||||
|
||||
interface DatabaseGraph
|
||||
{
|
||||
/**
|
||||
* @param array<string> $ids
|
||||
* @return Collection<Edge>
|
||||
*/
|
||||
public function getChildren(array $ids, QueryOptions $options): array;
|
||||
public function getParents(array $ids, QueryOptions $options): array;
|
||||
public function getChildren(array $ids, QueryOptions $options): Collection;
|
||||
|
||||
/**
|
||||
* @param array<string> $ids
|
||||
* @return Collection<Edge>
|
||||
*/
|
||||
public function getParents(array $ids, QueryOptions $options): Collection;
|
||||
}
|
||||
@@ -3,15 +3,18 @@
|
||||
namespace Lucent\Query\DatabaseGraph;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Lucent\Edge\Edge;
|
||||
use Lucent\Query\QueryOptions;
|
||||
use Lucent\Support\Collection;
|
||||
|
||||
class PgsqlDatabaseGraph implements DatabaseGraph
|
||||
{
|
||||
|
||||
/**
|
||||
* @param array<string> $ids
|
||||
* @return Collection<Edge>
|
||||
*/
|
||||
public function getChildren(array $ids, QueryOptions $options): array
|
||||
public function getChildren(array $ids, QueryOptions $options): Collection
|
||||
{
|
||||
$subquery = DB::table('edges AS g')
|
||||
->select(DB::raw('g.source,g.target,g.rank,"g"."sourceSchema","g"."targetSchema",g.field, 1 as depth '))
|
||||
@@ -30,16 +33,17 @@ class PgsqlDatabaseGraph implements DatabaseGraph
|
||||
->orderBy("rank")
|
||||
);
|
||||
|
||||
return DB::table('search_graph')
|
||||
return new Collection(DB::table('search_graph')
|
||||
// ->select(DB::raw("*, 1 as depth "))
|
||||
->withRecursiveExpression('search_graph', $subquery)
|
||||
->get()->toArray();
|
||||
->get()->map([Edge::class, 'fromDB']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string> $ids
|
||||
* @return Collection<Edge>
|
||||
*/
|
||||
public function getParents(array $ids, QueryOptions $options): array
|
||||
public function getParents(array $ids, QueryOptions $options): Collection
|
||||
{
|
||||
$subquery = DB::table('edges AS g')
|
||||
->select(DB::raw('g.source,g.target,g.rank,"g"."sourceSchema","g"."targetSchema",g.field, 1 as depth '))
|
||||
@@ -59,9 +63,9 @@ class PgsqlDatabaseGraph implements DatabaseGraph
|
||||
->orderBy("rank")
|
||||
);
|
||||
|
||||
return DB::table('search_graph')
|
||||
return new Collection(DB::table('search_graph')
|
||||
// ->select(DB::raw('sg.source,sg.target,sg.rank,sg."sourceSchema",sg."targetSchema",sg.field,sg.depth'))
|
||||
->withRecursiveExpression('search_graph', $subquery)
|
||||
->get()->toArray();
|
||||
->get()->map([Edge::class, 'fromDB']));
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,17 @@
|
||||
namespace Lucent\Query\DatabaseGraph;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Lucent\Edge\Edge;
|
||||
use Lucent\Query\QueryOptions;
|
||||
use Lucent\Support\Collection;
|
||||
|
||||
class SqliteDatabaseGraph implements DatabaseGraph
|
||||
{
|
||||
/**
|
||||
* @param array<string> $ids
|
||||
* @return Collection<Edge>
|
||||
*/
|
||||
public function getChildren(array $ids, QueryOptions $options): array
|
||||
public function getChildren(array $ids, QueryOptions $options): Collection
|
||||
{
|
||||
$subquery = DB::table('edges AS g')
|
||||
->select(DB::raw('g.source,g.target,g.rank,g.sourceSchema,g.targetSchema,g.field, 1 as depth '))
|
||||
@@ -29,16 +32,17 @@ class SqliteDatabaseGraph implements DatabaseGraph
|
||||
->orderBy("rank")
|
||||
);
|
||||
|
||||
return DB::table('search_graph')
|
||||
return new Collection(DB::table('search_graph')
|
||||
// ->select(DB::raw("*, 1 as depth "))
|
||||
->withRecursiveExpression('search_graph', $subquery)
|
||||
->get()->toArray();
|
||||
->get()->map([Edge::class, 'fromDB']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string> $ids
|
||||
* @return Collection<Edge>
|
||||
*/
|
||||
public function getParents(array $ids, QueryOptions $options): array
|
||||
public function getParents(array $ids, QueryOptions $options): Collection
|
||||
{
|
||||
$subquery = DB::table('edges AS g')
|
||||
->select(DB::raw('g.source,g.target,g.rank,"g"."sourceSchema","g"."targetSchema",g.field, 1 as depth '))
|
||||
@@ -58,9 +62,9 @@ class SqliteDatabaseGraph implements DatabaseGraph
|
||||
->orderBy("rank")
|
||||
);
|
||||
|
||||
return DB::table('search_graph')
|
||||
return new Collection(DB::table('search_graph')
|
||||
// ->select(DB::raw('sg.source,sg.target,sg.rank,sg."sourceSchema",sg."targetSchema",sg.field,sg.depth'))
|
||||
->withRecursiveExpression('search_graph', $subquery)
|
||||
->get()->toArray();
|
||||
->get()->map([Edge::class, 'fromDB']));
|
||||
}
|
||||
}
|
||||
+50
-47
@@ -4,23 +4,29 @@ namespace Lucent\Query;
|
||||
|
||||
use Lucent\Edge\Edge;
|
||||
use Lucent\Record\QueryRecord;
|
||||
use Lucent\Record\Record;
|
||||
use Lucent\Support\Collection;
|
||||
use PhpOption\Option;
|
||||
|
||||
final class Graph
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection<QueryRecord> $records
|
||||
* @param Collection<Record> $rootRecords
|
||||
* @param Collection<Record> $records
|
||||
* @param Collection<Edge> $edges
|
||||
* */
|
||||
public function __construct(
|
||||
public Collection $records,
|
||||
public Collection $edges,
|
||||
public Collection $parentEdges,
|
||||
public Collection $rootRecords,
|
||||
public Collection $records,
|
||||
public Collection $edges,
|
||||
public Collection $parentEdges,
|
||||
public QueryOptions $queryOptions,
|
||||
public ?int $total = null,
|
||||
public ?int $total = null,
|
||||
)
|
||||
{
|
||||
$this->edges->sortBy("rank")->values();
|
||||
$this->parentEdges->sortBy("rank")->values();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,7 +45,8 @@ final class Graph
|
||||
|
||||
public function tree(): Collection
|
||||
{
|
||||
return $this->getRootRecords()
|
||||
return $this->rootRecords
|
||||
->map([QueryRecord::class, 'fromRecord'])
|
||||
->map(fn($r) => $this->findParents($r))
|
||||
->map(fn($r) => $this->findChildren($r));
|
||||
|
||||
@@ -47,61 +54,57 @@ final class Graph
|
||||
|
||||
public function findChildren(QueryRecord $record, int $depth = 1): QueryRecord
|
||||
{
|
||||
if($this->queryOptions->childrenDepth < $depth){
|
||||
if ($this->queryOptions->childrenDepth < $depth) {
|
||||
return $record;
|
||||
}
|
||||
$recordEdges = $this->edges
|
||||
->filter(fn(Edge $ed) => $ed->source === $record->id )
|
||||
$record->_children = $this->edges
|
||||
->filter(fn(Edge $ed) => $ed->source === $record->record->id)
|
||||
->unique(fn(Edge $ed) => $ed->targetSchema . $ed->field . $ed->target . $ed->source)
|
||||
->sort(fn($a, $b) => $a->rank <=> $b->rank)->values();
|
||||
$groupRecordEdges = [];
|
||||
foreach ($recordEdges as $element) {
|
||||
$groupRecordEdges[$element->field][] = $element;
|
||||
}
|
||||
$children = [];
|
||||
foreach ($groupRecordEdges as $field => $edges) {
|
||||
|
||||
$children[$field] = [];
|
||||
foreach ($edges as $anEdge) {
|
||||
$aRecord = $this->records->filter(fn(QueryRecord $rec) => $rec->id == $anEdge->target)->values();
|
||||
if (empty($aRecord[0])) {
|
||||
continue;
|
||||
->sort(fn($a, $b) => $a->rank <=> $b->rank)
|
||||
->values()
|
||||
->map(function (Edge $edge): Option {
|
||||
$records = $this->records->filter(fn(Record $rec) => $rec->id == $edge->target)->values();
|
||||
if ($records->isEmpty()) {
|
||||
return none();
|
||||
}
|
||||
$queryRecord = QueryRecord::fromRecord($records->first());
|
||||
$queryRecord->edge = some($edge);
|
||||
return some($queryRecord);
|
||||
})
|
||||
->filter(fn(Option $o) => $o->isDefined())
|
||||
->values()
|
||||
->map(fn(Option $o) => $this->findChildren($o->get(), $depth + 1))
|
||||
->groupBy(fn(QueryRecord $qr) => $qr->edge->get()->field);
|
||||
|
||||
$children[$field][] = $this->findChildren($aRecord[0], $depth + 1);
|
||||
}
|
||||
}
|
||||
$record->_children = $children;
|
||||
return $record;
|
||||
}
|
||||
|
||||
|
||||
public function findParents(QueryRecord $record, int $depth = 1): QueryRecord
|
||||
{
|
||||
if($this->queryOptions->parentsDepth < $depth){
|
||||
|
||||
if ($this->queryOptions->parentsDepth < $depth) {
|
||||
return $record;
|
||||
}
|
||||
$recordEdges = $this->parentEdges->filter(fn(Edge $ed) => $ed->target === $record->id)->where("depth", $depth)->values()->sort(fn($a, $b) => $a->rank <=> $b->rank)->values();
|
||||
|
||||
$groupRecordEdges = [];
|
||||
foreach ($recordEdges as $element) {
|
||||
$groupRecordEdges[$element->field][] = $element;
|
||||
}
|
||||
$parents = [];
|
||||
foreach ($groupRecordEdges as $field => $edges) {
|
||||
|
||||
$parents[$field] = [];
|
||||
foreach ($edges as $anEdge) {
|
||||
$aRecord = $this->records->filter(fn(QueryRecord $rec) => $rec->id == $anEdge->source)->values();
|
||||
if (empty($aRecord[0])) {
|
||||
continue;
|
||||
$record->_parents = $this->parentEdges
|
||||
->filter(fn(Edge $ed) => $ed->target === $record->record->id)
|
||||
->where("depth", $depth)
|
||||
->values()
|
||||
->sort(fn($a, $b) => $a->rank <=> $b->rank)
|
||||
->values()
|
||||
->map(function (Edge $edge): Option {
|
||||
$records = $this->records->filter(fn(Record $rec) => $rec->id == $edge->source)->values();
|
||||
if ($records->isEmpty()) {
|
||||
return none();
|
||||
}
|
||||
$queryRecord = QueryRecord::fromRecord($records->first());
|
||||
$queryRecord->edge = some($edge);
|
||||
return some($queryRecord);
|
||||
})
|
||||
->filter(fn(Option $o) => $o->isDefined())
|
||||
->values()
|
||||
->map(fn(Option $o) => $this->findParents($o->get(), $depth + 1))
|
||||
->groupBy(fn(QueryRecord $qr) => $qr->edge->get()->field);
|
||||
|
||||
$parents[$field][] = $this->findParents($aRecord[0], $depth + 1);
|
||||
}
|
||||
}
|
||||
$record->_parents = $parents;
|
||||
return $record;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+29
-80
@@ -4,12 +4,11 @@ namespace Lucent\Query;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Lucent\Edge\Edge;
|
||||
use Lucent\Query\DatabaseGraph\DatabaseGraph;
|
||||
use Lucent\Query\Filter\AndFilter;
|
||||
use Lucent\Query\Filter\OrFilter;
|
||||
use Lucent\Record\InputFormatter;
|
||||
use Lucent\Record\QueryRecord;
|
||||
use Lucent\Record\Mapper;
|
||||
use Lucent\Record\Record;
|
||||
use Lucent\Support\Collection;
|
||||
|
||||
@@ -26,6 +25,7 @@ final class Query
|
||||
public readonly FilterParser $filterParser,
|
||||
public readonly InputFormatter $inputFormatter,
|
||||
public readonly DatabaseGraph $databaseGraph,
|
||||
public readonly Mapper $recordMapper,
|
||||
)
|
||||
{
|
||||
$this->options = new QueryOptions();
|
||||
@@ -46,91 +46,54 @@ final class Query
|
||||
|
||||
public function run(): Graph
|
||||
{
|
||||
$resultsRecords = $this->mainQuery();
|
||||
$ids = array_map(function ($rec) {
|
||||
return $rec->id;
|
||||
}, $resultsRecords);
|
||||
$rootRecords = $this->mainQuery();
|
||||
$ids = $rootRecords->pluck("id");
|
||||
|
||||
$resultChildrenEdgesTargetIds = [];
|
||||
$resultChildrenEdges = [];
|
||||
if ($this->options->childrenDepth > 0 && !empty($ids)) {
|
||||
$resultChildrenEdges = $this->getChildren($ids);
|
||||
$resultChildrenEdgesTargetIds = array_map(fn($e) => $e->target, $resultChildrenEdges);
|
||||
$resultChildrenEdges = new Collection();
|
||||
if ($this->options->childrenDepth > 0 && $ids->isNotEmpty()) {
|
||||
$resultChildrenEdges = $this->databaseGraph->getChildren($ids->toArray(), $this->options);
|
||||
$resultChildrenEdgesTargetIds = $resultChildrenEdges->pluck("target");
|
||||
}
|
||||
$resultParentSourceTargetIds = [];
|
||||
$resultParentEdges = [];
|
||||
if ($this->options->parentsDepth > 0 && !empty($ids)) {
|
||||
$resultParentEdges = $this->getParents($ids);
|
||||
$resultParentSourceTargetIds = array_map(fn($e) => $e->source, $resultParentEdges);
|
||||
$resultParentEdges = new Collection();
|
||||
if ($this->options->parentsDepth > 0 && $ids->isNotEmpty()) {
|
||||
$resultParentEdges = $this->databaseGraph->getParents($ids->toArray(), $this->options);
|
||||
$resultParentSourceTargetIds = $resultParentEdges->pluck("source");
|
||||
}
|
||||
|
||||
$edgesIds = collect($resultParentSourceTargetIds)->merge($resultChildrenEdgesTargetIds)->unique()->values()->toArray();
|
||||
$edgeRecords = [];
|
||||
$edgeRecords = new Collection();
|
||||
if (!empty($edgesIds)) {
|
||||
$edgeRecords = DB::table('records')
|
||||
$edgeRecords = new Collection(DB::table('records')
|
||||
->whereIn("id", $edgesIds)
|
||||
->whereIn("status", $this->options->status)
|
||||
->get()->toArray();
|
||||
->get()->map([$this->recordMapper, 'fromDB']));
|
||||
}
|
||||
$resultsRecordsUnique = collect(array_merge($resultsRecords, $edgeRecords))->unique("id")->values()->toArray();
|
||||
// $resultEdges = collect(array_merge($resultChildrenEdges, $resultParentEdges))
|
||||
// ->unique(fn($edge) => $edge->source . $edge->target . $edge->field)
|
||||
// ->toArray();
|
||||
|
||||
$formattedRecords = $this->formatRecords($resultsRecordsUnique, $resultChildrenEdges, $resultParentEdges);
|
||||
$graph = new Graph(
|
||||
$rootRecords,
|
||||
$edgeRecords,
|
||||
$resultChildrenEdges,
|
||||
$resultParentEdges,
|
||||
$this->options
|
||||
);
|
||||
$this->reset();
|
||||
return $formattedRecords;
|
||||
return $graph;
|
||||
|
||||
}
|
||||
|
||||
private function reset()
|
||||
private function reset(): void
|
||||
{
|
||||
$this->options = new QueryOptions();
|
||||
$this->filters = [];
|
||||
}
|
||||
|
||||
private function formatRecords(array $records, array $edges, array $parentEdges): Graph
|
||||
{
|
||||
$queryRecords = collect($records)->map(function ($recordData) {
|
||||
|
||||
$record = Record::fromDB($recordData);
|
||||
$record->data = $this->inputFormatter->fill($record->schema, $record->data);
|
||||
$queryRecord = QueryRecord::fromRecord($record);
|
||||
$queryRecord->isRoot = data_get($recordData, "isRoot") === true;
|
||||
return $queryRecord;
|
||||
})->toArray();
|
||||
|
||||
|
||||
$queryEdges = collect($edges)->map(function ($edgeData) {
|
||||
|
||||
return Edge::fromArray((array)$edgeData);
|
||||
|
||||
})->sortBy("rank")->values()->toArray();
|
||||
|
||||
$queryParentEdges = collect($parentEdges)->map(function ($edgeData) {
|
||||
|
||||
|
||||
return Edge::fromArray((array)$edgeData);
|
||||
|
||||
})->sortBy("rank")->values()->toArray();
|
||||
|
||||
|
||||
|
||||
return new Graph(
|
||||
new Collection($queryRecords),
|
||||
new Collection($queryEdges),
|
||||
new Collection($queryParentEdges),
|
||||
$this->options,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function tree(): Collection
|
||||
{
|
||||
return $this->run()->tree();
|
||||
}
|
||||
|
||||
|
||||
private function parseFilters(Builder $query): Builder
|
||||
{
|
||||
foreach ($this->filters as $filter) {
|
||||
@@ -140,8 +103,10 @@ final class Query
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
private function mainQuery(): array
|
||||
/**
|
||||
* @return Collection<Record>
|
||||
*/
|
||||
private function mainQuery(): Collection
|
||||
{
|
||||
$query = DB::table("records");
|
||||
$query = $this->parseFilters($query);
|
||||
@@ -149,24 +114,8 @@ final class Query
|
||||
$query->limit($this->options->limit);
|
||||
$query->offset($this->options->skip);
|
||||
}
|
||||
|
||||
$query = $this->orderByQuery($query);
|
||||
|
||||
return $query->get()->map(function ($r) {
|
||||
$r->isRoot = true;
|
||||
return $r;
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
private
|
||||
function getChildren(array $ids): array
|
||||
{
|
||||
return $this->databaseGraph->getChildren($ids, $this->options);
|
||||
}
|
||||
|
||||
private function getParents(array $ids): array
|
||||
{
|
||||
return $this->databaseGraph->getParents($ids, $this->options);
|
||||
return new Collection($query->get()->map([$this->recordMapper, 'fromDB']));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Record;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use stdClass;
|
||||
|
||||
class Document implements Record
|
||||
{
|
||||
|
||||
function __construct(
|
||||
public string $id,
|
||||
public string $schema,
|
||||
public Status $status,
|
||||
public System $_sys,
|
||||
public RecordData $data,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
private function indexValues(array $arrObject): string
|
||||
{
|
||||
|
||||
return trim(Str::lower(collect($arrObject)
|
||||
->map(function ($value) {
|
||||
if (is_array($value)) {
|
||||
return $this->indexValues($value ?? []);
|
||||
}
|
||||
return str_replace(array("\r", "\n"), '', strip_tags((string)$value));
|
||||
})
|
||||
->values()->join(" ")));
|
||||
}
|
||||
|
||||
public function toDB(): array
|
||||
{
|
||||
$searchIndex = $this->indexValues($this->data->toArray());
|
||||
return [
|
||||
"id" => $this->id,
|
||||
"status" => $this->status->value,
|
||||
"schema" => $this->schema,
|
||||
"_sys" => json_encode($this->_sys),
|
||||
"_file" => null,
|
||||
"data" => json_encode($this->data),
|
||||
"search" => $searchIndex,
|
||||
];
|
||||
}
|
||||
|
||||
public static function fromDB(stdClass $data): Document
|
||||
{
|
||||
return new Document(
|
||||
id: $data->id,
|
||||
schema: $data->schema,
|
||||
status: Status::from($data->status),
|
||||
_sys: System::fromArray(json_decode($data->_sys, true)),
|
||||
data: new RecordData(json_decode($data->data, true)),
|
||||
);
|
||||
}
|
||||
}
|
||||
+45
-22
@@ -2,37 +2,60 @@
|
||||
|
||||
namespace Lucent\Record;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use stdClass;
|
||||
|
||||
class File
|
||||
class File implements Record
|
||||
{
|
||||
|
||||
function __construct(
|
||||
public readonly string $originalName,
|
||||
public readonly string $mime,
|
||||
public readonly string $path,
|
||||
public readonly int $size,
|
||||
public readonly int $width,
|
||||
public readonly int $height,
|
||||
public readonly string $checksum,
|
||||
public string $id,
|
||||
public string $schema,
|
||||
public Status $status,
|
||||
public System $_sys,
|
||||
public RecordData $data,
|
||||
public FileInfo $_file,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public static function fromArray(array $data): File
|
||||
{
|
||||
return new File(
|
||||
originalName: data_get($data, "originalName"),
|
||||
mime: data_get($data, "mime"),
|
||||
path: data_get($data, "path"),
|
||||
size: data_get($data, "size"),
|
||||
width: data_get($data, "width"),
|
||||
height: data_get($data, "height"),
|
||||
checksum: data_get($data, "checksum"),
|
||||
);
|
||||
|
||||
private function indexValues(array $arrObject){
|
||||
|
||||
return trim(Str::lower(collect($arrObject)
|
||||
->map(function($value){
|
||||
if(is_array($value)){
|
||||
return $this->indexValues($value ?? []);
|
||||
}
|
||||
return str_replace(array("\r", "\n"), '', strip_tags((string)$value));
|
||||
})
|
||||
->values()->join(" ")." ". $this->_file->originalName));
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
public function toDB(): array
|
||||
{
|
||||
return \json_decode(\json_encode($this), true);
|
||||
$searchIndex = $this->indexValues($this->data->toArray());
|
||||
return [
|
||||
"id" => $this->id,
|
||||
"status" => $this->status->value,
|
||||
"schema" => $this->schema,
|
||||
"_sys" => json_encode($this->_sys),
|
||||
"_file" => json_encode($this->_file),
|
||||
"data" => json_encode($this->data),
|
||||
"search" => $searchIndex,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public static function fromDB(stdClass $data): File
|
||||
{
|
||||
|
||||
return new File(
|
||||
id: $data->id,
|
||||
schema: $data->schema,
|
||||
status: Status::from($data->status),
|
||||
_sys: System::fromArray(json_decode($data->_sys, true)),
|
||||
data: new RecordData(json_decode($data->data, true)),
|
||||
_file: FileInfo::fromJSON($data->_file),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Record;
|
||||
|
||||
|
||||
readonly class FileInfo
|
||||
{
|
||||
|
||||
function __construct(
|
||||
public string $originalName,
|
||||
public string $mime,
|
||||
public string $path,
|
||||
public int $size,
|
||||
public int $width,
|
||||
public int $height,
|
||||
public string $checksum,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public static function fromArray(array $data): FileInfo
|
||||
{
|
||||
return new FileInfo(
|
||||
originalName: data_get($data, "originalName"),
|
||||
mime: data_get($data, "mime"),
|
||||
path: data_get($data, "path"),
|
||||
size: data_get($data, "size"),
|
||||
width: data_get($data, "width"),
|
||||
height: data_get($data, "height"),
|
||||
checksum: data_get($data, "checksum"),
|
||||
);
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return \json_decode(\json_encode($this), true);
|
||||
}
|
||||
|
||||
public static function fromJSON(string $json): self
|
||||
{
|
||||
$file = json_decode($json, true);
|
||||
return self::fromArray($file);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Record;
|
||||
|
||||
use stdClass;
|
||||
|
||||
class Mapper
|
||||
{
|
||||
public function __construct(
|
||||
public InputFormatter $inputFormatter
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function fromDB(stdClass $data): Record
|
||||
{
|
||||
$record = match (true) {
|
||||
!empty($data->_file) => File::fromDB($data),
|
||||
default => Document::fromDB($data),
|
||||
};
|
||||
|
||||
$record->data = $this->inputFormatter->fill($record->schema, $record->data);
|
||||
return $record;
|
||||
}
|
||||
}
|
||||
+15
-18
@@ -2,21 +2,23 @@
|
||||
|
||||
namespace Lucent\Record;
|
||||
|
||||
use Lucent\LucentException;
|
||||
use Lucent\Edge\Edge;
|
||||
use Lucent\Support\Collection;
|
||||
use PhpOption\Option;
|
||||
|
||||
class QueryRecord
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Record $record
|
||||
* @param Option<Edge> $edge
|
||||
* @param Collection<QueryRecord> $_children
|
||||
* @param Collection<QueryRecord> $_parents
|
||||
*/
|
||||
function __construct(
|
||||
public string $id,
|
||||
public string $schema,
|
||||
public Status $status,
|
||||
public System $_sys,
|
||||
public RecordData $data,
|
||||
public bool $isRoot,
|
||||
public ?File $_file = null,
|
||||
public array $_children = [],
|
||||
public array $_parents = [],
|
||||
public Record $record,
|
||||
public Option $edge,
|
||||
public Collection $_children = new Collection(),
|
||||
public Collection $_parents = new Collection(),
|
||||
)
|
||||
{
|
||||
}
|
||||
@@ -24,13 +26,8 @@ class QueryRecord
|
||||
public static function fromRecord(Record $record): QueryRecord
|
||||
{
|
||||
return new QueryRecord(
|
||||
id: $record->id,
|
||||
schema: $record->schema,
|
||||
status: $record->status,
|
||||
_sys: $record->_sys,
|
||||
data: $record->data,
|
||||
isRoot: false,
|
||||
_file: $record->_file,
|
||||
record: $record,
|
||||
edge: none(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-67
@@ -2,78 +2,15 @@
|
||||
|
||||
namespace Lucent\Record;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use JsonSerializable;
|
||||
use stdClass;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Record implements JsonSerializable
|
||||
interface Record
|
||||
{
|
||||
|
||||
|
||||
function __construct(
|
||||
public string $id,
|
||||
public string $schema,
|
||||
public Status $status,
|
||||
public System $_sys,
|
||||
public RecordData $data,
|
||||
public ?File $_file = null,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
private function indexValues(array $arrObject){
|
||||
|
||||
return trim(Str::lower(collect($arrObject)
|
||||
->map(function($value){
|
||||
if(is_array($value)){
|
||||
return $this->indexValues($value ?? []);
|
||||
}
|
||||
return str_replace(array("\r", "\n"), '', strip_tags((string)$value));
|
||||
})
|
||||
->values()->join(" ")." ". $this->_file?->originalName ?? ""));
|
||||
}
|
||||
|
||||
public function toDB(): array
|
||||
{
|
||||
$searchIndex = $this->indexValues($this->data->toArray());
|
||||
return [
|
||||
"id" => $this->id,
|
||||
"status" => $this->status->value,
|
||||
"schema" => $this->schema,
|
||||
"_sys" => json_encode($this->_sys),
|
||||
"_file" => json_encode($this->_file),
|
||||
"data" => json_encode($this->data),
|
||||
"search" => $searchIndex,
|
||||
];
|
||||
}
|
||||
|
||||
public static function fromDB(stdClass $data): Record
|
||||
{
|
||||
|
||||
$file = json_decode($data->_file, true);
|
||||
if (!empty($file)) {
|
||||
|
||||
$file = new File(...$file);
|
||||
} else {
|
||||
$file = null;
|
||||
}
|
||||
|
||||
return new Record(
|
||||
id: $data->id,
|
||||
schema: $data->schema,
|
||||
status: Status::from($data->status),
|
||||
_sys: System::fromArray(json_decode($data->_sys, true)),
|
||||
data: new RecordData(json_decode($data->data, true)),
|
||||
_file: $file,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function jsonSerialize(): static
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
static function fromDB(stdClass $data): Record;
|
||||
public function toDB(): array;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Lucent\Revision;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Lucent\Edge\EdgeCollection;
|
||||
use Lucent\Record\File;
|
||||
use Lucent\Record\FileInfo;
|
||||
use Lucent\Record\Record;
|
||||
use Lucent\Record\RecordData;
|
||||
use Lucent\Record\System;
|
||||
@@ -19,7 +19,7 @@ readonly class Revision
|
||||
public System $_sys,
|
||||
public RecordData $data,
|
||||
public EdgeCollection $_edges,
|
||||
public ?File $_file = null,
|
||||
public ?FileInfo $_file = null,
|
||||
|
||||
)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Lucent\Revision;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Lucent\Edge\Edge;
|
||||
use Lucent\Edge\EdgeCollection;
|
||||
use Lucent\Record\File;
|
||||
use Lucent\Record\FileInfo;
|
||||
use Lucent\Record\RecordData;
|
||||
use Lucent\Record\System;
|
||||
use Lucent\Support\Collection;
|
||||
@@ -91,7 +91,7 @@ class RevisionRepo
|
||||
$file = json_decode($data->_file, true);
|
||||
if (!empty($file)) {
|
||||
|
||||
$file = new File(...$file);
|
||||
$file = new FileInfo(...$file);
|
||||
} else {
|
||||
$file = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user