Tpl: Add stuff to handle static files
* Move example application in example sub-directory * Widely use App::get() instead of Config::get()
This commit is contained in:
parent
f2edf4910a
commit
4f47dc056d
1148 changed files with 319 additions and 2959 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,6 +3,7 @@
|
|||
.*.swp
|
||||
# Exclude composer installed libs
|
||||
/vendor
|
||||
/composer.lock
|
||||
# Common UNIX user home directory files
|
||||
/.bash*
|
||||
/.vim*
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
"sentry/sdk": "^3.3",
|
||||
"ext-pdo": "^7.3",
|
||||
"ext-json": "^7.3",
|
||||
"ext-yaml": "^2.0"
|
||||
"ext-yaml": "^2.0",
|
||||
"league/mime-type-detection": "^1.11"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.9"
|
||||
|
|
2866
composer.lock
generated
2866
composer.lock
generated
File diff suppressed because it is too large
Load diff
0
data/.gitignore → example/data/.gitignore
vendored
0
data/.gitignore → example/data/.gitignore
vendored
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
|
||||
use EesyPHP\App;
|
||||
use EesyPHP\Config;
|
||||
use EesyPHP\I18n;
|
||||
use EesyPHP\SentrySpan;
|
||||
|
||||
|
@ -25,7 +24,7 @@ $root_dir_path = realpath(dirname($script).'/../');
|
|||
set_include_path($root_dir_path.'/includes' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
// Load composer autoload.php
|
||||
require("$root_dir_path/vendor/autoload.php");
|
||||
require("$root_dir_path/../vendor/autoload.php");
|
||||
|
||||
// Initialize EesyPHP application
|
||||
App::init(
|
||||
|
@ -34,6 +33,11 @@ App::init(
|
|||
'overwrite_config_files' => array(
|
||||
"$root_dir_path/includes/config.local.yml",
|
||||
),
|
||||
'templates' => array(
|
||||
'static_directories' => array(
|
||||
"$root_dir_path/static"
|
||||
),
|
||||
),
|
||||
),
|
||||
$root_dir_path
|
||||
);
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use EesyPHP\Config;
|
||||
use EesyPHP\App;
|
||||
use EesyPHP\Db;
|
||||
use EesyPHP\Hook;
|
||||
use EesyPHP\Log;
|
||||
|
@ -8,12 +8,12 @@ use EesyPHP\Log;
|
|||
use Unidecode\Unidecode;
|
||||
|
||||
$db = new Db(
|
||||
Config::get('db.dsn', null, 'string'),
|
||||
Config::get('db.user', null, 'string'),
|
||||
Config::get('db.password', null, 'string'),
|
||||
Config::get('db.options', array(), 'array'),
|
||||
Config::get('db.date_format', null, 'string'),
|
||||
Config::get('db.datetime_format', null, 'string'),
|
||||
App::get('db.dsn', null, 'string'),
|
||||
App::get('db.user', null, 'string'),
|
||||
App::get('db.password', null, 'string'),
|
||||
App::get('db.options', array(), 'array'),
|
||||
App::get('db.date_format', null, 'string'),
|
||||
App::get('db.datetime_format', null, 'string'),
|
||||
);
|
||||
|
||||
/*
|
||||
|
@ -154,7 +154,7 @@ function search_items($params) {
|
|||
global $db;
|
||||
|
||||
// Detect PgSQL backend
|
||||
$is_pgsql = (strpos(Config::get('db.dsn', '', 'string'), "pgsql:") === 0);
|
||||
$is_pgsql = (strpos(App::get('db.dsn', '', 'string'), "pgsql:") === 0);
|
||||
|
||||
$where = array();
|
||||
if (isset($params['status']) && $params['status'] && $params['status'] != 'all')
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use EesyPHP\Config;
|
||||
use EesyPHP\App;
|
||||
use EesyPHP\Date;
|
||||
use EesyPHP\Hook;
|
||||
use EesyPHP\Log;
|
||||
|
@ -23,13 +23,13 @@ Tpl :: enable_security_mode(
|
|||
);
|
||||
|
||||
// Defined some global template variables
|
||||
Tpl :: assign('public_root_url', Config::get('public_root_url', '/', 'string'));
|
||||
Tpl :: assign('main_pagetitle', Config::get('main_pagetitle', null, 'string'));
|
||||
Tpl :: assign('public_root_url', App::get('public_root_url', '/', 'string'));
|
||||
Tpl :: assign('main_pagetitle', App::get('main_pagetitle', null, 'string'));
|
||||
Tpl :: assign('session_key', $_SESSION['session_key']);
|
||||
|
||||
// Handle CSS & JS files included
|
||||
Tpl :: add_css_file(Config::get('included_css_files', array(), 'array'));
|
||||
Tpl :: add_js_file(Config::get('included_js_files', array(), 'array'));
|
||||
Tpl :: add_css_file(App::get('included_css_files', array(), 'array'));
|
||||
Tpl :: add_js_file(App::get('included_js_files', array(), 'array'));
|
||||
|
||||
function define_common_template_variables($event) {
|
||||
global $status_list, $admin;
|
||||
|
@ -41,7 +41,7 @@ function define_common_template_variables($event) {
|
|||
Tpl :: assign('admin', isset($admin) && $admin);
|
||||
Tpl :: assign(
|
||||
'webstats_js_code',
|
||||
Config::get('webstats_js_code', null, 'string'));
|
||||
App::get('webstats_js_code', null, 'string'));
|
||||
}
|
||||
Hook :: register('before_displaying_template', 'define_common_template_variables');
|
||||
|
|
@ -102,11 +102,11 @@ function handle_search($request) {
|
|||
Tpl :: assign('nbs_by_page', $nbs_by_page);
|
||||
Tpl :: assign('status_list', $status_list);
|
||||
|
||||
Tpl :: add_js_file(array(
|
||||
Tpl :: add_js_file(
|
||||
'lib/bootstrap4dialog/dist/js/bootstrap4dialog.min.js',
|
||||
'js/myconfirm.js',
|
||||
'js/search.js'
|
||||
));
|
||||
);
|
||||
|
||||
Tpl :: display("search.tpl", _("Search"));
|
||||
}
|
||||
|
@ -124,10 +124,10 @@ function handle_show($request) {
|
|||
Tpl :: assign('item', $item);
|
||||
|
||||
// Dialog
|
||||
Tpl :: add_js_file(array(
|
||||
Tpl :: add_js_file(
|
||||
'lib/bootstrap4dialog/dist/js/bootstrap4dialog.min.js',
|
||||
'js/myconfirm.js',
|
||||
));
|
||||
);
|
||||
|
||||
Tpl :: display(
|
||||
"show.tpl", _("Element %s"),
|
|
@ -1,30 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
|
||||
<meta name="description" content=""/>
|
||||
<meta name="author" content=""/>
|
||||
|
||||
<base href="{$public_root_url}/"/>
|
||||
{block name="head"}{/block}
|
||||
|
||||
<link rel="icon" href="images/favicon.png">
|
||||
<link rel="icon" href="{static_url path="images/favicon.png"}"/>
|
||||
|
||||
<title>{$main_pagetitle}{if $pagetitle} - {$pagetitle}{/if}</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="lib/bootstrap4/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="{static_url path="lib/bootstrap4/css/bootstrap.min.css"}" rel="stylesheet"/>
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link href="lib/Fork-Awesome-1.1.7/css/fork-awesome.min.css" rel="stylesheet">
|
||||
<link href="{static_url path="lib/Fork-Awesome-1.1.7/css/fork-awesome.min.css"}" rel="stylesheet"/>
|
||||
|
||||
<link href="css/style.css" rel="stylesheet">
|
||||
{foreach $css as $file}
|
||||
<link href="{$file}" rel="stylesheet">
|
||||
<link href="{static_url path="css/style.css"}" rel="stylesheet"/>
|
||||
{foreach $css as $path}
|
||||
<link href="{$path|escape:"quotes"}" rel="stylesheet"/>
|
||||
{/foreach}
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -34,7 +33,7 @@
|
|||
{block name="navbar"}
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<a class="navbar-brand" href="">
|
||||
<img id="logo" src="images/logo.png" alt="Logo" title="Logo"/>
|
||||
<img id="logo" src="{static_url path="images/logo.png"}" alt="Logo" title="Logo"/>
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
|
@ -89,12 +88,12 @@
|
|||
|
||||
|
||||
<!-- Jquery & Bootstrap -->
|
||||
<script src="lib/jquery-3.4.1.min.js"></script>
|
||||
<script src="lib/bootstrap4/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="{static_url path="lib/jquery-3.4.1.min.js"}"></script>
|
||||
<script src="{static_url path="lib/bootstrap4/js/bootstrap.bundle.min.js"}"></script>
|
||||
|
||||
<!-- Other libs & JavaScript scripts -->
|
||||
{foreach $js as $file}
|
||||
<script language="javascript" src="{$file}"></script>
|
||||
{foreach $js as $path}
|
||||
<script language="javascript" src="{$path|escape:"quotes"}"></script>
|
||||
{/foreach}
|
||||
|
||||
{if $webstats_js_code}{$webstats_js_code}{/if}
|
11
phpstan.neon
11
phpstan.neon
|
@ -2,11 +2,12 @@ parameters:
|
|||
level: 5
|
||||
paths:
|
||||
- src
|
||||
- includes
|
||||
- public_html
|
||||
- bin/eesyphp
|
||||
- example
|
||||
excludePaths:
|
||||
- includes/config.local.php
|
||||
- example/includes/config.local.php
|
||||
- example/data/tmp/templates_c
|
||||
universalObjectCratesClasses:
|
||||
- EesyPHP\UrlRequest
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#Instantiated class Mail_mime not found\\.#"
|
||||
|
@ -23,5 +24,5 @@ parameters:
|
|||
-
|
||||
message: "#Variable \\$status_list might not be defined\\.#"
|
||||
paths:
|
||||
- includes/cli.php
|
||||
- example/includes/cli.php
|
||||
|
||||
|
|
30
src/App.php
30
src/App.php
|
@ -40,35 +40,43 @@ class App {
|
|||
}
|
||||
|
||||
// Load overwrite configuration file
|
||||
foreach (self :: get_option('overwrite_config_files', array(), 'array') as $file) {
|
||||
foreach (self :: get('overwrite_config_files', array(), 'array') as $file) {
|
||||
$file = Config::replace_variables($file);
|
||||
if (is_file($file)) Config::load($file, true);
|
||||
}
|
||||
|
||||
if (self :: get_option('sentry.enabled', true, 'bool'))
|
||||
if (self :: get('sentry.enabled', true, 'bool'))
|
||||
SentryIntegration :: init();
|
||||
$sentry_transaction = new SentryTransaction();
|
||||
$sentry_span = new SentrySpan('app.init', 'Application initialization');
|
||||
|
||||
// Define upload_tmp_dir
|
||||
if (is_string(Config::get('upload_tmp_directory')))
|
||||
ini_set('upload_tmp_dir', Config::get('upload_tmp_directory'));
|
||||
if (is_string(self::get('upload_tmp_directory')))
|
||||
ini_set('upload_tmp_dir', self::get('upload_tmp_directory'));
|
||||
|
||||
if (self :: get_option('log.enabled', true, 'bool'))
|
||||
if (self :: get('log.enabled', true, 'bool'))
|
||||
Log::init();
|
||||
if (self :: get_option('session.enabled', true, 'bool'))
|
||||
if (self :: get('session.enabled', true, 'bool'))
|
||||
Session::init();
|
||||
if (self :: get_option('template.enabled', true, 'bool'))
|
||||
if (self :: get('template.enabled', true, 'bool'))
|
||||
Tpl :: init();
|
||||
if (self :: get_option('url.enabled', true, 'bool'))
|
||||
if (self :: get('url.enabled', true, 'bool'))
|
||||
Url::init();
|
||||
if (self :: get_option('mail.enabled', true, 'bool'))
|
||||
if (self :: get('mail.enabled', true, 'bool'))
|
||||
Email :: init();
|
||||
if (self :: get_option('i18n.enabled', true, 'bool'))
|
||||
if (self :: get('i18n.enabled', true, 'bool'))
|
||||
I18n::init();
|
||||
$sentry_span->finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the application is initialized
|
||||
* @return bool
|
||||
*/
|
||||
public static function initialized() {
|
||||
return !is_null(self :: $root_directory_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific option value
|
||||
*
|
||||
|
@ -82,7 +90,7 @@ class App {
|
|||
* is a string, split the value by comma (optional, default: true)
|
||||
* @return mixed The configuration variable value
|
||||
**/
|
||||
public static function get_option($key, $default=null, $cast=null, $split=true) {
|
||||
public static function get($key, $default=null, $cast=null, $split=true) {
|
||||
return Config::get(
|
||||
$key,
|
||||
Config::loaded()?Config::get($key, $default, $cast, $split):$default,
|
||||
|
|
|
@ -68,31 +68,31 @@ class Email {
|
|||
public static function init($sender=null, $send_method=null, $send_params=null, $catch_all=null,
|
||||
$headers=null, $php_mail_path=null, $php_mail_mime_path=null) {
|
||||
if (is_null($sender))
|
||||
$sender = Config::get('email.sender', null, 'string');
|
||||
$sender = App::get('email.sender', null, 'string');
|
||||
if ($sender) self :: $sender = $sender;
|
||||
|
||||
if (is_null($send_method))
|
||||
$send_method = Config::get('email.send_method', null, 'string');
|
||||
$send_method = App::get('email.send_method', null, 'string');
|
||||
if ($send_method) self :: $send_method = $send_method;
|
||||
|
||||
if (is_null($send_params))
|
||||
$send_params = Config::get('email.send_params', null, 'array');
|
||||
$send_params = App::get('email.send_params', null, 'array');
|
||||
if ($send_params) self :: $send_params = $send_params;
|
||||
|
||||
if (is_null($catch_all))
|
||||
$catch_all = Config::get('email.catch_all');
|
||||
$catch_all = App::get('email.catch_all');
|
||||
if ($catch_all) self :: $catch_all = $catch_all;
|
||||
|
||||
if (is_null($headers))
|
||||
$headers = Config::get('email.headers', null, 'array');
|
||||
$headers = App::get('email.headers', null, 'array');
|
||||
if ($headers) self :: $headers = $headers;
|
||||
|
||||
if (is_null($php_mail_path))
|
||||
$php_mail_path = Config::get('email.php_mail_path', null, 'string');
|
||||
$php_mail_path = App::get('email.php_mail_path', null, 'string');
|
||||
if ($php_mail_path) self :: $php_mail_path = $php_mail_path;
|
||||
|
||||
if (is_null($php_mail_mime_path))
|
||||
$php_mail_mime_path = Config::get('email.php_mail_mime_path', null, 'string');
|
||||
$php_mail_mime_path = App::get('email.php_mail_mime_path', null, 'string');
|
||||
if ($php_mail_mime_path) self :: $php_mail_mime_path = $php_mail_mime_path;
|
||||
}
|
||||
|
||||
|
|
15
src/I18n.php
15
src/I18n.php
|
@ -36,13 +36,13 @@ class I18n {
|
|||
*/
|
||||
public static function init($root_path=null, $default_locale=null) {
|
||||
if (is_null($root_path))
|
||||
self :: $root_path = Config::get(
|
||||
self :: $root_path = App::get(
|
||||
'i18n.root_directory', '${root_directory_path}/locales', 'string');
|
||||
if (!is_null($root_path))
|
||||
self :: $root_path = $root_path;
|
||||
|
||||
if (is_null($default_locale))
|
||||
self :: $default_locale = Config::get('i18n.default_locale', null, 'string');
|
||||
self :: $default_locale = App::get('i18n.default_locale', null, 'string');
|
||||
if (!is_null($default_locale))
|
||||
self :: $default_locale = $default_locale;
|
||||
|
||||
|
@ -68,7 +68,10 @@ class I18n {
|
|||
else {
|
||||
$lang = Locale::lookup(
|
||||
self :: get_available_langs(),
|
||||
Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']),
|
||||
Locale::acceptFromHttp(
|
||||
isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])?
|
||||
$_SERVER['HTTP_ACCEPT_LANGUAGE']:null
|
||||
),
|
||||
true,
|
||||
Locale::getPrimaryLanguage(self :: $default_locale)
|
||||
);
|
||||
|
@ -111,13 +114,13 @@ class I18n {
|
|||
Log :: trace("Test: "._('Hello world !'));
|
||||
|
||||
// JS translation file
|
||||
$js_translation_file = "translations/$lang.js";
|
||||
if (
|
||||
php_sapi_name() != "cli"
|
||||
&& is_file(App :: root_directory_path()."/public_html/$js_translation_file")
|
||||
&& Tpl :: initialized()
|
||||
) {
|
||||
Tpl :: add_js_file(array("lib/babel.js", "js/translation.js", $js_translation_file));
|
||||
Tpl :: register_static_directory(self :: $root_path, null, 'locales/');
|
||||
Tpl :: add_js_file("lib/babel.js", "js/translation.js");
|
||||
Tpl :: add_js_file("locales/", "$lang.js");
|
||||
}
|
||||
|
||||
if (php_sapi_name() == 'cli') {
|
||||
|
|
10
src/Log.php
10
src/Log.php
|
@ -72,19 +72,19 @@ class Log {
|
|||
if ($filepath)
|
||||
self :: $filepath = $filepath;
|
||||
elseif (php_sapi_name() == 'cli')
|
||||
self :: $filepath = Config::get(
|
||||
'log.cli_logfile_path', Config::get('log.cli_file_path'));
|
||||
self :: $filepath = App::get(
|
||||
'log.cli_logfile_path', App::get('log.cli_file_path'));
|
||||
else
|
||||
self :: $filepath = Config::get('log.file_path');
|
||||
self :: $filepath = App::get('log.file_path');
|
||||
|
||||
// Set log level
|
||||
self :: set_level($level?$level:Config::get('log.level'));
|
||||
self :: set_level($level?$level:App::get('log.level'));
|
||||
|
||||
// Log PHP errors
|
||||
if (!is_null($php_errors_levels)) {
|
||||
self :: $php_errors_levels = $php_errors_levels;
|
||||
}
|
||||
elseif ($levels = Config::get('log.php_errors_levels', array(), 'array')) {
|
||||
elseif ($levels = App::get('log.php_errors_levels', array(), 'array')) {
|
||||
$code = 'self :: $php_errors_levels = ';
|
||||
while($level = array_shift($levels)) {
|
||||
if (!is_string($level)) continue;
|
||||
|
|
|
@ -38,11 +38,11 @@ class SentryIntegration {
|
|||
public static function init($dsn=null, $traces_sample_rate=null,
|
||||
$php_error_types=null) {
|
||||
\Sentry\init([
|
||||
'dsn' => $dsn?$dsn:Config::get('sentry.dsn'),
|
||||
'dsn' => $dsn?$dsn:App::get('sentry.dsn'),
|
||||
'traces_sample_rate' => (
|
||||
$traces_sample_rate?
|
||||
$traces_sample_rate:
|
||||
Config::get('sentry.traces_sample_rate', 0.2, 'float')
|
||||
App::get('sentry.traces_sample_rate', 0.2, 'float')
|
||||
),
|
||||
]);
|
||||
|
||||
|
@ -57,7 +57,7 @@ class SentryIntegration {
|
|||
});
|
||||
|
||||
if (!is_array($php_error_types))
|
||||
$php_error_types = Config::get(
|
||||
$php_error_types = App::get(
|
||||
'sentry.php_error_types', self :: $php_error_types, 'array'
|
||||
);
|
||||
self :: $php_error_types = array();
|
||||
|
|
|
@ -27,7 +27,7 @@ class Session {
|
|||
|
||||
// Define session max duration
|
||||
if (is_null($max_duration))
|
||||
$max_duration = Config::get('session.max_duration', null, 'int');
|
||||
$max_duration = App::get('session.max_duration', null, 'int');
|
||||
if (is_int($max_duration))
|
||||
self :: $max_duration = $max_duration;
|
||||
|
||||
|
@ -44,7 +44,7 @@ class Session {
|
|||
|
||||
// Handle session timeout
|
||||
if (is_null($timeout))
|
||||
$timeout = Config::get('session.timeout', null, 'int');
|
||||
$timeout = App::get('session.timeout', null, 'int');
|
||||
if (is_int($timeout) && $timeout) {
|
||||
if (!isset($_SESSION['session_last_access'])) {
|
||||
Log :: debug('Set initial session last access');
|
||||
|
|
203
src/Tpl.php
203
src/Tpl.php
|
@ -5,6 +5,7 @@ namespace EesyPHP;
|
|||
use Exception;
|
||||
use Smarty;
|
||||
use Smarty_Security;
|
||||
use League\MimeTypeDetection\ExtensionMimeTypeDetector;
|
||||
|
||||
class Tpl {
|
||||
|
||||
|
@ -38,6 +39,12 @@ class Tpl {
|
|||
*/
|
||||
public static bool $_debug_ajax;
|
||||
|
||||
/**
|
||||
* Static directories
|
||||
* @var array
|
||||
*/
|
||||
private static array $static_directories = array();
|
||||
|
||||
/**
|
||||
* CSS files to load in next displayed page
|
||||
* @var array<string>
|
||||
|
@ -50,6 +57,18 @@ class Tpl {
|
|||
*/
|
||||
private static array $js_files = array();
|
||||
|
||||
/**
|
||||
* MIME type detector object
|
||||
* @var null|string
|
||||
*/
|
||||
private static $static_root_url;
|
||||
|
||||
/**
|
||||
* MIME type detector object
|
||||
* @var ExtensionMimeTypeDetector|null
|
||||
*/
|
||||
private static $mime_type_detector = null;
|
||||
|
||||
/**
|
||||
* Initialization
|
||||
* @param string $templates_dir Smarty templates directory path
|
||||
|
@ -59,14 +78,18 @@ class Tpl {
|
|||
* @param bool $debug_ajax Enable/disable AJAX returned data debugging in logs
|
||||
* (optional, default: from template.debug_ajax or debug_ajax config keys if set,
|
||||
* false otherwise)
|
||||
* @param bool $static_root_url Configure custom root URL path for static files
|
||||
* (optional, default: from template.static_root_url config key if set,
|
||||
* '/static' otherwise. Set to False to disable)
|
||||
* @return void
|
||||
*/
|
||||
public static function init($templates_dir=null, $templates_c_dir=null, $debug_ajax=null) {
|
||||
public static function init($templates_dir=null, $templates_c_dir=null, $debug_ajax=null,
|
||||
$static_root_url=null) {
|
||||
// Check templates/templates_c directories
|
||||
if (is_null($templates_dir))
|
||||
$templates_dir = Config::get('template.directory', null, 'string');
|
||||
$templates_dir = App::get('template.directory', null, 'string');
|
||||
if (is_null($templates_c_dir))
|
||||
$templates_c_dir = Config::get('template.cache_directory', null, 'string');
|
||||
$templates_c_dir = App::get('template.cache_directory', null, 'string');
|
||||
if (!$templates_dir || !is_dir($templates_dir)) {
|
||||
Log :: fatal(
|
||||
"Template directory not found (%s)",
|
||||
|
@ -83,9 +106,25 @@ class Tpl {
|
|||
self :: $smarty->setTemplateDir($templates_dir);
|
||||
self :: $smarty->setCompileDir($templates_c_dir);
|
||||
if (is_null($debug_ajax))
|
||||
$debug_ajax = Config::get('template.debug_ajax', Config::get('debug_ajax'));
|
||||
$debug_ajax = App::get('template.debug_ajax', App::get('debug_ajax'));
|
||||
self :: $_debug_ajax = boolval($debug_ajax);
|
||||
Log :: register_fatal_error_handler(array('\\EesyPHP\\Tpl', 'fatal_error'));
|
||||
|
||||
if (is_null($static_root_url))
|
||||
$static_root_url = App::get('template.static_root_url', 'static/', 'string');
|
||||
if ($static_root_url) {
|
||||
if (substr($static_root_url, 0, 1) == '/')
|
||||
$static_root_url = substr($static_root_url, 1);
|
||||
if (substr($static_root_url, -1) != '/')
|
||||
$static_root_url = "$static_root_url/";
|
||||
self :: $static_root_url = $static_root_url;
|
||||
$default_static_directory = realpath(__DIR__."/../static");
|
||||
self :: register_static_directory($default_static_directory, 100);
|
||||
self :: register_function('static_url', array('EesyPHP\\Tpl', 'smarty_static_url'));
|
||||
|
||||
foreach(App :: get('templates.static_directories', array(), 'array') as $path)
|
||||
self :: register_static_directory($path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,30 +214,50 @@ class Tpl {
|
|||
|
||||
/**
|
||||
* Register CSS file(s) to load on next displayed page
|
||||
* @param array<string|array<string>> $args CSS files to load
|
||||
* @param string|array<string> $args CSS files to load
|
||||
* @return void
|
||||
*/
|
||||
public static function add_css_file(...$args) {
|
||||
// Check if the first argument is a custom static root URL
|
||||
$root_url = self :: $static_root_url;
|
||||
if (
|
||||
$args && is_string($args[0]) && array_key_exists(
|
||||
self :: clean_static_root_url($args[0]),
|
||||
self :: $static_directories
|
||||
)
|
||||
)
|
||||
$root_url = self :: clean_static_root_url(array_shift($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;
|
||||
$path = $root_url.$file;
|
||||
if (!in_array($path, self :: $css_files))
|
||||
self :: $css_files[] = $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register JS file(s) to load on next displayed page
|
||||
* @param array<string|array<string>> $args JS files to load
|
||||
* @param string|array<string> $args JS files to load
|
||||
* @return void
|
||||
*/
|
||||
public static function add_js_file(...$args) {
|
||||
// Check if the first argument is a custom static root URL
|
||||
$root_url = self :: $static_root_url;
|
||||
if (
|
||||
$args && is_string($args[0]) && array_key_exists(
|
||||
self :: clean_static_root_url($args[0]),
|
||||
self :: $static_directories
|
||||
)
|
||||
)
|
||||
$root_url = self :: clean_static_root_url(array_shift($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;
|
||||
$path = $root_url.$file;
|
||||
if (!in_array($path, self :: $js_files))
|
||||
self :: $js_files[] = $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -360,4 +419,128 @@ class Tpl {
|
|||
public static function templates_directory() {
|
||||
return isset(self :: $templates_directory)?self :: $templates_directory:null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean static root URL helper
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function clean_static_root_url($value) {
|
||||
if (substr($value, 0, 1) == '/')
|
||||
$value = substr($value, 1);
|
||||
if (substr($value, -1) != '/')
|
||||
$value = "$value/";
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a static directory
|
||||
* @param string $path The static directory path
|
||||
* @param int|null $priority The priority of this static directory
|
||||
* (optional, default: prior than all other registered directories)
|
||||
* @return void
|
||||
*/
|
||||
public static function register_static_directory($path, $priority=null, $root_url=null) {
|
||||
if (is_null($root_url)) {
|
||||
if (!self :: $static_root_url)
|
||||
Log :: fatal(
|
||||
'register_static_directory(%s): no root URL provided and no default value configured',
|
||||
$path);
|
||||
$root_url = self :: $static_root_url;
|
||||
}
|
||||
|
||||
if (!array_key_exists($root_url, self :: $static_directories)) {
|
||||
self :: $static_directories[$root_url] = array();
|
||||
if (is_null($priority)) $priority = 100;
|
||||
$pattern = "#^(?P<root_url>$root_url)(?P<path>.*)#";
|
||||
Log :: trace(
|
||||
'Register static file URL handler for root URL "%s" with pattern "%s" and directory '.
|
||||
'"%s" (priority: %d)', $root_url, $pattern, $path, $priority);
|
||||
Url :: add_url_handler(
|
||||
$pattern,
|
||||
array('EesyPHP\\Tpl', 'handle_static_file'),
|
||||
false, // authenticated
|
||||
false, // override
|
||||
false, // API mode
|
||||
array('GET') // methods
|
||||
);
|
||||
if (is_null(self :: $mime_type_detector))
|
||||
self :: $mime_type_detector = new ExtensionMimeTypeDetector();
|
||||
}
|
||||
else {
|
||||
if (is_null($priority)) {
|
||||
$priority = max(self :: $static_directories[$root_url]);
|
||||
$priority++;
|
||||
}
|
||||
Log :: trace(
|
||||
'Register additionnal static directory "%s" for root URL "%s" (priority: %d)',
|
||||
$path, $root_url, $priority);
|
||||
}
|
||||
|
||||
if (substr($path, -1) == PATH_SEPARATOR)
|
||||
$path = substr($path, 0, -1);
|
||||
self :: $static_directories[$root_url][$path] = $priority;
|
||||
arsort(self :: $static_directories[$root_url]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve static path against registered static directories
|
||||
* @param string $path
|
||||
* @return string|false
|
||||
*/
|
||||
public static function resolve_static_path($root_url, $path) {
|
||||
if (!array_key_exists($root_url, self :: $static_directories)) {
|
||||
Log::error(
|
||||
'No static directory registered for root URL "%s". Can no resolve static file "%s" path.',
|
||||
$root_url, $path);
|
||||
return false;
|
||||
}
|
||||
foreach(array_keys(self :: $static_directories[$root_url]) as $dir) {
|
||||
$fullpath = "$dir/$path";
|
||||
if (file_exists($fullpath))
|
||||
return $fullpath;
|
||||
}
|
||||
Log::trace('Static file "%s%s" not found', $root_url, $path);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle URL request for static file
|
||||
* Note: this URL handler is registered in EesyPHP\Url by self::init().
|
||||
* @see self::init()
|
||||
* @param UrlRequest $request
|
||||
* @return void
|
||||
*/
|
||||
public static function handle_static_file($request) {
|
||||
$path = self :: resolve_static_path($request->root_url, $request->path);
|
||||
Log::trace('Resolved static file path for "%s": "%s"', $request->path, $path);
|
||||
if (!$path)
|
||||
Url :: trigger_error_404($request);
|
||||
$mime_type = self :: $mime_type_detector->detectMimeTypeFromFile($path);
|
||||
Log::trace('MIME type detected for "%s" is "%s"', $path, $mime_type);
|
||||
dump_file($path, $mime_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to retrieve static file URL
|
||||
* @param string $path The file path
|
||||
* @return string|false
|
||||
*/
|
||||
public static function static_url($path) {
|
||||
if (self :: $static_root_url)
|
||||
return self :: $static_root_url.$path;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Smarty function to print static file URL
|
||||
* @param array<string,mixed> $params Parameters from template file
|
||||
* @param Smarty $smarty The smarty object
|
||||
* @return void
|
||||
*/
|
||||
public static function smarty_static_url($params, $smarty) {
|
||||
if (!isset($params['path'])) return;
|
||||
$url = self :: static_url($params['path']);
|
||||
if ($url) echo $url;
|
||||
}
|
||||
}
|
||||
|
|
11
src/Url.php
11
src/Url.php
|
@ -57,7 +57,7 @@ class Url {
|
|||
*/
|
||||
public static function init($public_root_url=null, $api_mode=false) {
|
||||
if (is_null($public_root_url))
|
||||
$public_root_url = Config::get('public_root_url', null, 'string');
|
||||
$public_root_url = App::get('public_root_url', null, 'string');
|
||||
if (is_string($public_root_url) && $public_root_url) {
|
||||
// Check URL end
|
||||
if (substr(self :: $public_root_url, -1) == '/')
|
||||
|
@ -201,6 +201,15 @@ class Url {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a 404 HTTP error
|
||||
* @param UrlRequest|null $request Current UrlRequest object (optional, default: null)
|
||||
* @return void
|
||||
*/
|
||||
public static function trigger_error_404($request=null) {
|
||||
call_user_func_array(self :: $error_404_handler, array($request));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Interprets the requested URL and return the corresponding UrlRequest object
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace EesyPHP;
|
||||
|
||||
use League\MimeTypeDetection\ExtensionMimeTypeDetector;
|
||||
|
||||
/*
|
||||
* Parser/formater values helpers
|
||||
*/
|
||||
|
@ -120,11 +122,27 @@ function cast($value, $type, $split=false) {
|
|||
/*
|
||||
* Generic file/directory helpers
|
||||
*/
|
||||
function dump_file($file_path, $max_age=3600) {
|
||||
|
||||
/**
|
||||
* Dump file content to propose its download
|
||||
* @param string $file_path The file path
|
||||
* @param string|null $mime_type The file MIME type (optional, default: auto-detected)
|
||||
* @param int|null $max_age Max age in second of this file in browser cache (optional,
|
||||
* default: null=1h, set to False to disable Cache-Control header)
|
||||
* @return void
|
||||
*/
|
||||
function dump_file($file_path, $mime_type=null, $max_age=null) {
|
||||
if (is_file($file_path)) {
|
||||
header('Content-Type: '.mime_content_type($file_path));
|
||||
if (is_null($mime_type)) {
|
||||
$detector = new ExtensionMimeTypeDetector();
|
||||
$mime_type = $detector->detectMimeTypeFromFile($file_path);
|
||||
Log::trace('MIME type detected for "%s" is "%s"', $file_path, $mime_type);
|
||||
}
|
||||
header("Content-Type: $mime_type");
|
||||
$last_modified_time = filemtime($file_path);
|
||||
$etag = md5_file($file_path);
|
||||
$max_age = is_null($max_age)?3600:$max_age;
|
||||
if ($max_age)
|
||||
header("Cache-Control: max-age=$max_age, must-revalidate");
|
||||
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT");
|
||||
header("Etag: $etag");
|
||||
|
@ -147,8 +165,7 @@ function dump_file($file_path, $max_age=3600) {
|
|||
readfile($file_path);
|
||||
exit();
|
||||
}
|
||||
header("HTTP/1.1 404 Not found");
|
||||
exit();
|
||||
Url :: trigger_error_404();
|
||||
}
|
||||
|
||||
function delete_directory($dir, $recursive=true) {
|
||||
|
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 470 KiB After Width: | Height: | Size: 470 KiB |
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue