aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB')
-rw-r--r--phpBB/adm/style/acp_styles.html16
-rw-r--r--phpBB/docs/CHANGELOG.html3
-rw-r--r--phpBB/includes/acp/acp_styles.php506
-rw-r--r--phpBB/includes/bbcode.php15
-rw-r--r--phpBB/includes/functions_template.php6
-rw-r--r--phpBB/includes/session.php2
-rw-r--r--phpBB/includes/template.php129
-rw-r--r--phpBB/install/database_update.php11
-rw-r--r--phpBB/language/en/acp/styles.php8
9 files changed, 607 insertions, 89 deletions
diff --git a/phpBB/adm/style/acp_styles.html b/phpBB/adm/style/acp_styles.html
index a1363fce8d..652bdbd372 100644
--- a/phpBB/adm/style/acp_styles.html
+++ b/phpBB/adm/style/acp_styles.html
@@ -283,7 +283,7 @@
<tbody>
<!-- BEGIN file -->
<!-- IF file.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
- <td><a href="{file.U_VIEWSOURCE}" onclick="popup(this.href, 750, 550, '_source'); return false;">{file.FILENAME}</a></td>
+ <td><a href="{file.U_VIEWSOURCE}" onclick="popup(this.href, 750, 550, '_source'); return false;">{file.FILENAME_PATH}</a></td>
<td>{file.FILESIZE}</td>
<td>{file.CACHED}</td>
<td>{file.MODIFIED}</td>
@@ -461,6 +461,12 @@
<dt><label for="copyright">{L_COPYRIGHT}:</label></dt>
<dd><!-- IF S_INSTALL --><b id="copyright">{COPYRIGHT}</b><!-- ELSE --><input type="text" id="copyright" name="copyright" value="{COPYRIGHT}" /><!-- ENDIF --></dd>
</dl>
+ <!-- IF S_SUPERTEMPLATE -->
+ <dl>
+ <dt><label for="inheriting">{L_INHERITING_FROM}:</label></dt>
+ <dd> <b id="inheriting">{S_SUPERTEMPLATE}</b></dd>
+ </dl>
+ <!-- ENDIF -->
<!-- IF S_STYLE and not S_BASIS -->
<dl>
<dt><label for="template_id">{L_STYLE_TEMPLATE}:</label></dt>
@@ -475,11 +481,11 @@
<dd><!-- IF S_INSTALL --><b id="imageset_id">{IMAGESET_NAME}</b><!-- ELSE --><select id="imageset_id" name="imageset_id">{S_IMAGESET_OPTIONS}</select><!-- ENDIF --></dd>
</dl>
<!-- ENDIF -->
- <!-- IF S_TEMPLATE or S_THEME -->
+ <!-- IF (S_TEMPLATE or S_THEME) and (S_LOCATION or not S_INSTALL) -->
<dl>
- <dt><label for="store_db">{L_LOCATION}:</label><br /><span>{L_LOCATION_EXPLAIN}</span></dt>
- <dd><label><input type="radio" class="radio" name="store_db" value="0"<!-- IF not S_STORE_DB --> id="store_db" checked="checked"<!-- ENDIF --> /> {L_STORE_FILESYSTEM}</label>
- <label><input type="radio" class="radio" name="store_db" value="1"<!-- IF S_STORE_DB --> id="store_db" checked="checked"<!-- ENDIF --> /> {L_STORE_DATABASE}</label></dd>
+ <dt><label for="store_db">{L_LOCATION}:</label><br /><span><!-- IF S_STORE_DB_DISABLED -->{L_LOCATION_DISABLED_EXPLAIN}<!-- ELSE -->{L_LOCATION_EXPLAIN}<!-- ENDIF --></span></dt>
+ <dd><label><input type="radio" class="radio" name="store_db" value="0"<!-- IF not S_STORE_DB --> id="store_db" checked="checked"<!-- ENDIF --> <!-- IF S_STORE_DB_DISABLED -->disabled="disabled" <!-- ENDIF --> />{L_STORE_FILESYSTEM}</label>
+ <label><input type="radio" class="radio" name="store_db" value="1"<!-- IF S_STORE_DB --> id="store_db" checked="checked"<!-- ENDIF --> <!-- IF S_STORE_DB_DISABLED -->disabled="disabled" <!-- ENDIF -->/> {L_STORE_DATABASE}</label></dd>
</dl>
<!-- ENDIF -->
<!-- IF S_STYLE -->
diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html
index 310276bece..4956fd7b0e 100644
--- a/phpBB/docs/CHANGELOG.html
+++ b/phpBB/docs/CHANGELOG.html
@@ -53,7 +53,6 @@
<ol>
<li><a href="#changelog">Changelog</a>
<ol style="list-style-type: lower-roman;">
- <li><a href="#v302">Changes since 3.0.2</a></li>
<li><a href="#v301">Changes since 3.0.1</a></li>
<li><a href="#v300">Changes since 3.0.0</a></li>
<li><a href="#v30rc8">Changes since RC-8</a></li>
@@ -90,6 +89,8 @@
<li>[Change] No longer allow the direct use of MULTI_INSERT in sql_build_array. sql_multi_insert() must be used.</li>
<li>[Change] Display warning in ACP if config.php file is left writeable.</li>
<li>[Change] More restrictive chmod to new files being created.</li>
+ <li>[Feature] Allow limited inheritance for templates sets.</li>
+ <li>[Feature] Allow hard disabling of the template editor.</li>
</ul>
<a name="v301"></a><h3>1.ii. Changes since 3.0.1</h3>
diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php
index dd5255f755..fb146ad858 100644
--- a/phpBB/includes/acp/acp_styles.php
+++ b/phpBB/includes/acp/acp_styles.php
@@ -93,6 +93,17 @@ version = {VERSION}
parse_css_file = {PARSE_CSS_FILE}
';
+ $this->template_cfg .= '
+# Some configuration options
+
+#
+# You can use this function to inherit templates from another template.
+# The template of the given name has to be installed.
+# Templates cannot inherit from inheriting templates.
+#
+inherit_from = {INHERIT_FROM}
+';
+
$this->imageset_keys = array(
'logos' => array(
'site_logo',
@@ -670,6 +681,11 @@ parse_css_file = {PARSE_CSS_FILE}
{
global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
+ if (defined('DISABLE_ACP_EDITOR'))
+ {
+ trigger_error($user->lang['EDITOR_DISABLED'] . adm_back_link($this->u_action));
+ }
+
$this->page_title = 'EDIT_TEMPLATE';
$filelist = $filelist_cats = array();
@@ -729,13 +745,14 @@ parse_css_file = {PARSE_CSS_FILE}
// If it's not stored in the db yet, then update the template setting and store all template files in the db
if (!$template_info['template_storedb'])
{
- $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . '
- SET template_storedb = 1
- WHERE template_id = ' . $template_id;
- $db->sql_query($sql);
-
- $filelist = filelist("{$phpbb_root_path}styles/{$template_info['template_path']}/template", '', 'html');
- $this->store_templates('insert', $template_id, $template_info['template_path'], $filelist);
+ if ($this->get_super('template', $template_id))
+ {
+ $this->store_in_db('template', $super['template_id']);
+ }
+ else
+ {
+ $this->store_in_db('template', $template_id);
+ }
add_log('admin', 'LOG_TEMPLATE_EDIT_DETAILS', $template_info['template_name']);
$additional .= '<br />' . $user->lang['EDIT_TEMPLATE_STORED_DB'];
@@ -975,17 +992,30 @@ parse_css_file = {PARSE_CSS_FILE}
$filemtime = array();
if ($template_row['template_storedb'])
{
- $sql = 'SELECT template_filename, template_mtime
- FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
- WHERE template_id = $template_id";
- $result = $db->sql_query($sql);
-
- $filemtime = array();
- while ($row = $db->sql_fetchrow($result))
+ $ids = array();
+ if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id'])
{
- $filemtime[$row['template_filename']] = $row['template_mtime'];
+ $ids[] = $template_row['template_inherits_id'];
+ }
+ $ids[] = $template_row['template_id'];
+
+ $filemtime = array();
+ $file_template_db = array();
+
+ foreach ($ids as $id)
+ {
+ $sql = 'SELECT template_filename, template_mtime
+ FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
+ WHERE template_id = $id";
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $filemtime[$row['template_filename']] = $row['template_mtime'];
+ $file_template_db[$row['template_filename']] = $id;
+ }
+ $db->sql_freeresult($result);
}
- $db->sql_freeresult($result);
}
// Get a list of cached template files and then retrieve additional information about them
@@ -1006,14 +1036,39 @@ parse_css_file = {PARSE_CSS_FILE}
{
continue;
}
+
+ $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html";
+ $inherited = false;
+
+ if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id'])
+ {
+ if (!$template_row['template_storedb'])
+ {
+ if (!file_exists($file))
+ {
+ $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html";
+ $inherited = true;
+ }
+ }
+ else
+ {
+ if ($file_template_db[$file . '.html'] == $template_row['template_inherits_id'])
+ {
+ $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html";
+ $inherited = true;
+ }
+ }
+ }
+
$template->assign_block_vars('file', array(
'U_VIEWSOURCE' => $this->u_action . "&amp;action=cache&amp;id=$template_id&amp;source=$file",
'CACHED' => $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")),
'FILENAME' => $file,
+ 'FILENAME_PATH' => $file_tpl,
'FILESIZE' => sprintf('%.1f ' . $user->lang['KIB'], filesize("{$phpbb_root_path}cache/$filename") / 1024),
- 'MODIFIED' => $user->format_date((!$template_row['template_storedb']) ? filemtime("{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html") : $filemtime[$file . '.html']))
+ 'MODIFIED' => $user->format_date((!$template_row['template_storedb']) ? filemtime($file_tpl) : $filemtime[$file . '.html']))
);
}
unset($filemtime);
@@ -1517,6 +1572,18 @@ parse_css_file = {PARSE_CSS_FILE}
break;
}
+ if ($mode === 'template' && ($conflicts = $this->check_inheritance($mode, $style_id)))
+ {
+ $l_type = strtoupper($mode);
+ $msg = $user->lang[$l_type . '_DELETE_DEPENDENT'];
+ foreach ($conflicts as $id => $values)
+ {
+ $msg .= '<br />' . $values['template_name'];
+ }
+
+ trigger_error($msg . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
$l_prefix = strtoupper($mode);
$sql = "SELECT $sql_select
@@ -2218,51 +2285,38 @@ parse_css_file = {PARSE_CSS_FILE}
if ($style_row['template_storedb'] != $store_db)
{
- if (!$store_db && !$safe_mode && @is_writable("{$phpbb_root_path}styles/{$style_row['template_path']}/template"))
+ if ($super = $this->get_super($mode, $style_row['template_id']))
{
- $sql = 'SELECT *
- FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
- WHERE template_id = $style_id";
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
+ $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name']));
+ $sql_ary = array();
+ }
+ else
+ {
+ if (!$store_db && !$safe_mode && @is_writable("{$phpbb_root_path}styles/{$style_row['template_path']}/template"))
{
- if (!($fp = @fopen("{$phpbb_root_path}styles/{$style_row['template_path']}/template/" . $row['template_filename'], 'wb')))
+ $err = $this->store_in_fs('template', $style_row['template_id']);
+ if ($err)
{
- $store_db = 1;
- $error[] = $user->lang['EDIT_TEMPLATE_STORED_DB'];
- break;
+ $error += $err;
}
-
- fwrite($fp, $row['template_data']);
- fclose($fp);
}
- $db->sql_freeresult($result);
-
- if (!$store_db)
+ else if ($store_db)
{
+ $this->store_in_db('template', $style_row['template_id']);
+ }
+ else
+ {
+ // We no longer store within the db, but are also not able to update the file structure
+ // Since the admin want to switch this, we adhere to his decision. But we also need to remove the cache
$sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
WHERE template_id = $style_id";
$db->sql_query($sql);
}
- }
- else if ($store_db)
- {
- $filelist = filelist("{$phpbb_root_path}styles/{$style_row['template_path']}/template", '', 'html');
- $this->store_templates('insert', $style_id, $style_row['template_path'], $filelist);
- }
- else
- {
- // We no longer store within the db, but are also not able to update the file structure
- // Since the admin want to switch this, we adhere to his decision. But we also need to remove the cache
- $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
- WHERE template_id = $style_id";
- $db->sql_query($sql);
- }
- $sql_ary += array(
- 'template_storedb' => $store_db,
- );
+ $sql_ary += array(
+ 'template_storedb' => $store_db,
+ );
+ }
}
break;
}
@@ -2312,6 +2366,16 @@ parse_css_file = {PARSE_CSS_FILE}
$db->sql_freeresult($result);
}
}
+
+
+ if ($mode == 'template')
+ {
+ $super = array();
+ if (isset($style_row[$mode . '_inherits_id']) && $style_row['template_inherits_id'])
+ {
+ $super = $this->get_super($mode, $style_row['template_id']);
+ }
+ }
$this->page_title = 'EDIT_DETAILS_' . $l_type;
@@ -2323,8 +2387,10 @@ parse_css_file = {PARSE_CSS_FILE}
'S_THEME' => ($mode == 'theme') ? true : false,
'S_IMAGESET' => ($mode == 'imageset') ? true : false,
'S_STORE_DB' => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0,
+ 'S_STORE_DB_DISABLED' => (isset($style_row[$mode . '_inherits_id'])) ? $style_row[$mode . '_inherits_id'] : 0,
'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0,
'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0,
+ 'S_SUPERTEMPLATE' => (isset($style_row[$mode . '_inherits_id']) && $style_row[$mode . '_inherits_id']) ? $super['template_name'] : 0,
'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '',
'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '',
@@ -2682,6 +2748,7 @@ parse_css_file = {PARSE_CSS_FILE}
'S_DETAILS' => true,
'S_INSTALL' => true,
'S_ERROR_MSG' => (sizeof($error)) ? true : false,
+ 'S_LOCATION' => (isset($installcfg['inherit_from']) && $installcfg['inherit_from']) ? false : true,
'S_STYLE' => ($mode == 'style') ? true : false,
'S_TEMPLATE' => ($mode == 'template') ? true : false,
'S_THEME' => ($mode == 'theme') ? true : false,
@@ -3034,6 +3101,9 @@ parse_css_file = {PARSE_CSS_FILE}
{
global $phpbb_root_path, $db, $user;
+ // we parse the cfg here (again)
+ $cfg_data = parse_cfg_file("$root_path$mode/$mode.cfg");
+
switch ($mode)
{
case 'template':
@@ -3074,6 +3144,7 @@ parse_css_file = {PARSE_CSS_FILE}
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
+
if ($row)
{
@@ -3087,6 +3158,34 @@ parse_css_file = {PARSE_CSS_FILE}
$error[] = $user->lang[$l_type . '_ERR_NAME_EXIST'];
}
+ if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from'])
+ {
+ $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path, {$mode}_storedb
+ FROM $sql_from
+ WHERE {$mode}_name = '" . $db->sql_escape(strtolower($cfg_data['inherit_from'])) . "'
+ AND {$mode}_inherits_id = 0";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+ if (!$row)
+ {
+ $error[] = sprintf($user->lang[$l_type . '_ERR_REQUIRED_OR_INCOMPLETE'], $inherit_from);
+ }
+ else
+ {
+ $inherit_id = $row["{$mode}_id"];
+ $inherit_path = $row["{$mode}_path"];
+ $cfg_data['store_db'] = $row["{$mode}_storedb"];
+ $store_db = $row["{$mode}_storedb"];
+ }
+ }
+ else
+ {
+ $inherit_id = 0;
+ $inherit_path = '';
+ }
+
+
if (sizeof($error))
{
return false;
@@ -3102,8 +3201,6 @@ parse_css_file = {PARSE_CSS_FILE}
{
case 'template':
// We check if the template author defined a different bitfield
- $cfg_data = parse_cfg_file("$root_path$mode/template.cfg");
-
if (!empty($cfg_data['template_bitfield']))
{
$sql_ary['bbcode_bitfield'] = $cfg_data['template_bitfield'];
@@ -3115,15 +3212,21 @@ parse_css_file = {PARSE_CSS_FILE}
// We set a pre-defined bitfield here which we may use further in 3.2
$sql_ary += array(
- 'template_storedb' => $store_db
+ 'template_storedb' => $store_db,
);
+ if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from'])
+ {
+ $sql_ary += array(
+ 'template_inherits_id' => $inherit_id,
+ 'template_inherit_path' => $inherit_path,
+ );
+ }
break;
case 'theme':
// We are only interested in the theme configuration for now
- $theme_cfg = parse_cfg_file("{$phpbb_root_path}styles/$path/theme/theme.cfg");
- if (isset($theme_cfg['parse_css_file']) && $theme_cfg['parse_css_file'])
+ if (isset($cfg_data['parse_css_file']) && $cfg_data['parse_css_file'])
{
$store_db = 1;
}
@@ -3262,6 +3365,297 @@ parse_css_file = {PARSE_CSS_FILE}
// Return store_db in case it had to be altered
return $store_db;
}
+
+ /**
+ * Checks downwards dependencies
+ *
+ * @visibility public
+ * @param string $mode The element type to check - only template is supported
+ * @param int $id The template id
+ * @returns false if no component inherits, array with name, path and id for each subtemplate otherwise
+ */
+ function check_inheritance($mode, $id)
+ {
+ global $db;
+
+ $l_type = strtoupper($mode);
+
+ switch ($mode)
+ {
+ case 'template':
+ $sql_from = STYLES_TEMPLATE_TABLE;
+ break;
+
+ case 'theme':
+ $sql_from = STYLES_THEME_TABLE;
+ break;
+
+ case 'imageset':
+ $sql_from = STYLES_IMAGESET_TABLE;
+ break;
+ }
+
+ $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path
+ FROM $sql_from
+ WHERE {$mode}_inherits_id = " . (int) $id;
+ $result = $db->sql_query($sql);
+
+ $names = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+
+ $names[$row["{$mode}_id"]] = array(
+ "{$mode}_id" => $row["{$mode}_id"],
+ "{$mode}_name" => $row["{$mode}_name"],
+ "{$mode}_path" => $row["{$mode}_path"],
+ );
+ }
+ $db->sql_freeresult($result);
+
+ if (sizeof($names))
+ {
+ return $names;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Checks upwards dependencies
+ *
+ * @visibility public
+ * @param string $mode The element type to check - only template is supported
+ * @param int $id The template id
+ * @returns false if the component does not inherit, array with name, path and id otherwise
+ */
+ function get_super($mode, $id)
+ {
+ global $db;
+
+ $l_type = strtoupper($mode);
+
+ switch ($mode)
+ {
+ case 'template':
+ $sql_from = STYLES_TEMPLATE_TABLE;
+ break;
+
+ case 'theme':
+ $sql_from = STYLES_THEME_TABLE;
+ break;
+
+ case 'imageset':
+ $sql_from = STYLES_IMAGESET_TABLE;
+ break;
+ }
+
+
+ $sql = "SELECT {$mode}_inherits_id
+ FROM $sql_from
+ WHERE {$mode}_id = " . (int) $id;
+ $result = $db->sql_query_limit($sql, 1);
+
+ if ($row = $db->sql_fetchrow($result))
+ {
+ $db->sql_freeresult($result);
+ }
+ else
+ {
+ return false;
+ }
+
+ $super_id = $row["{$mode}_inherits_id"];
+
+ $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path
+ FROM $sql_from
+ WHERE {$mode}_id = " . (int) $super_id;
+
+ $result = $db->sql_query_limit($sql, 1);
+ if ($row = $db->sql_fetchrow($result))
+ {
+ $db->sql_freeresult($result);
+ return $row;
+ }
+
+ return false;
+ }
+
+ /**
+ * Moves a template set and its subtemplates to the database
+ *
+ * @visibility public
+ * @param string $mode The component to move - only template is supported
+ * @param int $id The template id
+ */
+ function store_in_db($mode, $id)
+ {
+ global $db, $user;
+
+ $error = array();
+ $l_type = strtoupper($mode);
+ if ($super = $this->get_super($mode, $id))
+ {
+ $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name']));
+ return $error;
+ }
+
+ $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path
+ FROM " . STYLES_TEMPLATE_TABLE . '
+ WHERE template_id = ' . (int) $id;
+
+ $result = $db->sql_query_limit($sql, 1);
+ if ($row = $db->sql_fetchrow($result))
+ {
+ $db->sql_freeresult($result);
+ $subs = $this->check_inheritance($mode, $id);
+
+ $this->_store_in_db($mode, $id, $row["{$mode}_path"]);
+ if ($subs && sizeof($subs))
+ {
+ foreach ($subs as $sub_id => $sub)
+ {
+ if ($err = $this->_store_in_db($mode, $sub["{$mode}_id"], $sub["{$mode}_path"]))
+ {
+ $error[] = $err;
+ }
+ }
+ }
+ }
+ if (sizeof($error))
+ {
+ return $error;
+ }
+
+ return false;
+ }
+
+ /**
+ * Moves a template set to the database
+ *
+ * @visibility private
+ * @param string $mode The component to move - only template is supported
+ * @param int $id The template id
+ * @param string $path TThe path to the template files
+ */
+ function _store_in_db($mode, $id, $path)
+ {
+ global $phpbb_root_path, $db;
+
+ $filelist = filelist("{$phpbb_root_path}styles/{$path}/template", '', 'html');
+ $this->store_templates('insert', $id, $path, $filelist);
+
+ // Okay, we do the query here -shouldn't be triggered often.
+ $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . '
+ SET template_storedb = 1
+ WHERE template_id = ' . $id;
+ $db->sql_query($sql);
+ }
+
+ /**
+ * Moves a template set and its subtemplates to the filesystem
+ *
+ * @visibility public
+ * @param string $mode The component to move - only template is supported
+ * @param int $id The template id
+ */
+ function store_in_fs($mode, $id)
+ {
+ global $db, $user;
+
+ $error = array();
+ $l_type = strtoupper($mode);
+ if ($super = $this->get_super($mode, $id))
+ {
+ $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name']));
+ return($error);
+ }
+
+ $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path
+ FROM " . STYLES_TEMPLATE_TABLE . '
+ WHERE template_id = ' . (int) $id;
+
+ $result = $db->sql_query_limit($sql, 1);
+ if ($row = $db->sql_fetchrow($result))
+ {
+ $db->sql_freeresult($result);
+ if (!sizeof($error))
+ {
+ $subs = $this->check_inheritance($mode, $id);
+
+ $this->_store_in_fs($mode, $id, $row["{$mode}_path"]);
+
+ if ($subs && sizeof($subs))
+ {
+ foreach ($subs as $sub_id => $sub)
+ {
+ $this->_store_in_fs($mode, $sub["{$mode}_id"], $sub["{$mode}_path"]);
+ }
+ }
+ }
+ if (sizeof($error))
+ {
+ $this->store_in_db($id, $mode);
+ return $error;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Moves a template set to the filesystem
+ *
+ * @visibility private
+ * @param string $mode The component to move - only template is supported
+ * @param int $id The template id
+ * @param string $path The path to the template
+ */
+ function _store_in_fs($mode, $id, $path)
+ {
+ global $phpbb_root_path, $db, $user, $safe_mode;
+
+ $store_db = 0;
+ $error = array();
+ if (!$safe_mode && @is_writable("{$phpbb_root_path}styles/{$path}/template"))
+ {
+ $sql = 'SELECT *
+ FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
+ WHERE template_id = $id";
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ if (!($fp = @fopen("{$phpbb_root_path}styles/{$path}/template/" . $row['template_filename'], 'wb')))
+ {
+ $store_db = 1;
+ $error[] = $user->lang['EDIT_TEMPLATE_STORED_DB'];
+ break;
+ }
+
+ fwrite($fp, $row['template_data']);
+ fclose($fp);
+ }
+ $db->sql_freeresult($result);
+
+ if (!$store_db)
+ {
+ $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . "
+ WHERE template_id = $id";
+ $db->sql_query($sql);
+ }
+ }
+ if (sizeof($error))
+ {
+ return $error;
+ }
+ $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . '
+ SET template_storedb = 0
+ WHERE template_id = ' . $id;
+ $db->sql_query($sql);
+
+ return false;
+ }
}
diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php
index ef73762582..fd8fadf3a7 100644
--- a/phpBB/includes/bbcode.php
+++ b/phpBB/includes/bbcode.php
@@ -134,10 +134,21 @@ class bbcode
{
$this->template_bitfield = new bitfield($user->theme['bbcode_bitfield']);
$this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template/bbcode.html';
-
+
if (!@file_exists($this->template_filename))
{
- trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR);
+ if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'])
+ {
+ $this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template/bbcode.html';
+ if (!@file_exists($this->template_filename))
+ {
+ trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR);
+ }
+ }
+ else
+ {
+ trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR);
+ }
}
}
diff --git a/phpBB/includes/functions_template.php b/phpBB/includes/functions_template.php
index 17d3328427..1e7fbaa8e6 100644
--- a/phpBB/includes/functions_template.php
+++ b/phpBB/includes/functions_template.php
@@ -72,15 +72,15 @@ class template_compile
if ($store_in_db)
{
global $db, $user;
-
+
$sql_ary = array(
- 'template_id' => $user->theme['template_id'],
+ 'template_id' => $this->template->files_template[$handle],
'template_filename' => $this->template->filename[$handle],
'template_included' => '',
'template_mtime' => time(),
'template_data' => trim(@file_get_contents($this->template->files[$handle])),
);
-
+
$sql = 'INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
$db->sql_query($sql);
}
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index b2a9bd2559..30101c7411 100644
--- a/phpBB/includes/session.php
+++ b/phpBB/includes/session.php
@@ -1480,7 +1480,7 @@ class user extends session
$style = ($style) ? $style : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']);
}
- $sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name
+ $sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name
FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i
WHERE s.style_id = $style
AND t.template_id = s.template_id
diff --git a/phpBB/includes/template.php b/phpBB/includes/template.php
index 2e60beb658..d17ad55691 100644
--- a/phpBB/includes/template.php
+++ b/phpBB/includes/template.php
@@ -36,6 +36,9 @@ class template
var $cachepath = '';
var $files = array();
var $filename = array();
+ var $files_inherit = array();
+ var $files_template = array();
+ var $inherit_root = '';
// this will hash handle names to the compiled/uncompiled code for that handle.
var $compiled_code = array();
@@ -52,6 +55,11 @@ class template
{
$this->root = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template';
$this->cachepath = $phpbb_root_path . 'cache/tpl_' . $user->theme['template_path'] . '_';
+
+ if ($user->theme['template_inherits_id'])
+ {
+ $this->inherit_root = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template';
+ }
}
else
{
@@ -88,7 +96,6 @@ class template
{
return false;
}
-
foreach ($filename_array as $handle => $filename)
{
if (empty($filename))
@@ -98,8 +105,13 @@ class template
$this->filename[$handle] = $filename;
$this->files[$handle] = $this->root . '/' . $filename;
+
+ if ($this->inherit_root)
+ {
+ $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename;
+ }
}
-
+
return true;
}
@@ -197,7 +209,7 @@ class template
return true;
}
-
+
/**
* Load a compiled template if possible, if not, recompile it
* @access private
@@ -207,9 +219,24 @@ class template
global $user, $phpEx, $config;
$filename = $this->cachepath . str_replace('/', '.', $this->filename[$handle]) . '.' . $phpEx;
-
- $recompile = (($config['load_tplcompile'] && @filemtime($filename) < filemtime($this->files[$handle])) || !file_exists($filename) || @filesize($filename) === 0) ? true : false;
-
+ $this->files_template[$handle] = $user->theme['template_id'];
+
+ $recompile = false;
+ if (!file_exists($filename) || @filesize($filename) === 0)
+ {
+ $recompile = true;
+ }
+ else if ($config['load_tplcompile'])
+ {
+ // No way around it: we need to check inheritance here
+ if ($user->theme['template_inherits_id'] && !file_exists($this->files[$handle]))
+ {
+ $this->files[$handle] = $this->files_inherit[$handle];
+ $this->files_template[$handle] = $user->theme['template_inherits_id'];
+ }
+ $recompile = (@filemtime($filename) < filemtime($this->files[$handle])) ? true : false;
+ }
+
// Recompile page if the original template is newer, otherwise load the compiled version
if (!$recompile)
{
@@ -222,7 +249,14 @@ class template
{
include($phpbb_root_path . 'includes/functions_template.' . $phpEx);
}
-
+
+ // Inheritance - we point to another template file for this one. Equality is also used for store_db
+ if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($this->files[$handle]))
+ {
+ $this->files[$handle] = $this->files_inherit[$handle];
+ $this->files_template[$handle] = $user->theme['template_inherits_id'];
+ }
+
$compile = new template_compile($this);
// If we don't have a file assigned to this handle, die.
@@ -240,28 +274,70 @@ class template
if (isset($user->theme['template_storedb']) && $user->theme['template_storedb'])
{
- $sql = 'SELECT *
+ $rows = array();
+ $ids = array();
+ // Inheritance
+ if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'])
+ {
+ $ids[] = $user->theme['template_inherits_id'];
+ }
+ $ids[] = $user->theme['template_id'];
+
+ foreach ($ids as $id)
+ {
+ $sql = 'SELECT *
FROM ' . STYLES_TEMPLATE_DATA_TABLE . '
- WHERE template_id = ' . $user->theme['template_id'] . "
+ WHERE template_id = ' . $id . "
AND (template_filename = '" . $db->sql_escape($this->filename[$handle]) . "'
OR template_included " . $db->sql_like_expression($db->any_char . $this->filename[$handle] . ':' . $db->any_char) . ')';
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
-
- if ($row)
+
+ $result = $db->sql_query($sql);
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $rows[$row['template_filename']] = $row;
+ }
+ $db->sql_freeresult($result);
+ }
+
+ if (sizeof($rows))
{
- do
+ foreach ($rows as $row)
{
- if ($row['template_mtime'] < filemtime($phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template/' . $row['template_filename']))
+ $file = $this->root . '/' . $row['template_filename'];
+ $force_reload = false;
+ if ($row['template_id'] != $user->theme['template_id'])
+ {
+ // make sure that we are not overlooking a file not in the db yet
+ if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($file))
+ {
+ $file = $this->inherit_root . '/' . $row['template_filename'];
+ $this->files[$row['template_filename']] = $file;
+ $this->files_inherit[$row['template_filename']] = $file;
+ $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id'];
+ }
+ else if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'])
+ {
+ // Ok, we have a situation. There is a file in the subtemplate, but nothing in the DB. We have to fix that.
+ $force_reload = true;
+ $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id'];
+ }
+ }
+ else
+ {
+ $this->files_template[$row['template_filename']] = $user->theme['template_id'];
+ }
+
+ if ($force_reload || $row['template_mtime'] < filemtime($file))
{
if ($row['template_filename'] == $this->filename[$handle])
{
- $compile->_tpl_load_file($handle);
+ $compile->_tpl_load_file($handle, true);
}
else
{
- $this->files[$row['template_filename']] = $this->root . '/' . $row['template_filename'];
- $compile->_tpl_load_file($row['template_filename']);
+ $this->files[$row['template_filename']] = $file;
+ $this->filename[$row['template_filename']] = $row['template_filename'];
+ $compile->_tpl_load_file($row['template_filename'], true);
unset($this->compiled_code[$row['template_filename']]);
unset($this->files[$row['template_filename']]);
unset($this->filename[$row['template_filename']]);
@@ -284,15 +360,22 @@ class template
}
}
}
- while ($row = $db->sql_fetchrow($result));
}
else
{
+ $file = $this->root . '/' . $row['template_filename'];
+
+ if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($file))
+ {
+ $file = $this->inherit_root . '/' . $row['template_filename'];
+ $this->files[$row['template_filename']] = $file;
+ $this->files_inherit[$row['template_filename']] = $file;
+ $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id'];
+ }
// Try to load from filesystem and instruct to insert into the styles table...
$compile->_tpl_load_file($handle, true);
return false;
}
- $db->sql_freeresult($result);
return false;
}
@@ -512,8 +595,12 @@ class template
$handle = $filename;
$this->filename[$handle] = $filename;
$this->files[$handle] = $this->root . '/' . $filename;
+ if ($this->inherit_root)
+ {
+ $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename;
+ }
- $filename = $this->_tpl_load($handle);
+ $filename = $this->_tpl_load($handle);
if ($include)
{
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index fb287299e5..296731c5f9 100644
--- a/phpBB/install/database_update.php
+++ b/phpBB/install/database_update.php
@@ -531,6 +531,17 @@ $database_update_info = array(
),
// No changes from 3.0.2-RC2 to 3.0.2
'3.0.2-RC2' => array(),
+
+ // Changes from 3.0.2 to the next version
+ '3.0.2' => array(
+ // Add the following columns
+ 'add_columns' => array(
+ STYLES_TEMPLATE_TABLE => array(
+ 'template_inherits_id' => array('UINT:4', 0),
+ 'template_inherit_path' => array('VCHAR', NULL),
+ ),
+ ),
+ ),
);
// Determine mapping database type
diff --git a/phpBB/language/en/acp/styles.php b/phpBB/language/en/acp/styles.php
index a6333fcba0..b3bd8300cd 100644
--- a/phpBB/language/en/acp/styles.php
+++ b/phpBB/language/en/acp/styles.php
@@ -86,6 +86,7 @@ $lang = array_merge($lang, array(
'DETAILS' => 'Details',
'DIMENSIONS_EXPLAIN' => 'Selecting yes here will include width/height parameters.',
+
'EDIT_DETAILS_IMAGESET' => 'Edit imageset details',
'EDIT_DETAILS_IMAGESET_EXPLAIN' => 'Here you can edit certain imageset details such as its name.',
'EDIT_DETAILS_STYLE' => 'Edit style',
@@ -103,6 +104,7 @@ $lang = array_merge($lang, array(
'EDIT_THEME_EXPLAIN' => 'Here you can edit the selected theme, changing colours, images, etc.',
'EDIT_THEME_STORED_DB' => 'The stylesheet file was unwritable so the stylesheet is now stored in the database containing your modification.',
'EDIT_THEME_STORE_PARSED' => 'The theme requires that its stylesheet is parsed. This is only possible if it’s stored in the database.',
+ 'EDITOR_DISABLED' => 'The template editor is disabled.',
'EXPORT' => 'Export',
'FOREGROUND' => 'Foreground',
@@ -269,6 +271,7 @@ $lang = array_merge($lang, array(
'INCLUDE_IMAGESET' => 'Include imageset',
'INCLUDE_TEMPLATE' => 'Include template',
'INCLUDE_THEME' => 'Include theme',
+ 'INHERITING_FROM' => 'Inherits from',
'INSTALL_IMAGESET' => 'Install imageset',
'INSTALL_IMAGESET_EXPLAIN' => 'Here you can install your selected imageset. You can edit certain details if you wish or use the installation defaults.',
'INSTALL_STYLE' => 'Install style',
@@ -284,6 +287,8 @@ $lang = array_merge($lang, array(
'LINE_SPACING' => 'Line spacing',
'LOCALISED_IMAGES' => 'Localised',
+ 'LOCATION_DISABLED_EXPLAIN' => 'This setting is inherited and cannot be changed.',
+
'NO_CLASS' => 'Cannot find class in stylesheet.',
'NO_IMAGESET' => 'Cannot find imageset on filesystem.',
@@ -364,6 +369,7 @@ $lang = array_merge($lang, array(
'TEMPLATE_CACHE_CLEARED' => 'Template cache cleared successfully.',
'TEMPLATE_CACHE_EMPTY' => 'There are no cached templates.',
'TEMPLATE_DELETED' => 'Template set deleted successfully.',
+ 'TEMPLATE_DELETE_DEPENDENT' => 'The template set cannot be deleted as there are one or more other template sets inheriting from it:',
'TEMPLATE_DELETED_FS' => 'Template set removed from database but some files may remain on the filesystem.',
'TEMPLATE_DETAILS_UPDATED' => 'Template details successfully updated.',
'TEMPLATE_EDITOR' => 'Raw HTML template editor',
@@ -375,12 +381,14 @@ $lang = array_merge($lang, array(
'TEMPLATE_ERR_NAME_EXIST' => 'A template set with that name already exists.',
'TEMPLATE_ERR_NAME_LONG' => 'The template name can be no longer than 30 characters.',
'TEMPLATE_ERR_NOT_TEMPLATE' => 'The archive you specified does not contain a valid template set.',
+ 'TEMPLATE_ERR_REQUIRED_OR_INCOMPLETE' => 'The new template set requires the template %s to be installed and not inheriting itself. ',
'TEMPLATE_ERR_STYLE_NAME' => 'You must supply a name for this template.',
'TEMPLATE_EXPORT' => 'Export templates',
'TEMPLATE_EXPORT_EXPLAIN' => 'Here you can export a template set in the form of an archive. This archive will contain all the files necessary to install the templates on another board. You may select whether to download the file directly or to place it in your store folder for download later or via FTP.',
'TEMPLATE_EXPORTED' => 'Templates exported successfully and stored in %s.',
'TEMPLATE_FILE' => 'Template file',
'TEMPLATE_FILE_UPDATED' => 'Template file updated successfully.',
+ 'TEMPLATE_INHERITS' => 'This template sets inherits from %s and thus cannot have a different storage setting than its super template.',
'TEMPLATE_LOCATION' => 'Store templates in',
'TEMPLATE_LOCATION_EXPLAIN' => 'Images are always stored on the filesystem.',
'TEMPLATE_NAME' => 'Template name',