-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FIX Improving support for cascading themes
- Fixes an issue where themes would cascade "up" the list of themes - Provides configuration for defining custom theme options with their own sets of cascading themes Fixes #392
- Loading branch information
Showing
5 changed files
with
255 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
<?php | ||
|
||
namespace SilverStripe\Subsites\Service; | ||
|
||
use SilverStripe\Core\Config\Configurable; | ||
use SilverStripe\Core\Injector\Injectable; | ||
use SilverStripe\Subsites\Model\Subsite; | ||
use SilverStripe\View\SSViewer; | ||
|
||
class ThemeResolver | ||
{ | ||
use Injectable; | ||
use Configurable; | ||
|
||
/** | ||
* Cascading definitions for themes, keyed by the name they should appear under in the CMS. For example: | ||
* | ||
* [ | ||
* 'theme-1' => [ | ||
* '$public', | ||
* 'starter', | ||
* '$default', | ||
* ], | ||
* 'theme-2' => [ | ||
* 'custom', | ||
* 'watea', | ||
* 'starter', | ||
* '$public', | ||
* '$default', | ||
* ] | ||
* ] | ||
* | ||
* @config | ||
* @var null|array[] | ||
*/ | ||
private static $theme_options; | ||
|
||
/** | ||
* Get the list of themes for the given sub site that can be given to SSViewer::set_themes | ||
* | ||
* @param Subsite $site | ||
* @return array | ||
*/ | ||
public function getThemeList(Subsite $site) | ||
{ | ||
$themes = array_values(SSViewer::get_themes()); | ||
$siteTheme = $site->Theme; | ||
|
||
if (!$siteTheme) { | ||
return $themes; | ||
} | ||
|
||
$customOptions = $this->config()->get('theme_options'); | ||
if ($customOptions && isset($customOptions[$siteTheme])) { | ||
return $customOptions[$siteTheme]; | ||
} | ||
|
||
// Ensure themes don't cascade "up" the list | ||
$index = array_search($siteTheme, $themes); | ||
|
||
if ($index > 0) { | ||
// Check if the default is public themes | ||
$publicDefault = $themes[0] === SSViewer::PUBLIC_THEME; | ||
|
||
// Take only those that appear after theme chosen (non-inclusive) | ||
$themes = array_slice($themes, $index + 1); | ||
|
||
// Add back in public | ||
if ($publicDefault) { | ||
array_unshift($themes, SSViewer::PUBLIC_THEME); | ||
} | ||
} | ||
|
||
// Add our theme | ||
array_unshift($themes, $siteTheme); | ||
|
||
return $themes; | ||
} | ||
|
||
/** | ||
* Get a list of custom cascading theme definitions if available | ||
* | ||
* @return null|array | ||
*/ | ||
public function getCustomThemeOptions() | ||
{ | ||
$config = $this->config()->get('theme_options'); | ||
|
||
if (!$config) { | ||
return null; | ||
} | ||
|
||
return array_keys($config); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
<?php | ||
|
||
namespace SilverStripe\Subsites\Tests\Service; | ||
|
||
use SilverStripe\Core\Config\Config; | ||
use SilverStripe\Dev\SapphireTest; | ||
use SilverStripe\Subsites\Model\Subsite; | ||
use SilverStripe\Subsites\Service\ThemeResolver; | ||
use SilverStripe\View\SSViewer; | ||
|
||
class ThemeResolverTest extends SapphireTest | ||
{ | ||
protected $themeList = [ | ||
SSViewer::PUBLIC_THEME, | ||
'custom', | ||
'main', | ||
'backup', | ||
SSViewer::DEFAULT_THEME, | ||
]; | ||
|
||
protected function setUp() | ||
{ | ||
parent::setUp(); | ||
|
||
// Setup known theme config | ||
Config::modify()->set(SSViewer::class, 'themes', $this->themeList); | ||
} | ||
|
||
public function testSubsiteWithoutThemeReturnsDefaultThemeList() | ||
{ | ||
$subsite = new Subsite(); | ||
$resolver = new ThemeResolver(); | ||
|
||
$this->assertSame($this->themeList, $resolver->getThemeList($subsite)); | ||
} | ||
|
||
public function testSubsiteWithCustomThemePrependsToList() | ||
{ | ||
$subsite = new Subsite(); | ||
$subsite->Theme = 'subsite'; | ||
|
||
$resolver = new ThemeResolver(); | ||
|
||
$expected = array_merge(['subsite'], $this->themeList); | ||
|
||
$this->assertSame($expected, $resolver->getThemeList($subsite)); | ||
} | ||
|
||
public function testSubsiteWithCustomThemeDoesNotCascadeUpTheList() | ||
{ | ||
$subsite = new Subsite(); | ||
$subsite->Theme = 'main'; | ||
|
||
$resolver = new ThemeResolver(); | ||
|
||
$expected = [ | ||
'main', // 'main' is moved to the top | ||
SSViewer::PUBLIC_THEME, // $public is preserved | ||
// Anything above 'main' is removed | ||
'backup', | ||
SSViewer::DEFAULT_THEME, | ||
]; | ||
|
||
$this->assertSame($expected, $resolver->getThemeList($subsite)); | ||
} | ||
|
||
/** | ||
* @dataProvider customThemeDefinitionsAreRespectedProvider | ||
*/ | ||
public function testCustomThemeDefinitionsAreRespected($themeOptions, $siteTheme, $expected) | ||
{ | ||
Config::modify()->set(ThemeResolver::class, 'theme_options', $themeOptions); | ||
|
||
$subsite = new Subsite(); | ||
$subsite->Theme = $siteTheme; | ||
|
||
$resolver = new ThemeResolver(); | ||
|
||
$this->assertSame($expected, $resolver->getThemeList($subsite)); | ||
} | ||
|
||
public function customThemeDefinitionsAreRespectedProvider() | ||
{ | ||
return [ | ||
// Simple | ||
[ | ||
['test' => $expected = [ | ||
'subsite', | ||
'backup', | ||
SSViewer::PUBLIC_THEME, | ||
SSViewer::DEFAULT_THEME, | ||
]], | ||
'test', | ||
$expected | ||
], | ||
// Many options | ||
[ | ||
[ | ||
'aye' => [ | ||
'aye', | ||
'thing', | ||
SSViewer::DEFAULT_THEME, | ||
], | ||
'bee' => $expected = [ | ||
'subsite', | ||
'backup', | ||
SSViewer::PUBLIC_THEME, | ||
SSViewer::DEFAULT_THEME, | ||
], | ||
'sea' => [ | ||
'mer', | ||
'ocean', | ||
SSViewer::DEFAULT_THEME, | ||
], | ||
], | ||
'bee', | ||
$expected | ||
], | ||
// Conflicting with root definitions | ||
[ | ||
['main' => $expected = [ | ||
'subsite', | ||
'backup', | ||
SSViewer::PUBLIC_THEME, | ||
SSViewer::DEFAULT_THEME, | ||
]], | ||
'main', | ||
$expected | ||
], | ||
// Declaring a theme specifically should still work | ||
[ | ||
['test' => [ | ||
'subsite', | ||
'backup', | ||
SSViewer::PUBLIC_THEME, | ||
SSViewer::DEFAULT_THEME, | ||
]], | ||
'other', | ||
array_merge(['other'], $this->themeList) | ||
], | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters