Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,7 @@
['name' => 'objectRelations#removeReferences', 'url' => '/api/objects/{register}/{schema}/{id}/relation-references/{anchor}', 'verb' => 'DELETE', 'requirements' => ['id' => '[^/]+', 'anchor' => '[^/]+']],
['name' => 'objectRelations#derive', 'url' => '/api/objects/{register}/{schema}/{id}/derive', 'verb' => 'POST', 'requirements' => ['id' => '[^/]+']],
['name' => 'objectRelations#graph', 'url' => '/api/objects/{register}/{schema}/{id}/graph', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']],
['name' => 'objectRelations#tree', 'url' => '/api/objects/{register}/{schema}/{id}/tree', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']],
['name' => 'objectRelations#exportGraph', 'url' => '/api/objects/{register}/{schema}/{id}/graph/export', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']],
// Locks.
// Whether a row exists in other registers, and nothing about the
Expand Down
61 changes: 61 additions & 0 deletions lib/Controller/ObjectRelationsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
use OCA\OpenRegister\Service\Object\ObjectReadAccess;
use OCA\OpenRegister\Service\ObjectService;
use OCA\OpenRegister\Service\Relation\ObjectRelationService;
use OCA\OpenRegister\Service\Relation\ObjectTreeService;
use OCA\OpenRegister\Service\Relation\RelationGraphService;
use OCA\OpenRegister\Service\Relation\RelationTypeResolver;
use OCP\AppFramework\Controller;
Expand Down Expand Up @@ -67,6 +68,7 @@ class ObjectRelationsController extends Controller {
* @param ObjectService $objectService Reads and writes objects, with RBAC.
* @param ExportGate $exportGate The export verb, checked before the graph leaves.
* @param ObjectReadAccess $access Resolves an object under the caller's own RBAC.
* @param ObjectTreeService $trees The bounded walk along a schema's parent property.
*
* @spec openspec/changes/relation-types-with-inverses/specs/referential-integrity/spec.md
*/
Expand All @@ -78,6 +80,7 @@ public function __construct(
private readonly ObjectService $objectService,
private readonly ExportGate $exportGate,
private readonly ObjectReadAccess $access,
private readonly ObjectTreeService $trees,
) {
parent::__construct(appName: $appName, request: $request);
}//end __construct()
Expand Down Expand Up @@ -483,6 +486,64 @@ public function graph(string $register, string $schema, string $id): JSONRespons
);
}//end graph()

/**
* The ancestors and descendants of an object along its schema's parent property.
*
* Query: `direction` (descendants, ancestors or both; default descendants),
* `depth` (default the schema's declared bound) and `fields` (comma-separated
* properties copied onto each node). Every node passes the caller's RBAC.
*
* @param string $register The register slug or id.
* @param string $schema The schema slug or id.
* @param string $id The object's uuid.
*
* @return JSONResponse The tree.
*
* @spec openspec/changes/object-tree-read/specs/referential-integrity/spec.md
*/
#[NoAdminRequired]
#[NoCSRFRequired]
public function tree(string $register, string $schema, string $id): JSONResponse {
$object = $this->access->readable(register: $register, schema: $schema, id: $id);
if ($object === null) {
return $this->access->notReadable();
}

$direction = (string)$this->request->getParam('direction', ObjectTreeService::DIRECTION_DESCENDANTS);
$directions = [
ObjectTreeService::DIRECTION_DESCENDANTS,
ObjectTreeService::DIRECTION_ANCESTORS,
ObjectTreeService::DIRECTION_BOTH,
];
if (in_array($direction, $directions, true) === false) {
return new JSONResponse(
data: ['error' => 'direction must be one of: '.implode(', ', $directions)],
statusCode: 400
);
}

$depth = null;
if ($this->stringParam(name: 'depth') !== null) {
$depth = $this->depth();
}

$fields = array_values(
array_filter(
array_map('trim', explode(',', (string)$this->stringParam(name: 'fields'))),
static fn (string $field): bool => $field !== ''
)
);

return new JSONResponse(
data: $this->trees->tree(
root: $object,
direction: $direction,
depth: $depth,
fields: $fields
)
);
}//end tree()

/**
* The same graph, as rows a spreadsheet opens.
*
Expand Down
Loading
Loading