Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 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
3 changes: 3 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use OCA\Tables\Event\TableDeletedEvent;
use OCA\Tables\Event\TableOwnershipTransferredEvent;
use OCA\Tables\Event\ViewDeletedEvent;
use OCA\Tables\TablesMigrator;
use OCA\Tables\Listener\AddMissingIndicesListener;
use OCA\Tables\Listener\AnalyticsDatasourceListener;
use OCA\Tables\Listener\BeforeTemplateRenderedListener;
Expand Down Expand Up @@ -94,6 +95,8 @@ public function register(IRegistrationContext $context): void {

$context->registerMiddleware(PermissionMiddleware::class);
$context->registerMiddleware(ShareControlMiddleware::class);

$context->registerUserMigrator(TablesMigrator::class);
}

public function boot(IBootContext $context): void {
Expand Down
18 changes: 18 additions & 0 deletions lib/Db/ColumnMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,22 @@ public function preloadColumns(array $columns, ?array $filters = null, ?array $s
private function getCacheKey(int $id): string {
return 'column_' . $id;
}

/**
* @param int[] $tableIds
*
* @return Column[]
*/
public function findAllByTableIds(array $tableIds): array {
if (empty($tableIds)) {
return [];
}

$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->table)
->where($qb->expr()->in('table_id', $qb->createNamedParameter($tableIds, IQueryBuilder::PARAM_INT_ARRAY)));

return $this->findEntities($qb);
}
}
31 changes: 31 additions & 0 deletions lib/Db/RowCellBulkFetchTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Tables\Db;

use OCP\DB\QueryBuilder\IQueryBuilder;

trait RowCellBulkFetchTrait {
/**
* @param int[] $rowIds
* @param int[] $columnIds
*
* @return array
*/
public function findAllByRowIdsAndColumnIds(array $rowIds, array $columnIds): array {
if (empty($rowIds) || empty($columnIds)) {
return [];
}
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->table)
->where($qb->expr()->in('row_id', $qb->createNamedParameter($rowIds, IQueryBuilder::PARAM_INT_ARRAY)))
->andWhere($qb->expr()->in('column_id', $qb->createNamedParameter($columnIds, IQueryBuilder::PARAM_INT_ARRAY)));

return $this->findEntities($qb);
}
}
3 changes: 3 additions & 0 deletions lib/Db/RowCellDatetimeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
namespace OCA\Tables\Db;

use OCP\IDBConnection;
use OCA\Tables\Db\RowCellBulkFetchTrait;

