aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFerdinand Thiessen <opensource@fthiessen.de>2025-01-24 12:52:33 +0100
committerFerdinand Thiessen <opensource@fthiessen.de>2025-01-29 09:52:04 +0100
commitc244364f72b800e89f6fbcaee3db32ccf29a62e9 (patch)
tree5a4f9a87ce75bcafef43348e90631dc1a6d0a095
parent7a8285b281a4bff5a4162177bcd175300fd841b9 (diff)
downloadnextcloud-server-backport/50398/stable29.tar.gz
nextcloud-server-backport/50398/stable29.zip
fix: Correctly return app id and app version for `core` styles and imagesbackport/50398/stable29
fix(TemplateLayout): `core` is not an app but the server itself Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
-rw-r--r--lib/private/App/AppManager.php8
-rw-r--r--lib/private/TemplateLayout.php19
-rw-r--r--tests/lib/App/AppManagerTest.php95
-rw-r--r--tests/lib/AppTest.php48
4 files changed, 141 insertions, 29 deletions
diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php
index c6e6ba2975e..08bcd4ade80 100644
--- a/lib/private/App/AppManager.php
+++ b/lib/private/App/AppManager.php
@@ -739,8 +739,12 @@ class AppManager implements IAppManager {
public function getAppVersion(string $appId, bool $useCache = true): string {
if (!$useCache || !isset($this->appVersions[$appId])) {
- $appInfo = $this->getAppInfo($appId);
- $this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0';
+ if ($appId === 'core') {
+ $this->appVersions[$appId] = \OC_Util::getVersionString();
+ } else {
+ $appInfo = $this->getAppInfo($appId);
+ $this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0';
+ }
}
return $this->appVersions[$appId];
}
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index 3f6521a8e37..cb2678acce4 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -358,13 +358,18 @@ class TemplateLayout extends \OC_Template {
return false;
}
- $appVersion = $this->appManager->getAppVersion($appId);
- // For shipped apps the app version is not a single source of truth, we rather also need to consider the Nextcloud version
- if ($this->appManager->isShipped($appId)) {
- $appVersion .= '-' . self::$versionHash;
- }
+ if ($appId === 'core') {
+ // core is not a real app but the server itself
+ $hash = self::$versionHash;
+ } else {
+ $appVersion = $this->appManager->getAppVersion($appId);
+ // For shipped apps the app version is not a single source of truth, we rather also need to consider the Nextcloud version
+ if ($this->appManager->isShipped($appId)) {
+ $appVersion .= '-' . self::$versionHash;
+ }
- $hash = substr(md5($appVersion), 0, 8);
+ $hash = substr(md5($appVersion), 0, 8);
+ }
self::$cacheBusterCache[$path] = $hash;
}
@@ -392,6 +397,8 @@ class TemplateLayout extends \OC_Template {
if ($pathParts[0] === 'css') {
// This is a scss request
return $pathParts[1];
+ } elseif ($pathParts[0] === 'core') {
+ return 'core';
}
return end($pathParts);
}
diff --git a/tests/lib/App/AppManagerTest.php b/tests/lib/App/AppManagerTest.php
index dfbaedff957..b07a3d1ad72 100644
--- a/tests/lib/App/AppManagerTest.php
+++ b/tests/lib/App/AppManagerTest.php
@@ -116,6 +116,10 @@ class AppManagerTest extends TestCase {
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
+
+ $this->overwriteService(AppConfig::class, $this->appConfig);
+ $this->overwriteService(IURLGenerator::class, $this->urlGenerator);
+
$this->cacheFactory->expects($this->any())
->method('createDistributed')
->with('settings')
@@ -132,6 +136,14 @@ class AppManagerTest extends TestCase {
);
}
+ protected function tearDown(): void {
+ parent::tearDown();
+
+ // Reset static OC_Util
+ $util = new \OC_Util();
+ self::invokePrivate($util, 'versionCache', [null]);
+ }
+
/**
* @dataProvider dataGetAppIcon
*/
@@ -888,4 +900,87 @@ class AppManagerTest extends TestCase {
$this->assertEquals($expectedApp, $this->manager->getDefaultAppForUser(null, $withFallbacks));
}
+
+ public function testGetAppVersion() {
+ $manager = $this->getMockBuilder(AppManager::class)
+ ->setConstructorArgs([
+ $this->userSession,
+ $this->config,
+ $this->appConfig,
+ $this->groupManager,
+ $this->cacheFactory,
+ $this->eventDispatcher,
+ $this->logger,
+ ])
+ ->onlyMethods([
+ 'getAppInfo',
+ ])
+ ->getMock();
+
+ $manager->expects(self::once())
+ ->method('getAppInfo')
+ ->with('myapp')
+ ->willReturn(['version' => '99.99.99-rc.99']);
+
+ $this->assertEquals(
+ '99.99.99-rc.99',
+ $manager->getAppVersion('myapp'),
+ );
+ }
+
+ public function testGetAppVersionCore() {
+ $manager = $this->getMockBuilder(AppManager::class)
+ ->setConstructorArgs([
+ $this->userSession,
+ $this->config,
+ $this->appConfig,
+ $this->groupManager,
+ $this->cacheFactory,
+ $this->eventDispatcher,
+ $this->logger,
+ ])
+ ->onlyMethods([
+ 'getAppInfo',
+ ])
+ ->getMock();
+
+ $manager->expects(self::never())
+ ->method('getAppInfo');
+
+ $util = new \OC_Util();
+ self::invokePrivate($util, 'versionCache', [['OC_VersionString' => '1.2.3-beta.4']]);
+
+ $this->assertEquals(
+ '1.2.3-beta.4',
+ $manager->getAppVersion('core'),
+ );
+ }
+
+ public function testGetAppVersionUnknown() {
+ $manager = $this->getMockBuilder(AppManager::class)
+ ->setConstructorArgs([
+ $this->userSession,
+ $this->config,
+ $this->appConfig,
+ $this->groupManager,
+ $this->cacheFactory,
+ $this->eventDispatcher,
+ $this->logger,
+ ])
+ ->onlyMethods([
+ 'getAppInfo',
+ ])
+ ->getMock();
+
+ $manager->expects(self::once())
+ ->method('getAppInfo')
+ ->with('unknown')
+ ->willReturn(null);
+
+ $this->assertEquals(
+ '0',
+ $manager->getAppVersion('unknown'),
+ );
+ }
+
}
diff --git a/tests/lib/AppTest.php b/tests/lib/AppTest.php
index 4e723e5d2f1..be1770afc0e 100644
--- a/tests/lib/AppTest.php
+++ b/tests/lib/AppTest.php
@@ -14,7 +14,13 @@ use OC\App\InfoParser;
use OC\AppConfig;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IAppConfig;
+use OCP\ICacheFactory;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\IGroupManager;
use OCP\IURLGenerator;
+use OCP\IUserManager;
+use OCP\IUserSession;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
@@ -459,12 +465,12 @@ class AppTest extends \Test\TestCase {
*
* @dataProvider appConfigValuesProvider
*/
- public function testEnabledApps($user, $expectedApps, $forceAll) {
- $userManager = \OC::$server->getUserManager();
- $groupManager = \OC::$server->getGroupManager();
- $user1 = $userManager->createUser(self::TEST_USER1, self::TEST_USER1);
- $user2 = $userManager->createUser(self::TEST_USER2, self::TEST_USER2);
- $user3 = $userManager->createUser(self::TEST_USER3, self::TEST_USER3);
+ public function testEnabledApps($user, $expectedApps, $forceAll): void {
+ $userManager = \OCP\Server::get(IUserManager::class);
+ $groupManager = \OCP\Server::get(IGroupManager::class);
+ $user1 = $userManager->createUser(self::TEST_USER1, 'NotAnEasyPassword123456+');
+ $user2 = $userManager->createUser(self::TEST_USER2, 'NotAnEasyPassword123456_');
+ $user3 = $userManager->createUser(self::TEST_USER3, 'NotAnEasyPassword123456?');
$group1 = $groupManager->createGroup(self::TEST_GROUP1);
$group1->addUser($user1);
@@ -508,9 +514,9 @@ class AppTest extends \Test\TestCase {
* Test isEnabledApps() with cache, not re-reading the list of
* enabled apps more than once when a user is set.
*/
- public function testEnabledAppsCache() {
- $userManager = \OC::$server->getUserManager();
- $user1 = $userManager->createUser(self::TEST_USER1, self::TEST_USER1);
+ public function testEnabledAppsCache(): void {
+ $userManager = \OCP\Server::get(IUserManager::class);
+ $user1 = $userManager->createUser(self::TEST_USER1, 'NotAnEasyPassword123456+');
\OC_User::setUserId(self::TEST_USER1);
@@ -541,8 +547,8 @@ class AppTest extends \Test\TestCase {
private function setupAppConfigMock() {
/** @var AppConfig|MockObject */
$appConfig = $this->getMockBuilder(AppConfig::class)
- ->setMethods(['getValues'])
- ->setConstructorArgs([\OC::$server->getDatabaseConnection()])
+ ->onlyMethods(['getValues'])
+ ->setConstructorArgs([\OCP\Server::get(IDBConnection::class)])
->disableOriginalConstructor()
->getMock();
@@ -558,14 +564,14 @@ class AppTest extends \Test\TestCase {
private function registerAppConfig(AppConfig $appConfig) {
$this->overwriteService(AppConfig::class, $appConfig);
$this->overwriteService(AppManager::class, new AppManager(
- \OC::$server->getUserSession(),
- \OC::$server->getConfig(),
- $appConfig,
- \OC::$server->getGroupManager(),
- \OC::$server->getMemCacheFactory(),
- \OC::$server->get(IEventDispatcher::class),
- \OC::$server->get(LoggerInterface::class),
- \OC::$server->get(IURLGenerator::class),
+ \OCP\Server::get(IUserSession::class),
+ \OCP\Server::get(IConfig::class),
+ \OCP\Server::get(IAppConfig::class),
+ \OCP\Server::get(IGroupManager::class),
+ \OCP\Server::get(ICacheFactory::class),
+ \OCP\Server::get(IEventDispatcher::class),
+ \OCP\Server::get(LoggerInterface::class),
+ \OCP\Server::get(IURLGenerator::class),
));
}
@@ -624,14 +630,14 @@ class AppTest extends \Test\TestCase {
public function testParseAppInfoL10N() {
$parser = new InfoParser();
- $data = $parser->parse(\OC::$SERVERROOT. "/tests/data/app/description-multi-lang.xml");
+ $data = $parser->parse(\OC::$SERVERROOT . '/tests/data/app/description-multi-lang.xml');
$this->assertEquals('English', \OC_App::parseAppInfo($data, 'en')['description']);
$this->assertEquals('German', \OC_App::parseAppInfo($data, 'de')['description']);
}
public function testParseAppInfoL10NSingleLanguage() {
$parser = new InfoParser();
- $data = $parser->parse(\OC::$SERVERROOT. "/tests/data/app/description-single-lang.xml");
+ $data = $parser->parse(\OC::$SERVERROOT . '/tests/data/app/description-single-lang.xml');
$this->assertEquals('English', \OC_App::parseAppInfo($data, 'en')['description']);
}
}