Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
53dcc9f
w.i.p. download schema as json file + set schema.source for upload
WilcoLouwerse Oct 31, 2024
d293ad5
Merge branch 'development' into feature/REGISTERS-30/from-schema-to-json
WilcoLouwerse Nov 1, 2024
bee2868
Merge branch 'development' into feature/REGISTERS-30/from-schema-to-json
WilcoLouwerse Nov 5, 2024
fe86d3e
Merge branch 'development' into feature/REGISTERS-30/from-schema-to-json
WilcoLouwerse Nov 7, 2024
b2733d5
Fix fields for Register & change how download response is stuctured
WilcoLouwerse Nov 7, 2024
4de5988
Merge branch 'development' into feature/REGISTERS-30/from-schema-to-json
WilcoLouwerse Nov 11, 2024
665eeeb
Merge branch 'development' into feature/REGISTERS-30/from-schema-to-json
WilcoLouwerse Nov 14, 2024
e60b076
Fixes downloadService
WilcoLouwerse Nov 14, 2024
0afb9c9
More fixes for DownloadService
WilcoLouwerse Nov 14, 2024
2fded41
style fixes
WilcoLouwerse Nov 14, 2024
24f85d1
Merge remote-tracking branch 'origin/development' into feature/REGIST…
remko48 Nov 21, 2024
131dbf9
Removed some old code that didn't do anything
WilcoLouwerse Nov 21, 2024
ebf48e3
Merge branch 'development' into feature/REGISTERS-30/from-schema-to-json
WilcoLouwerse Nov 21, 2024
f9d6be7
Show empty schema property config unless used for validation / download
WilcoLouwerse Nov 25, 2024
aaaf88b
Merge branch 'development' into feature/REGISTERS-30/from-schema-to-json
WilcoLouwerse Nov 26, 2024
13676d1
Merge branch 'development' into feature/REGISTERS-30/from-schema-to-json
WilcoLouwerse Nov 28, 2024
3c42542
Small rename for variable
WilcoLouwerse Nov 28, 2024
943fb34
Merge branch 'development' into feature/REGISTERS-30/from-schema-to-json
WilcoLouwerse Dec 5, 2024
f8f69c6
Merge pull request #49 from ConductionNL/feature/REGISTERS-30/from-sc…
WilcoLouwerse Dec 5, 2024
0727635
Object and file tabs
rubenvdlinde Dec 7, 2024
1680445
Merge branch 'development' into feature/REGISTER-66/ui
rubenvdlinde Dec 7, 2024
a99799d
First draft for ui logic
rubenvdlinde Dec 7, 2024
7f3da5d
First fixes
rubenvdlinde Dec 7, 2024
a52a45d
Save sub schema as the proper schema
rubenvdlinde Dec 8, 2024
e8fc791
Setting up the usses list
rubenvdlinde Dec 8, 2024
cdf6895
Made used by view and fix for searching in relations by uuid
rubenvdlinde Dec 8, 2024
e33e3bc
Allow filtering on relations and support non internal relations
rubenvdlinde Dec 8, 2024
9070566
Bit of testing on grapping the relations
rubenvdlinde Dec 8, 2024
8f7b607
Fix for relating to self
rubenvdlinde Dec 8, 2024
95f9101
Lint
remko48 Dec 9, 2024
50f0b3f
Small changes for updating return object
rjzondervan Dec 9, 2024
e3af0f0
Added changes to EditSchemaProperty
remko48 Dec 9, 2024
816468c
Merge pull request #94 from ConductionNL/feature/REGISTER-66/ui
remko48 Dec 9, 2024
0d84b95
dev to main PR fixes
rjzondervan Dec 9, 2024
aebe523
Added docblock for downloadService
WilcoLouwerse Dec 9, 2024
7f59d25
small fix in code style
WilcoLouwerse Dec 9, 2024
4440208
Merge pull request #96 from ConductionNL/fix/PR-comments
rjzondervan Dec 9, 2024
e91b64d
Added uploadService class docblock
WilcoLouwerse Dec 9, 2024
d01be00
Merge pull request #97 from ConductionNL/fix/PR-comments
WilcoLouwerse Dec 9, 2024
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 @@ -13,6 +13,7 @@
['name' => 'objects#logs', 'url' => '/api/objects-logs/{id}', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']],
['name' => 'objects#mappings', 'url' => '/api/objects/mappings', 'verb' => 'GET'],
['name' => 'objects#auditTrails', 'url' => '/api/objects/audit-trails/{id}', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']],
['name' => 'objects#relations', 'url' => '/api/objects/relations/{id}', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']],
['name' => 'schemas#upload', 'url' => '/api/schemas/upload', 'verb' => 'POST'],
['name' => 'schemas#uploadUpdate', 'url' => '/api/schemas/{id}/upload', 'verb' => 'PUT', 'requirements' => ['id' => '[^/]+']],
['name' => 'schemas#download', 'url' => '/api/schemas/{id}/download', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']],
Expand Down
40 changes: 37 additions & 3 deletions lib/Controller/ObjectsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public function create(ObjectService $objectService): JSONResponse
*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this controller have a class docblock?

* @return JSONResponse A JSON response containing the updated object details
*/
public function update(int $id): JSONResponse
public function update(int $id, ObjectService $objectService): JSONResponse
{
$data = $this->request->getParams();
$object = $data['object'];
Expand All @@ -204,8 +204,12 @@ public function update(int $id): JSONResponse
}

// save it
$oldObject = $this->objectEntityMapper->find($id);
$objectEntity = $this->objectEntityMapper->updateFromArray(id: $id, object: $data);
try {
$objectEntity = $objectService->saveObject(register: $data['register'], schema: $data['schema'], object: $data['object']);
} catch (ValidationException $exception) {
$formatter = new ErrorFormatter();
return new JSONResponse(['message' => $exception->getMessage(), 'validationErrors' => $formatter->format($exception->getErrors())], 400);
}

$this->auditTrailMapper->createAuditTrail(new: $objectEntity, old: $oldObject);

Expand Down Expand Up @@ -274,6 +278,36 @@ public function contracts(int $id): JSONResponse
return new JSONResponse(['error' => 'Not yet implemented'], 501);
}

/**
* Retrieves all objects that use a object
*
* This method returns all the call logs associated with a object based on its ID.
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param int $id The ID of the object to retrieve logs for
*
* @return JSONResponse A JSON response containing the call logs
*/
public function relations(int $id): JSONResponse
{
try {
// Lets grap the object to stablish an uri
$object = $this->objectEntityMapper->find($id);
$relations = $this->objectEntityMapper->findByRelationUri($object->getUri());

// We dont want to return the entity, but the object (and kant reley on the normal serilzier)
foreach ($relations as $key => $relation) {
$relations[$key] = $relation->getObjectArray();
}

return new JSONResponse($relations);
} catch (DoesNotExistException $e) {
return new JSONResponse(['error' => 'Relations not found'], 404);
}
}

/**
* Retrieves call logs for an object
*
Expand Down
37 changes: 13 additions & 24 deletions lib/Controller/SchemasController.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ public function upload(?int $id = null): JSONResponse
return $phpArray;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this controller have a class docblock?

}

//@todo Maybe check if Schema already exists? If uploaded with url, check if schema with this $phpArray['source'] exists?

// Set default title if not provided or empty
if (empty($phpArray['title']) === true) {
$phpArray['title'] = 'New Schema';
Expand All @@ -236,43 +238,30 @@ public function upload(?int $id = null): JSONResponse

/**
* Creates and return a json file for a Schema.
* @todo move most of this code to DownloadService and make it even more Abstract using Entity->jsonSerialize instead of Schema->jsonSerialize, etc.
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param int $id The ID of the schema to return json file for
* @return JSONResponse A json Response containing the json
* @throws \Exception
*/
public function download(int $id): JSONResponse
{
try {
$schema = $this->schemaMapper->find($id);
} catch (DoesNotExistException $exception) {
return new JSONResponse(data: ['error' => 'Not Found'], statusCode: 404);
}

$contentType = $this->request->getHeader('Content-Type');
$accept = $this->request->getHeader('Accept');

if (empty($contentType) === true) {
return new JSONResponse(data: ['error' => 'Request is missing header Content-Type'], statusCode: 400);
if (empty($accept) === true) {
return new JSONResponse(data: ['error' => 'Request is missing header Accept'], statusCode: 400);
}

switch ($contentType) {
case 'application/json':
$type = 'json';
$responseData = [
'jsonArray' => $schema->jsonSerialize(),
'jsonString' => json_encode($schema->jsonSerialize())
];
break;
default:
return new JSONResponse(data: ['error' => "The Content-Type $contentType is not supported."], statusCode: 400);
}
$responseData = $this->downloadService->download(objectType: 'schema', id: $id, accept: $accept);

// @todo Create a downloadable json file and return it.
$file = $this->downloadService->download(type: $type);
$statusCode = 200;
if (isset($responseData['statusCode']) === true) {
$statusCode = $responseData['statusCode'];
unset($responseData['statusCode']);
}

return new JSONResponse($responseData);
return new JSONResponse(data: $responseData, statusCode: $statusCode);
}
}
9 changes: 6 additions & 3 deletions lib/Db/ObjectAuditLogMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,12 @@ public function updateFromArray(int $id, array $object): ObjectAuditLog
$obj->hydrate($object);

// Set or update the version
$version = explode('.', $obj->getVersion());
$version[2] = (int)$version[2] + 1;
$obj->setVersion(implode('.', $version));
if (isset($object['version']) === false) {
$version = explode('.', $obj->getVersion());
$version[2] = (int)$version[2] + 1;
$obj->setVersion(implode('.', $version));
}


return $this->update($obj);
}
Expand Down
68 changes: 63 additions & 5 deletions lib/Db/ObjectEntityMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,36 @@ public function findAll(?int $limit = null, ?int $offset = null, ?array $filters
}
}

// @roto: tody this code up please and make ik monogdb compatible
// Check if _relations filter exists to search in relations column
if (isset($filters['_relations']) === true) {
// Handle both single string and array of relations
$relations = (array) $filters['_relations'];

// Build OR conditions for each relation
$orConditions = [];
foreach ($relations as $relation) {
$orConditions[] = $qb->expr()->isNotNull(
$qb->createFunction(
"JSON_SEARCH(relations, 'one', " .
$qb->createNamedParameter($relation) .
", NULL, '$')"
)
);
}

// Add the combined OR conditions to query
$qb->andWhere($qb->expr()->orX(...$orConditions));

// Remove _relations from filters since it's handled separately
unset($filters['_relations']);
}

// Filter and search the objects
$qb = $this->databaseJsonService->filterJson(builder: $qb, filters: $filters);
$qb = $this->databaseJsonService->searchJson(builder: $qb, search: $search);
$qb = $this->databaseJsonService->orderJson(builder: $qb, order: $sort);

// var_dump($qb->getSQL());

return $this->findEntities(query: $qb);
}

