Skip to content

Commit

Permalink
This is my proposal on implementing the ability to switch frontend an…
Browse files Browse the repository at this point in the history
…d backend templates independently.

- This introduces a new option "template_backend" that will be set to indicate the backend template, defaults to 2k11.
- The "Engine: xxx" line in info.txt still works, but only for the frontend
- The frontend fallback chain defaults to the old "default" template to ensure that themes will work that have "old-style" HTML output
- The backend fallback chain only falls back to 2k11 and then "default"
- In the future, we will remove templates/default/admin once the mechanism is proven stable

To test this in all cases you can:

- Copy 2k11/ to 2k11-custom, edit info.txt, give it a distinct name. Edit the admin/index.tpl file to add some code to ensure that you will see that template in the backend if you pick it, or adjust the style.css or whatever.
- Copy idea/ to idea-custom, edit info.txt, add a "Engine: 2k11" line. Now you can test how a template would look like that fallsback on 2k11 instead of "default"

Those permutations can be checked and come to my mind:

- Backend: 2k11, Frontend: 2k11
- Backend: 2k11-custom, Frontend: 2k11
- Backend: 2k11, Frontend: 2k11-custom

- Backend: 2k11, Frontend: idea
- Backend: 2k11, Frontend: idea-custom

- Backend: 2k11-custom, Frontend: idea
- Backend: 2k11-custom, Frontend: idea-custom

They seem to work.

Currently the display of backend and frontend theme in templates.inc.tpl takes up some larger space. Maybe it could be prettified somehow, maybe put frontend and backend template next to each other, not beneath each other? Maybe @yellowled has some suggestions.

@onli and @ophian - please have a look at this, since you both also worked on the fallback chains. Please tell me if you have issues with this. We can easily revert, if you see this approach as not workable. This is more a "proof of concept" draft.
  • Loading branch information
garvinhicking committed May 14, 2014
1 parent a6b20ad commit dd83225
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 27 deletions.
12 changes: 12 additions & 0 deletions docs/NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
Version 2.0-beta2 ()
------------------------------------------------------------------------

* Backend and Frontend themes can now be set independently from
each other. New backend themes now need to set:

Backend: Yes

in their info.txt file. If you adapt a custom admin theme,
ensure that it is compatible to the new "2k11" backend to
ensure proper future usage within Serendipity. The bulletproof
backend will now no longer be recognized as a backend theme
option, but can be selected as a new frontend theme, while
using 2k11 (=default) in the backend.

* Include klogger, call it as $serendipity['logger']->debug/error

* Add HTTP_Request2 and dependencies as bundled libraries and
Expand Down
25 changes: 16 additions & 9 deletions include/admin/templates.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,33 +62,40 @@ function import(&$config) {
$data["adminAction"] = "editConfiguration";
}

