From 806db75f9962a3d847c0f997f3bceda96e38bb4b Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Fri, 19 Jan 2018 22:53:05 +0300 Subject: [PATCH 1/9] There is no 3rdparty since OC 10 --- lib/private/Template/CSSResourceLocator.php | 5 ++- lib/private/Template/JSResourceLocator.php | 5 --- lib/private/Template/ResourceLocator.php | 7 ++-- lib/private/TemplateLayout.php | 2 -- tests/lib/Template/ResourceLocatorTest.php | 36 ++++----------------- 5 files changed, 11 insertions(+), 44 deletions(-) diff --git a/lib/private/Template/CSSResourceLocator.php b/lib/private/Template/CSSResourceLocator.php index bade14a3c1af..bf97db38ff4a 100644 --- a/lib/private/Template/CSSResourceLocator.php +++ b/lib/private/Template/CSSResourceLocator.php @@ -31,9 +31,8 @@ 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') + if ( + $this->appendOnceIfExist($this->serverroot, $style.'.css') || $this->appendOnceIfExist($this->serverroot, 'core/'.$style.'.css') ) { return; diff --git a/lib/private/Template/JSResourceLocator.php b/lib/private/Template/JSResourceLocator.php index a4af5ace7ec1..829aa55c7b73 100644 --- a/lib/private/Template/JSResourceLocator.php +++ b/lib/private/Template/JSResourceLocator.php @@ -33,11 +33,6 @@ class JSResourceLocator extends ResourceLocator { public function doFind($script) { $themeDirectory = $this->theme->getDirectory(); - if (strpos($script, '3rdparty') === 0 - && $this->appendOnceIfExist($this->thirdpartyroot, $script.'.js')) { - return; - } - 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. diff --git a/lib/private/Template/ResourceLocator.php b/lib/private/Template/ResourceLocator.php index 01861f0ab92b..98aa50fad946 100644 --- a/lib/private/Template/ResourceLocator.php +++ b/lib/private/Template/ResourceLocator.php @@ -38,7 +38,6 @@ abstract class ResourceLocator { protected $mapping; protected $serverroot; - protected $thirdpartyroot; protected $webroot; protected $resources = []; @@ -50,14 +49,12 @@ abstract class ResourceLocator { * @param \OCP\ILogger $logger * @param ITheme $theme * @param array $core_map - * @param array $party_map */ - public function __construct(\OCP\ILogger $logger, $theme, $core_map, $party_map) { + public function __construct(\OCP\ILogger $logger, $theme, $core_map) { $this->logger = $logger; $this->theme = $theme; - $this->mapping = $core_map + $party_map; + $this->mapping = $core_map; $this->serverroot = key($core_map); - $this->thirdpartyroot = key($party_map); $this->webroot = $this->mapping[$this->serverroot]; } diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index ad9f39c3088e..0bb307420229 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -164,7 +164,6 @@ static public function findStylesheetFiles($styles) { $locator = new \OC\Template\CSSResourceLocator( \OC::$server->getLogger(), \OC_Util::getTheme(), - [\OC::$SERVERROOT => \OC::$WEBROOT], [\OC::$SERVERROOT => \OC::$WEBROOT]); $locator->find($styles); return $locator->getResources(); @@ -178,7 +177,6 @@ static public function findJavascriptFiles($scripts) { $locator = new \OC\Template\JSResourceLocator( \OC::$server->getLogger(), \OC_Util::getTheme(), - [\OC::$SERVERROOT => \OC::$WEBROOT], [\OC::$SERVERROOT => \OC::$WEBROOT]); $locator->find($scripts); return $locator->getResources(); diff --git a/tests/lib/Template/ResourceLocatorTest.php b/tests/lib/Template/ResourceLocatorTest.php index 927b9f0e715f..9e662aeacf27 100644 --- a/tests/lib/Template/ResourceLocatorTest.php +++ b/tests/lib/Template/ResourceLocatorTest.php @@ -40,33 +40,30 @@ 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); return $this->getMockForAbstractClass('OC\Template\ResourceLocator', - [$this->logger, $themeInstance, $core_map, $party_map, $appsRoots], + [$this->logger, $themeInstance, $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 +75,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 +94,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 +108,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()); } } From 98e12ec593611d5f4518477506860d77ab7ad291 Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Fri, 19 Jan 2018 22:53:43 +0300 Subject: [PATCH 2/9] Resolve relative webpath properly --- lib/private/App/AppManager.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 4d1d3a562f55..9eb26dbc2efe 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -523,7 +523,12 @@ public function getAppPath($appId) { */ public function getAppWebPath($appId) { if (($appRoot = $this->findAppInDirectories($appId)) !== false) { - return \OC::$WEBROOT . $appRoot['url']; + $ocWebRoot = \OC::$WEBROOT; + while (strpos($appRoot['url'], '..') === 0) { + $appRoot['url'] = substr($appRoot['url'],3); + $ocWebRoot = dirname($ocWebRoot); + } + return $ocWebRoot . '/' . $appRoot['url']; } return false; } From dfb2f67f4f8f806978a7f09c4134ce21f76bf790 Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Wed, 24 Jan 2018 02:56:07 +0300 Subject: [PATCH 3/9] Css and Js resource locator is ready --- lib/private/Template/CSSResourceLocator.php | 13 +++-- lib/private/Template/JSResourceLocator.php | 19 ++++--- lib/private/Theme/Theme.php | 17 ++++++ lib/private/Theme/ThemeService.php | 59 +++++++++------------ 4 files changed, 64 insertions(+), 44 deletions(-) diff --git a/lib/private/Template/CSSResourceLocator.php b/lib/private/Template/CSSResourceLocator.php index bf97db38ff4a..10d55d4b2716 100644 --- a/lib/private/Template/CSSResourceLocator.php +++ b/lib/private/Template/CSSResourceLocator.php @@ -52,9 +52,16 @@ public function doFind($style) { */ public function doFindTheme($style) { $themeDirectory = $this->theme->getDirectory(); + $baseDirectory = $this->theme->getBaseDirectory(); + $webroot = null; + if ($baseDirectory === '') { + $baseDirectory = $this->serverroot; + } else { + $webroot = rtrim($this->theme->getWebPath(), $themeDirectory); + } - $this->appendOnceIfExist($this->serverroot, $themeDirectory . '/apps/' . $style . '.css') - || $this->appendOnceIfExist($this->serverroot, $themeDirectory . '/' . $style . '.css') - || $this->appendOnceIfExist($this->serverroot, $themeDirectory . '/core/' . $style . '.css'); + $this->appendOnceIfExist($baseDirectory, $themeDirectory . '/apps/' . $style . '.css', $webroot) + || $this->appendOnceIfExist($baseDirectory, $themeDirectory . '/' . $style . '.css', $webroot) + || $this->appendOnceIfExist($baseDirectory, $themeDirectory . '/core/' . $style . '.css', $webroot); } } diff --git a/lib/private/Template/JSResourceLocator.php b/lib/private/Template/JSResourceLocator.php index 829aa55c7b73..e849e6299bd1 100644 --- a/lib/private/Template/JSResourceLocator.php +++ b/lib/private/Template/JSResourceLocator.php @@ -32,24 +32,31 @@ class JSResourceLocator extends ResourceLocator { */ public function doFind($script) { $themeDirectory = $this->theme->getDirectory(); + $baseDirectory = $this->theme->getBaseDirectory(); + $webroot = null; + if ($baseDirectory === '') { + $baseDirectory = $this->serverroot; + } else { + $webroot = rtrim($this->theme->getWebPath(), $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($baseDirectory, $themeDirectory.'/core/'.$script.'.js', $webroot); $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($baseDirectory, $themeDirectory.'/'.$script.'.js', $webroot); + $found += $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/apps/'.$script.'.js', $webroot); if ($found) { return; } - } else if ($this->appendOnceIfExist($this->serverroot, $themeDirectory.'/apps/'.$script.'.js') - || $this->appendOnceIfExist($this->serverroot, $themeDirectory.'/'.$script.'.js') + } else if ($this->appendOnceIfExist($baseDirectory, $themeDirectory.'/apps/'.$script.'.js', $webroot) + || $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/'.$script.'.js', $webroot) || $this->appendOnceIfExist($this->serverroot, $script.'.js') - || $this->appendOnceIfExist($this->serverroot, $themeDirectory.'/core/'.$script.'.js') + || $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/core/'.$script.'.js', $webroot) || $this->appendOnceIfExist($this->serverroot, 'core/'.$script.'.js') ) { return; diff --git a/lib/private/Theme/Theme.php b/lib/private/Theme/Theme.php index 369198f11929..9b17edff12cc 100644 --- a/lib/private/Theme/Theme.php +++ b/lib/private/Theme/Theme.php @@ -28,6 +28,8 @@ class Theme implements ITheme { */ private $name; + private $baseDirectory = ''; + /** * @var string */ @@ -56,6 +58,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..4627d7ae6521 100644 --- a/lib/private/Theme/ThemeService.php +++ b/lib/private/Theme/ThemeService.php @@ -76,8 +76,29 @@ public function setAppTheme($themeName = '') { * @return Theme */ private function makeTheme($themeName, $appTheme = true, Theme $theme = null) { - $directory = $this->getDirectory($themeName, $appTheme); - $webPath = $this->getWebPath($themeName, $appTheme); + $baseDirectory = ''; + $directory = ''; + $webPath = ''; + if ($themeName !== '') { + if ($appTheme) { + $themeDirectory = \OC_App::getAppPath($themeName); + if (strpos($themeDirectory, \OC::$SERVERROOT)===0) { + $directory = substr($themeDirectory, strlen(\OC::$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; + } + } if (is_null($theme)) { $theme = new Theme( @@ -90,43 +111,11 @@ private function makeTheme($themeName, $appTheme = true, Theme $theme = null) { $theme->setDirectory($directory); $theme->setWebPath($webPath); } + $theme->setBaseDirectory($baseDirectory); return $theme; } - /** - * @param string $themeName - * @param bool $appTheme - * @return string - */ - private function getDirectory($themeName, $appTheme = true) { - if ($themeName !== '') { - if ($appTheme) { - return substr(\OC_App::getAppPath($themeName), strlen(\OC::$SERVERROOT) + 1); - } - 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; - } - - return ''; - } - /** * @return Theme[] */ From 5c3dd2b8c291dbed965b35442bd964117e045a2a Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Wed, 24 Jan 2018 21:17:55 +0300 Subject: [PATCH 4/9] Fix TemplateLocator --- lib/private/Template/Base.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/private/Template/Base.php b/lib/private/Template/Base.php index 79e69f46016e..2a2b89f7d212 100644 --- a/lib/private/Template/Base.php +++ b/lib/private/Template/Base.php @@ -85,7 +85,11 @@ protected function getAppTemplateDirs(ITheme $theme, $app, $serverRoot, $appDir) $templateDirectories = []; // Templates dir from the active theme first if ($theme->getDirectory() !== '') { - $templateDirectories[] = $serverRoot . '/' . $theme->getDirectory() . '/apps/' . $app . '/templates/'; + $baseDirectory = $theme->getBaseDirectory(); + if ($baseDirectory === ''){ + $baseDirectory = $serverRoot; + } + $templateDirectories[] = $baseDirectory . '/' . $theme->getDirectory() . '/apps/' . $app . '/templates/'; } // Templates dir from the app dir then @@ -126,7 +130,11 @@ protected function getSettingsTemplateDirs(ITheme $theme, $serverRoot) { protected function getTemplateDirs(ITheme $theme, $basePath, $relativePath) { $directories = []; if ($theme->getDirectory() !== '') { - $directories[] = $basePath . '/' . $theme->getDirectory() . $relativePath; + $baseDirectory = $theme->getBaseDirectory(); + if ($baseDirectory === ''){ + $baseDirectory = $basePath; + } + $directories[] = $baseDirectory . '/' . $theme->getDirectory() . $relativePath; } $directories[] = $basePath . $relativePath; From 2b73a82651b6ef59165541c380c4f53c1a008590 Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Thu, 25 Jan 2018 00:57:22 +0300 Subject: [PATCH 5/9] Cleanup and fix test --- lib/private/Template/Base.php | 17 +++------- lib/private/Template/CSSResourceLocator.php | 23 +++++++++----- lib/private/Template/JSResourceLocator.php | 35 ++++++++++----------- lib/private/Template/ResourceLocator.php | 10 ++++-- lib/private/Theme/Theme.php | 5 ++- lib/private/Theme/ThemeService.php | 4 +-- lib/private/legacy/template.php | 2 +- lib/public/Theme/ITheme.php | 6 ++++ tests/lib/Template/BaseTest.php | 8 +++-- 9 files changed, 63 insertions(+), 47 deletions(-) diff --git a/lib/private/Template/Base.php b/lib/private/Template/Base.php index 2a2b89f7d212..c67bc5c43b9f 100644 --- a/lib/private/Template/Base.php +++ b/lib/private/Template/Base.php @@ -77,19 +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() !== '') { - $baseDirectory = $theme->getBaseDirectory(); - if ($baseDirectory === ''){ - $baseDirectory = $serverRoot; - } - $templateDirectories[] = $baseDirectory . '/' . $theme->getDirectory() . '/apps/' . $app . '/templates/'; + $templateDirectories[] = $theme->getBaseDirectory() . '/' . $theme->getDirectory() . '/apps/' . $app . '/templates/'; } // Templates dir from the app dir then @@ -130,13 +125,9 @@ protected function getSettingsTemplateDirs(ITheme $theme, $serverRoot) { protected function getTemplateDirs(ITheme $theme, $basePath, $relativePath) { $directories = []; if ($theme->getDirectory() !== '') { - $baseDirectory = $theme->getBaseDirectory(); - if ($baseDirectory === ''){ - $baseDirectory = $basePath; - } - $directories[] = $baseDirectory . '/' . $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 10d55d4b2716..10333227c1b9 100644 --- a/lib/private/Template/CSSResourceLocator.php +++ b/lib/private/Template/CSSResourceLocator.php @@ -51,17 +51,24 @@ public function doFind($style) { * @param string $style */ public function doFindTheme($style) { + $fullStyle = $style . '.css'; $themeDirectory = $this->theme->getDirectory(); $baseDirectory = $this->theme->getBaseDirectory(); - $webroot = null; - if ($baseDirectory === '') { - $baseDirectory = $this->serverroot; - } else { - $webroot = rtrim($this->theme->getWebPath(), $themeDirectory); + $webRoot = ''; + if ($baseDirectory !== $this->serverroot) { + $webRoot = substr($this->theme->getWebPath(), 0, -strlen($themeDirectory)); } - $this->appendOnceIfExist($baseDirectory, $themeDirectory . '/apps/' . $style . '.css', $webroot) - || $this->appendOnceIfExist($baseDirectory, $themeDirectory . '/' . $style . '.css', $webroot) - || $this->appendOnceIfExist($baseDirectory, $themeDirectory . '/core/' . $style . '.css', $webroot); + $searchLocations = [ + $this->buildPath([$themeDirectory, '/apps', $fullStyle]), + $this->buildPath([$themeDirectory, $fullStyle]), + $this->buildPath([$themeDirectory, '/core', $fullStyle]), + ]; + + foreach ($searchLocations as $location) { + if ($this->appendOnceIfExist($baseDirectory, $location, $webRoot)) { + break; + } + } } } diff --git a/lib/private/Template/JSResourceLocator.php b/lib/private/Template/JSResourceLocator.php index e849e6299bd1..6e5e7ec00472 100644 --- a/lib/private/Template/JSResourceLocator.php +++ b/lib/private/Template/JSResourceLocator.php @@ -31,46 +31,45 @@ class JSResourceLocator extends ResourceLocator { * @param string $script */ public function doFind($script) { + $fullScript = $script . '.js'; $themeDirectory = $this->theme->getDirectory(); $baseDirectory = $this->theme->getBaseDirectory(); - $webroot = null; - if ($baseDirectory === '') { - $baseDirectory = $this->serverroot; - } else { - $webroot = rtrim($this->theme->getWebPath(), $themeDirectory); + $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($baseDirectory, $themeDirectory.'/core/'.$script.'.js', $webroot); - $found += $this->appendOnceIfExist($this->serverroot, $script.'.js'); - $found += $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/'.$script.'.js', $webroot); - $found += $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/apps/'.$script.'.js', $webroot); + $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($baseDirectory, $themeDirectory.'/apps/'.$script.'.js', $webroot) - || $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/'.$script.'.js', $webroot) - || $this->appendOnceIfExist($this->serverroot, $script.'.js') - || $this->appendOnceIfExist($baseDirectory, $themeDirectory.'/core/'.$script.'.js', $webroot) - || $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 = substr($fullScript, 0, strpos($fullScript, '/')); + $fullScript = substr($fullScript, strpos($fullScript, '/')+1); $app_path = \OC_App::getAppPath($app); if( $app_path === false ) { return; } $app_url = \OC_App::getAppWebPath($app); $app_url = ($app_url !== false) ? $app_url : null; // missing translations files fill be ignored - $this->appendOnceIfExist($app_path, $script . '.js', $app_url); + $this->appendOnceIfExist($app_path, $fullScript, $app_url); } /** diff --git a/lib/private/Template/ResourceLocator.php b/lib/private/Template/ResourceLocator.php index 98aa50fad946..5958c92360f8 100644 --- a/lib/private/Template/ResourceLocator.php +++ b/lib/private/Template/ResourceLocator.php @@ -141,8 +141,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/Theme/Theme.php b/lib/private/Theme/Theme.php index 9b17edff12cc..fc7c8be1b3e0 100644 --- a/lib/private/Theme/Theme.php +++ b/lib/private/Theme/Theme.php @@ -28,7 +28,10 @@ class Theme implements ITheme { */ private $name; - private $baseDirectory = ''; + /** + * @var string + */ + private $baseDirectory; /** * @var string diff --git a/lib/private/Theme/ThemeService.php b/lib/private/Theme/ThemeService.php index 4627d7ae6521..8493959bc852 100644 --- a/lib/private/Theme/ThemeService.php +++ b/lib/private/Theme/ThemeService.php @@ -76,7 +76,7 @@ public function setAppTheme($themeName = '') { * @return Theme */ private function makeTheme($themeName, $appTheme = true, Theme $theme = null) { - $baseDirectory = ''; + $baseDirectory = \OC::$SERVERROOT; $directory = ''; $webPath = ''; if ($themeName !== '') { @@ -93,7 +93,7 @@ private function makeTheme($themeName, $appTheme = true, Theme $theme = null) { } } - $webPath = \OC_App::getAppWebPath($themeName); + $webPath = \OC_App::getAppWebPath($themeName); } else { $directory = 'themes/' . $themeName; $webPath = '/themes/' . $themeName; 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/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( [ From 4f5333d8e0cc6fc2989eb8ff835f077e2e49da78 Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Thu, 25 Jan 2018 21:45:14 +0300 Subject: [PATCH 6/9] Fix image path and L10N backend --- lib/private/L10N/Factory.php | 2 +- lib/private/URLGenerator.php | 28 ++++++++++++---------------- 2 files changed, 13 insertions(+), 17 deletions(-) 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/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; + } } } From a39c9805f2d60d4735d32df5107a8a62d8d73139 Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Fri, 2 Feb 2018 00:35:25 +0300 Subject: [PATCH 7/9] Add unit test for the relative web path --- lib/private/App/AppManager.php | 19 +++++++++++++++---- tests/lib/App/ManagerTest.php | 24 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 9eb26dbc2efe..217ddad464b8 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -523,12 +523,14 @@ public function getAppPath($appId) { */ public function getAppWebPath($appId) { if (($appRoot = $this->findAppInDirectories($appId)) !== false) { - $ocWebRoot = \OC::$WEBROOT; - while (strpos($appRoot['url'], '..') === 0) { - $appRoot['url'] = substr($appRoot['url'],3); + $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 . '/' . $appRoot['url']; + return $ocWebRoot . '/' . ltrim($appRoot['url'], '/'); } return false; } @@ -584,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/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); + } } From 04d01beea294360709d3ffe3ccffd16854650af4 Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Tue, 6 Feb 2018 22:14:18 +0300 Subject: [PATCH 8/9] Inject OC::SERVERROOT --- lib/private/Server.php | 5 ++- lib/private/Theme/ThemeService.php | 47 +++++++++++++++------------- tests/lib/Theme/ThemeServiceTest.php | 8 ++--- 3 files changed, 33 insertions(+), 27 deletions(-) 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/Theme/ThemeService.php b/lib/private/Theme/ThemeService.php index 8493959bc852..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,24 +71,26 @@ 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) { - $baseDirectory = \OC::$SERVERROOT; + private function makeTheme($themeName, $appTheme = true) { + $baseDirectory = $this->serverRoot; $directory = ''; $webPath = ''; if ($themeName !== '') { if ($appTheme) { $themeDirectory = \OC_App::getAppPath($themeName); - if (strpos($themeDirectory, \OC::$SERVERROOT)===0) { - $directory = substr($themeDirectory, strlen(\OC::$SERVERROOT) + 1); + // 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) { @@ -100,20 +107,16 @@ private function makeTheme($themeName, $appTheme = true, Theme $theme = null) { } } - if (is_null($theme)) { - $theme = new Theme( - $themeName, - $directory, - $webPath - ); + if (is_null($this->theme)) { + $this->theme = new Theme($themeName, $directory, $webPath); } else { - $theme->setName($themeName); - $theme->setDirectory($directory); - $theme->setWebPath($webPath); + $this->theme->setName($themeName); + $this->theme->setDirectory($directory); + $this->theme->setWebPath($webPath); } - $theme->setBaseDirectory($baseDirectory); + $this->theme->setBaseDirectory($baseDirectory); - return $theme; + return $this->theme; } /** @@ -141,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/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()); From 82cc6b01f0009a2eb8585ab7fb28b803f8697eb2 Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Wed, 7 Feb 2018 23:16:38 +0300 Subject: [PATCH 9/9] Inject appManager into ResourceLocator. Tests --- lib/private/Template/CSSResourceLocator.php | 29 ++-- lib/private/Template/JSResourceLocator.php | 16 ++- lib/private/Template/ResourceLocator.php | 21 ++- lib/private/TemplateLayout.php | 6 +- tests/lib/Template/CSSResourceLocatorTest.php | 106 ++++++++++++++ tests/lib/Template/JSResourceLocatorTest.php | 132 ++++++++++++++++++ tests/lib/Template/ResourceLocatorTest.php | 5 +- 7 files changed, 294 insertions(+), 21 deletions(-) create mode 100644 tests/lib/Template/CSSResourceLocatorTest.php create mode 100644 tests/lib/Template/JSResourceLocatorTest.php diff --git a/lib/private/Template/CSSResourceLocator.php b/lib/private/Template/CSSResourceLocator.php index 10333227c1b9..d86863f3f863 100644 --- a/lib/private/Template/CSSResourceLocator.php +++ b/lib/private/Template/CSSResourceLocator.php @@ -31,27 +31,28 @@ class CSSResourceLocator extends ResourceLocator { * @param string $style */ public function doFind($style) { + $fullStyle = $this->addExtension($style); if ( - $this->appendOnceIfExist($this->serverroot, $style.'.css') - || $this->appendOnceIfExist($this->serverroot, 'core/'.$style.'.css') + $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 = $style . '.css'; + $fullStyle = $this->addExtension($style); $themeDirectory = $this->theme->getDirectory(); $baseDirectory = $this->theme->getBaseDirectory(); $webRoot = ''; @@ -60,9 +61,9 @@ public function doFindTheme($style) { } $searchLocations = [ - $this->buildPath([$themeDirectory, '/apps', $fullStyle]), + $this->buildPath([$themeDirectory, 'apps', $fullStyle]), $this->buildPath([$themeDirectory, $fullStyle]), - $this->buildPath([$themeDirectory, '/core', $fullStyle]), + $this->buildPath([$themeDirectory, 'core', $fullStyle]), ]; foreach ($searchLocations as $location) { @@ -71,4 +72,12 @@ public function doFindTheme($style) { } } } + + /** + * @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 6e5e7ec00472..a266b2116cb2 100644 --- a/lib/private/Template/JSResourceLocator.php +++ b/lib/private/Template/JSResourceLocator.php @@ -31,7 +31,7 @@ class JSResourceLocator extends ResourceLocator { * @param string $script */ public function doFind($script) { - $fullScript = $script . '.js'; + $fullScript = $this->addExtension($script); $themeDirectory = $this->theme->getDirectory(); $baseDirectory = $this->theme->getBaseDirectory(); $webRoot = ''; @@ -63,12 +63,12 @@ public function doFind($script) { $app = substr($fullScript, 0, strpos($fullScript, '/')); $fullScript = substr($fullScript, strpos($fullScript, '/')+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; - // missing translations files fill be ignored + // missing translations files will be ignored $this->appendOnceIfExist($app_path, $fullScript, $app_url); } @@ -77,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 5958c92360f8..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 { @@ -42,17 +44,22 @@ abstract class ResourceLocator { 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 */ - public function __construct(\OCP\ILogger $logger, $theme, $core_map) { - $this->logger = $logger; + public function __construct(ITheme $theme, IAppManager $appManager, ILogger $logger, $core_map) { $this->theme = $theme; + $this->logger = $logger; + $this->appManager = $appManager; $this->mapping = $core_map; $this->serverroot = key($core_map); $this->webroot = $this->mapping[$this->serverroot]; @@ -68,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 * diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index 0bb307420229..2787a5cdc1bf 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -162,8 +162,9 @@ public function __construct( $renderAs, $appId = '' ) { */ static public function findStylesheetFiles($styles) { $locator = new \OC\Template\CSSResourceLocator( - \OC::$server->getLogger(), \OC_Util::getTheme(), + \OC::$server->getAppManager(), + \OC::$server->getLogger(), [\OC::$SERVERROOT => \OC::$WEBROOT]); $locator->find($styles); return $locator->getResources(); @@ -175,8 +176,9 @@ static public function findStylesheetFiles($styles) { */ static public function findJavascriptFiles($scripts) { $locator = new \OC\Template\JSResourceLocator( - \OC::$server->getLogger(), \OC_Util::getTheme(), + \OC::$server->getAppManager(), + \OC::$server->getLogger(), [\OC::$SERVERROOT => \OC::$WEBROOT]); $locator->find($scripts); return $locator->getResources(); 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 9e662aeacf27..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; @@ -47,8 +48,10 @@ 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, $appsRoots], + [$themeInstance, $appManagerInstance, $this->logger, $core_map, $appsRoots], '', true, true, true, []); }