From 0ebc5cc9eee8b4f904d624a8c4506ae6223ea5db Mon Sep 17 00:00:00 2001 From: David M Date: Thu, 12 Jun 2008 07:24:13 +0000 Subject: [PATCH] The beginnings of the destruction of phpBB's greatest bottleneck, dynamic css... As of phpBB 3.0.x, we take our "generic" CSS for a theme and later on combine it with the imagesets and languages as needed... What we did for 3.0.x involved dynamically resolving the variables in the CSS and then sending it off, caching it at several layers (except the one that mattered). The biggest issue with style.php is that it is one giant str_replace on every page load, no matter what; cache be damned. Instead, the trick is to cache the full compilation earlier on... Further work to do: kill all the old crap and fully integrate the new solution git-svn-id: file:///svn/phpbb/trunk@8649 89ea8834-ac86-4346-8a33-228a782c2dd0 --- phpBB/includes/acp/acp_styles.php | 117 ++++++++++++++++++++++++++++++ phpBB/includes/functions.php | 2 +- 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index e5002a3de6..80bc1eb935 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -1060,6 +1060,9 @@ parse_css_file = {PARSE_CSS_FILE} } $db->sql_freeresult($result); + $theme_info['theme_id'] = $theme_id; + self::generate_stylesheets($theme_info); + // save changes to the theme if the user submitted any if ($save_changes) { @@ -2856,6 +2859,120 @@ parse_css_file = {PARSE_CSS_FILE} } + function generate_stylesheets($theme) + { + global $db, $phpbb_root_path, $config; + + // get all the lang_dirs + $sql = 'SELECT lang_dir + FROM ' . LANG_TABLE; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $lang_dirs[] = $row['lang_dir']; + } + $db->sql_freeresult($result); + + // get all imagesets this theme is associated with + $sql = 'SELECT si.imageset_id, si.imageset_path, st.template_path + FROM ' . STYLES_TABLE . ' s, ' . STYLES_IMAGESET_TABLE . ' si, ' . STYLES_TEMPLATE_TABLE . ' st + WHERE s.theme_id = ' . (int) $theme['theme_id'] . ' + AND s.imageset_id = si.imageset_id + AND s.template_id = st.template_id'; + $result = $db->sql_query($sql); + while ($theme_row = $db->sql_fetchrow($result)) + { + foreach ($lang_dirs as $lang_dir) + { + $theme['imageset_path'] = $theme_row['imageset_path']; + $theme['imageset_id'] = $theme_row['imageset_id']; + $theme['template_path'] = $theme_row['template_path']; + + $user_image_lang = (file_exists($phpbb_root_path . 'styles/' . $theme['imageset_path'] . '/imageset/' . $lang_dir)) ? $lang_dir : $config['default_lang']; + + // Parse Theme Data + $replace = array( + '{T_THEME_PATH}' => "./styles/" . $theme['theme_path'] . '/theme', + '{T_TEMPLATE_PATH}' => "./styles/" . $theme['template_path'] . '/template', + '{T_IMAGESET_PATH}' => "./styles/" . $theme['imageset_path'] . '/imageset', + '{T_IMAGESET_LANG_PATH}' => "./styles/" . $theme['imageset_path'] . '/imageset/' . $user_image_lang, + '{T_STYLESHEET_NAME}' => $theme['theme_name'], + '{S_USER_LANG}' => $lang_dir // this bastard forces us to make a copy for every language that is installed, not just those with an actual i18'd imageset! + ); + + $sql = 'SELECT image_name, image_filename, image_lang, image_width, image_height + FROM ' . STYLES_IMAGESET_DATA_TABLE . ' + WHERE imageset_id = ' . $theme['imageset_id'] . " + AND image_filename <> '' + AND image_lang IN ('" . $db->sql_escape($user_image_lang) . "', '')"; + $result2 = $db->sql_query($sql); + + $img_array = array(); + while ($row = $db->sql_fetchrow($result2)) + { + $img_array[$row['image_name']] = $row; + } + $db->sql_freeresult($result2); + + $specific_theme_data = str_replace(array_keys($replace), array_values($replace), $theme['theme_data']); + + $matches = array(); + preg_match_all('#\{IMG_([A-Za-z0-9_]*?)_(WIDTH|HEIGHT|SRC)\}#', $specific_theme_data, $matches); + + $imgs = $find = $replace = array(); + if (isset($matches[0]) && sizeof($matches[0])) + { + foreach ($matches[1] as $i => $img) + { + $img = strtolower($img); + $find[] = $matches[0][$i]; + + if (!isset($img_array[$img])) + { + $replace[] = ''; + continue; + } + + if (!isset($imgs[$img])) + { + $img_data = &$img_array[$img]; + $imgsrc = ($img_data['image_lang'] ? $img_data['image_lang'] . '/' : '') . $img_data['image_filename']; + $imgs[$img] = array( + 'src' => $phpbb_root_path . 'styles/' . $theme['imageset_path'] . '/imageset/' . $imgsrc, + 'width' => $img_data['image_width'], + 'height' => $img_data['image_height'], + ); + } + + switch ($matches[2][$i]) + { + case 'SRC': + $replace[] = $imgs[$img]['src']; + break; + + case 'WIDTH': + $replace[] = $imgs[$img]['width']; + break; + + case 'HEIGHT': + $replace[] = $imgs[$img]['height']; + break; + + default: + continue; + } + } + + if (sizeof($find)) + { + $specific_theme_data = str_replace($find, $replace, $specific_theme_data); + } + } + file_put_contents($phpbb_root_path . '/store/' . $theme['theme_id'] . '_' . $theme['imageset_id'] . '_' . $lang_dir . '.css', $specific_theme_data, LOCK_EX); + } + } + $db->sql_freeresult($result); + } /** $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 3ef369aacf..ff16616863 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -3416,7 +3416,7 @@ function page_header($page_title = '', $display_online_list = true) 'T_ICONS_PATH' => PHPBB_ROOT_PATH . $config['icons_path'] . '/', 'T_RANKS_PATH' => PHPBB_ROOT_PATH . $config['ranks_path'] . '/', 'T_UPLOAD_PATH' => PHPBB_ROOT_PATH . $config['upload_path'] . '/', - 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? PHPBB_ROOT_PATH . 'styles/' . $user->theme['theme_path'] . '/theme/stylesheet.css' : PHPBB_ROOT_PATH . 'style.' . PHP_EXT . "?sid=$user->session_id&id=" . $user->theme['style_id'] . '&lang=' . $user->data['user_lang'], + 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? PHPBB_ROOT_PATH . 'styles/' . $user->theme['theme_path'] . '/theme/stylesheet.css' : PHPBB_ROOT_PATH . 'style.' . PHP_EXT . "?sid=$user->session_id&id=" . $user->theme['style_id'] . '&lang=' . $user->data['user_lang'], //"{$phpbb_root_path}store/{$user->theme['theme_id']}_{$user->theme['imageset_id']}_{$user->lang_name}.css" 'T_STYLESHEET_NAME' => $user->theme['theme_name'], 'SITE_LOGO_IMG' => $user->img('site_logo'))