Alimozzaman

Archive for the ‘Liferay’ Category

I am assuming that you have your Liferay maven based development environment is ready. If not, I would recommend to read out this simple-way-to-setup-liferay-environment-through-maven. This is pretty straight forward and lovely pitch of guideline.

So now you have your environment ready and the directory structure looks like the following image. Yes, we can now start developing a sample hook to achieve some functionalities.

Figure: Liferay Maven based development directory structure.

Project Environment:

  • Linux
  • Liferay 6.x+
  • Maven 2

Create Hook

  • Lets goto your hook directory from command prompt (i.e. cd /home/workspace/example/liferay/src/hook )
  • Type command mvn archetype:generate
  • A list of archetype will come up. Find liferay-hook-archetype from the list and check the number for the same archetype. You will get something like below but number could be changed based on the version.

21: remote -> com.liferay.maven.archetypes:liferay-ext-archetype (Provides an archetype to create Liferay extensions.)

22: remote -> com.liferay.maven.archetypes:liferay-hook-archetype (Provides an archetype to create Liferay hooks.)

23: remote -> com.liferay.maven.archetypes:liferay-layouttpl-archetype (Provides an archetype to create Liferay layout templates.)

24: remote -> com.liferay.maven.archetypes:liferay-portlet-archetype (Provides an archetype to create Liferay portlets.)

In next step, you need to select Liferay Version. So select version accordingly (i.e. 6.1.0)

  • Next, define proper groupId (i.e. com.example.liferay)
  • Define proper artifactId (i.e. samplehook)
  • Specify version (i.e. 1.0-SNAPSHOT)
  • Package(i.e. com.example.liferay)
  • Confirm all the values and hit ‘Y’ for confirmation

Yahooooooooo , Your are done !!! Your Hook is created. Now you know how to create a hook in a minute, great (y)

Before deploying your package, just confirm your Portal deploy path into your auto generated pom.xml inside your sample hook ( /home/workspace/example/liferay/src/hook/sample-hook/pom.xml )

Open the pom.xml in a text editor and find the

…………..

<properties>

<liferay.auto.deploy.dir>/home/workspace/example/liferay/bundle/deploy</liferay.auto.deploy.dir>

<liferay.version>6.1.0</liferay.version>

</properties>

</project

…………….

Package and Deploy

Go to sample-hook directory and run

mvn clean package

To deploy the hook into your Liferay bundle you can run

mvn clean install liferay:deploy

Well done, you have created your sample hook with maven and deployed it to your Liferay bundle.

Are you thinking, What is Liferay hook system?

I am not gonna explain using lot of words because some guys already explained it very nicely. You can read this article to get the idea of Liferay Hook Plugin, here you go http://www.liferay.com/community/wiki/-/wiki/Main/Portal+Hook+Plugins

But then again, let me give a brief in one or two lines.

In brief, using hook plugin, we can change liferay JSP, Portal Properties, Event, Services, defining your own Model listener, overriding/adding struts actions etc.

Now I am going to show you how and where we can change those functionalities.

Overridding a JSP

Now you want to change any look and feel of an existing portlet of Liferay. For example – I want to change a jsp file of the Blog Portlet.

Okay, lets point to <sample-hook>/src/main/webapp/WEB-INF/liferay-hook.xml and open that file in an editor and the add <custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

So it will look like the following.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

</hook>

Now copy any blog portlet jsp file, for example – I want to override edit_entry.jsp, and put that into

<sample-hook>/src/main/webapp/META-INF/custom_jsps/html/portlet/blogs

Change anything your want into that file and deploy the hook. You would see that the default look and feel got changed if u change anything there. You are done with JSP overriding.

Note : If you want to know what Liferay did with the original file, then goto your <liferay-bundle>/webapp/ROOT/WEB-INF/html/portlet/blogs/ and u can find that the original file renamed edit_entry.portal.jsp

Portal Properties

Well, if you want to override any portal property value, you need to add

<portal-properties>portal.properties</portal-properties> into your liferay-hook.xml like the following.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

</hook>

Now create a portal.properties into your <sample-hook>src/main/resources and change the value. For example – by default terms.of.use.required=true into liferay. You can put that into your hook portal.properties and change it to false.

#

# Set this to true if all users are required to agree to the terms of use.

#

terms.of.use.required=false

Deploy the hook and check the term’s page. You might need to restart the tomcat if u dont see its not effecting.

Event

Liferay has a few event handler connection points throughout its lifecycle.

The available events are:

  • Application Startup Events (application.startup.events)
  • Login Events (login.events.pre, login.events.post)
  • Service Events (servlet.service.events.pre, servlet.service.events.post)

Now I want to override any event with my custom implementation, for example – application.startup.events, where I want to change some default behavior. So I can put that property into <sample-hook>src/main/resources/portal.properties and override the default value.

Example : In liferay source, the default value of application.startup.events property is

application.startup.events=com.liferay.portal.events.AppStartupAction

I can change that to custom one like the following into portal.properties

application.startup.events=com.liferay.samplehook.events.StartupAction

package com.liferay.samplehook.actions;

import com.liferay.portal.kernel.dao.orm.QueryUtil;

import com.liferay.portal.kernel.events.ActionException;

import java.io.InputStream;

import java.util.*;

/**

* Action called on startup, used to create initial data.

*

* @author Rony

*

*/

public class StartupAction extends SimpleAction {

public void run(String[] ids) throws ActionException {

try {

doRun(GetterUtil.getLong(ids[0]));

} catch (Exception e) {

throw new ActionException(e);

}

}

// Do your custom coding here.

}

Do your customization in AppStartupAction, deploy it and restart the tomcat.

Or you can also define override event using liferay-hook.xml like the following

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

<event>

     <event-class>com.liferay.samplehook.ServicePreAction</event-class>
     <event-type>servlet.service.events.pre</event-type>
  </event>

</hook>

Now you know two ways/process to override liferay events.

Done!

Overriding a Portal Service

Liferay provide dummy wrapper classes for all of its services, for example BlogsEntryLocalServiceWrapper is created as a wrapper of the BlogsEntryLocalService that is used to add, remove and retrieve blog entry. To modify the functionality of BlogsEntryLocalService from our hook, all we have to do is create a class that extends from BlogsEntryLocalServiceWrapper, override some of its methods or what ever you want, then we have to configure so that Liferay pick this extension instead of default wrapper class.

Sample code//

package com.liferay.samplehook.service;

import com.liferay.portal.kernel.exception.PortalException;

import com.liferay.portal.kernel.exception.SystemException;

public class CustomBlogsEntryLocalServiceImpl extends CustomBlogsEntryLocalServiceWrapper{

//Add custom coding

}

Next, lets ask Liferay to pick this class instead of the default one. Edit your liferay-hook.xml and add the <service> tags like the follow. Deploy the hook and restart the tomcat and check the effect.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

<event>

<event-class>com.liferay.samplehook.ServicePreAction</event-class>
<event-type>servlet.service.events.pre</event-type>

  </event>

  <service>

<service-type>com.liferay.portal.service.BlogsEntryLocalService </service-type>

<service-impl>com.liferay.samplehook.service. CustomBlogsEntryLocalServiceImpl </service-impl>

  </service>

</hook>

We are done and we can follow this technique to override other Liferay services.

Model Listeners

  1. Overriding default Model Listener: In Liferay, we have some model listeners and we need to override them for sometimes. In hook portal.properties, we can define our own class to override them.

Lets take LayoutSetListener as an example and we want to set our own theme for all community layouts.

In Liferay portal.properties, we have a Listener class like this: value.object.listener.com.liferay.portal.model.LayoutSet=com.liferay.portal.model.LayoutSetListener

Now lets define our own class into Hook portal.properties to customize the layout like this:

value.object.listener.com.liferay.portal.model.LayoutSet= com.liferay.samplehook .modellisteners.LayoutSetListener

Example code to add custom theme for all group layouts by default instead of default Classic theme.

public class LayoutSetListener extends BaseModelListener<LayoutSet> {

public void onAfterCreate(LayoutSet layoutSet) throws ModelListenerException {

try {

Group group = GroupLocalServiceUtil.getGroup(layoutSet.getGroupId());

if (group.isCommunity()) {

addCommunityLayouts(group);

}

} catch (Exception e) {

throw new ModelListenerException(e);

}

}

protected void addCommunityLayouts(Group group) throws Exception {

// Look and Feel

updateLookAndFeel(group);

}

private void updateLookAndFeel(Group group) throws Exception {

LayoutSetLocalServiceUtil.updateLookAndFeel(group.getGroupId(), “sample_WAR_sampletheme”, “”, “”, false);

}

}

We are done adding our own theme overriding LayoutSet model.

  1. Add custom Model Listener: If we want to add our own Model Listener, we can also easily achieve that using hook system.

Lets say we want to add a blog post Listener, we can inform liferay to pickup our custom model by adding a <model-listener> tag into the hook liferay-hook.xml file. So your liferay-hook.xml will look like this.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

<event>

 <event-class>com.liferay.samplehook.ServicePreAction</event-class>
 <event-type>servlet.service.events.pre</event-type>
</event>

    <service>

<service-type>com.liferay.portal.service.BlogsEntryLocalService </service-type>

<service-impl>com.liferay.samplehook.service. CustomBlogsEntryLocalServiceImpl </service-impl>

  </service>

   <model-listener>
    <model-listener-class>com.liferay.samplehook .modellisteners.MyBlogEntryListener
    </model-listener-class>
     <model-name>com.liferay.portlet.blogs.model.BlogsEntry</model- name>
  </model-listener>
</hook>

public class MyBlogEntryListener implements ModelListener {
  //Custom code here.
}
You can also Look into the post for detail at
 http://www.liferay.com/community/wiki/-/wiki/Main/Portal+Hook+Plugins

We are done!

Overriding/Adding struts actions

We can also override and add new Struts-actions from Hook System. Edit your liferay-hook.xml and add the following lines.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

<event>

  <event-class>com.liferay.samplehook.ServicePreAction</event-class>
  <event-type>servlet.service.events.pre</event-type>
 </event>

    <service>

<service-type>com.liferay.portal.service.BlogsEntryLocalService </service-type>

<service-impl>com.liferay.samplehook.service. CustomBlogsEntryLocalServiceImpl </service-impl>

  </service>

  <model-listener>
    <model-listener-class>com.liferay.samplehook .modellisteners.MyBlogEntryListener
    </model-listener-class>
     <model-name>com.liferay.portlet.blogs.model.BlogsEntry</model- name>
  </model-listener>

   <struts-action>
    <struts-action-path>/portal/sample</struts-action-path>
    <struts-action-impl>com.liferay.samplehook.action.SampleStrutsAction</struts-action-impl> 
</struts-action>
</hook>
This has been explained in detail at http://www.liferay.com/web/mika.koivisto/blog/-/blogs/7132115

Language Bundles

We can also add new language package or override existing translation from the hook like the following way.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

<language-properties>content/Language_en.properties</language-properties>

<language-properties>content/Language_nl.properties</language-properties>

<language-properties>content/Language_fi.properties</language-properties>

<event>

  <event-class>com.liferay.samplehook.ServicePreAction</event-class>
  <event-type>servlet.service.events.pre</event-type>
 </event>

    <service>

<service-type>com.liferay.portal.service.BlogsEntryLocalService </service-type>

