Subversion Repositories Applications.framework

Compare Revisions

No changes between revisions

Ignore whitespace Rev 178 → Rev 179

/branches/v0.2-buhl/framework/Url.php
New file
0,0 → 1,772
<?php
// declare(encoding='UTF-8');
/**
* classe Url, gérant le découpage des paramètres, leurs modification etc...
* Traduction et conversion d'une classe (NET_Url2) issue de Pear
*
* @category Php5
* @package Framework
// Auteur principal
* @author Christian Schmidt <schmidt@php.net>
// Autre auteurs
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright 2009 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version SVN: $Id$
* @link /doc/framework/
*
*/
class Url
{
/**
* Parsing strict dans resoudre() (voir RFC 3986, section 5.2.2). Par défaut
* à true.
*/
const OPTION_STRICTE = 'strict';
 
/**
* Répresenter les tableaux dans les requêtes en utilisant la notation php []. Par défaut à true.
*/
const OPTION_UTILISER_CROCHETS = 'use_brackets';
 
/**
* URL-encoder les clés des variables dans les requêtes. Par défaut à true.
*/
const OPTION_ENCODER_CLES = 'encode_keys';
 
/**
* Séparateurs de variables lors du parsing de la requête. Chaque caractère
* est considéré comme un séparateur. Par défaut, spécifié par le paramêtre
* arg_separator.input dans php.ini (par défaut "&").
*/
const OPTION_SEPARATEUR_ENTREE = 'input_separator';
 
/**
* Séparateur de variables lors de la génération de la requête. Par défaut, spécifié
* par le paramètre arg_separator.output dans php.ini (par défaut "&").
*/
const OPTION_SEPARATEUR_SORTIE = 'output_separator';
 
/**
* Options par défaut correspondant au comportement de php
* vis à vis de $_GET
*/
private $options = array(
self::OPTION_STRICTE => true,
self::OPTION_UTILISER_CROCHETS => true,
self::OPTION_ENCODER_CLES => true,
self::OPTION_SEPARATEUR_ENTREE => 'x&',
self::OPTION_SEPARATEUR_SORTIE => 'x&');
 
/**
* @var string|bool
*/
private $schema = false;
 
/**
* @var string|bool
*/
private $infoUtilisateur = false;
 
/**
* @var string|bool
*/
private $hote = false;
 
/**
* @var int|bool
*/
private $port = false;
 
/**
* @var string
*/
private $chemin = '';
 
/**
* @var string|bool
*/
private $requete = false;
 
/**
* @var string|bool
*/
private $fragment = false;
 
/**
* @param string $url une URL relative ou absolue
* @param array $options
*/
public function __construct($url, $options = null) {
$this->setOption(self::OPTION_SEPARATEUR_ENTREE,
Config::get('fw_url_arg_separateur_entree'));
$this->setOption(self::OPTION_SEPARATEUR_SORTIE,
Config::get('fw_url_arg_separateur_sortie'));
if (is_array($options)) {
foreach ($options as $nomOption => $valeur) {
$this->setOption($nomOption);
}
}
 
if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) {
$this->schema = $reg[1];
$url = substr($url, strlen($reg[0]));
}
 
if (preg_match('@^//([^/#?]+)@', $url, $reg)) {
$this->setAutorite($reg[1]);
$url = substr($url, strlen($reg[0]));
}
 
$i = strcspn($url, '?#');
$this->chemin = substr($url, 0, $i);
$url = substr($url, $i);
 
if (preg_match('@^\?([^#]*)@', $url, $reg)) {
$this->requete = $reg[1];
$url = substr($url, strlen($reg[0]));
}
 
if ($url) {
$this->fragment = substr($url, 1);
}
}
 
/**
* Retourne le schéma, c.a.d. "http" ou "urn", ou false si aucun schéma n'est
* spécifié, i.e. l'url est une url relative
*
* @return string|bool
*/
public function getSchema() {
return $this->schema;
}
 
/**
* @param string|bool $schema
*
* @return void
* @see getSchema()
*/
public function setSchema($schema) {
$this->schema = $schema;
}
 
/**
* renvoie la partie user de la partie infoUtilisateur (partie précédant le premier
* ":"), ou false si aucune partie infoUtilisateur n'est définie.
*
* @return string|bool
*/
public function getUtilisateur() {
return $this->infoUtilisateur !== false ? preg_replace('@:.*$@', '', $this->infoUtilisateur) : false;
}
 
/**
* renvoie la partie mot de passe de la partie infoUtilisateur (partie après le premier
* ":"), , ou false si aucune partie infoUtilisateur n'est définie (i.e. l'URL ne contient
* pas de "@" en face du nom d'hôte) ou si la partie infoUtilisateur ne contient pas de ":".
*
* @return string|bool
*/
public function getMotDePasse() {
return $this->infoUtilisateur !== false ? substr(strstr($this->infoUtilisateur, ':'), 1) : false;
}
 
/**
* Renvoie la partie userinfio, ou false si celle-ci n'existe pas, i.e. si la partie
* autorité ne contient pas de "@"
*
* @return string|bool
*/
public function getInfoUtilisateur() {
return $this->infoUtilisateur;
}
 
/**
* Setteur pour la partie infoUtilisateur. Si deux argument sont passé, ils sont combinés
* dans la partie infoUtilisateur de cette manière username ":" password.
*
* @param string|bool $infoUtilisateur infoUtilisateur ou username
* @param string|bool $motDePasse
*
* @return void
*/
public function setInfoUtilisateur($infoUtilisateur, $motDePasse = false) {
$this->infoUtilisateur = $infoUtilisateur;
if ($motDePasse !== false) {
$this->infoUtilisateur .= ':' . $motDePasse;
}
}
 
/**
* Renvoie la partie hôte, ou false s'il n'y a pas de partie autorité, c.a.d.
* l'URL est relative.
*
* @return string|bool
*/
public function getHote() {
return $this->hote;
}
 
/**
* @param string|bool $hote
*
* @return void
*/
public function setHote($hote) {
$this->hote = $hote;
}
 
/**
* Renvoie le numéro de port, ou false si aucun numéro de port n'est spécifié,
* i.e. le port par défaut doit utilisé.
*
* @return int|bool
*/
public function getPort() {
return $this->port;
}
 
/**
* @param int|bool $port
*
* @return void
*/
public function setPort($port) {
$this->port = intval($port);
}
 
/**
* Renvoie la partie autorité, i.e. [ infoUtilisateur "@" ] hote [ ":" port ], ou
* false si celle-ci est absente.
*
* @return string|bool
*/
public function getAutorite() {
if (!$this->hote) {
return false;
}
 
$autorite = '';
 
if ($this->infoUtilisateur !== false) {
$autorite .= $this->infoUtilisateur . '@';
}
 
$autorite .= $this->hote;
 
if ($this->port !== false) {
$autorite .= ':' . $this->port;
}
 
return $autorite;
}
 
/**
* @param string|false $autorite
*
* @return void
*/
public function setAutorite($autorite) {
$this->user = false;
$this->pass = false;
$this->hote = false;
$this->port = false;
if (preg_match('@^(([^\@]+)\@)?([^:]+)(:(\d*))?$@', $autorite, $reg)) {
if ($reg[1]) {
$this->infoUtilisateur = $reg[2];
}
 
$this->hote = $reg[3];
if (isset($reg[5])) {
$this->port = intval($reg[5]);
}
}
}
 
/**
* Renvoie la partie chemin (chemin) (éventuellement vide).
*
* @return string
*/
public function getChemin() {
return $this->chemin;
}
 
/**
* @param string $chemin
*
* @return void
*/
public function setChemin($chemin) {
$this->chemin = $chemin;
}
 
/**
* renvoie la chaine de requête (requete string) (sans le premier "?"), ou false si "?"
* n'est pas présent dans l'url.
*
* @return string|bool
* @see self::getVariablesRequete()
*/
public function getRequete() {
return $this->requete;
}
 
/**
* @param string|bool $requete
*
* @return void
* @see self::setVariablesRequete()
*/
public function setRequete($requete) {
$this->requete = $requete;
}
 
/**
* Renvoie le nom du fragment, ou false si "#" n'est pas present dans l'URL.
*
* @return string|bool
*/
public function getFragment() {
return $this->fragment;
}
 
/**
* @param string|bool $fragment
*
* @return void
*/
public function setFragment($fragment) {
$this->fragment = $fragment;
}
 
/**
* Renvoie la requete string sous forme d'un tableau de variables telles qu'elles apparaitraient
* dans le $_GET d'un script PHP
*
* @return array
*/
public function getVariablesRequete() {
$pattern = '/' .
preg_quote($this->getOption(self::OPTION_SEPARATEUR_ENTREE), '/') .
'/';
$parties = preg_split($pattern, $this->requete, -1, PREG_SPLIT_NO_EMPTY);
$retour = array();
 
foreach ($parties as $partie) {
if (strpos($partie, '=') !== false) {
list($cle, $valeur) = explode('=', $partie, 2);
} else {
$cle = $partie;
$valeur = null;
}
 
if ($this->getOption(self::OPTION_ENCODER_CLES)) {
$cle = rawurldecode($cle);
}
$valeur = rawurldecode($valeur);
 
if ($this->getOption(self::OPTION_UTILISER_CROCHETS) &&
preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $cle, $matches)) {
 
$cle = $matches[1];
$idx = $matches[2];
 
// On s'assure que c'est bien un tableau
if (empty($retour[$cle]) || !is_array($retour[$cle])) {
$retour[$cle] = array();
}
 
// Ajout des données
if ($idx === '') {
$retour[$cle][] = $valeur;
} else {
$retour[$cle][$idx] = $valeur;
}
} elseif (!$this->getOption(self::OPTION_UTILISER_CROCHETS)
&& !empty($retour[$cle])
) {
$retour[$cle] = (array) $retour[$cle];
$retour[$cle][] = $valeur;
} else {
$retour[$cle] = $valeur;
}
}
 
