eesyphp/includes/smarty.php
Benjamin Renard 6fdc5447f1 Some improvments from recent works on apps based on its "framework"
* Code cleaning and fix some small errors using Phpstan
* Configure pre-commit to run Phpstan before each commit
* Some little improvments and logging, mail, smarty & URL libs
* Add Sentry integration
* Add Webstat JS code inclusion
* Install Smarty dependency using composer

Breaking changes:
* Rename Event class as HookEvent to avoid conflict with PECL event
* URL with refresh GET parameter now automatically trigger redirection without it
 after page loading to avoid to keep it in URL
2023-01-29 11:51:41 +01:00

324 lines
9.3 KiB
PHP

<?php
if (php_sapi_name() == "cli")
return true;
$smarty = new Smarty();
/*
* Configure Smarty regarding the installed version
*/
if (method_exists($smarty,'register_function')) {
$_smarty_version = 2;
function smarty_enable_security_mode($functions=array(), $modifiers=array()) {
global $smarty;
// Enable security
$smarty -> security = True;
// Allow functions in IF clauses
foreach($functions as $function)
$smarty -> security_settings['IF_FUNCS'][] = $function;
// Allow modifier functions
foreach($modifiers as $modifier)
$smarty -> security_settings['MODIFIER_FUNCS'][] = $modifier;
}
function smarty_register_function($func_name, $func) {
global $smarty;
$smarty -> register_function($func_name, $func);
}
}
elseif (method_exists($smarty,'registerPlugin')) {
$_smarty_version = 3;
function smarty_enable_security_mode($functions=array(), $modifiers=array()) {
global $smarty;
// Define security policy
$smarty_security_policy = new Smarty_Security($smarty);
// Allow functions in IF clauses
foreach($functions as $function)
$smarty_security_policy->php_functions[] = $function;
// Allow modifier functions
foreach($modifiers as $modifier)
$smarty_security_policy->php_modifiers[] = $modifier;
// Enable security
$smarty->enableSecurity($smarty_security_policy);
}
function smarty_register_function($func_name, $func) {
global $smarty;
$smarty -> registerPlugin("function", $func_name, $func);
}
}
else {
logging('FATAL', _('Smarty version not supported.'));
}
// Configure templates/templates_c directories
if (
!isset($smarty_templates_dir)
|| !is_dir($smarty_templates_dir)
)
logging(
'FATAL', "Template directory not found (%s)",
isset($smarty_templates_dir)?$smarty_templates_dir:'not set');
else
$smarty->setTemplateDir($smarty_templates_dir);
if (
!isset($smarty_templates_c_dir)
|| !is_dir($smarty_templates_c_dir)
|| !is_writable($smarty_templates_c_dir)
)
logging(
'FATAL', "Template cache directory not found or not writable (%s)",
isset($smarty_templates_c_dir)?$smarty_templates_c_dir:'not set');
else
$smarty->setCompileDir($smarty_templates_c_dir);
// Enable Smarty security
smarty_enable_security_mode(
// Allow some functions in IF clauses
array(
'isset', 'empty', 'count', 'in_array', 'is_array', 'array_key_exists', 'is_null',
'can_modify', 'can_archive', 'can_delete'
),
// Allow some modifier functions
array('range', 'implode', 'stripslashes')
);
// Defined some global template variables
$smarty->assign('public_root_url', isset($public_root_url)?$public_root_url:'/');
$smarty->assign('main_pagetitle', isset($main_pagetitle)?$main_pagetitle:null);
$smarty->assign('session_key', $_SESSION['session_key']);
// Handle in-page errors & messages
if (!isset($_SESSION['errors']))
$_SESSION['errors'] = array();
function add_error($error) {
// If more than one arguments passed, format error message using sprintf
if (func_num_args() > 1) {
$error = call_user_func_array(
'sprintf',
array_merge(array($error), array_slice(func_get_args(), 1))
);
}
$_SESSION['errors'][] = $error;
}
if (!isset($_SESSION['messages']))
$_SESSION['messages'] = array();
function add_message($message) {
// If more than one arguments passed, format message using sprintf
if (func_num_args() > 1) {
$message = call_user_func_array(
'sprintf',
array_merge(array($message), array_slice(func_get_args(), 1))
);
}
$_SESSION['messages'][] = $message;
}
// Handle CSS & JS files included
if (isset($included_css_files) && is_array($included_css_files)) {
$_css = $included_css_files;
}
else {
$_css = array();
}
function add_css_file() {
global $_css;
foreach (func_get_args() as $files) {
if (!is_array($files)) $files=array($files);
foreach ($files as $file) {
if (!in_array($file, $_css))
$_css[]=$file;
}
}
}
$_js = array();
function add_js_file() {
global $_js;
foreach (func_get_args() as $files) {
if (!is_array($files)) $files = array($files);
foreach ($files as $file) {
if (!in_array($file, $_js))
$_js[] = $file;
}
}
}
function _defineCommonTemplateVariables($template, $pagetitle) {
global $smarty, $_css, $_js, $status_list, $auth_user, $admin, $webstats_js_code;
$smarty->assign('pagetitle', $pagetitle);
// Messages
$smarty -> assign('errors', (isset($_SESSION['errors'])?$_SESSION['errors']:array()));
$smarty -> assign('messages', (isset($_SESSION['messages'])?$_SESSION['messages']:array()));
// Files inclusions
$smarty -> assign('css', $_css);
$smarty -> assign('js', $_js);
// Authenticated user info
if (isset($auth_user))
$smarty->assign('auth_user', $auth_user);
// Webstats JS code
$smarty->assign(
'webstats_js_code',
isset($webstats_js_code)?$webstats_js_code:null);
}
function display_template($template, $pagetitle=false) {
if (!$template)
logging("FATAL", _("No template specified."));
// If refresh parameter is present, remove it and redirect
if (isset($_GET['refresh'])) {
unset($_GET['refresh']);
$url = get_current_url();
if (!empty($_GET))
$url .= '?'.http_build_query($_GET);
redirect($url);
return;
}
$sentry_span = new SentrySpan('smarty.display_template', "Display Smarty template");
global $smarty;
// If more than 2 arguments passed, format pagetitle using sprintf
if ($pagetitle && func_num_args() > 2) {
$pagetitle = call_user_func_array(
'sprintf',
array_merge(array($pagetitle), array_slice(func_get_args(), 2))
);
}
try {
_defineCommonTemplateVariables($template, $pagetitle);
$smarty->display($template);
unset($_SESSION['errors']);
unset($_SESSION['messages']);
}
catch (Exception $e) {
log_exception($e, "Smarty - An exception occured displaying template '$template'");
if ($template != 'fatal_error.tpl')
logging("FATAL", _("An error occurred while displaying this page."));
}
$sentry_span->finish();
}
function display_ajax_return($data=null, $pretty=false) {
global $debug_ajax;
if (is_null($data))
$data = array();
// Adjust HTTP error code on unsuccessfull request
elseif (isset($data['success']) && !$data['success'] && http_response_code() == 200)
http_response_code(400);
if (isset($_SESSION['messages']) && !empty($_SESSION['messages'])) {
$data['messages'] = $_SESSION['messages'];
unset($_SESSION['messages']);
}
if (isset($_SESSION['errors']) && !empty($_SESSION['errors'])) {
$data['errors'] = $_SESSION['errors'];
unset($_SESSION['errors']);
}
if ($debug_ajax)
logging('DEBUG',"Ajax Response : ".vardump($data));
header('Content-Type: application/json');
echo json_encode($data, (($pretty||isset($_REQUEST['pretty']))?JSON_PRETTY_PRINT:0));
exit();
}
$ajax=false;
function fatal_error($error) {
global $smarty, $ajax, $api_mode;
// If more than one arguments passed, format error message using sprintf
if (func_num_args() > 1) {
$error = call_user_func_array(
'sprintf',
array_merge(array($error), array_slice(func_get_args(), 1))
);
}
if (php_sapi_name() == "cli")
die("FATAL ERROR : $error\n");
// Set HTTP reponse code to 500
http_response_code(500);
if ($ajax || $api_mode)
display_ajax_return(array('success' => false, 'error' => $error));
$smarty->assign('fatal_error', $error);
display_template('fatal_error.tpl');
exit();
}
// Templates functions
function smarty_item_status($params) {
global $status_list;
$status2class = array (
'pending' => 'info',
'validated' => 'success',
'refused' => 'danger',
'archived' => 'secondary',
);
if (array_key_exists($params['item']['status'], $status2class)) {
$class = $status2class[$params['item']['status']];
}
else
$class='danger';
echo "<span class='badge badge-$class'>";
echo (
array_key_exists($params['item']['status'], $status_list)?
$status_list[$params['item']['status']]:
"Inconnu (".$params['item']['status'].")"
);
echo "</span>";
}
smarty_register_function('item_status','smarty_item_status');
function smarty_format_time($params) {
echo format_time($params['time'], (!isset($params['with_time']) || (bool)$params['with_time']));
}
smarty_register_function('format_time','smarty_format_time');
function smarty_format_size($params, $smarty) {
if(!isset($params['digit'])) $params['digit'] = 2;
echo format_size($params['size'],$params['digit']);
}
smarty_register_function('format_size','smarty_format_size');
function smarty_table_ordered_th($params, $smarty) {
if ($params['order'] && $params['url'] && $params['text'] && is_array($params['search'])) {
echo "<a href='".$params['url']."?order=".$params['order']."'>".$params['text']."</a>";
}
if ($params['order']==$params['search']['order']) {
echo (
' <i class="fa fa-sort-'.
(strtolower($params['search']['order_direction'])=='asc'?'up':'down').
'" aria-hidden="true"></i>');
}
}
smarty_register_function('table_ordered_th','smarty_table_ordered_th');
function smarty_encodeJsonBase64($params, $smarty) {
if (isset($params['data']))
echo base64_encode(json_encode($params['data']));
}
smarty_register_function('encodeJsonBase64','smarty_encodeJsonBase64');
# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab