hellofacteurV1/modele/flux.php

402 lines
16 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* classe permettant de gérer des flux de syndication
* on ne traite pas ici le stockage des données, le cache, etc.
* pour la lecture des flux, inspiré des scripts trouvés sur :
* http://www.scriptol.fr/rss/lecteur-commun.php (Licence Mozilla 1.1.)
*
* @author Fabrice PENHOËT
**/
require_once("lien.php");
class Flux extends Lien
{
protected $source_url; // url de la page HTML déclarée en entête du flux
protected $type; // flux RSS ou Atom ?
protected $date_maj_flux; // date de dernière mise à jour du flux telle que déclarée en entête
/**
* Méthode testant la validité du type fournit pour le flux
*
* @return booléen suivant succès
* @author Fabrice PENHOËT
**/
public function set_type($type)
{
$type_ok=array("RSS","Atom");
if (!in_array($type,$type_ok))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES." >> $type"));
return false;
}
$this->type=$type;
return true;
}
/**
* Méthode retournant les flux de syndication déclarés en entête d'une page html
*
* @param objet de type Lien dont l'url doit être connue
* @return tableau listant les flux si trouvés, false sinon
* @author Fabrice PENHOËT
**/
static function detecte_flux_entete($lien)
{
if(!isset($lien->url))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT));
return false;
}
$entetes=$lien->get_entete_html();
if(empty($entetes))
return false;
$flux=array();
$i=0;
while(isset($entetes["link$i"]))
{
if(isset($entetes["link$i"]["type"]))
{
if(($entetes["link$i"]["type"]=="application/rss+xml")||($entetes["link$i"]["type"]=="application/atom+xml"))
$flux[$i]=$entetes["link$i"];
}
$i++;
}
if(count($flux)==0)
return false;
else
return $flux;
}
/**
* Recherche les infos d'un flux en se basant sur ses "tags"
* Attribue les valeurs trouvées
*
* @return booléen suivant succès
* @author Fabrice PENHOËT + scriptol.fr
**/
public function get_infos_entete()
{
if(!isset($this->url))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT));
return false;
}
$xml=$this->get_contenu(10.0);
if(empty($xml))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FLUX_INFOS));
return false;
}
$doc=new DOMDocument();
$doc->loadXML($xml);
$channels=$doc->getElementsByTagName("channel");
if($channels->length!=0)
$this->set_type("RSS");
else
{
$entries=$doc->getElementsByTagName("entry");
if($entries->length!=0)
$this->set_type("Atom");
}
if(empty($this->type))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FLUX_INFOS));
return false;
}
if($this->type=="RSS")
{
if(!empty($doc->getElementsByTagName("title")->item(0)->firstChild->textContent))
$this->designation=affiche_utf8(strip_tags($doc->getElementsByTagName("title")->item(0)->firstChild->textContent),UTF8_OK);
if(!empty($doc->getElementsByTagName("description")->item(0)->firstChild->textContent))
$this->description=html_entity_decode(str_replace("’","'",trim(strip_tags($doc->getElementsByTagName("description")->item(0)->firstChild->textContent))));//!! attention si pas de description pour le flux, récupère la première description d'un item
if(!empty($doc->getElementsByTagName("link")->item(0)->firstChild->textContent))
$this->source_url=$doc->getElementsByTagName("link")->item(0)->firstChild->textContent;
$tnl=$doc->getElementsByTagName("pubDate");
if($tnl->length==0)
$tnl=$doc->getElementsByTagName("lastBuildDate");
if($tnl->length!=0)
$this->date_maj_flux=$tnl->item(0)->firstChild->textContent;
}
else
{
if(!empty($doc->getElementsByTagName("title")->item(0)->firstChild->textContent))
$this->designation=affiche_utf8(strip_tags($doc->getElementsByTagName("title")->item(0)->firstChild->textContent),UTF8_OK);
if(!empty($doc->getElementsByTagName("summary")->item(0)->firstChild->textContent))
$this->description=affiche_utf8(strip_tags($doc->getElementsByTagName("summary")->item(0)->firstChild->textContent),UTF8_OK);
$links=$doc->getElementsByTagName("link");
if ($links->length!=0)
{
foreach($links as $link)
{
if(($link->getAttribute("rel")=="alternate")&&($link->getAttribute("type")=="text/html")&&(!empty($link->getAttribute("href"))))
{
$this->source_url=$link->getAttribute("href");
break;
}
}
}
if(!empty($doc->getElementsByTagName("updated")->item(0)->firstChild->textContent))
$this->date_maj_flux=$doc->getElementsByTagName("updated")->item(0)->firstChild->textContent;
}
return true;
}
/**
* Lit les items d'un flux RSS ou Atom
*
* @param $nb_max nombre maximum d'items que l'on souhaite récupérer, $log_erreur pour savoir si on enregistre les erreurs de lecture dans le journal
* @return tableau listant les infos du flux, false si erreur
* @author Fabrice PENHOËT
**/
public function lecture($nb_max=1000,$log_erreur=true)
{
if(!isset($this->url))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT));
return false;
}
if(!is_int($nb_max))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
$xml=$this->get_contenu(5.0);
if(empty($xml))
{
if($log_erreur)
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FLUX_INFOS." >> ".htmlentities($this->url,ENT_QUOTES)));
return false;
}
$carabug=array(" ","","&#38;","&");
$cara_remplace=array("","","&amp;","&amp;");
$xml=str_replace($carabug,$cara_remplace,$xml);
$doc=new DOMDocument();
$setXML=@$doc->loadXML($xml);
if($setXML===false)
return $this->lecture_reg($nb_max,$xml,$log_erreur);//fichier XML mal formé...
// quel format ?
$rss_ok=$doc->getElementsByTagName("channel");
$atom_ok=$doc->getElementsByTagName("feed");
if($rss_ok->length!=0)
$this->set_type("RSS");
elseif($atom_ok->length!=0)
$this->set_type("Atom");
else
{
if($log_erreur)
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FLUX_INFOS." >> ".htmlentities($this->url,ENT_QUOTES)));
return false;
}
if(empty($this->type))
{
if($log_erreur)
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FLUX_INFOS." >> ".htmlentities($this->url,ENT_QUOTES)));
return false;
}
$maj=array();
$i=0;
if($this->type=="RSS")
{
$items=$doc->getElementsByTagName("item");
if($items->length!=0)
{
foreach($items as $item)
{
if($i<$nb_max)
{
if(!empty($item->getElementsByTagName("title")->item(0)->firstChild->textContent))
$maj[$i]["designation"]=html_entity_decode(str_replace("’","'",trim(strip_tags($item->getElementsByTagName("title")->item(0)->firstChild->textContent))));
if(!empty($item->getElementsByTagName("description")->item(0)->firstChild->textContent))
$maj[$i]["description"]=html_entity_decode(str_replace("’","'",trim(strip_tags($item->getElementsByTagName("description")->item(0)->firstChild->textContent))));
if(!empty($item->getElementsByTagName("link")->item(0)->firstChild->textContent))
$maj[$i]["url"]=str_replace("&amp;","&",trim(strip_tags($item->getElementsByTagName("link")->item(0)->firstChild->textContent)));
$tnl=$item->getElementsByTagName("pubDate");
if($tnl->length==0)
$tnl=$item->getElementsByTagName("lastBuildDate");
if(($tnl->length!=0)&&(!empty($tnl->item(0)->firstChild->textContent)))
{
$maj[$i]["date_article"]=trim($tnl->item(0)->firstChild->textContent);
$date_maj=date_create($maj[$i]["date_article"]);
if(!empty($date_maj))
$maj[$i]["timeS"]=$date_maj->getTimestamp();
$date_maj=null;
}
}
// besoin au minimum d'un titre et d'une url
if((!empty($maj[$i]["designation"]))&&(!empty($maj[$i]["url"])))
$i++;
}
}
}
else
{
$entries=$doc->getElementsByTagName("entry");
if($entries->length!=0)
{
foreach($entries as $item)
{
if($i<$nb_max)
{
if(!empty($item->getElementsByTagName("title")->item(0)->firstChild->textContent))
$maj[$i]["designation"]=html_entity_decode(str_replace("’","'",trim(strip_tags($item->getElementsByTagName("title")->item(0)->firstChild->textContent))));
if(!empty($item->getElementsByTagName("summary")->item(0)->firstChild->textContent))
$maj[$i]["description"]=html_entity_decode(str_replace("’","'",trim(strip_tags($item->getElementsByTagName("summary")->item(0)->firstChild->textContent))));
else if(!empty($item->getElementsByTagName("content")->item(0)->firstChild->textContent))
$maj[$i]["description"]=html_entity_decode(trim($item->getElementsByTagName("content")->item(0)->firstChild->textContent));
if(!empty($item->getElementsByTagName("link")->item(0)->getAttribute("href")))
$maj[$i]["url"]=str_replace("&amp;","&",trim(strip_tags($item->getElementsByTagName("link")->item(0)->getAttribute("href"))));
// attention, il peut y avoir +sieurs balises link
$j=0;
while(null!=$item->getElementsByTagName("link")->item($j))
{
if((!empty($item->getElementsByTagName("link")->item($j)->getAttribute("href")))&&($item->getElementsByTagName("link")->item($j)->getAttribute("rel")=="alternate")&&($item->getElementsByTagName("link")->item($j)->getAttribute("type")=="text/html"))
{
$maj[$i]["url"]=str_replace("&amp;","&",trim(strip_tags($item->getElementsByTagName("link")->item($j)->getAttribute("href"))));
break(1);
}
$j++;
}
if((empty($maj[$i]["url"]))&&($j==1)&&(!empty($item->getElementsByTagName("link")->item(0)->getAttribute("href"))))// les propriétés du lien n'ont pas toutes été fournies.
$maj[$i]["url"]=str_replace("&amp;","&",trim(strip_tags($item->getElementsByTagName("link")->item(0)->getAttribute("href"))));
if(!empty($item->getElementsByTagName("updated")->item(0)->firstChild->textContent))
{
$maj[$i]["date_article"]=trim($item->getElementsByTagName("updated")->item(0)->firstChild->textContent);
$date_maj=date_create($maj[$i]["date_article"]);
if(!empty($date_maj))
$maj[$i]["timeS"]=$date_maj->getTimestamp();
$date_maj=null;
}
}
// besoin au minimum d'un titre et d'une url
if((!empty($maj[$i]["designation"]))&&(!empty($maj[$i]["url"])))
$i++;
}
}
}
if(count($maj)!=0)
return $maj;
else
return null;
}
/**
* Lit les items d'un flux RSS ou Atom non conforme et ne pouvant donc être chargé avec DOMDocument.
* //à revoir, bug encodage (?) avec des <20> qui apparaissent après les Reg
*
* @param $nb_max nombre maximum d'items que l'on souhaite récupérer, $xml le contenu du fichier à traiter, $log_erreur pour savoir si on enregistre les erreurs de lecture dans le journal
* @return tableau listant les infos du flux, false si erreur
* @author Fabrice PENHOËT
**/
public function lecture_reg($nb_max=1000,$xml,$log_erreur)
{
if(!is_int($nb_max))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT));
return false;
}
if(empty($xml))
{
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT));
return false;
}
else
$xml=str_replace("&amp;","&",$xml);//plus de bug ici
//est-ce que ça ressemble à un flux ?
if(strpos($xml,"</channel>")!==false)
$this->set_type("RSS");
elseif(strpos($xml,"</feed>")!==false)
$this->set_type("Atom");
else
{
if($log_erreur)
$ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FLUX_INFOS." >> ".htmlentities($this->url,ENT_QUOTES)));
return false;
}
$maj=array();
$i=0;
if($this->type=="RSS")
{
// liste des items trouvés dans le flux
$items=preg_split("#<\/?item>#i",$xml);
// date du flux utile si pas de date spécifiée pour chaque article.
$get_date_flux=preg_split("#<\/?lastBuildDate>#i",$xml);
if(!empty($get_date_flux[1]))
$date_flux=$get_date_flux[1];
for($j=1;$j<sizeof($items)-1;$j+=2)
{
// il peut y avoir +sieurs balises <title> et le type="html" n'est pas toujours déclaré... Je considère ici que le premier trouvé est le bon.
preg_match("#<title(?: (?:\w+)=\"(?:\w+)\")*>(.*)</title>?#i",$items[$j],$item_title);
if(!empty($item_title[1]))
$maj[$i]["designation"]=html_entity_decode(str_replace("’","'",trim(strip_tags(str_replace("]]>","",str_replace("<![CDATA[","",$item_title[1]))))));
preg_match("#<description(?: (?:\w+)=\"(?:\w+)\")*>(.*)</description>?#i",$items[$j],$item_description);
if(!empty($item_description[1]))
$maj[$i]["description"]=html_entity_decode(str_replace("’","'",trim(strip_tags(str_replace("]]>","",str_replace("<![CDATA[","",$item_description[1]))))));
preg_match("#<link(?: (?:\w+)=\"(?:\w+)\")*>(.*)</link>?#i",$items[$j],$item_link);
if((!empty($item_link[1]))&&(filter_var($item_link[1],FILTER_VALIDATE_URL)))
$maj[$i]["url"]=trim(strip_tags($item_link[1]));
$item_date=preg_split("#<\/?pubDate>#i",$items[$j]);
if(!empty($item_date[1]))
$maj[$i]["date_article"]=$item_date[1];
elseif(!empty($date_flux))
$maj[$i]["date_article"]=$date_flux;
if(!empty($maj[$i]["date_article"]))
{
$date_maj=date_create($maj[$i]["date_article"]);
if(!empty($date_maj))
$maj[$i]["timeS"]=$date_maj->getTimestamp();
$date_maj=null;
}
//au moins un titre et une url
if((!empty($maj[$i]["designation"]))&&(!empty($maj[$i]["url"])))
$i++;
else
$maj[$i]=null;
}
}
else
{
// liste des items trouvés dans le flux
$items=preg_split("#<\/?entry>#i",$xml);
// date du flux utile si pas de date spécifiée pour chaque article.
$get_date_flux=preg_split("#<\/?updated>#i",$xml);
if(!empty($get_date_flux[1]))
$date_flux=$get_date_flux[1];
for($j=1;$j<sizeof($items)-1;$j+=2)
{
// il peut y avoir +sieurs balises <title> et le type="html" n'est pas toujours déclaré... Je considère ici que le premier trouvé est le bon.
preg_match("#<title(?: (?:\w+)=\"(?:\w+)\")*>(.*)</title>?#i",$items[$j],$item_title);
if(!empty($item_title[1]))
$maj[$i]["designation"]=html_entity_decode(str_replace("’","'",trim(strip_tags(str_replace("]]>","",str_replace("<![CDATA[","",$item_title[1]))))));
preg_match("#<summary(?: (?:\w+)=\"(?:\w+)\")*>(.*)</summary>?#i",$items[$j],$item_description);
if(!empty($item_description[1]))
$maj[$i]["description"]=html_entity_decode(str_replace("’","'",trim(strip_tags(str_replace("]]>","",str_replace("<![CDATA[","",$item_description[1]))))));
else
{
preg_match("#<content(?: (?:\w+)=\"(?:\w+)\")*>(.*)</content>?#i",$items[$j],$item_description);
if(!empty($item_description[1]))
$maj[$i]["description"]=html_entity_decode(str_replace("’","'",trim(strip_tags(str_replace("]]>","",str_replace("<![CDATA[","",$item_description[1]))))));
}
//attention + sieurs href dans certains flux mais le 1er doit être le bon... -> pas certain ! à revoir !
preg_match("#href=\"(.+?)\"#",$items[$j],$item_link);
if((!empty($item_link[1]))&&(filter_var($item_link[1],FILTER_VALIDATE_URL)))
$maj[$i]["url"]=str_replace("&amp;","&",trim(strip_tags($item_link[1])));
$item_date=preg_split("#<\/?updated>#i",$items[$j]);
if(!empty($item_date[1]))
$maj[$i]["date_article"]=$item_date[1];
elseif(!empty($date_flux))
$maj[$i]["date_article"]=$date_flux;
if(!empty($maj[$i]["date_article"]))
{
$date_maj=date_create($maj[$i]["date_article"]);
if(!empty($date_maj))
$maj[$i]["timeS"]=$date_maj->getTimestamp();
$date_maj=null;
}
//au moins un titre et une url
if((!empty($maj[$i]["designation"]))&&(!empty($maj[$i]["url"])))
$i++;
else
$maj[$i]=null;
}
}
if(count($maj)!=0)
return $maj;
else
return null;
}
}