378 lines
15 KiB
PHP
378 lines
15 KiB
PHP
|
<?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("&","&",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;
|
||
|
}
|
||
|
}
|