<service-impl>com.liferay.samplehook.service. CustomBlogsEntryLocalServiceImpl </service-impl>

  </service>

   <model-listener>
    <model-listener-class>com.liferay.samplehook .modellisteners.MyBlogEntryListener
    </model-listener-class>
    <model-name>com.liferay.portlet.blogs.model.BlogsEntry</model- name>
  </model-listener>

   <struts-action>
    <struts-action-path>/portal/sample</struts-action-path>
    <struts-action-impl>com.liferay.samplehook.action.SampleStrutsAction</struts-action-impl> 
</struts-action>
</hook>

Great,now we know how to develop a hook using Maven what we can achieve
from Liferay Hook system at a glance.


Please make your comments or add suggestion to make this much better understanding for the community.
Tags: ,

Struts2 liferay 6.0.5+ all  User list and & Users detail portlet. This is very useful for any site where people can see all users and there detail. Its also good for the developers to have maven based struts2 development sample.Please give your feedback.

Please have a look at the userList portlet

I have contributed a nice looking Liferay 6.0.5+ theme, Lotus theme. I wish it will little help to the community. Also planning to contribute more.

 

Thanks

 

This is a very trivial but then again I want to share as I wasted some time to find this way to add a localization in my theme.

Step#1:  Set a  key in a variable into your init_custom.vm

#set ($a = $languageUtil.get($locale, “my-picture”))

step#2: Use the variable into your *.vm files

<span>$a</span>

step#3:  Add the corresponding value of the key  “my-picture” into your language file.

Ex- my-picture= <localized text>

Here you go… Very simple!

 

Multiple themes  selection

We can select the whole site theme from any navagation of our site which will be different user to user. Say , you  select your own theme that would be different than other users in a multi user site where user register to use the site. I hope this will help selecting theme from UI level in very convenient way.

1. Define a structs path in which you will be adding your Action class.

For example – I made a path using an existing portlet.

<action path=”/my_places/themes” type=”com.example.actions.themes.ThemeSwitchAction”>             <forward name=”portlet.my_places.view” path=”portlet.my_places.view” />

</action>

 

2. Now generate the url into your VM file, in my case I did add in dock.vm file like the following way.

#set ($my_places_url1 = $portletURLFactory.create($request, “49”, $page.getPlid(), “ACTION_PHASE”))

$my_places_url1.setWindowState(“normal”)

$my_places_url1.setPortletMode(“view”)

$my_places_url1.setParameter(“struts_action”, “/my_places/themes”)

// Set the theme ID

$my_places_url1.setParameter(“themeId”, “classic”)

<span>

<li>   <a  class = “theme-update-link” href=”#” onclick=”updateTheme(‘$my_places_url1.toString()’,this)” ><img src=”$images_folder/icon/stp-oranssi.png” alt=”Oranssi” /></a>

</li>

// set the second theme ID

$my_places_url1.setParameter(“themeId”, “classic_green “)

 

 

 

<li>

<a  class = “theme-update-link” href=”#” onclick=”updateTheme(‘$my_places_url1.toString()’,this)” ><img src=”$images_folder/icon/stp-red.png” alt=”Stp” /> </a>

</li>

//Set  the third theme ID

$my_places_url1.setParameter(“themeId”, “custom_theme_ID”)

<li>

<a  class = “theme-update-link” href=”#” onclick=”updateTheme(‘$my_places_url1.toString()’,this)” > <img src=”$images_folder/icon/stp-green.png” alt=”Classic” /> </a>

</li>

</span>

//Add the following Javascript to post your data.

<script type=”text/javascript”>

function updateTheme(url,obj){

var targetURL = url;

jQuery.post(targetURL, {ajax: ‘true’ },

function(){

location.reload();

});

}

</script>

 

 

 

 

3. Now you add the following lines in your Action class.

 

