From 3728c88521413c62ee7260085ea276148192b14f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 10 Aug 2026 11:33:07 +0200 Subject: [PATCH 1/6] fix(32bits): Store timestamp in ms in a string to avoid int overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same strategy as for snowflake ids. Signed-off-by: Côme Chilliet --- apps/sharing/lib/ResponseDefinitions.php | 2 +- lib/private/Sharing/SharingBackend.php | 24 +++++++++---------- lib/private/Sharing/SharingManager.php | 13 +++++----- lib/unstable/Sharing/Share.php | 2 +- .../Sharing/AbstractSharingManagerTests.php | 1 - 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/apps/sharing/lib/ResponseDefinitions.php b/apps/sharing/lib/ResponseDefinitions.php index 34bd1e4ab44b9..6a0b7b48d7a0c 100644 --- a/apps/sharing/lib/ResponseDefinitions.php +++ b/apps/sharing/lib/ResponseDefinitions.php @@ -123,7 +123,7 @@ * id: non-empty-string, * owner: SharingUser, * // Unix time in milliseconds - * last_updated: non-negative-int, + * last_updated: numeric-string, * state: SharingState, * sources: list, * recipients: list, diff --git a/lib/private/Sharing/SharingBackend.php b/lib/private/Sharing/SharingBackend.php index 35abf38315568..c57ffbdd6bcff 100644 --- a/lib/private/Sharing/SharingBackend.php +++ b/lib/private/Sharing/SharingBackend.php @@ -543,8 +543,8 @@ public function setLastUpdated(array $ids, \DateTimeImmutable $lastUpdated): voi $rowCount = $qb ->update('sharing_share') - ->set('last_updated', $qb->createNamedParameter(SharingManager::timeToMs($lastUpdated), IQueryBuilder::PARAM_INT)) - ->where($qb->expr()->in('id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY))) + ->set('last_updated', $qb->createNamedParameter(SharingManager::timeToMs($lastUpdated))) + ->where($qb->expr()->in('id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY))) ->executeStatement(); if ($rowCount !== count($chunk)) { throw new ShareNotFoundException(); @@ -618,7 +618,7 @@ private function list(ShareAccessContext $accessContext, ?string $filterShareID, } // The key type is array-key, because PHP will automatically cast the value. We can't type it as integer though, because we need to also support 32 bit systems and there the autocasting doesn't happen, if the value is too large. - /** @var array, recipients: list, properties: array, ShareProperty>, permissions: array, SharePermission>}> $shares */ + /** @var array, recipients: list, properties: array, ShareProperty>, permissions: array, SharePermission>}> $shares */ $shares = []; foreach ($queries as $qb) { $qb @@ -672,8 +672,8 @@ private function list(ShareAccessContext $accessContext, ?string $filterShareID, /** @var non-empty-string $id */ $id = (string)$row['id']; - /** @var non-negative-int $lastUpdated */ - $lastUpdated = (int)$row['last_updated']; + /** @var numeric-string $lastUpdated */ + $lastUpdated = (string)$row['last_updated']; /** @var string $state */ $state = $row['state']; $shares[$id] ??= [ @@ -718,10 +718,10 @@ private function list(ShareAccessContext $accessContext, ?string $filterShareID, 'ss.source_value', ) ->from('sharing_share_sources', 'ss') - ->where($qb->expr()->in('ss.share_id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY))); + ->where($qb->expr()->in('ss.share_id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY))); $result = $qb->executeQuery(); - /** @var array{source_class_id: mixed, source_value: non-empty-string, share_id: int}[] $rows */ + /** @var array{source_class_id: mixed, source_value: non-empty-string, share_id: string}[] $rows */ $rows = $result->fetchAll(); foreach ($rows as $row) { @@ -749,7 +749,7 @@ private function list(ShareAccessContext $accessContext, ?string $filterShareID, } $value = $row['source_value']; - $id = (string)$row['share_id']; + $id = $row['share_id']; $shares[$id]['sources'][] = new ShareSource( $typeClass, $value, @@ -777,7 +777,7 @@ private function list(ShareAccessContext $accessContext, ?string $filterShareID, 'sr.initiator_instance', ) ->from('sharing_share_recipients', 'sr') - ->where($qb->expr()->in('sr.share_id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY))); + ->where($qb->expr()->in('sr.share_id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY))); foreach ($qb->executeQuery()->fetchAll() as $row) { /** @var class-string $typeClass */ @@ -890,7 +890,7 @@ private function list(ShareAccessContext $accessContext, ?string $filterShareID, 'sp.property_value', ) ->from('sharing_share_properties', 'sp') - ->where($qb->expr()->in('sp.share_id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY))); + ->where($qb->expr()->in('sp.share_id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY))); $result = $qb->executeQuery(); foreach ($result->fetchAll() as $row) { @@ -961,7 +961,7 @@ private function list(ShareAccessContext $accessContext, ?string $filterShareID, 'sp.permission_enabled', ) ->from('sharing_share_permissions', 'sp') - ->where($qb->expr()->in('sp.share_id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY))); + ->where($qb->expr()->in('sp.share_id', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY))); $result = $qb->executeQuery(); foreach ($result->fetchAll() as $row) { @@ -1110,7 +1110,7 @@ public function createSharePermissionDefaultValue(Share $share, string $permissi return $share; } - private static function parseTimestamp(int $timestampMs): \DateTimeImmutable { + private static function parseTimestamp(string $timestampMs): \DateTimeImmutable { if (method_exists(\DateTimeImmutable::class, 'createFromTimestamp')) { // with php 8.3 the method doesn't exist and psalm doesn't know the return type /** @psalm-suppress MixedReturnStatement */ diff --git a/lib/private/Sharing/SharingManager.php b/lib/private/Sharing/SharingManager.php index 51b8dc18b0ec5..4c2b0f2ee11ca 100644 --- a/lib/private/Sharing/SharingManager.php +++ b/lib/private/Sharing/SharingManager.php @@ -753,18 +753,17 @@ private function processShareUpdates(array $sharesOrIds): array { } /** - * @return non-negative-int + * @return numeric-string */ - public static function timeToMs(\DateTimeImmutable $time): int { + public static function timeToMs(\DateTimeImmutable $time): string { if (method_exists($time, 'getMicrosecond')) { - /** @var int $micros */ - $micros = $time->getMicrosecond(); + $micros = (float)$time->getMicrosecond(); } else { - $micros = (int)$time->format('u'); + $micros = (float)$time->format('u'); } - $time = $time->getTimestamp() * 1000 + (int)floor($micros / 1000); - if ($time > 0) { + $time = (string)floor((float)$time->getTimestamp() * 1000.0 + $micros / 1000.0); + if ((float)$time > 0) { return $time; } diff --git a/lib/unstable/Sharing/Share.php b/lib/unstable/Sharing/Share.php index feed3031aa370..004313e724d19 100644 --- a/lib/unstable/Sharing/Share.php +++ b/lib/unstable/Sharing/Share.php @@ -132,7 +132,7 @@ * id: non-empty-string, * owner: SharingUser, * // Unix time in milliseconds - * last_updated: non-negative-int, + * last_updated: numeric-string, * state: SharingState, * sources: list, * recipients: list, diff --git a/tests/lib/Sharing/AbstractSharingManagerTests.php b/tests/lib/Sharing/AbstractSharingManagerTests.php index 3ab9d5e15c337..a79dc5d501bca 100644 --- a/tests/lib/Sharing/AbstractSharingManagerTests.php +++ b/tests/lib/Sharing/AbstractSharingManagerTests.php @@ -87,7 +87,6 @@ abstract protected function getShares(ShareAccessContext $accessContext, ?string protected IUser $user2; private function parseTime(mixed $timestampMs): \DateTimeImmutable { - $timestampMs = (int)$timestampMs; $time = \DateTimeImmutable::createFromFormat('U.u', number_format((float)$timestampMs / 1000.0, 3, '.', '')); if ($time === false) { throw new \RuntimeException('invalid timestamp: ' . $timestampMs); From 387288d6561880d148ad626e880e780f08a6d8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 10 Aug 2026 13:05:17 +0200 Subject: [PATCH 2/6] chore: Remove useless matrix from phpunit-32bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only PHP 8.4 is tested because we use our own image Signed-off-by: Côme Chilliet --- .github/workflows/phpunit-32bits.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/phpunit-32bits.yml b/.github/workflows/phpunit-32bits.yml index 0bcbb786e25a4..105b174342b18 100644 --- a/.github/workflows/phpunit-32bits.yml +++ b/.github/workflows/phpunit-32bits.yml @@ -29,8 +29,6 @@ jobs: strategy: fail-fast: false - matrix: - php-versions: ['8.3', '8,5'] steps: - name: Checkout server From a46f0bc3d10648a4738fdaefe0199590f8f1c66e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 10 Aug 2026 16:33:26 +0200 Subject: [PATCH 3/6] chore(ci): use ${GITHUB_WORKSPACE} instead of hardcoded value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That helps when testing locally with nektos/act Signed-off-by: Côme Chilliet --- .github/workflows/phpunit-32bits.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/phpunit-32bits.yml b/.github/workflows/phpunit-32bits.yml index 105b174342b18..f1d8da06fd0e2 100644 --- a/.github/workflows/phpunit-32bits.yml +++ b/.github/workflows/phpunit-32bits.yml @@ -41,7 +41,7 @@ jobs: uses: docker://ghcr.io/nextcloud/continuous-integration-php8.4-32bit:latest with: args: /bin/sh -c " - git config --global --add safe.directory /github/workspace && + git config --global --add safe.directory ${GITHUB_WORKSPACE} && composer install --no-interaction" - name: Set up Nextcloud From 376a64c4aebf9ae5afba0042454422e12abc3bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 10 Aug 2026 17:19:53 +0200 Subject: [PATCH 4/6] fix: PHP_INT_SIZE is 8 on 64bits, not 4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ternary was reversed because of this typo. Signed-off-by: Côme Chilliet --- lib/private/ServerInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/ServerInfo.php b/lib/private/ServerInfo.php index bf5dec468f270..05da80bae046f 100644 --- a/lib/private/ServerInfo.php +++ b/lib/private/ServerInfo.php @@ -25,7 +25,7 @@ public function getServerId(): int { if ($serverid < 1) { // Fallback: generates a server ID based on hostname /** @var int<0,max> */ - $serverid = PHP_INT_SIZE === 4 + $serverid = PHP_INT_SIZE === 8 ? hexdec(hash('xxh32', $this->getHostname())) // Makes sure it doesn't overflow 32 bits int : hexdec(substr(hash('xxh32', $this->getHostname()), -3)); From fe96dd99c6301b544b38c5d6a9a1d20604d4efee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 11 Aug 2026 09:22:00 +0200 Subject: [PATCH 5/6] chore(sharing): Rebuild openapi.json files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- apps/sharing/openapi.json | 6 ++---- openapi.json | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/sharing/openapi.json b/apps/sharing/openapi.json index 191435bf86c60..98beb6864c1d6 100644 --- a/apps/sharing/openapi.json +++ b/apps/sharing/openapi.json @@ -465,10 +465,8 @@ "$ref": "#/components/schemas/User" }, "last_updated": { - "type": "integer", - "format": "int64", - "description": "Unix time in milliseconds", - "minimum": 0 + "type": "string", + "description": "Unix time in milliseconds" }, "state": { "$ref": "#/components/schemas/State" diff --git a/openapi.json b/openapi.json index 3aaf8b5a32b70..a0d248d466ca2 100644 --- a/openapi.json +++ b/openapi.json @@ -4653,10 +4653,8 @@ "$ref": "#/components/schemas/SharingUser" }, "last_updated": { - "type": "integer", - "format": "int64", - "description": "Unix time in milliseconds", - "minimum": 0 + "type": "string", + "description": "Unix time in milliseconds" }, "state": { "$ref": "#/components/schemas/SharingState" From d9867d73b235cb91d0988d243daa2abee9bbbb53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 11 Aug 2026 10:41:44 +0200 Subject: [PATCH 6/6] chore(sharing): Improve typing in tests to please psalm:strict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- apps/sharing/tests/Command/CommandTest.php | 44 +++++++++---------- .../tests/Controller/ApiV1ControllerTest.php | 14 ++++-- .../Sharing/AbstractSharingManagerTests.php | 32 +++++++++++++- 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/apps/sharing/tests/Command/CommandTest.php b/apps/sharing/tests/Command/CommandTest.php index fae0f6717c181..19b1ca1b27139 100644 --- a/apps/sharing/tests/Command/CommandTest.php +++ b/apps/sharing/tests/Command/CommandTest.php @@ -164,7 +164,7 @@ protected function searchRecipients(ShareAccessContext $accessContext, ?array $f } /** - * @return array + * @return SharingShare */ #[Override] protected function createShare(ShareAccessContext $accessContext): array { @@ -177,12 +177,12 @@ protected function createShare(ShareAccessContext $accessContext): array { ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } /** - * @return array + * @return SharingShare */ #[Override] protected function updateShareState(ShareAccessContext $accessContext, string $id, ShareState $state): array { @@ -195,12 +195,12 @@ protected function updateShareState(ShareAccessContext $accessContext, string $i ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } /** - * @return array + * @return SharingShare */ #[Override] protected function addShareSource(ShareAccessContext $accessContext, string $id, ShareSource $source): array { @@ -214,12 +214,12 @@ protected function addShareSource(ShareAccessContext $accessContext, string $id, ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } /** - * @return array + * @return SharingShare */ #[Override] protected function removeShareSource(ShareAccessContext $accessContext, string $id, ShareSource $source): array { @@ -233,12 +233,12 @@ protected function removeShareSource(ShareAccessContext $accessContext, string $ ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } /** - * @return array + * @return SharingShare */ #[Override] protected function addShareRecipient(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient): array { @@ -253,12 +253,12 @@ protected function addShareRecipient(ShareAccessContext $accessContext, string $ ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } /** - * @return array + * @return SharingShare */ #[Override] protected function removeShareRecipient(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient): array { @@ -273,12 +273,12 @@ protected function removeShareRecipient(ShareAccessContext $accessContext, strin ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } /** - * @return array + * @return SharingShare */ #[Override] protected function updateShareRecipientSecret(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient, string $secret): array { @@ -294,12 +294,12 @@ protected function updateShareRecipientSecret(ShareAccessContext $accessContext, ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } /** - * @return array + * @return SharingShare */ #[Override] protected function updateShareProperty(ShareAccessContext $accessContext, string $id, ShareProperty $property): array { @@ -313,12 +313,12 @@ protected function updateShareProperty(ShareAccessContext $accessContext, string ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } /** - * @return array + * @return SharingShare */ #[Override] protected function updateSharePermission(ShareAccessContext $accessContext, string $id, SharePermission $permission): array { @@ -332,12 +332,12 @@ protected function updateSharePermission(ShareAccessContext $accessContext, stri ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } /** - * @return array + * @return SharingShare */ #[Override] protected function selectSharePermissionPreset(ShareAccessContext $accessContext, string $id, string $permissionPresetClass): array { @@ -350,7 +350,7 @@ protected function selectSharePermissionPreset(ShareAccessContext $accessContext ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } @@ -379,7 +379,7 @@ protected function getShare(ShareAccessContext $accessContext, string $id): arra ], [], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } @@ -399,7 +399,7 @@ protected function getShares(ShareAccessContext $accessContext, ?string $filterS ['limit', $limit], ], ); - /** @psalm-suppress MixedReturnStatement */ + /** @var SharingShare[] */ return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR); } } diff --git a/apps/sharing/tests/Controller/ApiV1ControllerTest.php b/apps/sharing/tests/Controller/ApiV1ControllerTest.php index eaf057a8f4aa6..05395007891c8 100644 --- a/apps/sharing/tests/Controller/ApiV1ControllerTest.php +++ b/apps/sharing/tests/Controller/ApiV1ControllerTest.php @@ -95,53 +95,63 @@ protected function searchRecipients(ShareAccessContext $accessContext, ?array $f #[Override] protected function createShare(ShareAccessContext $accessContext): array { + /** @var SharingShare */ return $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->createShare()); } #[Override] protected function updateShareState(ShareAccessContext $accessContext, string $id, ShareState $state): array { + /** @var SharingShare */ return $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->updateShareState($id, $state->value)); } #[Override] protected function addShareSource(ShareAccessContext $accessContext, string $id, ShareSource $source): array { + /** @var SharingShare */ return $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->addShareSource($id, $source->class, $source->value)); } #[Override] protected function removeShareSource(ShareAccessContext $accessContext, string $id, ShareSource $source): array { + /** @var SharingShare */ return $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->removeShareSource($id, $source->class, $source->value)); } #[Override] protected function addShareRecipient(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient): array { + /** @var SharingShare */ return $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->addShareRecipient($id, $recipient->class, $recipient->value, $recipient->instance)); } #[Override] protected function removeShareRecipient(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient): array { + /** @var SharingShare */ return $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->removeShareRecipient($id, $recipient->class, $recipient->value, $recipient->instance)); } #[Override] protected function updateShareRecipientSecret(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient, string $secret): array { /** @psalm-suppress ArgumentTypeCoercion */ + /** @var SharingShare */ return $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->updateShareRecipientSecret($id, $recipient->class, $recipient->value, $recipient->instance, $secret)); } #[Override] protected function updateShareProperty(ShareAccessContext $accessContext, string $id, ShareProperty $property): array { + /** @var SharingShare */ return $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->updateShareProperty($id, $property->class, $property->value)); } #[Override] protected function updateSharePermission(ShareAccessContext $accessContext, string $id, SharePermission $permission): array { + /** @var SharingShare */ return $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->updateSharePermission($id, $permission->class, $permission->enabled)); } #[Override] protected function selectSharePermissionPreset(ShareAccessContext $accessContext, string $id, string $permissionPresetClass): array { /** @psalm-suppress ArgumentTypeCoercion */ + /** @var SharingShare */ return $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->selectSharePermissionPreset($id, $permissionPresetClass)); } @@ -150,11 +160,9 @@ protected function deleteShare(ShareAccessContext $accessContext, string $id): v $this->executeRequest($accessContext, fn (ApiV1Controller $controller): DataResponse => $controller->deleteShare($id)); } - /** - * @psalm-suppress MixedReturnTypeCoercion - */ #[Override] protected function getShare(ShareAccessContext $accessContext, string $id): array { + /** @var SharingShare */ return $this->executeRequest(new ShareAccessContext($accessContext->currentUser, null, [], $accessContext->overrideChecks), fn (ApiV1Controller $controller): DataResponse => $controller->getShare($id, $accessContext->secret, $accessContext->arguments)); } diff --git a/tests/lib/Sharing/AbstractSharingManagerTests.php b/tests/lib/Sharing/AbstractSharingManagerTests.php index a79dc5d501bca..ee248397d8cf9 100644 --- a/tests/lib/Sharing/AbstractSharingManagerTests.php +++ b/tests/lib/Sharing/AbstractSharingManagerTests.php @@ -42,24 +42,54 @@ abstract class AbstractSharingManagerTests extends TestCase { abstract protected function searchRecipients(ShareAccessContext $accessContext, ?array $filterRecipientTypeClasses, string $query, int $limit, int $offset, ?string $id = null): array; + /** + * @return SharingShare + */ abstract protected function createShare(ShareAccessContext $accessContext): array; + /** + * @return SharingShare + */ abstract protected function updateShareState(ShareAccessContext $accessContext, string $id, ShareState $state): array; + /** + * @return SharingShare + */ abstract protected function addShareSource(ShareAccessContext $accessContext, string $id, ShareSource $source): array; + /** + * @return SharingShare + */ abstract protected function removeShareSource(ShareAccessContext $accessContext, string $id, ShareSource $source): array; + /** + * @return SharingShare + */ abstract protected function addShareRecipient(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient): array; + /** + * @return SharingShare + */ abstract protected function removeShareRecipient(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient): array; + /** + * @return SharingShare + */ abstract protected function updateShareRecipientSecret(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient, string $secret): array; + /** + * @return SharingShare + */ abstract protected function updateShareProperty(ShareAccessContext $accessContext, string $id, ShareProperty $property): array; + /** + * @return SharingShare + */ abstract protected function updateSharePermission(ShareAccessContext $accessContext, string $id, SharePermission $permission): array; + /** + * @return SharingShare + */ abstract protected function selectSharePermissionPreset(ShareAccessContext $accessContext, string $id, string $permissionPresetClass): array; abstract protected function deleteShare(ShareAccessContext $accessContext, string $id): void; @@ -86,7 +116,7 @@ abstract protected function getShares(ShareAccessContext $accessContext, ?string protected IUser $user2; - private function parseTime(mixed $timestampMs): \DateTimeImmutable { + private function parseTime(string $timestampMs): \DateTimeImmutable { $time = \DateTimeImmutable::createFromFormat('U.u', number_format((float)$timestampMs / 1000.0, 3, '.', '')); if ($time === false) { throw new \RuntimeException('invalid timestamp: ' . $timestampMs);