hellofacteurV1/modele/journal_erreurs.php

378 lines
15 KiB
PHP
Executable File

<?php
/**
* classe minimaliste permettant de gérer un journal des erreurs / application
* les infos sont stockées dans des fichiers
* ce script étant appelé avant tous les autres
* il ne doit lui-même utiliser que des classes et fonctions natives
*
* @author Fabrice PENHOËT
**/
class journal_erreurs
{
private $script;// adresse du script où survient l'erreur
private $ligne;// ligne du script où est enregistrée l'erreur
private $page;// la page où le script est appelé
private $message;// le message d'erreur à enregistrer
public $erreurs=array(); // erreurs rencontrées dans les méthodes
/**
* Constructeur qui initialise certains attributs en testant les valeurs fournies
*
* @param infos_erreur tableau contenant les infos à ajouter au journal (vide sinon).
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
public function __construct($infos_erreur=null)
{
if(!empty($infos_erreur))
{
if(empty($infos_erreur[0])||(empty($infos_erreur[1]))||(empty($infos_erreur[2])))
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_ECRITURE." >> ".ERREUR_PARAM_MANQUANT));
return false;
}
else if(!file_exists($infos_erreur[0]))
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_ECRITURE." >> ".ERREUR_FICHIER_EXISTE));
return false;
}
else if(!is_int($infos_erreur[1]))
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_ECRITURE." >> ".ERREUR_JOURNAL_LIGNE));
return false;
}
else
{
$this->script=$infos_erreur[0];
$this->ligne=$infos_erreur[1];
$this->message=strip_tags($infos_erreur[2]);
if(!empty($infos_erreur[3]))
$this->page=$infos_erreur[3];
else
$this->page=(isset($GLOBALS['page'])&&(is_array($GLOBALS['page']))) ? htmlspecialchars(implode("/",$GLOBALS['page'])) : "inconnue";
/*
if(!empty($_SERVER['QUERY_STRING']))
$this->page=$_SERVER['QUERY_STRING'];
elseif(!empty($_SERVER['HTTP_REFERER']))
$this->page=$_SERVER['HTTP_REFERER'];
else
$this->page="";*/
if($this->ajout_journal())
return true;
else
return false;
}
}
else
return true;
}
/**
* Méthode qui enregistre une nouvelle entrée dans le journal.
*
* @param null
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
private function ajout_journal()
{
if(!defined('JOURNAL_REP'))
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_ECRITURE." >> ".ERREUR_JOURNAL_REP));
return false;
}
$repertoire_fichier=JOURNAL_REP."/".strval(date('Y/m/'));
$nom_fichier=strval(date('d')).".journal";
$now=time();
$code="\$journal[$now]['script']='".$this->script."';\$journal[$now]['ligne']='".$this->ligne."';\$journal[$now]['page']=\"".str_replace("\"","'",$this->page)."\";\$journal[$now]['erreur']=\"".str_replace("\"","'",$this->message)."\";";
if(file_exists($repertoire_fichier.$nom_fichier))
{
if(!file_put_contents($repertoire_fichier.$nom_fichier,$code,FILE_APPEND | LOCK_EX))
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_ECRITURE." >> ".ERREUR_FICHIER_ECRITURE));
return false;
}
else
return true;
}
else
{
if(!file_exists($repertoire_fichier))
{
if(!mkdir($repertoire_fichier,JOURNAL_REP_CHMOD,true))
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_ECRITURE." >> ".ERREUR_REP_CREA));
return false;
}
}
if(!file_put_contents($repertoire_fichier.$nom_fichier,"<?php\n$code",LOCK_EX))
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_ECRITURE." >> ".ERREUR_FICHIER_ECRITURE));
return false;
}
else
return true;
}
}
/**
* Lecture du fichier du journal sur un période
*
* @param dates de début et de fin de la période au format JJ/MM/AAAA
* @return tableau contenant les enregistrements du journal. false si ça plante.
* @author Fabrice PENHOËT
**/
public function get_journal($date_debut="",$date_fin="")
{
if(!defined('JOURNAL_REP'))
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_LECTURE." >> ".ERREUR_JOURNAL_REP));
return false;
}
if(empty($date_debut))
$date_debut=date("d/m/Y");
if(empty($date_fin))
$date_fin=$date_debut;
if(preg_match(DATE_FORMAT_EREG,$date_debut)==0)
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_LECTURE." >> ".ERREUR_DATE_FORMAT));
return false;
}
if(preg_match(DATE_FORMAT_EREG,$date_fin)==0)
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_LECTURE." >> ".ERREUR_DATE_FORMAT));
return false;
}
$dates_debut=explode("/",$date_debut);
$dates_fin=explode("/",$date_fin);
if(!checkdate($dates_debut[1],$dates_debut[0],$dates_debut[2]))
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_LECTURE." >> ".ERREUR_DATE_VALIDE));
return false;
}
if(!checkdate($dates_fin[1],$dates_fin[0],$dates_fin[2]))
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_LECTURE." >> ".ERREUR_DATE_VALIDE));
return false;
}
if(IntervalDates($date_debut,$date_fin)<0)
{
$this->erreurs=array_merge($this->erreurs,(array) (ERREUR_JOURNAL_LECTURE." >> ".ERREUR_DATE_INTERVAL));
return false;
}
$journal_periode=array();
$date_journal=$date_debut;
while(IntervalDates($date_journal,$date_fin)>=0)
{
$dates_journal=explode("/",$date_journal);
$adresse_journal=JOURNAL_REP."/".$dates_journal[2]."/".$dates_journal[1]."/".$dates_journal[0].".journal";
if(file_exists($adresse_journal))
{
include($adresse_journal);
if(is_array($journal))
$journal_periode=$journal_periode+$journal;
unset($journal);
}
// date à 4H du matin pour ne pas rester coincé avec les heures d'été qui changent à 3H du matin...
$date_journal=date("d/m/Y",mktime(4,0,0,$dates_journal[1],$dates_journal[0],$dates_journal[2])+3600*24);
}
return $journal_periode;
}
/**
* Je retourne une version sans doublon du journal des erreurs
* c'est-à-dire qu'une même erreur n'est pas affichée plusieurs fois
*
* @param dates de début et de fin de la période au format JJ/MM/AAAA
* @return tableau contenant les enregistrements du journal sans doublon. false si ça plante.
* @author Fabrice PENHOËT
**/
public function get_journal_sansdoublon($date_debut="",$date_fin="")
{
$logs=$this->get_journal($date_debut,$date_fin);
if(!empty($logs))
{
krsort($logs);//les + récents d'abord
$logs_sansdoublon=array();
foreach($logs as $timestamp=>$infos)
{
$index=urlencode($infos["erreur"].$infos["script"]);
if(!isset($logs_sansdoublon[$index]))
{
$logs_sansdoublon[$index]["msg"]=str_replace("&amp;","&",htmlentities($infos["erreur"]));
$logs_sansdoublon[$index]["script"]=htmlentities($infos["script"]);
$logs_sansdoublon[$index]["pages"][]=htmlentities($infos["page"]);
$logs_sansdoublon[$index]["cpt"]=1;
$logs_sansdoublon[$index]["times_premier"]=$timestamp;
$logs_sansdoublon[$index]["times_dernier"]=$timestamp;
$logs_sansdoublon[$index]["lignes"][]=$infos["ligne"];
}
else
{
$logs_sansdoublon[$index]["cpt"]=$logs_sansdoublon[$index]["cpt"]+1;
if(!in_array($infos["ligne"],$logs_sansdoublon[$index]["lignes"]))
$logs_sansdoublon[$index]["lignes"][]=$infos["ligne"];
if(!in_array($infos["page"],$logs_sansdoublon[$index]["pages"]))
$logs_sansdoublon[$index]["pages"][]=$infos["page"];
if($logs_sansdoublon[$index]["times_premier"]>$timestamp)
$logs_sansdoublon[$index]["times_premier"]=$timestamp;
if($logs_sansdoublon[$index]["times_dernier"]<$timestamp)
$logs_sansdoublon[$index]["times_dernier"]=$timestamp;
}
}
return $logs_sansdoublon;
}
else
return $logs;
}
/**
* Supprime les fichiers du journal plus anciens que la date fournie
*
* @param date limite format JJ/MM/AAAA. Vide pour supprimer toutes les archives.
* @return true si tout c'est bien passé, un message d'erreur sinon
* @author Fabrice PENHOËT
**/
static function vide_journal($date_limite="")
{
if(!defined('JOURNAL_REP'))
return ERREUR_JOURNAL_SUPPR." >> ".ERREUR_JOURNAL_REP;
if(empty($date_limite))
{
if(!supprime_repertoire(JOURNAL_REP."/",false))
return ERREUR_JOURNAL_SUPPR." >> ".__LINE__;
else
return true;
}
else
{
if(preg_match(DATE_FORMAT_EREG,$date_limite)==0)
return ERREUR_JOURNAL_SUPPR." >> ".ERREUR_DATE_FORMAT;
$dates_limite=explode("/",$date_limite);
if(!checkdate($dates_limite[1],$dates_limite[0],$dates_limite[2]))
return ERREUR_JOURNAL_SUPPR." >> ".ERREUR_DATE_VALIDE;
if(is_dir(JOURNAL_REP))
{
$rep_annee=opendir(JOURNAL_REP);
while($annee=readdir($rep_annee))
{
if((intval($annee)<intval($dates_limite[2]))&&($annee!=".")&&($annee!=".."))
supprime_repertoire(JOURNAL_REP."/".$annee);
else if(($annee!=".")&&($annee!=".."))
{
$rep_mois=opendir(JOURNAL_REP."/".$annee);
while($mois=readdir($rep_mois))
{
if((intval($mois)<intval($dates_limite[1]))&&($mois!=".")&&($mois!="..")&&(intval($annee)==intval($dates_limite[2])))
supprime_repertoire(JOURNAL_REP."/".$annee."/".$mois);
else if(($mois!=".")&&($mois!=".."))
{
$rep_jours=opendir(JOURNAL_REP."/".$annee."/".$mois);
while($jour=readdir($rep_jours))
{
if((intval($jour)<intval($dates_limite[0]))&&($jour!=".")&&($jour!="..")&&(intval($mois)==intval($dates_limite[1])))
unlink(JOURNAL_REP."/".$annee."/".$mois."/".$jour);
}
closedir($rep_jours);
}
}
closedir($rep_mois);
}
}
closedir($rep_annee);
}
else
return ERREUR_JOURNAL_SUPPR." >> ".ERREUR_REP_VALIDE;
}
}
/**
* Méthode générant un email en direction de l'administrateur avec les différents chiffres concernant les stats du site
* + le journal des dernières 24H
*
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
static function get_stats_journal_admin()
{
// les stats utilisateurs
global $Bd;
if((isset_connexion(__FILE__,__LINE__)===false)) return false;
$blabla_stats="";
//dernières 24H.
$debut=time()-24*3600;
$stats_jour=FclFlux_utilisateur::get_stats_utilisateurs($debut);
if(!empty($stats_jour))
$blabla_stats.="<h1>Stats des dernières 24H.</h1><p>Sur cette période, <b>".$stats_jour["nb_comptes"]." compte(s)</b> et <b>".$stats_jour["nb_abo"]." abonnements</b> ont été créé(s) pour <b>".$stats_jour["nb_comptes_suppr"]." comptes supprimé(s)</b>.<br><br><b>".$stats_jour["nb_mail_envoyes"]." mails envoyés à ".$stats_jour["nb_mail_uniques_envoyes"]." utilisateurs</b> différents, ce qui a généré <b>". $stats_jour["nb_clics_email"]." clics de ".$stats_jour["nb_clics_uniques_email"]." utilisateurs</b> différents.<br><br>Sur le partie web, <b>".$stats_jour["nb_clics_site"]." clics de ".$stats_jour["nb_clics_uniques_site"]." utilisateurs</b> différents, soit en tout : <b>". $stats_jour["nb_clics"]." clics de ".$stats_jour["nb_clics_uniques"]." utilisateurs</b> différents.</p>";
//global
$stats_totales=FclFlux_utilisateur::get_stats_utilisateurs(0);
if(!empty($stats_totales))
$blabla_stats.="<h1>Stats globales.</h1><p>En tout, <b>".$stats_totales["nb_comptes"]." comptes</b> utilisateur enregistrés dont ".$stats_totales["nb_comptes_valide"]." validés dont <b>".$stats_totales["nb_abonnes_email"]." abonnés (".round($stats_totales["nb_abonnes_email"]/($stats_totales["nb_comptes"]*0.01))." %) toujours actifs</b>.<br><br><b>".$stats_totales["nb_abo"]." abonnements</b> dont <b>".$stats_totales["nb_abo_email"]." par email</b> pour <b>".$stats_totales["nb_abonnes"]." abonnés</b> différents.<br><br>Il y a actuellement <b>".$stats_totales["nb_fantomes"]." utilisateurs sans abonnement</b> parmi ceux validés, soit <b>".round($stats_totales["nb_fantomes"]/($stats_totales["nb_comptes"]*0.01))." %</b>.<br><br>Et <b>".$stats_totales["nb_abonnes_desactives"]." abonnés qui ont été désactivés</b> soit <b>".round($stats_totales["nb_abonnes_desactives"]/($stats_totales["nb_comptes"]*0.01))." %</b> de tous les utilisateurs.</p>";
//journal admin dernières 24H.
$bug=new journal_erreurs;
$t_limite=time()-3600*24;
$date_debut=date("d/m/Y",$t_limite);
$date_fin=date("d/m/Y");
$erreurs_admin=$bug->get_journal_sansdoublon($date_debut,$date_fin);
if(is_array($erreurs_admin))
{
$blabla_stats.="<h1>Journal des logs des dernières 24H.</h1><p>";
foreach($erreurs_admin as $infos)
{
if($infos["times_dernier"]>$t_limite)
{
$blabla_stats.="<strong>".$infos["msg"]."</strong><br> >> ".$infos["script"].", ligne(s) : ".implode("|",$infos["lignes"]);
$blabla_stats.="<br>Page(s) d'appel : ".implode("|",$infos["pages"])."<br><i> >> <b><u>".$infos["cpt"]." fois</u></b>";
if($infos["times_premier"]!=$infos["times_dernier"])
$blabla_stats.=", du ".date("d/m/Y H:i:s",$infos["times_premier"])." au ".date("d/m/Y H:i:s",$infos["times_dernier"])."</i>.";
else
$blabla_stats.=" le ".date("d/m/Y H:i:s",$infos["times_premier"])."</i>.";
$blabla_stats.="<br><br>";
}
}
$blabla_stats.="</p>";
}
// envoi du message avec PHPMailer
// connexion au serveur smtp si il y a lieu :
require(BASE_REP."../divers/phpmailer-initialise.php");
$Mail_expediteur_email=EMAIL_TRANSACTIONNEL_DE;
$Mail_expediteur_nom=SITE_NOM;
$Mail_destinataire_email=EMAIL_ADMIN;
$Mail_destinataire_nom=SITE_NOM;
$Mail_sujet="Statistiques & journal dernières 24H.";
// message alternatif lorsque le html n'est pas lu :
$Mail_boby_txt="Pour voir les statistiques des dernières 24H, se connecter au site.";
//-- version html :
//texte invisible (sauf certains webmail ?) :
$Mail_html_sujet="Stats des dernières 24H pour ".SITE_NOM.".";
//entête avant logo :
$Mail_html_header="Stats des dernières 24H pour ".SITE_NOM.".";
//texte du message, hors liste de liens :
$Mail_html_intro=$blabla_stats;
//footer du mail html :
$Mail_html_footer="<p><a href='".SITE_NOM."'>".SITE_NOM."</a>, ".SITE_SLOGAN."</p>";
$Mail_boby_html="";
ob_start();
include(BASE_REP."../www/".TEMPLATE_REP."/mail/defaut.php");
$Mail_boby_html=ob_get_contents();
ob_end_clean();
$SMTP_CustomHeader["X-Mailin-Tag"]="stats_admin";
require(BASE_REP."../divers/phpmailer-envoi.php");
if(!$mail->Send())
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_EMAIL_ENVOI.$mail->ErrorInfo));
$this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_VALIDATION_MESSAGE);
}
}
/**
* Affichage par défaut d'un objet de la classe journal
*
* @return chaîne de caractères listant la valeur de chaque attribut
* @author Fabrice PENHOËT
**/
public function __toString()
{
$texte="Valeurs actuelles des attributs de l'objet ".__CLASS__." :\n";
foreach($this as $key => $value)
{
if(is_array($value))
$value=affiche_tableau($value,"<li>#valeur</li>","<ul>","</ul>");
$texte.="$key : $value\n";
}
return $texte;
}
}