aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/includes')
-rw-r--r--phpBB/includes/acp/acp_styles.php472
1 files changed, 123 insertions, 349 deletions
diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php
index 61d7d51efc..4f61027a09 100644
--- a/phpBB/includes/acp/acp_styles.php
+++ b/phpBB/includes/acp/acp_styles.php
@@ -820,7 +820,7 @@ parse_css_file = {PARSE_CSS_FILE}
// we don't need any single element categories so put them into the misc '' category
for ($i = 0, $n = sizeof($cats); $i < $n; $i++)
{
- if (sizeof($filelist_cats[$cats[$i]]) == 1)
+ if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '')
{
$filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]);
unset($filelist_cats[$cats[$i]]);
@@ -858,6 +858,15 @@ parse_css_file = {PARSE_CSS_FILE}
'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$template_id&amp;text_rows=$text_rows",
'U_BACK' => $this->u_action,
+ 'L_EDIT' => $user->lang['EDIT_TEMPLATE'],
+ 'L_EDIT_EXPLAIN' => $user->lang['EDIT_TEMPLATE_EXPLAIN'],
+ 'L_EDITOR' => $user->lang['TEMPLATE_EDITOR'],
+ 'L_EDITOR_HEIGHT' => $user->lang['TEMPLATE_EDITOR_HEIGHT'],
+ 'L_FILE' => $user->lang['TEMPLATE_FILE'],
+ 'L_SELECT' => $user->lang['SELECT_TEMPLATE'],
+ 'L_SELECTED' => $user->lang['SELECTED_TEMPLATE'],
+ 'L_SELECTED_FILE' => $user->lang['SELECTED_TEMPLATE_FILE'],
+
'SELECTED_TEMPLATE' => $template_info['template_name'],
'TEMPLATE_FILE' => $template_file,
'TEMPLATE_DATA' => htmlspecialchars($template_data),
@@ -998,27 +1007,23 @@ parse_css_file = {PARSE_CSS_FILE}
*/
function edit_theme($theme_id)
{
- global $phpbb_root_path, $phpbb_admin_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
+ global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
$this->page_title = 'EDIT_THEME';
+ $filelist = $filelist_cats = array();
+
// we want newlines no carriage returns!
- $_POST['css_data'] = (isset($_POST['css_data']) && !empty($_POST['css_data'])) ? str_replace(array("\r\n", "\r"), array("\n", "\n"), $_POST['css_data']) : '';
+ $_POST['template_data'] = (isset($_POST['template_data']) && !empty($_POST['template_data'])) ? str_replace(array("\r\n", "\r"), array("\n", "\n"), $_POST['template_data']) : '';
- // get user input
+ $theme_data = (STRIP) ? stripslashes($_POST['template_data']) : $_POST['template_data'];
+ $theme_file = request_var('template_file', '');
$text_rows = max(5, min(999, request_var('text_rows', 20)));
- $hide_css = request_var('hidecss', false);
- $show_css = !$hide_css && request_var('showcss', false);
- $edit_class = request_var('css_class', '');
- $custom_class = request_var('custom_class', '');
- $css_data = (STRIP) ? stripslashes($_POST['css_data']) : $_POST['css_data'];
- $submit = isset($_POST['submit']) ? true : false;
- $add_custom = isset($_POST['add_custom']) ? true : false;
- $matches = array();
-
- // no curly brackets inside a CSS block please
- $css_data = str_replace(array('{', '}'), '', $css_data);
+ $save_changes = (isset($_POST['save'])) ? true : false;
+ // make sure theme_file path doesn't go upwards
+ $theme_file = str_replace('..', '.', $theme_file);
+
// Retrieve some information about the theme
$sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data
FROM ' . STYLES_THEME_TABLE . "
@@ -1031,383 +1036,152 @@ parse_css_file = {PARSE_CSS_FILE}
}
$db->sql_freeresult($result);
- $stylesheet_path = $phpbb_root_path . 'styles/' . $theme_info['theme_path'] . '/theme/stylesheet.css';
- // Get the CSS data from either database or filesystem
- if (!$theme_info['theme_storedb'])
+ // save changes to the theme if the user submitted any
+ if ($save_changes)
{
- if (!file_exists($stylesheet_path) || !($stylesheet = file_get_contents($stylesheet_path)))
- {
- trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
- }
- else
- {
- $stylesheet = &$theme_info['theme_data'];
- }
-
- // Pull out a list of classes
- $classes = array();
- if (preg_match_all('/^([a-z0-9\.,:#_\->* \t]+?)[ \t\n]*?\{.*?\}/msi', $stylesheet, $matches))
- {
- $classes = $matches[1];
- }
-
- // Generate html for the list of classes
- $s_hidden_fields = array();
- $s_classes = '';
- sort($classes);
- foreach ($classes as $class)
- {
- $selected = ($class == $edit_class) ? ' selected="selected"' : '';
- $s_classes .= '<option value="' . $class . '" title="' . $class . '"' . $selected . '>' . truncate_string($class, 40, false, '...') . '</option>';
- }
-
- $template->assign_vars(array(
- 'S_EDIT_THEME' => true,
- 'S_SHOWCSS' => $show_css,
- 'S_CLASSES' => $s_classes,
- 'S_CLASS' => $edit_class,
-
- 'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;showcss=$show_css&amp;text_rows=$text_rows",
- 'U_BACK' => $this->u_action,
-
- 'SELECTED_THEME' => $theme_info['theme_name'],
- 'TEXT_ROWS' => $text_rows)
- );
-
- // only continue if we are really editing anything
- if (!$edit_class && !$add_custom)
- {
- return;
- }
-
- // These are the elements for the simple view
- $match_elements = array(
- 'colors' => array('background-color', 'color',),
- 'sizes' => array('font-size', 'line-height',),
- 'images' => array('background-image',),
- 'repeat' => array('background-repeat',),
- 'other' => array('font-weight', 'font-family', 'font-style', 'text-decoration',),
- );
-
- // Used in an sprintf statement to generate appropriate output for rawcss mode
- $map_elements = array(
- 'colors' => '%s',
- 'sizes' => '%1.10f',
- 'images' => 'url(\'./%s\')',
- 'repeat' => '%s',
- 'other' => '%s',
- );
-
- $units = array('px', '%', 'em', 'pt');
- $repeat_types = array(
- '' => $user->lang['UNSET'],
- 'none' => $user->lang['REPEAT_NO'],
- 'repeat-x' => $user->lang['REPEAT_X'],
- 'repeat-y' => $user->lang['REPEAT_Y'],
- 'both' => $user->lang['REPEAT_ALL'],
- );
-
- // Fill css_data with the class contents from the stylesheet
- // in case we just selected a class and it's not filled yet
- if (!$css_data && !$submit && !isset($_POST['hidecss']) && !isset($_POST['showcss']) && !$add_custom)
- {
- preg_match('#^[ \t]*?' . preg_quote($edit_class, '#') . '[ \t\n]*?\{(.*?)\}#ms', $stylesheet, $matches);
+ // Get the filesystem location of the current file
+ $file = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme/$theme_file";
+ $additional = '';
+ $message = $user->lang['THEME_UPDATED'];
- if (!isset($matches[1]))
+ // If the theme is stored on the filesystem try to write the file else store it in the database
+ if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($file) && @is_writable($file))
{
- trigger_error($user->lang['NO_CLASS'] . adm_back_link($this->u_action), E_USER_WARNING);
+ if (!($fp = fopen($file, 'wb')))
+ {
+ trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+ fwrite($fp, $theme_data);
+ fclose($fp);
}
-
- $css_data = implode(";\n", array_diff(array_map('trim', explode("\n", preg_replace("#;[\n]*#s", "\n", $matches[1]))), array('')));
- if ($css_data)
+ else
{
- $css_data .= ';';
- }
- }
-
- // If we don't show raw css and the user did not submit any modification
- // then generate a list of css elements and output them via the template
- if (!$show_css && !$submit && !$add_custom)
- {
- $css_elements = array_diff(array_map('trim', explode("\n", preg_replace("#;[\n]*#s", "\n", $css_data))), array(''));
+ // Write stylesheet to db
+ $sql_ary = array(
+ 'theme_mtime' => time(),
+ 'theme_storedb' => 1,
+ 'theme_data' => $this->db_theme_data($theme_info, $theme_data),
+ );
+ $sql = 'UPDATE ' . STYLES_THEME_TABLE . '
+ SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
+ WHERE theme_id = ' . $theme_id;
+ $db->sql_query($sql);
- // Grab list of potential images for the "images" type
- $img_filelist = filelist($phpbb_root_path . 'styles/' . $theme_info['theme_name'] . '/theme');
+ $cache->destroy('sql', STYLES_THEME_TABLE);
- foreach ($match_elements as $type => $match_ary)
- {
- foreach ($match_ary as $match)
+ // notify the user if the theme was not stored in the db before his modification
+ if (!$theme_info['theme_storedb'])
{
- $var = str_replace('-', '_', $match);
- $value = '';
- $unit = '';
-
- if (sizeof($css_elements))
- {
- // first read in the setting
- foreach ($css_elements as $key => $element)
- {
- if (preg_match('#^' . preg_quote($match, '#') . ':[ \t\n]*?(.*?)$#', $element, $matches))
- {
- switch ($type)
- {
- case 'sizes':
- $value = trim($matches[1]);
-
- if (preg_match('#(.*?)(px|%|em|pt)#', $matches[1], $matches))
- {
- $unit = trim($matches[2]);
- $value = trim($matches[1]);
- }
- break;
-
- case 'images':
- if (preg_match('#url\(\'(.*?)\'\)#', $matches[1], $matches))
- {
- $value = trim($matches[1]);
- }
- break;
-
- case 'colors':
- $value = trim($matches[1]);
- if ($value[0] == '#')
- {
- $value = substr($value, 1);
- }
- break;
-
- default:
- $value = trim($matches[1]);
- }
-
- // Remove this element from array
- unset($css_elements[$key]);
- break;
- }
- }
- }
-
- // then display it in the template
- switch ($type)
- {
- case 'sizes':
- // generate a list of units
- $s_units = '';
- foreach ($units as $unit_option)
- {
- $selected = ($unit_option == $unit) ? ' selected="selected"' : '';
- $s_units .= "<option value=\"$unit_option\"$selected>$unit_option</option>";
- }
- $s_units = '<option value=""' . (($unit == '') ? ' selected="selected"' : '') . '>' . $user->lang['NO_UNIT'] . '</option>' . $s_units;
-
- $template->assign_vars(array(
- strtoupper($var) => htmlspecialchars($value),
- 'S_' . strtoupper($var) . '_UNITS' => $s_units)
- );
- break;
-
- case 'images':
- // generate a list of images for this setting
- $s_imglist = '';
- foreach ($img_filelist as $path => $img_ary)
- {
- foreach ($img_ary as $img)
- {
- $img = htmlspecialchars(((substr($path, 0, 1) == '/') ? substr($path, 1) : $path) . $img);
-
- $selected = (preg_match('#' . preg_quote($img) . '$#', $value)) ? ' selected="selected"' : '';
- $s_imglist .= "<option value=\"$img\"$selected>$img</option>";
- }
- }
- $s_imglist = '<option value=""' . (($value == '') ? ' selected="selected"' : '') . '>' . $user->lang['NO_IMAGE'] . '</option>' . $s_imglist;
-
- $template->assign_vars(array(
- 'S_' . strtoupper($var) => $s_imglist)
- );
- unset($s_imglist);
- break;
-
- case 'repeat':
- // generate a list of repeat options
- $s_repeat_types = '';
- foreach ($repeat_types as $repeat_type => $repeat_lang)
- {
- $selected = ($value == $repeat_type) ? ' selected="selected"' : '';
- $s_repeat_types .= "<option value=\"$repeat_type\"$selected>$repeat_lang</option>";
- }
-
- $template->assign_vars(array(
- 'S_' . strtoupper($var) => $s_repeat_types)
- );
-
- default:
- $template->assign_vars(array(
- strtoupper($var) => htmlspecialchars($value))
- );
- }
+ add_log('admin', 'LOG_THEME_EDIT_DETAILS', $theme_info['theme_name']);
+ $message .= '<br />' . $user->lang['EDIT_THEME_STORED_DB'];
}
}
+ $cache->destroy('sql', STYLES_THEME_TABLE);
+ add_log('admin', (!$theme_info['theme_storedb']) ? 'LOG_THEME_EDIT_FILE' : 'LOG_THEME_EDIT', $theme_info['theme_name'], (!$theme_info['theme_storedb']) ? $theme_file : '');
- // Any remaining elements must be custom data so we save that in a hidden field
- if (sizeof($css_elements))
- {
- $s_hidden_fields['cssother'] = implode(' ;; ', $css_elements);
- }
-
- unset($img_filelist, $css_elements);
+ trigger_error($message . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;template_file=$theme_file&amp;text_rows=$text_rows"));
}
- // else if we are showing raw css or the user submitted data from the simple view
- // then we need to turn the given information into raw css
- else if (!$css_data && !$add_custom)
- {
- foreach ($match_elements as $type => $match_ary)
- {
- foreach ($match_ary as $match)
- {
- $var = str_replace('-', '_', $match);
- $value = '';
- $unit = '';
-
- // retrieve and validate data for this setting
- switch ($type)
- {
- case 'sizes':
- $value = request_var($var, 0.0);
- $unit = request_var($var . '_unit', '');
-
- if ((request_var($var, '') === '') || !in_array($unit, $units))
- {
- $value = '';
- }
- break;
-
- case 'images':
- $value = str_replace('..', '.', request_var($var, ''));
- if (!file_exists("{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme/" . $value))
- {
- $value = '';
- }
- break;
-
- case 'colors':
- $value = request_var($var, '');
- if (preg_match('#^(?:[A-F0-9]{6}|[A-F0-9]{3})$#', $value))
- {
- $value = '#' . $value;
- }
- break;
-
- case 'repeat':
- $value = request_var($var, '');
- if (!isset($repeat_types[$value]))
- {
- $value = '';
- }
- break;
- default:
- $value = htmlspecialchars_decode(request_var($var, ''));
- }
+ // Generate a category array containing theme filenames
+ if (!$theme_info['theme_storedb'])
+ {
+ $theme_path = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme";
- // use the element mapping to create raw css code
- if ($value !== '')
- {
- $css_data .= $match . ': ' . ($type == 'sizes' ? rtrim(sprintf($map_elements[$type], $value), '0') : sprintf($map_elements[$type], $value)) . $unit . ";\n";
- }
- }
- }
+ $filelist = filelist($theme_path, '', 'css');
- // append additional data sent to us
- if ($other = request_var('cssother', ''))
+ if ($theme_file)
{
- $css_data .= str_replace(' ;; ', ";\n", $other) . ';';
- $css_data = preg_replace("#\*/;\n#", "*/\n", $css_data);
+ if (!file_exists($theme_path . "/$theme_file") || !($theme_data = file_get_contents($theme_path . "/$theme_file")))
+ {
+ trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
}
}
- // make sure we have $show_css set, so we can link to the show_css page if we need to
- else if (!$hide_css)
+ else
{
- $show_css = true;
+ $theme_data = &$theme_info['theme_data'];
}
- if ($submit || $add_custom)
+ // Now create the categories
+ $filelist_cats[''] = array();
+ foreach ($filelist as $pathfile => $file_ary)
{
- if ($submit)
+ // Use the directory name as category name
+ if (!empty($pathfile))
{
- // if the user submitted a modification replace the old class definition in the stylesheet
- // with the new one
- if (preg_match('#^' . preg_quote($edit_class, '#') . '[ \t\n]*?\{(.*?)\}#ms', $stylesheet))
+ $filelist_cats[$pathfile] = array();
+ foreach ($file_ary as $file)
{
- $stylesheet = preg_replace('#^(' . preg_quote($edit_class, '#') . '[ \t\n]*?\{).*?(\})#ms', "$1\n\t" . str_replace("\n", "\n\t", $css_data) . "\n$2", $stylesheet);
+ $filelist_cats[$pathfile][$pathfile . $file] = $file;
}
- $message = $user->lang['THEME_UPDATED'];
}
+ // or if it's in the main category use the word before the first underscore to group files
else
{
- // check whether the custom class name is valid
- if (!preg_match('/^[a-z0-9\.,:#_\ \t->*]+$/i', $custom_class))
- {
- trigger_error($user->lang['THEME_ERR_CLASS_CHARS'] . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;text_rows=$text_rows"), E_USER_WARNING);
- }
- else
+ $cats = array();
+ foreach ($file_ary as $file)
{
- // append an empty class definition to the stylesheet
- $stylesheet .= "\n$custom_class {\n\t\n}";
- $message = $user->lang['THEME_CLASS_ADDED'];
+ $cats[] = substr($file, 0, strpos($file, '_'));
+ $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file;
}
- }
- // where should we store the CSS?
- if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($stylesheet_path) && @is_writable($stylesheet_path))
- {
- // write stylesheet to file
- if (!($fp = fopen($stylesheet_path, 'wb')))
+ $cats = array_values(array_unique($cats));
+
+ // we don't need any single element categories so put them into the misc '' category
+ for ($i = 0, $n = sizeof($cats); $i < $n; $i++)
{
- trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
+ if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '')
+ {
+ $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]);
+ unset($filelist_cats[$cats[$i]]);
+ }
}
- fwrite($fp, $stylesheet);
- fclose($fp);
+ unset($cats);
}
- else
- {
- // Write stylesheet to db
- $sql_ary = array(
- 'theme_mtime' => time(),
- 'theme_storedb' => 1,
- 'theme_data' => $this->db_theme_data($theme_info, $stylesheet),
- );
- $sql = 'UPDATE ' . STYLES_THEME_TABLE . '
- SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
- WHERE theme_id = ' . $theme_id;
- $db->sql_query($sql);
+ }
+ unset($filelist);
- $cache->destroy('sql', STYLES_THEME_TABLE);
+ // Generate list of categorised theme files
+ $tpl_options = '';
+ ksort($filelist_cats);
+ foreach ($filelist_cats as $category => $tpl_ary)
+ {
+ ksort($tpl_ary);
- // notify the user if the template was not stored in the db before his modification
- if (!$theme_info['theme_storedb'])
- {
- add_log('admin', 'LOG_THEME_EDIT_DETAILS', $theme_info['theme_name']);
- $message .= '<br />' . $user->lang['EDIT_THEME_STORED_DB'];
- }
+ if (!empty($category))
+ {
+ $tpl_options .= '<option class="sep" value="">' . $category . '</option>';
}
- $cache->destroy('sql', STYLES_THEME_TABLE);
- add_log('admin', ($add_custom) ? 'LOG_THEME_EDIT_ADD' : 'LOG_THEME_EDIT', $theme_info['theme_name'], ($add_custom) ? $custom_class : $edit_class);
-
- trigger_error($message . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;css_class=$edit_class&amp;showcss=$show_css&amp;text_rows=$text_rows"));
+ foreach ($tpl_ary as $filename => $file)
+ {
+ $selected = ($theme_file == $filename) ? ' selected="selected"' : '';
+ $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>';
+ }
}
- unset($matches);
-
- $s_hidden_fields['css_class'] = $edit_class;
$template->assign_vars(array(
- 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields),
+ 'S_EDIT_THEME' => true,
+ 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $theme_file)),
+ 'S_THEME_IN_DB' => $theme_info['theme_storedb'],
+ 'S_TEMPLATES' => $tpl_options,
- 'U_SWATCH' => append_sid("{$phpbb_admin_path}swatch.$phpEx", 'form=acp_theme') . '&amp;name=',
- 'UA_SWATCH' => append_sid("{$phpbb_admin_path}swatch.$phpEx", 'form=acp_theme', false) . '&name=',
+ 'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;text_rows=$text_rows",
+ 'U_BACK' => $this->u_action,
- 'CSS_DATA' => htmlspecialchars($css_data))
+ 'L_EDIT' => $user->lang['EDIT_THEME'],
+ 'L_EDIT_EXPLAIN' => $user->lang['EDIT_THEME_EXPLAIN'],
+ 'L_EDITOR' => $user->lang['THEME_EDITOR'],
+ 'L_EDITOR_HEIGHT' => $user->lang['THEME_EDITOR_HEIGHT'],
+ 'L_FILE' => $user->lang['THEME_FILE'],
+ 'L_SELECT' => $user->lang['SELECT_THEME'],
+ 'L_SELECTED' => $user->lang['SELECTED_THEME'],
+ 'L_SELECTED_FILE' => $user->lang['SELECTED_THEME_FILE'],
+
+ 'SELECTED_TEMPLATE' => $theme_info['theme_name'],
+ 'TEMPLATE_FILE' => $theme_file,
+ 'TEMPLATE_DATA' => htmlspecialchars($theme_data),
+ 'TEXT_ROWS' => $text_rows)
);
}