Skip to content

Commit

Permalink
feat(Contexts): accept nodes in context update endpoint
Browse files Browse the repository at this point in the history
- includes a fix to also show pages that have no content

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
  • Loading branch information
blizzz committed Mar 11, 2024
1 parent 0d141de commit 1a4fcd2
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 11 deletions.
11 changes: 9 additions & 2 deletions lib/Controller/ContextController.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,16 @@ public function create(string $name, string $iconName, string $description = '',
* @NoAdminRequired
* @CanManageContext
*/
public function update(int $contextId, ?string $name, ?string $iconName, ?string $description): DataResponse {
public function update(int $contextId, ?string $name, ?string $iconName, ?string $description, ?array $nodes): DataResponse {
try {
return new DataResponse($this->contextService->update($contextId, $name, $iconName, $description)->jsonSerialize());
return new DataResponse($this->contextService->update(
$contextId,
$this->userId,
$name,
$iconName,
$description,
$nodes,
)->jsonSerialize());
} catch (Exception|MultipleObjectsReturnedException $e) {
return $this->handleError($e);
} catch (DoesNotExistException $e) {
Expand Down
14 changes: 8 additions & 6 deletions lib/Db/ContextMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ protected function getFindContextBaseQuery(?string $userId): IQueryBuilder {
$qb->select(
'c.*',
'r.id as node_rel_id', 'r.node_id', 'r.node_type', 'r.permissions',
'p.page_type',
'pc.id as content_id', 'pc.page_id', 'pc.order',
'p.id as page_id', 'p.page_type',
'pc.id as content_id', 'pc.order',
'n.display_mode as display_mode_default',
's.id as share_id', 's.receiver', 's.receiver_type'
)
Expand Down Expand Up @@ -119,10 +119,12 @@ protected function formatResultRows(array $rows, ?string $userId) {
}
$carry[$item['page_id']]['id'] = $item['page_id'];
$carry[$item['page_id']]['page_type'] = $item['page_type'];
$carry[$item['page_id']]['content'][$item['content_id']] = [
'order' => $item['order'],
'node_rel_id' => $item['node_rel_id']
];
if ($item['node_rel_id'] !== null) {
$carry[$item['page_id']]['content'][$item['content_id']] = [
'order' => $item['order'],
'node_rel_id' => $item['node_rel_id']
];
}

return $carry;
}, []);
Expand Down
96 changes: 93 additions & 3 deletions lib/Service/ContextService.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ public function create(string $name, string $iconName, string $description, arra
* @throws DoesNotExistException
* @throws MultipleObjectsReturnedException
*/
public function update(int $contextId, ?string $name, ?string $iconName, ?string $description): Context {
$context = $this->contextMapper->findById($contextId);
public function update(int $contextId, string $userId, ?string $name, ?string $iconName, ?string $description, ?array $nodes): Context {
$context = $this->contextMapper->findById($contextId, $userId);

if ($name !== null) {
$context->setName(trim($name));
Expand All @@ -133,7 +133,75 @@ public function update(int $contextId, ?string $name, ?string $iconName, ?string
$context->setDescription(trim($description));
}

return $this->contextMapper->update($context);
$hasUpdatedNodeInformation = false;
if ($nodes !== null) {
$currentNodes = $context->getNodes();
$currentPages = $context->getPages();

$nodesBeingRemoved = [];
$nodesBeingAdded = [];
$nodesBeingKept = [];

// new node relationships do not have an ID. We can recognize them
// through their nodeType and nodeIds. For this we need to transform
// the known relationships` keys to a compatible format.
$oldNodeResolvableIdMapper = [];
foreach ($currentNodes as $i => $oldNode) {
$key = sprintf('t%di%d', $oldNode['node_type'], $oldNode['node_id']);
$oldNodeResolvableIdMapper[$key] = $i;
}

foreach ($nodes as $node) {
$key = sprintf('t%di%d', $node['type'], $node['id']);
if (isset($oldNodeResolvableIdMapper[$key])) {
unset($oldNodeResolvableIdMapper[$key]);
$nodesBeingKept[$key] = $node;
continue;
}
$nodesBeingAdded[$key] = $node;
}

foreach (array_diff_key($oldNodeResolvableIdMapper, $nodesBeingAdded, $nodesBeingKept) as $toRemoveId) {
$nodesBeingRemoved[$toRemoveId] = $currentNodes[$toRemoveId];
}
unset($nodesBeingKept);

$hasUpdatedNodeInformation = !empty($nodesBeingAdded) || !empty($nodesBeingRemoved);

foreach ($nodesBeingRemoved as $node) {
/** @var ContextNodeRelation $removedNode */
/** @var PageContent[] $removedContents */
[$removedNode, $removedContents] = $this->removeNodeFromContextAndPages($node['id']);
foreach ($removedContents as $removedContent) {
unset($currentPages[$removedContent->getPageId()]['content'][$removedContent->getId()]);
}
unset($currentNodes[$removedNode->getId()]);
}
unset($nodesBeingRemoved);

foreach ($nodesBeingAdded as $node) {
/** @var ContextNodeRelation $addedNode */
/** @var PageContent $updatedContent */
[$addedNode, $updatedContent] = $this->addNodeToContextAndStartpage(
$contextId,
$node['id'],
$node['type'],
$node['permissions'],
$node['order'] ?? 100,
$userId
);
$currentNodes[$addedNode->getId()] = $addedNode->jsonSerialize();
$currentPages[$updatedContent->getPageId()]['content'][$updatedContent->getId()] = $updatedContent->jsonSerialize();
}
unset($nodesBeingAdded);
}

$context = $this->contextMapper->update($context);
if ($hasUpdatedNodeInformation && isset($currentNodes) && isset($currentPages)) {
$context->setNodes($currentNodes);
$context->setPages($currentPages);
}
return $context;
}

/**
Expand Down Expand Up @@ -198,6 +266,28 @@ public function removeNodeFromContextById(int $nodeRelationId): ContextNodeRelat
return $this->contextNodeRelMapper->delete($nodeRelation);
}

/**
* @throws MultipleObjectsReturnedException
* @throws DoesNotExistException
* @throws Exception
*/
public function addNodeToContextAndStartpage(int $contextId, int $nodeId, int $nodeType, int $permissions, int $order, string $userId): array {
$relation = $this->addNodeToContextById($contextId, $nodeId, $nodeType, $permissions, $userId);
$pageContent = $this->addNodeRelToPage($relation, $order);
return [$relation, $pageContent];
}

/**
* @throws DoesNotExistException
* @throws MultipleObjectsReturnedException
* @throws Exception
*/
public function removeNodeFromContextAndPages(int $nodeRelationId): array {
$nodeRelation = $this->removeNodeFromContextById($nodeRelationId);
$contents = $this->removeNodeRelFromAllPages($nodeRelation);
return [$nodeRelation, $contents];
}

/**
* @throws Exception
*/
Expand Down

0 comments on commit 1a4fcd2

Please sign in to comment.