public void processAction(ActionMapping mapping, ActionForm form,

PortletConfig portletConfig, ActionRequest actionRequest,

ActionResponse actionResponse) throws Exception {

 

_log.info(ThemeSwitchAction.class.getName() + ”  WORKED”);

 

ThemeDisplay themeDisplay = (ThemeDisplay) actionRequest

.getAttribute(WebKeys.THEME_DISPLAY);

 

String themeId = ParamUtil.getString(actionRequest, “themeId”);

 

Group group = GroupLocalServiceUtil.getGroup(themeDisplay.getLayout()

.getGroupId());

 

// Setting group theme.

LayoutSetLocalServiceUtil.updateLookAndFeel(group.getGroupId(),

themeId, “01”, “”, false);

 

// Setting user home page theme.

LayoutSetLocalServiceUtil.updateLookAndFeel(themeDisplay.getUser()

.getGroup().getGroupId(), themeId, “01”, “”, false);

 

_log.info(ThemeSwitchAction.class.getName()

+ ”  set the theme for you.”);

 

 

 

}

4. To make sure your themeID is update every where , you can add this method into service preaction in your hook

 

protected void updateGroupThemes(HttpServletRequest request,

HttpServletResponse response)  {

try {

ThemeDisplay themeDisplay = (ThemeDisplay) request

.getAttribute(WebKeys.THEME_DISPLAY);

LayoutSet userHomeLayout = LayoutSetLocalServiceUtil.getLayoutSet(

themeDisplay.getUser().getGroup().getGroupId(), false);

String themeId = userHomeLayout.getThemeId();

LayoutSet updatedLayout = LayoutSetLocalServiceUtil.updateLookAndFeel(themeDisplay.getLayout().getGroupId(), false, themeId, “01”, “”, false);

 

LayoutSetLocalServiceUtil.updateLayoutSet(updatedLayout);

 

 

 

} catch (Exception e) {

//

}

}

 

5. Also you can add the follwoing lines into your community update method if u need to update your community layout theme on run time.

ThemeDisplay themeDisplay = (ThemeDisplay) request

.getAttribute(WebKeys.THEME_DISPLAY);

LayoutSet userHomeLayout = LayoutSetLocalServiceUtil.getLayoutSet(

themeDisplay.getUser().getGroup().getGroupId(), false);

String themeId = userHomeLayout.getThemeId();

LayoutSet updatedLayout = LayoutSetLocalServiceUtil.updateLookAndFeel(themeDisplay.getLayout().getGroupId(), false, themeId, “01”, “”, false);

 

LayoutSetLocalServiceUtil.updateLayoutSet(updatedLayout);

 

 

Enjoying making default theme according to user!!!

Drop me an email if u need further help  and also make valuable comment to make it much more clear!!

 

 

 

We can add any child page of any community from admin panel in the following way. See the picture. But we can do the same thing programmatically.

Here is the way to add a child page:

1.  Overwrite your EditGroupAction.java page into EXT.

2. Add the following lines  into updateGroup function.

Group group = GroupServiceUtil.addGroup(
name, description, type, friendlyURL, active, serviceContext);

after this line add ……..

boolean privateLayout = false;
long parentLayoutId = 0;
String childpageName = “childPage”;
String titleChild = “childPage”;
String descriptionChild = “childPage”;
String type = LayoutConstants.TYPE_PORTLET;
boolean hidden = false;
String friendlyURL = “/childPage”;

Layout layout = LayoutLocalServiceUtil.addLayout(userId,
group.getGroupId(),
privateLayout,
parentLayoutId,
childpageName,
titleChild,
descriptionChild,
type,
hidden,
friendlyURL);

/****You can add custom template and also u can add portlet  to it******/

LayoutTypePortlet layoutTypePortlet = (LayoutTypePortlet) layout.getLayoutType();

layoutTypePortlet.setLayoutTemplateId(0, “layouttpl-id”, false);
layoutTypePortlet.addPortletId(0, “20”, “column-1”, -1,false);
LayoutLocalServiceUtil.updateLayout(layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(), layout.getTypeSettings());

//Then you can update the permission

updatePermissions(layout,true);

/*********End up the coding************/

//Here is the update permission method

