diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 4d1d3a562f55..217ddad464b8 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -523,7 +523,14 @@ public function getAppPath($appId) { */ public function getAppWebPath($appId) { if (($appRoot = $this->findAppInDirectories($appId)) !== false) { - return \OC::$WEBROOT . $appRoot['url']; + $ocWebRoot = $this->getOcWebRoot(); + // consider all relative ../ in the app web path as an adjustment + // for oC web root + while (strpos($appRoot['url'], '../') === 0) { + $appRoot['url'] = substr($appRoot['url'], 3); + $ocWebRoot = dirname($ocWebRoot); + } + return $ocWebRoot . '/' . ltrim($appRoot['url'], '/'); } return false; } @@ -579,6 +586,15 @@ protected function saveAppPath($appId, $appData) { $this->appDirs[$appId] = $appData; } + /** + * Get OC web root + * Wrapper for easy mocking + * @return string + */ + protected function getOcWebRoot() { + return \OC::$WEBROOT; + } + /** * Get apps roots as an array of path and url * Wrapper for easy mocking diff --git a/lib/private/L10N/Factory.php b/lib/private/L10N/Factory.php index 34a97c3708d0..cfd0f6b82295 100644 --- a/lib/private/L10N/Factory.php +++ b/lib/private/L10N/Factory.php @@ -372,7 +372,7 @@ protected function getActiveLegacyThemeDirectory() { protected function getActiveAppThemeDirectory() { $theme = $this->themeService->getTheme(); if ($theme instanceof ITheme && $theme->getDirectory() !== '' ) { - return $this->serverRoot . '/' . $theme->getDirectory(); + return $theme->getBaseDirectory(). '/' . $theme->getDirectory(); } return ''; } diff --git a/lib/private/Server.php b/lib/private/Server.php index 1f9f04bfdcff..d0352f624261 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -847,7 +847,10 @@ public function __construct($webRoot, \OC\Config $config) { }); $this->registerService('ThemeService', function ($c) { - return new ThemeService($this->getSystemConfig()->getValue('theme')); + return new ThemeService( + $this->getSystemConfig()->getValue('theme'), + \OC::$SERVERROOT + ); }); $this->registerAlias('OCP\Theme\IThemeService', 'ThemeService'); $this->registerAlias('OCP\IUserSession', 'UserSession'); diff --git a/lib/private/Template/Base.php b/lib/private/Template/Base.php index 79e69f46016e..c67bc5c43b9f 100644 --- a/lib/private/Template/Base.php +++ b/lib/private/Template/Base.php @@ -77,15 +77,14 @@ public function __construct($template, $requestToken, $l10n, $theme, $themeDefau /** * @param ITheme $theme * @param string $app - * @param string $serverRoot * @param string|false $appDir * @return string[] */ - protected function getAppTemplateDirs(ITheme $theme, $app, $serverRoot, $appDir) { + protected function getAppTemplateDirs(ITheme $theme, $app, $appDir) { $templateDirectories = []; // Templates dir from the active theme first if ($theme->getDirectory() !== '') { - $templateDirectories[] = $serverRoot . '/' . $theme->getDirectory() . '/apps/' . $app . '/templates/'; + $templateDirectories[] = $theme->getBaseDirectory() . '/' . $theme->getDirectory() . '/apps/' . $app . '/templates/'; } // Templates dir from the app dir then @@ -126,9 +125,9 @@ protected function getSettingsTemplateDirs(ITheme $theme, $serverRoot) { protected function getTemplateDirs(ITheme $theme, $basePath, $relativePath) { $directories = []; if ($theme->getDirectory() !== '') { - $directories[] = $basePath . '/' . $theme->getDirectory() . $relativePath; + $directories[] = $theme->getBaseDirectory() . '/' . $theme->getDirectory() . $relativePath; } - $directories[] = $basePath . $relativePath; + $directories[] = $basePath . $relativePath; return $directories; } diff --git a/lib/private/Template/CSSResourceLocator.php b/lib/private/Template/CSSResourceLocator.php index bade14a3c1af..d86863f3f863 100644 --- a/lib/private/Template/CSSResourceLocator.php +++ b/lib/private/Template/CSSResourceLocator.php @@ -31,31 +31,53 @@ class CSSResourceLocator extends ResourceLocator { * @param string $style */ public function doFind($style) { - if (strpos($style, '3rdparty') === 0 - && $this->appendOnceIfExist($this->thirdpartyroot, $style.'.css') - || $this->appendOnceIfExist($this->serverroot, $style.'.css') - || $this->appendOnceIfExist($this->serverroot, 'core/'.$style.'.css') + $fullStyle = $this->addExtension($style); + if ( + $this->appendOnceIfExist($this->serverroot, $fullStyle) + || $this->appendOnceIfExist($this->serverroot, 'core/' . $fullStyle) ) { return; } - $app = substr($style, 0, strpos($style, '/')); - $style = substr($style, strpos($style, '/')+1); + $app = substr($fullStyle, 0, strpos($fullStyle, '/')); + $fullStyle = substr($fullStyle, strpos($fullStyle, '/')+1); - $app_path = \OC_App::getAppPath($app); + $app_path = $this->appManager->getAppPath($app); if( $app_path === false ) { return; } - $app_url = \OC_App::getAppWebPath($app); + $app_url = $this->appManager->getAppWebPath($app); $app_url = ($app_url !== false) ? $app_url : null; - $this->appendOnceIfExist($app_path, $style.'.css', $app_url); + $this->appendOnceIfExist($app_path, $fullStyle, $app_url); } /** * @param string $style */ public function doFindTheme($style) { + $fullStyle = $this->addExtension($style); $themeDirectory = $this->theme->getDirectory(); + $baseDirectory = $this->theme->getBaseDirectory(); + $webRoot = ''; + if ($baseDirectory !== $this->serverroot) { + $webRoot = substr($this->theme->getWebPath(), 0, -strlen($themeDirectory)); + } + + $searchLocations = [ + $this->buildPath([$themeDirectory, 'apps', $fullStyle]), + $this->buildPath([$themeDirectory, $fullStyle]), + $this->buildPath([$themeDirectory, 'core', $fullStyle]), + ]; - $this->appendOnceIfExist($this->serverroot, $themeDirectory . '/apps/' . $style . '.css') - || $this->appendOnceIfExist($this->serverroot, $themeDirectory . '/' . $style . '.css') - || $this->appendOnceIfExist($this->serverroot, $themeDirectory . '/core/' . $style . '.css'); + foreach ($searchLocations as $location) { + if ($this->appendOnceIfExist($baseDirectory, $location, $webRoot)) { + break; + } + } + } + + /** + * @param string $path + * @return string + */ + protected function addExtension($path) { + return $path . '.css'; } } diff --git a/lib/private/Template/JSResourceLocator.php b/lib/private/Template/JSResourceLocator.php index a4af5ace7ec1..a266b2116cb2 100644 --- a/lib/private/Template/JSResourceLocator.php +++ b/lib/private/Template/JSResourceLocator.php @@ -31,44 +31,45 @@ class JSResourceLocator extends ResourceLocator { * @param string $script */ public function doFind($script) { + $fullScript = $this->addExtension($script); $themeDirectory = $this->theme->getDirectory(); - - if (strpos($script, '3rdparty') === 0 - && $this->appendOnceIfExist($this->thirdpartyroot, $script.'.js')) { - return; + $baseDirectory = $this->theme->getBaseDirectory(); + $webRoot = ''; + if ($baseDirectory !== $this->serverroot) { + $webRoot = substr($this->theme->getWebPath(), 0, -strlen($themeDirectory)); } if (strpos($script, '/l10n/') !== false) { // For language files we try to load them all, so themes can overwrite // single l10n strings without having to translate all of them. $found = 0; - $found += $this->appendOnceIfExist($this->serverroot, 'core/'.$script.'.js'); - $found += $this->appendOnceIfExist($this->serverroot, $themeDirectory.'/core/'.$script.'.js'); - $found += $this->appendOnceIfExist($this->serverroot, $script.'.js'); - $found += $this->appendOnceIfExist($this->serverroot, $themeDirectory.'/'.$script.'.js'); - $found += $this->appendOnceIfExist($this->serverroot, $themeDirectory.'/apps/'.$script.'.js'); + $found += $this->appendOnceIfExist($this->serverroot, 'core/'.$fullScript); + $found += $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/core/'.$fullScript, $webRoot); + $found += $this->appendOnceIfExist($this->serverroot, $fullScript); + $found += $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/'.$fullScript, $webRoot); + $found += $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/apps/'.$fullScript, $webRoot); if ($found) { return; } - } else if ($this->appendOnceIfExist($this->serverroot, $themeDirectory.'/apps/'.$script.'.js') - || $this->appendOnceIfExist($this->serverroot, $themeDirectory.'/'.$script.'.js') - || $this->appendOnceIfExist($this->serverroot, $script.'.js') - || $this->appendOnceIfExist($this->serverroot, $themeDirectory.'/core/'.$script.'.js') - || $this->appendOnceIfExist($this->serverroot, 'core/'.$script.'.js') + } else if ($this->appendOnceIfExist($baseDirectory, $themeDirectory.'/apps/'.$fullScript, $webRoot) + || $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/'.$fullScript, $webRoot) + || $this->appendOnceIfExist($this->serverroot, $fullScript) + || $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/core/'.$fullScript, $webRoot) + || $this->appendOnceIfExist($this->serverroot, 'core/'.$fullScript) ) { return; } - $app = substr($script, 0, strpos($script, '/')); - $script = substr($script, strpos($script, '/')+1); - $app_path = \OC_App::getAppPath($app); + $app = substr($fullScript, 0, strpos($fullScript, '/')); + $fullScript = substr($fullScript, strpos($fullScript, '/')+1); + $app_path = $this->appManager->getAppPath($app); if( $app_path === false ) { return; } - $app_url = \OC_App::getAppWebPath($app); + $app_url = $this->appManager->getAppWebPath($app); $app_url = ($app_url !== false) ? $app_url : null; - // missing translations files fill be ignored - $this->appendOnceIfExist($app_path, $script . '.js', $app_url); + // missing translations files will be ignored + $this->appendOnceIfExist($app_path, $fullScript, $app_url); } /** @@ -76,4 +77,12 @@ public function doFind($script) { */ public function doFindTheme($script) { } + + /** + * @param string $path + * @return string + */ + protected function addExtension($path) { + return $path . '.js'; + } } diff --git a/lib/private/Template/ResourceLocator.php b/lib/private/Template/ResourceLocator.php index 01861f0ab92b..b04c46c12bae 100644 --- a/lib/private/Template/ResourceLocator.php +++ b/lib/private/Template/ResourceLocator.php @@ -28,6 +28,8 @@ namespace OC\Template; +use OCP\App\IAppManager; +use OCP\ILogger; use OCP\Theme\ITheme; abstract class ResourceLocator { @@ -38,26 +40,28 @@ abstract class ResourceLocator { protected $mapping; protected $serverroot; - protected $thirdpartyroot; protected $webroot; protected $resources = []; - /** @var \OCP\ILogger */ + /** @var $appManager */ + protected $appManager; + + /** @var ILogger */ protected $logger; /** - * @param \OCP\ILogger $logger * @param ITheme $theme + * @param IAppManager $appManager + * @param ILogger $logger * @param array $core_map - * @param array $party_map */ - public function __construct(\OCP\ILogger $logger, $theme, $core_map, $party_map) { - $this->logger = $logger; + public function __construct(ITheme $theme, IAppManager $appManager, ILogger $logger, $core_map) { $this->theme = $theme; - $this->mapping = $core_map + $party_map; + $this->logger = $logger; + $this->appManager = $appManager; + $this->mapping = $core_map; $this->serverroot = key($core_map); - $this->thirdpartyroot = key($party_map); $this->webroot = $this->mapping[$this->serverroot]; } @@ -71,6 +75,12 @@ abstract public function doFind($resource); */ abstract public function doFindTheme($resource); + /** + * @param string $path + * @return string + */ + abstract protected function addExtension($path); + /** * Finds the resources and adds them to the list * @@ -144,8 +154,14 @@ protected function append($root, $file, $webRoot = null, $throw = true) { * @param string[] $parts path parts to concatenate * @return string $parts concatenated */ - private function buildPath($parts){ - return join(DIRECTORY_SEPARATOR, $parts); + protected function buildPath($parts){ + $trimmedParts = array_map( + function($part){ + return rtrim($part, '/'); + }, + $parts + ); + return join(DIRECTORY_SEPARATOR, $trimmedParts); } /** diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index ad9f39c3088e..2787a5cdc1bf 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -162,9 +162,9 @@ public function __construct( $renderAs, $appId = '' ) { */ static public function findStylesheetFiles($styles) { $locator = new \OC\Template\CSSResourceLocator( - \OC::$server->getLogger(), \OC_Util::getTheme(), - [\OC::$SERVERROOT => \OC::$WEBROOT], + \OC::$server->getAppManager(), + \OC::$server->getLogger(), [\OC::$SERVERROOT => \OC::$WEBROOT]); $locator->find($styles); return $locator->getResources(); @@ -176,9 +176,9 @@ static public function findStylesheetFiles($styles) { */ static public function findJavascriptFiles($scripts) { $locator = new \OC\Template\JSResourceLocator( - \OC::$server->getLogger(), \OC_Util::getTheme(), - [\OC::$SERVERROOT => \OC::$WEBROOT], + \OC::$server->getAppManager(), + \OC::$server->getLogger(), [\OC::$SERVERROOT => \OC::$WEBROOT]); $locator->find($scripts); return $locator->getResources(); diff --git a/lib/private/Theme/Theme.php b/lib/private/Theme/Theme.php index 369198f11929..fc7c8be1b3e0 100644 --- a/lib/private/Theme/Theme.php +++ b/lib/private/Theme/Theme.php @@ -28,6 +28,11 @@ class Theme implements ITheme { */ private $name; + /** + * @var string + */ + private $baseDirectory; + /** * @var string */ @@ -56,6 +61,21 @@ public function getName() { return $this->name; } + /** + * @param string $baseDirectory + * @return string + */ + public function setBaseDirectory($baseDirectory) { + $this->baseDirectory = $baseDirectory; + } + + /** + * @return string + */ + public function getBaseDirectory() { + return $this->baseDirectory; + } + /** * @return string */ diff --git a/lib/private/Theme/ThemeService.php b/lib/private/Theme/ThemeService.php index 4793c3e74778..65e8181dd6c8 100644 --- a/lib/private/Theme/ThemeService.php +++ b/lib/private/Theme/ThemeService.php @@ -29,6 +29,9 @@ class ThemeService implements IThemeService { * @var Theme */ private $theme; + + /** @var string */ + private $serverRoot; /** @var string */ private $defaultThemeDirectory; @@ -37,9 +40,11 @@ class ThemeService implements IThemeService { * ThemeService constructor. * * @param string $themeName + * @param string $serverRoot */ - public function __construct($themeName = '') { - $this->defaultThemeDirectory = \OC::$SERVERROOT . self::DEFAULT_THEME_PATH; + public function __construct($themeName, $serverRoot) { + $this->serverRoot = $serverRoot; + $this->defaultThemeDirectory = $this->serverRoot . self::DEFAULT_THEME_PATH; if ($themeName === '' && $this->defaultThemeExists()) { $themeName = 'default'; @@ -66,65 +71,52 @@ public function getTheme() { * @param string $themeName */ public function setAppTheme($themeName = '') { - $this->theme = $this->makeTheme($themeName, true, $this->getTheme()); + $this->theme = $this->makeTheme($themeName, true); } /** * @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); - } - - return $theme; - } - - /** - * @param string $themeName - * @param bool $appTheme - * @return string - */ - private function getDirectory($themeName, $appTheme = true) { + private function makeTheme($themeName, $appTheme = true) { + $baseDirectory = $this->serverRoot; + $directory = ''; + $webPath = ''; if ($themeName !== '') { if ($appTheme) { - return substr(\OC_App::getAppPath($themeName), strlen(\OC::$SERVERROOT) + 1); + $themeDirectory = \OC_App::getAppPath($themeName); + // Use OC server root as a theme base directory if theme is located below it + // Use path to an app root as a theme base directory otherwise + // in any case theme directory is relative to theme base directory + if (strpos($themeDirectory, $this->serverRoot)===0) { + $directory = substr($themeDirectory, strlen($this->serverRoot) + 1); + } else { + foreach (\OC::$APPSROOTS as $appRoot) { + if (strpos($themeDirectory, $appRoot['path'])===0) { + $baseDirectory = $appRoot['path']; + $directory = substr($themeDirectory, strlen($appRoot['path']) + 1); + } + } + } + + $webPath = \OC_App::getAppWebPath($themeName); + } else { + $directory = 'themes/' . $themeName; + $webPath = '/themes/' . $themeName; } - return 'themes/' . $themeName; } - return ''; - } - - /** - * @param $themeName - * @param bool $appTheme - * @return false|string - */ - private function getWebPath($themeName, $appTheme = true) { - if ($themeName !== '') { - if ($appTheme) { - $appWebPath = \OC_App::getAppWebPath($themeName); - return $appWebPath ? $appWebPath : ''; - } - return '/themes/' . $themeName; + if (is_null($this->theme)) { + $this->theme = new Theme($themeName, $directory, $webPath); + } else { + $this->theme->setName($themeName); + $this->theme->setDirectory($directory); + $this->theme->setWebPath($webPath); } + $this->theme->setBaseDirectory($baseDirectory); - return ''; + return $this->theme; } /** @@ -152,13 +144,13 @@ private function getAllAppThemes() { */ private function getAllLegacyThemes() { $themes = []; - if (is_dir(\OC::$SERVERROOT . '/themes')) { - if ($handle = opendir(\OC::$SERVERROOT . '/themes')) { + if (is_dir($this->serverRoot . '/themes')) { + if ($handle = opendir($this->serverRoot . '/themes')) { while (false !== ($entry = readdir($handle))) { if ($entry === '.' || $entry === '..') { continue; } - if (is_dir(\OC::$SERVERROOT . '/themes/' . $entry)) { + if (is_dir($this->serverRoot . '/themes/' . $entry)) { $themes[$entry] = $this->makeTheme($entry, false); } } diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php index 3cfc2dd3f7b5..650b0af29c13 100644 --- a/lib/private/URLGenerator.php +++ b/lib/private/URLGenerator.php @@ -180,20 +180,19 @@ private function getImagePath($app, $imageName) { array_unshift($directories, "$appPath", "/$app"); } + $themeDirectory = $this->theme->getDirectory(); foreach($directories as $directory) { $directory = $directory . "/img/"; - $themeDirectory = $this->theme->getDirectory(); - $file = $directory . $imageName; - if (!empty($themeDirectory)) { - if ($imagePath = $this->getImagePathOrFallback('/' . $this->theme->getDirectory() . $file)) { - return $imagePath; - } + if ($themeDirectory !== '' + && $imagePath = $this->getImagePathOrFallback( $this->theme->getBaseDirectory() . '/' . $themeDirectory . $file) + ) { + return $this->theme->getWebPath() . $file; } - if ($imagePath = $this->getImagePathOrFallback($file)) { - return $imagePath; + if ($imagePath = $this->getImagePathOrFallback(\OC::$SERVERROOT . $file)) { + return \OC::$WEBROOT . $file; } } } @@ -203,15 +202,12 @@ private function getImagePath($app, $imageName) { * @return string */ private function getImagePathOrFallback($file) { - - if (file_exists(\OC::$SERVERROOT . $file)) { - return \OC::$WEBROOT . $file; - } - $fallback = substr($file, 0, -3) . 'png'; - - if (file_exists(\OC::$SERVERROOT . $fallback)) { - return \OC::$WEBROOT . $fallback; + $locations = [ $file, $fallback ]; + foreach ($locations as $location) { + if (file_exists($location)) { + return $location; + } } } diff --git a/lib/private/legacy/template.php b/lib/private/legacy/template.php index 5e466f767002..c52348d72071 100644 --- a/lib/private/legacy/template.php +++ b/lib/private/legacy/template.php @@ -194,7 +194,7 @@ protected function findTemplate($theme, $app, $name) { } elseif ($app === 'settings') { $dirs = $this->getSettingsTemplateDirs($theme, OC::$SERVERROOT); } else { - $dirs = $this->getAppTemplateDirs($theme, $app, OC::$SERVERROOT, OC_App::getAppPath($app)); + $dirs = $this->getAppTemplateDirs($theme, $app, OC_App::getAppPath($app)); } $locator = new \OC\Template\TemplateFileLocator( $dirs ); diff --git a/lib/public/Theme/ITheme.php b/lib/public/Theme/ITheme.php index fcdec7ae997d..2dfa6b77bfb4 100644 --- a/lib/public/Theme/ITheme.php +++ b/lib/public/Theme/ITheme.php @@ -32,6 +32,12 @@ interface ITheme { */ public function getName(); + /** + * @return string + * @since 10.0.8 + */ + public function getBaseDirectory(); + /** * @return string * @since 10.0.3 diff --git a/tests/lib/App/ManagerTest.php b/tests/lib/App/ManagerTest.php index 1f9499850ede..270386494be8 100644 --- a/tests/lib/App/ManagerTest.php +++ b/tests/lib/App/ManagerTest.php @@ -529,4 +529,28 @@ public function testPathIsNotCachedForNotFoundApp() { $appPath = $appManager->getAppPath($appId); $this->assertFalse($appPath); } + + public function testAppWebRootAboveOcWebroot() { + $appId = 'notexistingapp'; + + $appManager = $this->getMockBuilder(AppManager::class) + ->setMethods(['findAppInDirectories', 'getOcWebRoot']) + ->disableOriginalConstructor() + ->getMock(); + + $appManager->expects($this->any()) + ->method('getOcWebRoot') + ->willReturn('some/host/path'); + + $appManager->expects($this->any()) + ->method('findAppInDirectories') + ->with($appId) + ->willReturn([ + 'path' => '/not/essential', + 'url' => '../../relative', + ]); + + $appWebPath = $appManager->getAppWebPath($appId); + $this->assertEquals('some/relative', $appWebPath); + } } diff --git a/tests/lib/Template/BaseTest.php b/tests/lib/Template/BaseTest.php index 2813a6bb2918..0231168a2d68 100644 --- a/tests/lib/Template/BaseTest.php +++ b/tests/lib/Template/BaseTest.php @@ -38,12 +38,16 @@ public function testTemplateIsLocatedWhenThemeIsActive() { ->method('getDirectory') ->willReturn('theme-test'); + $this->theme->expects($this->any()) + ->method('getBaseDirectory') + ->willReturn($this->serverRoot); + $app = 'anyapp'; $directories = self::invokePrivate( $base, 'getAppTemplateDirs', - [$this->theme, $app, $this->serverRoot, $this->serverRoot . '/apps3/anyapp'] + [$this->theme, $app, $this->serverRoot . '/apps3/anyapp'] ); $this->assertEquals( [ @@ -68,7 +72,7 @@ public function testTemplateIsLocatedWhenThemeIsNotActive() { $directories = self::invokePrivate( $base, 'getAppTemplateDirs', - [$this->theme, $app, $this->serverRoot, $this->serverRoot . '/apps3/anyapp'] + [$this->theme, $app, $this->serverRoot . '/apps3/anyapp'] ); $this->assertEquals( [ diff --git a/tests/lib/Template/CSSResourceLocatorTest.php b/tests/lib/Template/CSSResourceLocatorTest.php new file mode 100644 index 000000000000..224abf122c1c --- /dev/null +++ b/tests/lib/Template/CSSResourceLocatorTest.php @@ -0,0 +1,106 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Template; + +use OC\App\AppManager; +use OC\Template\CSSResourceLocator; +use OC\Theme\Theme; +use OCP\ILogger; +use Test\TestCase; + +class CSSResourceLocatorTest extends TestCase { + /** @var \PHPUnit_Framework_MockObject_MockObject */ + protected $logger; + /** @var \PHPUnit_Framework_MockObject_MockObject */ + protected $appManager; + protected $serverRoot = '/var/www/owncloud'; + protected $appRoot = '/var/www/apps'; + protected $themeAppDir = 'theme-best'; + + + protected function setUp() { + parent::setUp(); + $this->logger = $this->createMock(ILogger::class); + } + + /** + * @param string $theme + * @param array $core_map + * @param array $appsRoots + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function getResourceLocator($theme, $core_map, $appsRoots) { + $themeInstance = $this->createMock(Theme::class); + $themeInstance->method('getName')->willReturn($theme); + $themeInstance->method('getBaseDirectory')->willReturn($this->appRoot); + $themeInstance->method('getDirectory')->willReturn($this->themeAppDir); + + $this->appManager = $this->getMockBuilder(AppManager::class) + ->disableOriginalConstructor() + ->getMock(); + + return $this->getMockBuilder(CSSResourceLocator::class) + ->setConstructorArgs([$themeInstance, $this->appManager, $this->logger, $core_map, $appsRoots]) + ->setMethods(['appendOnceIfExist']) + ->getMock(); + } + + public function testFindCoreStyle() { + /** @var \OC\Template\CSSResourceLocator $locator */ + $locator = $this->getResourceLocator( + 'theme', + [$this->serverRoot => 'map'], + ['foo' => 'bar'] + ); + $this->appManager->expects($this->any()) + ->method('getAppPath') + ->with('core') + ->willReturn(false); + + $locator->expects($this->exactly(5)) + ->method('appendOnceIfExist') + ->withConsecutive( + ['/var/www/owncloud', 'core/css/style.css', ''], + ['/var/www/owncloud', 'core/core/css/style.css', ''], + ['/var/www/apps', 'theme-best/apps/core/css/style.css', ''], + ['/var/www/apps', 'theme-best/core/css/style.css', ''], + ['/var/www/apps', 'theme-best/core/core/css/style.css', ''] + + ); + + $locator->find(['core/css/style']); + } + + public function testFindAppStyle() { + /** @var \OC\Template\CSSResourceLocator $locator */ + $locator = $this->getResourceLocator( + 'theme', + [$this->serverRoot => 'map'], + ['foo' => 'bar'] + ); + $this->appManager->expects($this->any()) + ->method('getAppPath') + ->with('randomapp') + ->willReturn('/var/www/apps/randomapp'); + + $locator->expects($this->exactly(6)) + ->method('appendOnceIfExist') + ->withConsecutive( + ['/var/www/owncloud', 'randomapp/css/style.css', ''], + ['/var/www/owncloud', 'core/randomapp/css/style.css', ''], + ['/var/www/apps/randomapp', 'css/style.css', ''], + ['/var/www/apps', 'theme-best/apps/randomapp/css/style.css', ''], + ['/var/www/apps', 'theme-best/randomapp/css/style.css', ''], + ['/var/www/apps', 'theme-best/core/randomapp/css/style.css', ''] + ); + + $locator->find(['randomapp/css/style']); + } + +} diff --git a/tests/lib/Template/JSResourceLocatorTest.php b/tests/lib/Template/JSResourceLocatorTest.php new file mode 100644 index 000000000000..6970072bced8 --- /dev/null +++ b/tests/lib/Template/JSResourceLocatorTest.php @@ -0,0 +1,132 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Template; + +use OC\App\AppManager; +use OC\Template\JSResourceLocator; +use OC\Theme\Theme; +use OCP\ILogger; +use Test\TestCase; + +class JSResourceLocatorTest extends TestCase { + /** @var \PHPUnit_Framework_MockObject_MockObject */ + protected $logger; + /** @var \PHPUnit_Framework_MockObject_MockObject */ + protected $appManager; + protected $serverRoot = '/var/www/owncloud'; + protected $appRoot = '/var/www/apps'; + protected $themeAppDir = 'theme-best'; + + + protected function setUp() { + parent::setUp(); + $this->logger = $this->createMock(ILogger::class); + } + + /** + * @param string $theme + * @param array $core_map + * @param array $appsRoots + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function getResourceLocator($theme, $core_map, $appsRoots) { + $themeInstance = $this->createMock(Theme::class); + $themeInstance->method('getName')->willReturn($theme); + $themeInstance->method('getBaseDirectory')->willReturn($this->appRoot); + $themeInstance->method('getDirectory')->willReturn($this->themeAppDir); + + $this->appManager = $this->getMockBuilder(AppManager::class) + ->disableOriginalConstructor() + ->getMock(); + + return $this->getMockBuilder(JSResourceLocator::class) + ->setConstructorArgs([$themeInstance, $this->appManager, $this->logger, $core_map, $appsRoots]) + ->setMethods(['appendOnceIfExist']) + ->getMock(); + } + + public function testFindCoreScript() { + /** @var \OC\Template\JSResourceLocator $locator */ + $locator = $this->getResourceLocator( + 'theme', + [$this->serverRoot => 'map'], + ['foo' => 'bar'] + ); + $this->appManager->expects($this->any()) + ->method('getAppPath') + ->with('core') + ->willReturn(false); + + $locator->expects($this->exactly(5)) + ->method('appendOnceIfExist') + ->withConsecutive( + ['/var/www/apps', 'theme-best/apps/core/js/script.js', ''], + ['/var/www/apps', 'theme-best/core/js/script.js', ''], + ['/var/www/owncloud', 'core/js/script.js', ''], + ['/var/www/apps', 'theme-best/core/core/js/script.js', ''], + ['/var/www/owncloud', 'core/core/js/script.js', ''] + ); + + $locator->find(['core/js/script']); + } + + public function testFindAppScript() { + /** @var \OC\Template\JSResourceLocator $locator */ + $locator = $this->getResourceLocator( + 'theme', + [$this->serverRoot => 'map'], + ['foo' => 'bar'] + ); + $this->appManager->expects($this->any()) + ->method('getAppPath') + ->with('randomapp') + ->willReturn('/var/www/apps/randomapp'); + + $locator->expects($this->exactly(6)) + ->method('appendOnceIfExist') + ->withConsecutive( + ['/var/www/apps', 'theme-best/apps/randomapp/js/script.js', ''], + ['/var/www/apps', 'theme-best/randomapp/js/script.js', ''], + ['/var/www/owncloud', 'randomapp/js/script.js', ''], + ['/var/www/apps', 'theme-best/core/randomapp/js/script.js', ''], + ['/var/www/owncloud', 'core/randomapp/js/script.js', ''], + ['/var/www/apps/randomapp', 'js/script.js', ''] + ); + + $locator->find(['randomapp/js/script']); + } + + + public function testFindL10nScript() { + /** @var \OC\Template\JSResourceLocator $locator */ + $locator = $this->getResourceLocator( + 'theme', + [$this->serverRoot => 'map'], + ['foo' => 'bar'] + ); + $this->appManager->expects($this->any()) + ->method('getAppPath') + ->with('randomapp') + ->willReturn('/var/www/apps/randomapp'); + + $locator->expects($this->exactly(6)) + ->method('appendOnceIfExist') + ->withConsecutive( + ['/var/www/owncloud', 'core/randomapp/l10n/en_GB.js', ''], + ['/var/www/apps', 'theme-best/core/randomapp/l10n/en_GB.js', ''], + ['/var/www/owncloud', 'randomapp/l10n/en_GB.js', ''], + ['/var/www/apps', 'theme-best/randomapp/l10n/en_GB.js', ''], + ['/var/www/apps', 'theme-best/apps/randomapp/l10n/en_GB.js', ''], + ['/var/www/apps/randomapp', 'l10n/en_GB.js', ''] + ); + + $locator->find(['randomapp/l10n/en_GB']); + } + +} diff --git a/tests/lib/Template/ResourceLocatorTest.php b/tests/lib/Template/ResourceLocatorTest.php index 927b9f0e715f..507dc28d8952 100644 --- a/tests/lib/Template/ResourceLocatorTest.php +++ b/tests/lib/Template/ResourceLocatorTest.php @@ -8,6 +8,7 @@ namespace Test\Template; +use OC\App\AppManager; use OC\Template\ResourceNotFoundException; use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\vfsStreamWrapper; @@ -40,33 +41,32 @@ protected function setUp() { /** * @param string $theme * @param array $core_map - * @param array $party_map * @param array $appsRoots * @return \PHPUnit_Framework_MockObject_MockObject */ - public function getResourceLocator($theme, $core_map, $party_map, $appsRoots) { + public function getResourceLocator($theme, $core_map, $appsRoots) { $themeInstance = $this->createMock('OC\Theme\Theme'); $themeInstance->method('getName')->willReturn($theme); + $appManagerInstance = $this->createMock(AppManager::class); + return $this->getMockForAbstractClass('OC\Template\ResourceLocator', - [$this->logger, $themeInstance, $core_map, $party_map, $appsRoots], + [$themeInstance, $appManagerInstance, $this->logger, $core_map, $appsRoots], '', true, true, true, []); } public function testConstructor() { - $locator = $this->getResourceLocator('theme', - ['core'=>'map'], ['3rd'=>'party'], ['foo'=>'bar']); + $locator = $this->getResourceLocator('theme', ['core'=>'map'], ['foo'=>'bar']); $this->assertAttributeInstanceOf('OC\Theme\Theme', 'theme', $locator); $this->assertAttributeEquals('core', 'serverroot', $locator); - $this->assertAttributeEquals(['core'=>'map','3rd'=>'party'], 'mapping', $locator); - $this->assertAttributeEquals('3rd', 'thirdpartyroot', $locator); + $this->assertAttributeEquals(['core'=>'map'], 'mapping', $locator); $this->assertAttributeEquals('map', 'webroot', $locator); $this->assertAttributeEquals([], 'resources', $locator); } public function testFind() { $locator = $this->getResourceLocator('theme', - ['core' => 'map'], ['3rd' => 'party'], ['foo' => 'bar']); + ['core' => 'map'], ['foo' => 'bar']); $locator->expects($this->once()) ->method('doFind') ->with('foo'); @@ -78,8 +78,7 @@ public function testFind() { } public function testFindNotFound() { - $locator = $this->getResourceLocator('theme', - ['core'=>'map'], ['3rd'=>'party'], ['foo'=>'bar']); + $locator = $this->getResourceLocator('theme', ['core'=>'map'], ['foo'=>'bar']); $locator->expects($this->once()) ->method('doFind') ->with('foo') @@ -98,13 +97,11 @@ public function testFindNotFound() { public function testAppendOnceIfExist() { /** @var \OC\Template\ResourceLocator $locator */ - $locator = $this->getResourceLocator('theme', - [__DIR__=>'map'], [vfsStream::url('resources')=>'party'], ['foo'=>'bar']); + $locator = $this->getResourceLocator('theme', [__DIR__=>'map'], ['foo'=>'bar']); $method = new \ReflectionMethod($locator, 'appendOnceIfExist'); $method->setAccessible(true); - $method->invoke($locator, __DIR__, basename(__FILE__), 'webroot'); $resource1 = [__DIR__, 'webroot', basename(__FILE__)]; $this->assertEquals([__FILE__ => $resource1], $locator->getResources()); @@ -114,22 +111,6 @@ public function testAppendOnceIfExist() { $method->invoke($locator, __DIR__, 'does-not-exist'); $this->assertEquals([__FILE__ => $resource1], $locator->getResources()); - - - $method->invoke($locator, vfsStream::url('resources'), $this->filenames[0]); - $resource2 = [vfsStream::url('resources'), 'party', $this->filenames[0]]; - $this->assertEquals([ - __FILE__ => $resource1, - vfsStream::url('resources') . '/' . $this->filenames[0] => $resource2 - ], $locator->getResources()); - - $method->invoke($locator, vfsStream::url('resources'), $this->filenames[1]); - $resource3 = [vfsStream::url('resources'), 'party', $this->filenames[1]]; - $this->assertEquals([ - __FILE__ => $resource1, - vfsStream::url('resources') . '/' . $this->filenames[0] => $resource2, - vfsStream::url('resources') . '/' . $this->filenames[1] => $resource3 - ], $locator->getResources()); } } diff --git a/tests/lib/Theme/ThemeServiceTest.php b/tests/lib/Theme/ThemeServiceTest.php index cacf841f1917..f6c1ca899bd6 100644 --- a/tests/lib/Theme/ThemeServiceTest.php +++ b/tests/lib/Theme/ThemeServiceTest.php @@ -7,7 +7,7 @@ class ThemeServiceTest extends \PHPUnit\Framework\TestCase { public function testCreatesThemeByGivenName() { - $themeService = new ThemeService('theme-name'); + $themeService = new ThemeService('theme-name', \OC::$SERVERROOT); $theme = $themeService->getTheme(); $this->assertEquals('theme-name', $theme->getName()); $this->assertEquals('themes/theme-name', $theme->getDirectory()); @@ -23,7 +23,7 @@ public function testCreatesEmptyThemeIfDefaultDoesNotExist() { ->method('defaultThemeExists') ->willReturn(false); - $themeService->__construct(''); + $themeService->__construct('', \OC::$SERVERROOT); $theme = $themeService->getTheme(); $this->assertEquals('', $theme->getName()); @@ -40,7 +40,7 @@ public function testCreatesDefaultThemeIfItExists() { ->method('defaultThemeExists') ->willReturn(true); - $themeService->__construct(''); + $themeService->__construct('', \OC::$SERVERROOT); $theme = $themeService->getTheme(); $this->assertEquals('default', $theme->getName()); @@ -48,7 +48,7 @@ public function testCreatesDefaultThemeIfItExists() { } public function testSetAppThemeSetsName() { - $themeService = new ThemeService(); + $themeService = new ThemeService('', \OC::$SERVERROOT); $this->assertEmpty($themeService->getTheme()->getName()); $themeService->setAppTheme('some-app-theme'); $this->assertEquals('some-app-theme', $themeService->getTheme()->getName());