mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENHANCEMENT Allow user theme selection through SiteConfig, falling back to SSViewer::set_theme() as a default if there are none selected
MINOR Unit tests for SSViewer::current_theme() and SiteConfig::getAvailableThemes() (from r98110) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@102597 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
334b83dd23
commit
21299ba686
@ -153,7 +153,7 @@ class ManifestBuilder {
|
||||
*
|
||||
* @param string $baseDir Optional: Absolute path to theme directory for testing e.g. "/Users/sharvey/Sites/test24/themes"
|
||||
* @param boolean $includeSubThemes If set to TRUE, sub-themes such as "blackcandy_blog" are included too
|
||||
* @return array indexed array of theme directories
|
||||
* @return array Listing of theme directories
|
||||
*/
|
||||
public static function get_themes($baseDir = null, $includeSubThemes = false) {
|
||||
// If no base directory specified, the default is the project root
|
||||
@ -168,7 +168,7 @@ class ManifestBuilder {
|
||||
if(strpos($file, '_') === false) {
|
||||
$include = true;
|
||||
}
|
||||
if($include) $themes[] = $file;
|
||||
if($include) $themes[$file] = $file;
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
|
@ -87,6 +87,11 @@ class SSViewer {
|
||||
*/
|
||||
protected static $current_theme = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected static $cached_theme = null;
|
||||
|
||||
/**
|
||||
* Create a template from a string instead of a .ss file
|
||||
*
|
||||
@ -106,8 +111,18 @@ class SSViewer {
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
static function current_theme() {
|
||||
return self::$current_theme;
|
||||
static function current_theme($cached = true) {
|
||||
if($cached && self::$cached_theme) {
|
||||
// First case is to return the cached user theme so we don't requery SiteConfig again
|
||||
return self::$cached_theme;
|
||||
} else {
|
||||
// Need to refresh the cache from the SiteConfig
|
||||
$theme = SiteConfig::current_site_config()->Theme;
|
||||
self::$cached_theme = $theme;
|
||||
}
|
||||
// Fall back to the default SSViewer::set_theme() behaviour
|
||||
if(!$theme) $theme = self::$current_theme;
|
||||
return $theme;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,13 +156,13 @@ class SSViewer {
|
||||
else $templateFolder = null;
|
||||
|
||||
// Use the theme template if available
|
||||
if(self::$current_theme && isset($_TEMPLATE_MANIFEST[$template]['themes'][self::$current_theme])) {
|
||||
if(self::current_theme() && isset($_TEMPLATE_MANIFEST[$template]['themes'][self::current_theme()])) {
|
||||
$this->chosenTemplates = array_merge(
|
||||
$_TEMPLATE_MANIFEST[$template]['themes'][self::$current_theme],
|
||||
$_TEMPLATE_MANIFEST[$template]['themes'][self::current_theme()],
|
||||
$this->chosenTemplates
|
||||
);
|
||||
|
||||
if(isset($_GET['debug_request'])) Debug::message("Found template '$template' from main theme '" . self::$current_theme . "': " . var_export($_TEMPLATE_MANIFEST[$template]['themes'][self::$current_theme], true));
|
||||
if(isset($_GET['debug_request'])) Debug::message("Found template '$template' from main theme '" . self::current_theme() . "': " . var_export($_TEMPLATE_MANIFEST[$template]['themes'][self::current_theme()], true));
|
||||
}
|
||||
|
||||
// Fall back to unthemed base templates
|
||||
@ -257,8 +272,8 @@ class SSViewer {
|
||||
*/
|
||||
public static function getTemplateFileByType($identifier, $type) {
|
||||
global $_TEMPLATE_MANIFEST;
|
||||
if(self::$current_theme && isset($_TEMPLATE_MANIFEST[$identifier]['themes'][self::$current_theme][$type])) {
|
||||
return $_TEMPLATE_MANIFEST[$identifier]['themes'][self::$current_theme][$type];
|
||||
if(self::current_theme() && isset($_TEMPLATE_MANIFEST[$identifier]['themes'][self::current_theme()][$type])) {
|
||||
return $_TEMPLATE_MANIFEST[$identifier]['themes'][self::current_theme()][$type];
|
||||
} else if(isset($_TEMPLATE_MANIFEST[$identifier][$type])){
|
||||
return $_TEMPLATE_MANIFEST[$identifier][$type];
|
||||
} else {
|
||||
|
@ -17,6 +17,7 @@ class SiteConfig extends DataObject {
|
||||
static $db = array(
|
||||
"Title" => "Varchar(255)",
|
||||
"Tagline" => "Varchar(255)",
|
||||
"Theme" => "Varchar(255)",
|
||||
"CanViewType" => "Enum('Anyone, LoggedInUsers, OnlyTheseUsers', 'Anyone')",
|
||||
"CanEditType" => "Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')",
|
||||
"CanCreateTopLevelType" => "Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')",
|
||||
@ -28,6 +29,12 @@ class SiteConfig extends DataObject {
|
||||
"CreateTopLevelGroups" => "Group"
|
||||
);
|
||||
|
||||
protected static $disabled_themes = array();
|
||||
|
||||
public static function disable_theme($theme) {
|
||||
self::$disabled_themes[$theme] = $theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields that are sent to the CMS. In
|
||||
* your decorators: updateEditFormFields(&$fields)
|
||||
@ -39,7 +46,8 @@ class SiteConfig extends DataObject {
|
||||
new TabSet("Root",
|
||||
new Tab('Main',
|
||||
$titleField = new TextField("Title", _t('SiteConfig.SITETITLE', "Site title")),
|
||||
$taglineField = new TextField("Tagline", _t('SiteConfig.SITETAGLINE', "Site Tagline/Slogan"))
|
||||
$taglineField = new TextField("Tagline", _t('SiteConfig.SITETAGLINE', "Site Tagline/Slogan")),
|
||||
new DropdownField("Theme", _t('SiteConfig.THEME', 'Theme'), $this->getAvailableThemes(), '', null, _t('SiteConfig.DEFAULTTHEME', '(Use default theme)'))
|
||||
),
|
||||
new Tab('Access',
|
||||
new HeaderField('WhoCanViewHeader', _t('SiteConfig.VIEWHEADER', "Who can view pages on this site?"), 2),
|
||||
@ -90,6 +98,19 @@ class SiteConfig extends DataObject {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available themes that haven't been marked as disabled.
|
||||
* @param string $baseDir Optional alternative theme base directory for testing
|
||||
* @return array of theme directory names
|
||||
*/
|
||||
public function getAvailableThemes($baseDir = null) {
|
||||
$themes = ManifestBuilder::get_themes($baseDir);
|
||||
foreach(self::$disabled_themes as $theme) {
|
||||
if(isset($themes[$theme])) unset($themes[$theme]);
|
||||
}
|
||||
return $themes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actions that are sent to the CMS. In
|
||||
* your decorators: updateEditFormActions(&$actions)
|
||||
|
@ -395,6 +395,25 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
return Controller::join_links($base, '/', $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the absolute URL for this page on the Live site.
|
||||
*/
|
||||
public function getAbsoluteLiveLink($includeStageEqualsLive = true) {
|
||||
$live = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $this->ID);
|
||||
|
||||
if($live) {
|
||||
$link = $live->AbsoluteLink();
|
||||
|
||||
if($includeStageEqualsLive) {
|
||||
$link .= '?stage=Live';
|
||||
}
|
||||
|
||||
return $link;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a CSS identifier generated from this page's link.
|
||||
*
|
||||
|
@ -37,15 +37,17 @@ table.CMSList thead th {
|
||||
background-repeat: repeat-x;
|
||||
background-position: left bottom;
|
||||
background-color: #ebeadb;
|
||||
height: 24px;
|
||||
border-right: 1px solid #aca899;
|
||||
border-left: 1px solid #ffffff;
|
||||
white-space: nowrap;
|
||||
padding: 3px;
|
||||
font-size: 12px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table.TableField thead th span,
|
||||
.TableListField table.data thead th span {
|
||||
display: block;
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
table.TableField thead th a,
|
||||
@ -57,8 +59,6 @@ table.CMSList thead th a {
|
||||
table.TableField thead th span.sortLink,
|
||||
.TableListField table.data thead th span.sortLink,
|
||||
table.CMSList thead th span.sortLink {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
@ -123,6 +123,7 @@ HTML;
|
||||
$field = new TreeMultiselectField_Readonly($this->name, $this->title, $this->sourceObject, $this->keyField, $this->labelField);
|
||||
$field->addExtraClass($this->extraClass());
|
||||
$field->setForm($this->form);
|
||||
$field->setValue($this->value);
|
||||
return $field;
|
||||
}
|
||||
}
|
||||
|
@ -17,15 +17,15 @@ TableListField.prototype = {
|
||||
rules['#'+this.id+' th'] = {
|
||||
initialize: function() {
|
||||
var sortLinks = $$('span.sortLinkHidden a', this);
|
||||
if(sortLinks) Element.hide(sortLinks[0]);
|
||||
if(sortLinks) sortLinks[0].style.visibility = 'hidden';
|
||||
},
|
||||
onmouseover: function(e) {
|
||||
var sortLinks = $$('span.sortLinkHidden a', this);
|
||||
if(sortLinks) Element.show(sortLinks[0]);
|
||||
if(sortLinks) sortLinks[0].style.visibility = 'visible';
|
||||
},
|
||||
onmouseout: function(e) {
|
||||
var sortLinks = $$('span.sortLinkHidden a', this);
|
||||
if(sortLinks) Element.hide(sortLinks[0]);
|
||||
if(sortLinks) sortLinks[0].style.visibility = 'hidden';
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -18,17 +18,16 @@
|
||||
<a href="$SortLink">$Title</a>
|
||||
</span>
|
||||
<span class="sortLink <% if SortBy %><% else %>sortLinkHidden<% end_if %>">
|
||||
<a href="$SortLink"">
|
||||
<% if SortDirection = desc %>
|
||||
<img src="cms/images/bullet_arrow_down.png" alt="<% _t('SORTDESC', 'Sort in descending order') %>" />
|
||||
<a href="$SortLink"><img src="cms/images/bullet_arrow_down.png" alt="<% _t('SORTDESC', 'Sort in descending order') %>" /></a>
|
||||
<% else %>
|
||||
<img src="cms/images/bullet_arrow_up.png" alt="<% _t('SORTASC', 'Sort in ascending order') %>" />
|
||||
<a href="$SortLink"><img src="cms/images/bullet_arrow_up.png" alt="<% _t('SORTASC', 'Sort in ascending order') %>" /></a>
|
||||
<% end_if %>
|
||||
</a>
|
||||
|
||||
</span>
|
||||
<% else %>
|
||||
$Title
|
||||
<span>$Title</span>
|
||||
<% end_if %>
|
||||
</th>
|
||||
<% end_control %>
|
||||
|
@ -140,15 +140,15 @@ class ManifestBuilderTest extends SapphireTest {
|
||||
mkdir($testThemeBaseDir . $ds . 'darkshades_blog');
|
||||
|
||||
$this->assertEquals(array(
|
||||
'blackcandy',
|
||||
'darkshades'
|
||||
'blackcandy' => 'blackcandy',
|
||||
'darkshades' => 'darkshades'
|
||||
), ManifestBuilder::get_themes($testThemeBaseDir), 'Our test theme directory contains 2 themes');
|
||||
|
||||
$this->assertEquals(array(
|
||||
'blackcandy',
|
||||
'blackcandy_blog',
|
||||
'darkshades',
|
||||
'darkshades_blog'
|
||||
'blackcandy' => 'blackcandy',
|
||||
'blackcandy_blog' => 'blackcandy_blog',
|
||||
'darkshades' => 'darkshades',
|
||||
'darkshades_blog' => 'darkshades_blog'
|
||||
), ManifestBuilder::get_themes($testThemeBaseDir, true), 'Our test theme directory contains 2 themes and 2 sub-themes');
|
||||
|
||||
// Remove all the test themes we created
|
||||
|
@ -1,6 +1,30 @@
|
||||
<?php
|
||||
|
||||
class SSViewerTest extends SapphireTest {
|
||||
|
||||
/**
|
||||
* Tests for {@link SSViewer::current_theme()} for different behaviour
|
||||
* of user defined themes via {@link SiteConfig} and default theme
|
||||
* when no user themes are defined.
|
||||
*/
|
||||
function testCurrentTheme() {
|
||||
$config = SiteConfig::current_site_config();
|
||||
$oldTheme = $config->Theme;
|
||||
$config->Theme = '';
|
||||
$config->write();
|
||||
|
||||
SSViewer::set_theme('mytheme');
|
||||
$this->assertEquals('mytheme', SSViewer::current_theme(), 'Current theme is the default - user has not defined one');
|
||||
|
||||
$config->Theme = 'myusertheme';
|
||||
$config->write();
|
||||
$this->assertEquals('myusertheme', SSViewer::current_theme(), 'Current theme is a user defined one');
|
||||
|
||||
// Set the theme back to the original
|
||||
$config->Theme = $oldTheme;
|
||||
$config->write();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a template without a <head> tag still renders.
|
||||
*/
|
||||
|
@ -54,5 +54,26 @@ class SiteConfigTest extends SapphireTest {
|
||||
$this->assertTrue($pageEn->canEdit($translatorEn));
|
||||
}
|
||||
|
||||
function testAvailableThemes() {
|
||||
$config = SiteConfig::current_site_config();
|
||||
$ds = DIRECTORY_SEPARATOR;
|
||||
$testThemeBaseDir = TEMP_FOLDER . $ds . 'test-themes';
|
||||
|
||||
if(file_exists($testThemeBaseDir)) Filesystem::removeFolder($testThemeBaseDir);
|
||||
mkdir($testThemeBaseDir);
|
||||
mkdir($testThemeBaseDir . $ds . 'blackcandy');
|
||||
mkdir($testThemeBaseDir . $ds . 'blackcandy_blog');
|
||||
mkdir($testThemeBaseDir . $ds . 'darkshades');
|
||||
mkdir($testThemeBaseDir . $ds . 'darkshades_blog');
|
||||
|
||||
$themes = $config->getAvailableThemes($testThemeBaseDir);
|
||||
$this->assertContains('blackcandy', $themes, 'Test themes contain blackcandy theme');
|
||||
$this->assertContains('darkshades', $themes, 'Test themes contain darkshades theme');
|
||||
|
||||
SiteConfig::disable_theme('darkshades');
|
||||
$themes = $config->getAvailableThemes($testThemeBaseDir);
|
||||
$this->assertFalse(in_array('darkshades', $themes), 'Darkshades was disabled - it is no longer available');
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
Loading…
Reference in New Issue
Block a user