diff --git a/appinfo/routes.php b/appinfo/routes.php index 1e73a64dc..1246d6bc6 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -126,5 +126,7 @@ ['name' => 'Context#index', 'url' => '/api/2/contexts', 'verb' => 'GET'], ['name' => 'Context#show', 'url' => '/api/2/contexts/{contextId}', 'verb' => 'GET'], + ['name' => 'Context#create', 'url' => '/api/2/contexts', 'verb' => 'POST'], + ] ]; diff --git a/lib/Controller/ContextController.php b/lib/Controller/ContextController.php index 5a09ab0b4..d9dafa229 100644 --- a/lib/Controller/ContextController.php +++ b/lib/Controller/ContextController.php @@ -73,6 +73,27 @@ public function show(int $contextId): DataResponse { } } + /** + * [api v2] Create a new context and return it + * + * @NoAdminRequired + * + * @param string $title Title of the table + * @param string|null $emoji Emoji for the table + * @param string $template Template to use if wanted + * + * @return DataResponse|DataResponse + * + * 200: Tables returned + */ + public function create(string $name, string $iconName, string $description = '', array $nodes = []): DataResponse { + try { + return new DataResponse($this->contextService->create($name, $iconName, $description, $nodes, $this->userId, 0)->jsonSerialize()); + } catch (InternalError|Exception $e) { + return $this->handleError($e); + } + } + /** * @param Context[] $contexts * @return array diff --git a/lib/Db/ContextNodeRelation.php b/lib/Db/ContextNodeRelation.php new file mode 100644 index 000000000..972b868de --- /dev/null +++ b/lib/Db/ContextNodeRelation.php @@ -0,0 +1,40 @@ +addType('id', 'integer'); + } + + public function jsonSerialize(): array { + return [ + 'id' => $this->getId(), + 'contextId' => $this->getContextId(), + 'nodeId' => $this->getNodeId(), + 'nodeType' => $this->getNodeType(), + 'permissions' => $this->getPermissions() + ]; + } +} + diff --git a/lib/Db/ContextNodeRelationMapper.php b/lib/Db/ContextNodeRelationMapper.php new file mode 100644 index 000000000..af2f628da --- /dev/null +++ b/lib/Db/ContextNodeRelationMapper.php @@ -0,0 +1,17 @@ +table, ContextNodeRelation::class); + } + +} diff --git a/lib/Db/Page.php b/lib/Db/Page.php new file mode 100644 index 000000000..a7757fb1e --- /dev/null +++ b/lib/Db/Page.php @@ -0,0 +1,32 @@ +addType('id', 'integer'); + } + + public function jsonSerialize(): array { + return [ + 'id' => $this->getId(), + 'contextId' => $this->getContextId(), + 'pageType' => $this->getPageType(), + ]; + } +} diff --git a/lib/Db/PageContent.php b/lib/Db/PageContent.php new file mode 100644 index 000000000..45bb1e735 --- /dev/null +++ b/lib/Db/PageContent.php @@ -0,0 +1,34 @@ +addType('id', 'integer'); + } + + public function jsonSerialize(): array { + return [ + 'id' => $this->getId(), + 'pageId' => $this->getPageId(), + 'nodeRelId' => $this->getNodeRelId(), + 'order' => $this->getOrder(), + ]; + } +} diff --git a/lib/Db/PageContentMapper.php b/lib/Db/PageContentMapper.php new file mode 100644 index 000000000..9674291fa --- /dev/null +++ b/lib/Db/PageContentMapper.php @@ -0,0 +1,14 @@ +table, ContextNodeRelation::class); + } +} diff --git a/lib/Db/PageMapper.php b/lib/Db/PageMapper.php new file mode 100644 index 000000000..60d77eecf --- /dev/null +++ b/lib/Db/PageMapper.php @@ -0,0 +1,14 @@ +table, ContextNodeRelation::class); + } +} diff --git a/lib/Service/ContextService.php b/lib/Service/ContextService.php index 16790ebbd..c8161d059 100644 --- a/lib/Service/ContextService.php +++ b/lib/Service/ContextService.php @@ -4,32 +4,49 @@ namespace OCA\Tables\Service; +use OCA\Tables\AppInfo\Application; use OCA\Tables\Db\Context; use OCA\Tables\Db\ContextMapper; +use OCA\Tables\Db\ContextNodeRelation; +use OCA\Tables\Db\ContextNodeRelationMapper; +use OCA\Tables\Db\Page; +use OCA\Tables\Db\PageContent; +use OCA\Tables\Db\PageContentMapper; +use OCA\Tables\Db\PageMapper; use OCA\Tables\Errors\InternalError; use OCP\DB\Exception; use Psr\Log\LoggerInterface; +use function OCP\Log\logger; class ContextService { - private ContextMapper $mapper; + private ContextMapper $contextMapper; private bool $isCLI; private LoggerInterface $logger; + private ContextNodeRelationMapper $contextNodeRelMapper; + private PageMapper $pageMapper; + private PageContentMapper $pageContentMapper; public function __construct( - ContextMapper $mapper, - LoggerInterface $logger, - bool $isCLI, + ContextMapper $contextMapper, + ContextNodeRelationMapper $contextNodeRelationMapper, + PageMapper $pageMapper, + PageContentMapper $pageContentMapper, + LoggerInterface $logger, + bool $isCLI, ) { - $this->mapper = $mapper; + $this->contextMapper = $contextMapper; $this->isCLI = $isCLI; $this->logger = $logger; + $this->contextNodeRelMapper = $contextNodeRelationMapper; + $this->pageMapper = $pageMapper; + $this->pageContentMapper = $pageContentMapper; } /** - * @throws InternalError - * @throws Exception * @return Context[] + * @throws Exception + * @throws InternalError */ public function findAll(?string $userId): array { if ($userId !== null && trim($userId) === '') { @@ -40,7 +57,7 @@ public function findAll(?string $userId): array { $this->logger->warning($error); throw new InternalError($error); } - return $this->mapper->findAll($userId); + return $this->contextMapper->findAll($userId); } /** @@ -57,6 +74,76 @@ public function findById(int $id, ?string $userId): Context { throw new InternalError($error); } - return $this->mapper->findById($id, $userId); + return $this->contextMapper->findById($id, $userId); + } + + public function create(string $name, string $iconName, string $description, array $nodes, string $ownerId, int $ownerType): Context { + $context = new Context(); + $context->setName($name); + $context->setIcon($iconName); + $context->setDescription($description); + $context->setOwnerId($ownerId); + $context->setOwnerType($ownerType); + + $this->contextMapper->insert($context); + + if (!empty($nodes)) { + $context->resetUpdatedFields(); + $this->insertNodesFromArray($context, $nodes); + $this->insertPage($context); + } + + return $context; + } + + + protected function insertPage(Context $context) { + $page = new Page(); + $page->setContextId($context->getId()); + $page->setPageType(Page::TYPE_STARTPAGE); + $this->pageMapper->insert($page); + + $addedPage = $page->jsonSerialize(); + + $i = 1; + foreach ($context->getNodes() as $node) { + $pageContent = new PageContent(); + $pageContent->setPageId($page->getId()); + $pageContent->setNodeRelId($node['id']); + $pageContent->setOrder(10 * $i++); + + $this->pageContentMapper->insert($pageContent); + + $addedPage['content'][$pageContent->getId()] = $pageContent->jsonSerialize(); + // the content is already embedded in the page + unset($addedPage['content'][$pageContent->getId()]['pageId']); + } + + $context->setPages($addedPage); + } + + protected function insertNodesFromArray(Context $context, array $nodes) { + $addedNodes = []; + + foreach ($nodes as $node) { + $contextNodeRel = new ContextNodeRelation(); + $contextNodeRel->setContextId($context->getId()); + $contextNodeRel->setNodeId($node['id']); + $contextNodeRel->setNodeType($node['type']); + $contextNodeRel->setPermissions($node['permissions'] ?? 660); + + try { + $this->contextNodeRelMapper->insert($contextNodeRel); + $addedNodes[] = $contextNodeRel->jsonSerialize(); + } catch (Exception $e) { + logger(Application::APP_ID)->warning('Could not add node {ntype}/{nid} to context {cid}', [ + 'ntype' => $node['type'], + 'nid' => $node['id'], + 'cid' => $context['id'], + 'exception' => $e, + ]); + } + } + $context->setNodes($addedNodes); } }