Expand Down Expand Up @@ -219,9 +243,12 @@ public function updateFromArray(int $id, array $object): ObjectEntity
$obj->hydrate($object);

// Set or update the version
$version = explode('.', $obj->getVersion());
$version[2] = (int)$version[2] + 1;
$obj->setVersion(implode('.', $version));
if (isset($object['version']) === false) {
$version = explode('.', $obj->getVersion());
$version[2] = (int)$version[2] + 1;
$obj->setVersion(implode('.', $version));
}


return $this->update($obj);
}
Expand Down Expand Up @@ -265,4 +292,35 @@ public function getFacets(array $filters = [], ?string $search = null)
search: $search
);
}

/**
* Find objects that have a specific URI or UUID in their relations
*
* @param string $search The URI or UUID to search for in relations
* @param bool $partialMatch Whether to search for partial matches (default: false)
* @return array An array of ObjectEntities that have the specified URI/UUID
*/
public function findByRelationUri(string $search, bool $partialMatch = false): array
{
$qb = $this->db->getQueryBuilder();

// For partial matches, we use '%' wildcards and 'all' mode to search anywhere in the JSON
// For exact matches, we use 'one' mode which finds exact string matches
$mode = $partialMatch ? 'all' : 'one';
$searchTerm = $partialMatch ? '%' . $search . '%' : $search;

$qb->select('*')
->from('openregister_objects')
->where(
$qb->expr()->isNotNull(
$qb->createFunction(
"JSON_SEARCH(relations, '" . $mode . "', " .
$qb->createNamedParameter($searchTerm) .
($partialMatch ? ", NULL, '$')" : ")")
)
)
);

return $this->findEntities($qb);
}
}
10 changes: 6 additions & 4 deletions lib/Db/RegisterMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

/**
* The RegisterMapper class
*
*
* @package OCA\OpenRegister\Db
*/
class RegisterMapper extends QBMapper
Expand Down Expand Up @@ -128,9 +128,11 @@ public function updateFromArray(int $id, array $object): Register
$obj->hydrate($object);

// Update the version
$version = explode('.', $obj->getVersion());
$version[2] = (int)$version[2] + 1;
$obj->setVersion(implode('.', $version));
if (isset($object['version']) === false) {
$version = explode('.', $obj->getVersion());
$version[2] = (int)$version[2] + 1;
$obj->setVersion(implode('.', $version));
}

// Update the register and return it
return $this->update($obj);
Expand Down
53 changes: 15 additions & 38 deletions lib/Db/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,32 +79,17 @@ public function hydrate(array $object): self
*/
public function jsonSerialize(): array
{
$required = $this->required ?? [];
$properties = [];
if (isset($this->properties) === true) {
foreach ($this->properties as $key => $property) {
$properties[$key] = $property;
if (isset($property['type']) === false) {
$properties[$key] = $property;
continue;
foreach ($this->properties as $title => $property) {
$title = $property['title'] ?? $title;
if ($property['required'] === true && in_array($title, $required) === false) {
$required[] = $title;
}
unset($property['title'], $property['required']);

if (isset($property['format']) === true) {
switch ($property['format']) {
case 'string':
// For now array as string
case 'array':
$properties[$key]['default'] = (string) $property;
break;
case 'int':
case 'integer':
case 'number':
$properties[$key]['default'] = (int) $property;
break;
case 'bool':
$properties[$key]['default'] = (bool) $property;
break;
}
}
$properties[$title] = $property;
}
}

Expand All @@ -115,7 +100,7 @@ public function jsonSerialize(): array
'description' => $this->description,
'version' => $this->version,
'summary' => $this->summary,
'required' => $this->required,
'required' => $required,
'properties' => $properties,
'archive' => $this->archive,
'source' => $this->source,
Expand Down Expand Up @@ -143,29 +128,21 @@ public function jsonSerialize(): array
public function getSchemaObject(IURLGenerator $urlGenerator): object
{
$data = $this->jsonSerialize();
$properties = $data['properties'];
unset($data['properties'], $data['id'], $data['uuid'], $data['summary'], $data['archive'], $data['source'],
$data['updated'], $data['created']);

$data['required'] = [];

$data['type'] = 'object';

foreach ($properties as $property) {
$title = $property['title'];
if ($property['required'] === true) {
$data['required'][] = $title;
}
unset($property['title'], $property['required']);

foreach ($data['properties'] as $title => $property) {
// Remove empty fields with array_filter().
$data['properties'][$title] = array_filter($property);
}

unset($data['id'], $data['uuid'], $data['summary'], $data['archive'], $data['source'],
$data['updated'], $data['created']);

$data['type'] = 'object';

// Validator needs this specific $schema
$data['$schema'] = 'https://json-schema.org/draft/2020-12/schema';
$data['$id'] = $urlGenerator->getAbsoluteURL($urlGenerator->linkToRoute('openregister.Schemas.show', ['id' => $this->getUuid()]));


return json_decode(json_encode($data));
}
}
8 changes: 5 additions & 3 deletions lib/Db/SchemaMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,11 @@ public function updateFromArray(int $id, array $object): Schema
$obj->hydrate($object);

// Set or update the version
$version = explode('.', $obj->getVersion());
$version[2] = (int)$version[2] + 1;
$obj->setVersion(implode('.', $version));
if (isset($object['version']) === false) {
$version = explode('.', $obj->getVersion());
$version[2] = (int)$version[2] + 1;
$obj->setVersion(implode('.', $version));
}

return $this->update($obj);
}
Expand Down
10 changes: 6 additions & 4 deletions lib/Db/SourceMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

/**
* The SourceMapper class
*
*
* @package OCA\OpenRegister\Db
*/
class SourceMapper extends QBMapper
Expand Down Expand Up @@ -116,9 +116,11 @@ public function updateFromArray(int $id, array $object): Source
$obj->hydrate($object);

// Set or update the version
$version = explode('.', $obj->getVersion());
$version[2] = (int)$version[2] + 1;
$obj->setVersion(implode('.', $version));
if (isset($object['version']) === false) {
$version = explode('.', $obj->getVersion());
$version[2] = (int)$version[2] + 1;
$obj->setVersion(implode('.', $version));
}

return $this->update($obj);
}
Expand Down
Loading