return $retour;
}
 
/**
* @param array $tableau (nom => valeur) tableau
*
* @return void
*/
public function setVariablesRequete(array $tableau) {
if (!$tableau) {
$this->requete = false;
} else {
foreach ($tableau as $nom => $valeur) {
if ($this->getOption(self::OPTION_ENCODER_CLES)) {
$nom = rawurlencode($nom);
}
 
if (is_array($valeur)) {
foreach ($valeur as $k => $v) {
$parties[] = $this->getOption(self::OPTION_UTILISER_CROCHETS)
? sprintf('%s[%s]=%s', $nom, $k, $v)
: ($nom . '=' . $v);
}
} elseif (!is_null($valeur)) {
$parties[] = $nom . '=' . $valeur;
} else {
$parties[] = $nom;
}
}
$this->requete = implode($this->getOption(self::OPTION_SEPARATEUR_SORTIE),
$parties);
}
}
 
/**
* @param string $nom
* @param mixed $valeur
*
* @return array
*/
public function setVariableRequete($nom, $valeur) {
$tableau = $this->getVariablesRequete();
$tableau[$nom] = $valeur;
$this->setVariablesRequete($tableau);
}
 
/**
* @param string $nom
*
* @return void
*/
public function unsetVariableRequete($nom) {
$tableau = $this->getVariablesRequete();
unset($tableau[$nom]);
$this->setVariablesRequete($tableau);
}
/**
* @param array $noms tableau des noms de variable à supprimer de l'url.
*
* @return void
*/
public function unsetVariablesRequete($noms) {
$tableau = $this->getVariablesRequete();
foreach ($noms as $nom) {
unset($tableau[$nom]);
}
$this->setVariablesRequete($tableau);
}
 
/**
* Renvoie un représentation sous forme de chaine de l'URL
*
* @return string
*/
public function getURL() {
// Voir RFC 3986, section 5.3
$url = "";
 
if ($this->schema !== false) {
$url .= $this->schema . ':';
}
 
$autorite = $this->getAutorite();
if ($autorite !== false) {
$url .= '//' . $autorite;
}
$url .= $this->chemin;
 
if ($this->requete !== false) {
$url .= '?' . $this->requete;
}
 
if ($this->fragment !== false) {
$url .= '#' . $this->fragment;
}
 
return $url;
}
 
/**
* Renvoie une représentation de cette URL sous forme de chaine normalisée. Utile pour la
* comparaison d'URLs
*
* @return string
*/
public function getURLNormalisee() {
$url = clone $this;
$url->normaliser();
return $url->getUrl();
}
 
/**
* Renvoie une instance normalisée de Url
*
* @return Url
*/
public function normaliser() {
// See RFC 3886, section 6
 
// les cchémas sont insesibles à la casse
if ($this->schema) {
$this->schema = strtolower($this->schema);
}
 
// les noms d'hotes sont insensibles à la casse
if ($this->hote) {
$this->hote = strtolower($this->hote);
}
 
// Supprimer le numéro de port par défaut pour les schemas connus (RFC 3986, section 6.2.3)
if ($this->port &&
$this->schema &&
$this->port == getservbyname($this->schema, 'tcp')) {
 
$this->port = false;
}
 
// normalisation dans le cas d'un encodage avec %XX pourcentage (RFC 3986, section 6.2.2.1)
foreach (array('infoUtilisateur', 'hote', 'chemin') as $partie) {
if ($this->$partie) {
$this->$partie = preg_replace('/%[0-9a-f]{2}/ie', 'strtoupper("\0")', $this->$partie);
}
}
 
// normalisation des segments du chemin (RFC 3986, section 6.2.2.3)
$this->chemin = self::supprimerSegmentsAPoints($this->chemin);
 
// normalisation basée sur le schéma (RFC 3986, section 6.2.3)
if ($this->hote && !$this->chemin) {
$this->chemin = '/';
}
}
 
/**
* Renvoie vrai ou faux suivant que l'instance en cours représente une URL relative ou absolue.
*
* @return bool
*/
public function etreAbsolue() {
return (bool) $this->schema;
}
 
/**
* Renvoie une instance de Url représentant une URL absolue relative à
* cette URL.
*
* @param Url|string $reference URL relative
*
* @return Url
*/
public function resoudre($reference) {
if (is_string($reference)) {
$reference = new self($reference);
}
if (!$this->etreAbsolue()) {
throw new Exception('L\'URL de base doit être absolue !');
}
 
// Un parseur non strict peut choisir d'ignorer un schema dans la référence
// si celui ci est identique au schéma de base de l'URI.
if (!$this->getOption(self::OPTION_STRICTE) && $reference->schema == $this->schema) {
$reference->schema = false;
}
 
$cible = new self('');
if ($reference->schema !== false) {
$cible->schema = $reference->schema;
$cible->setAutorite($reference->getAutorite());
$cible->chemin = self::supprimerSegmentsAPoints($reference->chemin);
$cible->requete = $reference->requete;
} else {
$autorite = $reference->getAutorite();
if ($autorite !== false) {
$cible->setAutorite($autorite);
$cible->chemin = self::supprimerSegmentsAPoints($reference->chemin);
$cible->requete = $reference->requete;
} else {
if ($reference->chemin == '') {
$cible->chemin = $this->chemin;
if ($reference->requete !== false) {
$cible->requete = $reference->requete;
} else {
$cible->requete = $this->requete;
}
} else {
if (substr($reference->chemin, 0, 1) == '/') {
$cible->chemin = self::supprimerSegmentsAPoints($reference->chemin);
} else {
// Concaténation chemins (RFC 3986, section 5.2.3)
if ($this->hote !== false && $this->chemin == '') {
$cible->chemin = '/' . $this->chemin;
} else {
$i = strrpos($this->chemin, '/');
if ($i !== false) {
$cible->chemin = substr($this->chemin, 0, $i + 1);
}
$cible->chemin .= $reference->chemin;
}
$cible->chemin = self::supprimerSegmentsAPoints($cible->chemin);
}
$cible->requete = $reference->requete;
}
$cible->setAutorite($this->getAutorite());
}
$cible->schema = $this->schema;
}
 
$cible->fragment = $reference->fragment;
 
return $cible;
}
 
/**
* La suppression des segments à points est décrite dans la RFC 3986, section 5.2.4, e.g.
* "/foo/../bar/baz" => "/bar/baz"
*
* @param string $chemin un chemin
*
* @return string un chemin
*/
private static function supprimerSegmentsAPoints($chemin) {
$sortie = '';
 
// Assurons de ne pas nous retrouver piégés dans une boucle infinie due à un bug de
// cette méthode
$j = 0;
while ($chemin && $j++ < 100) {
// Étape A
if (substr($chemin, 0, 2) == './') {
$chemin = substr($chemin, 2);
} elseif (substr($chemin, 0, 3) == '../') {
$chemin = substr($chemin, 3);
 
// Étape B
} elseif (substr($chemin, 0, 3) == '/./' || $chemin == '/.') {
$chemin = '/' . substr($chemin, 3);
 
// Étape C
} elseif (substr($chemin, 0, 4) == '/../' || $chemin == '/..') {
$chemin = '/' . substr($chemin, 4);
$i = strrpos($sortie, '/');
$sortie = $i === false ? '' : substr($sortie, 0, $i);
 
// Étape D
} elseif ($chemin == '.' || $chemin == '..') {
$chemin = '';
 
// Étape E
} else {
$i = strpos($chemin, '/');
if ($i === 0) {
$i = strpos($chemin, '/', 1);
}
if ($i === false) {
$i = strlen($chemin);
}
$sortie .= substr($chemin, 0, $i);
$chemin = substr($chemin, $i);
}
}
 
return $sortie;
}
 
/**
* Renvoie une instance de Url representant l'URL canonique du script PHP
* en cours d'éxécution
*
* @return string
*/
public static function getCanonique() {
if (!isset($_SERVER['REQUEST_METHOD'])) {
// ALERT - pas d'URL en cours
throw new Exception('Le script n\'a pas été appellé à travers un serveur web');
}
 
// on part d'une URL relative
$url = new self($_SERVER['PHP_SELF']);
$url->schema = isset($_SERVER['HTTPS']) ? 'https' : 'http';
$url->hote = $_SERVER['SERVER_NAME'];
$port = intval($_SERVER['SERVER_PORT']);
if ($url->schema == 'http' && $port != 80 ||
$url->schema == 'https' && $port != 443) {
 
$url->port = $port;
}
return $url;
}
 
/**
* Renvoie l'URL utilisée pour récupérer la requête en cours
*
* @return string
*/
public static function getURLDemande() {
return self::getDemande()->getUrl();
}
 
/**
* Renvoie une instance de Url representant l'URL utilisée pour
* récupérer la requête en cours
*
* @return Url
*/
public static function getDemande() {
if (!isset($_SERVER['REQUEST_METHOD'])) {
// ALERTE - pas d'URL en cours
throw new Exception('Le script n\'a pas été appellé à travers un serveur web');
}
 
// On part d'une URL relative
$url = new self($_SERVER['REQUEST_URI']);
$url->schema = isset($_SERVER['HTTPS']) ? 'https' : 'http';
// On met à jour les valeurs de l'hote et si possible du port
$url->setAutorite($_SERVER['HTTP_hote']);
return $url;
}
 
