mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #5830 from open-sausages/pulls/4.0/nested-themes-fixes
API Abstract ThemeManifest into ThemeList
This commit is contained in:
commit
46b15a93ca
@ -20,7 +20,7 @@ use SilverStripe\Security\Member;
|
|||||||
use SilverStripe\Security\Permission;
|
use SilverStripe\Security\Permission;
|
||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
use SilverStripe\Security\PermissionProvider;
|
use SilverStripe\Security\PermissionProvider;
|
||||||
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -408,7 +408,8 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
&& $candidate->MenuItem->controller
|
&& $candidate->MenuItem->controller
|
||||||
&& singleton($candidate->MenuItem->controller)->canView()
|
&& singleton($candidate->MenuItem->controller)->canView()
|
||||||
) {
|
) {
|
||||||
return $this->redirect($candidate->Link);
|
$this->redirect($candidate->Link);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,11 +435,14 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return Security::permissionFailure($this, $messageSet);
|
Security::permissionFailure($this, $messageSet);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't continue if there's already been a redirection request.
|
// Don't continue if there's already been a redirection request.
|
||||||
if($this->redirectedTo()) return;
|
if($this->redirectedTo()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Audit logging hook
|
// Audit logging hook
|
||||||
if(empty($_REQUEST['executeForm']) && !$this->getRequest()->isAjax()) $this->extend('accessedCMS');
|
if(empty($_REQUEST['executeForm']) && !$this->getRequest()->isAjax()) $this->extend('accessedCMS');
|
||||||
@ -452,29 +456,6 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
// file because insufficient information exists when that is being processed
|
// file because insufficient information exists when that is being processed
|
||||||
$htmlEditorConfig = HTMLEditorConfig::get_active();
|
$htmlEditorConfig = HTMLEditorConfig::get_active();
|
||||||
$htmlEditorConfig->setOption('language', i18n::get_tinymce_lang());
|
$htmlEditorConfig->setOption('language', i18n::get_tinymce_lang());
|
||||||
if(!$htmlEditorConfig->getOption('content_css')) {
|
|
||||||
$cssFiles = array();
|
|
||||||
$cssFiles[] = FRAMEWORK_ADMIN_DIR . '/client/dist/styles/editor.css';
|
|
||||||
|
|
||||||
// Use theme from the site config
|
|
||||||
if(class_exists('SiteConfig') && ($config = SiteConfig::current_site_config()) && $config->Theme) {
|
|
||||||
$theme = $config->Theme;
|
|
||||||
} elseif(Config::inst()->get('SSViewer', 'theme_enabled') && Config::inst()->get('SSViewer', 'theme')) {
|
|
||||||
$theme = Config::inst()->get('SSViewer', 'theme');
|
|
||||||
} else {
|
|
||||||
$theme = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($theme) $cssFiles[] = THEMES_DIR . "/{$theme}/css/editor.css";
|
|
||||||
else if(project()) $cssFiles[] = project() . '/css/editor.css';
|
|
||||||
|
|
||||||
// Remove files that don't exist
|
|
||||||
foreach($cssFiles as $k => $cssFile) {
|
|
||||||
if(!file_exists(BASE_PATH . '/' . $cssFile)) unset($cssFiles[$k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$htmlEditorConfig->setOption('content_css', implode(',', $cssFiles));
|
|
||||||
}
|
|
||||||
|
|
||||||
Requirements::customScript("
|
Requirements::customScript("
|
||||||
window.ss = window.ss || {};
|
window.ss = window.ss || {};
|
||||||
@ -1713,9 +1694,8 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
if($page) {
|
if($page) {
|
||||||
$navigator = new SilverStripeNavigator($page);
|
$navigator = new SilverStripeNavigator($page);
|
||||||
return $navigator->renderWith($this->getTemplatesWithSuffix('_SilverStripeNavigator'));
|
return $navigator->renderWith($this->getTemplatesWithSuffix('_SilverStripeNavigator'));
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,7 +77,7 @@ require_once 'core/manifest/ConfigManifest.php';
|
|||||||
require_once 'core/manifest/ConfigStaticManifest.php';
|
require_once 'core/manifest/ConfigStaticManifest.php';
|
||||||
require_once 'core/manifest/ClassManifest.php';
|
require_once 'core/manifest/ClassManifest.php';
|
||||||
require_once 'core/manifest/ManifestFileFinder.php';
|
require_once 'core/manifest/ManifestFileFinder.php';
|
||||||
require_once 'view/TemplateLoader.php';
|
require_once 'view/ThemeResourceLoader.php';
|
||||||
require_once 'core/manifest/TokenisedRegularExpression.php';
|
require_once 'core/manifest/TokenisedRegularExpression.php';
|
||||||
require_once 'control/injector/Injector.php';
|
require_once 'control/injector/Injector.php';
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ $configManifest = new SS_ConfigManifest(BASE_PATH, false, $flush);
|
|||||||
Config::inst()->pushConfigYamlManifest($configManifest);
|
Config::inst()->pushConfigYamlManifest($configManifest);
|
||||||
|
|
||||||
// Load template manifest
|
// Load template manifest
|
||||||
SilverStripe\View\TemplateLoader::instance()->addSet('$default', new SilverStripe\View\ThemeManifest(
|
SilverStripe\View\ThemeResourceLoader::instance()->addSet('$default', new SilverStripe\View\ThemeManifest(
|
||||||
BASE_PATH, project(), false, $flush
|
BASE_PATH, project(), false, $flush
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ use SilverStripe\Security\Member;
|
|||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
use SilverStripe\Security\Group;
|
use SilverStripe\Security\Group;
|
||||||
use SilverStripe\Security\Permission;
|
use SilverStripe\Security\Permission;
|
||||||
use SilverStripe\View\TemplateLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
use SilverStripe\View\ThemeManifest;
|
use SilverStripe\View\ThemeManifest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -848,7 +848,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
|
|||||||
SS_ClassLoader::instance()->pushManifest($classManifest, false);
|
SS_ClassLoader::instance()->pushManifest($classManifest, false);
|
||||||
SapphireTest::set_test_class_manifest($classManifest);
|
SapphireTest::set_test_class_manifest($classManifest);
|
||||||
|
|
||||||
TemplateLoader::instance()->addSet('$default', new ThemeManifest(
|
ThemeResourceLoader::instance()->addSet('$default', new ThemeManifest(
|
||||||
BASE_PATH, project(), true, $flush
|
BASE_PATH, project(), true, $flush
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -51,6 +51,8 @@
|
|||||||
a shorthand substitute.
|
a shorthand substitute.
|
||||||
* `FormField->dontEscape` has been removed. Escaping is now managed on a class by class basis.
|
* `FormField->dontEscape` has been removed. Escaping is now managed on a class by class basis.
|
||||||
* `DBString->LimitWordCountXML` removed. Use `LimitWordCount` for XML safe version.
|
* `DBString->LimitWordCountXML` removed. Use `LimitWordCount` for XML safe version.
|
||||||
|
* `$module` parameter in `themedCSS` and `themedJavascript` removed.
|
||||||
|
* Theme selector has been removed from SiteConfig. Please use `SSViewer.themes` config instead.
|
||||||
|
|
||||||
## New API
|
## New API
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use SilverStripe\View\TemplateLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default configuration for HtmlEditor specific to tinymce
|
* Default configuration for HtmlEditor specific to tinymce
|
||||||
@ -417,24 +417,16 @@ class TinyMCEConfig extends HTMLEditorConfig {
|
|||||||
*/
|
*/
|
||||||
protected function getEditorCSS() {
|
protected function getEditorCSS() {
|
||||||
$editor = array();
|
$editor = array();
|
||||||
$editor[] = Controller::join_links(
|
|
||||||
Director::absoluteBaseURL(),
|
|
||||||
FRAMEWORK_ADMIN_DIR . '/client/dist/styles/editor.css'
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach(SSViewer::get_themes() as $theme) {
|
// Add standard editor.css
|
||||||
$path = TemplateLoader::instance()->getPath($theme);
|
$editor[] = Director::absoluteURL(FRAMEWORK_ADMIN_DIR . '/client/dist/styles/editor.css');
|
||||||
$editorDir = $path . '/css/editor.css';;
|
|
||||||
|
|
||||||
if(file_exists(BASE_PATH . '/' . $editorDir)) {
|
// Themed editor.css
|
||||||
$editor[] = Controller::join_links(
|
$themedEditor = ThemeResourceLoader::instance()->findThemedCSS('editor', SSViewer::get_themes());
|
||||||
Director::absoluteBaseURL(),
|
if($themedEditor) {
|
||||||
$editorDir
|
$editor[] = Director::absoluteURL($themedEditor, Director::BASE);
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $editor;
|
return $editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use SilverStripe\View\TemplateLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
use SilverStripe\View\ThemeManifest;
|
use SilverStripe\View\ThemeManifest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9,7 +9,7 @@ use SilverStripe\View\ThemeManifest;
|
|||||||
* @package framework
|
* @package framework
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class TemplateLoaderTest extends SapphireTest {
|
class ThemeResourceLoaderTest extends SapphireTest {
|
||||||
|
|
||||||
private $base;
|
private $base;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ class TemplateLoaderTest extends SapphireTest {
|
|||||||
private $manifest;
|
private $manifest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var TemplateLoader
|
* @var ThemeResourceLoader
|
||||||
*/
|
*/
|
||||||
private $loader;
|
private $loader;
|
||||||
|
|
||||||
@ -28,12 +28,13 @@ class TemplateLoaderTest extends SapphireTest {
|
|||||||
*/
|
*/
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
// Fake project root
|
// Fake project root
|
||||||
$this->base = dirname(__FILE__) . '/fixtures/templatemanifest';
|
$this->base = dirname(__FILE__) . '/fixtures/templatemanifest';
|
||||||
// New ThemeManifest for that root
|
// New ThemeManifest for that root
|
||||||
$this->manifest = new ThemeManifest($this->base, 'myproject', false, true);
|
$this->manifest = new ThemeManifest($this->base, 'myproject', false, true);
|
||||||
// New Loader for that root
|
// New Loader for that root
|
||||||
$this->loader = new TemplateLoader($this->base);
|
$this->loader = new ThemeResourceLoader($this->base);
|
||||||
$this->loader->addSet('$default', $this->manifest);
|
$this->loader->addSet('$default', $this->manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +129,58 @@ class TemplateLoaderTest extends SapphireTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFindThemedCSS() {
|
||||||
|
$this->assertEquals(
|
||||||
|
"myproject/css/project.css",
|
||||||
|
$this->loader->findThemedCSS('project', ['$default', 'theme'])
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
"themes/theme/css/project.css",
|
||||||
|
$this->loader->findThemedCSS('project', ['theme', '$default'])
|
||||||
|
);
|
||||||
|
$this->assertEmpty(
|
||||||
|
$this->loader->findThemedCSS('nofile', ['theme', '$default'])
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'module/css/content.css',
|
||||||
|
$this->loader->findThemedCSS('content', ['/module', 'theme'])
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'module/css/content.css',
|
||||||
|
$this->loader->findThemedCSS('content', ['/module', 'theme', '$default'])
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'module/css/content.css',
|
||||||
|
$this->loader->findThemedCSS('content', ['$default', '/module', 'theme'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindThemedJavascript() {
|
||||||
|
$this->assertEquals(
|
||||||
|
"myproject/javascript/project.js",
|
||||||
|
$this->loader->findThemedJavascript('project', ['$default', 'theme'])
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
"themes/theme/javascript/project.js",
|
||||||
|
$this->loader->findThemedJavascript('project', ['theme', '$default'])
|
||||||
|
);
|
||||||
|
$this->assertEmpty(
|
||||||
|
$this->loader->findThemedJavascript('nofile', ['theme', '$default'])
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'module/javascript/content.js',
|
||||||
|
$this->loader->findThemedJavascript('content', ['/module', 'theme'])
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'module/javascript/content.js',
|
||||||
|
$this->loader->findThemedJavascript('content', ['/module', 'theme', '$default'])
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'module/javascript/content.js',
|
||||||
|
$this->loader->findThemedJavascript('content', ['$default', '/module', 'theme'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
protected function createTestTemplates($templates) {
|
protected function createTestTemplates($templates) {
|
||||||
foreach ($templates as $template) {
|
foreach ($templates as $template) {
|
||||||
file_put_contents($template, '');
|
file_put_contents($template, '');
|
@ -0,0 +1,3 @@
|
|||||||
|
.class {
|
||||||
|
display: block;
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
.class {
|
||||||
|
display: block;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
var i = 0;
|
@ -0,0 +1 @@
|
|||||||
|
var i = 0;
|
@ -0,0 +1,3 @@
|
|||||||
|
.class {
|
||||||
|
display: block;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
var i = 0;
|
@ -0,0 +1,3 @@
|
|||||||
|
.class {
|
||||||
|
display: block;
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
.class {
|
||||||
|
display: block;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
var i = 0;
|
@ -0,0 +1 @@
|
|||||||
|
var i = 0;
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use SilverStripe\View\TemplateLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @package framework
|
* @package framework
|
||||||
@ -17,8 +17,8 @@ class i18nSSLegacyAdapterTest extends SapphireTest {
|
|||||||
Config::inst()->update('Director', 'alternate_base_folder', $this->alternateBasePath);
|
Config::inst()->update('Director', 'alternate_base_folder', $this->alternateBasePath);
|
||||||
|
|
||||||
// Replace old template loader with new one with alternate base path
|
// Replace old template loader with new one with alternate base path
|
||||||
$this->_oldLoader = TemplateLoader::instance();
|
$this->_oldLoader = ThemeResourceLoader::instance();
|
||||||
TemplateLoader::set_instance(new TemplateLoader($this->alternateBasePath));
|
ThemeResourceLoader::set_instance(new ThemeResourceLoader($this->alternateBasePath));
|
||||||
|
|
||||||
$this->_oldTheme = Config::inst()->get('SSViewer', 'theme');
|
$this->_oldTheme = Config::inst()->get('SSViewer', 'theme');
|
||||||
Config::inst()->update('SSViewer', 'theme', 'testtheme1');
|
Config::inst()->update('SSViewer', 'theme', 'testtheme1');
|
||||||
@ -42,7 +42,7 @@ class i18nSSLegacyAdapterTest extends SapphireTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
TemplateLoader::set_instance($this->_oldLoader);
|
ThemeResourceLoader::set_instance($this->_oldLoader);
|
||||||
SS_ClassLoader::instance()->popManifest();
|
SS_ClassLoader::instance()->popManifest();
|
||||||
i18n::set_locale($this->originalLocale);
|
i18n::set_locale($this->originalLocale);
|
||||||
Config::inst()->update('Director', 'alternate_base_folder', null);
|
Config::inst()->update('Director', 'alternate_base_folder', null);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\View\TemplateLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
use SilverStripe\View\ThemeManifest;
|
use SilverStripe\View\ThemeManifest;
|
||||||
|
|
||||||
require_once 'Zend/Translate.php';
|
require_once 'Zend/Translate.php';
|
||||||
@ -39,8 +39,8 @@ class i18nTest extends SapphireTest {
|
|||||||
Config::inst()->update('Director', 'alternate_base_folder', $this->alternateBasePath);
|
Config::inst()->update('Director', 'alternate_base_folder', $this->alternateBasePath);
|
||||||
|
|
||||||
// Replace old template loader with new one with alternate base path
|
// Replace old template loader with new one with alternate base path
|
||||||
$this->_oldLoader = TemplateLoader::instance();
|
$this->_oldLoader = ThemeResourceLoader::instance();
|
||||||
TemplateLoader::set_instance($loader = new TemplateLoader($this->alternateBasePath));
|
ThemeResourceLoader::set_instance($loader = new ThemeResourceLoader($this->alternateBasePath));
|
||||||
$loader->addSet('$default', new ThemeManifest(
|
$loader->addSet('$default', new ThemeManifest(
|
||||||
$this->alternateBasePath, project(), false, true
|
$this->alternateBasePath, project(), false, true
|
||||||
));
|
));
|
||||||
@ -64,7 +64,7 @@ class i18nTest extends SapphireTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
TemplateLoader::set_instance($this->_oldLoader);
|
ThemeResourceLoader::set_instance($this->_oldLoader);
|
||||||
i18n::set_locale($this->originalLocale);
|
i18n::set_locale($this->originalLocale);
|
||||||
Config::inst()->update('Director', 'alternate_base_folder', null);
|
Config::inst()->update('Director', 'alternate_base_folder', null);
|
||||||
Config::inst()->update('SSViewer', 'theme', $this->_oldTheme);
|
Config::inst()->update('SSViewer', 'theme', $this->_oldTheme);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use SilverStripe\View\TemplateLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @package framework
|
* @package framework
|
||||||
@ -38,12 +38,12 @@ class i18nTextCollectorTest extends SapphireTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Replace old template loader with new one with alternate base path
|
// Replace old template loader with new one with alternate base path
|
||||||
$this->_oldLoader = TemplateLoader::instance();
|
$this->_oldLoader = ThemeResourceLoader::instance();
|
||||||
TemplateLoader::set_instance(new TemplateLoader($this->alternateBasePath));
|
ThemeResourceLoader::set_instance(new ThemeResourceLoader($this->alternateBasePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
TemplateLoader::set_instance($this->_oldLoader);
|
ThemeResourceLoader::set_instance($this->_oldLoader);
|
||||||
// Pop if added during testing
|
// Pop if added during testing
|
||||||
if(SS_ClassLoader::instance()->getManifest() === $this->manifest) {
|
if(SS_ClassLoader::instance()->getManifest() === $this->manifest) {
|
||||||
SS_ClassLoader::instance()->popManifest();
|
SS_ClassLoader::instance()->popManifest();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use SilverStripe\Filesystem\Storage\GeneratedAssetHandler;
|
use SilverStripe\Filesystem\Storage\GeneratedAssetHandler;
|
||||||
use SilverStripe\View\TemplateLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requirements tracker for JavaScript and CSS.
|
* Requirements tracker for JavaScript and CSS.
|
||||||
@ -190,13 +190,11 @@ class Requirements implements Flushable {
|
|||||||
* the module is used.
|
* the module is used.
|
||||||
*
|
*
|
||||||
* @param string $name The name of the file - eg '/css/File.css' would have the name 'File'
|
* @param string $name The name of the file - eg '/css/File.css' would have the name 'File'
|
||||||
* @param string $module The module to fall back to if the css file does not exist in the
|
|
||||||
* current theme.
|
|
||||||
* @param string $media Comma-separated list of media types to use in the link tag
|
* @param string $media Comma-separated list of media types to use in the link tag
|
||||||
* (e.g. 'screen,projector')
|
* (e.g. 'screen,projector')
|
||||||
*/
|
*/
|
||||||
public static function themedCSS($name, $module = null, $media = null) {
|
public static function themedCSS($name, $media = null) {
|
||||||
self::backend()->themedCSS($name, $module, $media);
|
self::backend()->themedCSS($name, $media);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -207,13 +205,11 @@ class Requirements implements Flushable {
|
|||||||
* the module is used.
|
* the module is used.
|
||||||
*
|
*
|
||||||
* @param string $name The name of the file - eg '/javascript/File.js' would have the name 'File'
|
* @param string $name The name of the file - eg '/javascript/File.js' would have the name 'File'
|
||||||
* @param string $module The module to fall back to if the javascript file does not exist in the
|
|
||||||
* current theme.
|
|
||||||
* @param string $type Comma-separated list of types to use in the script tag
|
* @param string $type Comma-separated list of types to use in the script tag
|
||||||
* (e.g. 'text/javascript,text/ecmascript')
|
* (e.g. 'text/javascript,text/ecmascript')
|
||||||
*/
|
*/
|
||||||
public static function themedJavascript($name, $module = null, $type = null) {
|
public static function themedJavascript($name, $type = null) {
|
||||||
return self::backend()->themedJavascript($name, $module, $type);
|
return self::backend()->themedJavascript($name, $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1810,34 +1806,19 @@ class Requirements_Backend
|
|||||||
* the module is used.
|
* the module is used.
|
||||||
*
|
*
|
||||||
* @param string $name The name of the file - eg '/css/File.css' would have the name 'File'
|
* @param string $name The name of the file - eg '/css/File.css' would have the name 'File'
|
||||||
* @param string $module The module to fall back to if the css file does not exist in the
|
|
||||||
* current theme.
|
|
||||||
* @param string $media Comma-separated list of media types to use in the link tag
|
* @param string $media Comma-separated list of media types to use in the link tag
|
||||||
* (e.g. 'screen,projector')
|
* (e.g. 'screen,projector')
|
||||||
*/
|
*/
|
||||||
public function themedCSS($name, $module = null, $media = null) {
|
public function themedCSS($name, $media = null) {
|
||||||
$css = "/css/$name.css";
|
$path = ThemeResourceLoader::instance()->findThemedCSS($name, SSViewer::get_themes());
|
||||||
|
if($path) {
|
||||||
$project = project();
|
$this->css($path, $media);
|
||||||
$absbase = BASE_PATH . DIRECTORY_SEPARATOR;
|
} else {
|
||||||
$absproject = $absbase . $project;
|
throw new \InvalidArgumentException(
|
||||||
|
"The css file doesn't exists. Please check if the file $name.css exists in any context or search for "
|
||||||
if(file_exists($absproject . $css)) {
|
. "themedCSS references calling this file in your templates."
|
||||||
return $this->css($project . $css, $media);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(SSViewer::get_themes() as $theme) {
|
|
||||||
$path = TemplateLoader::instance()->getPath($theme);
|
|
||||||
$abspath = BASE_PATH . '/' . $path;
|
|
||||||
|
|
||||||
if(file_exists($abspath . $css)) {
|
|
||||||
return $this->css($path . $css, $media);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
"The css file doesn't exists. Please check if the file $name.css exists in any context or search for "
|
|
||||||
. "themedCSS references calling this file in your templates."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1848,38 +1829,23 @@ class Requirements_Backend
|
|||||||
* the module is used.
|
* the module is used.
|
||||||
*
|
*
|
||||||
* @param string $name The name of the file - eg '/js/File.js' would have the name 'File'
|
* @param string $name The name of the file - eg '/js/File.js' would have the name 'File'
|
||||||
* @param string $module The module to fall back to if the javascript file does not exist in the
|
|
||||||
* current theme.
|
|
||||||
* @param string $type Comma-separated list of types to use in the script tag
|
* @param string $type Comma-separated list of types to use in the script tag
|
||||||
* (e.g. 'text/javascript,text/ecmascript')
|
* (e.g. 'text/javascript,text/ecmascript')
|
||||||
*/
|
*/
|
||||||
public function themedJavascript($name, $module = null, $type = null) {
|
public function themedJavascript($name, $type = null) {
|
||||||
$js = "/javascript/$name.js";
|
$path = ThemeResourceLoader::instance()->findThemedJavascript($name, SSViewer::get_themes());
|
||||||
|
if($path) {
|
||||||
$opts = array(
|
$opts = [];
|
||||||
'type' => $type,
|
if($type) {
|
||||||
);
|
$opts['type'] = $type;
|
||||||
|
}
|
||||||
$project = project();
|
$this->javascript($path, $opts);
|
||||||
$absbase = BASE_PATH . DIRECTORY_SEPARATOR;
|
} else {
|
||||||
$absproject = $absbase . $project;
|
throw new \InvalidArgumentException(
|
||||||
|
"The javascript file doesn't exists. Please check if the file $name.js exists in any "
|
||||||
if(file_exists($absproject . $js)) {
|
. "context or search for themedJavascript references calling this file in your templates."
|
||||||
return $this->javascript($project . $js, $opts);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(SSViewer::get_themes() as $theme) {
|
|
||||||
$path = TemplateLoader::instance()->getPath($theme);
|
|
||||||
$abspath = BASE_PATH . '/' . $path;
|
|
||||||
|
|
||||||
if(file_exists($abspath . $js)) {
|
|
||||||
return $this->javascript($path . $js, $opts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
"The javascript file doesn't exists. Please check if the file $name.js exists in any context or search for "
|
|
||||||
. "themedJavascript references calling this file in your templates."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use SilverStripe\ORM\FieldType\DBField;
|
use SilverStripe\ORM\FieldType\DBField;
|
||||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||||
use SilverStripe\Security\Permission;
|
use SilverStripe\Security\Permission;
|
||||||
use SilverStripe\View\TemplateLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This tracks the current scope for an SSViewer instance. It has three goals:
|
* This tracks the current scope for an SSViewer instance. It has three goals:
|
||||||
@ -686,6 +686,11 @@ class SSViewer_DataPresenter extends SSViewer_Scope {
|
|||||||
*/
|
*/
|
||||||
class SSViewer implements Flushable {
|
class SSViewer implements Flushable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier for the default theme
|
||||||
|
*/
|
||||||
|
const DEFAULT_THEME = '$default';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
* @var boolean $source_file_comments
|
* @var boolean $source_file_comments
|
||||||
@ -809,6 +814,12 @@ class SSViewer implements Flushable {
|
|||||||
return $viewer;
|
return $viewer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign the list of active themes to apply.
|
||||||
|
* If default themes should be included add $default as the last entry.
|
||||||
|
*
|
||||||
|
* @param array $themes
|
||||||
|
*/
|
||||||
public static function set_themes($themes = []) {
|
public static function set_themes($themes = []) {
|
||||||
Config::inst()->remove('SSViewer', 'themes');
|
Config::inst()->remove('SSViewer', 'themes');
|
||||||
Config::inst()->update('SSViewer', 'themes', $themes);
|
Config::inst()->update('SSViewer', 'themes', $themes);
|
||||||
@ -819,14 +830,23 @@ class SSViewer implements Flushable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function get_themes() {
|
public static function get_themes() {
|
||||||
$res = ['$default'];
|
$default = [self::DEFAULT_THEME];
|
||||||
|
|
||||||
if (Config::inst()->get('SSViewer', 'theme_enabled')) {
|
if (!Config::inst()->get('SSViewer', 'theme_enabled')) {
|
||||||
if ($list = Config::inst()->get('SSViewer', 'themes')) $res = $list;
|
return $default;
|
||||||
elseif ($theme = Config::inst()->get('SSViewer', 'theme')) $res = [$theme, '$default'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $res;
|
// Explicit list is assigned
|
||||||
|
if ($list = Config::inst()->get('SSViewer', 'themes')) {
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support legacy behaviour
|
||||||
|
if ($theme = Config::inst()->get('SSViewer', 'theme')) {
|
||||||
|
return [$theme, self::DEFAULT_THEME];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -835,7 +855,7 @@ class SSViewer implements Flushable {
|
|||||||
*/
|
*/
|
||||||
public static function set_theme($theme) {
|
public static function set_theme($theme) {
|
||||||
Deprecation::notice('4.0', 'Use the "SSViewer#set_themes" instead');
|
Deprecation::notice('4.0', 'Use the "SSViewer#set_themes" instead');
|
||||||
self::set_themes([$theme]);
|
self::set_themes([$theme, self::DEFAULT_THEME]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -850,9 +870,9 @@ class SSViewer implements Flushable {
|
|||||||
public static function get_templates_by_class($className, $suffix = '', $baseClass = null) {
|
public static function get_templates_by_class($className, $suffix = '', $baseClass = null) {
|
||||||
// Figure out the class name from the supplied context.
|
// Figure out the class name from the supplied context.
|
||||||
if(!is_string($className) || !class_exists($className)) {
|
if(!is_string($className) || !class_exists($className)) {
|
||||||
throw new InvalidArgumentException('SSViewer::get_templates_by_class() expects a valid class name as ' .
|
throw new InvalidArgumentException(
|
||||||
'its first parameter.');
|
'SSViewer::get_templates_by_class() expects a valid class name as its first parameter.'
|
||||||
return array();
|
);
|
||||||
}
|
}
|
||||||
$templates = array();
|
$templates = array();
|
||||||
$classes = array_reverse(ClassInfo::ancestry($className));
|
$classes = array_reverse(ClassInfo::ancestry($className));
|
||||||
@ -904,7 +924,7 @@ class SSViewer implements Flushable {
|
|||||||
|
|
||||||
public function setTemplate($templates) {
|
public function setTemplate($templates) {
|
||||||
$this->templates = $templates;
|
$this->templates = $templates;
|
||||||
$this->chosen = TemplateLoader::instance()->findTemplate($templates, self::get_themes());
|
$this->chosen = ThemeResourceLoader::instance()->findTemplate($templates, self::get_themes());
|
||||||
$this->subTemplates = [];
|
$this->subTemplates = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -937,7 +957,7 @@ class SSViewer implements Flushable {
|
|||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public static function hasTemplate($templates) {
|
public static function hasTemplate($templates) {
|
||||||
return (bool)TemplateLoader::instance()->findTemplate($templates, self::get_themes());
|
return (bool)ThemeResourceLoader::instance()->findTemplate($templates, self::get_themes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1014,7 +1034,7 @@ class SSViewer implements Flushable {
|
|||||||
* @return string Full system path to a template file
|
* @return string Full system path to a template file
|
||||||
*/
|
*/
|
||||||
public static function getTemplateFileByType($identifier, $type) {
|
public static function getTemplateFileByType($identifier, $type) {
|
||||||
return TemplateLoader::instance()->findTemplate(['type' => $type, $identifier], self::get_themes());
|
return ThemeResourceLoader::instance()->findTemplate(['type' => $type, $identifier], self::get_themes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
29
view/ThemeList.php
Normal file
29
view/ThemeList.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains references to any number of themes or theme directories
|
||||||
|
*/
|
||||||
|
interface ThemeList
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a map of all themes information. The map is in the following format:
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* [
|
||||||
|
* '/mysite',
|
||||||
|
* 'vendor/module:themename',
|
||||||
|
* '/framework/admin'
|
||||||
|
* 'simple'
|
||||||
|
* ]
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* These may be in any format, including vendor/namespace:path, or /absolute-path,
|
||||||
|
* but will not include references to any other {@see ThemeContainer} as
|
||||||
|
* SSViewer::get_themes() does.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getThemes();
|
||||||
|
}
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
namespace SilverStripe\View;
|
namespace SilverStripe\View;
|
||||||
|
|
||||||
use \ManifestFileFinder;
|
use ManifestCache;
|
||||||
|
use ManifestFileFinder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class which builds a manifest of all themes (which is really just a directory called "templates")
|
* A class which builds a manifest of all themes (which is really just a directory called "templates")
|
||||||
@ -10,17 +11,50 @@ use \ManifestFileFinder;
|
|||||||
* @package framework
|
* @package framework
|
||||||
* @subpackage manifest
|
* @subpackage manifest
|
||||||
*/
|
*/
|
||||||
class ThemeManifest {
|
class ThemeManifest implements ThemeList {
|
||||||
|
|
||||||
const TEMPLATES_DIR = 'templates';
|
const TEMPLATES_DIR = 'templates';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base path
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $base;
|
protected $base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Include tests
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
protected $tests;
|
protected $tests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path to application code
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $project;
|
protected $project;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache
|
||||||
|
*
|
||||||
|
* @var ManifestCache
|
||||||
|
*/
|
||||||
protected $cache;
|
protected $cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache key
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $cacheKey;
|
protected $cacheKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of theme root directories
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $themes = null;
|
protected $themes = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,21 +105,10 @@ class ThemeManifest {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a map of all themes information. The map is in the following format:
|
|
||||||
*
|
|
||||||
* <code>
|
|
||||||
* [
|
|
||||||
* 'mysite',
|
|
||||||
* 'framework',
|
|
||||||
* 'framework/admin'
|
|
||||||
* ]
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getThemes() {
|
public function getThemes() {
|
||||||
if ($this->themes === null) $this->init();
|
if ($this->themes === null) {
|
||||||
|
$this->init();
|
||||||
|
}
|
||||||
return $this->themes;
|
return $this->themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,26 +134,38 @@ class ThemeManifest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a directory to the manifest
|
||||||
|
*
|
||||||
|
* @param string $basename
|
||||||
|
* @param string $pathname
|
||||||
|
* @param int $depth
|
||||||
|
*/
|
||||||
public function handleDirectory($basename, $pathname, $depth)
|
public function handleDirectory($basename, $pathname, $depth)
|
||||||
{
|
{
|
||||||
if ($basename == self::TEMPLATES_DIR) {
|
if ($basename !== self::TEMPLATES_DIR) {
|
||||||
// We only want part of the full path, so split into directories
|
return;
|
||||||
$parts = explode('/', $pathname);
|
}
|
||||||
// Take the end (the part relative to base), except the very last directory
|
|
||||||
$themeParts = array_slice($parts, -$depth, $depth-1);
|
|
||||||
// Then join again
|
|
||||||
$path = '/'.implode('/', $themeParts);
|
|
||||||
|
|
||||||
// If this is in the project, add to beginning of list. Else add to end.
|
// We only want part of the full path, so split into directories
|
||||||
if ($themeParts[0] == $this->project) {
|
$parts = explode('/', $pathname);
|
||||||
array_unshift($this->themes, $path);
|
// Take the end (the part relative to base), except the very last directory
|
||||||
}
|
$themeParts = array_slice($parts, -$depth, $depth-1);
|
||||||
else {
|
// Then join again
|
||||||
array_push($this->themes, $path);
|
$path = '/'.implode('/', $themeParts);
|
||||||
}
|
|
||||||
|
// If this is in the project, add to beginning of list. Else add to end.
|
||||||
|
if ($themeParts[0] == $this->project) {
|
||||||
|
array_unshift($this->themes, $path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
array_push($this->themes, $path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the manifest
|
||||||
|
*/
|
||||||
protected function init() {
|
protected function init() {
|
||||||
if ($data = $this->cache->load($this->cacheKey)) {
|
if ($data = $this->cache->load($this->cacheKey)) {
|
||||||
$this->themes = $data;
|
$this->themes = $data;
|
||||||
|
@ -2,31 +2,44 @@
|
|||||||
|
|
||||||
namespace SilverStripe\View;
|
namespace SilverStripe\View;
|
||||||
|
|
||||||
|
use Deprecation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles finding templates from a stack of template manifest objects.
|
* Handles finding templates from a stack of template manifest objects.
|
||||||
*
|
*
|
||||||
* @package framework
|
* @package framework
|
||||||
* @subpackage view
|
* @subpackage view
|
||||||
*/
|
*/
|
||||||
class TemplateLoader {
|
class ThemeResourceLoader {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var TemplateLoader
|
* @var ThemeResourceLoader
|
||||||
*/
|
*/
|
||||||
private static $instance;
|
private static $instance;
|
||||||
|
|
||||||
protected $base;
|
protected $base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ThemeManifest[]
|
* List of template "sets" that contain a test manifest, and have an alias.
|
||||||
|
* E.g. '$default'
|
||||||
|
*
|
||||||
|
* @var ThemeList[]
|
||||||
*/
|
*/
|
||||||
protected $sets = [];
|
protected $sets = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ThemeResourceLoader
|
||||||
|
*/
|
||||||
public static function instance() {
|
public static function instance() {
|
||||||
return self::$instance ? self::$instance : self::$instance = new self();
|
return self::$instance ? self::$instance : self::$instance = new self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function set_instance(TemplateLoader $instance) {
|
/**
|
||||||
|
* Set instance
|
||||||
|
*
|
||||||
|
* @param ThemeResourceLoader $instance
|
||||||
|
*/
|
||||||
|
public static function set_instance(ThemeResourceLoader $instance) {
|
||||||
self::$instance = $instance;
|
self::$instance = $instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,12 +51,25 @@ class TemplateLoader {
|
|||||||
* Add a new theme manifest for a given identifier. E.g. '$default'
|
* Add a new theme manifest for a given identifier. E.g. '$default'
|
||||||
*
|
*
|
||||||
* @param string $set
|
* @param string $set
|
||||||
* @param ThemeManifest $manifest
|
* @param ThemeList $manifest
|
||||||
*/
|
*/
|
||||||
public function addSet($set, $manifest) {
|
public function addSet($set, ThemeList $manifest) {
|
||||||
$this->sets[$set] = $manifest;
|
$this->sets[$set] = $manifest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a named theme set
|
||||||
|
*
|
||||||
|
* @param string $set
|
||||||
|
* @return ThemeList
|
||||||
|
*/
|
||||||
|
public function getSet($set) {
|
||||||
|
if(isset($this->sets[$set])) {
|
||||||
|
return $this->sets[$set];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a theme identifier, determine the path from the root directory
|
* Given a theme identifier, determine the path from the root directory
|
||||||
*
|
*
|
||||||
@ -56,7 +82,7 @@ class TemplateLoader {
|
|||||||
* of that module. ('/mymodule').
|
* of that module. ('/mymodule').
|
||||||
*
|
*
|
||||||
* @param string $identifier Theme identifier.
|
* @param string $identifier Theme identifier.
|
||||||
* @return string Path from root, not including leading forward slash. E.g. themes/mytheme
|
* @return string Path from root, not including leading or trailing forward slash. E.g. themes/mytheme
|
||||||
*/
|
*/
|
||||||
public function getPath($identifier) {
|
public function getPath($identifier) {
|
||||||
$slashPos = strpos($identifier, '/');
|
$slashPos = strpos($identifier, '/');
|
||||||
@ -111,7 +137,9 @@ class TemplateLoader {
|
|||||||
* theme-coupled resolution.
|
* theme-coupled resolution.
|
||||||
* @param array $themes List of themes to use to resolve themes. In most cases
|
* @param array $themes List of themes to use to resolve themes. In most cases
|
||||||
* you should pass in {@see SSViewer::get_themes()}
|
* you should pass in {@see SSViewer::get_themes()}
|
||||||
* @return string Path to resolved template file, or null if not resolved.
|
* @return string Absolute path to resolved template file, or null if not resolved.
|
||||||
|
* File location will be in the format themes/<theme>/templates/<directories>/<type>/<basename>.ss
|
||||||
|
* Note that type (e.g. 'Layout') is not the root level directory under 'templates'.
|
||||||
*/
|
*/
|
||||||
public function findTemplate($template, $themes) {
|
public function findTemplate($template, $themes) {
|
||||||
$type = '';
|
$type = '';
|
||||||
@ -141,14 +169,13 @@ class TemplateLoader {
|
|||||||
$tail = array_pop($parts);
|
$tail = array_pop($parts);
|
||||||
$head = implode('/', $parts);
|
$head = implode('/', $parts);
|
||||||
|
|
||||||
foreach($themes as $themename) {
|
$themePaths = $this->getThemePaths($themes);
|
||||||
$subthemes = isset($this->sets[$themename]) ? $this->sets[$themename]->getThemes() : [$themename];
|
foreach($themePaths as $themePath) {
|
||||||
|
// Join path
|
||||||
foreach($subthemes as $theme) {
|
$pathParts = [ $this->base, $themePath, 'templates', $head, $type, $tail ];
|
||||||
$themePath = $this->base . '/' . $this->getPath($theme);
|
$path = implode('/', array_filter($pathParts)) . '.ss';
|
||||||
|
if (file_exists($path)) {
|
||||||
$path = $themePath . '/templates/' . implode('/', array_filter([$head, $type, $tail])) . '.ss';
|
return $path;
|
||||||
if (file_exists($path)) return $path;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,4 +184,73 @@ class TemplateLoader {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve themed CSS path
|
||||||
|
*
|
||||||
|
* @param string $name Name of CSS file without extension
|
||||||
|
* @param array $themes List of themes
|
||||||
|
* @return string Path to resolved CSS file (relative to base dir)
|
||||||
|
*/
|
||||||
|
public function findThemedCSS($name, $themes)
|
||||||
|
{
|
||||||
|
$css = "/css/$name.css";
|
||||||
|
$paths = $this->getThemePaths($themes);
|
||||||
|
foreach ($paths as $themePath) {
|
||||||
|
$abspath = $this->base . '/' . $themePath;
|
||||||
|
|
||||||
|
if (file_exists($abspath . $css)) {
|
||||||
|
return $themePath . $css;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSS exists in no context
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the given themeable javascript as required.
|
||||||
|
*
|
||||||
|
* A javascript file in the current theme path name 'themename/javascript/$name.js' is first searched for,
|
||||||
|
* and it that doesn't exist and the module parameter is set then a javascript file with that name in
|
||||||
|
* the module is used.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the file - eg '/js/File.js' would have the name 'File'
|
||||||
|
* @param array $themes List of themes
|
||||||
|
* @return string Path to resolved javascript file (relative to base dir)
|
||||||
|
*/
|
||||||
|
public function findThemedJavascript($name, $themes) {
|
||||||
|
$js = "/javascript/$name.js";
|
||||||
|
$paths = $this->getThemePaths($themes);
|
||||||
|
foreach ($paths as $themePath) {
|
||||||
|
$abspath = $this->base . '/' . $themePath;
|
||||||
|
|
||||||
|
if (file_exists($abspath . $js)) {
|
||||||
|
return $themePath . $js;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// js exists in no context
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve all themes to the list of root folders relative to site root
|
||||||
|
*
|
||||||
|
* @param array $themes List of themes to resolve. Supports named theme sets.
|
||||||
|
* @return array List of root-relative folders in order of precendence.
|
||||||
|
*/
|
||||||
|
public function getThemePaths($themes) {
|
||||||
|
$paths = [];
|
||||||
|
foreach($themes as $themename) {
|
||||||
|
// Expand theme sets
|
||||||
|
$set = $this->getSet($themename);
|
||||||
|
$subthemes = $set ? $set->getThemes() : [$themename];
|
||||||
|
|
||||||
|
// Resolve paths
|
||||||
|
foreach ($subthemes as $theme) {
|
||||||
|
$paths[] = $this->getPath($theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $paths;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user