aboutsummaryrefslogtreecommitdiff
path: root/lib/Minz
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Minz')
-rw-r--r--lib/Minz/ActionController.php42
-rw-r--r--lib/Minz/ActionException.php9
-rw-r--r--lib/Minz/BadConfigurationException.php9
-rw-r--r--lib/Minz/Cache.php116
-rw-r--r--lib/Minz/Configuration.php340
-rw-r--r--lib/Minz/ControllerNotActionControllerException.php9
-rw-r--r--lib/Minz/ControllerNotExistException.php9
-rw-r--r--lib/Minz/CurrentPagePaginationException.php8
-rw-r--r--lib/Minz/Dispatcher.php149
-rw-r--r--lib/Minz/Error.php94
-rw-r--r--lib/Minz/Exception.php16
-rw-r--r--lib/Minz/FileNotExistException.php8
-rw-r--r--lib/Minz/FrontController.php110
-rw-r--r--lib/Minz/Helper.php22
-rw-r--r--lib/Minz/Log.php83
-rw-r--r--lib/Minz/Model.php12
-rw-r--r--lib/Minz/ModelArray.php81
-rw-r--r--lib/Minz/ModelPdo.php119
-rw-r--r--lib/Minz/PDOConnectionException.php9
-rw-r--r--lib/Minz/Paginator.php196
-rw-r--r--lib/Minz/PermissionDeniedException.php8
-rw-r--r--lib/Minz/Request.php204
-rw-r--r--lib/Minz/Response.php60
-rw-r--r--lib/Minz/RouteNotFoundException.php16
-rw-r--r--lib/Minz/Router.php209
-rw-r--r--lib/Minz/Session.php71
-rw-r--r--lib/Minz/Translate.php71
-rw-r--r--lib/Minz/Url.php132
-rw-r--r--lib/Minz/View.php232
29 files changed, 2444 insertions, 0 deletions
diff --git a/lib/Minz/ActionController.php b/lib/Minz/ActionController.php
new file mode 100644
index 000000000..409d9611f
--- /dev/null
+++ b/lib/Minz/ActionController.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe ActionController représente le contrôleur de l'application
+ */
+class Minz_ActionController {
+ protected $router;
+ protected $view;
+
+ /**
+ * Constructeur
+ * @param $controller nom du controller
+ * @param $action nom de l'action à lancer
+ */
+ public function __construct ($router) {
+ $this->router = $router;
+ $this->view = new Minz_View ();
+ $this->view->attributeParams ();
+ }
+
+ /**
+ * Getteur
+ */
+ public function view () {
+ return $this->view;
+ }
+
+ /**
+ * Méthodes à redéfinir (ou non) par héritage
+ * firstAction est la première méthode exécutée par le Dispatcher
+ * lastAction est la dernière
+ */
+ public function init () { }
+ public function firstAction () { }
+ public function lastAction () { }
+}
+
+
diff --git a/lib/Minz/ActionException.php b/lib/Minz/ActionException.php
new file mode 100644
index 000000000..c566a076f
--- /dev/null
+++ b/lib/Minz/ActionException.php
@@ -0,0 +1,9 @@
+<?php
+class Minz_ActionException extends Minz_Exception {
+ public function __construct ($controller_name, $action_name, $code = self::ERROR) {
+ $message = '`' . $action_name . '` cannot be invoked on `'
+ . $controller_name . '`';
+
+ parent::__construct ($message, $code);
+ }
+}
diff --git a/lib/Minz/BadConfigurationException.php b/lib/Minz/BadConfigurationException.php
new file mode 100644
index 000000000..a7b77d687
--- /dev/null
+++ b/lib/Minz/BadConfigurationException.php
@@ -0,0 +1,9 @@
+<?php
+class Minz_BadConfigurationException extends Minz_Exception {
+ public function __construct ($part_missing, $code = self::ERROR) {
+ $message = '`' . $part_missing
+ . '` in the configuration file is missing or is misconfigured';
+
+ parent::__construct ($message, $code);
+ }
+}
diff --git a/lib/Minz/Cache.php b/lib/Minz/Cache.php
new file mode 100644
index 000000000..fcb627eb2
--- /dev/null
+++ b/lib/Minz/Cache.php
@@ -0,0 +1,116 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe Cache permet de gérer facilement les pages en cache
+ */
+class Minz_Cache {
+ /**
+ * $expire timestamp auquel expire le cache de $url
+ */
+ private $expire = 0;
+
+ /**
+ * $file est le nom du fichier de cache
+ */
+ private $file = '';
+
+ /**
+ * $enabled permet de déterminer si le cache est activé
+ */
+ private static $enabled = true;
+
+ /**
+ * Constructeur
+ */
+ public function __construct () {
+ $this->_fileName ();
+ $this->_expire ();
+ }
+
+ /**
+ * Setteurs
+ */
+ public function _fileName () {
+ $file = md5 (Minz_Request::getURI ());
+
+ $this->file = CACHE_PATH . '/'.$file;
+ }
+
+ public function _expire () {
+ if ($this->exist ()) {
+ $this->expire = filemtime ($this->file)
+ + Minz_Configuration::delayCache ();
+ }
+ }
+
+ /**
+ * Permet de savoir si le cache est activé
+ * @return true si activé, false sinon
+ */
+ public static function isEnabled () {
+ return Minz_Configuration::cacheEnabled () && self::$enabled;
+ }
+
+ /**
+ * Active / désactive le cache
+ */
+ public static function switchOn () {
+ self::$enabled = true;
+ }
+ public static function switchOff () {
+ self::$enabled = false;
+ }
+
+ /**
+ * Détermine si le cache de $url a expiré ou non
+ * @return true si il a expiré, false sinon
+ */
+ public function expired () {
+ return time () > $this->expire;
+ }
+
+ /**
+ * Affiche le contenu du cache
+ * @print le code html du cache
+ */
+ public function render () {
+ if ($this->exist ()) {
+ include ($this->file);
+ }
+ }
+
+ /**
+ * Enregistre $html en cache
+ * @param $html le html à mettre en cache
+ */
+ public function cache ($html) {
+ file_put_contents ($this->file, $html);
+ }
+
+ /**
+ * Permet de savoir si le cache existe
+ * @return true si il existe, false sinon
+ */
+ public function exist () {
+ return file_exists ($this->file);
+ }
+
+ /**
+ * Nettoie le cache en supprimant tous les fichiers
+ */
+ public static function clean () {
+ $files = opendir (CACHE_PATH);
+
+ while ($fic = readdir ($files)) {
+ if ($fic != '.' && $fic != '..') {
+ unlink (CACHE_PATH.'/'.$fic);
+ }
+ }
+
+ closedir ($files);
+ }
+}
diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php
new file mode 100644
index 000000000..572b9984d
--- /dev/null
+++ b/lib/Minz/Configuration.php
@@ -0,0 +1,340 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe Configuration permet de gérer la configuration de l'application
+ */
+class Minz_Configuration {
+ const CONF_PATH_NAME = '/config.php';
+
+ /**
+ * VERSION est la version actuelle de MINZ
+ */
+ const VERSION = '1.3.1.freshrss'; // version spéciale FreshRSS
+
+ /**
+ * valeurs possibles pour l'"environment"
+ * SILENT rend l'application muette (pas de log)
+ * PRODUCTION est recommandée pour une appli en production
+ * (log les erreurs critiques)
+ * DEVELOPMENT log toutes les erreurs
+ */
+ const SILENT = 0;
+ const PRODUCTION = 1;
+ const DEVELOPMENT = 2;
+
+ /**
+ * définition des variables de configuration
+ * $salt une chaîne de caractères aléatoires (obligatoire)
+ * $environment gère le niveau d'affichage pour log et erreurs
+ * $use_url_rewriting indique si on utilise l'url_rewriting
+ * $base_url le chemin de base pour accéder à l'application
+ * $title le nom de l'application
+ * $language la langue par défaut de l'application
+ * $cacheEnabled permet de savoir si le cache doit être activé
+ * $delayCache la limite de cache
+ * $db paramètres pour la base de données (tableau)
+ * - host le serveur de la base
+ * - user nom d'utilisateur
+ * - password mot de passe de l'utilisateur
+ * - base le nom de la base de données
+ */
+ private static $salt = '';
+ private static $environment = Minz_Configuration::PRODUCTION;
+ private static $base_url = '';
+ private static $use_url_rewriting = false;
+ private static $title = '';
+ private static $language = 'en';
+ private static $cache_enabled = false;
+ private static $delay_cache = 3600;
+ private static $default_user = '';
+ private static $allow_anonymous = false;
+ private static $auth_type = 'none';
+
+ private static $db = array (
+ 'type' => 'mysql',
+ 'host' => '',
+ 'user' => '',
+ 'password' => '',
+ 'base' => '',
+ 'prefix' => '',
+ );
+
+ /*
+ * Getteurs
+ */
+ public static function salt () {
+ return self::$salt;
+ }
+ public static function environment ($str = false) {
+ $env = self::$environment;
+
+ if ($str) {
+ switch (self::$environment) {
+ case self::SILENT:
+ $env = 'silent';
+ break;
+ case self::DEVELOPMENT:
+ $env = 'development';
+ break;
+ case self::PRODUCTION:
+ default:
+ $env = 'production';
+ }
+ }
+
+ return $env;
+ }
+ public static function baseUrl () {
+ return self::$base_url;
+ }
+ public static function useUrlRewriting () {
+ return self::$use_url_rewriting;
+ }
+ public static function title () {
+ return self::$title;
+ }
+ public static function language () {
+ return self::$language;
+ }
+ public static function cacheEnabled () {
+ return self::$cache_enabled;
+ }
+ public static function delayCache () {
+ return self::$delay_cache;
+ }
+ public static function dataBase () {
+ return self::$db;
+ }
+ public static function defaultUser () {
+ return self::$default_user;
+ }
+ public static function isAdmin($currentUser) {
+ return $currentUser === self::$default_user;
+ }
+ public static function allowAnonymous() {
+ return self::$allow_anonymous;
+ }
+ public static function authType() {
+ return self::$auth_type;
+ }
+ public static function needsLogin() {
+ return self::$auth_type !== 'none';
+ }
+ public static function canLogIn() {
+ return self::$auth_type === 'form' || self::$auth_type === 'persona';
+ }
+
+ public static function _allowAnonymous($allow = false) {
+ self::$allow_anonymous = ((bool)$allow) && self::canLogIn();
+ }
+ public static function _authType($value) {
+ $value = strtolower($value);
+ switch ($value) {
+ case 'form':
+ case 'http_auth':
+ case 'persona':
+ case 'none':
+ self::$auth_type = $value;
+ break;
+ }
+ self::_allowAnonymous(self::$allow_anonymous);
+ }
+
+ /**
+ * Initialise les variables de configuration
+ * @exception Minz_FileNotExistException si le CONF_PATH_NAME n'existe pas
+ * @exception Minz_BadConfigurationException si CONF_PATH_NAME mal formaté
+ */
+ public static function init () {
+ try {
+ self::parseFile ();
+ self::setReporting ();
+ } catch (Minz_FileNotExistException $e) {
+ throw $e;
+ } catch (Minz_BadConfigurationException $e) {
+ throw $e;
+ }
+ }
+
+ public static function writeFile() {
+ $ini_array = array(
+ 'general' => array(
+ 'environment' => self::environment(true),
+ 'use_url_rewriting' => self::$use_url_rewriting,
+ 'salt' => self::$salt,
+ 'base_url' => self::$base_url,
+ 'title' => self::$title,
+ 'default_user' => self::$default_user,
+ 'allow_anonymous' => self::$allow_anonymous,
+ 'auth_type' => self::$auth_type,
+ ),
+ 'db' => self::$db,
+ );
+ @rename(DATA_PATH . self::CONF_PATH_NAME, DATA_PATH . self::CONF_PATH_NAME . '.bak.php');
+ $result = file_put_contents(DATA_PATH . self::CONF_PATH_NAME, "<?php\n return " . var_export($ini_array, true) . ';');
+ if (function_exists('opcache_invalidate')) {
+ opcache_invalidate(DATA_PATH . self::CONF_PATH_NAME); //Clear PHP 5.5+ cache for include
+ }
+ return (bool)$result;
+ }
+
+ /**
+ * Parse un fichier de configuration
+ * @exception Minz_PermissionDeniedException si le CONF_PATH_NAME n'est pas accessible
+ * @exception Minz_BadConfigurationException si CONF_PATH_NAME mal formaté
+ */
+ private static function parseFile () {
+ $ini_array = include(DATA_PATH . self::CONF_PATH_NAME);
+
+ if (!is_array($ini_array)) {
+ throw new Minz_PermissionDeniedException (
+ DATA_PATH . self::CONF_PATH_NAME,
+ Minz_Exception::ERROR
+ );
+ }
+
+ // [general] est obligatoire
+ if (!isset ($ini_array['general'])) {
+ throw new Minz_BadConfigurationException (
+ '[general]',
+ Minz_Exception::ERROR
+ );
+ }
+ $general = $ini_array['general'];
+
+ // salt est obligatoire
+ if (!isset ($general['salt'])) {
+ if (isset($general['sel_application'])) { //v0.6
+ $general['salt'] = $general['sel_application'];
+ } else {
+ throw new Minz_BadConfigurationException (
+ 'salt',
+ Minz_Exception::ERROR
+ );
+ }
+ }
+ self::$salt = $general['salt'];
+
+ if (isset ($general['environment'])) {
+ switch ($general['environment']) {
+ case 'silent':
+ self::$environment = Minz_Configuration::SILENT;
+ break;
+ case 'development':
+ self::$environment = Minz_Configuration::DEVELOPMENT;
+ break;
+ case 'production':
+ self::$environment = Minz_Configuration::PRODUCTION;
+ break;
+ default:
+ if ($general['environment'] >= 0 &&
+ $general['environment'] <= 2) {
+ // fallback 0.7-beta
+ self::$environment = $general['environment'];
+ } else {
+ throw new Minz_BadConfigurationException (
+ 'environment',
+ Minz_Exception::ERROR
+ );
+ }
+ }
+
+ }
+ if (isset ($general['base_url'])) {
+ self::$base_url = $general['base_url'];
+ }
+ if (isset ($general['use_url_rewriting'])) {
+ self::$use_url_rewriting = $general['use_url_rewriting'];
+ }
+
+ if (isset ($general['title'])) {
+ self::$title = $general['title'];
+ }
+ if (isset ($general['language'])) {
+ self::$language = $general['language'];
+ }
+ if (isset ($general['cache_enabled'])) {
+ self::$cache_enabled = $general['cache_enabled'];
+ if (CACHE_PATH === false && self::$cache_enabled) {
+ throw new FileNotExistException (
+ 'CACHE_PATH',
+ Minz_Exception::ERROR
+ );
+ }
+ }
+ if (isset ($general['delay_cache'])) {
+ self::$delay_cache = inval($general['delay_cache']);
+ }
+ if (isset ($general['default_user'])) {
+ self::$default_user = $general['default_user'];
+ }
+ if (isset ($general['auth_type'])) {
+ self::_authType($general['auth_type']);
+ }
+ if (isset ($general['allow_anonymous'])) {
+ self::$allow_anonymous = ((bool)($general['allow_anonymous'])) && ($general['allow_anonymous'] !== 'no');
+ }
+
+ // Base de données
+ if (isset ($ini_array['db'])) {
+ $db = $ini_array['db'];
+ if (empty($db['host'])) {
+ throw new Minz_BadConfigurationException (
+ 'host',
+ Minz_Exception::ERROR
+ );
+ }
+ if (empty($db['user'])) {
+ throw new Minz_BadConfigurationException (
+ 'user',
+ Minz_Exception::ERROR
+ );
+ }
+ if (!isset ($db['password'])) {
+ throw new Minz_BadConfigurationException (
+ 'password',
+ Minz_Exception::ERROR
+ );
+ }
+ if (empty($db['base'])) {
+ throw new Minz_BadConfigurationException (
+ 'base',
+ Minz_Exception::ERROR
+ );
+ }
+
+ if (!empty($db['type'])) {
+ self::$db['type'] = $db['type'];
+ }
+ self::$db['host'] = $db['host'];
+ self::$db['user'] = $db['user'];
+ self::$db['password'] = $db['password'];
+ self::$db['base'] = $db['base'];
+ if (isset($db['prefix'])) {
+ self::$db['prefix'] = $db['prefix'];
+ }
+ }
+ }
+
+ private static function setReporting() {
+ switch (self::$environment) {
+ case self::PRODUCTION:
+ error_reporting(E_ALL);
+ ini_set('display_errors','Off');
+ ini_set('log_errors', 'On');
+ break;
+ case self::DEVELOPMENT:
+ error_reporting(E_ALL);
+ ini_set('display_errors','On');
+ ini_set('log_errors', 'On');
+ break;
+ case self::SILENT:
+ error_reporting(0);
+ break;
+ }
+ }
+}
diff --git a/lib/Minz/ControllerNotActionControllerException.php b/lib/Minz/ControllerNotActionControllerException.php
new file mode 100644
index 000000000..535a1377e
--- /dev/null
+++ b/lib/Minz/ControllerNotActionControllerException.php
@@ -0,0 +1,9 @@
+<?php
+class Minz_ControllerNotActionControllerException extends Minz_Exception {
+ public function __construct ($controller_name, $code = self::ERROR) {
+ $message = 'Controller `' . $controller_name
+ . '` isn\'t instance of ActionController';
+
+ parent::__construct ($message, $code);
+ }
+}
diff --git a/lib/Minz/ControllerNotExistException.php b/lib/Minz/ControllerNotExistException.php
new file mode 100644
index 000000000..523867d11
--- /dev/null
+++ b/lib/Minz/ControllerNotExistException.php
@@ -0,0 +1,9 @@
+<?php
+class Minz_ControllerNotExistException extends Minz_Exception {
+ public function __construct ($controller_name, $code = self::ERROR) {
+ $message = 'Controller `' . $controller_name
+ . '` doesn\'t exist';
+
+ parent::__construct ($message, $code);
+ }
+}
diff --git a/lib/Minz/CurrentPagePaginationException.php b/lib/Minz/CurrentPagePaginationException.php
new file mode 100644
index 000000000..74214d879
--- /dev/null
+++ b/lib/Minz/CurrentPagePaginationException.php
@@ -0,0 +1,8 @@
+<?php
+class Minz_CurrentPagePaginationException extends Minz_Exception {
+ public function __construct ($page) {
+ $message = 'Page number `' . $page . '` doesn\'t exist';
+
+ parent::__construct ($message, self::ERROR);
+ }
+}
diff --git a/lib/Minz/Dispatcher.php b/lib/Minz/Dispatcher.php
new file mode 100644
index 000000000..71dfe8ac6
--- /dev/null
+++ b/lib/Minz/Dispatcher.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * Le Dispatcher s'occupe d'initialiser le Controller et d'executer l'action
+ * déterminée dans la Request
+ * C'est un singleton
+ */
+class Minz_Dispatcher {
+ const CONTROLLERS_PATH_NAME = '/Controllers';
+
+ /* singleton */
+ private static $instance = null;
+
+ private $router;
+ private $controller;
+
+ /**
+ * Récupère l'instance du Dispatcher
+ */
+ public static function getInstance ($router) {
+ if (self::$instance === null) {
+ self::$instance = new Minz_Dispatcher ($router);
+ }
+ return self::$instance;
+ }
+
+ /**
+ * Constructeur
+ */
+ private function __construct ($router) {
+ $this->router = $router;
+ }
+
+ /**
+ * Lance le controller indiqué dans Request
+ * Remplit le body de Response à partir de la Vue
+ * @exception Minz_Exception
+ */
+ public function run ($ob = true) {
+ $cache = new Minz_Cache();
+ // Le ob_start est dupliqué : sans ça il y a un bug sous Firefox
+ // ici on l'appelle avec 'ob_gzhandler', après sans.
+ // Vraisemblablement la compression fonctionne mais c'est sale
+ // J'ignore les effets de bord :(
+ if ($ob) {
+ ob_start ('ob_gzhandler');
+ }
+
+ if (Minz_Cache::isEnabled () && !$cache->expired ()) {
+ if ($ob) {
+ ob_start ();
+ }
+ $cache->render ();
+ if ($ob) {
+ $text = ob_get_clean();
+ }
+ } else {
+ $text = ''; //TODO: Clean this code
+ while (Minz_Request::$reseted) {
+ Minz_Request::$reseted = false;
+
+ try {
+ $this->createController ('FreshRSS_' . Minz_Request::controllerName () . '_Controller');
+ $this->controller->init ();
+ $this->controller->firstAction ();
+ $this->launchAction (
+ Minz_Request::actionName ()
+ . 'Action'
+ );
+ $this->controller->lastAction ();
+
+ if (!Minz_Request::$reseted) {
+ if ($ob) {
+ ob_start ();
+ }
+ $this->controller->view ()->build ();
+ if ($ob) {
+ $text = ob_get_clean();
+ }
+ }
+ } catch (Minz_Exception $e) {
+ throw $e;
+ }
+ }
+
+ if (Minz_Cache::isEnabled ()) {
+ $cache->cache ($text);
+ }
+ }
+
+ Minz_Response::setBody ($text);
+ }
+
+ /**
+ * Instancie le Controller
+ * @param $controller_name le nom du controller à instancier
+ * @exception ControllerNotExistException le controller n'existe pas
+ * @exception ControllerNotActionControllerException controller n'est
+ * > pas une instance de ActionController
+ */
+ private function createController ($controller_name) {
+ $filename = APP_PATH . self::CONTROLLERS_PATH_NAME . '/'
+ . $controller_name . '.php';
+
+ if (!class_exists ($controller_name)) {
+ throw new Minz_ControllerNotExistException (
+ $controller_name,
+ Minz_Exception::ERROR
+ );
+ }
+ $this->controller = new $controller_name ($this->router);
+
+ if (! ($this->controller instanceof Minz_ActionController)) {
+ throw new Minz_ControllerNotActionControllerException (
+ $controller_name,
+ Minz_Exception::ERROR
+ );
+ }
+ }
+
+ /**
+ * Lance l'action sur le controller du dispatcher
+ * @param $action_name le nom de l'action
+ * @exception ActionException si on ne peut pas exécuter l'action sur
+ * le controller
+ */
+ private function launchAction ($action_name) {
+ if (!Minz_Request::$reseted) {
+ if (!is_callable (array (
+ $this->controller,
+ $action_name
+ ))) {
+ throw new Minz_ActionException (
+ get_class ($this->controller),
+ $action_name,
+ Minz_Exception::ERROR
+ );
+ }
+ call_user_func (array (
+ $this->controller,
+ $action_name
+ ));
+ }
+ }
+}
diff --git a/lib/Minz/Error.php b/lib/Minz/Error.php
new file mode 100644
index 000000000..337ab6c0a
--- /dev/null
+++ b/lib/Minz/Error.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe Error permet de lancer des erreurs HTTP
+ */
+class Minz_Error {
+ public function __construct () { }
+
+ /**
+ * Permet de lancer une erreur
+ * @param $code le type de l'erreur, par défaut 404 (page not found)
+ * @param $logs logs d'erreurs découpés de la forme
+ * > $logs['error']
+ * > $logs['warning']
+ * > $logs['notice']
+ * @param $redirect indique s'il faut forcer la redirection (les logs ne seront pas transmis)
+ */
+ public static function error ($code = 404, $logs = array (), $redirect = false) {
+ $logs = self::processLogs ($logs);
+ $error_filename = APP_PATH . '/Controllers/errorController.php';
+
+ if (file_exists ($error_filename)) {
+ $params = array (
+ 'code' => $code,
+ 'logs' => $logs
+ );
+
+ Minz_Response::setHeader ($code);
+ if ($redirect) {
+ Minz_Request::forward (array (
+ 'c' => 'error'
+ ), true);
+ } else {
+ Minz_Request::forward (array (
+ 'c' => 'error',
+ 'params' => $params
+ ), false);
+ }
+ } else {
+ $text = '<h1>An error occured</h1>'."\n";
+
+ if (!empty ($logs)) {
+ $text .= '<ul>'."\n";
+ foreach ($logs as $log) {
+ $text .= '<li>' . $log . '</li>'."\n";
+ }
+ $text .= '</ul>'."\n";
+ }
+
+ Minz_Response::setHeader ($code);
+ Minz_Response::setBody ($text);
+ Minz_Response::send ();
+ exit ();
+ }
+ }
+
+ /**
+ * Permet de retourner les logs de façon à n'avoir que
+ * ceux que l'on veut réellement
+ * @param $logs les logs rangés par catégories (error, warning, notice)
+ * @return la liste des logs, sans catégorie,
+ * > en fonction de l'environment
+ */
+ private static function processLogs ($logs) {
+ $env = Minz_Configuration::environment ();
+ $logs_ok = array ();
+ $error = array ();
+ $warning = array ();
+ $notice = array ();
+
+ if (isset ($logs['error'])) {
+ $error = $logs['error'];
+ }
+ if (isset ($logs['warning'])) {
+ $warning = $logs['warning'];
+ }
+ if (isset ($logs['notice'])) {
+ $notice = $logs['notice'];
+ }
+
+ if ($env == Minz_Configuration::PRODUCTION) {
+ $logs_ok = $error;
+ }
+ if ($env == Minz_Configuration::DEVELOPMENT) {
+ $logs_ok = array_merge ($error, $warning, $notice);
+ }
+
+ return $logs_ok;
+ }
+}
diff --git a/lib/Minz/Exception.php b/lib/Minz/Exception.php
new file mode 100644
index 000000000..b5e71e0d8
--- /dev/null
+++ b/lib/Minz/Exception.php
@@ -0,0 +1,16 @@
+<?php
+class Minz_Exception extends Exception {
+ const ERROR = 0;
+ const WARNING = 10;
+ const NOTICE = 20;
+
+ public function __construct ($message, $code = self::ERROR) {
+ if ($code != Minz_Exception::ERROR
+ && $code != Minz_Exception::WARNING
+ && $code != Minz_Exception::NOTICE) {
+ $code = Minz_Exception::ERROR;
+ }
+
+ parent::__construct ($message, $code);
+ }
+}
diff --git a/lib/Minz/FileNotExistException.php b/lib/Minz/FileNotExistException.php
new file mode 100644
index 000000000..f8dfbdf66
--- /dev/null
+++ b/lib/Minz/FileNotExistException.php
@@ -0,0 +1,8 @@
+<?php
+class Minz_FileNotExistException extends Minz_Exception {
+ public function __construct ($file_name, $code = self::ERROR) {
+ $message = 'File not found: `' . $file_name.'`';
+
+ parent::__construct ($message, $code);
+ }
+}
diff --git a/lib/Minz/FrontController.php b/lib/Minz/FrontController.php
new file mode 100644
index 000000000..80eda8877
--- /dev/null
+++ b/lib/Minz/FrontController.php
@@ -0,0 +1,110 @@
+<?php
+# ***** BEGIN LICENSE BLOCK *****
+# MINZ - a free PHP Framework like Zend Framework
+# Copyright (C) 2011 Marien Fressinaud
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# ***** END LICENSE BLOCK *****
+
+/**
+ * La classe FrontController est le Dispatcher du framework, elle lance l'application
+ * Elle est appelée en général dans le fichier index.php à la racine du serveur
+ */
+class Minz_FrontController {
+ protected $dispatcher;
+ protected $router;
+
+ private $useOb = true;
+
+ /**
+ * Constructeur
+ * Initialise le router et le dispatcher
+ */
+ public function __construct () {
+ if (LOG_PATH === false) {
+ $this->killApp ('Path not found: LOG_PATH');
+ }
+
+ try {
+ Minz_Configuration::init ();
+
+ Minz_Request::init ();
+
+ $this->router = new Minz_Router ();
+ $this->router->init ();
+ } catch (Minz_RouteNotFoundException $e) {
+ Minz_Log::record ($e->getMessage (), Minz_Log::ERROR);
+ Minz_Error::error (
+ 404,
+ array ('error' => array ($e->getMessage ()))
+ );
+ } catch (Minz_Exception $e) {
+ Minz_Log::record ($e->getMessage (), Minz_Log::ERROR);
+ $this->killApp ($e->getMessage ());
+ }
+
+ $this->dispatcher = Minz_Dispatcher::getInstance ($this->router);
+ }
+
+ /**
+ * Démarre l'application (lance le dispatcher et renvoie la réponse
+ */
+ public function run () {
+ try {
+ $this->dispatcher->run ($this->useOb);
+ Minz_Response::send ();
+ } catch (Minz_Exception $e) {
+ try {
+ Minz_Log::record ($e->getMessage (), Minz_Log::ERROR);
+ } catch (Minz_PermissionDeniedException $e) {
+ $this->killApp ($e->getMessage ());
+ }
+
+ if ($e instanceof Minz_FileNotExistException ||
+ $e instanceof Minz_ControllerNotExistException ||
+ $e instanceof Minz_ControllerNotActionControllerException ||
+ $e instanceof Minz_ActionException) {
+ Minz_Error::error (
+ 404,
+ array ('error' => array ($e->getMessage ())),
+ true
+ );
+ } else {
+ $this->killApp ();
+ }
+ }
+ }
+
+ /**
+ * Permet d'arrêter le programme en urgence
+ */
+ private function killApp ($txt = '') {
+ if ($txt == '') {
+ $txt = 'See logs files';
+ }
+ exit ('### Application problem ###<br />'."\n".$txt);
+ }
+
+ public function useOb() {
+ return $this->useOb;
+ }
+
+ /**
+ * Use ob_start('ob_gzhandler') or not.
+ */
+ public function _useOb($ob) {
+ return $this->useOb = (bool)$ob;
+ }
+}
diff --git a/lib/Minz/Helper.php b/lib/Minz/Helper.php
new file mode 100644
index 000000000..b058211d3
--- /dev/null
+++ b/lib/Minz/Helper.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe Helper représente une aide pour des tâches récurrentes
+ */
+class Minz_Helper {
+ /**
+ * Annule les effets des magic_quotes pour une variable donnée
+ * @param $var variable à traiter (tableau ou simple variable)
+ */
+ public static function stripslashes_r ($var) {
+ if (is_array ($var)){
+ return array_map (array ('Helper', 'stripslashes_r'), $var);
+ } else {
+ return stripslashes($var);
+ }
+ }
+}
diff --git a/lib/Minz/Log.php b/lib/Minz/Log.php
new file mode 100644
index 000000000..e710aad4a
--- /dev/null
+++ b/lib/Minz/Log.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe Log permet de logger des erreurs
+ */
+class Minz_Log {
+ /**
+ * Les différents niveau de log
+ * ERROR erreurs bloquantes de l'application
+ * WARNING erreurs pouvant géner le bon fonctionnement, mais non bloquantes
+ * NOTICE erreurs mineures ou messages d'informations
+ * DEBUG Informations affichées pour le déboggage
+ */
+ const ERROR = 2;
+ const WARNING = 4;
+ const NOTICE = 8;
+ const DEBUG = 16;
+
+ /**
+ * Enregistre un message dans un fichier de log spécifique
+ * Message non loggué si
+ * - environment = SILENT
+ * - level = WARNING et environment = PRODUCTION
+ * - level = NOTICE et environment = PRODUCTION
+ * @param $information message d'erreur / information à enregistrer
+ * @param $level niveau d'erreur
+ * @param $file_name fichier de log, par défaut LOG_PATH/application.log
+ */
+ public static function record ($information, $level, $file_name = null) {
+ $env = Minz_Configuration::environment ();
+
+ if (! ($env === Minz_Configuration::SILENT
+ || ($env === Minz_Configuration::PRODUCTION
+ && ($level >= Minz_Log::NOTICE)))) {
+ if ($file_name === null) {
+ $file_name = LOG_PATH . '/' . Minz_Session::param('currentUser', '_') . '.log';
+ }
+
+ switch ($level) {
+ case Minz_Log::ERROR :
+ $level_label = 'error';
+ break;
+ case Minz_Log::WARNING :
+ $level_label = 'warning';
+ break;
+ case Minz_Log::NOTICE :
+ $level_label = 'notice';
+ break;
+ case Minz_Log::DEBUG :
+ $level_label = 'debug';
+ break;
+ default :
+ $level_label = 'unknown';
+ }
+
+ $log = '[' . date('r') . ']'
+ . ' [' . $level_label . ']'
+ . ' --- ' . $information . "\n";
+
+ if (file_put_contents($file_name, $log, FILE_APPEND | LOCK_EX) === false) {
+ throw new Minz_PermissionDeniedException($file_name, Minz_Exception::ERROR);
+ }
+ }
+ }
+
+ /**
+ * Automatise le log des variables globales $_GET et $_POST
+ * Fait appel à la fonction record(...)
+ * Ne fonctionne qu'en environnement "development"
+ * @param $file_name fichier de log, par défaut LOG_PATH/application.log
+ */
+ public static function recordRequest($file_name = null) {
+ $msg_get = str_replace("\n", '', '$_GET content : ' . print_r($_GET, true));
+ $msg_post = str_replace("\n", '', '$_POST content : ' . print_r($_POST, true));
+
+ self::record($msg_get, Minz_Log::DEBUG, $file_name);
+ self::record($msg_post, Minz_Log::DEBUG, $file_name);
+ }
+}
diff --git a/lib/Minz/Model.php b/lib/Minz/Model.php
new file mode 100644
index 000000000..adbaba942
--- /dev/null
+++ b/lib/Minz/Model.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe Model représente un modèle de l'application (représentation MVC)
+ */
+class Minz_Model {
+
+}
diff --git a/lib/Minz/ModelArray.php b/lib/Minz/ModelArray.php
new file mode 100644
index 000000000..ff23dbc83
--- /dev/null
+++ b/lib/Minz/ModelArray.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe Model_array représente le modèle interragissant avec les fichiers de type texte gérant des tableaux php
+ */
+class Minz_ModelArray {
+ /**
+ * $filename est le nom du fichier
+ */
+ protected $filename;
+
+ /**
+ * Ouvre le fichier indiqué, charge le tableau dans $array et le $filename
+ * @param $filename le nom du fichier à ouvrir contenant un tableau
+ * Remarque : $array sera obligatoirement un tableau
+ */
+ public function __construct ($filename) {
+ $this->filename = $filename;
+ }
+
+ protected function loadArray() {
+ if (!file_exists($this->filename)) {
+ throw new Minz_FileNotExistException($this->filename, Minz_Exception::WARNING);
+ }
+ elseif (($handle = $this->getLock()) === false) {
+ throw new Minz_PermissionDeniedException($this->filename);
+ } else {
+ $data = include($this->filename);
+ $this->releaseLock($handle);
+
+ if ($data === false) {
+ throw new Minz_PermissionDeniedException($this->filename);
+ } elseif (!is_array($data)) {
+ $data = array();
+ }
+ return $data;
+ }
+ }
+
+ /**
+ * Sauve le tableau $array dans le fichier $filename
+ **/
+ protected function writeArray($array) {
+ if (file_put_contents($this->filename, "<?php\n return " . var_export($array, true) . ';', LOCK_EX) === false) {
+ throw new Minz_PermissionDeniedException($this->filename);
+ }
+ if (function_exists('opcache_invalidate')) {
+ opcache_invalidate($this->filename); //Clear PHP 5.5+ cache for include
+ }
+ return true;
+ }
+
+ private function getLock() {
+ $handle = fopen($this->filename, 'r');
+ if ($handle === false) {
+ return false;
+ }
+
+ $count = 50;
+ while (!flock($handle, LOCK_SH) && $count > 0) {
+ $count--;
+ usleep(1000);
+ }
+
+ if ($count > 0) {
+ return $handle;
+ } else {
+ fclose($handle);
+ return false;
+ }
+ }
+
+ private function releaseLock($handle) {
+ flock($handle, LOCK_UN);
+ fclose($handle);
+ }
+}
diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php
new file mode 100644
index 000000000..831df13a2
--- /dev/null
+++ b/lib/Minz/ModelPdo.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe Model_sql représente le modèle interragissant avec les bases de données
+ * Seul la connexion MySQL est prise en charge pour le moment
+ */
+class Minz_ModelPdo {
+
+ /**
+ * Partage la connexion à la base de données entre toutes les instances.
+ */
+ public static $useSharedBd = true;
+ private static $sharedBd = null;
+ private static $sharedPrefix;
+
+ /**
+ * $bd variable représentant la base de données
+ */
+ protected $bd;
+
+ protected $prefix;
+
+ /**
+ * Créé la connexion à la base de données à l'aide des variables
+ * HOST, BASE, USER et PASS définies dans le fichier de configuration
+ */
+ public function __construct () {
+ if (self::$useSharedBd && self::$sharedBd != null) {
+ $this->bd = self::$sharedBd;
+ $this->prefix = self::$sharedPrefix;
+ return;
+ }
+
+ $db = Minz_Configuration::dataBase ();
+ $driver_options = null;
+
+ try {
+ $type = $db['type'];
+ if($type == 'mysql') {
+ $string = $type
+ . ':host=' . $db['host']
+ . ';dbname=' . $db['base']
+ . ';charset=utf8';
+ $driver_options = array(
+ PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
+ );
+ } elseif($type == 'sqlite') {
+ $string = $type . ':/' . DATA_PATH . $db['base'] . '.sqlite'; //TODO: DEBUG UTF-8 http://www.siteduzero.com/forum/sujet/sqlite-connexion-utf-8-18797
+ }
+
+ $this->bd = new FreshPDO (
+ $string,
+ $db['user'],
+ $db['password'],
+ $driver_options
+ );
+ self::$sharedBd = $this->bd;
+
+ $this->prefix = $db['prefix'] . Minz_Session::param('currentUser', '_') . '_';
+ self::$sharedPrefix = $this->prefix;
+ } catch (Exception $e) {
+ throw new Minz_PDOConnectionException (
+ $string,
+ $db['user'], Minz_Exception::ERROR
+ );
+ }
+ }
+
+ public function beginTransaction() {
+ $this->bd->beginTransaction();
+ }
+ public function commit() {
+ $this->bd->commit();
+ }
+ public function rollBack() {
+ $this->bd->rollBack();
+ }
+
+ public function size($all = false) {
+ $db = Minz_Configuration::dataBase ();
+ $sql = 'SELECT SUM(data_length + index_length) FROM information_schema.TABLES WHERE table_schema = ?';
+ $values = array ($db['base']);
+ if (!$all) {
+ $sql .= ' AND table_name LIKE ?';
+ $values[] = $this->prefix . '%';
+ }
+ $stm = $this->bd->prepare ($sql);
+ $stm->execute ($values);
+ $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0);
+ return $res[0];
+ }
+
+ public static function clean() {
+ self::$sharedBd = null;
+ self::$sharedPrefix = '';
+ }
+}
+
+class FreshPDO extends PDO {
+ private static function check($statement) {
+ if (preg_match('/^(?:UPDATE|INSERT|DELETE)/i', $statement)) {
+ invalidateHttpCache();
+ }
+ }
+
+ public function prepare ($statement, $driver_options = array()) {
+ FreshPDO::check($statement);
+ return parent::prepare($statement, $driver_options);
+ }
+
+ public function exec ($statement) {
+ FreshPDO::check($statement);
+ return parent::exec($statement);
+ }
+}
diff --git a/lib/Minz/PDOConnectionException.php b/lib/Minz/PDOConnectionException.php
new file mode 100644
index 000000000..faf2e0fe9
--- /dev/null
+++ b/lib/Minz/PDOConnectionException.php
@@ -0,0 +1,9 @@
+<?php
+class Minz_PDOConnectionException extends Minz_Exception {
+ public function __construct ($string_connection, $user, $code = self::ERROR) {
+ $message = 'Access to database is denied for `' . $user . '`'
+ . ' (`' . $string_connection . '`)';
+
+ parent::__construct ($message, $code);
+ }
+}
diff --git a/lib/Minz/Paginator.php b/lib/Minz/Paginator.php
new file mode 100644
index 000000000..5858e76a5
--- /dev/null
+++ b/lib/Minz/Paginator.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe Paginator permet de gérer la pagination de l'application facilement
+ */
+class Minz_Paginator {
+ /**
+ * $items tableau des éléments à afficher/gérer
+ */
+ private $items = array ();
+
+ /**
+ * $nbItemsPerPage le nombre d'éléments par page
+ */
+ private $nbItemsPerPage = 10;
+
+ /**
+ * $currentPage page actuelle à gérer
+ */
+ private $currentPage = 1;
+
+ /**
+ * $nbPage le nombre de pages de pagination
+ */
+ private $nbPage = 1;
+
+ /**
+ * $nbItems le nombre d'éléments
+ */
+ private $nbItems = 0;
+
+ /**
+ * Constructeur
+ * @param $items les éléments à gérer
+ */
+ public function __construct ($items) {
+ $this->_items ($items);
+ $this->_nbItems (count ($this->items (true)));
+ $this->_nbItemsPerPage ($this->nbItemsPerPage);
+ $this->_currentPage ($this->currentPage);
+ }
+
+ /**
+ * Permet d'afficher la pagination
+ * @param $view nom du fichier de vue situé dans /app/views/helpers/
+ * @param $getteur variable de type $_GET[] permettant de retrouver la page
+ */
+ public function render ($view, $getteur) {
+ $view = APP_PATH . '/views/helpers/'.$view;
+
+ if (file_exists ($view)) {
+ include ($view);
+ }
+ }
+
+ /**
+ * Permet de retrouver la page d'un élément donné
+ * @param $item l'élément à retrouver
+ * @return la page à laquelle se trouve l'élément (false si non trouvé)
+ */
+ public function pageByItem ($item) {
+ $page = false;
+ $i = 0;
+
+ do {
+ if ($item == $this->items[$i]) {
+ $page = ceil (($i + 1) / $this->nbItemsPerPage);
+ }
+
+ $i++;
+ } while (!$page && $i < $this->nbItems ());
+
+ return $page;
+ }
+
+ /**
+ * Permet de retrouver la position d'un élément donné (à partir de 0)
+ * @param $item l'élément à retrouver
+ * @return la position à laquelle se trouve l'élément (false si non trouvé)
+ */
+ public function positionByItem ($item) {
+ $find = false;
+ $i = 0;
+
+ do {
+ if ($item == $this->items[$i]) {
+ $find = true;
+ } else {
+ $i++;
+ }
+ } while (!$find && $i < $this->nbItems ());
+
+ return $i;
+ }
+
+ /**
+ * Permet de récupérer un item par sa position
+ * @param $pos la position de l'élément
+ * @return l'item situé à $pos (dernier item si $pos<0, 1er si $pos>=count($items))
+ */
+ public function itemByPosition ($pos) {
+ if ($pos < 0) {
+ $pos = $this->nbItems () - 1;
+ }
+ if ($pos >= count($this->items)) {
+ $pos = 0;
+ }
+
+ return $this->items[$pos];
+ }
+
+ /**
+ * GETTEURS
+ */
+ /**
+ * @param $all si à true, retourne tous les éléments sans prendre en compte la pagination
+ */
+ public function items ($all = false) {
+ $array = array ();
+ $nbItems = $this->nbItems ();
+
+ if ($nbItems <= $this->nbItemsPerPage || $all) {
+ $array = $this->items;
+ } else {
+ $begin = ($this->currentPage - 1) * $this->nbItemsPerPage;
+ $counter = 0;
+ $i = 0;
+
+ foreach ($this->items as $key => $item) {
+ if ($i >= $begin) {
+ $array[$key] = $item;
+ $counter++;
+ }
+ if ($counter >= $this->nbItemsPerPage) {
+ break;
+ }
+ $i++;
+ }
+ }
+
+ return $array;
+ }
+ public function nbItemsPerPage () {
+ return $this->nbItemsPerPage;
+ }
+ public function currentPage () {
+ return $this->currentPage;
+ }
+ public function nbPage () {
+ return $this->nbPage;
+ }
+ public function nbItems () {
+ return $this->nbItems;
+ }
+
+ /**
+ * SETTEURS
+ */
+ public function _items ($items) {
+ if (is_array ($items)) {
+ $this->items = $items;
+ }
+
+ $this->_nbPage ();
+ }
+ public function _nbItemsPerPage ($nbItemsPerPage) {
+ if ($nbItemsPerPage > $this->nbItems ()) {
+ $nbItemsPerPage = $this->nbItems ();
+ }
+ if ($nbItemsPerPage < 0) {
+ $nbItemsPerPage = 0;
+ }
+
+ $this->nbItemsPerPage = $nbItemsPerPage;
+ $this->_nbPage ();
+ }
+ public function _currentPage ($page) {
+ if($page < 1 || ($page > $this->nbPage && $this->nbPage > 0)) {
+ throw new CurrentPagePaginationException ($page);
+ }
+
+ $this->currentPage = $page;
+ }
+ private function _nbPage () {
+ if ($this->nbItemsPerPage > 0) {
+ $this->nbPage = ceil ($this->nbItems () / $this->nbItemsPerPage);
+ }
+ }
+ public function _nbItems ($value) {
+ $this->nbItems = $value;
+ }
+}
diff --git a/lib/Minz/PermissionDeniedException.php b/lib/Minz/PermissionDeniedException.php
new file mode 100644
index 000000000..61be530d3
--- /dev/null
+++ b/lib/Minz/PermissionDeniedException.php
@@ -0,0 +1,8 @@
+<?php
+class Minz_PermissionDeniedException extends Minz_Exception {
+ public function __construct ($file_name, $code = self::ERROR) {
+ $message = 'Permission is denied for `' . $file_name.'`';
+
+ parent::__construct ($message, $code);
+ }
+}
diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php
new file mode 100644
index 000000000..d4e1355d7
--- /dev/null
+++ b/lib/Minz/Request.php
@@ -0,0 +1,204 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * Request représente la requête http
+ */
+class Minz_Request {
+ private static $controller_name = '';
+ private static $action_name = '';
+ private static $params = array ();
+
+ private static $default_controller_name = 'index';
+ private static $default_action_name = 'index';
+
+ public static $reseted = true;
+
+ /**
+ * Getteurs
+ */
+ public static function controllerName () {
+ return self::$controller_name;
+ }
+ public static function actionName () {
+ return self::$action_name;
+ }
+ public static function params () {
+ return self::$params;
+ }
+ static function htmlspecialchars_utf8 ($p) {
+ return htmlspecialchars($p, ENT_COMPAT, 'UTF-8');
+ }
+ public static function param ($key, $default = false, $specialchars = false) {
+ if (isset (self::$params[$key])) {
+ $p = self::$params[$key];
+ if(is_object($p) || $specialchars) {
+ return $p;
+ } elseif(is_array($p)) {
+ return array_map('self::htmlspecialchars_utf8', $p);
+ } else {
+ return self::htmlspecialchars_utf8($p);
+ }
+ } else {
+ return $default;
+ }
+ }
+ public static function defaultControllerName () {
+ return self::$default_controller_name;
+ }
+ public static function defaultActionName () {
+ return self::$default_action_name;
+ }
+
+ /**
+ * Setteurs
+ */
+ public static function _controllerName ($controller_name) {
+ self::$controller_name = $controller_name;
+ }
+ public static function _actionName ($action_name) {
+ self::$action_name = $action_name;
+ }
+ public static function _params ($params) {
+ if (!is_array($params)) {
+ $params = array ($params);
+ }
+
+ self::$params = $params;
+ }
+ public static function _param ($key, $value = false) {
+ if ($value === false) {
+ unset (self::$params[$key]);
+ } else {
+ self::$params[$key] = $value;
+ }
+ }
+
+ /**
+ * Initialise la Request
+ */
+ public static function init () {
+ self::magicQuotesOff ();
+ }
+
+ /**
+ * Retourn le nom de domaine du site
+ */
+ public static function getDomainName () {
+ return $_SERVER['HTTP_HOST'];
+ }
+
+ /**
+ * Détermine la base de l'url
+ * @return la base de l'url
+ */
+ public static function getBaseUrl () {
+ $defaultBaseUrl = Minz_Configuration::baseUrl();
+ if (!empty($defaultBaseUrl)) {
+ return $defaultBaseUrl;
+ } elseif (isset($_SERVER['REQUEST_URI'])) {
+ return dirname($_SERVER['REQUEST_URI']) . '/';
+ } else {
+ return '/';
+ }
+ }
+
+ /**
+ * Récupère l'URI de la requête
+ * @return l'URI
+ */
+ public static function getURI () {
+ if (isset ($_SERVER['REQUEST_URI'])) {
+ $base_url = self::getBaseUrl ();
+ $uri = $_SERVER['REQUEST_URI'];
+
+ $len_base_url = strlen ($base_url);
+ $real_uri = substr ($uri, $len_base_url);
+ } else {
+ $real_uri = '';
+ }
+
+ return $real_uri;
+ }
+
+ /**
+ * Relance une requête
+ * @param $url l'url vers laquelle est relancée la requête
+ * @param $redirect si vrai, force la redirection http
+ * > sinon, le dispatcher recharge en interne
+ */
+ public static function forward ($url = array (), $redirect = false) {
+ $url = Minz_Url::checkUrl ($url);
+
+ if ($redirect) {
+ header ('Location: ' . Minz_Url::display ($url, 'php'));
+ exit ();
+ } else {
+ self::$reseted = true;
+
+ self::_controllerName ($url['c']);
+ self::_actionName ($url['a']);
+ self::_params (array_merge (
+ self::$params,
+ $url['params']
+ ));
+ }
+ }
+
+ /**
+ * Permet de récupérer une variable de type $_GET
+ * @param $param nom de la variable
+ * @param $default valeur par défaut à attribuer à la variable
+ * @return $_GET[$param]
+ * $_GET si $param = false
+ * $default si $_GET[$param] n'existe pas
+ */
+ public static function fetchGET ($param = false, $default = false) {
+ if ($param === false) {
+ return $_GET;
+ } elseif (isset ($_GET[$param])) {
+ return $_GET[$param];
+ } else {
+ return $default;
+ }
+ }
+
+ /**
+ * Permet de récupérer une variable de type $_POST
+ * @param $param nom de la variable
+ * @param $default valeur par défaut à attribuer à la variable
+ * @return $_POST[$param]
+ * $_POST si $param = false
+ * $default si $_POST[$param] n'existe pas
+ */
+ public static function fetchPOST ($param = false, $default = false) {
+ if ($param === false) {
+ return $_POST;
+ } elseif (isset ($_POST[$param])) {
+ return $_POST[$param];
+ } else {
+ return $default;
+ }
+ }
+
+ /**
+ * Méthode désactivant les magic_quotes pour les variables
+ * $_GET
+ * $_POST
+ * $_COOKIE
+ */
+ private static function magicQuotesOff () {
+ if (get_magic_quotes_gpc ()) {
+ $_GET = Minz_Helper::stripslashes_r ($_GET);
+ $_POST = Minz_Helper::stripslashes_r ($_POST);
+ $_COOKIE = Minz_Helper::stripslashes_r ($_COOKIE);
+ }
+ }
+
+ public static function isPost () {
+ return !empty ($_POST) || !empty ($_FILES);
+ }
+}
diff --git a/lib/Minz/Response.php b/lib/Minz/Response.php
new file mode 100644
index 000000000..f8ea3d946
--- /dev/null
+++ b/lib/Minz/Response.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * Response représente la requête http renvoyée à l'utilisateur
+ */
+class Minz_Response {
+ private static $header = 'HTTP/1.0 200 OK';
+ private static $body = '';
+
+ /**
+ * Mets à jour le body de la Response
+ * @param $text le texte à incorporer dans le body
+ */
+ public static function setBody ($text) {
+ self::$body = $text;
+ }
+
+ /**
+ * Mets à jour le header de la Response
+ * @param $code le code HTTP, valeurs possibles
+ * - 200 (OK)
+ * - 403 (Forbidden)
+ * - 404 (Forbidden)
+ * - 500 (Forbidden) -> par défaut si $code erroné
+ * - 503 (Forbidden)
+ */
+ public static function setHeader ($code) {
+ switch ($code) {
+ case 200 :
+ self::$header = 'HTTP/1.0 200 OK';
+ break;
+ case 403 :
+ self::$header = 'HTTP/1.0 403 Forbidden';
+ break;
+ case 404 :
+ self::$header = 'HTTP/1.0 404 Not Found';
+ break;
+ case 500 :
+ self::$header = 'HTTP/1.0 500 Internal Server Error';
+ break;
+ case 503 :
+ self::$header = 'HTTP/1.0 503 Service Unavailable';
+ break;
+ default :
+ self::$header = 'HTTP/1.0 500 Internal Server Error';
+ }
+ }
+
+ /**
+ * Envoie la Response à l'utilisateur
+ */
+ public static function send () {
+ header (self::$header);
+ echo self::$body;
+ }
+}
diff --git a/lib/Minz/RouteNotFoundException.php b/lib/Minz/RouteNotFoundException.php
new file mode 100644
index 000000000..dc4f6fbad
--- /dev/null
+++ b/lib/Minz/RouteNotFoundException.php
@@ -0,0 +1,16 @@
+<?php
+class Minz_RouteNotFoundException extends Minz_Exception {
+ private $route;
+
+ public function __construct ($route, $code = self::ERROR) {
+ $this->route = $route;
+
+ $message = 'Route `' . $route . '` not found';
+
+ parent::__construct ($message, $code);
+ }
+
+ public function route () {
+ return $this->route;
+ }
+}
diff --git a/lib/Minz/Router.php b/lib/Minz/Router.php
new file mode 100644
index 000000000..1ccd72597
--- /dev/null
+++ b/lib/Minz/Router.php
@@ -0,0 +1,209 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe Router gère le routage de l'application
+ * Les routes sont définies dans APP_PATH.'/configuration/routes.php'
+ */
+class Minz_Router {
+ const ROUTES_PATH_NAME = '/configuration/routes.php';
+
+ private $routes = array ();
+
+ /**
+ * Constructeur
+ * @exception FileNotExistException si ROUTES_PATH_NAME n'existe pas
+ * et que l'on utilise l'url rewriting
+ */
+ public function __construct () {
+ if (Minz_Configuration::useUrlRewriting ()) {
+ if (file_exists (APP_PATH . self::ROUTES_PATH_NAME)) {
+ $routes = include (
+ APP_PATH . self::ROUTES_PATH_NAME
+ );
+
+ if (!is_array ($routes)) {
+ $routes = array ();
+ }
+
+ $this->routes = array_map (
+ array ('Url', 'checkUrl'),
+ $routes
+ );
+ } else {
+ throw new Minz_FileNotExistException (
+ self::ROUTES_PATH_NAME,
+ Minz_Exception::ERROR
+ );
+ }
+ }
+ }
+
+ /**
+ * Initialise le Router en déterminant le couple Controller / Action
+ * Mets à jour la Request
+ * @exception RouteNotFoundException si l'uri n'est pas présente dans
+ * > la table de routage
+ */
+ public function init () {
+ $url = array ();
+
+ if (Minz_Configuration::useUrlRewriting ()) {
+ try {
+ $url = $this->buildWithRewriting ();
+ } catch (Minz_RouteNotFoundException $e) {
+ throw $e;
+ }
+ } else {
+ $url = $this->buildWithoutRewriting ();
+ }
+
+ $url['params'] = array_merge (
+ $url['params'],
+ Minz_Request::fetchPOST ()
+ );
+
+ Minz_Request::forward ($url);
+ }
+
+ /**
+ * Retourne un tableau représentant l'url passée par la barre d'adresses
+ * Ne se base PAS sur la table de routage
+ * @return tableau représentant l'url
+ */
+ public function buildWithoutRewriting () {
+ $url = array ();
+
+ $url['c'] = Minz_Request::fetchGET (
+ 'c',
+ Minz_Request::defaultControllerName ()
+ );
+ $url['a'] = Minz_Request::fetchGET (
+ 'a',
+ Minz_Request::defaultActionName ()
+ );
+ $url['params'] = Minz_Request::fetchGET ();
+
+ // post-traitement
+ unset ($url['params']['c']);
+ unset ($url['params']['a']);
+
+ return $url;
+ }
+
+ /**
+ * Retourne un tableau représentant l'url passée par la barre d'adresses
+ * Se base sur la table de routage
+ * @return tableau représentant l'url
+ * @exception RouteNotFoundException si l'uri n'est pas présente dans
+ * > la table de routage
+ */
+ public function buildWithRewriting () {
+ $url = array ();
+ $uri = Minz_Request::getURI ();
+ $find = false;
+
+ foreach ($this->routes as $route) {
+ $regex = '*^' . $route['route'] . '$*';
+ if (preg_match ($regex, $uri, $matches)) {
+ $url['c'] = $route['controller'];
+ $url['a'] = $route['action'];
+ $url['params'] = $this->getParams (
+ $route['params'],
+ $matches
+ );
+ $find = true;
+ break;
+ }
+ }
+
+ if (!$find && $uri != '/') {
+ throw new Minz_RouteNotFoundException (
+ $uri,
+ Minz_Exception::ERROR
+ );
+ }
+
+ // post-traitement
+ $url = Minz_Url::checkUrl ($url);
+
+ return $url;
+ }
+
+ /**
+ * Retourne l'uri d'une url en se basant sur la table de routage
+ * @param l'url sous forme de tableau
+ * @return l'uri formatée (string) selon une route trouvée
+ */
+ public function printUriRewrited ($url) {
+ $route = $this->searchRoute ($url);
+
+ if ($route !== false) {
+ return $this->replaceParams ($route, $url['params']);
+ }
+
+ return '';
+ }
+
+ /**
+ * Recherche la route correspondante à une url
+ * @param l'url sous forme de tableau
+ * @return la route telle que spécifiée dans la table de routage,
+ * false si pas trouvée
+ */
+ public function searchRoute ($url) {
+ foreach ($this->routes as $route) {
+ if ($route['controller'] == $url['c']
+ && $route['action'] == $url['a']) {
+ // calcule la différence des tableaux de params
+ $params = array_flip ($route['params']);
+ $difference_params = array_diff_key (
+ $params,
+ $url['params']
+ );
+
+ // vérifie que pas de différence
+ // et le cas où $params est vide et pas $url['params']
+ if (empty ($difference_params)
+ && (!empty ($params) || empty ($url['params']))) {
+ return $route;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Récupère un tableau dont
+ * - les clés sont définies dans $params_route
+ * - les valeurs sont situées dans $matches
+ * Le tableau $matches est décalé de +1 par rapport à $params_route
+ */
+ private function getParams($params_route, $matches) {
+ $params = array ();
+
+ for ($i = 0; $i < count ($params_route); $i++) {
+ $param = $params_route[$i];
+ $params[$param] = $matches[$i + 1];
+ }
+
+ return $params;
+ }
+
+ /**
+ * Remplace les éléments de la route par les valeurs contenues dans $params
+ */
+ private function replaceParams ($route, $params_replace) {
+ $uri = $route['route'];
+ $params = array();
+ foreach($route['params'] as $param) {
+ $uri = preg_replace('#\((.+)\)#U', $params_replace[$param], $uri, 1);
+ }
+
+ return stripslashes($uri);
+ }
+}
diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php
new file mode 100644
index 000000000..ddabc4658
--- /dev/null
+++ b/lib/Minz/Session.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * La classe Session gère la session utilisateur
+ * C'est un singleton
+ */
+class Minz_Session {
+ /**
+ * $session stocke les variables de session
+ */
+ private static $session = array (); //TODO: Try to avoid having another local copy
+
+ /**
+ * Initialise la session, avec un nom
+ * Le nom de session est utilisé comme nom pour les cookies et les URLs (i.e. PHPSESSID).
+ * Il ne doit contenir que des caractères alphanumériques ; il doit être court et descriptif
+ */
+ public static function init ($name) {
+ // démarre la session
+ session_name ($name);
+ session_set_cookie_params (0, dirname(empty($_SERVER['REQUEST_URI']) ? '/' : dirname($_SERVER['REQUEST_URI'])), null, false, true);
+ session_start ();
+
+ if (isset ($_SESSION)) {
+ self::$session = $_SESSION;
+ }
+ }
+
+
+ /**
+ * Permet de récupérer une variable de session
+ * @param $p le paramètre à récupérer
+ * @return la valeur de la variable de session, false si n'existe pas
+ */
+ public static function param ($p, $default = false) {
+ return isset(self::$session[$p]) ? self::$session[$p] : $default;
+ }
+
+
+ /**
+ * Permet de créer ou mettre à jour une variable de session
+ * @param $p le paramètre à créer ou modifier
+ * @param $v la valeur à attribuer, false pour supprimer
+ */
+ public static function _param ($p, $v = false) {
+ if ($v === false) {
+ unset ($_SESSION[$p]);
+ unset (self::$session[$p]);
+ } else {
+ $_SESSION[$p] = $v;
+ self::$session[$p] = $v;
+ }
+ }
+
+
+ /**
+ * Permet d'effacer une session
+ * @param $force si à false, n'efface pas le paramètre de langue
+ */
+ public static function unset_session ($force = false) {
+ $language = self::param ('language');
+
+ session_destroy();
+ self::$session = array ();
+
+ if (!$force) {
+ self::_param ('language', $language);
+ Minz_Translate::reset ();
+ }
+ }
+}
diff --git a/lib/Minz/Translate.php b/lib/Minz/Translate.php
new file mode 100644
index 000000000..e14f783f7
--- /dev/null
+++ b/lib/Minz/Translate.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * La classe Translate se charge de la traduction
+ * Utilise les fichiers du répertoire /app/i18n/
+ */
+class Minz_Translate {
+ /**
+ * $language est la langue à afficher
+ */
+ private static $language;
+
+ /**
+ * $translates est le tableau de correspondance
+ * $key => $traduction
+ */
+ private static $translates = array ();
+
+ /**
+ * Inclus le fichier de langue qui va bien
+ * l'enregistre dans $translates
+ */
+ public static function init () {
+ $l = Minz_Configuration::language ();
+ self::$language = Minz_Session::param ('language', $l);
+
+ $l_path = APP_PATH . '/i18n/' . self::$language . '.php';
+
+ if (file_exists ($l_path)) {
+ self::$translates = include ($l_path);
+ }
+ }
+
+ /**
+ * Alias de init
+ */
+ public static function reset () {
+ self::init ();
+ }
+
+ /**
+ * Traduit une clé en sa valeur du tableau $translates
+ * @param $key la clé à traduire
+ * @return la valeur correspondante à la clé
+ * > si non présente dans le tableau, on retourne la clé elle-même
+ */
+ public static function t ($key) {
+ $translate = $key;
+
+ if (isset (self::$translates[$key])) {
+ $translate = self::$translates[$key];
+ }
+
+ $args = func_get_args ();
+ unset($args[0]);
+
+ return vsprintf ($translate, $args);
+ }
+
+ /**
+ * Retourne la langue utilisée actuellement
+ * @return la langue
+ */
+ public static function language () {
+ return self::$language;
+ }
+}
diff --git a/lib/Minz/Url.php b/lib/Minz/Url.php
new file mode 100644
index 000000000..17f1ddece
--- /dev/null
+++ b/lib/Minz/Url.php
@@ -0,0 +1,132 @@
+<?php
+
+/**
+ * La classe Url permet de gérer les URL à travers MINZ
+ */
+class Minz_Url {
+ /**
+ * Affiche une Url formatée selon que l'on utilise l'url_rewriting ou non
+ * si oui, on cherche dans la table de routage la correspondance pour formater
+ * @param $url l'url à formater définie comme un tableau :
+ * $url['c'] = controller
+ * $url['a'] = action
+ * $url['params'] = tableau des paramètres supplémentaires
+ * $url['protocol'] = protocole à utiliser (http par défaut)
+ * ou comme une chaîne de caractère
+ * @param $encodage pour indiquer comment encoder les & (& ou &amp; pour html)
+ * @return l'url formatée
+ */
+ public static function display ($url = array (), $encodage = 'html', $absolute = false) {
+ $isArray = is_array($url);
+
+ if ($isArray) {
+ $url = self::checkUrl ($url);
+ }
+
+ $url_string = '';
+
+ if ($absolute) {
+ if ($isArray && isset ($url['protocol'])) {
+ $protocol = $url['protocol'];
+ } elseif (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
+ $protocol = 'https:';
+ } else {
+ $protocol = 'http:';
+ }
+ $url_string = $protocol . '//' . Minz_Request::getDomainName () . Minz_Request::getBaseUrl ();
+ } else {
+ $url_string = $isArray ? '.' : PUBLIC_RELATIVE;
+ }
+
+ if ($isArray) {
+ $router = new Minz_Router ();
+
+ if (Minz_Configuration::useUrlRewriting ()) {
+ $url_string .= $router->printUriRewrited ($url);
+ } else {
+ $url_string .= self::printUri ($url, $encodage);
+ }
+ } else {
+ $url_string .= $url;
+ }
+
+ return $url_string;
+ }
+
+ /**
+ * Construit l'URI d'une URL sans url rewriting
+ * @param l'url sous forme de tableau
+ * @param $encodage pour indiquer comment encoder les & (& ou &amp; pour html)
+ * @return l'uri sous la forme ?key=value&key2=value2
+ */
+ private static function printUri ($url, $encodage) {
+ $uri = '';
+ $separator = '/?';
+
+ if($encodage == 'html') {
+ $and = '&amp;';
+ } else {
+ $and = '&';
+ }
+
+ if (isset ($url['c'])
+ && $url['c'] != Minz_Request::defaultControllerName ()) {
+ $uri .= $separator . 'c=' . $url['c'];
+ $separator = $and;
+ }
+
+ if (isset ($url['a'])
+ && $url['a'] != Minz_Request::defaultActionName ()) {
+ $uri .= $separator . 'a=' . $url['a'];
+ $separator = $and;
+ }
+
+ if (isset ($url['params'])) {
+ foreach ($url['params'] as $key => $param) {
+ $uri .= $separator . $key . '=' . $param;
+ $separator = $and;
+ }
+ }
+
+ return $uri;
+ }
+
+ /**
+ * Vérifie que les éléments du tableau représentant une url soit ok
+ * @param l'url sous forme de tableau (sinon renverra directement $url)
+ * @return l'url vérifié
+ */
+ public static function checkUrl ($url) {
+ $url_checked = $url;
+
+ if (is_array ($url)) {
+ if (!isset ($url['c'])) {
+ $url_checked['c'] = Minz_Request::defaultControllerName ();
+ }
+ if (!isset ($url['a'])) {
+ $url_checked['a'] = Minz_Request::defaultActionName ();
+ }
+ if (!isset ($url['params'])) {
+ $url_checked['params'] = array ();
+ }
+ }
+
+ return $url_checked;
+ }
+}
+
+function _url ($controller, $action) {
+ $nb_args = func_num_args ();
+
+ if($nb_args < 2 || $nb_args % 2 != 0) {
+ return false;
+ }
+
+ $args = func_get_args ();
+ $params = array ();
+ for($i = 2; $i < $nb_args; $i = $i + 2) {
+ $params[$args[$i]] = $args[$i + 1];
+ }
+
+ return Minz_Url::display (array ('c' => $controller, 'a' => $action, 'params' => $params));
+}
diff --git a/lib/Minz/View.php b/lib/Minz/View.php
new file mode 100644
index 000000000..e170bd406
--- /dev/null
+++ b/lib/Minz/View.php
@@ -0,0 +1,232 @@
+<?php
+/**
+ * MINZ - Copyright 2011 Marien Fressinaud
+ * Sous licence AGPL3 <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * La classe View représente la vue de l'application
+ */
+class Minz_View {
+ const VIEWS_PATH_NAME = '/views';
+ const LAYOUT_PATH_NAME = '/layout';
+ const LAYOUT_FILENAME = '/layout.phtml';
+
+ private $view_filename = '';
+ private $use_layout = null;
+
+ private static $title = '';
+ private static $styles = array ();
+ private static $scripts = array ();
+
+ private static $params = array ();
+
+ /**
+ * Constructeur
+ * Détermine si on utilise un layout ou non
+ */
+ public function __construct () {
+ $this->view_filename = APP_PATH
+ . self::VIEWS_PATH_NAME . '/'
+ . Minz_Request::controllerName () . '/'
+ . Minz_Request::actionName () . '.phtml';
+
+ self::$title = Minz_Configuration::title ();
+ }
+
+ /**
+ * Construit la vue
+ */
+ public function build () {
+ if ($this->use_layout === null) { //TODO: avoid file_exists and require views to be explicit
+ $this->use_layout = file_exists (APP_PATH . self::LAYOUT_PATH_NAME . self::LAYOUT_FILENAME);
+ }
+ if ($this->use_layout) {
+ $this->buildLayout ();
+ } else {
+ $this->render ();
+ }
+ }
+
+ /**
+ * Construit le layout
+ */
+ public function buildLayout () {
+ include (
+ APP_PATH
+ . self::LAYOUT_PATH_NAME
+ . self::LAYOUT_FILENAME
+ );
+ }
+
+ /**
+ * Affiche la Vue en elle-même
+ */
+ public function render () {
+ if ((include($this->view_filename)) === false) {
+ Minz_Log::record ('File not found: `'
+ . $this->view_filename . '`',
+ Minz_Log::NOTICE);
+ }
+ }
+
+ /**
+ * Ajoute un élément du layout
+ * @param $part l'élément partial à ajouter
+ */
+ public function partial ($part) {
+ $fic_partial = APP_PATH
+ . self::LAYOUT_PATH_NAME . '/'
+ . $part . '.phtml';
+
+ if ((include($fic_partial)) === false) {
+ Minz_Log::record ('File not found: `'
+ . $fic_partial . '`',
+ Minz_Log::WARNING);
+ }
+ }
+
+ /**
+ * Affiche un élément graphique situé dans APP./views/helpers/
+ * @param $helper l'élément à afficher
+ */
+ public function renderHelper ($helper) {
+ $fic_helper = APP_PATH
+ . '/views/helpers/'
+ . $helper . '.phtml';
+
+ if ((include($fic_helper)) === false) {;
+ Minz_Log::record ('File not found: `'
+ . $fic_helper . '`',
+ Minz_Log::WARNING);
+ }
+ }
+
+ /**
+ * Permet de choisir si on souhaite utiliser le layout
+ * @param $use true si on souhaite utiliser le layout, false sinon
+ */
+ public function _useLayout ($use) {
+ $this->use_layout = $use;
+ }
+
+ /**
+ * Gestion du titre
+ */
+ public static function title () {
+ return self::$title;
+ }
+ public static function headTitle () {
+ return '<title>' . self::$title . '</title>' . "\n";
+ }
+ public static function _title ($title) {
+ self::$title = $title;
+ }
+ public static function prependTitle ($title) {
+ self::$title = $title . self::$title;
+ }
+ public static function appendTitle ($title) {
+ self::$title = self::$title . $title;
+ }
+
+ /**
+ * Gestion des feuilles de style
+ */
+ public static function headStyle () {
+ $styles = '';
+
+ foreach(self::$styles as $style) {
+ $cond = $style['cond'];
+ if ($cond) {
+ $styles .= '<!--[if ' . $cond . ']>';
+ }
+
+ $styles .= '<link rel="stylesheet" ' .
+ ($style['media'] === 'all' ? '' : 'media="' . $style['media'] . '" ') .
+ 'href="' . $style['url'] . '" />';
+
+ if ($cond) {
+ $styles .= '<![endif]-->';
+ }
+
+ $styles .= "\n";
+ }
+
+ return $styles;
+ }
+ public static function prependStyle ($url, $media = 'all', $cond = false) {
+ array_unshift (self::$styles, array (
+ 'url' => $url,
+ 'media' => $media,
+ 'cond' => $cond
+ ));
+ }
+ public static function appendStyle ($url, $media = 'all', $cond = false) {
+ self::$styles[] = array (
+ 'url' => $url,
+ 'media' => $media,
+ 'cond' => $cond
+ );
+ }
+
+ /**
+ * Gestion des scripts JS
+ */
+ public static function headScript () {
+ $scripts = '';
+
+ foreach (self::$scripts as $script) {
+ $cond = $script['cond'];
+ if ($cond) {
+ $scripts .= '<!--[if ' . $cond . ']>';
+ }
+
+ $scripts .= '<script src="' . $script['url'] . '"';
+ if ($script['defer']) {
+ $scripts .= ' defer="defer"';
+ }
+ if ($script['async']) {
+ $scripts .= ' async="async"';
+ }
+ $scripts .= '></script>';
+
+ if ($cond) {
+ $scripts .= '<![endif]-->';
+ }
+
+ $scripts .= "\n";
+ }
+
+ return $scripts;
+ }
+ public static function prependScript ($url, $cond = false, $defer = true, $async = true) {
+ array_unshift(self::$scripts, array (
+ 'url' => $url,
+ 'cond' => $cond,
+ 'defer' => $defer,
+ 'async' => $async,
+ ));
+ }
+ public static function appendScript ($url, $cond = false, $defer = true, $async = true) {
+ self::$scripts[] = array (
+ 'url' => $url,
+ 'cond' => $cond,
+ 'defer' => $defer,
+ 'async' => $async,
+ );
+ }
+
+ /**
+ * Gestion des paramètres ajoutés à la vue
+ */
+ public static function _param ($key, $value) {
+ self::$params[$key] = $value;
+ }
+ public function attributeParams () {
+ foreach (Minz_View::$params as $key => $value) {
+ $this->$key = $value;
+ }
+ }
+}
+
+