/** @template-extends RowCellMapperSuper<RowCellDatetime, string, string> */
class RowCellDatetimeMapper extends RowCellMapperSuper {
use RowCellBulkFetchTrait;

protected string $table = 'tables_row_cells_datetime';

public function __construct(IDBConnection $db) {
Expand Down
3 changes: 3 additions & 0 deletions lib/Db/RowCellNumberMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@

use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCA\Tables\Db\RowCellBulkFetchTrait;

/** @template-extends RowCellMapperSuper<RowCellNumber, int|float|null, int|float|null> */
class RowCellNumberMapper extends RowCellMapperSuper {
use RowCellBulkFetchTrait;

protected string $table = 'tables_row_cells_number';

public function __construct(IDBConnection $db) {
Expand Down
3 changes: 3 additions & 0 deletions lib/Db/RowCellSelectionMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
namespace OCA\Tables\Db;

use OCP\IDBConnection;
use OCA\Tables\Db\RowCellBulkFetchTrait;

/**
* @template-extends RowCellMapperSuper<RowCellSelection, string, string|array>
*/
class RowCellSelectionMapper extends RowCellMapperSuper {
use RowCellBulkFetchTrait;

protected string $table = 'tables_row_cells_selection';

public function __construct(IDBConnection $db) {
Expand Down
3 changes: 3 additions & 0 deletions lib/Db/RowCellTextMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
namespace OCA\Tables\Db;

use OCP\IDBConnection;
use OCA\Tables\Db\RowCellBulkFetchTrait;

/** @template-extends RowCellMapperSuper<RowCellText, string, string> */
class RowCellTextMapper extends RowCellMapperSuper {
use RowCellBulkFetchTrait;

protected string $table = 'tables_row_cells_text';

public function __construct(IDBConnection $db) {
Expand Down
3 changes: 3 additions & 0 deletions lib/Db/RowCellUsergroupMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@
use OCA\Tables\Constants\UsergroupType;
use OCA\Tables\Helper\CircleHelper;
use OCA\Tables\Helper\GroupHelper;
use OCA\Tables\Db\RowCellBulkFetchTrait;
use OCP\IDBConnection;
use OCP\IUserManager;
use OCP\IUserSession;

/** @template-extends RowCellMapperSuper<RowCellUsergroup, array, array> */
class RowCellUsergroupMapper extends RowCellMapperSuper {
use RowCellBulkFetchTrait;

protected string $table = 'tables_row_cells_usergroup';

public function __construct(
Expand Down
16 changes: 16 additions & 0 deletions lib/Db/RowSleeveMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,20 @@ public function countRows(int $tableId): int {
return 0;
}
}

/**
* @param int[] $tableIds
*
* @return RowSleeve[]
*/
public function findAllByTableIds(array $tableIds): array {
if (empty($tableIds)) {
return [];
}
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->table)
->where($qb->expr()->in('table_id', $qb->createNamedParameter($tableIds, IQueryBuilder::PARAM_INT_ARRAY)));
return $this->findEntities($qb);
}
}
33 changes: 33 additions & 0 deletions lib/Db/ShareMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,37 @@ public function deleteByNode(int $nodeId, string $nodeType):void {
->andWhere($qb->expr()->eq('node_type', $qb->createNamedParameter($nodeType, IQueryBuilder::PARAM_STR)))
->executeStatement();
}

/**
* @param int[] $tableIds
* @param int[] $contextIds
*
* @return Share[]
*/
// add better function name
public function findByNodeIdsAndTypes(array $tableIds, array $contextIds): array {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->table);

$orX = $qb->expr()->orX();
if (!empty($tableIds)) {
$orX->add(
$qb->expr()->andX(
$qb->expr()->eq('node_type', $qb->createNamedParameter('table', IQueryBuilder::PARAM_STR)),
$qb->expr()->in('node_id', $qb->createNamedParameter($tableIds, IQueryBuilder::PARAM_INT_ARRAY))
)
);
}
if (!empty($contextIds)) {
$orX->add(
$qb->expr()->andX(
$qb->expr()->eq('node_type', $qb->createNamedParameter('context', IQueryBuilder::PARAM_STR)),
$qb->expr()->in('node_id', $qb->createNamedParameter($contextIds, IQueryBuilder::PARAM_INT_ARRAY))
)
);
}
$qb->where($orX);
return $this->findEntities($qb);
}
}
4 changes: 4 additions & 0 deletions lib/Db/TableMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,8 @@ public function insert(Entity $entity): Table {
$this->cache[(string)$entity->getId()] = $entity;
return $entity;
}

public function getDbConnection() {
return $this->db;
}
}
52 changes: 52 additions & 0 deletions lib/Service/ColumnService.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Exception;
use OCA\Tables\Db\Column;
use OCA\Tables\Db\ColumnMapper;
use OCA\Tables\Db\Table;
use OCA\Tables\Db\TableMapper;
use OCA\Tables\Db\View;
use OCA\Tables\Dto\Column as ColumnDto;
Expand Down Expand Up @@ -558,4 +559,55 @@ private function enhanceColumns(?array $columns, ?View $view = null): array {
}
return $columns;
}

/**
* @param Table $table
* @param array $column
*
* @return Column
*
* @throws InternalError
*/
public function importColumn(Table $table, array $column): Column
{
$item = new Column();
$item->setTableId($table->getId());
$item->setTitle($column['title']);
Copy link
Member

Choose a reason for hiding this comment

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

I'm not 100% sure with the abstraction layers in the tables app but you could probably shorten this by using https://github.com/nextcloud/server/blob/master/lib/public/AppFramework/Db/Entity.php#L51-L62

$item = Column::fromRow($column);

Please verify though, setTableId may need separate handling still.

Copy link
Author

Choose a reason for hiding this comment

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

@juliusknorr will do.

$item->setCreatedBy($column['createdBy']);
$item->setCreatedAt($column['createdAt']);
$item->setLastEditBy($column['lastEditBy']);
$item->setLastEditAt($column['lastEditAt']);
$item->setType($column['type']);
$item->setSubtype($column['subtype']);
$item->setMandatory($column['mandatory']);
$item->setDescription($column['description']);
$item->setNumberDefault($column['numberDefault']);
$item->setNumberMin($column['numberMin']);
$item->setNumberMax($column['numberMax']);
$item->setNumberDecimals($column['numberDecimals']);
$item->setNumberPrefix($column['numberPrefix']);
$item->setNumberSuffix($column['numberSuffix']);
$item->setTextDefault($column['textDefault']);
$item->setTextAllowedPattern($column['textAllowedPattern']);
$item->setTextMaxLength($column['textMaxLength']);
$item->setTextUnique($column['textUnique']);
$item->setSelectionOptions(json_encode($column['selectionOptions']));
$item->setSelectionDefault($column['selectionDefault']);
$item->setDatetimeDefault($column['datetimeDefault']);
$item->setUsergroupDefault(json_encode($column['usergroupDefault']));
$item->setUsergroupMultipleItems($column['usergroupMultipleItems']);
$item->setUsergroupSelectUsers($column['usergroupSelectUsers']);
$item->setUsergroupSelectGroups($column['usergroupSelectGroups']);
$item->setUsergroupSelectTeams($column['usergroupSelectTeams']);
$item->setShowUserStatus($column['showUserStatus']);
$item->setCustomSettings(json_encode($column['customSettings']));

try {
$newColumn = $this->mapper->insert($item);
} catch (\Exception $e) {
$this->logger->error('importColumn insert error: ' . $e->getMessage());
throw new InternalError('importColumn insert error: ' . $e->getMessage());
}
return $newColumn;
}
}
76 changes: 76 additions & 0 deletions lib/Service/ContextService.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use OCA\Tables\Db\PageContent;
use OCA\Tables\Db\PageContentMapper;
use OCA\Tables\Db\PageMapper;
use OCA\Tables\Db\Table;
use OCA\Tables\Errors\BadRequestError;
use OCA\Tables\Errors\InternalError;
use OCA\Tables\Errors\NotFoundError;
Expand Down Expand Up @@ -508,4 +509,79 @@ protected function insertNodesFromArray(Context $context, array $nodes): void {
}
$context->setNodes($addedNodes);
}

/**
* @param Table $table
* @param array $context
* @param int $tableOldId
*
* @return Context|null
*
* @throws \Exception
*/
public function importContext(Table $table, array $context, int $tableOldId): ?Context {
// checking if any node in $context['nodes'] matches the old table id
$hasMatchingNode = false;
if (!empty($context['nodes'])) {
foreach ($context['nodes'] as $nodeArr) {
if (($nodeArr['node_id'] ?? null) == $tableOldId) {
$hasMatchingNode = true;
break;
}
}
}

if (!$hasMatchingNode) {
return null;
}

$newContext = new Context();
$newContext->setName($context['name'] ?? '');
$newContext->setIcon($context['iconName'] ?? '');
$newContext->setDescription($context['description'] ?? '');
$newContext->setOwnerId($context['owner'] ?? '');
Copy link
Member

Choose a reason for hiding this comment

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

If we import, do we set the old owner id? Or would be be needed to change this to the current user id of the importer instead? Same probably applies to other importers

Copy link
Author

Choose a reason for hiding this comment

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

@juliusknorr this was actually one of the final fixes im making, im going to actually check if the user exist and if not then use current logged in user, what do you think about that? or should we go straight with the current user?

Copy link
Member

Choose a reason for hiding this comment

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

We should always use the user that is importing as the new owner (as I assume only your own tables/context are exported). The current logged in user may not work as I assume it is importing in a background job?

But I would guess there is a way to get the "target" user as part of the import process of the user_migration app

Copy link
Author

Choose a reason for hiding this comment

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

understandable, i'm currently working on that.

$newContext->setOwnerType($context['ownerType'] ?? 0);
$this->contextMapper->insert($newContext);

// insert nodes
$nodeRelMap = [];
if (!empty($context['nodes'])) {
foreach ($context['nodes'] as $nodeArr) {
$contextNodeRel = new ContextNodeRelation();
$contextNodeRel->setContextId($newContext->getId());
$contextNodeRel->setNodeId($table->getId());
$contextNodeRel->setNodeType($nodeArr['node_type'] ?? $nodeArr['nodeType'] ?? 0);
$contextNodeRel->setPermissions($nodeArr['permissions'] ?? 0);
$contextNodeRel = $this->contextNodeRelMapper->insert($contextNodeRel);
$nodeRelMap[$nodeArr['id'] ?? null] = $contextNodeRel;
}
}

// insert pages
$pageMap = [];
if (!empty($context['pages'])) {
foreach ($context['pages'] as $pageArr) {
$page = new Page();
$page->setContextId($newContext->getId());
$page->setPageType($pageArr['page_type'] ?? $pageArr['pageType'] ?? '');
$page = $this->pageMapper->insert($page);
$pageMap[$pageArr['id'] ?? null] = $page;

// insert page conten
if (!empty($pageArr['content'])) {
foreach ($pageArr['content'] as $contentArr) {
$pageContent = new PageContent();
$pageContent->setPageId($page->getId());
$oldNodeRelId = $contentArr['node_rel_id'] ?? $contentArr['nodeRelId'] ?? null;
$newNodeRel = $nodeRelMap[$oldNodeRelId] ?? null;
$pageContent->setNodeRelId($newNodeRel ? $newNodeRel->getId() : null);
$pageContent->setOrder($contentArr['order'] ?? 100);
$this->pageContentMapper->insert($pageContent);
}
}
}
}

return $newContext;
}
}
Loading
Loading