Skip to content

Commit

Permalink
Merge pull request #865 from nextcloud/feat/archive-favorites
Browse files Browse the repository at this point in the history
feat: Add backend for table archive and favorite flag
  • Loading branch information
juliusknorr authored Mar 3, 2024
2 parents 25fd585 + 8c9fc70 commit b0e1534
Show file tree
Hide file tree
Showing 22 changed files with 787 additions and 58 deletions.
3 changes: 3 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,8 @@
['name' => 'ApiColumns#createTextColumn', 'url' => '/api/2/columns/text', 'verb' => 'POST'],
['name' => 'ApiColumns#createSelectionColumn', 'url' => '/api/2/columns/selection', 'verb' => 'POST'],
['name' => 'ApiColumns#createDatetimeColumn', 'url' => '/api/2/columns/datetime', 'verb' => 'POST'],

['name' => 'ApiFavorite#create', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'POST', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']],
['name' => 'ApiFavorite#destroy', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'DELETE', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']],
]
];
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"lint": "find . -name \\*.php -not -path './vendor/*' -not -path './build/*' -print0 | xargs -0 -n1 php -l",
"cs:check": "php-cs-fixer fix --dry-run --diff",
"cs:fix": "php-cs-fixer fix",
"psalm": "./vendor/bin/psalm.phar --show-info=true --no-cache",
"psalm": "./vendor/bin/psalm.phar --show-info=false --no-cache",
"psalm:update-baseline": "./vendor/bin/psalm.phar --update-baseline",
"psalm:fix": "./vendor/bin/psalm.phar --no-cache --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType",
"psalm:fix:dry": "./vendor/bin/psalm.phar --no-cache --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType --dry-run",
Expand Down
6 changes: 5 additions & 1 deletion lib/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function __construct(IAppManager $appManager, LoggerInterface $logger, IC

/**
*
* @return array{tables: array{enabled: bool, version: string, apiVersions: string[], column_types: string[]}}
* @return array{tables: array{enabled: bool, version: string, apiVersions: string[], features: string[], column_types: string[]}}
*
* @inheritDoc
*/
Expand All @@ -63,6 +63,10 @@ public function getCapabilities(): array {
'apiVersions' => [
'1.0'
],
'features' => [
'favorite',
'archive',
],
'column_types' => [
'text-line',
$textColumnVariant,
Expand Down
12 changes: 10 additions & 2 deletions lib/Command/RenameTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ public function __construct(TableService $tableService, LoggerInterface $logger)

protected function configure(): void {
$this
->setName('tables:rename')
->setName('tables:update')
->setAliases(['tables:rename'])
->setDescription('Rename a table.')
->addArgument(
'ID',
Expand All @@ -62,6 +63,12 @@ protected function configure(): void {
InputOption::VALUE_OPTIONAL,
'New emoji.'
)
->addOption(
'archived',
'a',
InputOption::VALUE_NONE,
'Archived'
)
;
}

Expand All @@ -74,9 +81,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$id = $input->getArgument('ID');
$title = $input->getArgument('title');
$emoji = $input->getOption('emoji');
$archived = $input->getOption('archived');

try {
$table = $this->tableService->update($id, $title, $emoji, '');
$table = $this->tableService->update($id, $title, $emoji, $archived, '');

$arr = $table->jsonSerialize();
unset($arr['hasShares']);
Expand Down
4 changes: 2 additions & 2 deletions lib/Controller/Api1Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,9 @@ public function getTable(int $tableId): DataResponse {
* 403: No permissions
* 404: Not found
*/
public function updateTable(int $tableId, string $title = null, string $emoji = null): DataResponse {
public function updateTable(int $tableId, string $title = null, string $emoji = null, ?bool $archived = false): DataResponse {
try {
return new DataResponse($this->tableService->update($tableId, $title, $emoji, $this->userId)->jsonSerialize());
return new DataResponse($this->tableService->update($tableId, $title, $emoji, $archived, $this->userId)->jsonSerialize());
} catch (PermissionError $e) {
$this->logger->warning('A permission error occurred: ' . $e->getMessage());
$message = ['message' => $e->getMessage()];
Expand Down
86 changes: 86 additions & 0 deletions lib/Controller/ApiFavoriteController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

declare(strict_types=1);

namespace OCA\Tables\Controller;

use Exception;
use OCA\Tables\Errors\InternalError;
use OCA\Tables\Errors\NotFoundError;
use OCA\Tables\Errors\PermissionError;
use OCA\Tables\ResponseDefinitions;
use OCA\Tables\Service\FavoritesService;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\DB\Exception as DBException;
use OCP\IL10N;
use OCP\IRequest;
use Psr\Log\LoggerInterface;

/**
* @psalm-import-type TablesTable from ResponseDefinitions
*/
class ApiFavoriteController extends AOCSController {
private FavoritesService $service;

public function __construct(
IRequest $request,
LoggerInterface $logger,
FavoritesService $service,
IL10N $n,
string $userId) {
parent::__construct($request, $logger, $n, $userId);
$this->service = $service;
}

/**
* [api v2] Add a node (table or view) to user favorites
*
* @NoAdminRequired
*
* @param int $nodeType
* @param int $nodeId
* @return DataResponse<Http::STATUS_OK, array{}, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
*
* 200: Tables returned
*/
public function create(int $nodeType, int $nodeId): DataResponse {
try {
$this->service->addFavorite($nodeType, $nodeId);
return new DataResponse();
} catch (NotFoundError $e) {
return $this->handleNotFoundError($e);
} catch (PermissionError $e) {
return $this->handlePermissionError($e);
} catch (InternalError|DBException|Exception $e) {
return $this->handleError($e);
}
}


/**
* [api v2] Remove a node (table or view) to from favorites
*
* @NoAdminRequired
*
* @param int $nodeType
* @param int $nodeId
* @return DataResponse<Http::STATUS_OK, array{}, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
*
* 200: Deleted table returned
* 403: No permissions
* 404: Not found
*/
public function destroy(int $nodeType, int $nodeId): DataResponse {
try {
$this->service->removeFavorite($nodeType, $nodeId);
return new DataResponse();
} catch (NotFoundError $e) {
return $this->handleNotFoundError($e);
} catch (PermissionError $e) {
return $this->handlePermissionError($e);
} catch (InternalError|DBException|Exception $e) {
return $this->handleError($e);
}
}
}
4 changes: 2 additions & 2 deletions lib/Controller/ApiTablesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ public function create(string $title, ?string $emoji, string $template = 'custom
* 403: No permissions
* 404: Not found
*/
public function update(int $id, string $title = null, string $emoji = null): DataResponse {
public function update(int $id, ?string $title = null, ?string $emoji = null, ?bool $archived = null): DataResponse {
try {
return new DataResponse($this->service->update($id, $title, $emoji, $this->userId)->jsonSerialize());
return new DataResponse($this->service->update($id, $title, $emoji, $archived, $this->userId)->jsonSerialize());
} catch (PermissionError $e) {
return $this->handlePermissionError($e);
} catch (InternalError $e) {
Expand Down
6 changes: 3 additions & 3 deletions lib/Controller/TableController.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ public function destroy(int $id): DataResponse {
/**
* @NoAdminRequired
*/
public function update(int $id, string $title = null, string $emoji = null): DataResponse {
return $this->handleError(function () use ($id, $title, $emoji) {
return $this->service->update($id, $title, $emoji, $this->userId);
public function update(int $id, string $title = null, string $emoji = null, ?bool $archived = null): DataResponse {
return $this->handleError(function () use ($id, $title, $emoji, $archived) {
return $this->service->update($id, $title, $emoji, $archived, $this->userId);
});
}
}
9 changes: 9 additions & 0 deletions lib/Db/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* @method setTitle(string $title)
* @method getEmoji(): string
* @method setEmoji(string $emoji)
* @method getArchived(): bool
* @method setArchived(bool $archived)
* @method getOwnership(): string
* @method setOwnership(string $ownership)
* @method getOwnerDisplayName(): string
Expand All @@ -26,6 +28,8 @@
* @method setOnSharePermissions(array $onSharePermissions)
* @method getHasShares(): bool
* @method setHasShares(bool $hasShares)
* @method getFavorite(): bool
* @method setFavorite(bool $favorite)
* @method getRowsCount(): int
* @method setRowsCount(int $rowsCount)
* @method getColumnsCount(): int
Expand All @@ -52,17 +56,20 @@ class Table extends Entity implements JsonSerializable {
protected ?string $createdAt = null;
protected ?string $lastEditBy = null;
protected ?string $lastEditAt = null;
protected bool $archived = false;
protected ?bool $isShared = null;
protected ?array $onSharePermissions = null;

protected ?bool $hasShares = false;
protected ?bool $favorite = false;
protected ?int $rowsCount = 0;
protected ?int $columnsCount = 0;
protected ?array $views = null;
protected ?array $columns = null;

public function __construct() {
$this->addType('id', 'integer');
$this->addType('archived', 'boolean');
}

/**
Expand All @@ -79,7 +86,9 @@ public function jsonSerialize(): array {
'createdAt' => $this->createdAt ?: '',
'lastEditBy' => $this->lastEditBy ?: '',
'lastEditAt' => $this->lastEditAt ?: '',
'archived' => $this->archived,
'isShared' => !!$this->isShared,
'favorite' => $this->favorite,
'onSharePermissions' => $this->getSharePermissions(),
'hasShares' => !!$this->hasShares,
'rowsCount' => $this->rowsCount ?: 0,
Expand Down
4 changes: 4 additions & 0 deletions lib/Db/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
* @method setOnSharePermissions(array $onSharePermissions)
* @method getHasShares(): bool
* @method setHasShares(bool $hasShares)
* @method getFavorite(): bool
* @method setFavorite(bool $favorite)
* @method getRowsCount(): int
* @method setRowsCount(int $rowCount)
* @method getOwnership(): string
Expand All @@ -57,6 +59,7 @@ class View extends Entity implements JsonSerializable {
protected ?bool $isShared = null;
protected ?array $onSharePermissions = null;
protected ?bool $hasShares = false;
protected bool $favorite = false;
protected ?int $rowsCount = 0;
protected ?string $ownership = null;
protected ?string $ownerDisplayName = null;
Expand Down Expand Up @@ -137,6 +140,7 @@ public function jsonSerialize(): array {
'columns' => $this->getColumnsArray(),
'sort' => $this->getSortArray(),
'isShared' => !!$this->isShared,
'favorite' => $this->favorite,
'onSharePermissions' => $this->getSharePermissions(),
'hasShares' => !!$this->hasShares,
'rowsCount' => $this->rowsCount ?: 0,
Expand Down
60 changes: 60 additions & 0 deletions lib/Migration/Version000800Date20240222000000.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

/** @noinspection PhpUnused */

declare(strict_types=1);

namespace OCA\Tables\Migration;

use Closure;
use OCP\DB\Exception;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

class Version000800Date20240222000000 extends SimpleMigrationStep {
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
* @throws Exception
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();

if ($schema->hasTable('tables_tables')) {
$table = $schema->getTable('tables_tables');
$table->addColumn('archived', Types::BOOLEAN, [
'default' => false,
'notnull' => true,
]);
}

if (!$schema->hasTable('tables_favorites')) {
$table = $schema->createTable('tables_favorites');
$table->addColumn('id', Types::BIGINT, [
'notnull' => true,
'autoincrement' => true,
'unsigned' => true,
]);
$table->addColumn('node_type', Types::SMALLINT, [
'notnull' => true,
]);
$table->addColumn('node_id', Types::BIGINT, [
'notnull' => true,
]);
$table->addColumn('user_id', Types::STRING, [
'notnull' => true,
'length' => 64,
]);
$table->setPrimaryKey(['id']);
$table->addIndex(['user_id'], 'idx_tables_fav_uid');
}

return $schema;
}

}
3 changes: 3 additions & 0 deletions lib/ResponseDefinitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* sort: list<array{columnId: int, mode: 'ASC'|'DESC'}>,
* filter: list<list<array{columnId: int, operator: 'begins-with'|'ends-with'|'contains'|'is-equal'|'is-greater-than'|'is-greater-than-or-equal'|'is-lower-than'|'is-lower-than-or-equal'|'is-empty', value: string|int|float}>>,
* isShared: bool,
* favorite: bool,
* onSharePermissions: ?array{
* read: bool,
* create: bool,
Expand All @@ -44,6 +45,8 @@
* createdAt: string,
* lastEditBy: string,
* lastEditAt: string,
* archived: bool,
* favorite: bool,
* isShared: bool,
* onSharePermissions: ?array{
* read: bool,
Expand Down
Loading

0 comments on commit b0e1534

Please sign in to comment.