Merge pull request #63114 from nextcloud/fix/fix-32bits-support-35

Fix errors from 32bits CI
pull/63140/head
Côme Chilliet 1 week ago committed by GitHub
commit cbbb991ed5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      .github/workflows/phpunit-32bits.yml
  2. 2
      apps/sharing/lib/ResponseDefinitions.php
  3. 6
      apps/sharing/openapi.json
  4. 44
      apps/sharing/tests/Command/CommandTest.php
  5. 14
      apps/sharing/tests/Controller/ApiV1ControllerTest.php
  6. 2
      lib/private/ServerInfo.php
  7. 24
      lib/private/Sharing/SharingBackend.php
  8. 13
      lib/private/Sharing/SharingManager.php
  9. 2
      lib/unstable/Sharing/Share.php
  10. 6
      openapi.json
  11. 33
      tests/lib/Sharing/AbstractSharingManagerTests.php

@ -29,8 +29,6 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['8.3', '8,5']
steps:
- name: Checkout server
@ -43,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

@ -123,7 +123,7 @@ use NCU\Sharing\Source\IShareSourceType;
* id: non-empty-string,
* owner: SharingUser,
* // Unix time in milliseconds
* last_updated: non-negative-int,
* last_updated: numeric-string,
* state: SharingState,
* sources: list<SharingSource>,
* recipients: list<SharingRecipient>,

@ -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"

@ -164,7 +164,7 @@ final class CommandTest extends AbstractSharingManagerTests {
}
/**
* @return array<string, mixed>
* @return SharingShare
*/
#[Override]
protected function createShare(ShareAccessContext $accessContext): array {
@ -177,12 +177,12 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
/**
* @return array<string, mixed>
* @return SharingShare
*/
#[Override]
protected function updateShareState(ShareAccessContext $accessContext, string $id, ShareState $state): array {
@ -195,12 +195,12 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
/**
* @return array<string, mixed>
* @return SharingShare
*/
#[Override]
protected function addShareSource(ShareAccessContext $accessContext, string $id, ShareSource $source): array {
@ -214,12 +214,12 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
/**
* @return array<string, mixed>
* @return SharingShare
*/
#[Override]
protected function removeShareSource(ShareAccessContext $accessContext, string $id, ShareSource $source): array {
@ -233,12 +233,12 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
/**
* @return array<string, mixed>
* @return SharingShare
*/
#[Override]
protected function addShareRecipient(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient): array {
@ -253,12 +253,12 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
/**
* @return array<string, mixed>
* @return SharingShare
*/
#[Override]
protected function removeShareRecipient(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient): array {
@ -273,12 +273,12 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
/**
* @return array<string, mixed>
* @return SharingShare
*/
#[Override]
protected function updateShareRecipientSecret(ShareAccessContext $accessContext, string $id, ShareRecipient $recipient, string $secret): array {
@ -294,12 +294,12 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
/**
* @return array<string, mixed>
* @return SharingShare
*/
#[Override]
protected function updateShareProperty(ShareAccessContext $accessContext, string $id, ShareProperty $property): array {
@ -313,12 +313,12 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
/**
* @return array<string, mixed>
* @return SharingShare
*/
#[Override]
protected function updateSharePermission(ShareAccessContext $accessContext, string $id, SharePermission $permission): array {
@ -332,12 +332,12 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
/**
* @return array<string, mixed>
* @return SharingShare
*/
#[Override]
protected function selectSharePermissionPreset(ShareAccessContext $accessContext, string $id, string $permissionPresetClass): array {
@ -350,7 +350,7 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
@ -379,7 +379,7 @@ final class CommandTest extends AbstractSharingManagerTests {
],
[],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
@ -399,7 +399,7 @@ final class CommandTest extends AbstractSharingManagerTests {
['limit', $limit],
],
);
/** @psalm-suppress MixedReturnStatement */
/** @var SharingShare[] */
return json_decode($stdout, true, 512, JSON_THROW_ON_ERROR);
}
}

@ -95,53 +95,63 @@ final class ApiV1ControllerTest extends AbstractSharingManagerTests {
#[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 @@ final class ApiV1ControllerTest extends AbstractSharingManagerTests {
$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));
}

@ -25,7 +25,7 @@ readonly class ServerInfo implements IServerInfo {
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));

@ -543,8 +543,8 @@ final readonly class SharingBackend implements ISharingBackend {
$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 @@ final readonly class SharingBackend implements ISharingBackend {
}
// 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<array-key, array{id: non-empty-string, owner: ShareUser, last_updated: non-negative-int, state: ShareState, sources: list<ShareSource>, recipients: list<ShareRecipient>, properties: array<class-string<ISharePropertyType>, ShareProperty>, permissions: array<class-string<ISharePermissionType>, SharePermission>}> $shares */
/** @var array<array-key, array{id: non-empty-string, owner: ShareUser, last_updated: numeric-string, state: ShareState, sources: list<ShareSource>, recipients: list<ShareRecipient>, properties: array<class-string<ISharePropertyType>, ShareProperty>, permissions: array<class-string<ISharePermissionType>, SharePermission>}> $shares */
$shares = [];
foreach ($queries as $qb) {
$qb
@ -672,8 +672,8 @@ final readonly class SharingBackend implements ISharingBackend {
/** @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 @@ final readonly class SharingBackend implements ISharingBackend {
'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 @@ final readonly class SharingBackend implements ISharingBackend {
}
$value = $row['source_value'];
$id = (string)$row['share_id'];
$id = $row['share_id'];
$shares[$id]['sources'][] = new ShareSource(
$typeClass,
$value,
@ -777,7 +777,7 @@ final readonly class SharingBackend implements ISharingBackend {
'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<IShareRecipientType> $typeClass */
@ -890,7 +890,7 @@ final readonly class SharingBackend implements ISharingBackend {
'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 @@ final readonly class SharingBackend implements ISharingBackend {
'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 @@ final readonly class SharingBackend implements ISharingBackend {
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 */

@ -753,18 +753,17 @@ final readonly class SharingManager implements ISharingManager, IEventListener {
}
/**
* @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;
}

@ -132,7 +132,7 @@ use OCP\L10N\IFactory;
* id: non-empty-string,
* owner: SharingUser,
* // Unix time in milliseconds
* last_updated: non-negative-int,
* last_updated: numeric-string,
* state: SharingState,
* sources: list<SharingSource>,
* recipients: list<SharingRecipient>,

@ -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"

@ -42,24 +42,54 @@ use Test\TestCase;
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,8 +116,7 @@ abstract class AbstractSharingManagerTests extends TestCase {
protected IUser $user2;
private function parseTime(mixed $timestampMs): \DateTimeImmutable {
$timestampMs = (int)$timestampMs;
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);

Loading…
Cancel
Save