mirror of
https://github.com/nextcloud/server.git
synced 2026-10-09 21:51:10 +02:00
PHP 8.3 allows class constants to declare a type. Adopt it where doing so cannot break third-party apps. Typing an inheritable constant is a hard BC break: a subclass that redeclares it untyped fails to load with "Type of C::FOO must be compatible with P::FOO of type string". Changes are therefore limited to constants that cannot be redeclared by a subclass: - private const (not inherited) - final public/protected const - constants declared in a final class or an enum Interface constants, trait constants, and public/protected constants in non-final (including abstract) classes are left untyped, as is all of lib/public (OCP) and lib/unstable (NCU). One review-requested exception: the public OBJECT_PREFIX/OBJECT_SUFFIX constants of the app-internal CalDAV import helpers (TextImporter, XmlImporter) are typed as well; these classes are not public API and have no subclasses. Only string, int and array are used. float is avoided because it would silently coerce an int literal and change === comparisons. No constant name or value is modified: every changed line adds only the type token, so runtime behaviour is unchanged. Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
146 lines
4.9 KiB
PHP
146 lines
4.9 KiB
PHP
<?php
|
|
|
|
/**
|
|
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Test\Avatar;
|
|
|
|
use OC\Avatar\RemoteAvatar;
|
|
use OCP\Federation\ICloudId;
|
|
use OCP\Federation\ICloudIdManager;
|
|
use OCP\Files\SimpleFS\ISimpleFile;
|
|
use OCP\Files\SimpleFS\ISimpleFolder;
|
|
use OCP\Http\Client\IClient;
|
|
use OCP\Http\Client\IClientService;
|
|
use OCP\Http\Client\IResponse;
|
|
use OCP\IConfig;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
use Psr\Log\LoggerInterface;
|
|
use Test\TestCase;
|
|
|
|
class RemoteAvatarTest extends TestCase {
|
|
private const string CLOUD_ID = 'user@https://remote.example.com';
|
|
|
|
private ISimpleFolder&MockObject $folder;
|
|
private IConfig&MockObject $config;
|
|
private LoggerInterface&MockObject $logger;
|
|
private ICloudIdManager&MockObject $cloudIdManager;
|
|
private IClientService&MockObject $clientService;
|
|
private RemoteAvatar $avatar;
|
|
|
|
#[\Override]
|
|
protected function setUp(): void {
|
|
parent::setUp();
|
|
|
|
$this->config = $this->createMock(IConfig::class);
|
|
$this->logger = $this->createMock(LoggerInterface::class);
|
|
|
|
$cloudId = $this->createMock(ICloudId::class);
|
|
$cloudId->method('getUser')->willReturn('user');
|
|
$cloudId->method('getRemote')->willReturn('https://remote.example.com');
|
|
$cloudId->method('getDisplayId')->willReturn('user@remote.example.com');
|
|
|
|
$this->cloudIdManager = $this->createMock(ICloudIdManager::class);
|
|
$this->cloudIdManager->method('resolveCloudId')
|
|
->with(self::CLOUD_ID)
|
|
->willReturn($cloudId);
|
|
$this->overwriteService(ICloudIdManager::class, $this->cloudIdManager);
|
|
|
|
$this->clientService = $this->createMock(IClientService::class);
|
|
$this->overwriteService(IClientService::class, $this->clientService);
|
|
|
|
$this->folder = $this->createMock(ISimpleFolder::class);
|
|
$this->avatar = new RemoteAvatar($this->folder, self::CLOUD_ID, $this->config, $this->logger);
|
|
}
|
|
|
|
/**
|
|
* Stubs the client returned by IClientService::newClient() to respond to
|
|
* a single GET request, optionally asserting the requested URL/options.
|
|
*
|
|
* @param string|resource|false $body
|
|
*/
|
|
private function mockRemoteClient(string $contentType, string $body, ?string $expectedUrl = null, ?array $expectedOptions = null): void {
|
|
$response = $this->createMock(IResponse::class);
|
|
$response->method('getHeader')->with('Content-Type')->willReturn($contentType);
|
|
$response->method('getBody')->willReturn($body);
|
|
|
|
$client = $this->createMock(IClient::class);
|
|
$matcher = $client->expects($this->once())->method('get');
|
|
if ($expectedUrl !== null) {
|
|
$matcher->with($expectedUrl, $expectedOptions ?? $this->anything());
|
|
}
|
|
$matcher->willReturn($response);
|
|
|
|
$this->clientService->method('newClient')->willReturn($client);
|
|
}
|
|
|
|
public function testExists(): void {
|
|
$this->assertTrue($this->avatar->exists());
|
|
}
|
|
|
|
public function testGetDisplayName(): void {
|
|
$this->assertSame('user@remote.example.com', $this->avatar->getDisplayName());
|
|
}
|
|
|
|
public function testGetFileFetchesAvatarFromRemoteInstance(): void {
|
|
$this->config->method('getSystemValueBool')
|
|
->with('sharing.federation.allowSelfSignedCertificates', false)
|
|
->willReturn(false);
|
|
|
|
$fileContents = 'png-bytes';
|
|
|
|
$this->mockRemoteClient(
|
|
'image/png',
|
|
$fileContents,
|
|
'https://remote.example.com/index.php/avatar/user/64',
|
|
['verify' => true],
|
|
);
|
|
|
|
$expectedFile = $this->createMock(ISimpleFile::class);
|
|
$expectedFile->expects($this->once())->method('getContent')->willReturn($fileContents);
|
|
|
|
$this->folder->expects($this->once())->method('newFile')->willReturn($expectedFile);
|
|
|
|
$file = $this->avatar->getFile(64);
|
|
$this->assertInstanceOf(ISimpleFile::class, $file);
|
|
$this->assertSame($fileContents, $file->getContent());
|
|
}
|
|
|
|
public function testGetFileFetchesAvatarFromCache(): void {
|
|
$this->config->method('getSystemValueBool')
|
|
->with('sharing.federation.allowSelfSignedCertificates', false)
|
|
->willReturn(false);
|
|
|
|
$fileContents = 'png-bytes';
|
|
|
|
$expectedFile = $this->createMock(ISimpleFile::class);
|
|
$expectedFile->expects($this->once())->method('getContent')->willReturn($fileContents);
|
|
$expectedFile->expects($this->once())->method('getMTime')->willReturn(time() + (60 * 60 * 24));
|
|
$expectedFile->expects($this->once())->method('getName')->willReturn('avatar.64.png');
|
|
$this->folder->expects($this->once())->method('getDirectoryListing')->willReturn([$expectedFile]);
|
|
|
|
$this->clientService->expects($this->never())->method('newClient');
|
|
|
|
$file = $this->avatar->getFile(64);
|
|
$this->assertInstanceOf(ISimpleFile::class, $file);
|
|
$this->assertSame($fileContents, $file->getContent());
|
|
}
|
|
|
|
public function testGetFileThrowsOnUnexpectedContentType(): void {
|
|
$this->mockRemoteClient('text/html', '<html></html>');
|
|
|
|
$this->expectException(\Exception::class);
|
|
$this->expectExceptionMessage('Unknown filetype');
|
|
|
|
$this->avatar->getFile(64);
|
|
}
|
|
|
|
public function testIsCustomAvatar(): void {
|
|
$this->assertTrue($this->avatar->isCustomAvatar());
|
|
}
|
|
}
|