/**
* Met à jour la valeur de l'option spécifiée.
*
* @param string $nomOption une des constantes commençant par self::OPTION_
* @param mixed $valeur valeur de l'option
*
* @return void
* @see self::OPTION_STRICTE
* @see self::OPTION_UTILISER_CROCHETS
* @see self::OPTION_ENCODER_CLES
*/
function setOption($nomOption, $valeur) {
if (!array_key_exists($nomOption, $this->options)) {
return false;
}
$this->options[$nomOption] = $valeur;
}
 
/**
* Renvoie la valeur de l'option specifiée.
*
* @param string $nomOption Nom de l'option demandée
*
* @return mixed
*/
function getOption($nomOption) {
return isset($this->options[$nomOption])
? $this->options[$nomOption] : false;
}
 
public function __toString() {
return $this->getURL();
}
}
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/Application.php
New file
0,0 → 1,82
<?php
// declare(encoding='UTF-8');
/**
* Classe fournissant des informations au Framework sur l'application.
*
* PHP version 5
*
* @category Debogage
* @package Framework
// Auteur principal :
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
// Autres auteurs :
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $$Id$$
* @copyright 1999-2009 Tela Botanica (accueil@tela-botanica.org)
*/
class Application {
 
/**
* tableau d'informations sur l'application
*/
private static $info = null;
/**
* chemin de base de l'application
*/
private static $chemin = null;
 
/**
* Modificateur pour le chemin de base
* @param string $chemin_fichier_principal chemin de base
*/
public static function setChemin($chemin_fichier_principal) {
if (self::$chemin === null) {
if (!file_exists($chemin_fichier_principal)) {
trigger_error("Le fichier indiqué n'existe pas. Utilisez __FILE__ dans la méthode set().", E_USER_ERROR);
} else {
self::$chemin = dirname($chemin_fichier_principal).DS;
}
} else {
trigger_error("Le chemin de l'application a déjà été enregistré auprès du Framework", E_USER_WARNING);
}
}
 
/**
* accesseur pour le chemin
* @return string le chemin
*/
public static function getChemin() {
return self::$chemin;
}
 
/** Le tableau des informations sur l'application possède les clés suivantes :
* - nom : nom de l'application
* - abr : abréviation de l'application
* - encodage : encodage de l'application (ISO-8859-15, UTF-8...)
*
* @param array $info tableau fournissant des informations sur l'application
* @return void
*/
public static function setInfo($info) {
if (self::$info === null) {
self::$info = $info;
} else {
trigger_error("Le informations de l'application ont déjà été enregistrées auprès du Framework", E_USER_WARNING);
}
}
 
/**
* accesseur pour le tableau d'infos
* @param string $cle la clé à laquelle on veut accéder
*/
public static function getInfo($cle = null) {
if ($cle !== null) {
if (isset(self::$info[$cle])) {
return self::$info[$cle];
}
} else {
return self::$info;
}
}
}
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/SquelettePhp.php
New file
0,0 → 1,74
<?php
// declare(encoding='UTF-8');
/**
* Classe SquelettePhp, traitant les squelette Php utilisant la syntaxe courte php ou pas.
* Ces méthodes sont statiques.
*
* @category php5
* @package Framework
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version SVN: $$Id$$
* @link /doc/framework/
*/
class SquelettePhp {
/**
* Fonction prenant en paramètre un chemin de fichier squelette et un tableau associatif de données,
* en extrait les variables, charge le squelette et retourne le résultat des deux combinés.
*
* @param String $fichier le chemin du fichier du squelette
* @param Array $donnees un tableau associatif contenant les variables a injecter dans le squelette.
*
* @return boolean false si la vue n'existe pas, sinon la chaine résultat.
*/
public static function analyser($fichier, Array $donnees = array()) {
$sortie = false;
if (file_exists($fichier)) {
// Extraction des variables du tableau de données
extract($donnees);
// Démarage de la bufferisation de sortie
ob_start();
// Si les tags courts sont activés
if ((bool) @ini_get('short_open_tag') === true) {
// Simple inclusion du squelette
include $fichier;
} else {
// Sinon, remplacement des tags courts par la syntaxe classique avec echo
$html_et_code_php = self::traiterTagsCourts($fichier);
// Pour évaluer du php mélangé dans du html il est nécessaire de fermer la balise php ouverte par eval
$html_et_code_php = '?>'.$html_et_code_php;
// Interprétation du html et du php dans le buffer
echo eval($html_et_code_php);
}
// Récupèration du contenu du buffer
$sortie = ob_get_contents();
// Suppression du buffer
@ob_end_clean();
} else {
$msg = "Le fichier du squelette '$fichier' n'existe pas.";
trigger_error($msg, E_USER_WARNING);
}
// Retourne le contenu
return $sortie;
}
/**
* Fonction chargeant le contenu du squelette et remplaçant les tags court php (<?= ...) par un tag long avec echo.
*
* @param String $chemin_squelette le chemin du fichier du squelette
*
* @return string le contenu du fichier du squelette php avec les tags courts remplacés.
*/
private static function traiterTagsCourts($chemin_squelette) {
$contenu = file_get_contents($chemin_squelette);
// Remplacement de tags courts par un tag long avec echo
$contenu = str_replace('<?=', '<?php echo ', $contenu);
// Ajout systématique d'un point virgule avant la fermeture php
$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu);
return $contenu;
}
}
?>
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/Registre.php
New file
0,0 → 1,94
<?php
// declare(encoding='UTF-8');
/**
* Classe registre, qui permet un accès à différentes variables à travers les autres classes.
* C'est un singleton
*
* PHP Version 5
*
* @category Class
* @package Framework
* @author Jean-Pascal Milcent <jmp@tela-botanica.org>
* @copyright 2009 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version SVN: $$Id$$
* @link /doc/framework/
*
*/
class Registre {
 
/**
* Tableau associatif stockant les variables
*/
private $stockage = array();
/**
* La classe registre se contient elle-même, (pour le pattern singleton)
*/
private static $registre;
 
/**
* Constructeur par défaut, privé, car on accède à la classe par le getInstance
*/
private function __construct() {
}
 
/**
* Fonction qui renvoie l'instance de classe en assurant son unicité, c'est l'unique méthode qui doit être
* utilisée pour récupérer l'objet Registre
*/
public static function getInstance() {
if (self::$registre instanceof Registre) {
return self::$registre;
}
self::$registre = new Registre;
return self::$registre;
}
 
/**
* Ajoute un objet au tableau selon un intitulé donné
* @param string l'intitulé sous lequel l'objet sera conservé
* @param mixed l'objet à conserver
*/
public function set($intitule, $objet) {
if (is_array($objet) && isset($this->stockage[$intitule])) {
$this->stockage[$intitule] = array_merge((array) $this->stockage[$intitule], (array) $objet);
$message = "Le tableau $intitule présent dans le registre a été fusionné avec un nouveau tableau de même intitulé !";
trigger_error($message, E_USER_WARNING);
} else {
$this->stockage[$intitule] = $objet;
}
}
 
/**
* Renvoie l'objet associé à l'intitulé donné en paramètre
* @return mixed l'objet associé à l'intitulé ou null s'il n'est pas présent
*/
public function get($intitule) {
if (isset($this->stockage[$intitule])) {
return $this->stockage[$intitule];
}
return null;
}
 
/**
* Détruit l'objet associé à l'intitulé, n'a pas d'effet si il n'y a pas d'objet associé
*/
public function detruire($intitule) {
if (isset($this->stockage[$intitule])) {
unset($this->stockage[$intitule]);
}
}
 
/**
* Teste si un objet est présent sous un intitulé donné
* @return boolean true si un objet associé à cet intitulé est présent, false sinon
*/
public function existe($intitule) {
if(isset($this->stockage[$intitule])){
return true;
}
return false;
}
}
?>
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/config.defaut.ini
New file
0,0 → 1,119
; Renommer ce fichier en config.ini
; +------------------------------------------------------------------------------------------------------+
; Général
; Séparateur de dossier
ds = DIRECTORY_SEPARATOR
; Séparateur de chemin
ps = PATH_SEPARATOR
; Fin de ligne de fichier
eol = PHP_EOL
 
; +------------------------------------------------------------------------------------------------------+
; Urls
; Le séparateur utilisé pour séparer les arguments des urls lorsque le framework parse une url.
; Pour remettre les valeurs par défaut, utitliser : "php:ini_get('arg_separator.input')"
fw_url_arg_separateur_entree = "&amp;"
; Le séparateur utilisé par le framework lorsqu'il génère des URL pour séparer les arguments.
; Pour remettre les valeurs par défaut, utitliser : "php:ini_get('arg_separator.output')"
fw_url_arg_separateur_sortie = "&amp;"
 
; +------------------------------------------------------------------------------------------------------+
; Débogage
; Indique si oui ou non on veut afficher le débogage.
fw_debogage = true
; Indique si oui ou non on veut afficher le contexte de débogage.
fw_debogage_contexte = false
; Niveau d'erreur à employer pour le code PHP. Voir le manuel de PHP pour les différents niveaux disponibles.
fw_debogage_niveau = 2048
; Indique si oui ou non on veut activer la journalisation des erreurs.
fw_log_debogage = false
; Indique le fuseau horaire pour le datage des logs.
fw_timezone = Europe/Paris
; Indique la taille max d'un fichier log (en octets)
fw_taille_max_logs = 1000000
 
; +------------------------------------------------------------------------------------------------------+
; Benchmark
; Indique si oui ou nom on veut afficher le tableau de chronométrage de l'application.
fw_benchmark_chrono = true
 
; +------------------------------------------------------------------------------------------------------+
; Chemins et fichiers
; Nom des fichiers de config recherché. Défini par défaut dans la classe Config
; fw_fichier_config = "config%s.ini"
; Chemin vers le dossier du framework. Défini par défaut dans la classe Config
; fw_chemin = "php:dirname(__FILE__).DS"
 
