diff --git a/lib/private/Server.php b/lib/private/Server.php index 66a00450c588..44de9ebae00a 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -808,6 +808,7 @@ public function __construct($webRoot, \OC\Config $config) { $this->registerService('ThemeService', function ($c) { return new ThemeService($this->getSystemConfig()->getValue('theme')); }); + $this->registerAlias('OCP\Theme\IThemeService', 'ThemeService'); $this->registerAlias('OCP\IUserSession', 'UserSession'); $this->registerAlias('OCP\Security\ICrypto', 'Crypto'); } diff --git a/lib/private/Template/Base.php b/lib/private/Template/Base.php index e19027af0321..ea33268acf29 100644 --- a/lib/private/Template/Base.php +++ b/lib/private/Template/Base.php @@ -30,7 +30,7 @@ namespace OC\Template; -use OC\Theme\Theme; +use OCP\Theme\ITheme; class Base { /** @@ -49,7 +49,7 @@ class Base { private $l10n; /** - * @var Theme + * @var ITheme */ protected $theme; @@ -62,7 +62,7 @@ class Base { * @param string $template * @param string $requestToken * @param \OCP\IL10N $l10n - * @param Theme $theme + * @param ITheme $theme * @param \OC_Defaults $themeDefaults */ public function __construct($template, $requestToken, $l10n, $theme, $themeDefaults) { @@ -77,7 +77,7 @@ public function __construct($template, $requestToken, $l10n, $theme, $themeDefau /** * @param string $serverRoot * @param string|false $app_dir - * @param Theme $theme + * @param ITheme $theme * @param string $app * @return string[] */ @@ -97,7 +97,7 @@ protected function getAppTemplateDirs($theme, $app, $serverRoot, $app_dir) { /** * @param string $serverRoot - * @param Theme $theme + * @param ITheme $theme * @return string[] */ protected function getCoreTemplateDirs($theme, $serverRoot) { diff --git a/lib/private/Template/ResourceLocator.php b/lib/private/Template/ResourceLocator.php index 5292ce8b7318..2ffd90cf1c1e 100644 --- a/lib/private/Template/ResourceLocator.php +++ b/lib/private/Template/ResourceLocator.php @@ -28,11 +28,11 @@ namespace OC\Template; -use OC\Theme\Theme; +use OCP\Theme\ITheme; abstract class ResourceLocator { /** - * @var Theme + * @var ITheme */ protected $theme; @@ -48,7 +48,7 @@ abstract class ResourceLocator { /** * @param \OCP\ILogger $logger - * @param Theme $theme + * @param ITheme $theme * @param array $core_map * @param array $party_map */ diff --git a/lib/private/Theme/Theme.php b/lib/private/Theme/Theme.php index 2f4e3656666e..efd9e7d68668 100644 --- a/lib/private/Theme/Theme.php +++ b/lib/private/Theme/Theme.php @@ -1,6 +1,5 @@ * @author Philipp Schaffrath * * @copyright Copyright (c) 2017, ownCloud GmbH @@ -17,11 +16,12 @@ * * You should have received a copy of the GNU Affero General Public License, version 3, * along with this program. If not, see - * */ namespace OC\Theme; -class Theme { +use OCP\Theme\ITheme; + +class Theme implements ITheme { /** * @var string @@ -39,14 +39,14 @@ class Theme { private $webPath; /** - * Theme constructor. - * * @param string $name * @param string $directory + * @param string $webPath */ - public function __construct($name = '', $directory = '') { + public function __construct($name = '', $directory = '', $webPath = '') { $this->name = $name; $this->directory = $directory; + $this->webPath = $webPath; } /** @@ -57,31 +57,31 @@ public function getName() { } /** - * @param $name + * @return string */ - public function setName($name) { - $this->name = $name; + public function getDirectory() { + return $this->directory; } /** * @return string */ - public function getDirectory() { - return $this->directory; + public function getWebPath() { + return $this->webPath; } /** - * @param string $directory + * @param string $name */ - public function setDirectory($directory) { - $this->directory = $directory; + public function setName($name) { + $this->name = $name; } /** - * @return string + * @param string $directory */ - public function getWebPath() { - return $this->webPath; + public function setDirectory($directory) { + $this->directory = $directory; } /** diff --git a/lib/private/Theme/ThemeService.php b/lib/private/Theme/ThemeService.php index b84293beafee..09fb5dd31947 100644 --- a/lib/private/Theme/ThemeService.php +++ b/lib/private/Theme/ThemeService.php @@ -1,6 +1,5 @@ * @author Philipp Schaffrath * * @copyright Copyright (c) 2017, ownCloud GmbH @@ -17,11 +16,12 @@ * * You should have received a copy of the GNU Affero General Public License, version 3, * along with this program. If not, see - * */ namespace OC\Theme; -class ThemeService { +use OCP\Theme\IThemeService; + +class ThemeService implements IThemeService { /** * @var Theme @@ -39,7 +39,12 @@ class ThemeService { */ public function __construct($themeName = '', $defaultThemeDirectory = '') { $this->setDefaultThemeDirectory($defaultThemeDirectory); - $this->createTheme($themeName); + + if ($themeName === '' && $this->defaultThemeExists()) { + $themeName = 'default'; + } + + $this->theme = $this->makeTheme($themeName, false); } /** @@ -53,58 +58,138 @@ private function setDefaultThemeDirectory($defaultThemeDirectory = '') { } } + /** + * @return bool + */ + private function defaultThemeExists() { + if (is_dir($this->defaultThemeDirectory)) { + return true; + } + + return false; + } + + /** + * @return Theme + */ + public function getTheme() { + return $this->theme; + } + /** * @param string $themeName */ - private function createTheme($themeName = '') { - if ($themeName === '' && $this->defaultThemeExists()) { - $themeName = 'default'; + public function setAppTheme($themeName = '') { + $this->theme = $this->makeTheme($themeName, true, $this->getTheme()); + } + + /** + * @param string $themeName + * @param bool $appTheme + * @param Theme $theme + * @return Theme + */ + private function makeTheme($themeName, $appTheme = true, Theme $theme = null) { + $directory = $this->getDirectory($themeName, $appTheme); + $webPath = $this->getWebPath($themeName, $appTheme); + + if (is_null($theme)) { + $theme = new Theme( + $themeName, + $directory, + $webPath + ); + } else { + $theme->setName($themeName); + $theme->setDirectory($directory); + $theme->setWebPath($webPath); } - $this->theme = new Theme($themeName, $this->getThemeDirectory($themeName)); + return $theme; } /** * @param string $themeName + * @param bool $appTheme * @return string */ - private function getThemeDirectory($themeName) { + private function getDirectory($themeName, $appTheme = true) { if ($themeName !== '') { - return 'themes/' . $themeName . '/'; - } else { - return ''; + if ($appTheme) { + return substr(\OC_App::getAppPath($themeName), strlen(\OC::$SERVERROOT) + 1); + } + return 'themes/' . $themeName; } + + return ''; } /** - * @return bool + * @param $themeName + * @param bool $appTheme + * @return false|string */ - private function defaultThemeExists() { - if (is_dir($this->defaultThemeDirectory)) { - return true; + private function getWebPath($themeName, $appTheme = true) { + if ($themeName !== '') { + if ($appTheme) { + $appWebPath = \OC_App::getAppWebPath($themeName); + return $appWebPath ? $appWebPath : ''; + } + return '/themes/' . $themeName; } - return false; + return ''; } /** - * @return Theme + * @return Theme[] */ - public function getTheme() { - return $this->theme; + public function getAllThemes() { + return array_merge($this->getAllAppThemes(), $this->getAllLegacyThemes()); } /** - * @param string $appName + * @return Theme[] */ - public function setAppTheme($appName = '') { - if ($appName !== '') { - $this->theme->setDirectory( - substr(\OC_App::getAppPath($appName), strlen(\OC::$SERVERROOT) + 1) - ); - $appWebPath = \OC_App::getAppWebPath($appName); - $this->theme->setWebPath($appWebPath ? $appWebPath : ''); - $this->theme->setName($appName); + private function getAllAppThemes() { + $themes = []; + foreach (\OC::$server->getAppManager()->getAllApps() as $app) { + if (\OC_App::isType($app, 'theme')) { + $themes[$app] = $this->makeTheme($app); + } + } + return $themes; + } + + /** + * @return Theme[] + */ + private function getAllLegacyThemes() { + $themes = []; + if ($handle = opendir(\OC::$SERVERROOT . '/themes')) { + while (false !== ($entry = readdir($handle))) { + if ($entry === '.' || $entry === '..') { + continue; + } + if (is_dir(\OC::$SERVERROOT . '/themes/' . $entry)) { + $themes[$entry] = $this->makeTheme($entry, false); + } + } + closedir($handle); + return $themes; } + return $themes; + } + + /** + * @param string $themeName + * @return Theme|false + */ + public function findTheme($themeName) { + $allThemes = $this->getAllThemes(); + if (array_key_exists($themeName, $allThemes)) { + return $allThemes[$themeName]; + } + return false; } } diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php index 7db937c13942..6c6108d6c6c9 100644 --- a/lib/private/URLGenerator.php +++ b/lib/private/URLGenerator.php @@ -30,7 +30,7 @@ */ namespace OC; -use OC\Theme\Theme; +use OCP\Theme\ITheme; use OC_Defaults; use OCP\ICacheFactory; use OCP\IConfig; @@ -48,7 +48,7 @@ class URLGenerator implements IURLGenerator { private $cacheFactory; /** @var IRouter */ private $router; - /** @var Theme */ + /** @var ITheme */ private $theme; /** @@ -187,7 +187,7 @@ private function getImagePath($app, $imageName) { $file = $directory . $imageName; if (!empty($themeDirectory)) { - if ($imagePath = $this->getImagePathOrFallback('/' . $this->theme->getDirectory() . '/' . $file)) { + if ($imagePath = $this->getImagePathOrFallback('/' . $this->theme->getDirectory() . $file)) { return $imagePath; } } diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php index de59068a8856..489f9855406b 100644 --- a/lib/private/legacy/app.php +++ b/lib/private/legacy/app.php @@ -179,9 +179,9 @@ public static function loadApp($app, $checkUpgrade = true) { */ private static function enableThemeIfApplicable($app) { if (self::isType($app, 'theme')) { - /** @var \OC\Theme\ThemeService $themeManager */ - $themeManager = \OC::$server->query('ThemeService'); - $themeManager->setAppTheme($app); + /** @var \OCP\Theme\IThemeService $themeService */ + $themeService = \OC::$server->query('ThemeService'); + $themeService->setAppTheme($app); } } diff --git a/lib/private/legacy/template.php b/lib/private/legacy/template.php index 5c4a4fef61e5..3d5d4574ce65 100644 --- a/lib/private/legacy/template.php +++ b/lib/private/legacy/template.php @@ -37,7 +37,7 @@ */ use OC\TemplateLayout; -use OC\Theme\Theme; +use OCP\Theme\ITheme; require_once __DIR__.'/template/functions.php'; @@ -183,7 +183,7 @@ public static function initTemplateEngine($renderAs) { * * Will select the template file for the selected theme. * Checking all the possible locations. - * @param Theme $theme + * @param ITheme $theme * @param string $app * @return string */ diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php index c22db5083efc..c44f828a3f8d 100644 --- a/lib/private/legacy/util.php +++ b/lib/private/legacy/util.php @@ -1271,10 +1271,10 @@ public static function runningOnHhvm() { * Handles the case that there may not be a theme, then check if a "default" * theme exists and take that one * - * @return \OC\Theme\Theme the theme + * @return \OCP\Theme\ITheme the theme */ public static function getTheme() { - /** @var \OC\Theme\ThemeService $themeService */ + /** @var \OCP\Theme\IThemeService $themeService */ $themeService = \OC::$server->query('ThemeService'); return $themeService->getTheme(); } diff --git a/lib/public/Theme/ITheme.php b/lib/public/Theme/ITheme.php new file mode 100644 index 000000000000..c73390c975d7 --- /dev/null +++ b/lib/public/Theme/ITheme.php @@ -0,0 +1,64 @@ + + * + * @copyright Copyright (c) 2017, ownCloud GmbH + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + */ +namespace OCP\Theme; + +/** + * The representation of a Theme. + * @package OCP\Theme + * @since 10.0.3 + */ +interface ITheme { + + /** + * @return string + * @since 10.0.3 + */ + public function getName(); + + /** + * @return string + * @since 10.0.3 + */ + public function getDirectory(); + + /** + * @return string + * @since 10.0.3 + */ + public function getWebPath(); + + /** + * @param string $name + * @since 10.0.3 + */ + public function setName($name); + + /** + * @param string $directory + * @since 10.0.3 + */ + public function setDirectory($directory); + + /** + * @param string $webPath + * @since 10.0.3 + */ + public function setWebPath($webPath); +} diff --git a/lib/public/Theme/IThemeService.php b/lib/public/Theme/IThemeService.php new file mode 100644 index 000000000000..1661492ae873 --- /dev/null +++ b/lib/public/Theme/IThemeService.php @@ -0,0 +1,57 @@ + + * + * @copyright Copyright (c) 2017, ownCloud GmbH + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + */ +namespace OCP\Theme; + +/** + * @package OCP\Theme + * @since 10.0.3 + */ +interface IThemeService { + + /** + * Returns the currently active theme. + * @return ITheme + * @since 10.0.3 + */ + public function getTheme(); + + /** + * Sets an app as the active theme. + * @param string $themeName + * @since 10.0.3 + */ + public function setAppTheme($themeName = ''); + + /** + * Gets legacy and app themes as an array of ITheme's. + * @return ITheme[] + * @since 10.0.3 + */ + public function getAllThemes(); + + /** + * Returns an ITheme by its name, or false if there is no theme + * with that name. + * @param string $themeName + * @return ITheme|false + * @since 10.0.3 + */ + public function findTheme($themeName); +} diff --git a/tests/lib/Theme/ThemeServiceTest.php b/tests/lib/Theme/ThemeServiceTest.php index df0cacbff790..1ad2e5edab0a 100644 --- a/tests/lib/Theme/ThemeServiceTest.php +++ b/tests/lib/Theme/ThemeServiceTest.php @@ -22,7 +22,7 @@ public function testCreatesThemeByGivenName() { $themeService = new ThemeService('theme-name'); $theme = $themeService->getTheme(); $this->assertEquals('theme-name', $theme->getName()); - $this->assertEquals('themes/theme-name/', $theme->getDirectory()); + $this->assertEquals('themes/theme-name', $theme->getDirectory()); } public function testCreatesEmptyThemeIfDefaultDoesNotExist() { @@ -49,7 +49,7 @@ public function testCreatesDefaultThemeIfItExists() { $theme = $themeService->getTheme(); $this->assertEquals('default', $theme->getName()); - $this->assertEquals('themes/default/', $theme->getDirectory()); + $this->assertEquals('themes/default', $theme->getDirectory()); } public function testSetAppThemeSetsName() { diff --git a/tests/lib/Theme/ThemeTest.php b/tests/lib/Theme/ThemeTest.php index 25c0ed722df3..c44d3da0d29e 100644 --- a/tests/lib/Theme/ThemeTest.php +++ b/tests/lib/Theme/ThemeTest.php @@ -16,12 +16,14 @@ protected function setUp() { parent::setUp(); } - public function testConstructorSetsNameAndDirectory() { + public function testConstructorSetsNameDirectoryAndWebPath() { $this->assertEmpty($this->sut->getName()); $this->assertEmpty($this->sut->getDirectory()); - $this->sut = new Theme('name', 'directory/directory'); + $this->assertEmpty($this->sut->getWebPath()); + $this->sut = new Theme('name', 'directory/directory', 'directory/web-directory'); $this->assertEquals('name', $this->sut->getName()); $this->assertEquals('directory/directory', $this->sut->getDirectory()); + $this->assertEquals('directory/web-directory', $this->sut->getWebPath()); } public function testDirectoryCanBeSet() { @@ -35,4 +37,10 @@ public function testNameCanBeSet() { $this->sut->setName('some-name'); $this->assertEquals('some-name', $this->sut->getName()); } + + public function testWebPathCanBeSet() { + $this->assertEmpty($this->sut->getWebPath()); + $this->sut->setWebPath('test/web-directory'); + $this->assertEquals('test/web-directory', $this->sut->getWebPath()); + } }