Files
lucent-laravel/src/Http/Controller/RecordController.php
T
2024-10-05 15:19:53 +03:00

393 lines
13 KiB
PHP

<?php
namespace Lucent\Http\Controller;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Lucent\Account\AccountService;
use Lucent\Account\AuthService;
use Lucent\Channel\ChannelService;
use Lucent\LucentException;
use Lucent\Query\Operator\OperatorRegistry;
use Lucent\Query\Query;
use Lucent\Record\InputData\EdgeInputData;
use Lucent\Record\InputData\RecordInputData;
use Lucent\Record\Manager;
use Lucent\Record\QueryRecord;
use Lucent\Record\RecordService;
use Lucent\Record\Status;
use Lucent\Schema\SingletonSchema;
use Lucent\Schema\System;
use Lucent\Schema\Validator\ValidatorException;
use Lucent\Svelte\Svelte;
use function Lucent\Response\fail;
use function Lucent\Response\ok;
class RecordController extends Controller
{
public function __construct(
private readonly RecordService $recordService,
private readonly AccountService $accountService,
private readonly ChannelService $channelService,
private readonly Svelte $svelte,
private readonly Query $query,
private readonly Manager $recordManager,
private readonly OperatorRegistry $operatorRegistry
)
{
}
public function index(Request $request)
{
$schemaName = $request->route("schemaName");
if (!in_array($schemaName, $this->accountService->currentReadableSchemas())) {
return $this->svelte->render(
layout: "channel",
view: "recordNotFound",
title: "Schema Not Found",
);
}
$users = $this->accountService->all();
$schema = $this->channelService->getSchema($schemaName)->get();
$urlParams = $request->all();
$sort = data_get($urlParams, "sort") ?? $schema->sortBy ?? "";
$filter = data_get($urlParams, "filter") ?? [];
$arguments = array_merge([
"schema" => $schema->name,
"status_in" => "draft,published",
], $filter);
$skip = data_get($urlParams, "skip") ?? 0;
$limit = 30;
$records = [];
$graphArray = null;
$graph = $this->query
->filter($arguments)
->notLinked($request->input("notlinked") ?? "")
->limit($limit)
->status(explode(",", $arguments["status_in"]))
->skip($skip)
->sort($sort)
->childrenFields($schema?->visible ?? [])
->childrenDepth(1)
->parentsDepth(0)
->runWithCount();
$records = $graph->getRootRecords()->toArray();
if(get_class($schema) === SingletonSchema::class){
$id = $records[0]->id ?? null;
if(empty($id)){
return redirect($this->channelService->channel->lucentUrl."/records/new?schema=".$schemaName);
}
return redirect($this->channelService->channel->lucentUrl."/records/".$id);
}
$data = [
"schemas" => $this->channelService->channel->schemas,
"schema" => $schema,
"users" => $users,
"records" => $records,
"graph" => toArray($graph),
"systemFields" => array_values(System::list()),
"operators" => $this->operatorRegistry->all(),
"sortParam" => $sort,
"sortField" => $schema->fields->merge(array_values(System::list()))->firstWhere(fn($field) => $field->name === $sort || "-" . $field->name === $sort || "data." . $field->name === $sort || "-data." . $field->name === $sort),
"limit" => $limit,
"skip" => $skip,
"total" => $graph->total ?? 0,
"filter" => $request->input("filter") ?? [],
"inModal" => true,
"isWritable" => in_array($schemaName, $this->accountService->currentWritableSchemas())
];
if ($request->ajax()) {
$data["modalUrl"] = $request->fullUrl();
if (str_starts_with(config("lucent.url"), "https")) {
$data["modalUrl"] = str_replace("http://", "https://", $request->fullUrl());
}
return $data;
}
$data["inModal"] = false;
return $this->svelte->render(
layout: "channel",
view: "contentIndex",
title: "Records",
data: $data
);
}
public function exportCSV(Request $request)
{
$schemaName = $request->route("schemaName");
$schema = $this->channelService->channel->schemas->where("name", $schemaName)->first();
$urlParams = $request->all();
$sort = data_get($urlParams, "sort") ?? "-_sys.updatedAt";
$filter = data_get($urlParams, "filter") ?? [];
$arguments = array_merge([
"schema" => $schema->name,
"status_in" => "draft,published",
], $filter);
$records = $this->query
->filter($arguments)
->limit(-1)
->status(explode(",", $arguments["status_in"]))
// ->skip($skip)
->sort($sort)
->run()
->records;
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="' . $schemaName . '.csv";');
$handle = fopen('php://output', 'w');
$csvRow = ["id", ...array_keys($records[0]->data->toArray())];
fputcsv($handle, $csvRow, ',');
foreach ($records as $record) {
$csvRow = [$record->id, ...$record->data->toArray()];
$csvRow = array_values($csvRow);
fputcsv($handle, $csvRow, ',');
}
fclose($handle);
echo $handle;
exit;
}
public function new(Request $request)
{
if (!in_array($request->input("schema"), $this->accountService->currentWritableSchemas())) {
return $this->svelte->render(
layout: "channel",
view: "recordNotFound",
title: "Schema Not Found",
);
}
$schema = $this->channelService->channel->schemas->where("name", $request->input("schema"))->first();
$recordHistory = $this->recordManager->fromSession($request->session())->getRecords();
$record = $this->recordService->createEmpty($schema);
$queryRecord = QueryRecord::fromRecord($record);
return $this->svelte->render(
layout: "channel",
view: "recordEdit",
title: "New Record",
data: [
"schema" => $schema,
"record" => $queryRecord,
"recordHistory" => $recordHistory,
"isCreateMode" => true,
"isWritable" => in_array($record->schema, $this->accountService->currentWritableSchemas())
]
);
}
public function newInline(Request $request)
{
if (!in_array($request->input("schema"), $this->accountService->currentWritableSchemas())) {
return $this->svelte->render(
layout: "channel",
view: "recordNotFound",
title: "Schema Not Found",
);
}
$schema = $this->channelService->getSchema($request->input("schema"))->get();
$record = $this->recordService->createEmpty($schema);
$queryRecord = QueryRecord::fromRecord($record);
return [
"schema" => $schema,
"record" => $queryRecord,
"isCreateMode" => true,
"isWritable" => in_array($record->schema, $this->accountService->currentWritableSchemas())
];
}
public function edit(Request $request)
{
$rid = $request->route("rid");
$graph = $this->query
->filter(["id" => $rid])
->limit(1)
->skip(0)
->childrenDepth(2)
->childrenLimit(200)
->parentsDepth(1)
->parentsLimit(200)
->run();
if ($graph->records->isEmpty()) {
return $this->svelte->render(
layout: "channel",
view: "recordNotFound",
title: "Record Not Found",
);
}
$record = $graph->records->first();
if (!in_array($record->schema, $this->accountService->currentReadableSchemas())) {
return $this->svelte->render(
layout: "channel",
view: "recordNotFound",
title: "Schema Not Found",
);
}
$schema = $this->channelService->getSchema($record->schema)->get();
$recordHistory = $this->recordManager->fromSession($request->session())->push($rid)->getRecords($rid);
return $this->svelte->render(
layout: "channel",
view: "recordEdit",
title: "Edit Record",
data: [
"schema" => $schema,
"graph" => toArray($graph),
"record" => toArray($record),
"users" => $this->accountService->all(),
"recordHistory" => $recordHistory,
"isWritable" => in_array($record->schema, $this->accountService->currentWritableSchemas())
]
);
}
public function suggestions(Request $request)
{
$arguments = [
"schema" => $request->input("schema"),
];
if ($request->input("value")) {
if (in_array($request->input("ui"), ["text", "date"])) {
$arguments["data." . $request->input("field") . "_regex"] = $request->input("value");
} elseif ($request->input("ui") == "number") {
$arguments["data." . $request->input("field") . "_eqnum"] = floatval($request->input("value"));
} elseif ($request->input("ui") == "date") {
} elseif ($request->input("ui") == "search") {
$arguments["search_regex"] = $request->input("value");
}
}
$records = $this->query
->filter($arguments)
->limit(10)
->tree();
if ($records->isEmpty()) {
return ok([]);
}
return ok($records->toArray());
}
public function save(Request $request)
{
$recordId = $request->input("record.id");
try {
if ($request->input("isCreateMode")) {
$recordId = $this->recordService->create(
data: new RecordInputData(
$request->input("record.schema"),
$recordId ?? "",
$request->input("record.data"),
Status::from($request->input("record.status")),
),
edges: array_map(EdgeInputData::fromArray(...), $request->input("edges") ?? [])
);
} else {
$this->recordService->updateWithEdges(
id: $request->input("record.id"),
data: $request->input("record.data"),
status: Status::from($request->input("record.status")),
edges: array_map(EdgeInputData::fromArray(...), $request->input("edges") ?? []),
);
}
$newGraph = $this->query
->filter(["id" => $recordId])
->limit(10)
->childrenDepth(1)
->parentsDepth(1)
->run();
} catch (ValidatorException $th) {
return fail($th->getValidatorErrors());
} catch (LucentException $th) {
return fail($th);
}
return ok(toArray($newGraph));
}
public function clone(Request $request)
{
try {
$newRecordId = $this->recordService->clone(
recordId: $request->route("rid"),
);
} catch (LucentException $th) {
return fail($th);
} catch (ValidatorException $e) {
return fail($e);
}
return ok(["id" => $newRecordId]);
}
public function status(Request $request)
{
$this->recordService->changeStatusBulk(
status: $request->route("status"),
recordsIds: $request->input("records"),
);
return ok();
}
public function emptyTrash(Request $request)
{
$this->recordService->emptyTrash($request->route("schemaName"));
return redirect($this->channelService->channel->lucentUrl . "/content/" . $request->route("schemaName"));
}
public function delete(Request $request)
{
$ids = $request->input("ids");
try {
$this->recordService->deleteMany($ids);
} catch (Throwable $th) {
return fail($th);
}
return ok();
}
public function rollback(Request $request)
{
try {
$this->recordService->rollback(
recordId: $request->route("rid"),
version: (int)$request->route("version")
);
} catch (ValidatorException $th) {
return fail($th->getFirstValidatorError());
} catch (LucentException|Throwable $th) {
return fail($th);
}
return ok();
}
}