public void updatePermissions(Layout layout, boolean addDefaultActionIds)
throws Exception {

long companyId = layout.getCompanyId();

Role role = RoleLocalServiceUtil
.getRole(companyId, RoleConstants.GUEST);

String[] actionIds = new String[0];

String name = Layout.class.getName();
int scope = ResourceConstants.SCOPE_INDIVIDUAL;
String primKey = String.valueOf(layout.getPrimaryKey());

Resource resource = ResourceLocalServiceUtil.getResource(companyId,
name, scope, primKey);

if (addDefaultActionIds) {
actionIds = new String[] { ActionKeys.VIEW };
}

PermissionLocalServiceUtil.setRolePermissions(role.getRoleId(),
actionIds, resource.getResourceId());

PermissionLocalServiceUtil.setRolePermissions(RoleLocalServiceUtil.getRole(companyId,
RoleConstants.POWER_USER).getRoleId(),
actionIds, resource.getResourceId());

PermissionLocalServiceUtil.setRolePermissions(RoleLocalServiceUtil.getRole(companyId,
RoleConstants.COMMUNITY_MEMBER).getRoleId(),
actionIds, resource.getResourceId());
}

3.  You can check the child page like http://localhost:8080/web/<community-name>/childPage or from admin panel.

Enjoy!!

Make comment to make this more helpful  to the community.

 

These are the  default Liferay 6 theme variables defined in init.vm.  I was searching but did not get any link ,so I hope this will help lot of people also around  the globe. If anything goes  wrong, pls make a comment and also try to add something that will help people around us.

 

## ———- Common variables ———- ##

$theme_display
$portlet_display
$theme_timestamp
$theme_settings
$css_class
$layout
$page_group
$liferay_toggle_controls
$liferay_dockbar_pinned
$css_folder
$images_folder
$javascript_folder
$templates_folder
$full_css_path
$full_templates_path
$css_main_file
$js_main_file
$company_id
$company_name
$company_logo
$company_logo_height
$company_logo_width
$company_url

$user_id
$is_default_user
$user_first_name
$user_middle_name
$user_last_name
$user_name
$is_male
$is_female
$user_birthday
$user_email_address
$language_id
$w3c_language_id
$time_zone
$user_greeting
$user_comments
$user_login_ip
$user_last_login_ip
$is_signed_in
$group_id

## ———- URLs ———- ##
$show_add_content
$add_content_text
$add_content_url
$layout_text
$layout_url
$show_control_panel
$control_panel_text
$control_panel_url
$show_home
$home_text
$home_url
$show_my_account
$my_account_text
$my_account_url
$show_page_settings
$page_settings_text
$page_settings_url
$show_sign_in
$sign_in_text
$sign_in_url
$show_sign_out
$sign_out_text
$sign_out_url
$show_toggle_controls
$toggle_controls_text
$toggle_controls_url
$update_available_url

## ———- Page ———- ##

$the_title
$selectable
$is_maximized
$is_freeform

$page_javascript_1
$page_javascript_2
$page_javascript_3
$layout
$page = $layout
$is_first_child
$is_first_parent
$the_title
$is_portlet_page

$all_portlets
$column_1_portlets
$column_2_portlets
$column_3_portlets
$column_4_portlets
$column_5_portlets
$maximized_portlet_id
$typeSettingsProperties
$page_javascript_1
$page_javascript_2
$page_javascript_3
$community_name
$css_class
$my_places_portlet_url
$community_default_public_url
$community_default_private_url
$community_default_url
$the_title
$layouts
$pages

## ———- Navigation ———- ##
$nav_items
$has_navigation

## ———- Staging ———- ##
$show_staging
$staging_text
## ———- My places ———- ##
$show_my_places
$my_places_text

## ———- Includes ———- ##
$dir_include
$bottom_include
$bottom_ext_include
$content_include
$top_head_include
$top_messages_include

## ———- Date ———- ##
$date
$current_time
$the_year