mirror of
https://github.com/nextcloud/server.git
synced 2026-06-05 14:56:35 -04:00
Merge pull request #59089 from nextcloud/fix/expand-theming-capabilities
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (master, 8.4, main, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, files_reminders) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, routing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis (push) Waiting to run
Psalm static code analysis / static-code-analysis-security (push) Waiting to run
Psalm static code analysis / static-code-analysis-ocp (push) Waiting to run
Psalm static code analysis / static-code-analysis-ncu (push) Waiting to run
Psalm static code analysis / static-code-analysis-strict (push) Waiting to run
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (master, 8.4, main, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, files_reminders) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, routing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis (push) Waiting to run
Psalm static code analysis / static-code-analysis-security (push) Waiting to run
Psalm static code analysis / static-code-analysis-ocp (push) Waiting to run
Psalm static code analysis / static-code-analysis-ncu (push) Waiting to run
Psalm static code analysis / static-code-analysis-strict (push) Waiting to run
This commit is contained in:
commit
d677a3a5e2
8 changed files with 275 additions and 39 deletions
|
|
@ -8,8 +8,10 @@ namespace OCA\Theming;
|
|||
|
||||
use OCA\Theming\AppInfo\Application;
|
||||
use OCA\Theming\Service\BackgroundService;
|
||||
use OCA\Theming\Service\ThemesService;
|
||||
use OCP\Capabilities\IPublicCapability;
|
||||
use OCP\IConfig;
|
||||
use OCP\Config\IUserConfig;
|
||||
use OCP\IAppConfig;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
|
|
@ -21,18 +23,14 @@ use OCP\IUserSession;
|
|||
*/
|
||||
class Capabilities implements IPublicCapability {
|
||||
|
||||
/**
|
||||
* @param ThemingDefaults $theming
|
||||
* @param Util $util
|
||||
* @param IURLGenerator $url
|
||||
* @param IConfig $config
|
||||
*/
|
||||
public function __construct(
|
||||
protected ThemingDefaults $theming,
|
||||
protected Util $util,
|
||||
protected IURLGenerator $url,
|
||||
protected IConfig $config,
|
||||
protected IAppConfig $appConfig,
|
||||
protected IUserConfig $userConfig,
|
||||
protected IUserSession $userSession,
|
||||
protected ThemesService $themesService,
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
@ -44,6 +42,8 @@ class Capabilities implements IPublicCapability {
|
|||
* name: string,
|
||||
* productName: string,
|
||||
* url: string,
|
||||
* imprintUrl: string,
|
||||
* privacyUrl: string,
|
||||
* slogan: string,
|
||||
* color: string,
|
||||
* color-text: string,
|
||||
|
|
@ -57,6 +57,13 @@ class Capabilities implements IPublicCapability {
|
|||
* background-default: bool,
|
||||
* logoheader: string,
|
||||
* favicon: string,
|
||||
* primaryColor: string,
|
||||
* backgroundColor: string,
|
||||
* defaultPrimaryColor: string,
|
||||
* defaultBackgroundColor: string,
|
||||
* inverted: bool,
|
||||
* cacheBuster: string,
|
||||
* enabledThemes: list<string>,
|
||||
* },
|
||||
* }
|
||||
*/
|
||||
|
|
@ -64,7 +71,7 @@ class Capabilities implements IPublicCapability {
|
|||
$color = $this->theming->getDefaultColorPrimary();
|
||||
$colorText = $this->util->invertTextColor($color) ? '#000000' : '#ffffff';
|
||||
|
||||
$backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime', '');
|
||||
$backgroundLogo = $this->appConfig->getValueString('theming', 'backgroundMime', '');
|
||||
$backgroundColor = $this->theming->getColorBackground();
|
||||
$backgroundText = $this->theming->getTextColorBackground();
|
||||
$backgroundPlain = $backgroundLogo === 'backgroundColor' || ($backgroundLogo === '' && $backgroundColor !== BackgroundService::DEFAULT_COLOR);
|
||||
|
|
@ -80,7 +87,7 @@ class Capabilities implements IPublicCapability {
|
|||
$color = $this->theming->getColorPrimary();
|
||||
$colorText = $this->theming->getTextColorPrimary();
|
||||
|
||||
$backgroundImage = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT);
|
||||
$backgroundImage = $this->userConfig->getValueString($user->getUID(), Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT);
|
||||
if ($backgroundImage === BackgroundService::BACKGROUND_CUSTOM) {
|
||||
$backgroundPlain = false;
|
||||
$background = $this->url->linkToRouteAbsolute('theming.userTheme.getBackground');
|
||||
|
|
@ -98,6 +105,8 @@ class Capabilities implements IPublicCapability {
|
|||
'name' => $this->theming->getName(),
|
||||
'productName' => $this->theming->getProductName(),
|
||||
'url' => $this->theming->getBaseUrl(),
|
||||
'imprintUrl' => $this->theming->getImprintUrl(),
|
||||
'privacyUrl' => $this->theming->getPrivacyUrl(),
|
||||
'slogan' => $this->theming->getSlogan(),
|
||||
'color' => $color,
|
||||
'color-text' => $colorText,
|
||||
|
|
@ -111,6 +120,13 @@ class Capabilities implements IPublicCapability {
|
|||
'background-default' => !$this->util->isBackgroundThemed(),
|
||||
'logoheader' => $this->url->getAbsoluteURL($this->theming->getLogo()),
|
||||
'favicon' => $this->url->getAbsoluteURL($this->theming->getLogo()),
|
||||
'primaryColor' => $color,
|
||||
'backgroundColor' => $backgroundColor,
|
||||
'defaultPrimaryColor' => $this->theming->getDefaultColorPrimary(),
|
||||
'defaultBackgroundColor' => $this->theming->getDefaultColorBackground(),
|
||||
'inverted' => $this->util->invertTextColor($color),
|
||||
'cacheBuster' => $this->util->getCacheBuster(),
|
||||
'enabledThemes' => $this->themesService->getEnabledThemes(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ namespace OCA\Theming\Service;
|
|||
use OCA\Theming\ThemingDefaults;
|
||||
use OCA\Theming\Util;
|
||||
|
||||
/**
|
||||
* @deprecated since Nextcloud 34 — all properties are now exposed via Capabilities
|
||||
*/
|
||||
class JSDataService implements \JsonSerializable {
|
||||
|
||||
public function __construct(
|
||||
|
|
@ -40,10 +43,6 @@ class JSDataService implements \JsonSerializable {
|
|||
|
||||
'cacheBuster' => $this->util->getCacheBuster(),
|
||||
'enabledThemes' => $this->themesService->getEnabledThemes(),
|
||||
|
||||
// deprecated use primaryColor
|
||||
'color' => $this->themingDefaults->getColorPrimary(),
|
||||
'' => 'color is deprecated since Nextcloud 29, use primaryColor instead'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,9 +151,9 @@ class ThemesService {
|
|||
/**
|
||||
* Get the list of all enabled themes IDs for the current user.
|
||||
*
|
||||
* @return string[]
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getEnabledThemes(): array {
|
||||
public function getEnabledThemes() {
|
||||
$enforcedTheme = $this->config->getSystemValueString('enforce_theme', '');
|
||||
$user = $this->userSession->getUser();
|
||||
if ($user === null) {
|
||||
|
|
@ -163,6 +163,7 @@ class ThemesService {
|
|||
return [];
|
||||
}
|
||||
|
||||
/** @var list<string> */
|
||||
$enabledThemes = json_decode($this->config->getUserValue($user->getUID(), Application::APP_ID, 'enabled-themes', '["default"]'));
|
||||
if ($enforcedTheme !== '') {
|
||||
return array_merge([$enforcedTheme], $enabledThemes);
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class ThemingDefaults extends \OC_Defaults {
|
|||
return strip_tags($this->appConfig->getAppValueString(ConfigLexicon::INSTANCE_NAME, $this->entity));
|
||||
}
|
||||
|
||||
public function getProductName() {
|
||||
public function getProductName(): string {
|
||||
return strip_tags($this->appConfig->getAppValueString(ConfigLexicon::PRODUCT_NAME, $this->productName));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@
|
|||
"name",
|
||||
"productName",
|
||||
"url",
|
||||
"imprintUrl",
|
||||
"privacyUrl",
|
||||
"slogan",
|
||||
"color",
|
||||
"color-text",
|
||||
|
|
@ -93,7 +95,14 @@
|
|||
"background-plain",
|
||||
"background-default",
|
||||
"logoheader",
|
||||
"favicon"
|
||||
"favicon",
|
||||
"primaryColor",
|
||||
"backgroundColor",
|
||||
"defaultPrimaryColor",
|
||||
"defaultBackgroundColor",
|
||||
"inverted",
|
||||
"cacheBuster",
|
||||
"enabledThemes"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
|
|
@ -105,6 +114,12 @@
|
|||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"imprintUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"privacyUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"slogan": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -143,6 +158,30 @@
|
|||
},
|
||||
"favicon": {
|
||||
"type": "string"
|
||||
},
|
||||
"primaryColor": {
|
||||
"type": "string"
|
||||
},
|
||||
"backgroundColor": {
|
||||
"type": "string"
|
||||
},
|
||||
"defaultPrimaryColor": {
|
||||
"type": "string"
|
||||
},
|
||||
"defaultBackgroundColor": {
|
||||
"type": "string"
|
||||
},
|
||||
"inverted": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"cacheBuster": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabledThemes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,17 @@ namespace OCA\Theming\Tests;
|
|||
|
||||
use OCA\Theming\Capabilities;
|
||||
use OCA\Theming\ImageManager;
|
||||
use OCA\Theming\Service\BackgroundService;
|
||||
use OCA\Theming\Service\ThemesService;
|
||||
use OCA\Theming\ThemingDefaults;
|
||||
use OCA\Theming\Util;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Config\IUserConfig;
|
||||
use OCP\Files\IAppData;
|
||||
use OCP\IAppConfig;
|
||||
use OCP\IConfig;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
use OCP\ServerVersion;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
|
@ -28,9 +33,11 @@ use Test\TestCase;
|
|||
class CapabilitiesTest extends TestCase {
|
||||
protected ThemingDefaults&MockObject $theming;
|
||||
protected IURLGenerator&MockObject $url;
|
||||
protected IConfig&MockObject $config;
|
||||
protected IAppConfig&MockObject $appConfig;
|
||||
protected IUserConfig&MockObject $userConfig;
|
||||
protected Util&MockObject $util;
|
||||
protected IUserSession $userSession;
|
||||
protected IUserSession&MockObject $userSession;
|
||||
protected ThemesService&MockObject $themesService;
|
||||
protected Capabilities $capabilities;
|
||||
|
||||
protected function setUp(): void {
|
||||
|
|
@ -38,24 +45,30 @@ class CapabilitiesTest extends TestCase {
|
|||
|
||||
$this->theming = $this->createMock(ThemingDefaults::class);
|
||||
$this->url = $this->createMock(IURLGenerator::class);
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->appConfig = $this->createMock(IAppConfig::class);
|
||||
$this->userConfig = $this->createMock(IUserConfig::class);
|
||||
$this->util = $this->createMock(Util::class);
|
||||
$this->userSession = $this->createMock(IUserSession::class);
|
||||
$this->themesService = $this->createMock(ThemesService::class);
|
||||
$this->capabilities = new Capabilities(
|
||||
$this->theming,
|
||||
$this->util,
|
||||
$this->url,
|
||||
$this->config,
|
||||
$this->appConfig,
|
||||
$this->userConfig,
|
||||
$this->userSession,
|
||||
$this->themesService,
|
||||
);
|
||||
}
|
||||
|
||||
public static function dataGetCapabilities(): array {
|
||||
return [
|
||||
['name', 'url', 'slogan', '#FFFFFF', '#000000', 'logo', 'background', '#fff', '#000', 'http://absolute/', true, [
|
||||
['name', 'url', 'slogan', '#FFFFFF', '#000000', 'logo', 'background', '#fff', '#000', 'http://absolute/', true, 'https://imprint.example.com/', 'https://privacy.example.com/', '#0082c9', [
|
||||
'name' => 'name',
|
||||
'productName' => 'name',
|
||||
'url' => 'url',
|
||||
'imprintUrl' => 'https://imprint.example.com/',
|
||||
'privacyUrl' => 'https://privacy.example.com/',
|
||||
'slogan' => 'slogan',
|
||||
'color' => '#FFFFFF',
|
||||
'color-text' => '#000000',
|
||||
|
|
@ -69,11 +82,20 @@ class CapabilitiesTest extends TestCase {
|
|||
'background-default' => false,
|
||||
'logoheader' => 'http://absolute/logo',
|
||||
'favicon' => 'http://absolute/logo',
|
||||
'primaryColor' => '#FFFFFF',
|
||||
'backgroundColor' => '#fff',
|
||||
'defaultPrimaryColor' => '#FFFFFF',
|
||||
'defaultBackgroundColor' => '#0082c9',
|
||||
'inverted' => true,
|
||||
'cacheBuster' => 'v1',
|
||||
'enabledThemes' => ['default'],
|
||||
]],
|
||||
['name1', 'url2', 'slogan3', '#01e4a0', '#ffffff', 'logo5', 'background6', '#fff', '#000', 'http://localhost/', false, [
|
||||
['name1', 'url2', 'slogan3', '#01e4a0', '#ffffff', 'logo5', 'background6', '#fff', '#000', 'http://localhost/', false, '', '', '#0082c9', [
|
||||
'name' => 'name1',
|
||||
'productName' => 'name1',
|
||||
'url' => 'url2',
|
||||
'imprintUrl' => '',
|
||||
'privacyUrl' => '',
|
||||
'slogan' => 'slogan3',
|
||||
'color' => '#01e4a0',
|
||||
'color-text' => '#ffffff',
|
||||
|
|
@ -87,11 +109,20 @@ class CapabilitiesTest extends TestCase {
|
|||
'background-default' => true,
|
||||
'logoheader' => 'http://localhost/logo5',
|
||||
'favicon' => 'http://localhost/logo5',
|
||||
'primaryColor' => '#01e4a0',
|
||||
'backgroundColor' => '#fff',
|
||||
'defaultPrimaryColor' => '#01e4a0',
|
||||
'defaultBackgroundColor' => '#0082c9',
|
||||
'inverted' => false,
|
||||
'cacheBuster' => 'v1',
|
||||
'enabledThemes' => ['default'],
|
||||
]],
|
||||
['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', '#000000', '#ffffff', 'http://localhost/', true, [
|
||||
['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', '#000000', '#ffffff', 'http://localhost/', true, '', '', '#0082c9', [
|
||||
'name' => 'name1',
|
||||
'productName' => 'name1',
|
||||
'url' => 'url2',
|
||||
'imprintUrl' => '',
|
||||
'privacyUrl' => '',
|
||||
'slogan' => 'slogan3',
|
||||
'color' => '#000000',
|
||||
'color-text' => '#ffffff',
|
||||
|
|
@ -105,11 +136,20 @@ class CapabilitiesTest extends TestCase {
|
|||
'background-default' => false,
|
||||
'logoheader' => 'http://localhost/logo5',
|
||||
'favicon' => 'http://localhost/logo5',
|
||||
'primaryColor' => '#000000',
|
||||
'backgroundColor' => '#000000',
|
||||
'defaultPrimaryColor' => '#000000',
|
||||
'defaultBackgroundColor' => '#0082c9',
|
||||
'inverted' => false,
|
||||
'cacheBuster' => 'v1',
|
||||
'enabledThemes' => ['default'],
|
||||
]],
|
||||
['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', '#000000', '#ffffff', 'http://localhost/', false, [
|
||||
['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', '#000000', '#ffffff', 'http://localhost/', false, '', '', '#0082c9', [
|
||||
'name' => 'name1',
|
||||
'productName' => 'name1',
|
||||
'url' => 'url2',
|
||||
'imprintUrl' => '',
|
||||
'privacyUrl' => '',
|
||||
'slogan' => 'slogan3',
|
||||
'color' => '#000000',
|
||||
'color-text' => '#ffffff',
|
||||
|
|
@ -123,17 +163,25 @@ class CapabilitiesTest extends TestCase {
|
|||
'background-default' => true,
|
||||
'logoheader' => 'http://localhost/logo5',
|
||||
'favicon' => 'http://localhost/logo5',
|
||||
'primaryColor' => '#000000',
|
||||
'backgroundColor' => '#000000',
|
||||
'defaultPrimaryColor' => '#000000',
|
||||
'defaultBackgroundColor' => '#0082c9',
|
||||
'inverted' => false,
|
||||
'cacheBuster' => 'v1',
|
||||
'enabledThemes' => ['default'],
|
||||
]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param non-empty-array<string, string> $expected
|
||||
* @param array<string, mixed> $expected
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataGetCapabilities')]
|
||||
public function testGetCapabilities(string $name, string $url, string $slogan, string $color, string $textColor, string $logo, string $background, string $backgroundColor, string $backgroundTextColor, string $baseUrl, bool $backgroundThemed, array $expected): void {
|
||||
$this->config->expects($this->once())
|
||||
->method('getAppValue')
|
||||
public function testGetCapabilities(string $name, string $url, string $slogan, string $color, string $textColor, string $logo, string $background, string $backgroundColor, string $backgroundTextColor, string $baseUrl, bool $backgroundThemed, string $imprintUrl, string $privacyUrl, string $defaultBackgroundColor, array $expected): void {
|
||||
$this->appConfig->expects($this->once())
|
||||
->method('getValueString')
|
||||
->with('theming', 'backgroundMime', '')
|
||||
->willReturn($background);
|
||||
$this->theming->expects($this->once())
|
||||
->method('getName')
|
||||
|
|
@ -144,6 +192,12 @@ class CapabilitiesTest extends TestCase {
|
|||
$this->theming->expects($this->once())
|
||||
->method('getBaseUrl')
|
||||
->willReturn($url);
|
||||
$this->theming->expects($this->once())
|
||||
->method('getImprintUrl')
|
||||
->willReturn($imprintUrl);
|
||||
$this->theming->expects($this->once())
|
||||
->method('getPrivacyUrl')
|
||||
->willReturn($privacyUrl);
|
||||
$this->theming->expects($this->once())
|
||||
->method('getSlogan')
|
||||
->willReturn($slogan);
|
||||
|
|
@ -153,6 +207,9 @@ class CapabilitiesTest extends TestCase {
|
|||
$this->theming->expects($this->once())
|
||||
->method('getTextColorBackground')
|
||||
->willReturn($backgroundTextColor);
|
||||
$this->theming->expects($this->once())
|
||||
->method('getDefaultColorBackground')
|
||||
->willReturn($defaultBackgroundColor);
|
||||
$this->theming->expects($this->atLeast(1))
|
||||
->method('getDefaultColorPrimary')
|
||||
->willReturn($color);
|
||||
|
|
@ -160,20 +217,25 @@ class CapabilitiesTest extends TestCase {
|
|||
->method('getLogo')
|
||||
->willReturn($logo);
|
||||
|
||||
$util = new Util($this->createMock(ServerVersion::class), $this->config, $this->createMock(IAppManager::class), $this->createMock(IAppData::class), $this->createMock(ImageManager::class));
|
||||
$util = new Util($this->createMock(ServerVersion::class), $this->createMock(IConfig::class), $this->createMock(IAppManager::class), $this->createMock(IAppData::class), $this->createMock(ImageManager::class));
|
||||
$this->util->expects($this->exactly(3))
|
||||
->method('elementColor')
|
||||
->with($color)
|
||||
->willReturnCallback(static function (string $color, ?bool $brightBackground = null) use ($util) {
|
||||
return $util->elementColor($color, $brightBackground);
|
||||
});
|
||||
|
||||
$this->util->expects($this->any())
|
||||
->method('invertTextColor')
|
||||
->willReturnCallback(fn () => $textColor === '#000000');
|
||||
$this->util->expects($this->once())
|
||||
->method('isBackgroundThemed')
|
||||
->willReturn($backgroundThemed);
|
||||
$this->util->expects($this->once())
|
||||
->method('getCacheBuster')
|
||||
->willReturn('v1');
|
||||
$this->themesService->expects($this->once())
|
||||
->method('getEnabledThemes')
|
||||
->willReturn(['default']);
|
||||
|
||||
if ($background !== 'backgroundColor') {
|
||||
$this->theming->expects($this->once())
|
||||
|
|
@ -194,4 +256,87 @@ class CapabilitiesTest extends TestCase {
|
|||
|
||||
$this->assertEquals(['theming' => $expected], $this->capabilities->getCapabilities());
|
||||
}
|
||||
|
||||
public static function dataGetCapabilitiesWithUser(): array {
|
||||
return [
|
||||
'default background' => [
|
||||
BackgroundService::BACKGROUND_DEFAULT,
|
||||
false,
|
||||
'http://localhost/background',
|
||||
],
|
||||
'custom background' => [
|
||||
BackgroundService::BACKGROUND_CUSTOM,
|
||||
false,
|
||||
'http://localhost/route',
|
||||
],
|
||||
'shipped background' => [
|
||||
'jo-myoung-hee-fluid.webp',
|
||||
false,
|
||||
'http://localhost/img',
|
||||
],
|
||||
'solid color background' => [
|
||||
'solid',
|
||||
true,
|
||||
BackgroundService::DEFAULT_COLOR,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataGetCapabilitiesWithUser')]
|
||||
public function testGetCapabilitiesWithUser(string $backgroundImage, bool $expectedBackgroundPlain, string $expectedBackground): void {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user->method('getUID')->willReturn('user1');
|
||||
$this->userSession->method('getUser')->willReturn($user);
|
||||
|
||||
$userColor = '#00679e';
|
||||
$defaultColor = '#0082c9';
|
||||
|
||||
$this->theming->method('getDefaultColorPrimary')->willReturn($defaultColor);
|
||||
$this->theming->method('getColorPrimary')->willReturn($userColor);
|
||||
$this->theming->method('getTextColorPrimary')->willReturn('#ffffff');
|
||||
$this->theming->method('getName')->willReturn('Name');
|
||||
$this->theming->method('getProductName')->willReturn('Name');
|
||||
$this->theming->method('getBaseUrl')->willReturn('http://example.com/');
|
||||
$this->theming->method('getImprintUrl')->willReturn('');
|
||||
$this->theming->method('getPrivacyUrl')->willReturn('');
|
||||
$this->theming->method('getSlogan')->willReturn('Slogan');
|
||||
$this->theming->method('getColorBackground')->willReturn(BackgroundService::DEFAULT_COLOR);
|
||||
$this->theming->method('getTextColorBackground')->willReturn('#ffffff');
|
||||
$this->theming->method('getDefaultColorBackground')->willReturn('#0082c9');
|
||||
$this->theming->method('getLogo')->willReturn('/logo');
|
||||
$this->theming->method('getBackground')->willReturn('/background');
|
||||
|
||||
$this->appConfig->method('getValueString')->willReturn('');
|
||||
$this->userConfig->method('getValueString')->willReturn($backgroundImage);
|
||||
|
||||
$this->util->method('invertTextColor')->willReturn(false);
|
||||
$this->util->method('elementColor')->willReturn($userColor);
|
||||
$this->util->method('isBackgroundThemed')->willReturn(false);
|
||||
$this->util->method('getCacheBuster')->willReturn('v1');
|
||||
|
||||
$this->themesService->method('getEnabledThemes')->willReturn(['default']);
|
||||
|
||||
$this->url->method('getAbsoluteURL')->willReturnCallback(fn (string $url) => 'http://localhost' . $url);
|
||||
$this->url->method('linkToRouteAbsolute')->willReturn('http://localhost/route');
|
||||
$this->url->method('linkTo')->willReturn('http://localhost/img');
|
||||
|
||||
$result = $this->capabilities->getCapabilities();
|
||||
$theming = $result['theming'];
|
||||
|
||||
// For logged-in users, color/primaryColor reflect getColorPrimary(), not getDefaultColorPrimary()
|
||||
$this->assertSame($userColor, $theming['color']);
|
||||
$this->assertSame($userColor, $theming['primaryColor']);
|
||||
// color-text comes from getTextColorPrimary() directly, not invertTextColor()
|
||||
$this->assertSame('#ffffff', $theming['color-text']);
|
||||
// inverted uses invertTextColor() with the user's active color
|
||||
$this->assertSame(false, $theming['inverted']);
|
||||
// defaultPrimaryColor always reflects the admin-configured default
|
||||
$this->assertSame($defaultColor, $theming['defaultPrimaryColor']);
|
||||
// Background varies by user's background_image setting
|
||||
$this->assertSame($expectedBackgroundPlain, $theming['background-plain']);
|
||||
$this->assertSame($expectedBackground, $theming['background']);
|
||||
// New fields are always present
|
||||
$this->assertSame('v1', $theming['cacheBuster']);
|
||||
$this->assertSame(['default'], $theming['enabledThemes']);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2364,12 +2364,6 @@
|
|||
<code><![CDATA[FakeTranslationProvider]]></code>
|
||||
</DeprecatedInterface>
|
||||
</file>
|
||||
<file src="apps/theming/lib/Capabilities.php">
|
||||
<DeprecatedMethod>
|
||||
<code><![CDATA[getAppValue]]></code>
|
||||
<code><![CDATA[getUserValue]]></code>
|
||||
</DeprecatedMethod>
|
||||
</file>
|
||||
<file src="apps/theming/lib/Command/UpdateConfig.php">
|
||||
<DeprecatedMethod>
|
||||
<code><![CDATA[getAppValue]]></code>
|
||||
|
|
@ -2414,6 +2408,9 @@
|
|||
</DeprecatedMethod>
|
||||
</file>
|
||||
<file src="apps/theming/lib/Listener/BeforeTemplateRenderedListener.php">
|
||||
<DeprecatedClass>
|
||||
<code><![CDATA[JSDataService::class]]></code>
|
||||
</DeprecatedClass>
|
||||
<DeprecatedMethod>
|
||||
<code><![CDATA[getUserValue]]></code>
|
||||
</DeprecatedMethod>
|
||||
|
|
|
|||
41
openapi.json
41
openapi.json
|
|
@ -4225,6 +4225,8 @@
|
|||
"name",
|
||||
"productName",
|
||||
"url",
|
||||
"imprintUrl",
|
||||
"privacyUrl",
|
||||
"slogan",
|
||||
"color",
|
||||
"color-text",
|
||||
|
|
@ -4237,7 +4239,14 @@
|
|||
"background-plain",
|
||||
"background-default",
|
||||
"logoheader",
|
||||
"favicon"
|
||||
"favicon",
|
||||
"primaryColor",
|
||||
"backgroundColor",
|
||||
"defaultPrimaryColor",
|
||||
"defaultBackgroundColor",
|
||||
"inverted",
|
||||
"cacheBuster",
|
||||
"enabledThemes"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
|
|
@ -4249,6 +4258,12 @@
|
|||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"imprintUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"privacyUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"slogan": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -4287,6 +4302,30 @@
|
|||
},
|
||||
"favicon": {
|
||||
"type": "string"
|
||||
},
|
||||
"primaryColor": {
|
||||
"type": "string"
|
||||
},
|
||||
"backgroundColor": {
|
||||
"type": "string"
|
||||
},
|
||||
"defaultPrimaryColor": {
|
||||
"type": "string"
|
||||
},
|
||||
"defaultBackgroundColor": {
|
||||
"type": "string"
|
||||
},
|
||||
"inverted": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"cacheBuster": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabledThemes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue