We are working on a Silverstripe project that uses the Elemental Module to layout content.
The project also uses the Blog Module with the blog being used for two sections of the website - the work portfolio & a standard blog.
The challenge is: we want different content behaviour for each blog/section:
Portfolio - Element Blocks
Blog - standard blog/page behaviour
What is the best way to achieve this?
Should we extend Blog & BlogPost to new objects Portfolio & PortfolioItem to separate out the two different behaviours?
Or can we just add the following to the Blog Object/Controller:
if ($this->BlogType == 'portfolio'){
// enable Elemental
} else {
// disable Elemental
}
And finally, how do we disable Elemental on specific Pages? It isn't obvious in the documentation.
This was our solution - using the includeElemental method to disable/ enable Elemental on a case by case basis.
class BlogPostExtension extends DataExtension
{
public function updateCMSFields(FieldList $fields){
$fields->insertBefore(new
DropdownField("LayoutIndex", "Layout", ["Portfolio", "Blog"]), "Title");
}
public function includeElemental(){
if ($this->owner->LayoutIndex == 0) {
return true;
} else if ($this->owner->LayoutIndex == 1) {
return false;
}
}
}
Related
Is there any way to add/change allowed template of page children ? When I create child for specific page I would like to set template to use. I have that option when I use Processwire CMS:
Select the template(s) that will be allowed for children of pages using this template. Use this only if you specifically want to restrict placement of pages using this template. If none are selected then any are allowed, within the user's access limits. An example usage could be a 'news-list' template that is only allowed to have children using 'news-item' or 'press-release' templates.
I have come across this issue before and I have used a custom function to determine what level a page is at and then include a file based on that using:
get_post_ancestors();
The function (added to functions.php)
function hierarchy_level($post){
if(count(get_post_ancestors($post)) === 0){
return 'parent';
}elseif(count(get_post_ancestors($post)) === 1){
return 'child';
}
elseif(count(get_post_ancestors($post)) === 2){
return 'grandchild';
}else{
return false;
}
}
And usage in a page template:
$page_level = hierarchy_level($post);
switch ($page_level){
case 'parent':
include('template-parts/parent.php');
break;
case 'child':
include('template-parts/child.php');
break;
case 'grandchild':
include('template-parts/grandchild.php');
break;
}
I want to set different color on the dashboard of each site (in my multisite). For example the first site is based on the user's preference, but the second one always use Midnight theme.
Is there a way to set this in functions.php?
Thanks
Just found it on other's question. Put this on functions.php.
add_filter('get_user_option_admin_color', 'change_admin_color');
function change_admin_color($result) {
if(get_current_blog_id() === 2) {
return 'midnight';
}
else {
return $result;
}
}
I need a simple way to fallback on a default template if no mobile version exists.
With some regular expressions I recognize mobile platforms and want to render a template with the following pattern:
<template_name>.mobile.html.twig
But if this template doesn't exist, I want it to automatically fallback on:
<template_name>.html.twig
which always exists.
I tried nearly all the answers from this post:
Symfony 2 load different template depending on user agent properties
but with no success. Unfortunately there are no version numbers referenced.
At the moment I am trying to copy and modify the default twig loader.
By the way, What I want to achieve with this is the possibility to deploy different templates for mobile devices by just adding a template of the same name and adding a .mobile.
UPDATE:
http://www.99bugs.com/handling-mobile-template-switching-in-symfony2/
This one is also a good approach. It modifies the format property of the request object which affects the automatic template guessing when you don't specify a template in the controller with the render function (or annotation) but just return an array.
Resulting template name:
view/<controller>/<action>.<request format>.<engine>
So you could switch the request format from html to mobile.html based on the device detection.
The downside of this is that every template needs a mobile.html pendant (which then could just include the non-mobile version if not needed).
UPDATE:
Besides using a custom templating provider there is also the possibility to hook into the kernel.view event.
You could create a service to handle it and then use it in the same way that you do the templating service like so..
Create a service with the templating and request service injected into it..
Service (YAML)
acme.templating:
class: Acme\AcmeBundle\Templating\TemplatingProvider
scope: request
arguments:
- #templating
- #request // I assume you use request in your platform decision logic,
// otherwise you don't needs this or the scope part
- 'html'
Class
class TemplatingProvider
{
private $fallback;
private $platform;
... __construct($templating, $request, $fallback) etc
private function setPlatform() ... Your platform decision logic
private function getPlatform()
{
if (null === $this->platform) {
$this->setPlatform();
}
return $this->platform;
}
private function getTemplateName($name, $platform)
{
if ($platform === 'html') {
return $name;
}
$template = explode('.', $name);
$template = array_merge(
array_slice($template, 0, -2),
array($platform),
array_slice($template, -2)
);
return implode('.', $template);
}
public function renderResponse($name, array $parameters = array())
{
$newname = $this->getTemplateName($name, $this->getPlatform());
if ($this->templating->exists($newname)) {
return $this->templating->render($newname);
}
return $this->templating->renderResponse($this->getTemplateName(
$name, $this->fallback));
}
And then you could just call your templating service instead of the current one..
return $this->container->get('acme.templating')
->renderResponse('<template_name>.html.twig', array());
Can't you check if the template exist before ?
if ( $this->get('templating')->exists('<templatename>.html.twig') ) {
// return this->render(yourtemplate)
} else {
// return your default template
}
OR :
You can create a generic method, to insert in your root controller like :
public function renderMobile($templateName, $params)
{
$templateShortName = explode('.html.twig', $templateName)[0];
$mobileName = $templateShortName.'.mobile.html.twig';
if ( $this->get('templating')->exists($mobileName) ) {
return $this->renderView($mobileName, $params);
} else {
return $this->renderView($templateName, $params)
}
}
with this you can do :
return $this->renderMobile('yourtemplate', [yourparams]);
You can easily do this by harnessing the bundle inheritance properties in Symfony2 http://symfony.com/doc/current/cookbook/bundles/inheritance.html
create a bundle which holds your desktop templates (AcmeDemoDesktopBundle)
create a bundle which will hold your mobile templates (AcmeDemoMobileBundle) and mark the parent as AcmeDemoDesktopBundle
Then when you render a template simply call AcmeDemoMobileBundle:: - if the template exists, it'll be rendered otherwise you'll neatly fall back to the desktop version. No extra code, listeners or anything none-obvious required.
The downside of this of course is that you move your templates out of the individual bundles.
The fallback behavior you describe isn't that easy to implement (we found out the hard way..). Good news is we wanted the same setup as you ask for and ended up using the LiipThemeBundle for this purpose. It allows you to have different "themes" based on for example a device. It will do the fallback part for you.
For example:
Rendering a template:
#BundleName/Resources/template.html.twig
Will render and fallback to in order:
app/Resources/themes/phone/BundleName/template.html.twig
app/Resources/BundleName/views/template.html.twig
src/BundleName/Resources/themes/phone/template.html.twig
src/BundleName/Resources/views/template.html.twig
Edit: so with this approach you can have default templates that will always be the final fallback and have a special template for mobile where you need it.
I need to create a template for a view i've created (which I know how to do) but I don't want the page to be wrapped in the drupal html.php code. I want the resulting page to be only what is in the template file I create.
How do I do this?
I did found this which does what I need for content types lab
function yourthemename_preprocess_html(&$vars) {
if ($node = menu_get_object()) {
if($node->type == "lab") {
$vars['theme_hook_suggestions'][] = 'html__lab';
}
}
}
Then created a file called: html--lab.tpl.php
Can this method be used for my view?
does it have to be if($node->type == "lab")?
can I use something like if($view == "viewname")
Thanks
C
I think when you says "created a view" you mean a view + a page display.
So, when you browse to http://mystite.com/mypage, it will show the content of view.
In this case, you can use your code with some small modifications.
function yourthemename_preprocess_html(&$vars) {
if (arg(0) == 'mypage') {
$vars['theme_hook_suggestions'][] = 'html__mypage';
}
}
You will have to create the right .tpl.php file and clear the cache.
I am working on a module where i have a page that must have no regions or extra content. A kind of "please wait" page.
How do i diable all extra content (regions menus...etc) ? i think Panels has this ability but i can't find the snippet it uses.
On another hand is it possible for a module to specify a special custom page ? like the maintenance-page for example ?
The page.tpl.php method is not flexible. It is based on a presentation logic. You should use hook_page_alter() for a business logic solution. For example:
function yourmodulename_page_alter(&$page) {
if (current_path() == 'node/add/yourcontenttype') {
unset($page['sidebar_first']);
}
}
Also look at very powefull Context module.
You can create a an extra page.tpl.php specifically for the page where you want to hide the regions. The naming principle is similar to the one for nodes.
Let's say you have a page with the url example.com/content/contact. A template named page--content--contact.tpl.php would serve that page and any page that starts with that url, i.e. the page example.com/content/contact/staff would also use that template (I think).
Check the classes of the body element for clues to what you can name your template, most themes will print that. In my example above, the body element would include the class page-content-contact.
Only thing i can think of is writing checks in your page.tpl.php file to see if you on that "page" your talking about and not printing out the regions/menus, or use a different template. http://drupal.org/node/223440
If you want to do this before the blocks are rendered:
/**
* Implements hook_block_list_alter()
*
* Hides the right sidebar on some pages.
*/
function THEME_NAME_block_list_alter(&$blocks) {
// This condition could be more interesting.
if (current_path() !== 'node/add/yourcontenttype') {
return;
}
// Go through all blocks, and hide those in the 'sidebar_second' region.
foreach ($blocks as $i => $block) {
if ('sidebar_second' === $block->region) {
// Hide this block.
unset($blocks[$i]);
}
}
}
Note: Interestingly, this hook seems to work no matter if you have it in your theme or in a module.
(Please correct me if I'm wrong)