; Nom du dossier de la bibliotheque de codes de l'application.
dossier_bibliotheque = bibliotheque
; Nom du dossier des composants graphiques de l'application.
dossier_composants = composants
; Nom du dossier des controleurs de l'application.
dossier_configurations = configurations
; Nom du dossier des controleurs de l'application.
dossier_controleurs = controleurs
; Nom du dossier des traductions de l'application.
dossier_i18n = i18n
; Nom du dossier des modèles de l'application.
dossier_modeles = modeles
; Nom du dossier des squelettes de l'application.
dossier_squelettes = squelettes
; Nom du dossier des logs de l'application.
dossier_logs = logs
 
; Chemin vers le dossier de l'appli.
chemin_appli = "php:Application::getChemin()"
; Chemin vers le dossier de la bibliotheque de codes de l'application.
chemin_bibliotheque = "{ref:chemin_appli}{ref:dossier_bibliotheque}{ref:ds}"
; Chemin vers le dossier des composants graphiques de l'application.
chemin_composants = "{ref:chemin_appli}{ref:dossier_composants}{ref:ds}"
; Chemin vers le dossier des controleurs de l'application.
chemin_configurations = "{ref:chemin_appli}{ref:dossier_configurations}{ref:ds}"
; Chemin vers le dossier des controleurs de l'application.
chemin_controleurs = "{ref:chemin_appli}{ref:dossier_controleurs}{ref:ds}"
; Chemin vers le dossier des traductions de l'application.
chemin_i18n = "{ref:chemin_appli}{ref:dossier_i18n}{ref:ds}"
; Chemin vers le dossier des modèles de l'application.
chemin_modeles = "{ref:chemin_appli}{ref:dossier_modeles}{ref:ds}"
; Chemin vers le dossier des squelettes de l'application.
chemin_squelettes = "{ref:chemin_appli}{ref:dossier_squelettes}{ref:ds}"
; Chemin vers le dossier des logs de l'application.
chemin_logs = "{ref:chemin_appli}{ref:dossier_logs}{ref:ds}"
 
; +------------------------------------------------------------------------------------------------------+
; Paramètrage de la base de données.
; abstraction de la base de données.
bdd_abstraction = pdo
; Protocole de la base de données.
bdd_protocole = mysql
; Nom du serveur de bases de données.
bdd_serveur = localhost
; Nom de l'utilisateur de la base de données.
bdd_utilisateur = ""
; Mot de passe de l'utilisateur de la base de données.
bdd_mot_de_passe = ""
; Nom de la base de données principale.
bdd_nom = ""
; Encodage de la base de données principale. Normalement le même que l'application mais au format base de
données : voir ici : http://dev.mysql.com/doc/refman/5.0/en/charset-charsets.html
et là: http://www.postgresql.org/docs/8.1/static/multibyte.html pour les correspondances
bdd_encodage = "utf8"
 
; +------------------------------------------------------------------------------------------------------+
; Encodage de l'application, des fichiers php, squelettes... de l'application
appli_encodage = "UTF-8"
; Encodage des donnés renvoyées au navigateur
; (faire attention à la correspondane avec les .htaccess et les balises meta du html des squelettes)
sortie_encodage = "UTF-8"
 
; +------------------------------------------------------------------------------------------------------+
; URLs
; URL de base de l'application, si elle est laissée vide, l'application fonctionnera en Stand-alone
; Peut utiliser une objet Net_URL comme ceci : "php:$mon_objet_net_url->getUrl()"
url_base = ""
 
; +------------------------------------------------------------------------------------------------------+
; Identifications
; Indiquer ici si l'utilisateur est identifié ou pas.
; Peut utiliser un objet Auth comme ceci : "php:$mon_objet_auth->getAuth()"
identification = true
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/.htaccess
New file
0,0 → 1,2
# Ce fichier est là pour éviter l'accès au fichier .ini depuis un navigateur.
deny from all
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/Chronometre.php
New file
0,0 → 1,152
<?php
// declare(encoding='UTF-8');
/** Classe Chronometre() - Permet de stocker et d'afficher
* les temps d'éxécution de script.
*
* Cette classe permet de réaliser un ensemble
* de mesure de temps prises à
* différents endroits d'un script.
* Ces mesures peuvent ensuite être affichées au
* sein d'un tableau XHTML.
*
*
* PHP Version 5
*
* @category PHP
* @package Framework
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright 2009 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version Release: <package_version>
* @link /doc/framework/
*/
class Chronometre {
/*** Attributs : ***/
private $_temps = array();
 
/** Constructeur : **/
public function __construct() {
$this->setTemps(array('depart' => microtime()));
}
 
/** Accesseurs :
*
* @param string $cle la cle associée à un chronomètre particulier
*
* @return int le temps écoulé
*/
public function getTemps($cle = null) {
$temps = '';
if (!is_null($cle)) {
$temps = $this->_temps[$cle];
} else {
$temps = $this->_temps;
}
return $temps;
}
 
/** Setteur pour la variable temps
*
* @param array() $moment ajoute des points de chronométrage au tableau _temps
*
* @return null
*/
public function setTemps($moment = array ()) {
array_push($this->_temps, $moment);
}
 
/*** Méthodes : ***/
 
/** Méthode afficherChrono() -
* Permet d'afficher les temps d'éxécution de différentes parties d'un script.
*
* Cette fonction permet d'afficher un ensemble de
* mesure de temps prises à différents endroits d'un script.
* Ces mesures sont affichées au sein d'un tableau XHTML
* dont on peut controler l'indentation des balises.
* Pour un site en production, il suffit d'ajouter un style
* #chrono {display:none;} dans la css. De cette façon,
* le tableau ne s'affichera pas. Le webmaster lui pourra
* rajouter sa propre feuille de style affichant le tableau.
* Le développeur initial de cette fonction est Loic d'Anterroches.
* Elle a été modifiée par Jean-Pascal Milcent.
* Elle utilise une variable gobale : $_CHRONO_
*
* @author Loic d'Anterroches
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
*
* @param int $indentation_origine l'indentation de base.
* @param int $indentation le pas d'indentation.
* @return string la chaine XHTML de mesure des temps.
*/
public function afficherChrono($indentation_origine = 8, $indentation = 4) {
// Création du chrono de fin
$GLOBALS['_SCRIPT_']['chrono']->setTemps(array (
'fin' => microtime()
));
 
// Début création de l'affichage
$sortie = str_repeat(' ', $indentation_origine) .
'<table id="chrono" lang="fr" summary="Résultat du
chronométrage du programme affichant la page actuelle.">' . "\n";
$sortie .= str_repeat(' ', ($indentation_origine + ($indentation * 1))) .
'<caption>Chronométrage</caption>' . "\n";
$sortie .= str_repeat(' ', ($indentation_origine + ($indentation * 1))) .
'<thead>' . "\n";
$sortie .= str_repeat(' ', ($indentation_origine + ($indentation * 2))) .
'<tr><th>Action</th><th>Temps écoulé (en s.)</th>
<th>Cumul du temps écoulé (en s.)</th></tr>' . "\n";
$sortie .= str_repeat(' ', ($indentation_origine + ($indentation * 1))) .
'</thead>' . "\n";
 
$tbody = str_repeat(' ', ($indentation_origine + ($indentation * 1))) .
'<tbody>' . "\n";
 
$total_tps_ecoule = 0;
 
// Récupération de la premiére mesure
$tab_depart = & $this->getTemps(0);
list ($usec, $sec) = explode(' ', $tab_depart['depart']);
 
// Ce temps correspond à tps_fin
$tps_debut = ((float) $usec + (float) $sec);
 
foreach ($this->getTemps() as $tab_temps) {
foreach ($tab_temps as $cle => $valeur) {
list ($usec, $sec) = explode(' ', $valeur);
$tps_fin = ((float) $usec + (float) $sec);
 
$tps_ecoule = abs($tps_fin - $tps_debut);
$total_tps_ecoule += $tps_ecoule;
 
$tbody .= str_repeat(' ',
($indentation_origine + ($indentation * 2))) .
'<tr>' .
'<th>' . $cle . '</th>' .
'<td>' . number_format($tps_ecoule, 3, ',', ' ') . '</td>' .
'<td>' . number_format($total_tps_ecoule, 3, ',', ' ') . '</td>' .
'</tr>' . "\n";
$tps_debut = $tps_fin;
}
}
$tbody .= str_repeat(' ', ($indentation_origine + ($indentation * 1))) .
'</tbody>' . "\n";
 
$sortie .= str_repeat(' ', ($indentation_origine + ($indentation * 1))) .
'<tfoot>' . "\n";
$sortie .= str_repeat(' ', ($indentation_origine + ($indentation * 2))) .
'<tr>' .
'<th>' . 'Total du temps écoulé (en s.)' . '</th>' .
'<td colspan="2">' .
number_format($total_tps_ecoule, 3, ',', ' ') . '</td>' .
'</tr>' . "\n";
$sortie .= str_repeat(' ', ($indentation_origine + ($indentation * 1))) .
'</tfoot>' . "\n";
$sortie .= $tbody;
$sortie .= str_repeat(' ', $indentation_origine) .
'</table>' . "\n";
 
return $sortie;
}
}
?>
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/Config.php
New file
0,0 → 1,269
<?php
// declare(encoding='UTF-8');
/**
* Config permet de charger automatiquement les fichiers ini du Framework et de l'application.
* Elle offre l'accès en lecture seule aux paramètres de config.
* C'est une Singleton.
*
* PHP Version 5
*
* @category PHP
* @package Framework
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright 2009 Tela-Botanica
* @license GPL-v3 et CECILL-v2
* @version SVN: <svn_id>
* @link /doc/framework/
*/
 
