';
}
loadTemplate($template_name);
}
// Cause an error otherwise.
elseif ($template_name != 'Errors' && $template_name != 'index' && $fatal)
fatal_lang_error('theme_template_error', 'template', array((string) $template_name));
elseif ($fatal)
die(log_error(sprintf(isset($txt['theme_template_error']) ? $txt['theme_template_error'] : 'Unable to load Themes/default/%s.template.php!', (string) $template_name), 'template'));
else
return false;
}
/**
* Load a sub-template.
* What it does:
* - loads the sub template specified by sub_template_name, which must be in an already-loaded template.
* - if ?debug is in the query string, shows administrators a marker after every sub template
* for debugging purposes.
*
* @todo get rid of reading $_REQUEST directly
*
* @param string $sub_template_name
* @param bool $fatal = false, $fatal = true is for templates that shouldn't get a 'pretty' error screen.
*/
function loadSubTemplate($sub_template_name, $fatal = false)
{
global $context, $settings, $options, $txt, $db_show_debug;
if ($db_show_debug === true)
$context['debug']['sub_templates'][] = $sub_template_name;
// Figure out what the template function is named.
$theme_function = 'template_' . $sub_template_name;
if (function_exists($theme_function))
$theme_function();
elseif ($fatal === false)
fatal_lang_error('theme_template_error', 'template', array((string) $sub_template_name));
elseif ($fatal !== 'ignore')
die(log_error(sprintf(isset($txt['theme_template_error']) ? $txt['theme_template_error'] : 'Unable to load the %s sub template!', (string) $sub_template_name), 'template'));
// Are we showing debugging for templates? Just make sure not to do it before the doctype...
if (allowedTo('admin_forum') && isset($_REQUEST['debug']) && !in_array($sub_template_name, array('init', 'main_below')) && ob_get_length() > 0 && !isset($_REQUEST['xml']))
{
echo '
---- ', $sub_template_name, ' ends ----
';
}
}
/**
* Add a CSS file for output later
*
* @param string $filename
* @param array $options
*/
function loadCSSFile($filename, $options = array())
{
global $settings, $context;
if (strpos($filename, 'http://') === false || !empty($options['local']))
$filename = $settings['theme_url'] . '/' . $filename;
$context['css_files'][$filename] = $options;
}
/**
* Add a Javascript file for output later
*
* @param string $filename
* @param array $options, possible parameters:
* - local (true/false): define if the file is local
* - default_theme (true/false): force use of default theme url
* - defer (true/false): define if the file should be load in head or before the closing tag
*/
function loadJavascriptFile($filename, $options = array())
{
global $settings, $context;
$theme = !empty($options['default_theme']) ? 'default_theme_url' : 'theme_url';
if (strpos($filename, 'http') === false || !empty($options['local']))
$filename = $settings[$theme] . '/' . $filename;
$context['javascript_files'][$filename] = $options;
}
/**
* Load a language file. Tries the current and default themes as well as the user and global languages.
*
* @param string $template_name
* @param string $lang
* @param bool $fatal = true
* @param bool $force_reload = false
* @return string The language actually loaded.
*/
function loadLanguage($template_name, $lang = '', $fatal = true, $force_reload = false)
{
global $user_info, $language, $settings, $context, $modSettings;
global $cachedir, $db_show_debug, $sourcedir, $txt;
static $already_loaded = array();
// Default to the user's language.
if ($lang == '')
$lang = isset($user_info['language']) ? $user_info['language'] : $language;
// Do we want the English version of language file as fallback?
if (empty($modSettings['disable_language_fallback']) && $lang != 'english')
loadLanguage($template_name, 'english', false);
if (!$force_reload && isset($already_loaded[$template_name]) && $already_loaded[$template_name] == $lang)
return $lang;
// Make sure we have $settings - if not we're in trouble and need to find it!
if (empty($settings['default_theme_dir']))
{
require_once($sourcedir . '/ScheduledTasks.php');
loadEssentialThemeData();
}
// What theme are we in?
$theme_name = basename($settings['theme_url']);
if (empty($theme_name))
$theme_name = 'unknown';
// For each file open it up and write it out!
foreach (explode('+', $template_name) as $template)
{
// Obviously, the current theme is most important to check.
$attempts = array(
array($settings['theme_dir'], $template, $lang, $settings['theme_url']),
array($settings['theme_dir'], $template, $language, $settings['theme_url']),
);
// Do we have a base theme to worry about?
if (isset($settings['base_theme_dir']))
{
$attempts[] = array($settings['base_theme_dir'], $template, $lang, $settings['base_theme_url']);
$attempts[] = array($settings['base_theme_dir'], $template, $language, $settings['base_theme_url']);
}
// Fall back on the default theme if necessary.
$attempts[] = array($settings['default_theme_dir'], $template, $lang, $settings['default_theme_url']);
$attempts[] = array($settings['default_theme_dir'], $template, $language, $settings['default_theme_url']);
// Fall back on the English language if none of the preferred languages can be found.
if (!in_array('english', array($lang, $language)))
{
$attempts[] = array($settings['theme_dir'], $template, 'english', $settings['theme_url']);
$attempts[] = array($settings['default_theme_dir'], $template, 'english', $settings['default_theme_url']);
}
// Try to find the language file.
$found = false;
foreach ($attempts as $k => $file)
{
if (file_exists($file[0] . '/languages/' . $file[1] . '.' . $file[2] . '.php'))
{
// Include it!
template_include($file[0] . '/languages/' . $file[1] . '.' . $file[2] . '.php');
// Note that we found it.
$found = true;
break;
}
}
// That couldn't be found! Log the error, but *try* to continue normally.
if (!$found && $fatal)
{
log_error(sprintf($txt['theme_language_error'], $template_name . '.' . $lang, 'template'));
break;
}
// For the sake of backward compatibility
if (!empty($txt['emails']))
{
foreach ($txt['emails'] as $key => $value)
{
$txt[$key . '_subject'] = $value['subject'];
$txt[$key . '_body'] = $value['body'];
}
$txt['emails'] = array();
}
if (!empty($birthdayEmails))
{
foreach ($birthdayEmails as $key => $value)
{
$txtBirthdayEmails[$key . '_subject'] = $value['subject'];
$txtBirthdayEmails[$key . '_body'] = $value['body'];
$txtBirthdayEmails[$key . '_author'] = $value['author'];
}
$birthdayEmails = array();
}
}
// Keep track of what we're up to soldier.
if ($db_show_debug === true)
$context['debug']['language_files'][] = $template_name . '.' . $lang . ' (' . $theme_name . ')';
// Remember what we have loaded, and in which language.
$already_loaded[$template_name] = $lang;
// Return the language actually loaded.
return $lang;
}
/**
* Get all parent boards (requires first parent as parameter)
* It finds all the parents of id_parent, and that board itself.
* Additionally, it detects the moderators of said boards.
*
* @param int $id_parent
* @return an array of information about the boards found.
*/
function getBoardParents($id_parent)
{
global $scripturl, $smcFunc;
// First check if we have this cached already.
if (($boards = cache_get_data('board_parents-' . $id_parent, 480)) === null)
{
$boards = array();
$original_parent = $id_parent;
// Loop while the parent is non-zero.
while ($id_parent != 0)
{
$result = $smcFunc['db_query']('', '
SELECT
b.id_parent, b.name, {int:board_parent} AS id_board, IFNULL(mem.id_member, 0) AS id_moderator,
mem.real_name, b.child_level
FROM {db_prefix}boards AS b
LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_board = b.id_board)
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member)
WHERE b.id_board = {int:board_parent}',
array(
'board_parent' => $id_parent,
)
);
// In the EXTREMELY unlikely event this happens, give an error message.
if ($smcFunc['db_num_rows']($result) == 0)
fatal_lang_error('parent_not_found', 'critical');
while ($row = $smcFunc['db_fetch_assoc']($result))
{
if (!isset($boards[$row['id_board']]))
{
$id_parent = $row['id_parent'];
$boards[$row['id_board']] = array(
'url' => $scripturl . '?board=' . $row['id_board'] . '.0',
'name' => $row['name'],
'level' => $row['child_level'],
'moderators' => array()
);
}
// If a moderator exists for this board, add that moderator for all children too.
if (!empty($row['id_moderator']))
foreach ($boards as $id => $dummy)
{
$boards[$id]['moderators'][$row['id_moderator']] = array(
'id' => $row['id_moderator'],
'name' => $row['real_name'],
'href' => $scripturl . '?action=profile;u=' . $row['id_moderator'],
'link' => '' . $row['real_name'] . ''
);
}
}
$smcFunc['db_free_result']($result);
}
cache_put_data('board_parents-' . $original_parent, $boards, 480);
}
return $boards;
}
/**
* Attempt to reload our known languages.
* It will try to choose only utf8 or non-utf8 languages.
*
* @param bool $use_cache = true
* @param bool $favor_utf8 = true
* @return array
*/
function getLanguages($use_cache = true, $favor_utf8 = true)
{
global $context, $smcFunc, $settings, $modSettings;
// Either we don't use the cache, or its expired.
if (!$use_cache || ($context['languages'] = cache_get_data('known_languages' . ($favor_utf8 ? '' : '_all'), !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600)) == null)
{
// If we don't have our theme information yet, lets get it.
if (empty($settings['default_theme_dir']))
loadTheme(0, false);
// Default language directories to try.
$language_directories = array(
$settings['default_theme_dir'] . '/languages',
$settings['actual_theme_dir'] . '/languages',
);
// We possibly have a base theme directory.
if (!empty($settings['base_theme_dir']))
$language_directories[] = $settings['base_theme_dir'] . '/languages';
// Remove any duplicates.
$language_directories = array_unique($language_directories);
foreach ($language_directories as $language_dir)
{
// Can't look in here... doesn't exist!
if (!file_exists($language_dir))
continue;
$dir = dir($language_dir);
while ($entry = $dir->read())
{
// Look for the index language file....
if (!preg_match('~^index\.(.+)\.php$~', $entry, $matches))
continue;
$context['languages'][$matches[1]] = array(
'name' => $smcFunc['ucwords'](strtr($matches[1], array('_' => ' '))),
'selected' => false,
'filename' => $matches[1],
'location' => $language_dir . '/index.' . $matches[1] . '.php',
);
}
$dir->close();
}
// Favoring UTF8? Then prevent us from selecting non-UTF8 versions.
if ($favor_utf8)
{
foreach ($context['languages'] as $lang)
if (substr($lang['filename'], strlen($lang['filename']) - 5, 5) != '-utf8' && isset($context['languages'][$lang['filename'] . '-utf8']))
unset($context['languages'][$lang['filename']]);
}
// Lets cash in on this deal.
if (!empty($modSettings['cache_enable']))
cache_put_data('known_languages' . ($favor_utf8 ? '' : '_all'), $context['languages'], !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
}
return $context['languages'];
}
/**
* Replace all vulgar words with respective proper words. (substring or whole words..)
* What this function does:
* - it censors the passed string.
* - if the theme setting allow_no_censored is on, and the theme option
* show_no_censored is enabled, does not censor, unless force is also set.
* - it caches the list of censored words to reduce parsing.
*
* @param string &$text
* @param bool $force = false
* @return string The censored text
*/
function censorText(&$text, $force = false)
{
global $modSettings, $options, $settings, $txt;
static $censor_vulgar = null, $censor_proper;
if ((!empty($options['show_no_censored']) && $settings['allow_no_censored'] && !$force) || empty($modSettings['censor_vulgar']) || trim($text) === '')
return $text;
// If they haven't yet been loaded, load them.
if ($censor_vulgar == null)
{
$censor_vulgar = explode("\n", $modSettings['censor_vulgar']);
$censor_proper = explode("\n", $modSettings['censor_proper']);
// Quote them for use in regular expressions.
if (!empty($modSettings['censorWholeWord']))
{
for ($i = 0, $n = count($censor_vulgar); $i < $n; $i++)
{
$censor_vulgar[$i] = str_replace(array('\\\\\\*', '\\*', '&', '\''), array('[*]', '[^\s]*?', '&', '''), preg_quote($censor_vulgar[$i], '/'));
$censor_vulgar[$i] = '/(?<=^|\W)' . $censor_vulgar[$i] . '(?=$|\W)/' . (empty($modSettings['censorIgnoreCase']) ? '' : 'i') . ((empty($modSettings['global_character_set']) ? $txt['lang_character_set'] : $modSettings['global_character_set']) === 'UTF-8' ? 'u' : '');
// @todo I'm thinking the old way is some kind of bug and this is actually fixing it.
//if (strpos($censor_vulgar[$i], '\'') !== false)
//$censor_vulgar[$i] = str_replace('\'', ''', $censor_vulgar[$i]);
}
}
}
// Censoring isn't so very complicated :P.
if (empty($modSettings['censorWholeWord']))
$text = empty($modSettings['censorIgnoreCase']) ? str_ireplace($censor_vulgar, $censor_proper, $text) : str_replace($censor_vulgar, $censor_proper, $text);
else
$text = preg_replace($censor_vulgar, $censor_proper, $text);
return $text;
}
/**
* Load the template/language file using eval or require? (with eval we can show an error message!)
* - loads the template or language file specified by filename.
* - uses eval unless disableTemplateEval is enabled.
* - outputs a parse error if the file did not exist or contained errors.
* - attempts to detect the error and line, and show detailed information.
*
* @param string $filename
* @param bool $once = false, if true only includes the file once (like include_once)
*/
function template_include($filename, $once = false)
{
global $context, $settings, $options, $txt, $scripturl, $modSettings;
global $user_info, $boardurl, $boarddir, $sourcedir;
global $maintenance, $mtitle, $mmessage;
static $templates = array();
// We want to be able to figure out any errors...
@ini_set('track_errors', '1');
// Don't include the file more than once, if $once is true.
if ($once && in_array($filename, $templates))
return;
// Add this file to the include list, whether $once is true or not.
else
$templates[] = $filename;
// Are we going to use eval?
if (empty($modSettings['disableTemplateEval']))
{
$file_found = file_exists($filename) && eval('?' . '>' . rtrim(file_get_contents($filename))) !== false;
$settings['current_include_filename'] = $filename;
}
else
{
$file_found = file_exists($filename);
if ($once && $file_found)
require_once($filename);
elseif ($file_found)
require($filename);
}
if ($file_found !== true)
{
ob_end_clean();
if (!empty($modSettings['enableCompressedOutput']))
@ob_start('ob_gzhandler');
else
ob_start();
if (isset($_GET['debug']) && !WIRELESS)
header('Content-Type: application/xhtml+xml; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set']));
// Don't cache error pages!!
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-cache');
if (!isset($txt['template_parse_error']))
{
$txt['template_parse_error'] = 'Template Parse Error!';
$txt['template_parse_error_message'] = 'It seems something has gone sour on the forum with the template system. This problem should only be temporary, so please come back later and try again. If you continue to see this message, please contact the administrator.
You can also try refreshing this page.';
$txt['template_parse_error_details'] = 'There was a problem loading the %1$s template or language file. Please check the syntax and try again - remember, single quotes (\') often have to be escaped with a slash (\\). To see more specific error information from PHP, try accessing the file directly.
You may want to try to refresh this page or use the default theme.';
}
// First, let's get the doctype and language information out of the way.
echo '
';
if (isset($context['character_set']))
echo '
';
if (!empty($maintenance) && !allowedTo('admin_forum'))
echo '
', $mtitle, '