Reputation: 1113
As per the documentation of Silverstripe, template inheritance is defined as follows:
Now I've got a site that has quite a few different themes. Well, "different" in that they have different names, but they still got an awful lot in common. Now I am putting all the common files in the /mysite/templates folder, but that means that if one of my themes needs a change in one of the templates, I need to remove that file from the common folder, and move it to ALL the different theme folders. In this way I end up with a lot of duplicate templates.
In my case it would be beneficial to change the inheritance order, causing the specific theme folder to take precedence over the /mysite folder. In such a way I could just copy the template that has to be changed to the theme folder and that theme one will use the changed one, while the rest keeps using the generic one in the /mysite folder:
It also seems to me to be the more obviuous way to do it, but I probably am missing some important point here. Nonetheless, would doing this be possible without hacking the core?
Upvotes: 3
Views: 495
Reputation: 926
The question and the accepted answer are for SilverStripe 3, and should be referred to for queries relating to SilverStripe 3.x. The following refers to SilverStripe 4.
As SilverStripe 4 is currently the latest stable version and now sets theme inheritance instead of template inheritance, the question and answer may not be suitable for newer installations or up to date installations.
The best way to control inheritance in SilverStripe 4 is to ensure that the themes are configured in the correct order, and that the module inheritance is configured appropriately.
Your mysite/_config/theme.yml
file typically declares the theme inheritance, and you should adjust this file to control theme inheritance appropriately. For modules, you need to specify the appropriate Before
and After
in your mycustommodule/_config/modules.yml
file.
The following example is for a sile with both the mytheme and simple themes, a custom module without an _config/modules.yml
file, and a vendor module without an _config/modules.yml
file.
SilverStripe\View\SSViewer:
themes:
- 'mytheme'
- 'simple'
- '$default'
In this example, SSViewer::get_themes()
will return those three items as an array in the same order: ['mytheme', 'simple', '$default]
. When checking to see if a template exists, $default
will then be replaced by the paths of all modules which define templates, in the same order as they appear in the manifest.
<?php
use SilverStripe\View\ThemeResourceLoader;
$templatePaths = ThemeResourceLoader::inst()->getThemePaths(SSViewer::get_themes());
$templatePaths === [
'themes/mytheme',
'themes/simple',
'mycustommodule',
'vendor/silverstripe/asset-admin',
'vendor/silverstripe/campaign-admin',
'vendor/silverstripe/reports',
'vendor/silverstripe/siteconfig',
// Some vendor modules may appear here...
'vendor/othervendor/custommodule',
'vendor/silverstripe/cms',
'vendor/silverstripe/admin',
'vendor/silverstripe/assets',
'vendor/silverstripe/framework'
];
Upvotes: 2
Reputation: 4278
Template inheritance rendering seems to be managed by two classes predominantly, SSViewer
(a core class for handling view rendering) and Controller
(which all other controllers inherit from).
For view rendering, a SSViewer
object can take an array in its constructor for template inheritance. This is important because the Controller
class actually instantiates the SSViewer
in a function called getViewer
.
It is important to mention at this stage, a normal SilverStripe site you are normally inheriting from ContentController
instead which overrides the getViewer
of Controller
. It won't really change too much of what you need to write but it is important depending how low-level you want this to apply.
For what you want to apply to pages in general, you would be looking at overriding getViewer
in your Page_Controller
. As for what specifically you would need to write, that is somewhat dependent on your entire site structure. I would imagine it would need to start off a little like this though:
public function getViewer($action) {
$viewer = Parent::getViewer($action);
$templates = $viewer->templates();
//Do your processing that you need to here
//Set it back via:
//$viewer->setTemplateFile($type, $file);
//Alternatively, you can create a new SSViewer object
return $viewer;
}
It will be a bit of experimentation to work out what exactly you need to do for shuffling around the data though this was never going to be easy. Once you start heading down this path, you likely will find a number of edge cases where this may not work properly (eg. template includes).
Upvotes: 2