class Config {
 
/**
* instance de la classe pointant sur elle même (pour le pattern singleton)
*/
private static $instance = null;
 
/**
* paramètres de configuration
*/
private static $parametres = array();
 
/**
* Constructeur vide
*/
private function __construct() {
// Définition de paramètres avant chargement du config.ini
self::$parametres = array(
'fw_fichier_config' => 'config%s.ini',
'fw_chemin' => dirname(__FILE__).DS
);
 
// Chargement du fichier config.ini du Framework
$existe = self::parserFichierIni(self::$parametres['fw_chemin'].sprintf(self::$parametres['fw_fichier_config'], ''));
if ($existe === false) {
trigger_error("Veuillez configurer le Framework en renommant le fichier config.defaut.ini en config.ini.", E_USER_ERROR);
}
 
// Chargement du fichier config.ini par défaut de l'application
$chemin_config_defaut_appli = self::$parametres['chemin_configurations'].sprintf(self::$parametres['fw_fichier_config'], '');
self::parserFichierIni($chemin_config_defaut_appli);
 
// Chargement des fichiers config.ini contextuels
if (PHP_SAPI == 'cli') {// mode console
foreach ($_SERVER['argv'] as $cle => $valeur) {
if ($valeur == '-contexte') {
chargerFichierContexte($_SERVER['argv'][($cle+1)]);
break;
}
}
} else {// mode web
// Pour Papyrus
if (defined('PAP_VERSION')) {
self::chargerFichierContexte('papyrus');
}
// Via le fichie .ini par défaut de l'appli
if (Config::existeValeur('info.contexte', self::$parametres)) {
self::chargerFichierContexte(Config::get('info.contexte'));
}
 
// Chargement du contexte présent dans le GET
if (isset($_GET['contexte'])) {
self::chargerFichierContexte($_GET['contexte']);
}
 
// Chargement du contexte présent dans le POST
if (isset($_POST['contexte'])) {
self::chargerFichierContexte($_POST['contexte']);
}
}
}
 
/**
* Charge le fichier de config correspondant au contexte
* @param string $contexte le contexte
*/
private static function chargerFichierContexte($contexte) {
$chemin_config_appli_contextuel = self::$parametres['chemin_configurations'];
$chemin_config_appli_contextuel .= sprintf(self::$parametres['fw_fichier_config'], '_'.$contexte);
self::parserFichierIni($chemin_config_appli_contextuel);
}
 
/**
* Parse le fichier ini donné en paramètre
* @param string $fichier_ini nom du fichier ini à parser
* @return array tableau contenant les paramètres du fichier ini
*/
private static function parserFichierIni($fichier_ini) {
$retour = false;
if (file_exists($fichier_ini)) {
$ini = parse_ini_file($fichier_ini, true);
$ini = self::analyserTableauIni($ini);
self::fusionner($ini);
$retour = true;
}
return $retour;
}
 
/**
* fusionne un tableau de paramètres avec le tableau de paramètres global
* @param array $ini le tableau à fusionner
*/
private static function fusionner(array $ini) {
self::$parametres = array_merge(self::$parametres, $ini);
}
 
/**
* renvoie la valeur demandé grâce une chaine de paramètres
* @param string $param la chaine de paramètres
* @param array $config le tableau de paramètre
* @return string la valeur de la chaine demandée
*/
private static function getValeur($param, $config) {
if ($param === null) {
return null;
} else {
if (strpos($param, '.') !== false) {
$pieces = explode('.', $param, 2);
if (strlen($pieces[0]) && strlen($pieces[1])) {
if (isset($config[$pieces[0]])) {
if (is_array($config[$pieces[0]])) {
return self::getValeur($pieces[1], $config[$pieces[0]]);
}
}
}
} else {
if (isset($config[$param])) {
return $config[$param];
}
}
return null;
}
}
 
/**
* Teste si param existe dans le tableau config
* @param string $param nom du paramètre
* @param array tableau de configuration
*/
private static function existeValeur($param, $config) {
$retour = false;
if (self::getValeur($param, $config) !== null) {
$retour = true;
}
return $retour;
}
 
/**
* Vérifie si l'instance de classe à été crée, si non la crée
*/
private static function verifierCreationInstance() {
if (empty(self::$instance)) {
self::$instance = new Config();
}
}
 
/**
* analyse un tableau de paramètres
* @param array $config le tableau de paramètres
* @return array le tableau analysé
*/
private static function analyserTableauIni($config = array()) {
foreach ($config as $cle => $valeur) {
if (is_array($valeur)) {
$config[$cle] = self::analyserTableauIni($valeur);
} else {
self::evaluerReferences($config, $cle);
self::evaluerPhp($config, $cle);
self::evaluerCle($config, $cle, $config[$cle]);
}
}
return $config;
}
 
/**
* dans le cas des chaine de configuration à sous clé (ex.: cle.souscle)
* evalue les valeurs correspondantes et crée les sous tableaux associés
* @param array $config tableau de configuration (par référence)
* @param string $cle la cle dans le tableau
* @param string $valeur la valeur à affecter
*/
private static function evaluerCle(&$config, $cle, $valeur) {
if (strpos($cle, '.') !== false) {
unset($config[$cle]);
$pieces = explode('.', $cle, 2);
if (strlen($pieces[0]) && strlen($pieces[1])) {
if (!isset($config[$pieces[0]])) {
if ($pieces[0] === '0' && !empty($config)) {
// convert the current values in $config into an array
$config = array($pieces[0] => $config);
} else {
$config[$pieces[0]] = array();
}
} elseif (!is_array($config[$pieces[0]])) {
throw new ErrorException("Ne peut pas créer de sous-clé pour '{$pieces[0]}' car la clé existe déjà");
}
$config[$pieces[0]] = self::evaluerCle($config[$pieces[0]], $pieces[1], $valeur);
} else {
throw new ErrorException("Clé invalide '$cle'");
}
} else {
$config[$cle] = $valeur;
}
return $config;
}
 
/**
* Evalue les valeurs de références à une clé dans le tableau config (cas du ref:cle)
* @param array $config tableau de configuration
* @param string $cle la clé dont il faut évaluer les références
*/
private static function evaluerReferences(&$config, $cle) {
if (preg_match_all('/{ref:([A-Za-z0-9_-]+)}/', $config[$cle], $correspondances, PREG_SET_ORDER)) {
foreach ($correspondances as $ref) {
$config[$cle] = str_replace($ref[0], self::getValeur($ref[1], $config), $config[$cle]);
}
}
}
 
/**
* Evalue le code php contenu dans un clé tu tableau config
* @param array $config tableau de configuration (par référence)
* @param string $cle le clé du tableau dont il faut évaluer la valeur
*/
private static function evaluerPhp(&$config, $cle) {
if (preg_match('/^php:(.+)$/', $config[$cle], $correspondances)) {
eval('$config["'.$cle.'"] = '.$correspondances[1].';');
}
}
 
/**
* Charge un fichier ini dans le tableau des paramètres de l'appli
* @param string $fichier_ini le nom du fichier à charger
* @return array le fichier ini parsé
*/
public static function charger($fichier_ini) {
self::verifierCreationInstance();
return self::parserFichierIni($fichier_ini);
}
 
/**
* Acesseur pour la valeur d'un paramètre
* @param string $param le nom du paramètre
* @return string la valeur du paramètre
*/
public static function get($param = null) {
self::verifierCreationInstance();
return self::getValeur($param, self::$parametres);
}
 
/**
* Vérifie si la valeur d'un paramètre existe
* @param string $param le nom du paramètre
* @return boolean vrai si le paramètre existe, false sinon
*/
public static function existe($param) {
self::verifierCreationInstance();
return self::existeValeur($param, self::$parametres);
}
}
?>
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/Modele.php
New file
0,0 → 1,345
<?php
// declare(encoding='UTF-8');
/**
* Classe modèle, donc d'accés au données, elle ne devrait pas être appelée de l'extérieur.
* Elle fait office d'abstraction légère de base de données en utilisant diveres possibilités
* d'abstraction de base de données (PDO, mysql, mysqli, sqlite)
* Elle est abstraite donc doit obligatoirement être étendue.
*
* PHP Version 5
*
* @category Class
* @package Framework
* @author aurelien <aurelien@tela-botanica.org>
* @copyright 2009 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version SVN: $$Id$$
* @link /doc/framework/
*
*/
abstract class Modele {
 
/**
* Mode de fetch associatif
*/
private $ASSOC = '';
/**
* Mode de fetch objet
*/
private $OBJECT = '';
 
/**
* abstraction de base de données utilisée
*/
private $abstraction;
/**
* registre global
*/
private $registre;
/**
* DSN pour accéder à la base de données
*/
private $dsn;
/**
* Type de base de données (mysql, mysqli, etc ...)
*/
private $type;
/**
* Hote herbergeant la base de données
*/
private $hote;
/**
* Nom de la base de données à laquelle le modèle doit se connecter
*/
private $bdd_nom;
/**
* Nom d'utilisateur
*/
private $utilisateur;
/**
* Mot de passe
*/
private $pass;
 
/**
* Encodage de la base de données
*/
private $encodage = null;
/**
* Connexion à la base de données
*/
private $connexion = null;
 
/**
* Constructeur par défaut, appelé à l'initialisation.
*/
public function __construct() {
// les différents paramètres nécessaires sont lus à partir du registre
$this->registre = Registre::getInstance();
$this->abstraction = strtolower(Config::get('bdd_abstraction'));
$this->type = Config::get('bdd_protocole');
$this->hote = Config::get('bdd_serveur');
$this->bdd_nom = Config::get('bdd_nom');
$this->utilisateur = Config::get('bdd_utilisateur');
$this->pass = Config::get('bdd_mot_de_passe');
$this->encodage = Config::get('bdd_encodage');
 
$this->dsn = $this->type.':dbname='.$this->bdd_nom.';host='.$this->hote;
$this->initialiserProtocole();
}
 
/**
* Connection à la base de données en utilisant les informations fournies par
* le fichier de configuration.
* private et final car n'a pas vocation a être appelée par l'utilisateur.
*
* @throws Exception une exception dans le cas ou là connexion échoue
*/
final private function connecter() {
switch ($this->abstraction) {
case 'pdo':
$this->connexion = new PDO($this->dsn, $this->utilisateur, $this->pass);
break;
 
case 'mysql':
$this->connexion = mysql_connect($this->hote,$this->utilisateur,$this->pass);
if ($this->connexion != null) {
mysql_select_db($this->bdd_nom, $this->connexion);
} else {
throw new Exception('Erreur de connexion à la base de données, vérifiez les paramètres du fichier de configuration');
}
break;
 
case 'mysqli':
$this->connexion = new mysqli($this->hote,$this->utilisateur,$this->pass, $this->bdd_nom);
if (!$this->connexion) {
throw new Exception('Erreur de connexion à la base de données, vérifiez les paramètres du fichier de configuration');
return;
}
break;
 
case 'sqlite3':
// cas particulier de sqllite, on considère que le nom de la base de données correspond au fichier à ouvrir
$this->connexion = new SQLite3($this->bdd_nom);
if (!$this->connexion) {
throw new Exception('Erreur de connexion à la base de données, vérifiez les paramètres du fichier de configuration');
return;
}
break;
 
default:
$this->connexion = null;
}
 
if ($this->encodage != null) {
$this->requete("SET names '".$this->encodage."'");
}
}
 
/**
* Fonction qui appelle la bonne fonction pour executer une requête suivant le type de bdd.
*
* @param string la requete à effectuer
* @return PDOStatement un objet contenant le résultat de la requête
*/
final protected function requete($requete) {
// on ne se connecte que lors du premier appel à une requete (lazy connexion)
if ($this->connexion == null) {
$this->connecter();
}
 
$retour = null;
 
switch ($this->abstraction) {
case 'pdo':
$retour = $this->connexion->query($requete);
break;
case 'mysql':
$retour = mysql_query($requete,$this->connexion);
break;
case 'mysqli':
$retour = $this->connexion->query($requete);
break;
case 'sqlite3':
$retour = $this->connexion->exec($requete);
break;
}
 
return $retour;
}
 
final protected function requeteUn($requete,$mode = 'ASSOC') {
// Connection seulement lors du premier appel à une requete (lazy connexion)
if ($this->connexion == null) {
$this->connecter();
}
 
$retour = null;
switch ($this->abstraction) {
case 'pdo':
try {
$res_req = $this->connexion->query($requete);
$retour =$res_req->fetch($this->$mode);
} catch (PDOException $e) {
$message = 'Requête echec. Fichier : "%s". Ligne : "%s". Message : %s';
trigger_error(sprintf($message, $e->getFile(), $e->getLine(), $e->getMessage()), E_USER_WARNING);
}
break;
case 'mysql':
$res = mysql_query($requete,$this->connexion);
$fonction_fetch = $this->$mode;
$retour = $fonction_fetch($res);
break;
case 'mysqli':
$res = $this->connexion->query($requete);
$fonction_fetch = $this->$mode;
$retour = $res->$fonction_fetch();
break;
case 'sqlite3':
$retour = $this->connexion->querySingle($requete);
break;
}
 
return $retour;
}
 
 
final protected function requeteTous($requete,$mode = 'ASSOC') {
// Connexion seulement lors du premier appel à une requete (lazy connexion)
if ($this->connexion == null) {
$this->connecter();
}
 
$retour = null;
 
switch ($this->abstraction) {
case 'pdo':
try {
$res_req = $this->connexion->query($requete);
if ($res_req !== false) {
$retour = $res_req->fetchAll($this->$mode);
} else {
$retour = false;
}
} catch (PDOException $e) {
$message = 'Requête echec. Fichier : "%s". Ligne : "%s". Message : %s';
trigger_error(sprintf($message, $e->getFile(), $e->getLine(), $e->getMessage()), E_USER_WARNING);
}
break;
case 'mysql':
$res = mysql_query($requete, $this->connexion);
$fonction_fetch = $this->$mode;
while ($ligne = $fonction_fetch($res)) {
$retour[] = $ligne;
}
break;
case 'mysqli':
$res = $this->connexion->query($requete);
$function_fetch = $this->$mode;
while ($ligne = $res->$function_fetch()) {
$retour[] = $ligne;
}
break;
case 'sqlite3':
$res = $this->connexion->query($requete);
while ($ligne = $res->fetch_array($this->ASSOC)) {
if ($mode == $this->ASSOC) {
$retour[] = $ligne;
} elseif ($mode == $this->OBJECT) {
// cas particulier de sqllite
// qui n'a pas de fonction fetch_object
$ligneObjet = new stdClass();
foreach ($ligne as $colonne => $valeur) {
$ligneObjet->$colonne = $valeur;
}
$retour[] = $ligneObjet;
}
}
break;
}
 
return $retour;
}
 
/**
* protège une chaine de caractères avant l'insertion dans la base de données
*/
final protected function proteger($chaine) {
 
// on ne se connecte que lors du premier appel à une requete
if ($this->connexion == null) {
$this->connecter();
}
 
$retour = $chaine;
 
switch ($this->abstraction) {
case 'pdo':
$retour = $this->connexion->quote($chaine);
break;
case 'mysql':
$retour = '"'.mysql_real_escape_string($chaine, $this->connexion).'"';
break;
case 'mysqli':
$retour = '"'.$this->connexion->real_escape_string($chaine).'"';
break;
case 'sqlite3':
$retour = $this->connexion->escapeString($chaine);
break;
}
 
return $retour;
}
 
/**
* initialise les constantes de classe à leur bonne valeur
* et lance une exception si le protocole n'est pas bien défini
* @throws Exception
*/
final public function initialiserProtocole() {
 
switch ($this->abstraction) {
case 'pdo':
$this->ASSOC = PDO::FETCH_ASSOC;
$this->OBJECT = PDO::FETCH_CLASS;
break;
case 'mysql':
$this->ASSOC = 'mysql_fetch_assoc';
$this->OBJECT = 'mysql_fetch_object';
break;
case 'mysqli':
$this->ASSOC = 'fetch_assoc';
$this->OBJECT = 'fetch_object';
break;
case 'sqlite3':
$this->ASSOC = 'SQLITE3_ASSOC';
$this->OBJECT = 'SQLITE3_OBJECT';
break;
default:
throw new Exception('Erreur : l\'abstraction '.$this->abstraction.' n\'est pas prise en charge');
break;
}
}
 
/**
* Destructeur de classe, se contente de fermer explicitement la connexion
*/
final public function __destruct() {
switch ($this->abstraction) {
case 'pdo':
$this->connexion = null;
break;
case 'mysql':
return mysql_close($this->connexion);
break;
case 'mysqli':
$this->connexion->close();
break;
case 'sqlite3':
$this->connexion->close();
break;
}
}
}
?>
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/Debug.php
New file
0,0 → 1,123
<?php
// declare(encoding='UTF-8');
/**
* Classe fournissant des fonctions de débogage équivalante à var_dump et print_r.
* L'affichage et l'utilisation de ces fonctions sont améliorés via cette classe.
* Cette classe est inspirée de la classe Zend_Debug.
*
* PHP version 5
*
* @category Debogage
* @package Framework
// Auteur principal :
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
// Autres auteurs :
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $$Id$$
* @copyright 1999-2009 Tela Botanica (accueil@tela-botanica.org)
*/
class Debug {
 
/**
* mode de php (cli ou sapi)
*/
protected static $mode = null;
 
/**
* Accesseur pour le mode
* @return string le mode de php
*/
public static function getMode() {
if (self::$mode === null) {
self::$mode = PHP_SAPI;
}
return self::$mode;
}
 
/**
* Equivalent de var_dump
* @param mixed $variable la variable à dumper
* @param string $mot_cle le mot cle à associer à la variable
* @param boolean $echo si true on affiche le résultat, si false on ne renvoie que la chaine sans l'afficher
* @return string la chaine à afficher representant le dump ou null si echo
*/
public static function dump($variable, $mot_cle = null, $echo = true) {
// var_dump de la variable dans un buffer et récupération de la sortie
ob_start();
var_dump($variable);
$sortie = ob_get_clean();
 
// Pré-traitement de la sortie
$sortie = preg_replace("/\]\=\>\n(\s+)/m", "] => ", $sortie);
 
// Traitement général du débogage
return self::traiterDebogage($mot_cle, $sortie, $echo);
}
 
/**
* Equivalent de print_r
* @param mixed $variable la variable à afficher
* @param string $mot_cle le mot cle à associer
* @param boolean $echo faire un echo ou non
* @return string la chaine contenant la variable printée ou null si echo
*/
public static function printr($variable, $mot_cle = null, $echo = true) {
// Récupération de la sortie
$sortie = print_r($variable, true);
 
// Traitement général du débogage
return self::traiterDebogage($mot_cle, $sortie, $echo);
}
 
/**
* Traite une chaine de débogage et les mots clés associés
* @param string $mot_cle le mot à associer à la chaine
* @param string $sortie le chaine de debogage
* @param boolean $echo faire un echo du resultat ou non
* @return string la chaine de debogage formatée ou bien null si echo
*/
private static function traiterDebogage($mot_cle, $sortie, $echo) {
// Formate le mot-clé
$mot_cle = self::formaterMotCle($mot_cle);
 
// Traitement de la sortie
$sortie = self::traiterSortieSuivantMode($mot_cle, $sortie);
 
// Affichage et/ou retour
if (Config::get('fw_debogage') == true) {
if ($echo) {
echo $sortie;
return null;
} else {
return $sortie;
}
}
}
 
/**
* formate un mot clé donné
* @param string $mot_cle le mot clé à formaté
* @return string le mot clé formaté ou bien un chaine vide le mot clé est null ou vide
*/
private static function formaterMotCle($mot_cle) {
return ($mot_cle === null) ? '' : rtrim($mot_cle).' ';
}
 
/**
* traite la sortie de la chaine de débogage suivant le mode de php
* @param string $mot_cle le mot clé associé à la chaine
* @param string $sortie la chaine de débogage
* @return string la sortie formatée pour le mode en cours
*/
private static function traiterSortieSuivantMode($mot_cle, $sortie) {
$corps = $mot_cle.PHP_EOL.$sortie;
if (self::getMode() == 'cli') {
$sortie = PHP_EOL.$corps.PHP_EOL;
} else {
$sortie = '<pre>'.$corps.'</pre>';
}
return $sortie;
}
}
?>
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/GestionnaireException.php
New file
0,0 → 1,192
<?php
// declare(encoding='UTF-8');
/**
* Classe de gestion des exceptions.
* C'est un Singleton.
*
* PHP Version 5
*
* @category Class
* @package Framework
* @author aurelien <aurelien@tela-botanica.org>
* @copyright 2009 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version SVN: $$Id$$
* @link /doc/framework/
*
*/
class GestionnaireException {
 
/**
* Liste des exceptions enregistrées
*/
private static $exceptions = array();
 
/**
* Détermine si l'on affiche ou non le contexte
*/
private static $contexte = false;
 
/**
* Détermine si l'on loggue ou non les erreurs
*/
private static $logger = false;
 
/**
* Détermine si l'on loggue ou non les erreurs
*/
private static $afficher = false;
 
/**
* Definit si php est lancé en ligne de commande ou en mode serveur
*/
private static $mode = null ;
 
/**
* le gestionnaire d'exception est un singleton
* et possède donc un "pointeur statique sur lui-même"
*/
private static $gestionnaireException;
 
/**
* Constructeur avec paramètres optionnel
* @param bool indique si l'on veut afficher ou non le contexte des exceptions (i.e. la trace)
*/
public function __construct() {
self::$exceptions = array();
self::$contexte = Config::get('fw_debogage_contexte');
self::$logger = Config::get('fw_log_debogage');
self::$afficher = Config::get('fw_debogage');
self::$mode = php_sapi_name();
 
set_exception_handler(array(get_class($this),'gererException'));
set_error_handler(array(get_class($this),'gererErreur'));
}
 
/**
* Renvoie le booleen définissant si l'on affiche le contexte ou non
*/
public static function getContexte() {
return self::$contexte;
}
 
/**
* Definit si l'on veut afficher le contexte ou non
* @param bool true si on veut afficher le contexte, false sinon, par défaut vaut false
*/
public static function setContexte($contexte) {
self::$contexte = $contexte;
}
 
/** Fonction d'accès au singleton
* @return GestionnaireErreur le gestionnaire d'exceptions courant
*/
public static function getInstance() {
if (self::$gestionnaireException instanceof GestionnaireException) {
return self::$gestionnaireException;
}
self::$gestionnaireException = new GestionnaireException;
 
return self::$gestionnaireException;
}
 
/**
* Fonction de gestion des exceptions, remplace le handler par défaut
* @param Exception $e l'exception à traiter
*/
public static function gererException(Exception $e) {
// pour le moment on se contente de l'ajouter au tableau et de les afficher
self::$exceptions[] = $e;
 
// si on doit logger on envoie l'exception au loggeur
if (self::$logger) {
self::loggerException($e);
}
}
 
/**
* Gère les erreurs en les convertissant en exceptions (remplace la fonction gestion d'erreurs native de php)
* @param int $niveau le niveau de l'erreur
* @param string $message le message associé à l'erreur
* @param string $fichier le nom du fichier où l'erreur s'est produite
* @param int $ligne la ligne où l'erreur s'est produite
* @param string $contexte le contexte associé à l'erreur
*/
public static function gererErreur($niveau, $message, $fichier, $ligne, $contexte){
// si aucun rapport d'erreur, on sort directement
if (error_reporting() == 0) {
return;
}
 
// sinon on crée une exception
$e = new ErrorException($message, 0, $niveau, $fichier, $ligne);
// que l'on donne au tableau d'exceptions
self::$exceptions[] = $e;
// on la logge si nécéssaire
if (self::$logger) {
self::loggerException($e);
}
return;
}
 
/**
* Renvoie les exceptions au format (X)HTML
* ou bien au format texte suivant le mode d'utilisation de PHP
*/
public static function getExceptions() {
$retour = '';
foreach (self::$exceptions as $cle => $e) {
switch (self::$mode) {
case 'cli' :
$retour .= $e->getMessage()."\n";
$retour .= 'Fichier : '.$e->getFile()."\n";
$retour .= 'Ligne : '.$e->getLine()."\n";
if (self::getContexte()) {
$retour .= 'Contexte : '."\n".print_r($e->getTraceAsString(), true)."\n";
}
break;
default:
$retour .= '<pre class="debogage">'."\n";
$retour .= $e->getMessage()."\n";
$retour .= '<span class="debogage_fichier">'.'Fichier : '.$e->getFile().'</span>'."\n";
$retour .= '<span class="debogage_ligne">'.'Ligne : '.$e->getLine().'</span>'."\n";
$retour .= '</pre>'."\n";
 
if (self::getContexte()) {
$retour .= '<pre>'."\n";
$retour .= '<strong>Contexte : </strong>'."\n".print_r($e->getTraceAsString(), true)."\n";
$retour .= '</pre>'."\n";
}
}
// Nous vidons le tableau des exceptions au fur et à mesure
unset(self::$exceptions[$cle]);
}
return $retour;
}
 
/**
* logge une exception donnée sous une forme lisible
* @param Exception $e l'exception à logger
*/
private static function loggerException($e) {
$erreur = '';
$erreur .= $e->getMessage()."\n";
$erreur .= 'Fichier : '.$e->getFile()."\n";
$erreur .= 'Ligne : '.$e->getLine()."\n";
if (self::getContexte()) {
$erreur .= 'Contexte : '."\n".print_r($e->getTraceAsString(), true)."\n";
}
$erreur .= "\n";
Log::ajouterEntree('erreurs',$erreur);
}
 
public function __destruct() {
// Si des erreurs n'ont pas été affichée nous forçons leur affichage
if (self::$afficher && count(self::$exceptions) > 0) {
echo self::getExceptions();
}
}
 
}
?>
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/Controleur.php
New file
0,0 → 1,142
<?php
// declare(encoding='UTF-8');
/**
* Classe Controleur, coeur d'une application, c'est normalement la seule classe d'une application
* qui devrait être appelée de l'extérieur.
* Elle est abstraite donc doit obligatoirement être étendue.
*
* @category php5
* @package Framework
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright 2009 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version SVN: $$Id$$
* @link /doc/framework/
*
*/
abstract class Controleur {
/**
* Registre global, normalement accessible partout
*/
private $registre;
 
/**
* Constructeur par défaut
*/
public function __construct() {
if (Config::existe('fw_html_errors')) {
ini_set('html_errors', Config::get('fw_html_errors'));
}
 
$this->registre = Registre::getInstance();
$this->registre->set('base_chemin_modele', Config::get('chemin_modeles'));
$this->registre->set('base_chemin_squelette', Config::get('chemin_squelettes'));
$this->registre->set('base_chemin_controleur', Config::get('chemin_controleurs'));
$this->registre->set('base_url_application', new Url(Config::get('url_base')));
$this->verifierEtReencoderTableauRequete();
}
 
/**
* Charge un modele donné et le rend disponible sous la forme $this->nom_modele
*
* @param string $nom_modele le nom du modèle à  charger
*
* @return boolean false si le chargement a échoué, sinon true.
*/
final protected function chargerModele($nom_modele) {
$sortie = true;
$modele = $this->getModele($nom_modele);
if ($modele !== false) {
$this->$nom_modele = new $nom_modele;
} else {
$sortie = false;
}
return $sortie;
}
 
/**
* Retourne un modele donné
*
* @param string $nom_modele le nom du modèle à  charger
*
* @return mixed false si le chargement a échoué, sinon l'objet du modèle demandé.
*/
final protected function getModele($nom_modele) {
$sortie = false;
$chemin_modele = $this->registre->get('base_chemin_modele').$nom_modele.'.php';
if (file_exists($chemin_modele)) {
include_once $chemin_modele;
if (class_exists($nom_modele)) {
$sortie = new $nom_modele;
}
}
return $sortie;
}
 
/**
* Fonction prenant en paramètre le nom d'un squelette et un tableau associatif de données,
* en extrait les variables, charge le squelette et retourne le résultat des deux combinés.
*
* @param String $nom_squelette le nom du squelette
* @param Array $donnees un tableau associatif contenant les variables a injecter dans la vue
*
* @return boolean false si la vue n'existe pas, sinon la chaine résultat.
*/
final protected function getVue($nom_squelette, $donnees = array()) {
 
$donnees = $this->preTraiterDonnees($donnees);
$chemin_squelette = ($this->registre->get('base_chemin_squelette')).$nom_squelette.'.tpl.html';
 
$sortie = SquelettePhp::analyser($chemin_squelette, $donnees);
 
return $sortie;
}
 
/**
* Fonction prenant en paramètre un tableau de données et effectuant un traitement dessus.
* Cette fonction est à surcharger dans les classes filles pour automatiser un traitement
* avant chaque chargement de vue.
*
* @param Array $donnees Le tableau de données à traiter
*
* @return Array $donnees Le tableau de données traité
*/
protected function preTraiterDonnees($donnees) {
return $donnees;
}
 
/**
* Procédure vérifiant l'encodage des tableaux $_GET et $_POST et les transcodant dans l'encodage de l'application
*/
protected function verifierEtReencoderTableauRequete() {
if (Config::get('sortie_encodage') != Config::get('appli_encodage')) {
$_POST = $this->encoderTableau($_POST, Config::get('appli_encodage'), Config::get('sortie_encodage'));
$_GET = $this->encoderTableau($_GET, Config::get('appli_encodage'), Config::get('sortie_encodage'));
}
}
 
/**
* Fonction récursive transcodant toutes les valeurs d'un tableau de leur encodage d'entrée vers un encodage de sortie donné
* @param $tableau Array Un tableau de données à encoder
* @param $encodage_sortie String l'encodage vers lequel on doit transcoder
* @param $encodage_entree String l'encodage original des chaines du tableau (optionnel)
* @return Array Le tableau encodé dans l'encodage de sortie
*
*/
final protected function encoderTableau($tableau, $encodage_sortie, $encodage_entree = null) {
if (is_array($tableau)) {
foreach ($tableau as $cle => $valeur) {
if (is_array($valeur)) {
$tableau[$cle] = $this->encoderTableau($tableau[$cle], $encodage_sortie, $encodage_entree);
} else {
$tableau[$cle] = mb_convert_encoding($valeur, $encodage_sortie, $encodage_entree);
}
}
}
 
return $tableau;
}
}
?>
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/autoload.inc.php
New file
0,0 → 1,67
<?php
// declare(encoding='UTF-8');
/**
* Fichier contenant la fonction de chargement automatique de classes, il doit toujours rester à la racine
* du framework car il initialise le chemin de l'application en se basant sur son propre emplacement.
*
* PHP Version 5.1.2
*
* @category Fichier_De_Fonctions
* @package Framework
// Auteur principal :
* @author Aurelien PERONNET <aurelien@tela-botanica.org>
// Autres auteurs :
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $$Id$$
* @copyright 1999-2009 Tela Botanica (accueil@tela-botanica.org)
*/
 
