Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ precedence = "aggregate"
SPDX-FileCopyrightText = "2025 Nextcloud GmbH and Nextcloud contributors"
SPDX-License-Identifier = "AGPL-3.0-or-later"

[[annotations]]
path = ["vendor-bin/rector/composer.json", "vendor-bin/rector/composer.lock", "tests/psalm-baseline.xml"]
precedence = "aggregate"
SPDX-FileCopyrightText = "2026 Nextcloud GmbH and Nextcloud contributors"
SPDX-License-Identifier = "AGPL-3.0-or-later"

[[annotations]]
path = ["img/app-dark.svg", "img/app.svg", "img/view.svg", "img/view-dark.svg", "img/material/*.svg"]
precedence = "aggregate"
Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"nextcloud/ocp": "dev-stable33",
"staabm/annotate-pull-request-from-checkstyle": "^1.8.7",
"phpunit/phpunit": "9.6.34",
"psalm/phar": "^5.26.1"
"psalm/phar": "^6.16"
},
"config": {
"optimize-autoloader": true,
Expand All @@ -44,6 +44,8 @@
"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",
"openapi": "generate-spec --verbose && (npm run typescript:generate || echo 'Please manually regenerate the typescript OpenAPI models')",
"rector:check": "rector --dry-run",
"rector:fix": "rector",
"scoper:update-deps": "./update-scoper-dependencies.sh",
"post-install-cmd": [
"composer bin all install --ansi",
Expand Down
16 changes: 8 additions & 8 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 31 additions & 11 deletions lib/Activity/ActivityManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,30 +47,43 @@
) {
}

public function triggerEvent($objectType, $object, $subject, $additionalParams = [], $author = null) {
/**
* @param Row2|Table $object
* @param \OCA\Tables\Model\ImportStats[]|null|string $additionalParams
* @param (array|null)[]|null|string $author
*
* @psalm-param 'tables_row'|'tables_table' $objectType
* @psalm-param array{importStats?: \OCA\Tables\Model\ImportStats}|null|string $additionalParams
* @psalm-param array{before: array|null, after: array|null}|null|string $author
*/
public function triggerEvent(string $objectType, Table|Row2 $object, string $subject, array|string|null $additionalParams = [], array|string|null $author = null) {
if ($author === null) {
$author = $this->userId;
}

try {
$event = $this->createEvent($objectType, $object, $subject, $additionalParams, $author);

Check failure on line 65 in lib/Activity/ActivityManager.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable34

InvalidArgument

lib/Activity/ActivityManager.php:65:64: InvalidArgument: Argument 4 of OCA\Tables\Activity\ActivityManager::createEvent expects array{after?: mixed, before?: mixed}, but array{importStats?: OCA\Tables\Model\ImportStats}|null|string with additional array shape fields (importStats) was provided (see https://psalm.dev/004)

Check failure on line 65 in lib/Activity/ActivityManager.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-master

InvalidArgument

lib/Activity/ActivityManager.php:65:64: InvalidArgument: Argument 4 of OCA\Tables\Activity\ActivityManager::createEvent expects array{after?: mixed, before?: mixed}, but array{importStats?: OCA\Tables\Model\ImportStats}|null|string with additional array shape fields (importStats) was provided (see https://psalm.dev/004)

Check failure on line 65 in lib/Activity/ActivityManager.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable33

InvalidArgument

lib/Activity/ActivityManager.php:65:64: InvalidArgument: Argument 4 of OCA\Tables\Activity\ActivityManager::createEvent expects array{after?: mixed, before?: mixed}, but array{importStats?: OCA\Tables\Model\ImportStats}|null|string with additional array shape fields (importStats) was provided (see https://psalm.dev/004)

if ($event !== null) {
$this->sendToUsers($event, $object);
}
} catch (\Exception $e) {
} catch (\Exception) {
// Ignore exception for undefined activities on update events
}
}

public function triggerUpdateEvents($objectType, ChangeSet $changeSet, $subject) {
/**
* @psalm-param 'tables_table' $objectType
* @psalm-param 'table_update' $subject
*/
public function triggerUpdateEvents(string $objectType, ChangeSet $changeSet, string $subject) {
$previousEntity = $changeSet->getBefore();
$entity = $changeSet->getAfter();
$events = [];

if ($previousEntity !== null) {
foreach ($entity->getUpdatedFields() as $field => $value) {
$getter = 'get' . ucfirst($field);
$getter = 'get' . ucfirst((string)$field);
$subjectComplete = $subject . '_' . $field;
$changes = [
'before' => $previousEntity->$getter(),
Expand All @@ -82,15 +95,15 @@
if ($event !== null) {
$events[] = $event;
}
} catch (\Exception $e) {
} catch (\Exception) {
// Ignore exception for undefined activities on update events
}
}
}
} else {
try {
$events = [$this->createEvent($objectType, $entity, $subject)];
} catch (\Exception $e) {
} catch (\Exception) {
// Ignore exception for undefined activities on update events
}
}
Expand All @@ -100,7 +113,14 @@
}
}

private function createEvent($objectType, $object, $subject, $additionalParams = [], $author = null) {
/**
* @psalm-param array{before?: mixed, after?: mixed} $additionalParams
* @psalm-param 'tables_row'|'tables_table' $objectType
* @psalm-param array{before: array|null, after: array|null}|null|string $author
*
* @param (array|null)[]|null|string $author
*/
private function createEvent(string $objectType, Row2|Table $object, string $subject, array $additionalParams = [], array|string|null $author = null) {
if ($object instanceof Table) {
$objectTitle = $object->getTitle();
$table = $object;
Expand All @@ -118,7 +138,7 @@
*/
$eventType = 'tables';
$subjectParams = [
'author' => $author === null ? $this->userId : $author,
'author' => $author ?? $this->userId,
'table' => $table
];
switch ($subject) {
Expand All @@ -138,7 +158,7 @@
$subjectParams['row'] = $object;
break;
case self::SUBJECT_IMPORT_FINISHED:
$subjectParams['importStats'] = $additionalParams['importStats'] ?? null;

Check failure on line 161 in lib/Activity/ActivityManager.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable34

InvalidArrayOffset

lib/Activity/ActivityManager.php:161:37: InvalidArrayOffset: Cannot access value on variable $additionalParams using offset value of 'importStats', expecting 'before' or 'after' (see https://psalm.dev/115)

Check failure on line 161 in lib/Activity/ActivityManager.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-master

InvalidArrayOffset

lib/Activity/ActivityManager.php:161:37: InvalidArrayOffset: Cannot access value on variable $additionalParams using offset value of 'importStats', expecting 'before' or 'after' (see https://psalm.dev/115)

Check failure on line 161 in lib/Activity/ActivityManager.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable33

InvalidArrayOffset

lib/Activity/ActivityManager.php:161:37: InvalidArrayOffset: Cannot access value on variable $additionalParams using offset value of 'importStats', expecting 'before' or 'after' (see https://psalm.dev/115)
break;
default:
throw new \Exception(sprintf('Unknown subject "%s" for activity.', $subject));
Expand Down Expand Up @@ -181,7 +201,7 @@
return $event;
}

private function sendToUsers(IEvent $event, $object) {
private function sendToUsers(IEvent $event, Row2|Table $object) {
if ($object instanceof Table) {
$tableId = $object->getId();
$owner = $object->getOwnership();
Expand All @@ -204,7 +224,7 @@
}
}

public function getActivitySubject($language, $subjectIdentifier, $subjectParams = [], $ownActivity = false) {
public function getActivitySubject(string $language, $subjectIdentifier, array $subjectParams = [], bool $ownActivity = false) {
$subject = '';
$l = $this->l10nFactory->get(Application::APP_ID, $language);

Expand Down Expand Up @@ -262,7 +282,7 @@
return $subject;
}

public function getActivityMessage($language, $subjectIdentifier) {
public function getActivityMessage(string $language, $subjectIdentifier) {
$l = $this->l10nFactory->get(Application::APP_ID, $language);

switch ($subjectIdentifier) {
Expand Down
4 changes: 2 additions & 2 deletions lib/Activity/ChangeSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
}
}

public function setBefore($before) {
public function setBefore(Entity $before) {
$this->before = clone $before;
}

public function setAfter($after) {
public function setAfter(Entity $after) {
$this->after = clone $after;
}

Expand All @@ -40,7 +40,7 @@
return $this->after;
}

public function jsonSerialize(): array {

Check failure on line 43 in lib/Activity/ChangeSet.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable34

MissingOverrideAttribute

lib/Activity/ChangeSet.php:43:2: MissingOverrideAttribute: Method OCA\Tables\Activity\ChangeSet::jsonserialize should have the "Override" attribute (see https://psalm.dev/358)

Check failure on line 43 in lib/Activity/ChangeSet.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-master

MissingOverrideAttribute

lib/Activity/ChangeSet.php:43:2: MissingOverrideAttribute: Method OCA\Tables\Activity\ChangeSet::jsonserialize should have the "Override" attribute (see https://psalm.dev/358)

Check failure on line 43 in lib/Activity/ChangeSet.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis dev-stable33

MissingOverrideAttribute

lib/Activity/ChangeSet.php:43:2: MissingOverrideAttribute: Method OCA\Tables\Activity\ChangeSet::jsonserialize should have the "Override" attribute (see https://psalm.dev/358)
return [
'before' => $this->getBefore(),
'after' => $this->getAfter()
Expand Down
8 changes: 4 additions & 4 deletions lib/Activity/TablesProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ class TablesProvider implements IProvider {

public function __construct(
private $userId,
private IURLGenerator $urlGenerator,
private ActivityManager $activityManager,
private IUserManager $userManager,
private LoggerInterface $logger,
private readonly IURLGenerator $urlGenerator,
private readonly ActivityManager $activityManager,
private readonly IUserManager $userManager,
private readonly LoggerInterface $logger,
) {
}

Expand Down
36 changes: 10 additions & 26 deletions lib/Analytics/AnalyticsDatasource.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,15 @@

class AnalyticsDatasource implements IDatasource {

private LoggerInterface $logger;
private IL10N $l10n;
private TableService $tableService;
private ViewService $viewService;
private RowService $rowService;
private ColumnService $columnService;

protected ?string $userId;

public function __construct(
IL10N $l10n,
LoggerInterface $logger,
TableService $tableService,
ViewService $viewService,
ColumnService $columnService,
RowService $rowService,
?string $userId,
private readonly IL10N $l10n,
private readonly LoggerInterface $logger,
private readonly TableService $tableService,
private readonly ViewService $viewService,
private readonly ColumnService $columnService,
private readonly RowService $rowService,
protected ?string $userId,
) {
$this->l10n = $l10n;
$this->logger = $logger;
$this->tableService = $tableService;
$this->viewService = $viewService;
$this->columnService = $columnService;
$this->rowService = $rowService;
$this->userId = $userId;
}

/**
Expand Down Expand Up @@ -110,7 +94,7 @@ public function getTemplate(): array {
// concatenate the option-string. The format is tableId:viewId-title
$tableString = $tableString . $table->getId() . ':' . $view->getId() . '-' . $view->getTitle() . '/';
}
} catch (PermissionError $e) {
} catch (PermissionError) {
// this is a shared table without shared views;
continue;
}
Expand Down Expand Up @@ -164,7 +148,7 @@ public function getTemplate(): array {
*/
public function readData($option): array {
// get the ids which come in the format tableId:viewId
$ids = explode(':', $option['tableId']);
$ids = explode(':', (string)$option['tableId']);
$this->userId = $option['user_id'];

if (count($ids) === 1) {
Expand Down Expand Up @@ -338,7 +322,7 @@ private function formatBooleanValue(mixed $value): string {
return '';
}

private function formatTextValue(Column $column, mixed $value): string {
private function formatTextValue(Column $column, string $value): string {
if ($value === null || $value === '') {
return '';
}
Expand Down
13 changes: 5 additions & 8 deletions lib/Api/V1Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,11 @@
use OCP\AppFramework\Db\MultipleObjectsReturnedException;

class V1Api {
private RowService $rowService;
private ColumnService $columnService;
private ?string $userId;

public function __construct(ColumnService $columnService, RowService $rowService, ?string $userId) {
$this->columnService = $columnService;
$this->rowService = $rowService;
$this->userId = $userId;
public function __construct(
private readonly ColumnService $columnService,
private readonly RowService $rowService,
private ?string $userId,
) {
}

/**
Expand Down
4 changes: 2 additions & 2 deletions lib/BackgroundJob/ConvertViewColumnsFormat.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function run($argument) {

$maxId = 0;
// Update each view
while ($view = $result->fetch()) {
while ($view = $result->fetchAssociative()) {
$this->processView($view, $updateQb);
$maxId = max($maxId, (int)$view['id']);
}
Expand All @@ -67,7 +67,7 @@ private function processView(array $view, \OCP\DB\QueryBuilder\IQueryBuilder $up
}

// Parse existing columns JSON
$columns = json_decode($view['columns'], true);
$columns = json_decode((string)$view['columns'], true);
if (!is_array($columns)) {
return;
}
Expand Down
12 changes: 6 additions & 6 deletions lib/BackgroundJob/ImportTableJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
class ImportTableJob extends QueuedJob {
public function __construct(
ITimeFactory $time,
private IUserManager $userManager,
private IUserSession $userSession,
private ImportService $importService,
private ActivityManager $activityManager,
private TableMapper $tableMapper,
private ViewMapper $viewMapper,
private readonly IUserManager $userManager,
private readonly IUserSession $userSession,
private readonly ImportService $importService,
private readonly ActivityManager $activityManager,
private readonly TableMapper $tableMapper,
private readonly ViewMapper $viewMapper,
) {
parent::__construct($time);
}
Expand Down
19 changes: 6 additions & 13 deletions lib/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,12 @@
* @package OCA\Tables
*/
class Capabilities implements ICapability {
private IAppManager $appManager;

private LoggerInterface $logger;

private IConfig $config;

private CircleHelper $circleHelper;

public function __construct(IAppManager $appManager, LoggerInterface $logger, IConfig $config, CircleHelper $circleHelper) {
$this->appManager = $appManager;
$this->logger = $logger;
$this->config = $config;
$this->circleHelper = $circleHelper;
public function __construct(
private readonly IAppManager $appManager,
private readonly LoggerInterface $logger,
private readonly IConfig $config,
private readonly CircleHelper $circleHelper,
) {
}

/**
Expand Down
10 changes: 4 additions & 6 deletions lib/Command/AddTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,11 @@
use Symfony\Component\Console\Output\OutputInterface;

class AddTable extends Command {
protected TableService $tableService;
protected LoggerInterface $logger;

public function __construct(TableService $tableService, LoggerInterface $logger) {
public function __construct(
protected TableService $tableService,
protected LoggerInterface $logger,
) {
parent::__construct();
$this->tableService = $tableService;
$this->logger = $logger;
}

protected function configure(): void {
Expand Down
Loading
Loading