* @copyright Tela-Botanica 1999-2008 * @licence GPL v3 & CeCILL v2 * @version $Id: ScriptCommande.class.php 1948 2009-09-03 14:12:02Z Jean-Pascal MILCENT $ */ // +-------------------------------------------------------------------------------------------------------------------+ // TODO : supprimer les classe getStaticIni(), getStaticParam() et getStaticNom(). Utiliser une seule méthode qui gère les deux méthodes d'appel. /** * classe representant une commande */ abstract class ScriptCommande extends Controleur { public $nom; public $parametres; /** * Paramêtres disponible pour la ligne de commande * le tableau se construit de la forme suivnate : * - clé = nom du paramêtre '-foo' * - value = contient un nouveau tableau composé de cette façaon : * - booléen: true si le paramêtre est obligatoire * - booléen ou var : true si le paramêtre nécessite un valeur à sa suite ou la valeur par défaut * - string: description du contenu du paramêtre * Les paramêtres optionels devraient être déclaré à la fin du tableau. * Le dernier parametre du tableau peut avoir la valeur '...', * il contiendra alors l'ensemble des paramêtres suivant trouvés sur la ligne de commande. * @var array */ private $_parametres_autorises = array( '-a' => array(true, true, 'Action à réaliser'), '-v' => array(false, '1', 'Mode verbeux : 1 ou 2'), '-t' => array(false, '', 'Test sur un nombre de ligne...')); /** * Contient les valeurs des paramêtres récupérés de la ligne de commande : * le tableau se construit de la forme suivnate : * - clé = nom du paramêtre '-foo' * - valeur = la valeur récupérée sur la ligne de commande * @var array */ private $_parametres; private static $_static_nom; private static $_static_parametres; private static $_static_ini; private static $log = ''; private static $log_fichier; private static $log_resource; private static $log_fichier_ecraser = false; public $syntaxhelp = ''; public $help = 'Aucune aide pour cette commande'; function __construct($commande_nom) { $this->setNom($commande_nom); parent::__construct(); } public function __destruct() { if (isset(self::$log_resource)) { if (fclose(self::$log_resource)) { self::$log_resource = null; } } } public function getNom() { return $this->nom; } public static function getStaticNom() { return self::$_static_nom; } private function setNom($script_nom) { $this->nom = $script_nom; self::$_static_nom = $script_nom; } public static function getLog() { return self::$log; } public static function setLog($l) { self::$log .= $l; } public function initialiser($plc) { // Récupération des paramêtres autorisés par le script $this->setParamAutorises($this->parametres); // Vérification et récupération des paramêtres de la ligne de commande if ($parametres = $this->verifierParametres($plc, $this->getParamAutorises())) { $this->setParam($parametres); } $tab_fichiers_ini = array( ES_CHEMIN_CONFIG.'bdd.ini', // Paramêtres de la base de données ES_CHEMIN_CONFIG.'commun.ini', // Paramêtres communs aux différents projets $this->getModuleChemin().DS.'configurations'.DS.'config.ini'); // Chargement des fichiers ini généraux for ($i = 0; $i < 2 ; $i++) { if (!$this->parserFichierIni($tab_fichiers_ini[$i])) { $e = "Le fichier $tab_fichiers_ini[$i] est introuvable\n"; trigger_error($e, E_USER_WARNING); } } } abstract public function executer(); protected function getModuleChemin($shouldexist = true) { $chemin = ES_CHEMIN_MODULE.$this->getNom().DS; if (!file_exists($chemin) && $shouldexist) { trigger_error("Erreur: le module '".$this->getNom()."' n'existe pas ($chemin)\n", E_USER_ERROR); } return $chemin; } private function verifierParametres($p_ligne, $p_autorise) { //print_r($p_ligne); // Récupération des paramêtres foreach ($p_autorise as $p_nom => $p_val) { if (count($p_ligne) == 0) { if ($p_val[0]) { trigger_error("Erreur: paramêtre manquant '".$p_nom."' \n", E_USER_WARNING); } } if ($p_nom == '...') { $parametres['...'] = array(); foreach($p_ligne as $arg) { $parametres['...'][] = $arg; } $p_ligne = array(); break; } else { if (isset($p_ligne[$p_nom])) { // Attribution de la valeur issue de la ligne de commande $parametres[ltrim($p_nom, '-')] = $p_ligne[$p_nom]; unset($p_ligne[$p_nom]); } else { // Attribution de la valeur par défaut if ($p_val[1] !== true) { $parametres[ltrim($p_nom, '-')] = $p_val[1]; } } } } // Gestion de l'excédant de paramêtres if (count($p_ligne)) { trigger_error("Erreur: trop de paramêtres\n", E_USER_ERROR); } return $parametres; } protected function setParamAutorises($param) { if (!is_null($param)) { foreach ($param as $c => $v) { if (isset($this->_parametres_autorises[$c])) { trigger_error("Erreur: le module '".$this->getNom()."' ne peut définir le paramêtre '$c' car il existe déjà\n", E_USER_ERROR); } else { $this->_parametres_autorises[$c] = $v; } } } } protected function getParamAutorises($param = null) { if (!is_null($param)) { if (isset($this->_parametres_autorises['-'.$param])) { return $this->_parametres_autorises['-'.$param]; } else if (isset($this->_parametres_autorises[$param])) { return $this->_parametres_autorises[$param]; } else { trigger_error("Erreur: le module '".$this->getNom()."' n'a pas défini le paramêtre '$param'\n", E_USER_WARNING); return false; } } else { return $this->_parametres_autorises; } } protected function setParam($params = array(), $val = null) { if (is_array($params)) { $this->_parametres = $params; self::$_static_parametres = $params; } else if (!is_array($params) && !is_null($val)) { $this->_parametres[$params] = $val; self::$_static_parametres[$params] = $val; } else { return false; } } protected function getParam($param = null) { if (!is_null($param)) { if (isset($this->_parametres['-'.$param])) { return $this->_parametres['-'.$param]; } else if (isset($this->_parametres[$param])) { return $this->_parametres[$param]; } else { trigger_error("Erreur: la ligne de commande ne contenait pas le paramêtre '$param'\n", E_USER_WARNING); return false; } } else { return $this->_parametres; } } protected static function getStaticParam($param = null) { if (!is_null($param)) { if (isset(self::$_static_parametres['-'.$param])) { return self::$_static_parametres['-'.$param]; } else if (isset(self::$_static_parametres[$param])) { return self::$_static_parametres[$param]; } else { trigger_error("Erreur: la ligne de commande ne contenait pas le paramêtre '$param'\n", E_USER_WARNING); return false; } } else { return self::$_static_parametres; } } protected function getIni($nom) { if (isset($this->_ini[$nom])) { return $this->_ini[$nom]; } else { return false; } } protected static function getStaticIni($nom) { if (isset(self::$_static_ini[$nom])) { return self::$_static_ini[$nom]; } else { return false; } } protected function parserFichierIni($fichier_ini) { if (file_exists($fichier_ini)) { $aso_ini = parse_ini_file($fichier_ini); foreach ($aso_ini as $cle => $val) { if (preg_match('/^php:(.+)$/', $val, $correspondances)) { eval('$this->$cle = '.$correspondances[1].';'); eval('$this->_ini[$cle] = '.$correspondances[1].';'); } else if (preg_match('/^php-static:(.+)$/', $val, $correspondances)) { eval('self::$'.$cle.' = '.$correspondances[1].';'); eval('$this->_ini[$cle] = '.$correspondances[1].';'); } else { // Ancienne forme : compatibilité avec les anciens scripts... $this->$cle = $val; // Nouvelle forme : utilisation de la méthode getInit(). $this->_ini[$cle] = $val; } } self::$_static_ini = $this->_ini; return true; } else { return false; } } // Log Resource /** * Lit la valeur de l'attribut Log Resource. * Utilise le motif de conception (= design pattern) Singleton. * * @access public * @param string le préfixe du nom de fichier à créer. * @return string retourne le Log Resource. */ public static function getLogResource() { if (!isset(self::$log_resource)) { if (file_exists(self::getLogFichier()) && !self::$log_fichier_ecraser) { // Ouvre en écriture seule ; place le pointeur de fichier à la fin du fichier. Si le fichier // n'existe pas, on tente de le créer. self::$log_resource = fopen(self::getLogFichier(), 'a'); } else { //Ouvre en écriture seule ; place le pointeur de fichier au début du fichier et réduit la taille // du fichier à 0. Si le fichier n'existe pas, on tente de le créer. self::$log_resource = fopen(self::getLogFichier(), 'w'); $entete_utf8 = "\xEF\xBB\xBF"; if (!fwrite(self::$log_resource, $entete_utf8)) { echo "Erreur écriture dans le fichier de log lors de l'ajout de l'entête UTF8.\n"; } } } return self::$log_resource; } // Log Fichier /** * Lit la valeur de l'attribut Log Fichier. * Utilise le motif de conception (= design pattern) Singleton. * * @access public * @return string retourne le nom du fichier de log. */ public static function getLogFichier() { if (!isset(self::$log_fichier)) { if (self::getStaticIni('projet_nom') && self::getStaticIni('version') && self::getStaticIni('sous_version')) { $fichier = self::getStaticIni('projet_nom').'_'. self::getStaticNom().'_'. self::getStaticParam('a').'_'. 'v'.self::getStaticIni('version').'_'.self::getStaticIni('sous_version'); } else { $fichier = self::getStaticNom().'_'.self::getStaticParam('a'); } if (!self::$log_fichier_ecraser) { $fichier .= '_'.date('Y-m-j_H:i:s', time()); } $fichier .= '.log'; // Ajout du chemin vers le fichier de log et stockage dans variable static self::$log_fichier = self::getStaticIni('log_chemin').$fichier; } return self::$log_fichier; } /** * Retourne un message d'avertissement formaté. * * @param string le message d'erreur avec des %s. * @param array le tableau des paramêtres à insérer dans le message d'erreur. * @param int le niveau de verbosité à dépasser pour afficher les messages. * @return string le message d'erreur formaté. */ private function traiterMessage($message, $tab_arguments = array(), $niveau = 0) { // Nous ajoutons dans le texte les infos provenant de la BDD (déjà encodées en UTF-8). $texte = vsprintf($message, $tab_arguments); if ($this->getParam('v') >= $niveau) { $prefixe = ''; if ($this->getIni('projet_nom') && $this->getIni('version') && $this->getIni('sous_version')) { $prefixe = $this->getIni('projet_nom').'v'.$this->getIni('version').'.'.$this->getIni('sous_version').'. '; } else { $prefixe = date('Y-m-j_H:i:s', time()).' - '.Script::getCode($niveau).' : '; } $log = $prefixe.$texte."\n"; echo $log; self::setLog($log); if (!fwrite($this->getLogResource(), $log)) { trigger_error('Erreur écriture dans le fichier de log.'."\n", E_USER_WARNING); } } return "\t".$texte."\n"; } /** * Retourne un message d'erreur après avoir écrit le message danns le fichier de log. * Si le mode verbeux est inactivé, écrit le message dans le fichier de log. * Si le mode verbeux de niveau 1 ou plus est activé, écrit le message dans le fichier de log et dans la console. * * @param string le message d'erreur avec des %s. * @param array le tableau des paramêtres à insérer dans le message d'erreur. * @return string le message d'erreur formaté. */ protected function traiterErreur($message, $tab_arguments = array()) { $niveau = Script::ERREUR; return $this->traiterMessage($message, $tab_arguments, $niveau); } /** * Retourne un message d'avertissement formaté. * Si le mode verbeux de niveau 1 est activé, écrit le message dans le fichier de log. * Si le mode verbeux de niveau 2 est activé, écrit le message dans le fichier de log et dans la console. * * @param string le message d'erreur avec des %s. * @param array le tableau des paramêtres à insérer dans le message d'erreur. * @return string le message d'erreur formaté. */ protected function traiterAttention($message, $tab_arguments = array()) { $niveau = Script::AVERTISSEMENT; return $this->traiterMessage($message, $tab_arguments, $niveau); } /** * Retourne un message d'information formaté. * Si le mode verbeux de niveau 2 est activé, écrit le message dans le fichier de log. * Si le mode verbeux de niveau 3 est activé, écrit le message dans le fichier de log et dans la console. * * @param string le message d'information avec des %s. * @param array le tableau des paramêtres à insérer dans le message d'erreur. * @param int le niveau de verbosité à dépasser pour afficher les messages. * @return string le message d'erreur formaté. */ protected function afficher($message, $tab_arguments = array(), $niveau = null) { if (is_null($niveau)) { $niveau = Script::INFO; } $msg = $this->traiterMessage($message, $tab_arguments, $niveau); return $msg ; } /** * Méthode 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 le squelette n'existe pas, sinon la chaine résultat. */ public static function traiterSquelettePhp($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 (/", "; ?>", $contenu); return $contenu; } /** * Créer et stocke du contenu dans un fichier. * * @param string le chemin et le nom du fichier. * @param string le contenu à stocker dans le fichier. * @param boolean true pour compresser (gz) le fichier. Par défaut vaut false. * @return string le message d'erreur formaté. */ protected function creerFichier($fichier, $contenu, $compression = false) { $e = null; if ($compression) { // Ajout de l'extension gz if (substr($fichier, -3) != '.gz') { $fichier = $fichier.'.gz'; } // Début de l'écriture du fichier compressé if ($resource = gzopen($fichier, 'w9')) { if (!gzwrite($resource, $contenu)) { $e = "Le contenu texte n'a pas pu être écrit dans le fichier compressé '$fichier'."; } if (!gzclose($resource)) { $e = "Le fichier compressé '$fichier' n'a pas pu être fermé."; } } else { $e = "Le fichier compressé '$fichier' n'a pas pu être ouvert."; } } else { if ($resource = fopen($fichier, 'w')) { if (!fwrite($resource, $contenu)) { $e = "Le contenu texte n'a pas pu être écrit dans le fichier '$fichier'."; } if (!fclose($resource)) { $e = "Le fichier '$fichier' n'a pas pu être fermé."; } } else { $e = "Le fichier '$fichier' n'a pas pu être ouvert."; } } if (is_null($e)) { return true; } else { trigger_error($e, E_USER_WARNING); return false; } } /** * Méthode permettant d'encoder de l'iso-8859-15 vers utf-8 un tableau de variables. * * @param mixed la chaine ou le tableau à encoder en utf-8 depuis l'iso-8859-15. * @param string l'encodage d'origine si ce n'est pas ISO-8859-15. * @return mixed la chaine ou le tableau encodé en utf-8. * @access protected */ protected function encoderUtf8( &$val, $encodage = 'ISO-8859-15') { //echo print_r($val, true)."\n"; if (is_array($val)) { foreach ($val as $c => $v) { $val[$c] = $this->encoderUtf8($v); } } else { // Nous vérifions si nous avons un bon encodage UTF-8 if (!is_numeric($val) && !empty($val) && !$this->detecterUtf8($val)) { // Les nombres, les valeurs vides et ce qui est déjà en UTF-8 ne sont pas encodés. $val = mb_convert_encoding($val, 'UTF-8', $encodage); } } return $val; } /** * Méthode permettant de détecter réellement l'encodage utf8. * mb_detect_encoding plante si la chaine de caractère se termine par un caractère accentué. * Provient de PHPDIG. * * @param string la chaine à vérifier. * @return bool true si c'est de l'utf8, sinon false. * @access private */ private function detecterUtf8($str) { if ($str === mb_convert_encoding(mb_convert_encoding($str, 'UTF-32', 'UTF-8'), 'UTF-8', 'UTF-32')) { return true; } else { return false; } } } ?>