// Redéfinition de la constante DIRECTORY_SEPARATOR
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
// Redéfinition de la constante PATH_SEPARATOR
if (!defined('PS')) {
define('PS', PATH_SEPARATOR);
}
 
// Autoload pour le Framework
function autoloadFw($nom_classe_fw) {
$fichier_a_inclure = dirname(__FILE__).DS.$nom_classe_fw.'.php';
if (file_exists($fichier_a_inclure)) {
include_once $fichier_a_inclure;
return null;
}
}
spl_autoload_register('autoloadFw');
 
// Instanciation du gestionnaire d'exception
GestionnaireException::getInstance();
// Instanciation du gestionnaire de logs
Log::getInstance();
// Encodage de l'application (défini ici car on peut avoir des sorties d'erreurs dès le début)
mb_internal_encoding(Config::get('appli_encodage'));
 
// Autoload par défaut pour l'application
function autoloadAppliDefaut($nom_classe) {
$dossiers_classes = array( Config::get('chemin_controleurs'),
Config::get('chemin_modeles'),
Config::get('chemin_bibliotheque'));
 
foreach ($dossiers_classes as $chemin) {
$fichier_a_tester = $chemin.$nom_classe.'.php';
if (file_exists($fichier_a_tester)) {
include_once $fichier_a_tester;
return null;
}
}
}
spl_autoload_register('autoloadAppliDefaut');
 
