diff --git a/includes/core.php b/includes/core.php
index cbc98bc..a938432 100644
--- a/includes/core.php
+++ b/includes/core.php
@@ -74,7 +74,7 @@ $status_list = array (
);
require_once('cli.php');
-require_once('smarty.php');
+require_once('templates.php');
Url::init(isset($public_root_url)?$public_root_url:null);
require_once('url-helpers.php');
require_once('db.php');
diff --git a/includes/functions.php b/includes/functions.php
index db6a41b..fbfc42a 100644
--- a/includes/functions.php
+++ b/includes/functions.php
@@ -3,6 +3,8 @@
use EesyPHP\Check;
use EesyPHP\Log;
use EesyPHP\Session;
+use EesyPHP\Tpl;
+use EesyPHP\Url;
/*
* Check values helpers
@@ -312,12 +314,12 @@ function run_external_command($command, $data_stdin=null, $escape_command_args=t
**/
function check_ajax_request($session_key=null) {
global $ajax, $debug_ajax;
- $ajax = true;
+ Url :: api_mode(true);
if (Session :: check_key($session_key))
- fatal_error('Invalid request');
+ Tpl :: fatal_error('Invalid request');
- if ($debug_ajax)
+ if (Tpl :: debug_ajax())
Log :: debug("Ajax Request : ".vardump($_REQUEST));
}
diff --git a/includes/smarty.php b/includes/smarty.php
deleted file mode 100644
index b264562..0000000
--- a/includes/smarty.php
+++ /dev/null
@@ -1,329 +0,0 @@
- 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 {
- Log :: fatal(_('Smarty version not supported.'));
-}
-
-// Configure templates/templates_c directories
-if (
- !isset($smarty_templates_dir)
- || !is_dir($smarty_templates_dir)
-)
- Log :: 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)
-)
- Log :: 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)
- Log :: fatal(_("No template specified."));
-
- // If refresh parameter is present, remove it and redirect
- if (isset($_GET['refresh'])) {
- unset($_GET['refresh']);
- $url = Url :: get_current_url();
- if (!empty($_GET))
- $url .= '?'.http_build_query($_GET);
- Url :: 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')
- Log :: 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)
- Log :: 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;
-
- // 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 || Url :: 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 "";
- echo (
- array_key_exists($params['item']['status'], $status_list)?
- $status_list[$params['item']['status']]:
- "Inconnu (".$params['item']['status'].")"
- );
- echo "";
-}
-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'])) {
- $params['url'] .= (strpos($params['url'], '?') === false?'?':'&')."order=".$params['order'];
- echo "".$params['text']."";
- }
- if ($params['order']==$params['search']['order']) {
- echo (
- ' ');
- }
-}
-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
diff --git a/includes/templates.php b/includes/templates.php
new file mode 100644
index 0000000..bcacba7
--- /dev/null
+++ b/includes/templates.php
@@ -0,0 +1,107 @@
+ 'info',
+ 'validated' => 'success',
+ 'refused' => 'danger',
+ 'archived' => 'secondary',
+ );
+ if (array_key_exists($params['item']['status'], $status2class)) {
+ $class = $status2class[$params['item']['status']];
+ }
+ else
+ $class='danger';
+ echo "";
+ echo (
+ array_key_exists($params['item']['status'], $status_list)?
+ $status_list[$params['item']['status']]:
+ "Inconnu (".$params['item']['status'].")"
+ );
+ echo "";
+}
+Tpl :: 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']));
+}
+Tpl :: 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']);
+}
+Tpl :: 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'])) {
+ $params['url'] .= (strpos($params['url'], '?') === false?'?':'&')."order=".$params['order'];
+ echo "".$params['text']."";
+ }
+ if ($params['order']==$params['search']['order']) {
+ echo (
+ ' ');
+ }
+}
+Tpl :: 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']));
+}
+Tpl :: register_function('encodeJsonBase64','smarty_encodeJsonBase64');
+
+# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab
diff --git a/includes/url-helpers.php b/includes/url-helpers.php
index f43ceb7..9332631 100644
--- a/includes/url-helpers.php
+++ b/includes/url-helpers.php
@@ -2,6 +2,7 @@
use EesyPHP\Check;
use EesyPHP\Log;
+use EesyPHP\Tpl;
function get_item_from_url($id, $fatal=false) {
if (!Check :: id($id))
@@ -12,7 +13,7 @@ function get_item_from_url($id, $fatal=false) {
$error = sprintf(_("Item #% s not found."), $id);
if ($fatal)
Log :: fatal($error);
- add_error($error);
+ Tpl :: add_error($error);
return false;
}
return $item;
diff --git a/includes/url-public.php b/includes/url-public.php
index bbfc7e1..de5b773 100644
--- a/includes/url-public.php
+++ b/includes/url-public.php
@@ -2,6 +2,7 @@
use EesyPHP\Check;
use EesyPHP\Log;
+use EesyPHP\Tpl;
use EesyPHP\Url;
use function EesyPHP\vardump;
@@ -10,12 +11,12 @@ if (php_sapi_name() == "cli")
return true;
function handle_homepage($request) {
- display_template("homepage.tpl", _("Hello world !"));
+ Tpl :: display("homepage.tpl", _("Hello world !"));
}
Url :: add_url_handler('#^$#', 'handle_homepage');
function handle_search($request) {
- global $smarty, $status_list;
+ global $status_list;
// Manage params
if(
@@ -39,7 +40,7 @@ function handle_search($request) {
if (check_status($_REQUEST['status']) || $_REQUEST['status'] == 'all')
$_SESSION['search']['status'] = $_REQUEST['status'];
else
- $smarty -> assign('status_error', true);
+ Tpl :: assign('status_error', true);
}
if (isset($_REQUEST['pattern'])) {
@@ -48,7 +49,7 @@ function handle_search($request) {
else if (Check :: search_pattern($_REQUEST['pattern']))
$_SESSION['search']['pattern'] = $_REQUEST['pattern'];
else
- $smarty -> assign('pattern_error', true);
+ Tpl :: assign('pattern_error', true);
}
// Order
@@ -91,23 +92,23 @@ function handle_search($request) {
Log :: debug('Search params : '.vardump($_SESSION['search']));
$result = search_items($_SESSION['search']);
if (!is_array($result))
- fatal_error(
+ Tpl :: fatal_error(
_("An error occurred while listing the items. ".
"If the problem persists, please contact support.")
);
- $smarty -> assign('result', $result);
- $smarty -> assign('search', $_SESSION['search']);
- $smarty -> assign('nbs_by_page', $nbs_by_page);
- $smarty -> assign('status_list', $status_list);
+ Tpl :: assign('result', $result);
+ Tpl :: assign('search', $_SESSION['search']);
+ Tpl :: assign('nbs_by_page', $nbs_by_page);
+ Tpl :: assign('status_list', $status_list);
- add_js_file(array(
+ Tpl :: add_js_file(array(
'lib/bootstrap4dialog/dist/js/bootstrap4dialog.min.js',
'js/myconfirm.js',
'js/search.js'
));
- display_template("search.tpl", _("Search"));
+ Tpl :: display("search.tpl", _("Search"));
}
Url :: add_url_handler('|^item/?$|', 'handle_search');
@@ -116,21 +117,19 @@ Url :: add_url_handler('|^item/?$|', 'handle_search');
*/
function handle_show($request) {
- global $smarty;
-
$item = get_item_from_url($request -> id);
if (!$item)
Url :: error_404();
- $smarty->assign('item', $item);
+ Tpl :: assign('item', $item);
// Dialog
- add_js_file(array(
+ Tpl :: add_js_file(array(
'lib/bootstrap4dialog/dist/js/bootstrap4dialog.min.js',
'js/myconfirm.js',
));
- display_template(
+ Tpl :: display(
"show.tpl", _("Element %s"),
(is_array($item)?$item['name']:"#".$request -> id)
);
@@ -138,42 +137,42 @@ function handle_show($request) {
Url :: add_url_handler('|^item/(?P[0-9]+)$|', 'handle_show');
function handle_create($request) {
- global $smarty, $status_list;
+ global $status_list;
$info = array();
$field_errors = handle_item_post_data($info);
if (isset($_POST['submit']) && empty($field_errors)) {
$item = add_item($info);
if (is_array($item)) {
- add_message(_("The element '% s' has been created."), $item['name']);
+ Tpl :: add_message(_("The element '% s' has been created."), $item['name']);
Url :: redirect('item/'.$item['id']);
}
else {
- add_error(_("An error occurred while saving this item."));
+ Tpl :: add_error(_("An error occurred while saving this item."));
}
}
Log :: debug('Validated data : '.vardump($info));
Log :: debug('Fields errors : '.vardump($field_errors));
if (isset($_POST['submit']) && !empty($field_errors))
- add_error(
+ Tpl :: add_error(
_("There are errors preventing this item from being saved. ".
"Please correct them before attempting to add this item."));
- $smarty->assign('submited', isset($_POST['submit']));
- $smarty->assign('info', $info);
- $smarty->assign('field_errors', $field_errors);
- $smarty->assign('status_list', $status_list);
+ Tpl :: assign('submited', isset($_POST['submit']));
+ Tpl :: assign('info', $info);
+ Tpl :: assign('field_errors', $field_errors);
+ Tpl :: assign('status_list', $status_list);
- display_template("form.tpl", _("New"));
+ Tpl :: display("form.tpl", _("New"));
}
Url :: add_url_handler('|^item/new$|', 'handle_create');
function handle_modify($request) {
- global $smarty, $status_list;
+ global $status_list;
$item = get_item_from_url($request -> id);
if(is_array($item)) {
if (!can_modify($item)) {
- add_error(_('You cannot edit this item.'));
+ Tpl :: add_error(_('You cannot edit this item.'));
Url :: redirect('item/'.$item['id']);
}
$info = array();
@@ -186,34 +185,34 @@ function handle_modify($request) {
}
Log :: debug('Changes : '.vardump($changes));
if (empty($changes)) {
- add_message(_("You have not made any changes to element '% s'."), $item['name']);
+ Tpl :: add_message(_("You have not made any changes to element '% s'."), $item['name']);
Url :: redirect('item/'.$item['id']);
}
else if (update_item($item['id'], $changes) === true) {
- add_message(_("The element '% s' has been updated successfully."), $item['name']);
+ Tpl :: add_message(_("The element '% s' has been updated successfully."), $item['name']);
Url :: redirect('item/'.$item['id']);
}
else {
- add_error(_("An error occurred while updating this item."));
+ Tpl :: add_error(_("An error occurred while updating this item."));
}
}
Log :: debug('Validated data : '.vardump($info));
Log :: debug('Fields errors : '.vardump($field_errors));
- $smarty->assign('submited', isset($_POST['submit']));
+ Tpl :: assign('submited', isset($_POST['submit']));
if (isset($_POST['submit']) && !empty($field_errors))
- add_error(
+ Tpl :: add_error(
_("There are errors preventing this item from being saved. ".
"Please correct them before attempting to save your changes."));
- $smarty->assign('info', (!empty($info)?$info:$item));
- $smarty->assign('item_id', $item['id']);
- $smarty->assign('field_errors', $field_errors);
- $smarty -> assign('status_list', $status_list);
+ Tpl :: assign('info', (!empty($info)?$info:$item));
+ Tpl :: assign('item_id', $item['id']);
+ Tpl :: assign('field_errors', $field_errors);
+ Tpl :: assign('status_list', $status_list);
}
else {
Url :: error_404();
}
- display_template(
+ Tpl :: display(
"form.tpl", _("Element %s: Modification"),
(is_array($item)?$item['name']:"#".$request -> id)
);
@@ -221,44 +220,40 @@ function handle_modify($request) {
Url :: add_url_handler('|^item/(?P[0-9]+)/modify$|', 'handle_modify');
function handle_archive($request) {
- global $smarty;
-
$item = get_item_from_url($request -> id);
if(!is_array($item)) {
- add_error(_("Item #% s not found."), $request -> id);
+ Tpl :: add_error(_("Item #% s not found."), $request -> id);
Url :: redirect('item');
}
elseif ($item['status'] == 'archived') {
- add_message(_("This item is already archived."));
+ Tpl :: add_message(_("This item is already archived."));
}
else if (!can_archive($item)) {
- add_error(_('You cannot archive this item.'));
+ Tpl :: add_error(_('You cannot archive this item.'));
}
else if (archive_item($item['id']) === true) {
- add_message(_("The element '% s' has been archived successfully."), $item['name']);
+ Tpl :: add_message(_("The element '% s' has been archived successfully."), $item['name']);
}
else {
- add_error(_('An error occurred while archiving this item.'));
+ Tpl :: add_error(_('An error occurred while archiving this item.'));
}
Url :: redirect('item/'.$item['id']);
}
Url :: add_url_handler('|^item/(?P[0-9]+)/archive$|', 'handle_archive');
function handle_delete($request) {
- global $smarty;
-
$item = get_item_from_url($request -> id);
if(!is_array($item)) {
- add_error(_("Item #% s not found."), $request -> id);
+ Tpl :: add_error(_("Item #% s not found."), $request -> id);
}
else if (!can_delete($item)) {
- add_error(_('You cannot delete this item.'));
+ Tpl :: add_error(_('You cannot delete this item.'));
}
else if (delete_item($item['id']) === true) {
- add_message(_("The element '% s' has been deleted successfully."), $item['name']);
+ Tpl :: add_message(_("The element '% s' has been deleted successfully."), $item['name']);
}
else {
- add_error(_('An error occurred while deleting this item.'));
+ Tpl :: add_error(_('An error occurred while deleting this item.'));
Url :: redirect('item/'.$item['id']);
}
Url :: redirect('item');
diff --git a/src/I18n.php b/src/I18n.php
index c7f7871..703f4d1 100644
--- a/src/I18n.php
+++ b/src/I18n.php
@@ -4,9 +4,9 @@ namespace EesyPHP;
use EesyPHP\Cli;
use EesyPHP\Log;
+use EesyPHP\Tpl;
use Locale;
-use add_js_file;
class I18n {
// Gettext text domain
@@ -109,9 +109,9 @@ class I18n {
php_sapi_name() != "cli"
&& isset($root_dir_path) && $root_dir_path
&& is_file("$root_dir_path/public_html/$js_translation_file")
- && function_exists('add_js_file')
+ && Tpl :: initialized()
) {
- add_js_file(array("lib/babel.js", "js/translation.js", $js_translation_file));
+ Tpl :: add_js_file(array("lib/babel.js", "js/translation.js", $js_translation_file));
}
if (php_sapi_name() == 'cli') {
@@ -254,7 +254,10 @@ class I18n {
* @return void
*/
public static function cli_extract_messages($command_args) {
- global $root_dir_path, $smarty_templates_dir;
+ global $root_dir_path;
+
+ // Store list of generated POT files
+ $pot_files = array();
// List PHP files to parse
$php_files = run_external_command(
@@ -281,7 +284,7 @@ class I18n {
);
if (!is_array($result) || $result[0] != 0)
Log :: fatal(_("Fail to extract messages from PHP files using xgettext."));
-
+ $pot_files[] = self :: $root_path."/php-messages.pot";
// List JS files to parse
$js_files = run_external_command(
@@ -308,18 +311,22 @@ class I18n {
);
if (!is_array($result) || $result[0] != 0)
Log :: fatal(_("Fail to extract messages from JS files using xgettext."));
+ $pot_files[] = self :: $root_path."/js-messages.pot";
- // Extract messages from templates files using tsmarty2c.php
- $result = run_external_command(
- array (
- "$root_dir_path/vendor/bin/tsmarty2c.php",
- "-o", self :: $root_path."/templates-messages.pot",
- $smarty_templates_dir,
- )
- );
- if (!is_array($result) || $result[0] != 0)
- Log :: fatal(
- _("Fail to extract messages from template files using tsmarty2c.php script."));
+ if (Tpl :: initialized()) {
+ // Extract messages from templates files using tsmarty2c.php
+ $result = run_external_command(
+ array (
+ "$root_dir_path/vendor/bin/tsmarty2c.php",
+ "-o", self :: $root_path."/templates-messages.pot",
+ Tpl :: templates_directory(),
+ )
+ );
+ if (!is_array($result) || $result[0] != 0)
+ Log :: fatal(
+ _("Fail to extract messages from template files using tsmarty2c.php script."));
+ $pot_files[] = self :: $root_path."/templates-messages.pot";
+ }
$fd = fopen(self :: $root_path."/headers.pot", 'w');
$headers = array(
@@ -335,14 +342,14 @@ class I18n {
fclose($fd);
// Merge previous results in messages.pot file using msgcat
- $result = run_external_command(array(
- 'msgcat',
- self :: $root_path."/headers.pot",
- self :: $root_path."/php-messages.pot",
- self :: $root_path."/js-messages.pot",
- self :: $root_path."/templates-messages.pot",
- "-t", "utf-8", "--use-first",
- "-o", self :: $root_path."/messages.pot",
+ $result = run_external_command(array_merge(
+ array(
+ 'msgcat',
+ "-t", "utf-8", "--use-first",
+ "-o", self :: $root_path."/messages.pot",
+ self :: $root_path."/headers.pot",
+ ),
+ $pot_files
));
if (!is_array($result) || $result[0] != 0)
Log :: fatal(_("Fail to merge messages using msgcat."));
@@ -356,7 +363,7 @@ class I18n {
* @return bool
*/
public static function cli_update_messages($command_args) {
- global $root_dir_path, $smarty_templates_dir;
+ global $root_dir_path;
$compendium_args = array();
foreach ($command_args as $path) {
@@ -444,7 +451,7 @@ class I18n {
* @return bool
*/
public static function cli_compile_messages($command_args) {
- global $root_dir_path, $smarty_templates_dir;
+ global $root_dir_path;
if ($dh = opendir(self :: $root_path)) {
$error = False;
diff --git a/src/Tpl.php b/src/Tpl.php
new file mode 100644
index 0000000..e750fa2
--- /dev/null
+++ b/src/Tpl.php
@@ -0,0 +1,362 @@
+
+ */
+ private static array $css_files = array();
+
+ /**
+ * JavaScript files to load in next displayed page
+ * @var array
+ */
+ private static array $js_files = array();
+
+ /**
+ * Initialization
+ * @param string $templates_dir Smarty templates directory path
+ * @param string $templates_c_dir Smarty cache templates directory path
+ * @param bool $debug_ajax Enable/disable AJAX returned data debugging in logs
+ * (optional, default: false)
+ * @return void
+ */
+ public static function init($templates_dir, $templates_c_dir, $debug_ajax=false) {
+ // Check templates/templates_c directories
+ if (!$templates_dir || !is_dir($templates_dir)) {
+ Log :: fatal(
+ "Template directory not found (%s)",
+ $templates_dir?$templates_dir:'not set');
+ return;
+ }
+ if (!$templates_c_dir || !is_dir($templates_c_dir) || !is_writable($templates_c_dir)) {
+ Log :: fatal(
+ "Template cache directory not found or not writable (%s)",
+ $templates_c_dir?$templates_c_dir:'not set');
+ return;
+ }
+ self :: $smarty = new Smarty();
+ self :: $smarty->setTemplateDir($templates_dir);
+ self :: $smarty->setCompileDir($templates_c_dir);
+ self :: $_debug_ajax = boolval($debug_ajax);
+ Log :: register_fatal_error_handler(array('\\EesyPHP\\Tpl', 'fatal_error'));
+ }
+
+ /**
+ * Enable security in mode to limit functions (in IF clauses) and modifiers usable from
+ * template files
+ * @param array|null $functions List of function names granted in IF clauses
+ * @param array|null $modifiers List of modifier names granted
+ * @return void
+ */
+ public static function enable_security_mode($functions=null, $modifiers=null) {
+ // Define security policy
+ self :: $smarty_security_policy = new Smarty_Security(self :: $smarty);
+
+ // Allow functions in IF clauses
+ if (is_array($functions))
+ foreach($functions as $function)
+ self :: $smarty_security_policy->php_functions[] = $function;
+
+ // Allow modifier functions
+ if (is_array($modifiers))
+ foreach($modifiers as $modifier)
+ self :: $smarty_security_policy->php_modifiers[] = $modifier;
+
+ // Enable security
+ self :: $smarty -> enableSecurity(self :: $smarty_security_policy);
+
+ // Initialize errors & messages session variables
+ if (!isset($_SESSION['errors']))
+ $_SESSION['errors'] = array();
+ if (!isset($_SESSION['messages']))
+ $_SESSION['messages'] = array();
+ }
+
+ /**
+ * Register a function usable from template files
+ * @param string $name The function name
+ * @param callable $callable The function
+ * @return void
+ */
+ public static function register_function($name, $callable) {
+ self :: $smarty -> registerPlugin("function", $name, $callable);
+ }
+
+ /**
+ * Assign template variable
+ * @param string $name The variable name
+ * @param mixed $value The variable value
+ * @return void
+ */
+ public static function assign($name, $value) {
+ self :: $smarty -> assign($name, $value);
+ }
+
+ /**
+ * Add error message
+ * @param string $error The message
+ * @param array $extra_args Extra arguments to use to compute error message using sprintf
+ * @return void
+ */
+ public static function add_error($error, ...$extra_args) {
+ // If extra arguments passed, format error message using sprintf
+ if ($extra_args) {
+ $error = call_user_func_array(
+ 'sprintf',
+ array_merge(array($error), $extra_args)
+ );
+ }
+ $_SESSION['errors'][] = $error;
+ }
+
+ /**
+ * Add informational message
+ * @param string $message The message
+ * @param array $extra_args Extra arguments to use to compute message using sprintf
+ * @return void
+ */
+ public static function add_message($message, ...$extra_args) {
+ // If extra arguments passed, format message using sprintf
+ if ($extra_args) {
+ $message = call_user_func_array(
+ 'sprintf',
+ array_merge(array($message), $extra_args)
+ );
+ }
+ $_SESSION['messages'][] = $message;
+ }
+
+ /**
+ * Register CSS file(s) to load on next displayed page
+ * @param array> $args CSS files to load
+ * @return void
+ */
+ public static function add_css_file(...$args) {
+ foreach ($args as $files) {
+ if (!is_array($files)) $files = array($files);
+ foreach ($files as $file) {
+ if (!in_array($file, self :: $css_files))
+ self :: $css_files[] = $file;
+ }
+ }
+ }
+
+ /**
+ * Register JS file(s) to load on next displayed page
+ * @param array> $args JS files to load
+ * @return void
+ */
+ public static function add_js_file(...$args) {
+ foreach ($args as $files) {
+ if (!is_array($files)) $files = array($files);
+ foreach ($files as $file) {
+ if (!in_array($file, self :: $js_files))
+ self :: $js_files[] = $file;
+ }
+ }
+ }
+
+ /**
+ * Define common variables
+ * @param string|null $pagetitle The page title
+ * @return void
+ */
+ protected static function define_common_variables($pagetitle=null) {
+ global $auth_user;
+ self :: assign('pagetitle', $pagetitle);
+
+ // Messages
+ self :: assign('errors', (isset($_SESSION['errors'])?$_SESSION['errors']:array()));
+ self :: assign('messages', (isset($_SESSION['messages'])?$_SESSION['messages']:array()));
+
+ // Files inclusions
+ self :: assign('css', self :: $css_files);
+ self :: assign('js', self :: $js_files);
+
+ // Authenticated user info
+ if (isset($auth_user))
+ self :: assign('auth_user', $auth_user);
+ }
+
+ /**
+ * Display the template
+ * @param string $template The template to display
+ * @param string|null $pagetitle The page title (optional)
+ * @param array $extra_args Extra arguments to use to compute the page title using sprintf
+ * @return void
+ */
+ public static function display($template, $pagetitle=null, ...$extra_args) {
+ if (!$template) {
+ Log :: fatal(_("No template specified."));
+ return;
+ }
+
+ // If refresh parameter is present, remove it and redirect
+ if (isset($_GET['refresh'])) {
+ unset($_GET['refresh']);
+ $url = Url :: get_current_url();
+ if (!empty($_GET))
+ $url .= '?'.http_build_query($_GET);
+ Url :: redirect($url);
+ return;
+ }
+
+ $sentry_span = new SentrySpan('smarty.display_template', "Display Smarty template");
+
+ // If extra arguments passed, format pagetitle using sprintf
+ if ($pagetitle && $extra_args) {
+ $pagetitle = call_user_func_array(
+ 'sprintf',
+ array_merge(array($pagetitle), $extra_args)
+ );
+ }
+ try {
+ Hook :: trigger('before_displaying_template');
+ self :: define_common_variables($pagetitle);
+ self :: $smarty->display($template);
+ }
+ catch (Exception $e) {
+ Log :: exception($e, "Smarty - An exception occured displaying template '$template'");
+ if ($template != 'fatal_error.tpl')
+ Log :: fatal(_("An error occurred while displaying this page."));
+ return;
+ }
+ unset($_SESSION['errors']);
+ unset($_SESSION['messages']);
+ Hook :: trigger('after_displaying_template');
+ $sentry_span->finish();
+ }
+
+ /**
+ * Display AJAX return
+ * @param array|null $data AJAX returned data (optional)
+ * @param bool $pretty AJAX returned data
+ * (optional, default: true if $_REQUEST['pretty'] is set, False otherwise)
+ * @return void
+ */
+ public static function display_ajax_return($data=null, $pretty=false) {
+ if (!is_array($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 (self :: $_debug_ajax)
+ Log :: debug("AJAX Response : ".vardump($data));
+ header('Content-Type: application/json');
+ echo json_encode($data, (($pretty||isset($_REQUEST['pretty']))?JSON_PRETTY_PRINT:0));
+ exit();
+ }
+
+ /**
+ * Handle a fatal error
+ * @param string $error The error message
+ * @param array $extra_args Extra arguments to use to compute the error message using sprintf
+ * @return void
+ */
+ public static function fatal_error($error, ...$extra_args) {
+ // If extra arguments passed, format error message using sprintf
+ if ($extra_args) {
+ $error = call_user_func_array(
+ 'sprintf',
+ array_merge(array($error), $extra_args)
+ );
+ }
+
+ if (php_sapi_name() == "cli")
+ die("FATAL ERROR : $error\n");
+
+ // Set HTTP reponse code to 500
+ http_response_code(500);
+
+ // Handle API mode
+ if (Url :: api_mode()) {
+ self :: display_ajax_return(array('success' => false, 'error' => $error));
+ return;
+ }
+
+ self :: assign('fatal_error', $error);
+ self :: display('fatal_error.tpl');
+ exit();
+ }
+
+ /**
+ * Get/set AJAX debug mode
+ * @param bool|null $value If boolean, the current API mode will be changed
+ * @return bool Current API mode
+ */
+ public static function debug_ajax($value=null) {
+ if (is_bool($value)) self :: $_debug_ajax = $value;
+ return self :: $_debug_ajax;
+ }
+
+ /**
+ * Check if initialized
+ * @return bool
+ */
+ public static function initialized() {
+ return isset(self :: $smarty);
+ }
+
+ /**
+ * Get the templates directory path
+ * @return string|null
+ */
+ public static function templates_directory() {
+ return isset(self :: $templates_directory)?self :: $templates_directory:null;
+ }
+}
diff --git a/src/Url.php b/src/Url.php
index a5bfdbc..2b56413 100644
--- a/src/Url.php
+++ b/src/Url.php
@@ -5,6 +5,7 @@ namespace EesyPHP;
use EesyPHP\Log;
use EesyPHP\SentrySpan;
use EesyPHP\SentryTransaction;
+use EesyPHP\Tpl;
use EesyPHP\UrlRequest;
use function EesyPHP\format_callable;
@@ -141,7 +142,6 @@ class Url {
* @return void
**/
public static function error_page($request=null, $error_code=null) {
- global $smarty;
$http_errors = array(
400 => array(
'pagetitle' => _("Bad request"),
@@ -170,10 +170,12 @@ class Url {
);
http_response_code($error_code);
- if (isset($smarty) && $smarty)
- $smarty -> assign('message', $error['message']);
- display_template('error_page.tpl', $error['pagetitle']);
- exit();
+ if (Tpl :: initialized()) {
+ Tpl :: assign('message', $error['message']);
+ Tpl :: display('error_page.tpl', $error['pagetitle']);
+ exit();
+ }
+ die($error['message']);
}
/**
@@ -391,8 +393,6 @@ class Url {
* @return void
**/
public static function handle_request($default_url=null) {
- global $smarty;
-
$sentry_span = new SentrySpan('http.handle_request', 'Handle the HTTP request');
$request = self :: get_request($default_url);
@@ -406,8 +406,8 @@ class Url {
if ($request -> api_mode)
self :: $_api_mode = true;
- if (isset($smarty) && $smarty)
- $smarty -> assign('request', $request);
+ if (Tpl :: initialized())
+ Tpl :: assign('request', $request);
// Check authentication (if need)
if($request -> authenticated)