Skip to content

Commit

Permalink
Merge pull request #111 from ConductionNL/feature/REGISTERS-85/improv…
Browse files Browse the repository at this point in the history
…ed-developer-experience

Adtional functions for object service
  • Loading branch information
rubenvdlinde authored Dec 27, 2024
2 parents 5f9631f + 8186bcc commit c0f7ed3
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 52 deletions.
6 changes: 3 additions & 3 deletions lib/Db/AuditTrailMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,13 @@ public function findAll(?int $limit = null, ?int $offset = null, ?array $filters
/**
* Finds all audit trails for a given object
*
* @param string $idOrUuid The id or uuid of the object
* @param string $identifier The id or uuid of the object
* @return array The audit trails
*/
public function findAllUuid(string $idOrUuid, ?int $limit = null, ?int $offset = null, ?array $filters = [], ?array $searchConditions = [], ?array $searchParams = []): array
public function findAllUuid(string $identifier, ?int $limit = null, ?int $offset = null, ?array $filters = [], ?array $searchConditions = [], ?array $searchParams = []): array
{
try {
$object = $this->objectEntityMapper->find(idOrUuid: $idOrUuid);
$object = $this->objectEntityMapper->find(identifier: $identifier);
$objectId = $object->getId();
$filters['object'] = $objectId;
return $this->findAll($limit, $offset, $filters, $searchConditions, $searchParams);
Expand Down
7 changes: 4 additions & 3 deletions lib/Db/ObjectEntityMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,17 @@ public function __construct(IDBConnection $db, MySQLJsonService $mySQLJsonServic
* @param int|string $idOrUuid The ID or UUID of the object to find
* @return ObjectEntity The ObjectEntity
*/
public function find($idOrUuid): ObjectEntity
public function find($identifier): ObjectEntity
{
$qb = $this->db->getQueryBuilder();

$qb->select('*')
->from('openregister_objects')
->where(
$qb->expr()->orX(
$qb->expr()->eq('id', $qb->createNamedParameter($idOrUuid, IQueryBuilder::PARAM_INT)),
$qb->expr()->eq('uuid', $qb->createNamedParameter($idOrUuid, IQueryBuilder::PARAM_STR))
$qb->expr()->eq('id', $qb->createNamedParameter($identifier, IQueryBuilder::PARAM_INT)),
$qb->expr()->eq('uuid', $qb->createNamedParameter($identifier, IQueryBuilder::PARAM_STR)),
$qb->expr()->eq('uri', $qb->createNamedParameter($identifier, IQueryBuilder::PARAM_STR))
)
);

Expand Down
203 changes: 157 additions & 46 deletions lib/Service/ObjectService.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use OCA\OpenRegister\Db\ObjectEntityMapper;
use OCA\OpenRegister\Db\AuditTrail;
use OCA\OpenRegister\Db\AuditTrailMapper;
use OCA\OpenRegister\Db\ObjectAuditLogMapper;
use OCA\OpenRegister\Exception\ValidationException;
use OCA\OpenRegister\Formats\BsnFormat;
use OCP\App\IAppManager;
Expand Down Expand Up @@ -67,6 +68,7 @@ public function __construct(
RegisterMapper $registerMapper,
SchemaMapper $schemaMapper,
AuditTrailMapper $auditTrailMapper,
ObjectAuditLogMapper $objectAuditLogMapper,
private ContainerInterface $container,
private readonly IURLGenerator $urlGenerator,
private readonly FileService $fileService,
Expand All @@ -77,6 +79,7 @@ public function __construct(
$this->registerMapper = $registerMapper;
$this->schemaMapper = $schemaMapper;
$this->auditTrailMapper = $auditTrailMapper;
$this->objectAuditLogMapper = $objectAuditLogMapper;
}

/**
Expand Down Expand Up @@ -130,10 +133,10 @@ public function validateObject(array $object, ?int $schemaId = null, object $sch
* @param int|string $id The ID or UUID to search for
* @param array|null $extend Properties to extend with related data
*
* @return ObjectEntity The found object
* @return ObjectEntity|null The found object or null if not found
* @throws Exception
*/
public function find(int|string $id, ?array $extend = []): ObjectEntity
public function find(int|string $id, ?array $extend = []): ?ObjectEntity
{
return $this->getObject(
register: $this->registerMapper->find($this->getRegister()),
Expand Down Expand Up @@ -223,7 +226,14 @@ public function delete(array|\JsonSerializable $object): bool
*
* @return array List of matching objects
*/
public function findAll(?int $limit = null, ?int $offset = null, array $filters = [], array $sort = [], ?string $search = null, ?array $extend = []): array
public function findAll(
?int $limit = null,
?int $offset = null,
array $filters = [],
array $sort = [],
?string $search = null,
?array $extend = []
): array
{
$objects = $this->getObjects(
register: $this->getRegister(),
Expand All @@ -235,6 +245,15 @@ public function findAll(?int $limit = null, ?int $offset = null, array $filters
search: $search
);

// If extend is provided, extend each object
if (!empty($extend)) {
$objects = array_map(function($object) use ($extend) {
// Convert object to array if needed
$objectArray = is_array($object) ? $object : $object->jsonSerialize();
return $this->extendEntity(entity: $objectArray, extend: $extend);
}, $objects);
}

return $objects;
}

Expand Down Expand Up @@ -406,7 +425,16 @@ public function findAllPaginated(array $requestParams): array
*
* @return array The retrieved objects.
*/
public function getObjects(?string $objectType = null, ?int $register = null, ?int $schema = null, ?int $limit = null, ?int $offset = null, array $filters = [], array $sort = [], ?string $search = null, ?array $extend = []): array
public function getObjects(
?string $objectType = null,
?int $register = null,
?int $schema = null,
?int $limit = null,
?int $offset = null,
array $filters = [],
array $sort = [],
?string $search = null
)
{
// Set object type and filters if register and schema are provided
if ($objectType === null && $register !== null && $schema !== null) {
Expand All @@ -419,7 +447,13 @@ public function getObjects(?string $objectType = null, ?int $register = null, ?i
$mapper = $this->getMapper($objectType);

// Use the mapper to find and return all objects of the specified type
return $mapper->findAll(limit: $limit, offset: $offset, filters: $filters, sort: $sort, search: $search);
return $mapper->findAll(
limit: $limit,
offset: $offset,
filters: $filters,
sort: $sort,
search: $search
);
}

/**
Expand All @@ -435,6 +469,11 @@ public function getObjects(?string $objectType = null, ?int $register = null, ?i
*/
public function saveObject(int $register, int $schema, array $object): ObjectEntity
{
// Remove system properties (starting with _)
$object = array_filter($object, function($key) {
return !str_starts_with($key, '_');
}, ARRAY_FILTER_USE_KEY);

// Convert register and schema to their respective objects if they are strings // @todo ???
if (is_string($register)) {
$register = $this->registerMapper->find($register);
Expand All @@ -453,8 +492,6 @@ public function saveObject(int $register, int $schema, array $object): ObjectEnt
);
}

// $validationResult = $this->validateObject(object: $object, schemaId: $schema);

// Create new entity if none exists
if (isset($object['id']) === false || $objectEntity === null) {
$objectEntity = new ObjectEntity();
Expand Down Expand Up @@ -482,26 +519,22 @@ public function saveObject(int $register, int $schema, array $object): ObjectEnt
// Let grap any links that we can
$objectEntity = $this->handleLinkRelations($objectEntity, $object);

$schemaObject = $this->schemaMapper->find($schema);
$schemaObject = $this->schemaMapper->find($schema);

// Handle object properties that are either nested objects or files
if ($schemaObject->getProperties() !== null && is_array($schemaObject->getProperties()) === true) {
$objectEntity = $this->handleObjectRelations($objectEntity, $object, $schemaObject->getProperties(), $register, $schema);
}

$objectEntity->setUri($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute('openregister.Objects.show', ['id' => $objectEntity->getUuid()])));
$objectEntity->setUri($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute('openregister.Objects.show', ['id' => $objectEntity->getUuid()])));

if ($objectEntity->getId()) {// && ($schemaObject->getHardValidation() === false || $validationResult->isValid() === true)){
$objectEntity = $this->objectEntityMapper->update($objectEntity);
$this->auditTrailMapper->createAuditTrail(new: $objectEntity, old: $oldObject);
} else {//if ($schemaObject->getHardValidation() === false || $validationResult->isValid() === true) {
$objectEntity = $this->objectEntityMapper->insert($objectEntity);
$this->auditTrailMapper->createAuditTrail(new: $objectEntity);
}

// if ($validationResult->isValid() === false) {
// throw new ValidationException(message: 'The object could not be validated', errors: $validationResult->error());
// }
if ($objectEntity->getId()) {
$objectEntity = $this->objectEntityMapper->update($objectEntity);
$this->auditTrailMapper->createAuditTrail(new: $objectEntity, old: $oldObject);
} else {
$objectEntity = $this->objectEntityMapper->insert($objectEntity);
$this->auditTrailMapper->createAuditTrail(new: $objectEntity);
}

return $objectEntity;
}
Expand Down Expand Up @@ -824,12 +857,11 @@ private function handleFileProperty(ObjectEntity $objectEntity, array $object, s
* @param string $uuid The UUID of the object to get
* @param array $extend Properties to extend with related data
*
* @return ObjectEntity The resulting object
* @return ObjectEntity|null The resulting object or null if not found
* @throws Exception If source type is unsupported
*/
public function getObject(Register $register, Schema $schema, string $uuid, ?array $extend = []): ObjectEntity
public function getObject(Register $register, Schema $schema, string $uuid, ?array $extend = []): ?ObjectEntity
{

// Handle internal source
if ($register->getSource() === 'internal' || $register->getSource() === '') {
return $this->objectEntityMapper->findByUuid($register, $schema, $uuid);
Expand Down Expand Up @@ -981,7 +1013,7 @@ public function renderEntity(array $entity, ?array $extend = []): array
* @param mixed $entity The entity to extend
* @param array $extend Properties to extend with related data
* @return array The extended entity as an array
* @throws Exception If property not found or no mapper available
* @throws Exception If property not found
*/
public function extendEntity(array $entity, array $extend): array
{
Expand Down Expand Up @@ -1009,26 +1041,48 @@ public function extendEntity(array $entity, array $extend): array
}

// Try to get mapper for property
$propertyObject = $property;
try {
$mapper = $this->getMapper(objectType: $property);
$propertyObject = $singularProperty;

// Extend with related objects using specific mapper
if (is_array($value) === true) {
$result[$property] = $this->getMultipleObjects(objectType: $propertyObject, ids: $value);
} else {
$objectId = is_object(value: $value) ? $value->getId() : $value;
$result[$property] = $mapper->find($objectId);
}
} catch (Exception $e) {
// If no specific mapper found, try to look up values in default database
try {
$mapper = $this->getMapper(objectType: $singularProperty);
$propertyObject = $singularProperty;
} catch (Exception $e) {
throw new Exception("No mapper available for property '$property'.");
if (is_array($value)) {
// Handle array of values
$extendedValues = [];
foreach ($value as $val) {
try {
$found = $this->objectEntityMapper->find($val);
if ($found) {
$extendedValues[] = $found;
}
} catch (Exception $e) {
continue;
}
}
if (!empty($extendedValues)) {
$result[$property] = $extendedValues;
}
} else {
// Handle single value
$found = $this->objectEntityMapper->find($value);
if ($found) {
$result[$property] = $found;
}
}
} catch (Exception $e2) {
// If lookup fails, keep original value
continue;
}
}

// Extend with related objects
if (is_array($value) === true) {
$result[$property] = $this->getMultipleObjects(objectType: $propertyObject, ids: $value);
} else {
$objectId = is_object(value: $value) ? $value->getId() : $value;
$result[$property] = $mapper->find($objectId);
}
}

return $result;
Expand Down Expand Up @@ -1104,19 +1158,76 @@ public function setSchema(int $schema): void
/**
* Get the audit trail for a specific object
*
* @todo: register and schema parameters are not needed anymore
*
* @param int $register The register ID
* @param int $schema The schema ID
* @param string $id The object ID
* @param int|null $register Optional register ID to override current register
* @param int|null $schema Optional schema ID to override current schema
* @return array The audit trail entries
*/
public function getAuditTrail(int $register, int $schema, string $id): array
public function getAuditTrail(string $id, ?int $register = null, ?int $schema = null): array
{
// Get the object to get its URI and UUID
$object = $this->find($id);

// @todo this is not working, it fails to find the logs
$auditTrails = $this->auditTrailMapper->findAll(filters: ['object' => $object->getId()]);

return $auditTrails;
}

/**
* Get all relations for a specific object
* Returns objects that link to this object (incoming references)
*
* @param string $id The object ID
* @param int|null $register Optional register ID to override current register
* @param int|null $schema Optional schema ID to override current schema
* @return array The objects that reference this object
*/
public function getRelations(string $id, ?int $register = null, ?int $schema = null): array
{
$register = $register ?? $this->getRegister();
$schema = $schema ?? $this->getSchema();

// Get the object to get its URI and UUID
$object = $this->find($id);

// Find objects that reference this object's URI or UUID
$referencingObjects = $this->objectEntityMapper->findByRelationUri(
search: $object->getUuid(),
partialMatch: true
);

// Filter out self-references if any
return array_filter($referencingObjects, function($referencingObject) use ($id) {
return $referencingObject->getUuid() !== $id;
});
}

/**
* Get all uses of a specific object
* Returns objects that this object links to (outgoing references)
*
* @param string $id The object ID
* @param int|null $register Optional register ID to override current register
* @param int|null $schema Optional schema ID to override current schema
* @return array The objects this object references
*/
public function getUses(string $id, ?int $register = null, ?int $schema = null): array
{
$filters = [
'object' => $id
];
// First get the object to access its relations
$object = $this->find($id);
$relations = $object->getRelations() ?? [];

// Get all referenced objects
$referencedObjects = [];
foreach ($relations as $path => $relationId) {
$referencedObjects[$path] = $this->objectEntityMapper->find($relationId);

if($referencedObjects[$path] === null){
$referencedObjects[$path] = $relationId;
}
}

return $this->auditTrailMapper->findAllUuid(idOrUuid: $id);
return $referencedObjects;
}
}

0 comments on commit c0f7ed3

Please sign in to comment.