// Autoload défini par l'application
if (function_exists('__autoload')) {
spl_autoload_register('__autoload');
}
?>
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/Log.php
New file
0,0 → 1,192
<?php
//declare(encoding='UTF-8');
/**
* Classe permettant de logger des messages dans les fichier situés dans le dossier de log
*
* PHP Version 5
*
* @category PHP
* @package Framework
* @author aurelien <aurelien@tela-botanica.org>
* @copyright 2009 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/framework/
*/
 
class Log {
 
/**
* Boolean indiquant si l'on doit utiliser les logs ou pas
*/
private static $logger = false;
 
 
/**
* Tableau associatif stockant les descripteurs de fichiers
*/
private static $fichiersLog = array();
 
/**
* Chemin de base du dossier log de l'application
*/
private static $cheminLogs = '';
 
/**
* Booleen indiquant si l'on peut correctement écrire dans les fichiers de logs
*/
private static $droitLogger = true;
 
/**
* Zone horaire (pour éviter des avertissements dans les dates)
*/
private static $timeZone = '';
 
/**
* Taille maximum d'un fichier de log avant que celui ne soit archivé (en octets)
*/
private static $tailleMax = 10000;
 
/**
* séparateur de chemin
*/
private static $sd = DIRECTORY_SEPARATOR;
 
/**
* Extension des fichiers de log
*/
private static $ext = '.log';
 
/**
* La classe registre se contient elle-même, (pour le pattern singleton)
*/
private static $log;
 
/**
* Constructeur par défaut, privé, car on accède à la classe par le getInstance
*/
private function __construct() {
self::$sd = Config::get('ds');
self::$cheminLogs = Config::get('chemin_logs');
self::$timeZone = Config::get('fw_timezone');
self::$tailleMax = Config::get('fw_taille_max_logs');
self::$logger = Config::get('fw_log_debogage');
 
// gestion de la timezone pour éviter des erreurs
if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
date_default_timezone_set(self::$timeZone);
}
 
if (self::$logger && (!is_dir(self::$cheminLogs) || !is_writable(self::$cheminLogs))) {
self::desactiverEcriture();
}
}
 