if ($serendipity['GET']['adminAction'] == 'install' ) {
if ($serendipity['GET']['adminAction'] == 'install' || $serendipity['GET']['adminAction'] == 'install-frontend' || $serendipity['GET']['adminAction'] == 'install-backend') {
serendipity_plugin_api::hook_event('backend_templates_fetchtemplate', $serendipity);

$themeInfo = serendipity_fetchTemplateInfo(htmlspecialchars($serendipity['GET']['theme']));

// A separate hook is used post installation, for plugins to possibly perform some actions
serendipity_plugin_api::hook_event('backend_templates_install', $serendipity['GET']['theme'], $themeInfo);

serendipity_set_config_var('template', htmlspecialchars($serendipity['GET']['theme']));
if ($serendipity['GET']['adminAction'] == 'install' || $serendipity['GET']['adminAction'] == 'install-frontend') {
serendipity_set_config_var('template', htmlspecialchars($serendipity['GET']['theme']));
}

// template_engine was set by default to default, which screws up the fallback chain (to the default-template first)
serendipity_set_config_var('template_engine', null);
if ($themeInfo['engine']) {
serendipity_set_config_var('template_engine', $themeInfo['engine']);
if ($serendipity['GET']['adminAction'] == 'install-backend' && $themeInfo['custom_admin_interface'] == YES) {
serendipity_set_config_var('template_backend', htmlspecialchars($serendipity['GET']['theme']));
} else {
// template_engine was set by default to default, which screws up the fallback chain (to the default-template first)
// The "Engine" now only applies to FRONTEND themes. Backend themes will always fall back to our default backend theme only, to ensure proper backend operation.
serendipity_set_config_var('template_engine', null);
if ($themeInfo['engine']) {
serendipity_set_config_var('template_engine', $themeInfo['engine']);
}
}
serendipity_set_config_var('last_template_change', time());

$data["adminAction"] = "install";
$data["install_template"] = htmlspecialchars($serendipity['GET']['theme']);

}

if ( @file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template'] .'/layout.php') ) {
$data["deprecated"] = true;
}

$data["cur_template"] = $serendipity['template'];
$data["cur_template"] = $serendipity['template'];
$data["cur_template_backend"] = $serendipity['template_backend'];

if (file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template'] . '/config.inc.php')) {
serendipity_smarty_init();
Expand Down Expand Up @@ -201,4 +208,4 @@ function import(&$config) {

echo serendipity_smarty_show('admin/templates.inc.tpl', $data);

/* vim: set sts=4 ts=4 expandtab : */
/* vim: set sts=4 ts=4 expandtab : */
2 changes: 1 addition & 1 deletion include/functions.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ function serendipity_fetchTemplateInfo($theme, $abspath = null) {

if ( $theme != 'default' && $theme != 'default-rtl'
&& @is_dir($serendipity['templatePath'] . $theme . '/admin')
&& @is_readable($serendipity['templatePath'] . $theme . '/admin/style.css') ) {
&& strtolower($data['backend']) == 'yes' ) {

$data['custom_admin_interface'] = YES;
} else {
Expand Down
28 changes: 19 additions & 9 deletions include/functions_config.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,16 +261,26 @@ function serendipity_getTemplateFile($file, $key = 'serendipityHTTPPath') {

$directories = array();

$directories[] = isset($serendipity['template']) ? $serendipity['template'] . '/' : '';
if (isset($serendipity['template_engine']) && $serendipity['template_engine'] != null) {
$p = explode(',', $serendipity['template_engine']);
foreach($p AS $te) {
$directories[] = trim($te) . '/';
if (defined('IN_serendipity_admin')) {
// Backend will always use our default backend (=defaultTemplate) as fallback.
$directories[] = isset($serendipity['template_backend']) ? $serendipity['template_backend'] . '/' : '';
$directories[] = $serendipity['defaultTemplate'] .'/';
$directories[] = 'default/';
} else {
$directories[] = isset($serendipity['template']) ? $serendipity['template'] . '/' : '';
if (isset($serendipity['template_engine']) && $serendipity['template_engine'] != null) {
$p = explode(',', $serendipity['template_engine']);
foreach($p AS $te) {
$directories[] = trim($te) . '/';
}
}
}

$directories[] = $serendipity['defaultTemplate'] .'/';
$directories[] = 'default/';
// Frontend templates currently need to fall back to "default" (see "idea"), so that they get the
// output they desire. If templates are based on 2k11, the need to set "Engine: 2k11" in their info.txt
// file.
$directories[] = 'default/';
$directories[] = $serendipity['defaultTemplate'] .'/';
}

foreach ($directories as $directory) {
$templateFile = $serendipity['templatePath'] . $directory . $file;
Expand All @@ -279,7 +289,7 @@ function serendipity_getTemplateFile($file, $key = 'serendipityHTTPPath') {
}

if (file_exists($serendipity['serendipityPath'] . $templateFile . ".tpl") && $serendipity['template'] . '/' == $directory && IS_installed) {
# catch .js.tpl files served via the template-plugin-api, but only if that template is active as well, so config.inc.php is laoded
# catch .js.tpl files served via the template-plugin-api, but only if that template is active as well, so config.inc.php is loaded
# this won't work in the installer
return $serendipity['baseURL'] . 'index.php?/plugin/' . $file;
}
Expand Down
24 changes: 23 additions & 1 deletion include/functions_smarty.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,12 @@ function serendipity_smarty_init($vars = array()) {
// Beware: Smarty is used in the Admin backend, despite of this.
include_once $template_dir . '/template.inc.php';
} else {

// Backend template overwritten here (NOT earlier due to frontend specific check
if (defined('IN_serendipity_admin')) {
$template_dir = $serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template_backend'];
}

// Set a session variable if Smarty fails:
$prev_smarty = $_SESSION['no_smarty'];
$_SESSION['no_smarty'] = true;
Expand Down Expand Up @@ -1014,6 +1020,7 @@ function serendipity_smarty_init($vars = array()) {
'category' => $category,
'category_info' => $category_info,
'template' => $serendipity['template'],
'template_backend' => $serendipity['template_backend'],

'dateRange' => (!empty($serendipity['range']) ? $serendipity['range'] : array())
)
Expand All @@ -1025,11 +1032,26 @@ function serendipity_smarty_init($vars = array()) {

// For advanced usage, we allow template authors to create a file 'config.inc.php' where they can
// setup custom smarty variables, modifiers etc. to use in their templates.

// If a template engine is defined we need that config.inc.php file as well. The template's actual file is loaded after that to be able to overwrite config.
if (isset($serendipity['template_engine']) && $serendipity['template_engine'] != null) {
$p = explode(',', $serendipity['template_engine']);
foreach($p AS $te) {
$config = $serendipity['serendipityPath'] . $serendipity['templatePath'] . trim($te) . '/config.inc.php';

if (file_exists($config)) {
include_once $config;
}

}
}

$config = $serendipity['smarty']->getConfigDir(0) . '/config.inc.php';
if (file_exists($config)) {
include_once $config;
}



if (is_array($template_loaded_config)) {
$template_vars =& $template_loaded_config;
$serendipity['smarty']->assignByRef('template_option', $template_vars);
Expand Down
6 changes: 6 additions & 0 deletions include/lang.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@
if (defined('S9Y_DATA_PATH')) {
@include_once (S9Y_DATA_PATH . 'templates/' . $serendipity['template'] . '/' . $charset . 'lang_' . $serendipity['lang'] . '.inc.php');
@include_once (S9Y_DATA_PATH . 'templates/' . $serendipity['template'] . '/lang_en.inc.php');

@include_once (S9Y_DATA_PATH . 'templates/' . $serendipity['template_backend'] . '/' . $charset . 'lang_' . $serendipity['lang'] . '.inc.php');
@include_once (S9Y_DATA_PATH . 'templates/' . $serendipity['template_backend'] . '/lang_en.inc.php');
} else {
@include_once (S9Y_INCLUDE_PATH . 'templates/' . $serendipity['template'] . '/' . $charset . 'lang_' . $serendipity['lang'] . '.inc.php');
@include_once (S9Y_INCLUDE_PATH . 'templates/' . $serendipity['template'] . '/lang_en.inc.php');

@include_once (S9Y_INCLUDE_PATH . 'templates/' . $serendipity['template_backend'] . '/' . $charset . 'lang_' . $serendipity['lang'] . '.inc.php');
@include_once (S9Y_INCLUDE_PATH . 'templates/' . $serendipity['template_backend'] . '/lang_en.inc.php');
}
}

Expand Down
13 changes: 10 additions & 3 deletions include/serendipity_smarty_class.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// define secure_dir and trusted_dirs for Serendipity_Smarty_Security_Policy class.
@define('S9Y_TEMPLATE_FALLBACK', $serendipity['serendipityPath'] . $serendipity['templatePath'] . 'default');
@define('S9Y_TEMPLATE_USERDEFAULT', $serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template']);
@define('S9Y_TEMPLATE_USERDEFAULT_BACKEND', $serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template_backend']);
@define('S9Y_TEMPLATE_SECUREDIR', $serendipity['serendipityPath'] . $serendipity['templatePath']);


Expand All @@ -29,7 +30,7 @@ class Serendipity_Smarty_Security_Policy extends Smarty_Security
public $secure_dir = array(S9Y_TEMPLATE_SECUREDIR); // do we need this then?
// actually no need, as template dirs are explicit defined as trusted_dirs. (unproofed)
public $trusted_dir = array(S9Y_TEMPLATE_USERDEFAULT, S9Y_TEMPLATE_FALLBACK); // do we need this then?
public $trusted_dir = array(S9Y_TEMPLATE_USERDEFAULT, S9Y_TEMPLATE_USERDEFAULT_BACKEND, S9Y_TEMPLATE_FALLBACK); // do we need this then?
#public $modifiers = array(); // can be omitted, when all allowed

Expand Down Expand Up @@ -121,9 +122,15 @@ private function setParams()
$template_engine = serendipity_get_config_var('template_engine');
$template_dirs = array();
if ($template_engine) {
$template_dirs[] = $serendipity['serendipityPath'] . $serendipity['templatePath'] . $template_engine;
}
$p = explode(',', $template_engine);
foreach($p AS $te) {
$template_dirs[] = $serendipity['serendipityPath'] . $serendipity['templatePath'] . trim($te) . '/';
}
}

$template_dirs[] = $serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['defaultTemplate'];
$template_dirs[] = $serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template_backend'];

// add secure dir to template path, in case engine did have entries
if (S9Y_TEMPLATE_SECUREDIR != $serendipity['serendipityPath'] . $serendipity['templatePath']) {
$template_dirs[] = S9Y_TEMPLATE_SECUREDIR;
Expand Down
2 changes: 2 additions & 0 deletions serendipity.css.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
break;

case 'serendipity_admin.css':
// This constant is needed to properly set the template context for the backend.
@define('IN_serendipity_admin', true);
$css_hook = 'css_backend';
$css_file = 'admin/style.css';
break;
Expand Down
5 changes: 5 additions & 0 deletions serendipity_config.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@
/* Name of folder for the default theme */
$serendipity['defaultTemplate'] = '2k11';

/* Default backend theme */
if (!isset($serendipity['template_backend'])) {
$serendipity['template_backend'] = '2k11';
}

/* Availiable languages */
if (!isset($serendipity['languages'])) {
$serendipity['languages'] = array('en' => 'English',
Expand Down
45 changes: 42 additions & 3 deletions templates/2k11/admin/templates.inc.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,46 @@
<a class="button_link" href="?serendipity[adminModule]=templates&amp;serendipity[adminAction]=editConfiguration" title="{$CONST.CONFIGURATION}">{$CONST.CONFIGURATION}</a>
</article>

{if $cur_template_backend}
{assign var="cur_tpl_backend" value=$templates[$cur_template_backend]}
<h2>{$CONST.CURRENT_TEMPLATE} - {$CONST.BACKEND}</h2>

<article class="clearfix current_template">
<h3>{$cur_tpl_backend.info.name}</h3>

<div class="clearfix equal_heights template_wrap">
<div class="template_preview">
{if $cur_tpl_backend.fullsize_preview || $cur_tpl_backend.preview}
{if $cur_tpl_backend.fullsize_preview}
<a class="media_fullsize" href="{$cur_tpl_backend.fullsize_preview}" title="{$CONST.MEDIA_FULLSIZE}: {$cur_tpl_backend.info.name}">
<img src="{$cur_tpl_backend.fullsize_preview}" class="template_preview_img" alt="{$CONST.PREVIEW}" >
</a>
{else}
<img src="{$cur_tpl_backend.preview}" alt="{$CONST.PREVIEW}" >
{/if}
{/if}
<footer id="template_info_cur_backend" class="template_info additional_info">
<dl class="clearfix">
<dt class="template_author">{$CONST.AUTHOR}:</dt>
<dd>{$cur_tpl_backend.info.author}</dd>
<dt class="template_date">{$CONST.LAST_UPDATED}:</dt>
<dd>{$cur_tpl_backend.info.date}</dd>
<dt class="template_admin">{$CONST.CUSTOM_ADMIN_INTERFACE}:</dt>
<dd>{$cur_tpl_backend.info.custom_admin_interface}</dd>
</dl>
</footer>
</div>
</div>

<button class="template_show_info button_link" type="button" data-href="#template_info_cur_backend" title="{$CONST.TEMPLATE_INFO}"><span class="icon-info-circled"></span><span class="visuallyhidden"> {$CONST.TEMPLATE_INFO}</span></button>
</article>
{/if}

<h2>{$CONST.AVAILABLE_TEMPLATES}</h2>

<ul class="plainList clearfix">
{foreach $templates as $template=>$info}
{if $info.info.engine == 'yes' || $template == $cur_template}{continue}{/if}
{if !empty($template)}
{if !empty($template) && $info.info.engine != 'yes'}
<li><article class="clearfix {cycle values="odd,even"}">
<h3>{$info.info.name}</h3>
<div class="clearfix equal_heights template_wrap">
Expand All @@ -85,7 +119,7 @@
<dd>{$info.info.author}</dd>
<dt class="template_date">{$CONST.LAST_UPDATED}:</dt>
<dd>{$info.info.date}</dd>
<dt class="template_admin">{$CONST.CUSTOM_ADMIN_INTERFACE}</dt>
<dt class="template_admin">{$CONST.CUSTOM_ADMIN_INTERFACE}:</dt>
<dd>{if $info.info.custom_admin_interface} {$info.info.custom_admin_interface} {else} {$CONST.NO} {/if}</dd>
</dl>
</footer>
Expand All @@ -95,7 +129,12 @@
<button class="template_show_info button_link" type="button" data-href="#template_info_{$info@key}" title="{$CONST.TEMPLATE_INFO}"><span class="icon-info-circled"></span><span class="visuallyhidden"> {$CONST.TEMPLATE_INFO}</span></button>

{if !$info.unmetRequirements}
{if $info.info.custom_admin_interface == $CONST.YES}
<a class="button_link" href="?serendipity[adminModule]=templates&amp;serendipity[adminAction]=install-frontend&amp;serendipity[theme]={$template}{$info.info.customURI}" title="{$CONST.SET_AS_TEMPLATE}">{$CONST.INSTALL}: {$CONST.FRONTEND}</a>
<a class="button_link" href="?serendipity[adminModule]=templates&amp;serendipity[adminAction]=install-backend&amp;serendipity[theme]={$template}{$info.info.customURI}" title="{$CONST.SET_AS_TEMPLATE}">{$CONST.INSTALL}: {$CONST.BACKEND}</a>
{else}
<a class="button_link" href="?serendipity[adminModule]=templates&amp;serendipity[adminAction]=install&amp;serendipity[theme]={$template}{$info.info.customURI}" title="{$CONST.SET_AS_TEMPLATE}">{$CONST.INSTALL}</a>
{/if}
{else}
<span class="unmet_requirements msg_error"><span class="icon-attention-circled"></span> {$info.unmetRequirements}></span>
{/if}
Expand Down
3 changes: 2 additions & 1 deletion templates/2k11/info.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Name: 2k11
Author: Matthias Mees, Veit Lehmann
Date: 2014-01-08
Require Serendipity: 1.6
Require Serendipity: 2.0
Backend: Yes
5 changes: 5 additions & 0 deletions templates/default/admin/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
This directory contains the pre Serendipity 2.0 admin tepmlates.

Since Serendipity 2.0, the "2k11" is the default backend template and holds the current admin template.

The files here are deprecated and will be removed in future versions.

0 comments on commit dd83225

Please sign in to comment.