hellofacteurV1/modele/FclFlux_lien.php

491 lines
18 KiB
PHP
Executable File

<?php
/**
* classe dérivée de la classe Lien décrivant les liens récupérés lors de l'importation des flux
* on traite aussi ici les clics & partages des utilisateurs concernant ces liens
* un journal permet de les enregistrer de manière différée
* des listes des liens les plus cliqués / partagés pourront servir pour les stats
* on a besoin de la classe FclFlux_utilisateur pour désigner les auteurs de clics / partages
* + de la classe FclFlux_flux pour désigner le flux à l'origine du lien.
*
* @author Fabrice PENHOËT
**/
require_once("lien.php");
require_once("FclFlux_utilisateur.php");
require_once("FclFlux_flux.php");
class FclFlux_lien extends Lien
{
public $id_lien;
protected $flux;// le flux à l'origine du lien
protected $time_lien;//timestamp de l'enregistrement du lien.
/**
* Constructeur qui initialise certains attributs en testant les valeurs fournies
* copier/ coller de la classe héritée mais méthodes contrôlant des champs supplémentaires
*
* @param infos tableau contenant les différentes données correspondant aux attributs (supposés homonymes)
* @return null
* @author Fabrice PENHOËT
**/
public function __construct($infos=null)
{
if((!empty($infos))&&(is_array($infos)))
{
//les limites doivent être connues avant le reste
if(!empty($infos["limites"]))
$this->limites=$infos["limites"];
unset($infos["limites"]);
$erreur_ok=false;
foreach ($infos as $attribut => $valeur)
{
$methode="set_$attribut";
if (method_exists(__CLASS__,$methode))
{
if(!$this->$methode($valeur))
$erreur_ok=true;
}
else
$this->$attribut=$valeur;
}
if(($erreur_ok)&&(empty($this->erreurs)))
$this->erreurs=(array) ERREUR_IMPREVUE;
}
}
/**
* Méthode vérifiant que le paramètre fourni est bien un flux existant
* et lui attribuant l'origine du lien si c'est le cas
*
* @param la valeur à contrôler
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
public function set_flux($flux)
{
if(!($flux instanceof FclFlux_flux))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
if(empty($flux->id_flux))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
if(($flux->recherche($flux->id_flux,"id_flux","id_flux")===false))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_ENREG_ABSENT." >> ".htmlentities($flux->id_flux,ENT_QUOTES)));
return false;
}
$this->flux=$flux;
return true;
}
/**
* Méthode cherchant un lien dans le bd via une valeur l'identifiant de manière unique
* champs acceptés : id_lien,url
*
* @return les données de la table dans un tableau si trouvé, false si pas trouvé ou en cas d'erreur
* @author Fabrice PENHOËT
**/
static function recherche($valeur,$champ_recherche="id_lien",$champ_sortie="*")
{
global $Bd;
if((isset_connexion(__FILE__,__LINE__)===false)) return false;
if(strpos("id_lien,url",$champ_recherche)===false)
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_CHAMP_RECHERCHE." >> ".htmlentities($champ_recherche,ENT_QUOTES)));
return false;
}
$prepare=$Bd->prepare("SELECT $champ_sortie FROM liens WHERE $champ_recherche=:valeur");
$recherche=$prepare->execute(array(":valeur"=>$valeur));
if((test_requete(__FILE__,__LINE__,$recherche,$prepare)===false)) return false;
$resultat=$prepare->fetch(PDO::FETCH_ASSOC);
$prepare=null;
if(empty($resultat))
return false;
else
return $resultat;
}
/**
* Méthode enregistrant un nouveau lien individuellement (à priori pas utilisée ?)
*
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
public function ajout()
{
global $Bd;
if((isset_connexion(__FILE__,__LINE__)===false)) return false;
if((empty($this->url))||(empty($this->designation))||(empty($this->flux)))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT));
return false;
}
$doublon=self::recherche($this->url,"url","id_lien");
if(!empty($doublon))
return false;
$date_actuelle=time();
$prepare=$Bd->prepare("INSERT INTO liens (ancre,url,flux_id,time_lien) VALUES (:ancre,:url,:flux_id,:date_actuelle)");
$ajout=$prepare->execute(array(':ancre'=>$this->designation,':url'=>$this->url,':flux_id'=>$this->flux->id_flux,':date_actuelle'=>$date_actuelle));
if((test_requete(__FILE__,__LINE__,$ajout,$prepare)===false)) return false;
$this->id_lien=$Bd->lastInsertId();
$prepare=$Bd->prepare("INSERT INTO liens_svg (id_lien,flux_id,time_lien) VALUES (:id,:flux_id,:date_actuelle)");
$ajout=$prepare->execute(array(':id'=>$this->id_lien,':flux_id'=>$this->flux->id_flux,':date_actuelle'=>$date_actuelle));
if((test_requete(__FILE__,__LINE__,$ajout,$prepare)===false)) return false;
$prepare=null;
return true;
}
/**
* Méthode modifiant les informations d'un lien (ne devrait pas servir mais bon...)
*
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
public function actualise()
{
global $Bd;
if((isset_connexion(__FILE__,__LINE__)===false)) return false;
if((empty($this->url))||(empty($this->designation))||(empty($this->id_lien)))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT." >> ".intval($this->id_lien)));
return false;
}
$lien_infos=self::recherche($this->id_lien,"id_lien","url");
if(empty($lien_infos))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_ENREG_ABSENT." >> ".intval($this->id_lien)));
return false;
}
if($this->url!=$lien_infos["url"])
{
$doublon=self::recherche($this->url,"url","id_lien");
if(!empty($doublon))
return false;
}
$prepare=$Bd->prepare("UPDATE liens SET ancre=:designation,url=:url WHERE id_lien=:id_lien;");
$maj=$prepare->execute(array(':designation'=>$this->designation,':url'=>$this->url,':id_lien'=>$this->id_lien));
if((test_requete(__FILE__,__LINE__,$maj,$prepare)===false)) return false;
$prepare=null;
//peut-être lancé ici maj cache derniers articles / flux ???
return true;
}
/**
* Méthode supprimant l'enregistrement d'un lien
*
* @param null
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
public function supprime()
{
global $Bd;
if((isset_connexion(__FILE__,__LINE__)===false)) return false;
if(empty($this->id_lien))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT));
return false;
}
$prepare=$Bd->prepare("DELETE FROM liens WHERE id_lien=:id_lien LIMIT 1;");
$suppr=$prepare->execute(array(':id_lien'=>$this->id_lien));
if((test_requete(__FILE__,__LINE__,$suppr,$prepare)===false)) return false;
$nb_enreg=$prepare->rowCount();
$prepare=null;
if($nb_enreg==0)
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_SUPPR." >> ".intval($this->id_lien)));
return false;
}
//peut-être lancé ici maj cache derniers articles / flux ???
return true;
}
/**
* Méthode actualisant un journal comptabilisant les clics / partages d'un lien
*
* @param utilisateur et abonnement concernés + action
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
public function ajout_journal_action($utilisateur,$abonnement,$action="clic",$contexte="email")
{
$actions_ok=explode("|",LIEN_ACTIONS);
if (!in_array($action,$actions_ok))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES." >> ".htmlentities($action,ENT_QUOTES)));
return false;
}
if(empty($this->id_lien))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
if(!($utilisateur instanceof FclFlux_utilisateur))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
if(empty($utilisateur->id_utilisateur))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
if(!($abonnement instanceof FclFlux_abonnement))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
if(empty($abonnement->id_abonnement))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
if(empty($contexte))
$contexte="email";
//je ne teste pas ici si l'utilisateur existe réellement dans la bd car je cherche à éviter les requêtes sql
$repertoire_fichier=CACHE_REP."/".CACHE_REP_LIENS."/actions/";
$nom_fichier=strval(date('Y-m-d-H-i'));
$now=time();
$code="\$a[$now]['act']='".$action."';\$a[$now]['u_id']='".$utilisateur->id_utilisateur."';\$a[$now]['a_id']='".$abonnement->id_abonnement."';\$a[$now]['l_id']='".$this->id_lien."';\$a[$now]['c']='".$contexte."';";
if(file_exists($repertoire_fichier.$nom_fichier))
{
if(!file_put_contents($repertoire_fichier.$nom_fichier,$code,FILE_APPEND | LOCK_EX))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_ECRITURE));
return false;
}
else
return true;
}
else
{
if(!file_exists($repertoire_fichier))
{
if(!mkdir($repertoire_fichier,CACHE_REP_CHMOD,true))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_REP_CREA));
return false;
}
}
if(!file_put_contents($repertoire_fichier.$nom_fichier,"<?php\n$code",LOCK_EX))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_ECRITURE));
return false;
}
else
return true;
}
}
/**
* Méthode enregistrant le contenu du journal des actions des utilisateurs
*
* @param null
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
static function sauve_journal_action()
{
global $Bd;
if((isset_connexion(__FILE__,__LINE__)===false)) return false;
$time_limite=time()-60;//un fichier est créé / minute, donc si fichier a + de 60 secondes, on peut l'importer
$repertoire_fichier=CACHE_REP."/".CACHE_REP_LIENS."/actions/";
$rep=opendir($repertoire_fichier);
$actions=array();
while($fichier=readdir($rep))
{
if(!(is_dir($repertoire_fichier.$fichier))&&($fichier!=".")&&($fichier!=".."))
{
$dates_fichier=explode("-",$fichier);
if(!checkdate($dates_fichier[1],$dates_fichier[2],$dates_fichier[0]))
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_DATE_VALIDE));
else
{
$time_fichier=filemtime($repertoire_fichier.$fichier);
if($time_fichier<$time_limite)
{
include($repertoire_fichier.$fichier);
if(is_array($a))
$actions=$actions+$a;
unlink($repertoire_fichier.$fichier);//dans tous les cas, le fichier est supprimé
unset($a);
}
}
}
}
closedir($rep);
$nb_import=0;
if(count($actions)!=0)
{
$prepare=$Bd->prepare("INSERT INTO liens_actions (lien_id,utilisateur_id,time_action,action,contexte,abonnement_id) VALUES (:lien_id,:utilisateur_id,:time,:action,:contexte,:abonnement_id)");
foreach ($actions as $time_action=>$infos)
{
$test_utilisateur=FclFlux_utilisateur::recherche($infos["u_id"],"id_utilisateur","id_utilisateur");
if(!empty($test_utilisateur))
{
$proprietaire=new FclFlux_utilisateur();
$proprietaire->id_utilisateur=$infos["u_id"];
$test_abonnement=FclFlux_abonnement::recherche($infos["a_id"],$proprietaire,"id_abonnement");
$test_lien=self::recherche($infos["l_id"],"id_lien","id_lien");
if((!empty($test_lien))&&(!empty($test_abonnement)))
{
$ajout=$prepare->execute(array(':lien_id'=>$infos["l_id"],':utilisateur_id'=>$infos["u_id"],':time'=>$time_action,':action'=>$infos["act"],':contexte'=>$infos["c"],':abonnement_id'=>$infos["a_id"]));
if((test_requete(__FILE__,__LINE__,$ajout,$prepare)===false)) return false;
$nb_import++;
}
}
}
$prepare=null;
}
return $nb_import;
}
/**
* Méthode listant les liens ayant reçus le + d'actions / utilisateur sur une période
*
* @param $action=action recherchée, les dates de début et de fin de la période concernée, $nb_max le nombre de résultats
* @return liste des des liens dans un tableau si trouvé (peut être vide), false en cas d'erreur
* @author Fabrice PENHOËT
**/
static function get_top_liens_action($action="clic",$date_debut,$date_fin,$nb_max=30)
{
global $Bd;
if((isset_connexion(__FILE__,__LINE__)===false)) return false;
if(empty($date_fin))
$date_fin=date("d/m/Y");
$actions_ok=explode("|",LIEN_ACTIONS);
if (!in_array($action,$actions_ok))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES." >> $action"));
return false;
}
if(!is_int($nb_max))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
if(preg_match(DATE_FORMAT_EREG,$date_debut)==0)
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_DATE_FORMAT));
return false;
}
if(preg_match(DATE_FORMAT_EREG,$date_fin)==0)
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,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]))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_DATE_VALIDE));
return false;
}
if(!checkdate($dates_fin[1],$dates_fin[0],$dates_fin[2]))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_DATE_VALIDE));
return false;
}
if(IntervalDates($date_debut,$date_fin)<=0)
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_DATE_INTERVAL));
return false;
}
$time_debut=mktime(0,0,0,$dates_debut[1],$dates_debut[0],$dates_debut[2]);
$time_fin=mktime(0,0,0,$dates_fin[1],$dates_fin[0],$dates_fin[2]);
$prepare=$Bd->prepare("SELECT DISTINCT ancre,url,flux_id,count(id_action) AS Cpt FROM liens AS L,liens_actions AS A WHERE ((L.id_lien=A.lien_id) AND (time_action >=:time_debut) AND (time_action <:time_fin) AND (action=:action)) GROUP BY lien_id ORDER BY count(id_action) DESC LIMIT 0,$nb_max;");
$recherche=$prepare->execute(array(":time_debut"=>$time_debut,":time_fin"=>$time_fin,":action"=>$action));
if((test_requete(__FILE__,__LINE__,$recherche,$prepare)===false)) return false;
$resultat=$prepare->fetchAll(PDO::FETCH_ASSOC);
$prepare=null;
return $resultat;
}
/**
* Méthode de création du cache des articles les + cliqués/partagés sur une période donnée
*
* @param $action=action recherchée, $periode la périodicité, la date de fin de la période, $nb_max le nombre de résultats
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
static function crea_cache_top_liens_action($periode="jour",$action="clic",$date_fin="",$nb_max=30)
{
$actions_ok=explode("|",LIEN_ACTIONS);
if (!in_array($action,$actions_ok))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES." >> $action"));
return false;
}
if(!is_int($nb_max))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
if(empty($date_fin))
$date_fin=date("d/m/Y");
if(preg_match(DATE_FORMAT_EREG,$date_fin)==0)
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_DATE_FORMAT));
return false;
}
$dates_fin=explode("/",$date_fin);
if(!checkdate($dates_fin[1],$dates_fin[0],$dates_fin[2]))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_DATE_VALIDE));
return false;
}
$time_fin=mktime(0,0,0,$dates_fin[1],$dates_fin[0],$dates_fin[2]);
if($periode=="jour")
{//à lancer après minuit pour stats de la veille
$time_debut=$time_fin-3600*24;
$date_debut=date("d/m/Y",$time_debut);
$dates_debut=explode("/",$date_debut);
$adresse_fichier=CACHE_REP_LIENS."/stats-".$action."/".$periode."/".$dates_debut[2]."-".$dates_debut[1]."-".$dates_debut[0];
}
else if($periode=="hebdo")
{//à lancer la lundi pour stats de la semaine précédente
$time_debut=$time_fin-3600*24*7;
$date_debut=date("d/m/Y",$time_debut);
$dates_debut=explode("/",$date_debut);
$num_semaine=date("W",$time_debut);
$adresse_fichier=CACHE_REP_LIENS."/stats-".$action."/".$periode."/".$dates_debut[2]."-".$num_semaine;
}
else if($periode=="mois")
{//à lancer le 1er du mois pour les stats du mois précédent
if($dates_fin[1]=="01")
{
$annee_debut=$dates_fin[2]-1;
$mois_debut="12";
}
else
{
$annee_debut=$dates_fin[2];
$mois_debut=$dates_fin[1]-1;
if(strlen($mois_debut)==1)
$mois_debut="0".$mois_debut;
}
$date_debut="01/$mois_debut/$annee_debut";
$adresse_fichier=CACHE_REP_LIENS."/stats-".$action."/".$periode."/".$annee_debut."-".$mois_debut;
}
else
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES));
return false;
}
$stats=self::get_top_liens_action($action,$date_debut,$date_fin,$nb_max);
return crea_cache($adresse_fichier,$stats);
}
/**
* Méthode supprimant les anciens liens de la base de données
* je garde dans la table d'archive ceux pour lesquels j'ai enregistré au moins une action (clic/partage/marque-pages)
*
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
static function supprime_anciens_liens()
{
global $Bd;
if((isset_connexion(__FILE__,__LINE__)===false)) return false;
$time_limite=time()-LIEN_IMPORT_MAX_JOURS*24*3600;
// tous les anciens liens de la table origine
$suppr=$Bd->query("DELETE FROM liens WHERE time_lien<$time_limite;");
if((test_requete(__FILE__,__LINE__,$suppr)===false)) return false;
// tous les anciens liens sans action de la table sauvegarde
$prepare_suppr=$Bd->query("DELETE FROM liens_svg WHERE ((time_lien<$time_limite) AND (id_lien NOT IN(SELECT DISTINCT lien_id FROM liens_actions)) AND (id_lien NOT IN(SELECT DISTINCT lien_id FROM utilisateurs_marque_pages where lien_id!=0)));");
if((test_requete(__FILE__,__LINE__,$prepare_suppr)===false)) return false;
$prepare_suppr=null;
return true;
}
}//fin de la classe