/**
* Fonction qui renvoie l'instance de classe en assurant son unicité, c'est l'unique méthode qui doit être
* utilisée pour récupérer l'objet Registre
* @return Log le gestionnaire de log en cours
*/
public static function getInstance() {
if (self::$log instanceof Log) {
return self::$log;
}
self::$log = new Log();
return self::$log;
}
 
/**
* Ajoute une entrée au log spécifié par le paramètre $nomFichier
* @param string $nomFichier le nom du fichier dans lequel écrire
*/
public static function ajouterEntree($nomFichier,$entree,$mode='a+') {
if(self::$droitLogger) {
$date = "\n"."\n".date('d m Y H:i')."\n" ;
 
// si le fichier est déjà dans le tableau et qu'on peut y écrire
if(self::verifierOuvrirFichier($nomFichier,$mode)) {
// on y écrit le message de log
fwrite(self::$fichiersLog[$nomFichier],$date.$entree);
// on vérifie si le fichier ne dépasse pas la taille maximale
self::verifierTailleFichierOuArchiver($nomFichier);
} else {
// sinon on interdit l'écriture
self::desactiverEcriture($nomFichier);
}
}
}
 
/**
* Vide un fichier log indiqué
* @param string $nomFichier le nom du fichier à vider
*/
public static function viderLog($nomFichier) {
self::ajouterEntree($nomFichier, '', 'w');
}
 
/**
* Vérifie la présence d'un fichier dans le tableau, ses droits d'écriture,
* l'ouvre si nécessaire
* @param string $nomFichier le nom du fichier dont on doit vérifier la présence
* @return boolean true si le fichier est ouvert ou maintenant accessible, false sinon
*/
public static function verifierOuvrirFichier($nomFichier,$mode) {
// le fichier est il déjà ouvert ?
if (in_array($nomFichier, self::$fichiersLog)) {
// si oui peut on y écrire ?
if (is_writable(self::$cheminLogs.$nomFichier.self::$ext)) {
// si oui on renvoie le descripteur
return true;
}
return false;
} else {
// sinon on l'ouvre
$fp = @fopen(self::$cheminLogs.$nomFichier.self::$ext,$mode);
// si l'ouverture a réussi et si le fichier a les droits d'écriture
if ($fp && is_writable(self::$cheminLogs.$nomFichier.self::$ext)) {
// si oui on renvoie le descripteur qu'on ajoute au tableau
self::$fichiersLog[$nomFichier] = $fp;
return true;
}
return false;
}
}
 
/**
* Vérifie la taille d'un fichier donné et si celle ci est trop importante
* archive le fichier de log
* @param string $nomFichier nom du fichier à vérifier
*/
private static function verifierTailleFichierOuArchiver($nomFichier) {
if(filesize(self::$cheminLogs.$nomFichier.self::$ext) > self::$tailleMax) {
rename(self::$cheminLogs.$nomFichier.self::$ext,self::$cheminLogs.$nomFichier.date('d_m_Y_H:i').self::$ext);
self::ajouterEntree($nomFichier,'');
}
}
 
/**
* Désactive l'écriture du log et envoie un message au gestionnaire d'erreurs
* @param string $nomFichier le nom du fichier qui a causé l'erreur
*/
private static function desactiverEcriture($nomFichier = '') {
self::$droitLogger = false;
if ($nomFichier != '') {
$fichierDossier = 'fichier '.$nomFichier ;
} else {
$fichierDossier = 'dossier des logs';
}
$message = 'Écriture impossible dans le '.$fichierDossier.', Assurez-vous des droits du dossier et des fichiers';
$e = new ErrorException($message, 0, E_USER_WARNING, __FILE__, __LINE__);
GestionnaireException::gererException($e);
}
 
/**
* destructeur de classe, ferme les descripteurs ouverts
*/
public function __destruct() {
foreach(self::$fichiersLog as $nomFichier => $fp) {
fclose($fp);
}
}
}
?>
Property changes:
Added: svn:keywords
+Id Author Date Revision HeadURL
\ No newline at end of property
/branches/v0.2-buhl/framework/.
New file
Property changes:
Added: svn:ignore
+config.ini