/branches/v1.4-broyeur/widget/modules/carto/config.defaut.ini |
---|
New file |
0,0 → 1,5 |
[carto] |
; Chemin vers le dossier contenant les fichiers kmz des limites communales |
communesKmzChemin = "/home/telabotap/www/commun/google/map/3/kmz/communes/,/home/telabotap/www/commun/google/map/3/kmz/communes_incompletes/" |
; Template de l'url où charger les fichiers kml des limites communales. |
limitesCommunaleUrlTpl = "http://www.tela-botanica.org/eflore/cel2/widget/modules/carto/squelettes/kml/%s" |
/branches/v1.4-broyeur/widget/modules/carto/Carto.php |
---|
New file |
0,0 → 1,308 |
<?php |
// declare(encoding='UTF-8'); |
/** |
* Service fournissant une carte dynamique des obsertions publiques du CEL. |
* Encodage en entrée : utf8 |
* Encodage en sortie : utf8 |
* |
* Cas d'utilisation et documentation : |
* @link http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=AideCELWidgetCarto |
* |
* Paramètres : |
* ===> utilisateur = identifiant |
* Affiche seulement les observations d'un utilisateur donné. L'identifiant correspond au courriel de |
* l'utilisateur avec lequel il s'est inscrit sur Tela Botanica. |
* ===> dept = code_du_département |
* Affiche seulement les observations pour le département français métropolitain indiqué. Les codes de département utilisables |
* sont : 01 à 19, 2A, 2B et 21 à 95. |
* ===> projet = mot-clé |
* Affiche seulement les observations pour le projet d'observations indiqué. Dans l'interface du CEL, vous pouvez taguer vos |
* observations avec un mot-clé de projet. Si vous voulez regrouper des observations de plusieurs utilisateurs, communiquez un |
* mot-clé de projet à vos amis et visualisez les informations ainsi regroupées. |
* ===> num_taxon = num_taxon |
* Affiche seulement les observations pour la plante indiquée. Le num_taxon correspond au numéro taxonomique de la plante. |
* Ce numéro est disponible dans les fiches d'eFlore. Par exemple, pour "Poa bulbosa L." le numéro taxonomique vaut 7080. |
* |
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org> |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt> |
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt> |
* @version $Id$ |
* @copyright Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org) |
*/ |
class Carto extends WidgetCommun { |
const DS = DIRECTORY_SEPARATOR; |
const SERVICE_DEFAUT = 'carte-defaut'; |
/** |
* Méthode appelée par défaut pour charger ce widget. |
*/ |
public function executer() { |
$retour = null; |
extract($this->parametres); |
if (!isset($carte)) { |
$carte = self::SERVICE_DEFAUT; |
} |
$methode = $this->traiterNomMethodeExecuter($carte); |
if (method_exists($this, $methode)) { |
$retour = $this->$methode(); |
} else { |
$this->messages[] = "Ce type de service '$methode' n'est pas disponible."; |
} |
if (is_null($retour)) { |
$info = 'Un problème est survenu : '.print_r($this->messages, true); |
$this->envoyer($info); |
} else { |
$squelette = dirname(__FILE__).self::DS.'squelettes'.self::DS.$retour['squelette'].'.tpl.html'; |
$html = $this->traiterSquelettePhp($squelette, $retour['donnees']); |
$this->envoyer($html); |
} |
} |
/** |
* Carte par défaut |
*/ |
public function executerCarteDefaut() { |
$widget = null; |
extract($this->parametres); |
$utilisateur = (isset($utilisateur) ? $utilisateur : '*'); |
$projet = (isset($projet) ? $projet : '*'); |
$dept = (isset($dept) ? $dept : '*'); |
$num_taxon = (isset($num_taxon) ? $num_taxon : '*'); |
// Création url données json |
$url_cel_carto = sprintf($this->config['chemins']['baseURLServicesCelTpl'], 'CelWidgetMap'); |
$url_json = "$url_cel_carto/carte-defaut-json/$utilisateur/$projet/$dept/$num_taxon"; |
$url_base = sprintf($this->config['chemins']['baseURLAbsoluDyn'], ''); |
// Création des infos du widget |
$widget['donnees']['url_cel_carto'] = $url_cel_carto; |
$widget['donnees']['url_json'] = $url_json; |
$widget['donnees']['url_base'] = $url_base; |
$widget['donnees']['jquery_version'] = '1.4.4'; |
$widget['donnees']['utilisateur'] = $utilisateur; |
$widget['donnees']['projet'] = $projet; |
$widget['donnees']['dept'] = $dept; |
$widget['donnees']['num_taxon'] = $num_taxon; |
$widget['donnees']['taxons'] = $this->chargerTaxons(); |
if ($num_taxon != '*') { |
$taxon_courrant = current($widget['donnees']['taxons']); |
$widget['donnees']['taxon_nom'] = $taxon_courrant['nom']; |
} |
$widget['squelette'] = 'carte_defaut'; |
if (isset($dept)) { |
// si on veut afficher les limites départemmentales on va compter et chercher les noms de fichiers |
$fichiersKml = $this->chercherFichierKml($dept); |
foreach ($fichiersKml as $kml => $dossier){ |
$url_limites_communales = sprintf($this->config['carto']['limitesCommunaleUrlTpl'], $dossier, $kml); |
$widget['donnees']['url_limites_communales'][] = $url_limites_communales; |
} |
} |
return $widget; |
} |
private function chargerTaxons() { |
extract($this->parametres); |
$utilisateur = (isset($utilisateur) ? $utilisateur : '*'); |
$projet = (isset($projet) ? $projet : '*'); |
$dept = (isset($dept) ? $dept : '*'); |
$num_taxon = (isset($num_taxon) ? $num_taxon : '*'); |
// Récupération des données au format Json |
$service = "CelWidgetMap/taxons/$utilisateur/$projet/$dept/$num_taxon"; |
$url = sprintf($this->config['chemins']['baseURLServicesCelTpl'], $service); |
$json = $this->getDao()->envoyerRequeteConsultation($url); |
$donnees = json_decode($json); |
// Post-traitement des données |
$taxons = $this->traiterTaxons($donnees); |
return $taxons; |
} |
private function traiterTaxons($donnees) { |
$taxons = array(); |
if (is_array($donnees) && count($donnees) > 0) { |
foreach ($donnees as $donnee) { |
if (!isset($taxons[$donnee->num_taxon]) && ! $this->etreVide($donnee->nom_ret)) { |
$taxon = array(); |
$taxon['nn'] = $donnee->num_nom_ret; |
$taxon['nt'] = $donnee->num_taxon; |
$taxon['nom'] = $this->nettoyerTexte($donnee->nom_ret); |
$taxon['famille'] = $this->nettoyerTexte($donnee->famille); |
$taxons[$donnee->num_taxon] = $taxon; |
} |
} |
} |
return $taxons; |
} |
private function chercherFichierKml($dept){ |
$chemins = explode(',', $this->config['carto']['communesKmzChemin']); |
$departements = explode(',', $dept);// plrs code de départements peuvent être demandés séparés par des virgules |
$departements_trouves = array(); |
$fichiers = array(); |
foreach ($chemins as $dossier_chemin) { |
if ($dossier_ressource = opendir($dossier_chemin)) { |
while ($element = readdir($dossier_ressource)) { |
if ($element != '.' && $element != '..') { |
foreach ($departements as $departement) { |
$nom_dossier = basename($dossier_chemin); |
if (!isset($departements_trouves[$departement]) || $departements_trouves[$departement] == $nom_dossier) { |
$dept_protege = preg_quote($departement); |
if (!is_dir($dossier_chemin.'/'.$element) && preg_match("/^$dept_protege(?:_[0-9]+|)\.km[lz]$/", $element)) { |
$fichiers[$element] = $nom_dossier; |
$departements_trouves[$departement] = $nom_dossier; |
} |
} |
} |
} |
} |
closedir($dossier_ressource); |
} |
} |
return $fichiers; |
} |
/** |
* Tableau des observations d'une station |
*/ |
public function executerObservations() { |
$widget = null; |
extract($this->parametres); |
$observations = $this->chargerObservation($station); |
// Création des infos du widget |
if (isset($observations['commune'])) { |
$commune = $observations['commune']; |
unset($observations['commune']); |
$widget['donnees']['commune'] = $commune; |
} |
$obs_ids = null; |
if (isset($observations['ids'])) { |
$obs_ids = $observations['ids']; |
unset($observations['ids']); |
} |
$widget['squelette'] = $this->choisirFormatSortie(count($observations)); |
if ($widget['squelette'] == 'obs_liste' && $obs_ids != null && count($obs_ids) > 0) { |
$widget['donnees']['images'] = $this->chargerImages($obs_ids); |
} |
$widget['donnees']['observations'] = $observations; |
$widget['donnees']['station_id'] = $station; |
return $widget; |
} |
private function chargerObservation($station) { |
extract($this->parametres); |
$utilisateur = (isset($utilisateur) ? $utilisateur : '*'); |
$projet = (isset($projet) ? $projet : '*'); |
$dept = (isset($dept) ? $dept : '*'); |
$num_taxon = (isset($num_taxon) ? $num_taxon : '*'); |
// Récupération des données au format Json |
$service = "CelWidgetMap/observations/$station/$utilisateur/$projet/$dept/$num_taxon"; |
$url = sprintf($this->config['chemins']['baseURLServicesCelTpl'], $service); |
$json = $this->getDao()->envoyerRequeteConsultation($url); |
$donnees = json_decode($json); |
// Post-traitement des données |
$observations = $this->traiterObservations($donnees); |
return $observations; |
} |
private function traiterObservations($donnees) { |
$observations = array(); |
if (is_array($donnees) && count($donnees) > 0) { |
foreach ($donnees as $donnee) { |
$observation = array(); |
$observation['id'] = $donnee->id; |
$observation['nn'] = $this->etreVide($donnee->num_nom_sel) ? null : $donnee->num_nom_sel; |
$observation['nom'] = $this->nettoyerTexte($donnee->nom_sel); |
$observation['date'] = $this->formaterDate($donnee->date_observation, '%d/%m/%Y'); |
$observation['lieu'] = $this->traiterLieu($donnee); |
$observation['observateur'] = $this->tronquerCourriel($donnee->identifiant); |
$observations[] = $observation; |
$observations['commune'] = $this->nettoyerTexte($donnee->location); |
$observations['ids'][] = $donnee->id; |
} |
} |
return $observations; |
} |
private function traiterLieu($donnee) { |
$lieu = array(); |
if (isset($donnee->lieudit) && ! empty($donnee->lieudit)) { |
$lieu[] = $donnee->lieudit; |
} |
if (isset($donnee->milieu) && ! empty($donnee->milieu)) { |
$lieu[] = $donnee->milieu; |
} |
return implode(', ', $lieu); |
} |
private function choisirFormatSortie($observations_nbre) { |
extract($this->parametres); |
$sortie = 'obs_tableau'; |
if (isset($format) && $format != '*') { |
$sortie = ($format == 'tableau' ) ? 'obs_tableau' : 'obs_liste'; |
} else { |
$sortie = ($observations_nbre > 4) ? 'obs_tableau' : 'obs_liste'; |
} |
return $sortie; |
} |
private function chargerImages($obs_ids) { |
// Récupération des données au format Json |
$service = 'CelImage/liste-ids?obsId='.implode(',', $obs_ids); |
$url = sprintf($this->config['chemins']['baseURLServicesCelTpl'], $service); |
$json = $this->getDao()->envoyerRequeteConsultation($url); |
$donnees = json_decode($json); |
// Post-traitement des données |
$images = $this->traiterImages($donnees); |
return $images; |
} |
private function traiterImages($donnees) { |
$images = array(); |
//echo '<br/><pre>'.print_r($donnees,true).'</pre>'; |
if (count($donnees) > 0) { |
foreach ($donnees as $id_obs => $id_images) { |
foreach ($id_images as $id_img) { |
$urls['id'] = $id_img; |
$urls['miniature'] = $this->getUrlImage($id_img, 'CXS'); |
$urls['normale'] = $this->getUrlImage($id_img, 'XL'); |
$images[$id_obs][] = $urls; |
} |
} |
} |
return $images; |
} |
/** |
* Afficher message d'avertissement. |
*/ |
public function executerAvertissement() { |
$widget = null; |
// Création des infos du widget |
$widget['donnees']['url_base'] = sprintf($this->config['chemins']['baseURLAbsoluDyn'], ''); |
$widget['squelette'] = 'avertissement'; |
return $widget; |
} |
} |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/avertissement.tpl.html |
---|
New file |
0,0 → 1,107 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml"> |
<head> |
<title>Avertissements - CEL widget cartographie</title> |
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> |
<meta http-equiv="Content-style-type" content="text/css" /> |
<meta http-equiv="Content-script-type" content="text/javascript" /> |
<meta http-equiv="Content-language" content="fr" /> |
<meta name="revisit-after" content="15 days" /> |
<meta name="robots" content="index,follow" /> |
<meta name="author" content="Delphine CAUQUIL, Jean-Pascal MILCENT" /> |
<meta name="keywords" content="Avertissement, Tela Botanica, cartographie, CEL" /> |
<meta name="description" content="Avertissement du widget de cartographie des observations publiques de plantes saisies dans le Carnet en Ligne (CEL)" /> |
<!-- Spécial mobile --> |
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> |
<!-- Favicones --> |
<link rel="icon" type="image/png" href="http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.png" /> |
<link rel="shortcut icon" type="image/x-icon" href="http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.ico" /> |
<!-- CSS --> |
<link href="<?=$url_base?>modules/carto/squelettes/css/carto.css" rel="stylesheet" type="text/css" media="screen" /> |
<style type=""> |
html { |
overflow:auto; |
} |
body { |
overflow:auto; |
} |
</style> |
<!-- Stats : Google Analytics --> |
<script type="text/javascript"> |
//<![CDATA[ |
var _gaq = _gaq || []; |
_gaq.push(['_setAccount', 'UA-20092557-1']); |
_gaq.push(['_trackPageview']); |
(function() { |
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
})(); |
//]]> |
</script> |
</head> |
<body> |
<div id="zone-avertissement"> |
<h1>Avertissements & informations</h1> |
<h2>C'est quoi ces chiffres sur la carte ?</h2> |
<p> |
Afin de ne pas divulguer la localisation des stations d'espèces rares ou protégées, l'ensemble des observations |
a été regroupé par commune.<br /> |
Ainsi les nombres apparaissant sur la carte représentent le nombre de communes où des observations ont été |
réalisées.<br /> |
Ce nombre varie en fonction du niveau de zoom auquel vous vous trouvez, jusqu'à faire apparaître l'icône |
<img src="http://chart.apis.google.com/chart?cht=mm&chs=24x32&chco=FFFFFF,008CFF,000000&ext=.png" alt="Icône de regroupement des observations" />. |
Il indique le centre d'une commune et permet en cliquant dessus d'afficher l'ensemble des observations que l'on |
peut y trouver. |
</p> |
<h2>Avertissements</h2> |
<p> |
Les observations affichées sur cette carte proviennent des saisies des membres du réseau Tela Botanica réalisées à l'aide |
de l'application <a href="http://www.tela-botanica.org/appli:cel" onclick="window.open(this.href); return false;">Carnet en Ligne (CEL)</a>.<br /> |
Bien que la plupart des botanistes cherchent à déterminer avec un maximum de rigueur les espèces qu'ils observent, il arrive que des erreurs soient faites.<br /> |
Il est donc important de garder un esprit critique vis à vis des observations diffusées sur cette carte.<br /> |
Nous souhaitons prochainement ajouter à cette application cartographique un moyen de contacter les auteurs des observations. |
Cette fonctionnalité permettra de faciliter la correction d'eventuelles erreurs.<br /> |
Pour l'instant, si vous constatez des problèmes, veuillez contacter : <a href="mailto:eflore_remarques@tela-botanica.org">eflore_remarques@tela-botanica.org</a>. |
</p> |
<h2>Le <a href="http://www.tela-botanica.org/appli:cel" onclick="window.open(this.href); return false;">Carnet en Ligne (CEL)</a>, c'est quoi ?</h2> |
<h3>Un outil pour gérer mes relevés de terrain</h3> |
<p> |
Le Carnet en ligne est <a href="http://www.tela-botanica.org/appli:cel" onclick="window.open(this.href); return false;">accessible en ligne sur le site de Tela Botanica</a>. |
Vous pouvez y déposer vos observations de plantes de manière simple et efficace |
(aide à la saisie, visualisation de la chorologie d’une plante, utilisation de Google Map), |
les trier et les rechercher. |
</p> |
<h3>Des fonctionnalités à la demande</h3> |
<ul> |
<li>Un module cartographique vous permet de géolocaliser vos observations grâce aux coordonnées ou bien par pointage sur une carte (en France métropolitaine).</li> |
<li>Un module image vous permet d’ajouter des images et des les associer à vos observations.</li> |
<li>Un module projet vous permet de créer des projets et d’y associer des observations.</li> |
<li>Un module import/export au format tableur pour traiter ses données.</li> |
</ul> |
<h3>Partage des données</h3> |
<p> |
Partager vos observations permet d’alimenter la base de données eFlore, de compléter automatiquement la carte |
de répartition des espèces du site de Tela Botanica, de servir de source de données pour des projets externes...<br /> |
Les données sont publiées sous licence libre <a href="http://www.tela-botanica.org/page:licence" onclick="window.open(this.href); return false;">Creative commons</a> |
afin d'en faciliter la divulgation. |
</p> |
<h3>Vous souhaitez participer ?</h3> |
<p>Consulter le mode d'emploi ci-dessous pour facilement prendre en main cet outil.</p> |
<div> |
<object style="width: 600px; height: 282px;"> |
<param value="http://static.issuu.com/webembed/viewers/style1/v1/IssuuViewer.swf?mode=embed&viewMode=presentation&layout=http%3A%2F%2Fskin.issuu.com%2Fv%2Flight%2Flayout.xml&showFlipBtn=true&autoFlip=true&autoFlipTime=6000&documentId=100624090135-b3beeea0f20641bf8f277c49ebc5bbee&docName=cel&username=marietela&loadingInfoText=Carnet%20en%20ligne&et=1277375679622&er=55" name="movie"> |
<param value="true" name="allowfullscreen"> |
<param value="false" name="menu"><embed flashvars="mode=embed&viewMode=presentation&layout=http%3A%2F%2Fskin.issuu.com%2Fv%2Flight%2Flayout.xml&showFlipBtn=true&autoFlip=true&autoFlipTime=6000&documentId=100624090135-b3beeea0f20641bf8f277c49ebc5bbee&docName=cel&username=marietela&loadingInfoText=Carnet%20en%20ligne&et=1277375679622&er=55" style="width: 600px; height: 282px;" menu="false" allowfullscreen="true" type="application/x-shockwave-flash" src="http://static.issuu.com/webembed/viewers/style1/v1/IssuuViewer.swf"> |
</object> |
<p style="width: 600px; text-align: left;"><a target="_blank" href="http://issuu.com/marietela/docs/cel?mode=embed&viewMode=presentation&layout=http%3A%2F%2Fskin.issuu.com%2Fv%2Flight%2Flayout.xml&showFlipBtn=true&autoFlip=true&autoFlipTime=6000">Open publication</a> - Free <a target="_blank" href="http://issuu.com">publishing</a> - <a target="_blank" href="http://issuu.com/search?q=terrain">More terrain</a></p> |
</div> |
</div> |
</body> |
</html> |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/obs_tableau.tpl.html |
---|
New file |
0,0 → 1,35 |
<div class="info-bulle-contenu"> |
<div class="onglets"> |
<ul> |
<li class="actif"><span class="onglet">Tableau</span></li> |
<li class="inactif"><a class="onglet" onclick="chargerFormatObs('<?=$station_id?>', 'liste');return false;" href="#">Liste</a></li> |
</ul> |
</div> |
<div id="observations"> |
<table> |
<caption><h2><?=count($observations)?> observations pour <?=(isset($commune) ? $commune : '?')?></h2></caption> |
<thead> |
<tr> |
<th>Nom</th><th>Date</th><th>Lieu</th><th>Observateur</th> |
</tr> |
</thead> |
<tbody> |
<? foreach ($observations as $obs) : ?> |
<tr> |
<td> |
<? if (isset($obs['nn'])) : ?> |
<a href="http://www.tela-botanica.org/nn<?=$obs['nn']?>" onclick="window.open(this.href); arreter(event); return false; "><?=$obs['nom']?></a> |
<? else : ?> |
<?=$obs['nom']?> |
<? endif; ?> |
</td> |
<td> <?=$obs['date']?></td> |
<td> <?=$obs['lieu']?></td> |
<td> <?=$obs['observateur']?></td> |
</tr> |
<? endforeach; ?> |
</tbody> |
</table> |
<? include(dirname(__FILE__).'/obs_msg_info.tpl.html') ?> |
</div> |
</div> |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/obs_liste.tpl.html |
---|
New file |
0,0 → 1,43 |
<div class="info-bulle-contenu"> |
<div class="onglets"> |
<ul> |
<li class="inactif"><a class="onglet" onclick="chargerFormatObs('<?=$station_id?>', 'tableau');return false;" href="#">Tableau</a></li> |
<li class="actif"><span class="onglet">Liste</span></li> |
</ul> |
</div> |
<div id="observations"> |
<h2><?=count($observations)?> observations pour <?=(isset($commune) ? $commune : '?')?></h2> |
<ol> |
<? foreach ($observations as $obs) : ?> |
<li> |
<div> |
<? if (isset($images[$obs['id']])) : ?> |
<? foreach ($images[$obs['id']] as $num => $urls) : ?> |
<div<?=($num == 0) ? ' class="cel-img-principale"': ' class="cel-img-secondaire"'?>> |
<a class="cel-img" href="<?=$urls['normale']?>" rel="cel-obs-<?=$obs['id']?>"> |
<img src="<?=$urls['miniature']?>" alt="Image #<?=$urls['id']?> de l'osbervation #<?=$obs['id']?>" /> |
</a> |
</div> |
<? endforeach ?> |
<? endif ?> |
<dl> |
<dt class="champ_nom_latin">Nom</dt> |
<dd> |
<? if (isset($obs['nn'])) : ?> |
<a href="http://www.tela-botanica.org/nn<?=$obs['nn']?>" onclick="window.open(this.href); arreter(event); return false; "><?=$obs['nom']?></a> |
<? else : ?> |
<?=$obs['nom']?> |
<? endif; ?> |
</dd> |
<dt>Lieu</dt><dd> <?=$obs['lieu']?></dd> |
<dt>Publié par</dt><dd> <?=$obs['observateur']?></dd> |
<dt>Le</dt><dd> <?=$obs['date']?></dd> |
</dl> |
<hr class="nettoyage"/> |
</div> |
</li> |
<? endforeach; ?> |
</ol> |
<? include(dirname(__FILE__).'/obs_msg_info.tpl.html') ?> |
</div> |
</div> |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/trie.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/trie.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/information.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/information.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/trie_croissant.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/trie_croissant.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/chargement.gif |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/chargement.gif |
---|
New file |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/fermeture.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/fermeture.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/ouverture.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/ouverture.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/trie_decroissant.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/images/trie_decroissant.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/obs_msg_info.tpl.html |
---|
New file |
0,0 → 1,3 |
<p id="obs-msg-info"> |
Les observations de cette carte sont regroupées par commune. |
</p> |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/carte_defaut.tpl.html |
---|
New file |
0,0 → 1,339 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml"> |
<head> |
<title>Observations publiques du CEL - Tela Botanica</title> |
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> |
<meta http-equiv="Content-style-type" content="text/css" /> |
<meta http-equiv="Content-script-type" content="text/javascript" /> |
<meta http-equiv="Content-language" content="fr" /> |
<meta name="revisit-after" content="15 days" /> |
<meta name="robots" content="index,follow" /> |
<meta name="author" content="Delphine CAUQUIL, Jean-Pascal MILCENT" /> |
<meta name="keywords" content="Tela Botanica, cartographie, CEL" /> |
<meta name="description" content="Widget de cartographie des observations publiques de plantes saisies dans le Carnet en Ligne (CEL)" /> |
<!-- Spécial mobile --> |
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> |
<!-- Favicones --> |
<link rel="icon" type="image/png" href="http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.png" /> |
<link rel="shortcut icon" type="image/x-icon" href="http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.ico" /> |
<!-- Javascript : bibliothèques --> |
<!-- Google Map v3 --> |
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.3&sensor=true"></script> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/google/map/3/markerclusterer/1.0/markerclusterer-1.0.pack.js"></script> |
<!-- Jquery --> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/<?=$jquery_version?>/jquery-<?=$jquery_version?>.min.js"></script> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/tablesorter/2.0.5/jquery.tablesorter.min.js"></script> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/fancybox/1.3.4/jquery.fancybox-1.3.4.pack.js"></script> |
<!-- Javascript : données --> |
<script src="<?=$url_json?>" type="text/javascript"></script> |
<!-- Javascript : appli carto --> |
<script type="text/javascript"> |
//<![CDATA[ |
var pointImageUrl = 'http://chart.apis.google.com/chart?cht=mm&chs=24x32&chco=FFFFFF,008CFF,000000&ext=.png'; |
var pointsOrigine = null; |
var boundsOrigine = null; |
var markerClusterer = null; |
var map = null; |
var nt = '<?=$num_taxon?>'; |
var infoBulle = new google.maps.InfoWindow(); |
google.maps.event.addListener(infoBulle, 'domready', function() { |
// Onglet Tableau : Jquery => TableSorter |
if ($("#observations table").get() != '') { |
// add parser through the tablesorter addParser method |
$.tablesorter.addParser({ |
// Définition d'un id unique pour ce parsseur |
id: 'date_cel', |
is: function(s) { |
// retourne false si le parsseur n'est pas autodétecté |
return false; |
}, |
format: function(s) { |
// Transformation date jj/mm/aaaa en aaaa/mm/jj |
s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1"); |
// Remplace la date par un nombre de millisecondes pour trier numériquement |
return $.tablesorter.formatFloat(new Date(s).getTime()); |
}, |
// set type, either numeric or text |
type: 'numeric' |
}); |
$("#observations table").tablesorter({ |
headers: { |
1: { |
sorter:'date_cel' |
} |
} |
}); |
} |
// Onglet Liste : Jquery => FancyBox |
if ($("#observations ol").get() != '') { |
$("a.cel-img").fancybox({ |
transitionIn : 'elastic', |
transitionOut : 'elastic', |
speedIn : 600, |
speedOut : 200, |
overlayShow : true |
}).bind('click', function(e) { |
if (e.stopPropagation) { |
e.stopPropagation(); |
} |
return false; |
}); |
} |
}); |
google.maps.event.addListener(infoBulle, 'closeclick', function() { |
map.panTo(pointClique.position); |
}); |
var pointClique = null; |
var carteCentre = new google.maps.LatLng(46.4, 3.10); |
var carteOptions = { |
zoom: 6, |
mapTypeId: google.maps.MapTypeId.ROADMAP, |
mapTypeControlOptions: { |
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU} |
}; |
var ctaLayer = null; |
function refreshMap() { |
var points = []; |
var bounds = new google.maps.LatLngBounds(); |
for (var i = 0; i < obs.nombre; ++i) { |
var maLatLng = new google.maps.LatLng(obs.points[i].coord_x, obs.points[i].coord_y); |
var pointImage = new google.maps.MarkerImage(pointImageUrl, new google.maps.Size(24, 32)); |
var point = new google.maps.Marker({ |
position: maLatLng, |
map: map, |
icon: pointImage, |
stationId: obs.points[i].id |
}); |
bounds.extend(maLatLng); |
google.maps.event.addListener(point, 'click', function() { |
pointClique = this; |
infoBulle.open(map, this); |
var limites = map.getBounds(); |
var centre = limites.getCenter(); |
var nordEst = limites.getNorthEast(); |
var centreSudLatLng = new google.maps.LatLng(nordEst.lat(), centre.lng()); |
map.panTo(centreSudLatLng); |
afficherMsgChargement(); |
chargerFormatObs(this.stationId, '*'); |
}); |
points.push(point); |
} |
if (pointsOrigine == null && boundsOrigine == null) { |
pointsOrigine = points; |
boundsOrigine = bounds; |
} |
executerMarkerClusterer(points, bounds); |
} |
function executerMarkerClusterer(points, bounds) { |
if (markerClusterer) { |
markerClusterer.clearMarkers(); |
} |
markerClusterer = new MarkerClusterer(map, points); |
map.fitBounds(bounds); |
} |
function afficherMsgChargement() { |
var chargement = document.getElementById('chargement').cloneNode(true); |
chargement.setAttribute('id', 'chargement-copie'); |
infoBulle.setContent(chargement); |
} |
function chargerFormatObs(stationId, format) { |
var url = '<?=$url_base?>carto?carte=observations'+ |
'&utilisateur=<?=$utilisateur?>'+ |
'&projet=<?=$projet?>'+ |
'&num_taxon='+nt+ |
'&dept=<?=$dept?>'+ |
'&format='+format+'&station='+stationId; |
$.get(url, function(observations){ |
infoBulle.setContent(observations); |
}); |
} |
function arreter(event) { |
if (event.stopPropagation) { |
event.stopPropagation(); |
} |
return false; |
} |
function afficher() { |
document.getElementById('panneau-lateral').style.width = '300px'; |
document.getElementById('pl-contenu').style.display = 'block'; |
document.getElementById('pl-ouverture').style.display = 'none'; |
document.getElementById('pl-fermeture').style.display = 'block'; |
document.getElementById('carte').style.left = '300px'; |
google.maps.event.trigger(map, 'resize'); |
}; |
function cacher() { |
document.getElementById('panneau-lateral').style.width = '24px'; |
document.getElementById('pl-contenu').style.display = 'none'; |
document.getElementById('pl-ouverture').style.display = 'block'; |
document.getElementById('pl-fermeture').style.display = 'none'; |
document.getElementById('carte').style.left = '24px'; |
google.maps.event.trigger(map, 'resize'); |
}; |
function ouvrirPopUp(url, nom) { |
window.open(url, nom, 'scrollbars=yes,width=650,height=600,directories=no,location=no,menubar=no,status=no,toolbar=no'); |
}; |
function filtrerParTaxon(ntAFiltrer) { |
infoBulle.close(); |
$('#taxon-'+nt).removeClass('taxon-actif'); |
if (nt == ntAFiltrer) { |
nt = '*'; |
executerMarkerClusterer(pointsOrigine, boundsOrigine); |
} else { |
var url = '<?=$url_cel_carto?>/carte-defaut-json/<?=$utilisateur?>/<?=$projet?>/<?=$dept?>/'+ntAFiltrer+'?formatRetour=jsonp&callback=?'; |
$.getJSON(url, function (observations) { |
obs = observations; |
nt = ntAFiltrer; |
$('#taxon-'+nt).addClass('taxon-actif'); |
refreshMap(); |
}); |
} |
}; |
function initialize() { |
map = new google.maps.Map(document.getElementById('carte'), carteOptions); |
// Ajout des limites communales sur la carte |
<? if (isset($url_limites_communales)) : ?> |
<? foreach ($url_limites_communales as $url) : ?> |
ctaLayer = new google.maps.KmlLayer('<?=$url?>', {preserveViewport: true}); |
ctaLayer.setMap(map); |
<? endforeach ?> |
<? endif ?> |
<? if ($num_taxon == '*') : ?> |
var ouvertureDiv = document.getElementById('pl-ouverture'); |
google.maps.event.addDomListener(ouvertureDiv, 'click', afficher); |
var fermetureDiv = document.getElementById('pl-fermeture'); |
google.maps.event.addDomListener(fermetureDiv, 'click', cacher); |
<? endif ?> |
refreshMap(); |
} |
// Déclenchement d'actions pour JQuery |
$(document).ready(function() { |
// Ajout du nombre de communes où des observations ont eu lieu |
$('#commune-nbre').append(obs.nombre); |
}); |
//]]> |
</script> |
<!-- CSS --> |
<link href="<?=$url_base?>modules/carto/squelettes/css/carto.css" rel="stylesheet" type="text/css" media="screen" /> |
<link rel="stylesheet" href="http://www.tela-botanica.org/commun/jquery/fancybox/1.3.4/jquery.fancybox-1.3.4.css" type="text/css" media="screen" /> |
<!--[if lt IE 7]> |
<style type="text/css"> |
#carte { |
height:expression(document.body.clientHeight-35); /* 80+20+20=120 */ |
width:expression(document.body.clientWidth-24); /* 200+20+20+20=260 */ |
} |
#panneau-lateral { |
height:expression(document.body.clientHeight-35); /* 80+20+20=120 */ |
} |
</style> |
<![endif]--> |
<? if ($num_taxon != '*') : ?> |
<style type="text/css"> |
#carte { |
left:0; |
} |
</style> |
<? endif ?> |
<!-- Stats : Google Analytics --> |
<script type="text/javascript"> |
//<![CDATA[ |
var _gaq = _gaq || []; |
_gaq.push(['_setAccount', 'UA-20092557-1']); |
_gaq.push(['_trackPageview']); |
(function() { |
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
})(); |
//]]> |
</script> |
</head> |
<body onload="initialize()"> |
<div id="zone-titre"> |
<h1 id="carte-titre"> |
<? if ($num_taxon == '*') : ?> |
<span id="commune-nbre"> </span> communes contenant des observations du <a href="http://www.tela-botanica.org/appli:cel" title="Carnet en Ligne" onclick="window.open(this.href); arreter(event); return false;">CEL</a> de <a href="http://www.tela-botanica.org/" onclick="window.open(this.href); arreter(event); return false;">Tela Botanica</a> |
<? else : ?> |
<span id="commune-nbre"> </span> communes pour <?=$taxon_nom?> - <a href="http://www.tela-botanica.org/appli:cel" title="Carnet en Ligne" onclick="window.open(this.href); arreter(event); return false;">CEL</a> de <a href="http://www.tela-botanica.org/" onclick="window.open(this.href); arreter(event); return false;">Tela Botanica</a> |
<? endif ?> |
</h1> |
<div id="zone-info"> |
<a href="<?=$url_base?>carto?carte=avertissement" onClick="ouvrirPopUp('<?=$url_base?>carto?carte=avertissement', 'Avertissement'); arreter(event); return false;"> |
<img src="<?=$url_base?>modules/carto/squelettes/images/information.png" |
alt="Avertissements" title="Avertissements & informations" /> |
</a> |
</div> |
</div> |
<? if ($num_taxon == '*') : ?> |
<div id="panneau-lateral"> |
<div id="pl-ouverture" title="Ouvrir le panneau latéral"><span>Panneau >></span></div> |
<div id="pl-fermeture" title="Fermer le panneau latéral"><span><< Fermer [x]</span></div> |
<div id="pl-contenu"> |
<div id="pl-entete"> |
<h2>Filtre sur <?=count($taxons)?> plantes</h2> |
<p> |
Cliquez sur un nom de plante pour filtrer les observations sur la carte.<br /> |
Pour revenir à l'état initial, cliquez à nouveau sur le nom sélectionné. |
</p> |
</div> |
<div id="pl-corps" onMouseOver="map.setOptions({'scrollwheel':false});" onMouseOut="map.setOptions({'scrollwheel':true});"> |
<ol id="taxons"> |
<? foreach ($taxons as $taxon) : ?> |
<li id="taxon-<?=$taxon['nt']?>"> |
<a href="#" onclick="filtrerParTaxon(<?=$taxon['nt']?>);" title="<?=$taxon['famille']?>"> |
<?=$taxon['nom']?> |
</a> |
</li> |
<? endforeach; ?> |
</ol> |
</div> |
</div> |
</div> |
<? endif ?> |
<div id="carte"></div> |
<!-- Blocs chargés à la demande : par défaut avec un style display à none --> |
<div id="chargement"> |
<img src="<?=$url_base?>modules/carto/squelettes/images/chargement.gif" alt="Chargement en cours..." /> |
<p>Chargement des observations en cours...</p> |
</div> |
</body> |
</html> |
/branches/v1.4-broyeur/widget/modules/carto/squelettes/css/carto.css |
---|
New file |
0,0 → 1,328 |
@charset "UTF-8"; |
html { |
overflow:hidden; |
} |
body { |
overflow:hidden; |
padding:0; |
margin:0; |
width:100%; |
height:100%; |
font-family:Arial; |
font-size:12px; |
} |
h1 { |
font-size:1.6em; |
} |
h2 { |
font-size:1.4em; |
} |
a, a:active, a:visited { |
border-bottom:1px dotted #666; |
color:#CCC; |
text-decoration:none; |
} |
a:active { |
outline:none; |
} |
a:focus { |
outline:thin dotted; |
} |
a:hover { |
color:#56B80E; |
border-bottom:1px dotted #56B80E; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Présentation des listes de définitions */ |
dl { |
width:100%; |
} |
dt { |
float:left; |
font-weight:bold; |
text-align:top left; |
margin-right:0.3em; |
} |
dd { |
width:auto; |
margin:0.5em 0; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Tableau : */ |
table { |
border:1px solid gray; |
border-collapse:collapse; |
} |
table thead, table tfoot, table tbody { |
background-color:Gainsboro; |
border:1px solid gray; |
} |
table tbody { |
background-color:#FFF; |
} |
table th { |
font-family:monospace; |
border:1px dotted gray; |
padding:5px; |
background-color:Gainsboro; |
} |
table td { |
font-family:arial; |
border:1px dotted gray; |
padding:5px; |
text-align:left; |
} |
table caption { |
font-family:sans-serif; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Tableau : tablesorter */ |
th.header { |
background:url(../images/trie.png) no-repeat center right; |
padding-right:20px; |
} |
th.headerSortUp { |
background:url(../images/trie_croissant.png) no-repeat center right #56B80E; |
color:white; |
} |
th.headerSortDown { |
background:url(../images/trie_decroissant.png) no-repeat center right #56B80E; |
color:white; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Générique */ |
.nettoyage{ |
clear:both; |
} |
hr.nettoyage{ |
visibility:hidden; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Carte */ |
#carte { |
padding:0; |
margin:0; |
position:absolute; |
top:35px; |
left:24px; |
right:0; |
bottom:0; |
overflow:auto; |
} |
.bouton { |
background-color:white; |
border:2px solid black; |
cursor:pointer; |
text-align:center; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Message de chargement */ |
#chargement { |
display:none; |
} |
#chargement-copie img{ |
display:block; |
margin:auto; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Avertissement */ |
#zone-avertissement { |
background-color:#4A4B4C; |
color:#CCC; |
padding:12px; |
text-align:justify; |
line-height:16px; |
} |
#zone-avertissement h1{ |
margin:0; |
} |
#zone-avertissement a { |
border-bottom:1px dotted gainsboro; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Carte titre */ |
#zone-titre { |
padding:0; |
margin:0; |
position:absolute; |
top:0; |
left:0; |
width:100%; |
height:35px; |
overflow:hidden; |
background:url(http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.png) no-repeat 8px 8px #4A4B4C; |
} |
#zone-info { |
position:absolute; |
top:0; |
right:8px; |
width:48px; |
text-align:right; |
} |
#zone-info img { |
display:inline; |
padding:4px; |
margin:0; |
border:none; |
} |
#carte-titre { |
display:inline-block; |
margin:0 0 0 24px; |
padding:0.2em; |
color:#CCCCCC; |
} |
#carte-titre {/*Hack CSS fonctionne seulement dans ie6, 7 & 8 */ |
display:inline !hackCssIe6Et7;/*Hack CSS pour ie6 & ie7 */ |
display /*\**/:inline\9;/*Hack CSS pour ie8 */ |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Panneau latéral */ |
#panneau-lateral { |
padding:0; |
margin:0; |
position:absolute; |
top:35px; |
left:0; |
bottom:0; |
width:24px; |
overflow:hidden; |
background-color:#4A4B4C; |
border-right:1px solid grey; |
} |
#pl-contenu { |
display:none; |
} |
#pl-entete { |
height:95px; |
} |
#pl-corps { |
position:absolute; |
top:105px; |
bottom:0; |
overflow:auto; |
padding:5px; |
width:290px; |
} |
#pl-ouverture, #pl-fermeture { |
position:absolute; |
top:0; |
height:24px; |
width:24px; |
text-align:center; |
cursor:pointer; |
} |
#pl-ouverture { |
left:0; |
background:url(../images/ouverture.png) no-repeat top left #4A4B4C; |
} |
#pl-fermeture { |
display:none; |
left:276px; |
background:url(../images/fermeture.png) no-repeat top right #4A4B4C; |
} |
#pl-ouverture span, #pl-fermeture span{ |
display:none; |
} |
/* Panneau latéral : balises */ |
#panneau-lateral h2, #panneau-lateral p { |
color:#CCCCCC;} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Liste des taxons de la carte */ |
#taxons { |
color:#999; |
} |
#taxons .taxon-actif, #taxons .taxon-actif a { |
color:#56B80E;} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Pop-up observations */ |
.info-bulle-contenu { |
margin:0; |
padding:0; |
} |
#observations { |
margin:23px 0 0 0; |
padding:5px; |
border:1px solid black; |
border-radius:0 0 10px 10px;-moz-border-radius:0 0 10px 10px;-webkit-border-radius:0 0 10px 10px; |
border-top:none !important; |
overflow:none; |
} |
#observations ol { |
padding-left:20px; |
} |
.champ_nom_latin { |
display:none; |
} |
#obs-msg-info { |
font-size:10px; |
color:#CCC; |
} |
#observations a { |
color:#333; |
border-bottom:1px dotted gainsboro; |
} |
#observations a:hover { |
color:#56B80E; |
border-bottom:1px dotted #56B80E; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Onglets */ |
.onglets { |
position:absolute; |
top:0; |
float:left; |
height:22px; |
padding:0; |
margin:0; |
border-bottom:1px solid black; |
width:100%; |
} |
.onglets ul { |
margin:0; |
padding:0; |
list-style:none; |
} |
.onglets li { |
float:left; |
text-transform:uppercase; |
text-align:center; |
} |
.onglets .onglet { |
display:block; |
padding:5px 15px 4px 15px; |
margin:0; |
font-size:12px; |
line-height:12px; |
border:1px solid black; |
border-radius:10px 10px 0 0;-moz-border-radius:10px 10px 0 0;-webkit-border-radius:10px 10px 0 0; |
text-decoration:none; |
} |
.onglets .actif .onglet { |
border-bottom:1px solid white; |
color:black; |
background-color:white; |
font-weight:bold; |
} |
.onglets .inactif .onglet { |
border-bottom:1px solid #000000; |
color:white; |
background-color:gray;/*rgba(29,30,32,0.8);*/ |
} |
.onglets .inactif .onglet:hover { |
color:black; |
background-color:Gainsboro; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Pop-up : liste */ |
.cel-img-principale img{ |
float:right; |
height:75px; |
padding:1px; |
border:1px solid white; |
} |
#observations .cel-img:hover img{ |
border:1px dotted #56B80E; |
} |
.cel-img-secondaire{ |
display:none; |
} |
/branches/v1.4-broyeur/widget/modules/carto |
---|
New file |
Property changes: |
Added: svn:ignore |
+config.ini |
/branches/v1.4-broyeur/widget/modules/photo/config.defaut.ini |
---|
New file |
0,0 → 1,19 |
[photo] |
; Chemin pour l'autoload à ajouter |
autoload = "bibliotheque/;bibliotheque/xml_feed_parser/1.0.4/;bibliotheque/xml_feed_parser/1.0.4/parsers/" |
; URL ou chemin du flux RSS contenant les liens vers les photos |
fluxRssUrl = "http://www.tela-botanica.org/service:cel:CelSyndicationImage/complet/atom" |
; Squelette d'url pour accéder à la fiche eFlore |
efloreUrlTpl = "http://www.tela-botanica.org/eflore/BDNFF/4.02/nn/%s/illustration" |
; Nombre de vignette à afficher : nombre de vignettes par ligne et nombre de lignes séparés par une vigule (ex. : 4,3). |
vignette = 4,3 |
; Afficher/Cacher l'affichage en grand de la dernière image ajoutée |
extraActif = true |
[photo.cache] |
; Active/Désactive le cache |
activation = true |
; Dossier où stocker les fichiers de cache du widget |
stockageDossier = "/tmp" |
; Durée de vie du fichier de cache |
dureeDeVie = 86400 |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/Cache.php |
---|
New file |
0,0 → 1,128 |
<?php |
class Cache { |
private $actif = null; |
private $dossier_stockage = null; |
private $duree_de_vie = null; |
public function __construct($dossier_stockage = null, $duree_de_vie = null, $activation = true) { |
$this->actif = ($activation) ? true : false; |
if ($this->actif) { |
$this->dossier_stockage = $dossier_stockage; |
if (is_null($dossier_stockage)) { |
$this->dossier_stockage = self::getDossierTmp(); |
} |
$this->duree_de_vie = $duree_de_vie; |
if (is_null($duree_de_vie)) { |
$this->duree_de_vie = 3600*24; |
} |
} |
} |
public function charger($id) { |
$contenu = false; |
if ($this->actif) { |
$chemin_fichier_cache = $this->dossier_stockage.DIRECTORY_SEPARATOR.$id.'.txt'; |
if (file_exists($chemin_fichier_cache ) && (time() - @filemtime($chemin_fichier_cache) < $this->duree_de_vie)) { |
$contenu = file_get_contents($chemin_fichier_cache); |
} |
} |
return $contenu; |
} |
public function sauver($id, $contenu) { |
if ($this->actif) { |
$chemin_fichier_cache = $this->dossier_stockage.DIRECTORY_SEPARATOR.$id.'.txt'; |
if (!file_exists($chemin_fichier_cache) || (time() - @filemtime($chemin_fichier_cache) > $this->duree_de_vie)) { |
$fh = fopen($chemin_fichier_cache,'w+'); |
if ($fh) { |
fputs($fh, $contenu); |
fclose($fh); |
} |
} |
} |
} |
/** |
* Détermine le dossier système temporaire et détecte si nous y avons accès en lecture et écriture. |
* |
* Inspiré de Zend_File_Transfer_Adapter_Abstract & Zend_Cache |
* |
* @return string|false le chemine vers le dossier temporaire ou false en cas d'échec. |
*/ |
private static function getDossierTmp() { |
$dossier_tmp = false; |
foreach (array($_ENV, $_SERVER) as $environnement) { |
foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $cle) { |
if (isset($environnement[$cle])) { |
if (($cle == 'windir') or ($cle == 'SystemRoot')) { |
$dossier = realpath($environnement[$cle] . '\\temp'); |
} else { |
$dossier = realpath($environnement[$cle]); |
} |
if (self::etreAccessibleEnLectureEtEcriture($dossier)) { |
$dossier_tmp = $dossier; |
break 2; |
} |
} |
} |
} |
if ( ! $dossier_tmp) { |
$dossier_televersement_tmp = ini_get('upload_tmp_dir'); |
if ($dossier_televersement_tmp) { |
$dossier = realpath($dossier_televersement_tmp); |
if (self::etreAccessibleEnLectureEtEcriture($dossier)) { |
$dossier_tmp = $dossier; |
} |
} |
} |
if ( ! $dossier_tmp) { |
if (function_exists('sys_get_temp_dir')) { |
$dossier = sys_get_temp_dir(); |
if (self::etreAccessibleEnLectureEtEcriture($dossier)) { |
$dossier_tmp = $dossier; |
} |
} |
} |
if ( ! $dossier_tmp) { |
// Tentative de création d'un fichier temporaire |
$fichier_tmp = tempnam(md5(uniqid(rand(), TRUE)), ''); |
if ($fichier_tmp) { |
$dossier = realpath(dirname($fichier_tmp)); |
unlink($fichier_tmp); |
if (self::etreAccessibleEnLectureEtEcriture($dossier)) { |
$dossier_tmp = $dossier; |
} |
} |
} |
if ( ! $dossier_tmp && self::etreAccessibleEnLectureEtEcriture('/tmp')) { |
$dossier_tmp = '/tmp'; |
} |
if ( ! $dossier_tmp && self::etreAccessibleEnLectureEtEcriture('\\temp')) { |
$dossier_tmp = '\\temp'; |
} |
return $dossier_tmp; |
} |
/** |
* Vérifie si le fichier ou dossier est accessible en lecture et écriture. |
* |
* @param $ressource chemin vers le dossier ou fichier à tester |
* @return boolean true si la ressource est accessible en lecture et écriture. |
*/ |
protected static function etreAccessibleEnLectureEtEcriture($ressource){ |
$accessible = false; |
if (is_readable($ressource) && is_writable($ressource)) { |
$accessible = true; |
} |
return $accessible; |
} |
} |
?> |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/schemas/rss11.rng |
---|
New file |
0,0 → 1,218 |
<?xml version="1.0" encoding="UTF-8"?> |
<!-- |
RELAX NG Compact Schema for RSS 1.1 |
Sean B. Palmer, inamidst.com |
Christopher Schmidt, crschmidt.net |
License: This schema is in the public domain |
--> |
<grammar xmlns:rss="http://purl.org/net/rss1.1#" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ns="http://purl.org/net/rss1.1#" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> |
<start> |
<ref name="Channel"/> |
</start> |
<define name="Channel"> |
<a:documentation>http://purl.org/net/rss1.1#Channel</a:documentation> |
<element name="Channel"> |
<ref name="Channel.content"/> |
</element> |
</define> |
<define name="Channel.content"> |
<optional> |
<ref name="AttrXMLLang"/> |
</optional> |
<optional> |
<ref name="AttrXMLBase"/> |
</optional> |
<ref name="AttrRDFAbout"/> |
<interleave> |
<ref name="title"/> |
<ref name="link"/> |
<ref name="description"/> |
<optional> |
<ref name="image"/> |
</optional> |
<zeroOrMore> |
<ref name="Any"/> |
</zeroOrMore> |
<ref name="items"/> |
</interleave> |
</define> |
<define name="title"> |
<a:documentation>http://purl.org/net/rss1.1#title</a:documentation> |
<element name="title"> |
<ref name="title.content"/> |
</element> |
</define> |
<define name="title.content"> |
<optional> |
<ref name="AttrXMLLang"/> |
</optional> |
<text/> |
</define> |
<define name="link"> |
<a:documentation>http://purl.org/net/rss1.1#link</a:documentation> |
<element name="link"> |
<ref name="link.content"/> |
</element> |
</define> |
<define name="link.content"> |
<data type="anyURI"/> |
</define> |
<define name="description"> |
<a:documentation>http://purl.org/net/rss1.1#description</a:documentation> |
<element name="description"> |
<ref name="description.content"/> |
</element> |
</define> |
<define name="description.content"> |
<optional> |
<ref name="AttrXMLLang"/> |
</optional> |
<text/> |
</define> |
<define name="image"> |
<a:documentation>http://purl.org/net/rss1.1#image</a:documentation> |
<element name="image"> |
<ref name="image.content"/> |
</element> |
</define> |
<define name="image.content"> |
<optional> |
<ref name="AttrXMLLang"/> |
</optional> |
<ref name="AttrRDFResource"/> |
<interleave> |
<ref name="title"/> |
<optional> |
<ref name="link"/> |
</optional> |
<ref name="url"/> |
<zeroOrMore> |
<ref name="Any"/> |
</zeroOrMore> |
</interleave> |
</define> |
<define name="url"> |
<a:documentation>http://purl.org/net/rss1.1#url</a:documentation> |
<element name="url"> |
<ref name="url.content"/> |
</element> |
</define> |
<define name="url.content"> |
<data type="anyURI"/> |
</define> |
<define name="items"> |
<a:documentation>http://purl.org/net/rss1.1#items</a:documentation> |
<element name="items"> |
<ref name="items.content"/> |
</element> |
</define> |
<define name="items.content"> |
<optional> |
<ref name="AttrXMLLang"/> |
</optional> |
<ref name="AttrRDFCollection"/> |
<zeroOrMore> |
<ref name="item"/> |
</zeroOrMore> |
</define> |
<define name="item"> |
<a:documentation>http://purl.org/net/rss1.1#item</a:documentation> |
<element name="item"> |
<ref name="item.content"/> |
</element> |
</define> |
<define name="item.content"> |
<optional> |
<ref name="AttrXMLLang"/> |
</optional> |
<ref name="AttrRDFAbout"/> |
<interleave> |
<ref name="title"/> |
<ref name="link"/> |
<optional> |
<ref name="description"/> |
</optional> |
<optional> |
<ref name="image"/> |
</optional> |
<zeroOrMore> |
<ref name="Any"/> |
</zeroOrMore> |
</interleave> |
</define> |
<define name="Any"> |
<a:documentation>http://purl.org/net/rss1.1#Any</a:documentation> |
<element> |
<anyName> |
<except> |
<nsName/> |
</except> |
</anyName> |
<ref name="Any.content"/> |
</element> |
</define> |
<define name="Any.content"> |
<zeroOrMore> |
<attribute> |
<anyName> |
<except> |
<nsName/> |
<nsName ns=""/> |
</except> |
</anyName> |
</attribute> |
</zeroOrMore> |
<mixed> |
<zeroOrMore> |
<ref name="Any"/> |
</zeroOrMore> |
</mixed> |
</define> |
<define name="AttrXMLLang"> |
<attribute name="xml:lang"> |
<data type="language"/> |
</attribute> |
</define> |
<define name="AttrXMLBase"> |
<attribute name="xml:base"> |
<data type="anyURI"/> |
</attribute> |
</define> |
<define name="AttrRDFAbout"> |
<attribute name="rdf:about"> |
<data type="anyURI"/> |
</attribute> |
</define> |
<define name="AttrRDFResource"> |
<attribute name="rdf:parseType"> |
<value>Resource</value> |
</attribute> |
</define> |
<define name="AttrRDFCollection"> |
<attribute name="rdf:parseType"> |
<value>Collection</value> |
</attribute> |
</define> |
</grammar> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/schemas/rss20.rng |
---|
New file |
0,0 → 1,298 |
<?xml version="1.0" encoding="utf-8"?> |
<!-- ====================================================================== |
* Author: Dino Morelli |
* Began: 2004-Feb-18 |
* Build #: 0001 |
* Version: 0.1 |
* E-Mail: dino.morelli@snet.net |
* URL: (none yet) |
* License: (none yet) |
* |
* ======================================================================== |
* |
* RSS v2.0 Relax NG schema |
* |
* ==================================================================== --> |
<grammar xmlns="http://relaxng.org/ns/structure/1.0"> |
<start> |
<ref name="element-rss" /> |
</start> |
<define name="element-title"> |
<element name="title"> |
<text /> |
</element> |
</define> |
<define name="element-description"> |
<element name="description"> |
<text /> |
</element> |
</define> |
<define name="element-link"> |
<element name="link"> |
<text /> |
</element> |
</define> |
<define name="element-category"> |
<element name="category"> |
<optional> |
<attribute name="domain" /> |
</optional> |
<text /> |
</element> |
</define> |
<define name="element-rss"> |
<element name="rss"> |
<attribute name="version"> |
<value>2.0</value> |
</attribute> |
<element name="channel"> |
<interleave> |
<ref name="element-title" /> |
<ref name="element-link" /> |
<ref name="element-description" /> |
<optional> |
<element name="language"><text /></element> |
</optional> |
<optional> |
<element name="copyright"><text /></element> |
</optional> |
<optional> |
<element name="lastBuildDate"><text /></element> |
</optional> |
<optional> |
<element name="docs"><text /></element> |
</optional> |
<optional> |
<element name="generator"><text /></element> |
</optional> |
<optional> |
<ref name="element-category" /> |
</optional> |
<optional> |
<element name="managingEditor"><text /></element> |
</optional> |
<optional> |
<element name="webMaster"><text /></element> |
</optional> |
<optional> |
<element name="pubDate"><text /></element> |
</optional> |
<optional> |
<element name="rating"><text /></element> |
</optional> |
<optional> |
<element name="image"> |
<interleave> |
<element name="url"><text /></element> |
<ref name="element-title" /> |
<ref name="element-link" /> |
<optional> |
<element name="width"><text /></element> |
</optional> |
<optional> |
<element name="height"><text /></element> |
</optional> |
<optional> |
<ref name="element-description" /> |
</optional> |
</interleave> |
</element> |
</optional> |
<optional> |
<element name="cloud"> |
<attribute name="domain" /> |
<attribute name="port" /> |
<attribute name="path" /> |
<attribute name="registerProcedure" /> |
<attribute name="protocol" /> |
</element> |
</optional> |
<optional> |
<element name="textInput"> |
<interleave> |
<ref name="element-title" /> |
<ref name="element-description" /> |
<element name="name"><text /></element> |
<ref name="element-link" /> |
</interleave> |
</element> |
</optional> |
<optional> |
<element name="skipHours"> |
<oneOrMore> |
<element name="hour"> |
<choice> |
<value>0</value> |
<value>1</value> |
<value>2</value> |
<value>3</value> |
<value>4</value> |
<value>5</value> |
<value>6</value> |
<value>7</value> |
<value>8</value> |
<value>9</value> |
<value>10</value> |
<value>11</value> |
<value>12</value> |
<value>13</value> |
<value>14</value> |
<value>15</value> |
<value>16</value> |
<value>17</value> |
<value>18</value> |
<value>19</value> |
<value>20</value> |
<value>21</value> |
<value>22</value> |
<value>23</value> |
</choice> |
</element> |
</oneOrMore> |
</element> |
</optional> |
<optional> |
<element name="skipDays"> |
<oneOrMore> |
<element name="day"> |
<choice> |
<value>0</value> |
<value>1</value> |
<value>2</value> |
<value>3</value> |
<value>4</value> |
<value>5</value> |
<value>6</value> |
<value>7</value> |
<value>8</value> |
<value>9</value> |
<value>10</value> |
<value>11</value> |
<value>12</value> |
<value>13</value> |
<value>14</value> |
<value>15</value> |
<value>16</value> |
<value>17</value> |
<value>18</value> |
<value>19</value> |
<value>20</value> |
<value>21</value> |
<value>22</value> |
<value>23</value> |
<value>24</value> |
<value>25</value> |
<value>26</value> |
<value>27</value> |
<value>28</value> |
<value>29</value> |
<value>30</value> |
<value>31</value> |
</choice> |
</element> |
</oneOrMore> |
</element> |
</optional> |
<optional> |
<element name="ttl"><text /></element> |
</optional> |
<zeroOrMore> |
<element name="item"> |
<interleave> |
<choice> |
<ref name="element-title" /> |
<ref name="element-description" /> |
<interleave> |
<ref name="element-title" /> |
<ref name="element-description" /> |
</interleave> |
</choice> |
<optional> |
<ref name="element-link" /> |
</optional> |
<optional> |
<element name="author"><text /></element> |
</optional> |
<optional> |
<ref name="element-category" /> |
</optional> |
<optional> |
<element name="comments"><text /></element> |
</optional> |
<optional> |
<element name="enclosure"> |
<attribute name="url" /> |
<attribute name="length" /> |
<attribute name="type" /> |
<text /> |
</element> |
</optional> |
<optional> |
<element name="guid"> |
<optional> |
<attribute name="isPermaLink"> |
<choice> |
<value>true</value> |
<value>false</value> |
</choice> |
</attribute> |
</optional> |
<text /> |
</element> |
</optional> |
<optional> |
<element name="pubDate"><text /></element> |
</optional> |
<optional> |
<element name="source"> |
<attribute name="url" /> |
<text /> |
</element> |
</optional> |
</interleave> |
</element> |
</zeroOrMore> |
</interleave> |
</element> |
</element> |
</define> |
</grammar> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/schemas/atom.rng |
---|
New file |
0,0 → 1,598 |
<?xml version="1.0" encoding="UTF-8"?> |
<!-- |
-*- rnc -*- |
RELAX NG Compact Syntax Grammar for the |
Atom Format Specification Version 11 |
--> |
<grammar ns="http://www.w3.org/1999/xhtml" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:s="http://www.ascc.net/xml/schematron" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> |
<start> |
<choice> |
<ref name="atomFeed"/> |
<ref name="atomEntry"/> |
</choice> |
</start> |
<!-- Common attributes --> |
<define name="atomCommonAttributes"> |
<optional> |
<attribute name="xml:base"> |
<ref name="atomUri"/> |
</attribute> |
</optional> |
<optional> |
<attribute name="xml:lang"> |
<ref name="atomLanguageTag"/> |
</attribute> |
</optional> |
<zeroOrMore> |
<ref name="undefinedAttribute"/> |
</zeroOrMore> |
</define> |
<!-- Text Constructs --> |
<define name="atomPlainTextConstruct"> |
<ref name="atomCommonAttributes"/> |
<optional> |
<attribute name="type"> |
<choice> |
<value>text</value> |
<value>html</value> |
</choice> |
</attribute> |
</optional> |
<text/> |
</define> |
<define name="atomXHTMLTextConstruct"> |
<ref name="atomCommonAttributes"/> |
<attribute name="type"> |
<value>xhtml</value> |
</attribute> |
<ref name="xhtmlDiv"/> |
</define> |
<define name="atomTextConstruct"> |
<choice> |
<ref name="atomPlainTextConstruct"/> |
<ref name="atomXHTMLTextConstruct"/> |
</choice> |
</define> |
<!-- Person Construct --> |
<define name="atomPersonConstruct"> |
<ref name="atomCommonAttributes"/> |
<interleave> |
<element name="atom:name"> |
<text/> |
</element> |
<optional> |
<element name="atom:uri"> |
<ref name="atomUri"/> |
</element> |
</optional> |
<optional> |
<element name="atom:email"> |
<ref name="atomEmailAddress"/> |
</element> |
</optional> |
<zeroOrMore> |
<ref name="extensionElement"/> |
</zeroOrMore> |
</interleave> |
</define> |
<!-- Date Construct --> |
<define name="atomDateConstruct"> |
<ref name="atomCommonAttributes"/> |
<data type="dateTime"/> |
</define> |
<!-- atom:feed --> |
<define name="atomFeed"> |
<element name="atom:feed"> |
<s:rule context="atom:feed"> |
<s:assert test="atom:author or not(atom:entry[not(atom:author)])">An atom:feed must have an atom:author unless all of its atom:entry children have an atom:author.</s:assert> |
</s:rule> |
<ref name="atomCommonAttributes"/> |
<interleave> |
<zeroOrMore> |
<ref name="atomAuthor"/> |
</zeroOrMore> |
<zeroOrMore> |
<ref name="atomCategory"/> |
</zeroOrMore> |
<zeroOrMore> |
<ref name="atomContributor"/> |
</zeroOrMore> |
<optional> |
<ref name="atomGenerator"/> |
</optional> |
<optional> |
<ref name="atomIcon"/> |
</optional> |
<ref name="atomId"/> |
<zeroOrMore> |
<ref name="atomLink"/> |
</zeroOrMore> |
<optional> |
<ref name="atomLogo"/> |
</optional> |
<optional> |
<ref name="atomRights"/> |
</optional> |
<optional> |
<ref name="atomSubtitle"/> |
</optional> |
<ref name="atomTitle"/> |
<ref name="atomUpdated"/> |
<zeroOrMore> |
<ref name="extensionElement"/> |
</zeroOrMore> |
</interleave> |
<zeroOrMore> |
<ref name="atomEntry"/> |
</zeroOrMore> |
</element> |
</define> |
<!-- atom:entry --> |
<define name="atomEntry"> |
<element name="atom:entry"> |
<s:rule context="atom:entry"> |
<s:assert test="atom:link[@rel='alternate'] or atom:link[not(@rel)] or atom:content">An atom:entry must have at least one atom:link element with a rel attribute of 'alternate' or an atom:content.</s:assert> |
</s:rule> |
<s:rule context="atom:entry"> |
<s:assert test="atom:author or ../atom:author or atom:source/atom:author">An atom:entry must have an atom:author if its feed does not.</s:assert> |
</s:rule> |
<ref name="atomCommonAttributes"/> |
<interleave> |
<zeroOrMore> |
<ref name="atomAuthor"/> |
</zeroOrMore> |
<zeroOrMore> |
<ref name="atomCategory"/> |
</zeroOrMore> |
<optional> |
<ref name="atomContent"/> |
</optional> |
<zeroOrMore> |
<ref name="atomContributor"/> |
</zeroOrMore> |
<ref name="atomId"/> |
<zeroOrMore> |
<ref name="atomLink"/> |
</zeroOrMore> |
<optional> |
<ref name="atomPublished"/> |
</optional> |
<optional> |
<ref name="atomRights"/> |
</optional> |
<optional> |
<ref name="atomSource"/> |
</optional> |
<optional> |
<ref name="atomSummary"/> |
</optional> |
<ref name="atomTitle"/> |
<ref name="atomUpdated"/> |
<zeroOrMore> |
<ref name="extensionElement"/> |
</zeroOrMore> |
</interleave> |
</element> |
</define> |
<!-- atom:content --> |
<define name="atomInlineTextContent"> |
<element name="atom:content"> |
<ref name="atomCommonAttributes"/> |
<optional> |
<attribute name="type"> |
<choice> |
<value>text</value> |
<value>html</value> |
</choice> |
</attribute> |
</optional> |
<zeroOrMore> |
<text/> |
</zeroOrMore> |
</element> |
</define> |
<define name="atomInlineXHTMLContent"> |
<element name="atom:content"> |
<ref name="atomCommonAttributes"/> |
<attribute name="type"> |
<value>xhtml</value> |
</attribute> |
<ref name="xhtmlDiv"/> |
</element> |
</define> |
<define name="atomInlineOtherContent"> |
<element name="atom:content"> |
<ref name="atomCommonAttributes"/> |
<optional> |
<attribute name="type"> |
<ref name="atomMediaType"/> |
</attribute> |
</optional> |
<zeroOrMore> |
<choice> |
<text/> |
<ref name="anyElement"/> |
</choice> |
</zeroOrMore> |
</element> |
</define> |
<define name="atomOutOfLineContent"> |
<element name="atom:content"> |
<ref name="atomCommonAttributes"/> |
<optional> |
<attribute name="type"> |
<ref name="atomMediaType"/> |
</attribute> |
</optional> |
<attribute name="src"> |
<ref name="atomUri"/> |
</attribute> |
<empty/> |
</element> |
</define> |
<define name="atomContent"> |
<choice> |
<ref name="atomInlineTextContent"/> |
<ref name="atomInlineXHTMLContent"/> |
<ref name="atomInlineOtherContent"/> |
<ref name="atomOutOfLineContent"/> |
</choice> |
</define> |
<!-- atom:author --> |
<define name="atomAuthor"> |
<element name="atom:author"> |
<ref name="atomPersonConstruct"/> |
</element> |
</define> |
<!-- atom:category --> |
<define name="atomCategory"> |
<element name="atom:category"> |
<ref name="atomCommonAttributes"/> |
<attribute name="term"/> |
<optional> |
<attribute name="scheme"> |
<ref name="atomUri"/> |
</attribute> |
</optional> |
<optional> |
<attribute name="label"/> |
</optional> |
<ref name="undefinedContent"/> |
</element> |
</define> |
<!-- atom:contributor --> |
<define name="atomContributor"> |
<element name="atom:contributor"> |
<ref name="atomPersonConstruct"/> |
</element> |
</define> |
<!-- atom:generator --> |
<define name="atomGenerator"> |
<element name="atom:generator"> |
<ref name="atomCommonAttributes"/> |
<optional> |
<attribute name="uri"> |
<ref name="atomUri"/> |
</attribute> |
</optional> |
<optional> |
<attribute name="version"/> |
</optional> |
<text/> |
</element> |
</define> |
<!-- atom:icon --> |
<define name="atomIcon"> |
<element name="atom:icon"> |
<ref name="atomCommonAttributes"/> |
<ref name="atomUri"/> |
</element> |
</define> |
<!-- atom:id --> |
<define name="atomId"> |
<element name="atom:id"> |
<ref name="atomCommonAttributes"/> |
<ref name="atomUri"/> |
</element> |
</define> |
<!-- atom:logo --> |
<define name="atomLogo"> |
<element name="atom:logo"> |
<ref name="atomCommonAttributes"/> |
<ref name="atomUri"/> |
</element> |
</define> |
<!-- atom:link --> |
<define name="atomLink"> |
<element name="atom:link"> |
<ref name="atomCommonAttributes"/> |
<attribute name="href"> |
<ref name="atomUri"/> |
</attribute> |
<optional> |
<attribute name="rel"> |
<choice> |
<ref name="atomNCName"/> |
<ref name="atomUri"/> |
</choice> |
</attribute> |
</optional> |
<optional> |
<attribute name="type"> |
<ref name="atomMediaType"/> |
</attribute> |
</optional> |
<optional> |
<attribute name="hreflang"> |
<ref name="atomLanguageTag"/> |
</attribute> |
</optional> |
<optional> |
<attribute name="title"/> |
</optional> |
<optional> |
<attribute name="length"/> |
</optional> |
<ref name="undefinedContent"/> |
</element> |
</define> |
<!-- atom:published --> |
<define name="atomPublished"> |
<element name="atom:published"> |
<ref name="atomDateConstruct"/> |
</element> |
</define> |
<!-- atom:rights --> |
<define name="atomRights"> |
<element name="atom:rights"> |
<ref name="atomTextConstruct"/> |
</element> |
</define> |
<!-- atom:source --> |
<define name="atomSource"> |
<element name="atom:source"> |
<ref name="atomCommonAttributes"/> |
<interleave> |
<zeroOrMore> |
<ref name="atomAuthor"/> |
</zeroOrMore> |
<zeroOrMore> |
<ref name="atomCategory"/> |
</zeroOrMore> |
<zeroOrMore> |
<ref name="atomContributor"/> |
</zeroOrMore> |
<optional> |
<ref name="atomGenerator"/> |
</optional> |
<optional> |
<ref name="atomIcon"/> |
</optional> |
<optional> |
<ref name="atomId"/> |
</optional> |
<zeroOrMore> |
<ref name="atomLink"/> |
</zeroOrMore> |
<optional> |
<ref name="atomLogo"/> |
</optional> |
<optional> |
<ref name="atomRights"/> |
</optional> |
<optional> |
<ref name="atomSubtitle"/> |
</optional> |
<optional> |
<ref name="atomTitle"/> |
</optional> |
<optional> |
<ref name="atomUpdated"/> |
</optional> |
<zeroOrMore> |
<ref name="extensionElement"/> |
</zeroOrMore> |
</interleave> |
</element> |
</define> |
<!-- atom:subtitle --> |
<define name="atomSubtitle"> |
<element name="atom:subtitle"> |
<ref name="atomTextConstruct"/> |
</element> |
</define> |
<!-- atom:summary --> |
<define name="atomSummary"> |
<element name="atom:summary"> |
<ref name="atomTextConstruct"/> |
</element> |
</define> |
<!-- atom:title --> |
<define name="atomTitle"> |
<element name="atom:title"> |
<ref name="atomTextConstruct"/> |
</element> |
</define> |
<!-- atom:updated --> |
<define name="atomUpdated"> |
<element name="atom:updated"> |
<ref name="atomDateConstruct"/> |
</element> |
</define> |
<!-- Low-level simple types --> |
<define name="atomNCName"> |
<data type="string"> |
<param name="minLength">1</param> |
<param name="pattern">[^:]*</param> |
</data> |
</define> |
<!-- Whatever a media type is, it contains at least one slash --> |
<define name="atomMediaType"> |
<data type="string"> |
<param name="pattern">.+/.+</param> |
</data> |
</define> |
<!-- As defined in RFC 3066 --> |
<define name="atomLanguageTag"> |
<data type="string"> |
<param name="pattern">[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*</param> |
</data> |
</define> |
<!-- |
Unconstrained; it's not entirely clear how IRI fit into |
xsd:anyURI so let's not try to constrain it here |
--> |
<define name="atomUri"> |
<text/> |
</define> |
<!-- Whatever an email address is, it contains at least one @ --> |
<define name="atomEmailAddress"> |
<data type="string"> |
<param name="pattern">.+@.+</param> |
</data> |
</define> |
<!-- Simple Extension --> |
<define name="simpleExtensionElement"> |
<element> |
<anyName> |
<except> |
<nsName ns="http://www.w3.org/2005/Atom"/> |
</except> |
</anyName> |
<text/> |
</element> |
</define> |
<!-- Structured Extension --> |
<define name="structuredExtensionElement"> |
<element> |
<anyName> |
<except> |
<nsName ns="http://www.w3.org/2005/Atom"/> |
</except> |
</anyName> |
<choice> |
<group> |
<oneOrMore> |
<attribute> |
<anyName/> |
</attribute> |
</oneOrMore> |
<zeroOrMore> |
<choice> |
<text/> |
<ref name="anyElement"/> |
</choice> |
</zeroOrMore> |
</group> |
<group> |
<zeroOrMore> |
<attribute> |
<anyName/> |
</attribute> |
</zeroOrMore> |
<group> |
<optional> |
<text/> |
</optional> |
<oneOrMore> |
<ref name="anyElement"/> |
</oneOrMore> |
<zeroOrMore> |
<choice> |
<text/> |
<ref name="anyElement"/> |
</choice> |
</zeroOrMore> |
</group> |
</group> |
</choice> |
</element> |
</define> |
<!-- Other Extensibility --> |
<define name="extensionElement"> |
<choice> |
<ref name="simpleExtensionElement"/> |
<ref name="structuredExtensionElement"/> |
</choice> |
</define> |
<define name="undefinedAttribute"> |
<attribute> |
<anyName> |
<except> |
<name>xml:base</name> |
<name>xml:lang</name> |
<nsName ns=""/> |
</except> |
</anyName> |
</attribute> |
</define> |
<define name="undefinedContent"> |
<zeroOrMore> |
<choice> |
<text/> |
<ref name="anyForeignElement"/> |
</choice> |
</zeroOrMore> |
</define> |
<define name="anyElement"> |
<element> |
<anyName/> |
<zeroOrMore> |
<choice> |
<attribute> |
<anyName/> |
</attribute> |
<text/> |
<ref name="anyElement"/> |
</choice> |
</zeroOrMore> |
</element> |
</define> |
<define name="anyForeignElement"> |
<element> |
<anyName> |
<except> |
<nsName ns="http://www.w3.org/2005/Atom"/> |
</except> |
</anyName> |
<zeroOrMore> |
<choice> |
<attribute> |
<anyName/> |
</attribute> |
<text/> |
<ref name="anyElement"/> |
</choice> |
</zeroOrMore> |
</element> |
</define> |
<!-- XHTML --> |
<define name="anyXHTML"> |
<element> |
<nsName/> |
<zeroOrMore> |
<choice> |
<attribute> |
<anyName/> |
</attribute> |
<text/> |
<ref name="anyXHTML"/> |
</choice> |
</zeroOrMore> |
</element> |
</define> |
<define name="xhtmlDiv"> |
<element name="xhtml:div"> |
<zeroOrMore> |
<choice> |
<attribute> |
<anyName/> |
</attribute> |
<text/> |
<ref name="anyXHTML"/> |
</choice> |
</zeroOrMore> |
</element> |
</define> |
</grammar> |
<!-- EOF --> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/schemas/README |
---|
New file |
0,0 → 1,9 |
Most of these schemas are only available in RNC (RelaxNG, Compact) format. |
libxml (and therefor PHP) only supports RelaxNG - the XML version. |
To update these, you will need a conversion utility, like trang (http://www.thaiopensource.com/relaxng/trang.html). |
clockwerx@clockwerx-desktop:~/trang$ java -jar trang.jar -I rnc -O rng http://atompub.org/2005/08/17/atom.rnc atom.rng |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/schemas/rss10.rng |
---|
New file |
0,0 → 1,113 |
<?xml version='1.0' encoding='UTF-8'?> |
<!-- http://www.xml.com/lpt/a/2002/01/23/relaxng.html --> |
<!-- http://www.oasis-open.org/committees/relax-ng/tutorial-20011203.html --> |
<!-- http://www.zvon.org/xxl/XMLSchemaTutorial/Output/ser_wildcards_st8.html --> |
<grammar xmlns='http://relaxng.org/ns/structure/1.0' |
xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' |
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' |
ns='http://purl.org/rss/1.0/' |
datatypeLibrary='http://www.w3.org/2001/XMLSchema-datatypes'> |
<start> |
<element name='RDF' ns='http://www.w3.org/1999/02/22-rdf-syntax-ns#'> |
<ref name='RDFContent'/> |
</element> |
</start> |
<define name='RDFContent' ns='http://purl.org/rss/1.0/'> |
<interleave> |
<element name='channel'> |
<ref name='channelContent'/> |
</element> |
<optional> |
<element name='image'><ref name='imageContent'/></element> |
</optional> |
<oneOrMore> |
<element name='item'><ref name='itemContent'/></element> |
</oneOrMore> |
</interleave> |
</define> |
<define name='channelContent' combine="interleave"> |
<interleave> |
<element name='title'><data type='string'/></element> |
<element name='link'><data type='anyURI'/></element> |
<element name='description'><data type='string'/></element> |
<element name='image'> |
<attribute name='resource' ns='http://www.w3.org/1999/02/22-rdf-syntax-ns#'> |
<data type='anyURI'/> |
</attribute> |
</element> |
<element name='items'> |
<ref name='itemsContent'/> |
</element> |
<attribute name='about' ns='http://www.w3.org/1999/02/22-rdf-syntax-ns#'> |
<data type='anyURI'/> |
</attribute> |
</interleave> |
</define> |
<define name="itemsContent"> |
<element name="Seq" ns='http://www.w3.org/1999/02/22-rdf-syntax-ns#'> |
<oneOrMore> |
<element name="li" ns='http://www.w3.org/1999/02/22-rdf-syntax-ns#'> |
<choice> |
<attribute name='resource'> <!-- Why doesn't RDF/RSS1.0 ns qualify this attribute? --> |
<data type='anyURI'/> |
</attribute> |
<attribute name='resource' ns='http://www.w3.org/1999/02/22-rdf-syntax-ns#'> |
<data type='anyURI'/> |
</attribute> |
</choice> |
</element> |
</oneOrMore> |
</element> |
</define> |
<define name='imageContent'> |
<interleave> |
<element name='title'><data type='string'/></element> |
<element name='link'><data type='anyURI'/></element> |
<element name='url'><data type='anyURI'/></element> |
<attribute name='about' ns='http://www.w3.org/1999/02/22-rdf-syntax-ns#'> |
<data type='anyURI'/> |
</attribute> |
</interleave> |
</define> |
<define name='itemContent'> |
<interleave> |
<element name='title'><data type='string'/></element> |
<element name='link'><data type='anyURI'/></element> |
<optional><element name='description'><data type='string'/></element></optional> |
<ref name="anyThing"/> |
<attribute name='about' ns='http://www.w3.org/1999/02/22-rdf-syntax-ns#'> |
<data type='anyURI'/> |
</attribute> |
</interleave> |
</define> |
<define name='anyThing'> |
<zeroOrMore> |
<choice> |
<text/> |
<element> |
<anyName> |
<except> |
<nsName/> |
</except> |
</anyName> |
<ref name='anyThing'/> |
<zeroOrMore> |
<attribute> |
<anyName/> |
</attribute> |
</zeroOrMore> |
</element> |
</choice> |
</zeroOrMore> |
</define> |
</grammar> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/XmlFeedParser.php |
---|
New file |
0,0 → 1,304 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Key gateway class for XML_Feed_Parser package |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL |
* @version CVS: $Id: Parser.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This is the core of the XML_Feed_Parser package. It identifies feed types |
* and abstracts access to them. It is an iterator, allowing for easy access |
* to the entire feed. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
*/ |
class XmlFeedParser implements Iterator { |
/** |
* This is where we hold the feed object |
* @var Object |
*/ |
private $feed; |
/** |
* To allow for extensions, we make a public reference to the feed model |
* @var DOMDocument |
*/ |
public $model; |
/** |
* A map between entry ID and offset |
* @var array |
*/ |
protected $idMappings = array(); |
/** |
* A storage space for Namespace URIs. |
* @var array |
*/ |
private $feedNamespaces = array( |
'rss2' => array( |
'http://backend.userland.com/rss', |
'http://backend.userland.com/rss2', |
'http://blogs.law.harvard.edu/tech/rss')); |
/** |
* Detects feed types and instantiate appropriate objects. |
* |
* Our constructor takes care of detecting feed types and instantiating |
* appropriate classes. For now we're going to treat Atom 0.3 as Atom 1.0 |
* but raise a warning. I do not intend to introduce full support for |
* Atom 0.3 as it has been deprecated, but others are welcome to. |
* |
* @param string $feed XML serialization of the feed |
* @param bool $strict Whether or not to validate the feed |
* @param bool $suppressWarnings Trigger errors for deprecated feed types? |
* @param bool $tidy Whether or not to try and use the tidy library on input |
*/ |
function __construct($feed, $strict = false, $suppressWarnings = true, $tidy = true) { |
$this->model = new DOMDocument; |
if (! $this->model->loadXML($feed)) { |
if (extension_loaded('tidy') && $tidy) { |
$tidy = new tidy; |
$tidy->parseString($feed, array('input-xml' => true, 'output-xml' => true)); |
$tidy->cleanRepair(); |
if (! $this->model->loadXML((string) $tidy)) { |
throw new XmlFeedParserException("Entrée invalide : le flux n'est pas du XML valide"); |
} |
} else { |
throw new XmlFeedParserException("Entrée invalide : le flux n'est pas du XML valide"); |
} |
} |
/* detect feed type */ |
$doc_element = $this->model->documentElement; |
$error = false; |
switch (true) { |
case ($doc_element->namespaceURI == 'http://www.w3.org/2005/Atom'): |
$class = 'XmlFeedParserAtom'; |
break; |
case ($doc_element->namespaceURI == 'http://purl.org/atom/ns#'): |
$class = 'XmlFeedParserAtom'; |
$error = "Atom 0.3 est déprécié, le parseur en version 1.0 sera utilisé mais toutes les options ne seront pas disponibles."; |
break; |
case ($doc_element->namespaceURI == 'http://purl.org/rss/1.0/' |
|| ($doc_element->hasChildNodes() && $doc_element->childNodes->length > 1 |
&& $doc_element->childNodes->item(1)->namespaceURI == 'http://purl.org/rss/1.0/')): |
$class = 'XmlFeedParserRss1'; |
break; |
case ($doc_element->namespaceURI == 'http://purl.org/rss/1.1/' |
|| ($doc_element->hasChildNodes() |
&& $doc_element->childNodes->length > 1 |
&& $doc_element->childNodes->item(1)->namespaceURI == 'http://purl.org/rss/1.1/')): |
$class = 'XmlFeedParserRss11'; |
break; |
case (($doc_element->hasChildNodes() |
&& $doc_element->childNodes->length > 1 |
&& $doc_element->childNodes->item(1)->namespaceURI == 'http://my.netscape.com/rdf/simple/0.9/') |
|| $doc_element->namespaceURI == 'http://my.netscape.com/rdf/simple/0.9/'): |
$class = 'XmlFeedParserRss09'; |
break; |
case ($doc_element->tagName == 'rss' |
and $doc_element->hasAttribute('version') |
&& $doc_element->getAttribute('version') == 0.91): |
$error = 'RSS 0.91 has been superceded by RSS2.0. Using RSS2.0 parser.'; |
$class = 'XmlFeedParserRss2'; |
break; |
case ($doc_element->tagName == 'rss' |
and $doc_element->hasAttribute('version') |
&& $doc_element->getAttribute('version') == 0.92): |
$error = 'RSS 0.92 has been superceded by RSS2.0. Using RSS2.0 parser.'; |
$class = 'XmlFeedParserRss2'; |
break; |
case (in_array($doc_element->namespaceURI, $this->feedNamespaces['rss2']) |
|| $doc_element->tagName == 'rss'): |
if (! $doc_element->hasAttribute('version') || $doc_element->getAttribute('version') != 2) { |
$error = 'RSS version not specified. Parsing as RSS2.0'; |
} |
$class = 'XmlFeedParserRss2'; |
break; |
default: |
throw new XmlFeedParserException('Type de flux de syndicaton inconnu'); |
break; |
} |
if (! $suppressWarnings && ! empty($error)) { |
trigger_error($error, E_USER_WARNING); |
} |
/* Instantiate feed object */ |
$this->feed = new $class($this->model, $strict); |
} |
/** |
* Proxy to allow feed element names to be used as method names |
* |
* For top-level feed elements we will provide access using methods or |
* attributes. This function simply passes on a request to the appropriate |
* feed type object. |
* |
* @param string $call - the method being called |
* @param array $attributes |
*/ |
function __call($call, $attributes) { |
$attributes = array_pad($attributes, 5, false); |
list($a, $b, $c, $d, $e) = $attributes; |
return $this->feed->$call($a, $b, $c, $d, $e); |
} |
/** |
* Proxy to allow feed element names to be used as attribute names |
* |
* To allow variable-like access to feed-level data we use this |
* method. It simply passes along to __call() which in turn passes |
* along to the relevant object. |
* |
* @param string $val - the name of the variable required |
*/ |
function __get($val) { |
return $this->feed->$val; |
} |
/** |
* Provides iteration functionality. |
* |
* Of course we must be able to iterate... This function simply increases |
* our internal counter. |
*/ |
function next() { |
if (isset($this->current_item) && |
$this->current_item <= $this->feed->numberEntries - 1) { |
++$this->current_item; |
} else if (! isset($this->current_item)) { |
$this->current_item = 0; |
} else { |
return false; |
} |
} |
/** |
* Return XML_Feed_Type object for current element |
* |
* @return XML_Feed_Parser_Type Object |
*/ |
function current() { |
return $this->getEntryByOffset($this->current_item); |
} |
/** |
* For iteration -- returns the key for the current stage in the array. |
* |
* @return int |
*/ |
function key() { |
return $this->current_item; |
} |
/** |
* For iteration -- tells whether we have reached the |
* end. |
* |
* @return bool |
*/ |
function valid() { |
return $this->current_item < $this->feed->numberEntries; |
} |
/** |
* For iteration -- resets the internal counter to the beginning. |
*/ |
function rewind() { |
$this->current_item = 0; |
} |
/** |
* Provides access to entries by ID if one is specified in the source feed. |
* |
* As well as allowing the items to be iterated over we want to allow |
* users to be able to access a specific entry. This is one of two ways of |
* doing that, the other being by offset. This method can be quite slow |
* if dealing with a large feed that hasn't yet been processed as it |
* instantiates objects for every entry until it finds the one needed. |
* |
* @param string $id Valid ID for the given feed format |
* @return XML_Feed_Parser_Type|false |
*/ |
function getEntryById($id) { |
if (isset($this->idMappings[$id])) { |
return $this->getEntryByOffset($this->idMappings[$id]); |
} |
/* |
* Since we have not yet encountered that ID, let's go through all the |
* remaining entries in order till we find it. |
* This is a fairly slow implementation, but it should work. |
*/ |
return $this->feed->getEntryById($id); |
} |
/** |
* Retrieve entry by numeric offset, starting from zero. |
* |
* As well as allowing the items to be iterated over we want to allow |
* users to be able to access a specific entry. This is one of two ways of |
* doing that, the other being by ID. |
* |
* @param int $offset The position of the entry within the feed, starting from 0 |
* @return XML_Feed_Parser_Type|false |
*/ |
function getEntryByOffset($offset) { |
if ($offset < $this->feed->numberEntries) { |
if (isset($this->feed->entries[$offset])) { |
return $this->feed->entries[$offset]; |
} else { |
try { |
$this->feed->getEntryByOffset($offset); |
} catch (Exception $e) { |
return false; |
} |
$id = $this->feed->entries[$offset]->getID(); |
$this->idMappings[$id] = $offset; |
return $this->feed->entries[$offset]; |
} |
} else { |
return false; |
} |
} |
/** |
* Retrieve version details from feed type class. |
* |
* @return void |
* @author James Stewart |
*/ |
function version() { |
return $this->feed->version; |
} |
/** |
* Returns a string representation of the feed. |
* |
* @return String |
**/ |
function __toString() { |
return $this->feed->__toString(); |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserAtom.php |
---|
New file |
0,0 → 1,357 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Atom feed class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: Atom.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This is the class that determines how we manage Atom 1.0 feeds |
* |
* How we deal with constructs: |
* date - return as unix datetime for use with the 'date' function unless specified otherwise |
* text - return as is. optional parameter will give access to attributes |
* person - defaults to name, but parameter based access |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
*/ |
class XmlFeedParserAtom extends XmlFeedParserType { |
/** |
* The URI of the RelaxNG schema used to (optionally) validate the feed |
* @var string |
*/ |
protected $relax = 'atom.rng'; |
/** |
* We're likely to use XPath, so let's keep it global |
* @var DOMXPath |
*/ |
public $xpath; |
/** |
* When performing XPath queries we will use this prefix |
* @var string |
*/ |
private $xpathPrefix = '//'; |
/** |
* The feed type we are parsing |
* @var string |
*/ |
public $version = 'Atom 1.0'; |
/** |
* The class used to represent individual items |
* @var string |
*/ |
protected $itemClass = 'XmlFeedParserAtomElement'; |
/** |
* The element containing entries |
* @var string |
*/ |
protected $itemElement = 'entry'; |
/** |
* Here we map those elements we're not going to handle individually |
* to the constructs they are. The optional second parameter in the array |
* tells the parser whether to 'fall back' (not apt. at the feed level) or |
* fail if the element is missing. If the parameter is not set, the function |
* will simply return false and leave it to the client to decide what to do. |
* @var array |
*/ |
protected $map = array( |
'author' => array('Person'), |
'contributor' => array('Person'), |
'icon' => array('Text'), |
'logo' => array('Text'), |
'id' => array('Text', 'fail'), |
'rights' => array('Text'), |
'subtitle' => array('Text'), |
'title' => array('Text', 'fail'), |
'updated' => array('Date', 'fail'), |
'link' => array('Link'), |
'generator' => array('Text'), |
'category' => array('Category')); |
/** |
* Here we provide a few mappings for those very special circumstances in |
* which it makes sense to map back to the RSS2 spec. Key is RSS2 version |
* value is an array consisting of the equivalent in atom and any attributes |
* needed to make the mapping. |
* @var array |
*/ |
protected $compatMap = array( |
'guid' => array('id'), |
'links' => array('link'), |
'tags' => array('category'), |
'contributors' => array('contributor')); |
/** |
* Our constructor does nothing more than its parent. |
* |
* @param DOMDocument $xml A DOM object representing the feed |
* @param bool (optional) $string Whether or not to validate this feed |
*/ |
function __construct(DOMDocument $model, $strict = false) { |
$this->model = $model; |
if ($strict) { |
if (! $this->relaxNGValidate()) { |
throw new XML_Feed_Parser_Exception('Failed required validation'); |
} |
} |
$this->xpath = new DOMXPath($this->model); |
$this->xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom'); |
$this->numberEntries = $this->count('entry'); |
} |
/** |
* Implement retrieval of an entry based on its ID for atom feeds. |
* |
* This function uses XPath to get the entry based on its ID. If DOMXPath::evaluate |
* is available, we also use that to store a reference to the entry in the array |
* used by getEntryByOffset so that method does not have to seek out the entry |
* if it's requested that way. |
* |
* @param string $id any valid Atom ID. |
* @return XML_Feed_Parser_AtomElement |
*/ |
function getEntryById($id) { |
if (isset($this->idMappings[$id])) { |
return $this->entries[$this->idMappings[$id]]; |
} |
$entries = $this->xpath->query("//atom:entry[atom:id='$id']"); |
if ($entries->length > 0) { |
$xmlBase = $entries->item(0)->baseURI; |
$entry = new $this->itemClass($entries->item(0), $this, $xmlBase); |
if (in_array('evaluate', get_class_methods($this->xpath))) { |
$offset = $this->xpath->evaluate("count(preceding-sibling::atom:entry)", $entries->item(0)); |
$this->entries[$offset] = $entry; |
} |
$this->idMappings[$id] = $entry; |
return $entry; |
} |
} |
/** |
* Retrieves data from a person construct. |
* |
* Get a person construct. We default to the 'name' element but allow |
* access to any of the elements. |
* |
* @param string $method The name of the person construct we want |
* @param array $arguments An array which we hope gives a 'param' |
* @return string|false |
*/ |
protected function getPerson($method, $arguments) { |
$offset = empty($arguments[0]) ? 0 : $arguments[0]; |
$parameter = empty($arguments[1]['param']) ? 'name' : $arguments[1]['param']; |
$section = $this->model->getElementsByTagName($method); |
if ($parameter == 'url') { |
$parameter = 'uri'; |
} |
if ($section->length <= $offset) { |
return false; |
} |
$param = $section->item($offset)->getElementsByTagName($parameter); |
if ($param->length == 0) { |
return false; |
} |
return $param->item(0)->nodeValue; |
} |
/** |
* Retrieves an element's content where that content is a text construct. |
* |
* Get a text construct. When calling this method, the two arguments |
* allowed are 'offset' and 'attribute', so $parser->subtitle() would |
* return the content of the element, while $parser->subtitle(false, 'type') |
* would return the value of the type attribute. |
* |
* @todo Clarify overlap with getContent() |
* @param string $method The name of the text construct we want |
* @param array $arguments An array which we hope gives a 'param' |
* @return string |
*/ |
protected function getText($method, $arguments) { |
$offset = empty($arguments[0]) ? 0: $arguments[0]; |
$attribute = empty($arguments[1]) ? false : $arguments[1]; |
$tags = $this->model->getElementsByTagName($method); |
if ($tags->length <= $offset) { |
return false; |
} |
$content = $tags->item($offset); |
if (! $content->hasAttribute('type')) { |
$content->setAttribute('type', 'text'); |
} |
$type = $content->getAttribute('type'); |
if (! empty($attribute) and |
! ($method == 'generator' and $attribute == 'name')) { |
if ($content->hasAttribute($attribute)) { |
return $content->getAttribute($attribute); |
} else if ($attribute == 'href' and $content->hasAttribute('uri')) { |
return $content->getAttribute('uri'); |
} |
return false; |
} |
return $this->parseTextConstruct($content); |
} |
/** |
* Extract content appropriately from atom text constructs |
* |
* Because of different rules applied to the content element and other text |
* constructs, they are deployed as separate functions, but they share quite |
* a bit of processing. This method performs the core common process, which is |
* to apply the rules for different mime types in order to extract the content. |
* |
* @param DOMNode $content the text construct node to be parsed |
* @return String |
* @author James Stewart |
**/ |
protected function parseTextConstruct(DOMNode $content) { |
if ($content->hasAttribute('type')) { |
$type = $content->getAttribute('type'); |
} else { |
$type = 'text'; |
} |
if (strpos($type, 'text/') === 0) { |
$type = 'text'; |
} |
switch ($type) { |
case 'text': |
case 'html': |
return $content->textContent; |
break; |
case 'xhtml': |
$container = $content->getElementsByTagName('div'); |
if ($container->length == 0) { |
return false; |
} |
$contents = $container->item(0); |
if ($contents->hasChildNodes()) { |
/* Iterate through, applying xml:base and store the result */ |
$result = ''; |
foreach ($contents->childNodes as $node) { |
$result .= $this->traverseNode($node); |
} |
return $result; |
} |
break; |
case preg_match('@^[a-zA-Z]+/[a-zA-Z+]*xml@i', $type) > 0: |
return $content; |
break; |
case 'application/octet-stream': |
default: |
return base64_decode(trim($content->nodeValue)); |
break; |
} |
return false; |
} |
/** |
* Get a category from the entry. |
* |
* A feed or entry can have any number of categories. A category can have the |
* attributes term, scheme and label. |
* |
* @param string $method The name of the text construct we want |
* @param array $arguments An array which we hope gives a 'param' |
* @return string |
*/ |
function getCategory($method, $arguments) { |
$offset = empty($arguments[0]) ? 0: $arguments[0]; |
$attribute = empty($arguments[1]) ? 'term' : $arguments[1]; |
$categories = $this->model->getElementsByTagName('category'); |
if ($categories->length <= $offset) { |
$category = $categories->item($offset); |
if ($category->hasAttribute($attribute)) { |
return $category->getAttribute($attribute); |
} |
} |
return false; |
} |
/** |
* This element must be present at least once with rel="feed". This element may be |
* present any number of further times so long as there is no clash. If no 'rel' is |
* present and we're asked for one, we follow the example of the Universal Feed |
* Parser and presume 'alternate'. |
* |
* @param int $offset the position of the link within the container |
* @param string $attribute the attribute name required |
* @param array an array of attributes to search by |
* @return string the value of the attribute |
*/ |
function getLink($offset = 0, $attribute = 'href', $params = false) { |
if (is_array($params) and !empty($params)) { |
$terms = array(); |
$alt_predicate = ''; |
$other_predicate = ''; |
foreach ($params as $key => $value) { |
if ($key == 'rel' && $value == 'alternate') { |
$alt_predicate = '[not(@rel) or @rel="alternate"]'; |
} else { |
$terms[] = "@$key='$value'"; |
} |
} |
if (!empty($terms)) { |
$other_predicate = '[' . join(' and ', $terms) . ']'; |
} |
$query = $this->xpathPrefix . 'atom:link' . $alt_predicate . $other_predicate; |
$links = $this->xpath->query($query); |
} else { |
$links = $this->model->getElementsByTagName('link'); |
} |
if ($links->length > $offset) { |
if ($links->item($offset)->hasAttribute($attribute)) { |
$value = $links->item($offset)->getAttribute($attribute); |
if ($attribute == 'href') { |
$value = $this->addBase($value, $links->item($offset)); |
} |
return $value; |
} else if ($attribute == 'rel') { |
return 'alternate'; |
} |
} |
return false; |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserRss09.php |
---|
New file |
0,0 → 1,215 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS0.9 class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS09.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class handles RSS0.9 feeds. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
* @todo Find a Relax NG URI we can use |
*/ |
class XmlFeedParserRss09 extends XmlFeedParserType { |
/** |
* The URI of the RelaxNG schema used to (optionally) validate the feed |
* @var string |
*/ |
protected $relax = ''; |
/** |
* We're likely to use XPath, so let's keep it global |
* @var DOMXPath |
*/ |
protected $xpath; |
/** |
* The feed type we are parsing |
* @var string |
*/ |
public $version = 'RSS 0.9'; |
/** |
* The class used to represent individual items |
* @var string |
*/ |
protected $itemClass = 'XmlFeedParserRss09Element'; |
/** |
* The element containing entries |
* @var string |
*/ |
protected $itemElement = 'item'; |
/** |
* Here we map those elements we're not going to handle individually |
* to the constructs they are. The optional second parameter in the array |
* tells the parser whether to 'fall back' (not apt. at the feed level) or |
* fail if the element is missing. If the parameter is not set, the function |
* will simply return false and leave it to the client to decide what to do. |
* @var array |
*/ |
protected $map = array( |
'title' => array('Text'), |
'link' => array('Text'), |
'description' => array('Text'), |
'image' => array('Image'), |
'textinput' => array('TextInput')); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS2. |
* @var array |
*/ |
protected $compatMap = array( |
'title' => array('title'), |
'link' => array('link'), |
'subtitle' => array('description')); |
/** |
* We will be working with multiple namespaces and it is useful to |
* keep them together |
* @var array |
*/ |
protected $namespaces = array( |
'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); |
/** |
* Our constructor does nothing more than its parent. |
* |
* @todo RelaxNG validation |
* @param DOMDocument $xml A DOM object representing the feed |
* @param bool (optional) $string Whether or not to validate this feed |
*/ |
function __construct(DOMDocument $model, $strict = false) { |
$this->model = $model; |
$this->xpath = new DOMXPath($model); |
foreach ($this->namespaces as $key => $value) { |
$this->xpath->registerNamespace($key, $value); |
} |
$this->numberEntries = $this->count('item'); |
} |
/** |
* Included for compatibility -- will not work with RSS 0.9 |
* |
* This is not something that will work with RSS0.9 as it does not have |
* clear restrictions on the global uniqueness of IDs. |
* |
* @param string $id any valid ID. |
* @return false |
*/ |
function getEntryById($id) { |
return false; |
} |
/** |
* Get details of the image associated with the feed. |
* |
* @return array|false an array simply containing the child elements |
*/ |
protected function getImage() { |
$images = $this->model->getElementsByTagName('image'); |
if ($images->length > 0) { |
$image = $images->item(0); |
$details = array(); |
if ($image->hasChildNodes()) { |
$details = array( |
'title' => $image->getElementsByTagName('title')->item(0)->value, |
'link' => $image->getElementsByTagName('link')->item(0)->value, |
'url' => $image->getElementsByTagName('url')->item(0)->value); |
} else { |
$details = array('title' => false, |
'link' => false, |
'url' => $image->attributes->getNamedItem('resource')->nodeValue); |
} |
$details = array_merge($details, |
array('description' => false, 'height' => false, 'width' => false)); |
if (! empty($details)) { |
return $details; |
} |
} |
return false; |
} |
/** |
* The textinput element is little used, but in the interests of |
* completeness we will support it. |
* |
* @return array|false |
*/ |
protected function getTextInput() { |
$inputs = $this->model->getElementsByTagName('textinput'); |
if ($inputs->length > 0) { |
$input = $inputs->item(0); |
$results = array(); |
$results['title'] = isset( |
$input->getElementsByTagName('title')->item(0)->value) ? |
$input->getElementsByTagName('title')->item(0)->value : null; |
$results['description'] = isset( |
$input->getElementsByTagName('description')->item(0)->value) ? |
$input->getElementsByTagName('description')->item(0)->value : null; |
$results['name'] = isset( |
$input->getElementsByTagName('name')->item(0)->value) ? |
$input->getElementsByTagName('name')->item(0)->value : null; |
$results['link'] = isset( |
$input->getElementsByTagName('link')->item(0)->value) ? |
$input->getElementsByTagName('link')->item(0)->value : null; |
if (empty($results['link']) && |
$input->attributes->getNamedItem('resource')) { |
$results['link'] = $input->attributes->getNamedItem('resource')->nodeValue; |
} |
if (! empty($results)) { |
return $results; |
} |
} |
return false; |
} |
/** |
* Get details of a link from the feed. |
* |
* In RSS1 a link is a text element but in order to ensure that we resolve |
* URLs properly we have a special function for them. |
* |
* @return string |
*/ |
function getLink($offset = 0, $attribute = 'href', $params = false) { |
$links = $this->model->getElementsByTagName('link'); |
if ($links->length <= $offset) { |
return false; |
} |
$link = $links->item($offset); |
return $this->addBase($link->nodeValue, $link); |
} |
/** |
* Not implemented - no available validation. |
*/ |
public function relaxNGValidate() { |
return true; |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserType.php |
---|
New file |
0,0 → 1,455 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Abstract class providing common methods for XML_Feed_Parser feeds. |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: Type.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This abstract class provides some general methods that are likely to be |
* implemented exactly the same way for all feed types. |
* |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
*/ |
abstract class XmlFeedParserType { |
/** |
* Where we store our DOM object for this feed |
* @var DOMDocument |
*/ |
public $model; |
/** |
* For iteration we'll want a count of the number of entries |
* @var int |
*/ |
public $numberEntries; |
/** |
* Where we store our entry objects once instantiated |
* @var array |
*/ |
public $entries = array(); |
/** |
* Store mappings between entry IDs and their position in the feed |
*/ |
public $idMappings = array(); |
/** |
* Proxy to allow use of element names as method names |
* |
* We are not going to provide methods for every entry type so this |
* function will allow for a lot of mapping. We rely pretty heavily |
* on this to handle our mappings between other feed types and atom. |
* |
* @param string $call - the method attempted |
* @param array $arguments - arguments to that method |
* @return mixed |
*/ |
function __call($call, $arguments = array()) { |
if (! is_array($arguments)) { |
$arguments = array(); |
} |
if (isset($this->compatMap[$call])) { |
$tempMap = $this->compatMap; |
$tempcall = array_pop($tempMap[$call]); |
if (! empty($tempMap)) { |
$arguments = array_merge($arguments, $tempMap[$call]); |
} |
$call = $tempcall; |
} |
/* To be helpful, we allow a case-insensitive search for this method */ |
if (! isset($this->map[$call])) { |
foreach (array_keys($this->map) as $key) { |
if (strtoupper($key) == strtoupper($call)) { |
$call = $key; |
break; |
} |
} |
} |
if (empty($this->map[$call])) { |
return false; |
} |
$method = 'get' . $this->map[$call][0]; |
if ($method == 'getLink') { |
$offset = empty($arguments[0]) ? 0 : $arguments[0]; |
$attribute = empty($arguments[1]) ? 'href' : $arguments[1]; |
$params = isset($arguments[2]) ? $arguments[2] : array(); |
return $this->getLink($offset, $attribute, $params); |
} |
if (method_exists($this, $method)) { |
return $this->$method($call, $arguments); |
} |
return false; |
} |
/** |
* Proxy to allow use of element names as attribute names |
* |
* For many elements variable-style access will be desirable. This function |
* provides for that. |
* |
* @param string $value - the variable required |
* @return mixed |
*/ |
function __get($value) { |
return $this->__call($value, array()); |
} |
/** |
* Utility function to help us resolve xml:base values |
* |
* We have other methods which will traverse the DOM and work out the different |
* xml:base declarations we need to be aware of. We then need to combine them. |
* If a declaration starts with a protocol then we restart the string. If it |
* starts with a / then we add on to the domain name. Otherwise we simply tag |
* it on to the end. |
* |
* @param string $base - the base to add the link to |
* @param string $link |
*/ |
function combineBases($base, $link) { |
if (preg_match('/^[A-Za-z]+:\/\//', $link)) { |
return $link; |
} else if (preg_match('/^\//', $link)) { |
/* Extract domain and suffix link to that */ |
preg_match('/^([A-Za-z]+:\/\/.*)?\/*/', $base, $results); |
$firstLayer = $results[0]; |
return $firstLayer . "/" . $link; |
} else if (preg_match('/^\.\.\//', $base)) { |
/* Step up link to find place to be */ |
preg_match('/^((\.\.\/)+)(.*)$/', $link, $bases); |
$suffix = $bases[3]; |
$count = preg_match_all('/\.\.\//', $bases[1], $steps); |
$url = explode("/", $base); |
for ($i = 0; $i <= $count; $i++) { |
array_pop($url); |
} |
return implode("/", $url) . "/" . $suffix; |
} else if (preg_match('/^(?!\/$)/', $base)) { |
$base = preg_replace('/(.*\/).*$/', '$1', $base) ; |
return $base . $link; |
} else { |
/* Just stick it on the end */ |
return $base . $link; |
} |
} |
/** |
* Determine whether we need to apply our xml:base rules |
* |
* Gets us the xml:base data and then processes that with regard |
* to our current link. |
* |
* @param string |
* @param DOMElement |
* @return string |
*/ |
function addBase($link, $element) { |
if (preg_match('/^[A-Za-z]+:\/\//', $link)) { |
return $link; |
} |
return $this->combineBases($element->baseURI, $link); |
} |
/** |
* Get an entry by its position in the feed, starting from zero |
* |
* As well as allowing the items to be iterated over we want to allow |
* users to be able to access a specific entry. This is one of two ways of |
* doing that, the other being by ID. |
* |
* @param int $offset |
* @return XML_Feed_Parser_RSS1Element |
*/ |
function getEntryByOffset($offset) { |
if (! isset($this->entries[$offset])) { |
$entries = $this->model->getElementsByTagName($this->itemElement); |
if ($entries->length > $offset) { |
$xmlBase = $entries->item($offset)->baseURI; |
$this->entries[$offset] = new $this->itemClass( |
$entries->item($offset), $this, $xmlBase); |
if ($id = $this->entries[$offset]->id) { |
$this->idMappings[$id] = $this->entries[$offset]; |
} |
} else { |
throw new XML_Feed_Parser_Exception('No entries found'); |
} |
} |
return $this->entries[$offset]; |
} |
/** |
* Return a date in seconds since epoch. |
* |
* Get a date construct. We use PHP's strtotime to return it as a unix datetime, which |
* is the number of seconds since 1970-01-01 00:00:00. |
* |
* @link http://php.net/strtotime |
* @param string $method The name of the date construct we want |
* @param array $arguments Included for compatibility with our __call usage |
* @return int|false datetime |
*/ |
protected function getDate($method, $arguments) { |
$time = $this->model->getElementsByTagName($method); |
if ($time->length == 0 || empty($time->item(0)->nodeValue)) { |
return false; |
} |
return strtotime($time->item(0)->nodeValue); |
} |
/** |
* Get a text construct. |
* |
* @param string $method The name of the text construct we want |
* @param array $arguments Included for compatibility with our __call usage |
* @return string |
*/ |
protected function getText($method, $arguments = array()) { |
$tags = $this->model->getElementsByTagName($method); |
if ($tags->length > 0) { |
$value = $tags->item(0)->nodeValue; |
return $value; |
} |
return false; |
} |
/** |
* Apply various rules to retrieve category data. |
* |
* There is no single way of declaring a category in RSS1/1.1 as there is in RSS2 |
* and Atom. Instead the usual approach is to use the dublin core namespace to |
* declare categories. For example delicious use both: |
* <dc:subject>PEAR</dc:subject> and: <taxo:topics><rdf:Bag> |
* <rdf:li resource="http://del.icio.us/tag/PEAR" /></rdf:Bag></taxo:topics> |
* to declare a categorisation of 'PEAR'. |
* |
* We need to be sensitive to this where possible. |
* |
* @param string $call for compatibility with our overloading |
* @param array $arguments - arg 0 is the offset, arg 1 is whether to return as array |
* @return string|array|false |
*/ |
protected function getCategory($call, $arguments) { |
$categories = $this->model->getElementsByTagName('subject'); |
$offset = empty($arguments[0]) ? 0 : $arguments[0]; |
$array = empty($arguments[1]) ? false : true; |
if ($categories->length <= $offset) { |
return false; |
} |
if ($array) { |
$list = array(); |
foreach ($categories as $category) { |
array_push($list, $category->nodeValue); |
} |
return $list; |
} |
return $categories->item($offset)->nodeValue; |
} |
/** |
* Count occurrences of an element |
* |
* This function will tell us how many times the element $type |
* appears at this level of the feed. |
* |
* @param string $type the element we want to get a count of |
* @return int |
*/ |
protected function count($type) { |
if ($tags = $this->model->getElementsByTagName($type)) { |
return $tags->length; |
} |
return 0; |
} |
/** |
* Part of our xml:base processing code |
* |
* We need a couple of methods to access XHTML content stored in feeds. |
* This is because we dereference all xml:base references before returning |
* the element. This method handles the attributes. |
* |
* @param DOMElement $node The DOM node we are iterating over |
* @return string |
*/ |
function processXHTMLAttributes($node) { |
$return = ''; |
foreach ($node->attributes as $attribute) { |
if ($attribute->name == 'src' or $attribute->name == 'href') { |
$attribute->value = $this->addBase(htmlentities($attribute->value, NULL, 'utf-8'), $attribute); |
} |
if ($attribute->name == 'base') { |
continue; |
} |
$return .= $attribute->name . '="' . htmlentities($attribute->value, NULL, 'utf-8') .'" '; |
} |
if (! empty($return)) { |
return ' ' . trim($return); |
} |
return ''; |
} |
/** |
* Convert HTML entities based on the current character set. |
* |
* @param String |
* @return String |
*/ |
function processEntitiesForNodeValue($node) { |
if (function_exists('iconv')) { |
$current_encoding = $node->ownerDocument->encoding; |
$value = iconv($current_encoding, 'UTF-8', $node->nodeValue); |
} else if ($current_encoding == 'iso-8859-1') { |
$value = utf8_encode($node->nodeValue); |
} else { |
$value = $node->nodeValue; |
} |
$decoded = html_entity_decode($value, NULL, 'UTF-8'); |
return htmlentities($decoded, NULL, 'UTF-8'); |
} |
/** |
* Part of our xml:base processing code |
* |
* We need a couple of methods to access XHTML content stored in feeds. |
* This is because we dereference all xml:base references before returning |
* the element. This method recurs through the tree descending from the node |
* and builds our string. |
* |
* @param DOMElement $node The DOM node we are processing |
* @return string |
*/ |
function traverseNode($node) { |
$content = ''; |
/* Add the opening of this node to the content */ |
if ($node instanceof DOMElement) { |
$content .= '<' . $node->tagName . |
$this->processXHTMLAttributes($node) . '>'; |
} |
/* Process children */ |
if ($node->hasChildNodes()) { |
foreach ($node->childNodes as $child) { |
$content .= $this->traverseNode($child); |
} |
} |
if ($node instanceof DOMText) { |
$content .= $this->processEntitiesForNodeValue($node); |
} |
/* Add the closing of this node to the content */ |
if ($node instanceof DOMElement) { |
$content .= '</' . $node->tagName . '>'; |
} |
return $content; |
} |
/** |
* Get content from RSS feeds (atom has its own implementation) |
* |
* The official way to include full content in an RSS1 entry is to use |
* the content module's element 'encoded', and RSS2 feeds often duplicate that. |
* Often, however, the 'description' element is used instead. We will offer that |
* as a fallback. Atom uses its own approach and overrides this method. |
* |
* @return string|false |
*/ |
protected function getContent() { |
$options = array('encoded', 'description'); |
foreach ($options as $element) { |
$test = $this->model->getElementsByTagName($element); |
if ($test->length == 0) { |
continue; |
} |
if ($test->item(0)->hasChildNodes()) { |
$value = ''; |
foreach ($test->item(0)->childNodes as $child) { |
if ($child instanceof DOMText) { |
$value .= $child->nodeValue; |
} else { |
$simple = simplexml_import_dom($child); |
$value .= $simple->asXML(); |
} |
} |
return $value; |
} else if ($test->length > 0) { |
return $test->item(0)->nodeValue; |
} |
} |
return false; |
} |
/** |
* Checks if this element has a particular child element. |
* |
* @param String |
* @param Integer |
* @return bool |
**/ |
function hasKey($name, $offset = 0) { |
$search = $this->model->getElementsByTagName($name); |
return $search->length > $offset; |
} |
/** |
* Return an XML serialization of the feed, should it be required. Most |
* users however, will already have a serialization that they used when |
* instantiating the object. |
* |
* @return string XML serialization of element |
*/ |
function __toString() { |
$simple = simplexml_import_dom($this->model); |
return $simple->asXML(); |
} |
/** |
* Get directory holding RNG schemas. Method is based on that |
* found in Contact_AddressBook. |
* |
* @return string PEAR data directory. |
* @access public |
* @static |
*/ |
static function getSchemaDir() { |
return dirname(__FILE__).'/../schemas'; |
} |
public function relaxNGValidate() { |
$dir = self::getSchemaDir(); |
$path = $dir . '/' . $this->relax; |
return $this->model->relaxNGValidate($path); |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserRss1Element.php |
---|
New file |
0,0 → 1,111 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS1 Element class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS1Element.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/* |
* This class provides support for RSS 1.0 entries. It will usually be called by |
* XML_Feed_Parser_RSS1 with which it shares many methods. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
*/ |
class XmlFeedParserRss1Element extends XmlFeedParserRss1 { |
/** |
* This will be a reference to the parent object for when we want |
* to use a 'fallback' rule |
* @var XML_Feed_Parser_RSS1 |
*/ |
protected $parent; |
/** |
* Our specific element map |
* @var array |
*/ |
protected $map = array( |
'id' => array('Id'), |
'title' => array('Text'), |
'link' => array('Link'), |
'description' => array('Text'), # or dc:description |
'category' => array('Category'), |
'rights' => array('Text'), # dc:rights |
'creator' => array('Text'), # dc:creator |
'publisher' => array('Text'), # dc:publisher |
'contributor' => array('Text'), # dc:contributor |
'date' => array('Date'), # dc:date |
'content' => array('Content') |
); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS1. |
* @var array |
*/ |
protected $compatMap = array( |
'content' => array('content'), |
'updated' => array('lastBuildDate'), |
'published' => array('date'), |
'subtitle' => array('description'), |
'updated' => array('date'), |
'author' => array('creator'), |
'contributor' => array('contributor') |
); |
/** |
* Store useful information for later. |
* |
* @param DOMElement $element - this item as a DOM element |
* @param XML_Feed_Parser_RSS1 $parent - the feed of which this is a member |
*/ |
function __construct(DOMElement $element, $parent, $xmlBase = '') { |
$this->model = $element; |
$this->parent = $parent; |
} |
/** |
* If an rdf:about attribute is specified, return it as an ID |
* |
* There is no established way of showing an ID for an RSS1 entry. We will |
* simulate it using the rdf:about attribute of the entry element. This cannot |
* be relied upon for unique IDs but may prove useful. |
* |
* @return string|false |
*/ |
function getId() { |
if ($this->model->attributes->getNamedItem('about')) { |
return $this->model->attributes->getNamedItem('about')->nodeValue; |
} |
return false; |
} |
/** |
* How RSS1 should support for enclosures is not clear. For now we will return |
* false. |
* |
* @return false |
*/ |
function getEnclosure() { |
return false; |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserRss11Element.php |
---|
New file |
0,0 → 1,145 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS1 Element class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS11Element.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/* |
* This class provides support for RSS 1.1 entries. It will usually be called by |
* XML_Feed_Parser_RSS11 with which it shares many methods. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
*/ |
class XmlFeedParserRss11Element extends XmlFeedParserRss11 { |
/** |
* This will be a reference to the parent object for when we want |
* to use a 'fallback' rule |
* @var XML_Feed_Parser_RSS1 |
*/ |
protected $parent; |
/** |
* Our specific element map |
* @var array |
*/ |
protected $map = array( |
'id' => array('Id'), |
'title' => array('Text'), |
'link' => array('Link'), |
'description' => array('Text'), # or dc:description |
'category' => array('Category'), |
'rights' => array('Text'), # dc:rights |
'creator' => array('Text'), # dc:creator |
'publisher' => array('Text'), # dc:publisher |
'contributor' => array('Text'), # dc:contributor |
'date' => array('Date'), # dc:date |
'content' => array('Content') |
); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS1. |
* @var array |
*/ |
protected $compatMap = array( |
'content' => array('content'), |
'updated' => array('lastBuildDate'), |
'published' => array('date'), |
'subtitle' => array('description'), |
'updated' => array('date'), |
'author' => array('creator'), |
'contributor' => array('contributor') |
); |
/** |
* Store useful information for later. |
* |
* @param DOMElement $element - this item as a DOM element |
* @param XML_Feed_Parser_RSS1 $parent - the feed of which this is a member |
*/ |
function __construct(DOMElement $element, $parent, $xmlBase = '') { |
$this->model = $element; |
$this->parent = $parent; |
} |
/** |
* If an rdf:about attribute is specified, return that as an ID |
* |
* There is no established way of showing an ID for an RSS1 entry. We will |
* simulate it using the rdf:about attribute of the entry element. This cannot |
* be relied upon for unique IDs but may prove useful. |
* |
* @return string|false |
*/ |
function getId() { |
if ($this->model->attributes->getNamedItem('about')) { |
return $this->model->attributes->getNamedItem('about')->nodeValue; |
} |
return false; |
} |
/** |
* Return the entry's content |
* |
* The official way to include full content in an RSS1 entry is to use |
* the content module's element 'encoded'. Often, however, the 'description' |
* element is used instead. We will offer that as a fallback. |
* |
* @return string|false |
*/ |
function getContent() { |
$options = array('encoded', 'description'); |
foreach ($options as $element) { |
$test = $this->model->getElementsByTagName($element); |
if ($test->length == 0) { |
continue; |
} |
if ($test->item(0)->hasChildNodes()) { |
$value = ''; |
foreach ($test->item(0)->childNodes as $child) { |
if ($child instanceof DOMText) { |
$value .= $child->nodeValue; |
} else { |
$simple = simplexml_import_dom($child); |
$value .= $simple->asXML(); |
} |
} |
return $value; |
} else if ($test->length > 0) { |
return $test->item(0)->nodeValue; |
} |
} |
return false; |
} |
/** |
* How RSS1.1 should support for enclosures is not clear. For now we will return |
* false. |
* |
* @return false |
*/ |
function getEnclosure() { |
return false; |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserRss2Element.php |
---|
New file |
0,0 → 1,166 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Class representing entries in an RSS2 feed. |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS2Element.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class provides support for RSS 2.0 entries. It will usually be |
* called by XML_Feed_Parser_RSS2 with which it shares many methods. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
*/ |
class XmlFeedParserRss2Element extends XmlFeedParserRss2 { |
/** |
* This will be a reference to the parent object for when we want |
* to use a 'fallback' rule |
* @var XML_Feed_Parser_RSS2 |
*/ |
protected $parent; |
/** |
* Our specific element map |
* @var array |
*/ |
protected $map = array( |
'title' => array('Text'), |
'guid' => array('Guid'), |
'description' => array('Text'), |
'author' => array('Text'), |
'comments' => array('Text'), |
'enclosure' => array('Enclosure'), |
'pubDate' => array('Date'), |
'source' => array('Source'), |
'link' => array('Text'), |
'content' => array('Content')); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS2. |
* @var array |
*/ |
protected $compatMap = array( |
'id' => array('guid'), |
'updated' => array('lastBuildDate'), |
'published' => array('pubdate'), |
'guidislink' => array('guid', 'ispermalink'), |
'summary' => array('description')); |
/** |
* Store useful information for later. |
* |
* @param DOMElement $element - this item as a DOM element |
* @param XML_Feed_Parser_RSS2 $parent - the feed of which this is a member |
*/ |
function __construct(DOMElement $element, $parent, $xmlBase = '') { |
$this->model = $element; |
$this->parent = $parent; |
} |
/** |
* Get the value of the guid element, if specified |
* |
* guid is the closest RSS2 has to atom's ID. It is usually but not always a |
* URI. The one attribute that RSS2 can posess is 'ispermalink' which specifies |
* whether the guid is itself dereferencable. Use of guid is not obligatory, |
* but is advisable. To get the guid you would call $item->id() (for atom |
* compatibility) or $item->guid(). To check if this guid is a permalink call |
* $item->guid("ispermalink"). |
* |
* @param string $method - the method name being called |
* @param array $params - parameters required |
* @return string the guid or value of ispermalink |
*/ |
protected function getGuid($method, $params) { |
$attribute = (isset($params[0]) and $params[0] == 'ispermalink') ? |
true : false; |
$tag = $this->model->getElementsByTagName('guid'); |
if ($tag->length > 0) { |
if ($attribute) { |
if ($tag->hasAttribute("ispermalink")) { |
return $tag->getAttribute("ispermalink"); |
} |
} |
return $tag->item(0)->nodeValue; |
} |
return false; |
} |
/** |
* Access details of file enclosures |
* |
* The RSS2 spec is ambiguous as to whether an enclosure element must be |
* unique in a given entry. For now we will assume it needn't, and allow |
* for an offset. |
* |
* @param string $method - the method being called |
* @param array $parameters - we expect the first of these to be our offset |
* @return array|false |
*/ |
protected function getEnclosure($method, $parameters) { |
$encs = $this->model->getElementsByTagName('enclosure'); |
$offset = isset($parameters[0]) ? $parameters[0] : 0; |
if ($encs->length > $offset) { |
try { |
if (! $encs->item($offset)->hasAttribute('url')) { |
return false; |
} |
$attrs = $encs->item($offset)->attributes; |
return array( |
'url' => $attrs->getNamedItem('url')->value, |
'length' => $attrs->getNamedItem('length')->value, |
'type' => $attrs->getNamedItem('type')->value); |
} catch (Exception $e) { |
return false; |
} |
} |
return false; |
} |
/** |
* Get the entry source if specified |
* |
* source is an optional sub-element of item. Like atom:source it tells |
* us about where the entry came from (eg. if it's been copied from another |
* feed). It is not a rich source of metadata in the same way as atom:source |
* and while it would be good to maintain compatibility by returning an |
* XML_Feed_Parser_RSS2 element, it makes a lot more sense to return an array. |
* |
* @return array|false |
*/ |
protected function getSource() { |
$get = $this->model->getElementsByTagName('source'); |
if ($get->length) { |
$source = $get->item(0); |
$array = array( |
'content' => $source->nodeValue); |
foreach ($source->attributes as $attribute) { |
$array[$attribute->name] = $attribute->value; |
} |
return $array; |
} |
return false; |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserRss1.php |
---|
New file |
0,0 → 1,267 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS1 class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS1.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class handles RSS1.0 feeds. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
* @todo Find a Relax NG URI we can use |
*/ |
class XmlFeedParserRss1 extends XmlFeedParserType { |
/** |
* The URI of the RelaxNG schema used to (optionally) validate the feed |
* @var string |
*/ |
protected $relax = 'rss10.rng'; |
/** |
* We're likely to use XPath, so let's keep it global |
* @var DOMXPath |
*/ |
protected $xpath; |
/** |
* The feed type we are parsing |
* @var string |
*/ |
public $version = 'RSS 1.0'; |
/** |
* The class used to represent individual items |
* @var string |
*/ |
protected $itemClass = 'XmlFeedParserRss1Element'; |
/** |
* The element containing entries |
* @var string |
*/ |
protected $itemElement = 'item'; |
/** |
* Here we map those elements we're not going to handle individually |
* to the constructs they are. The optional second parameter in the array |
* tells the parser whether to 'fall back' (not apt. at the feed level) or |
* fail if the element is missing. If the parameter is not set, the function |
* will simply return false and leave it to the client to decide what to do. |
* @var array |
*/ |
protected $map = array( |
'title' => array('Text'), |
'link' => array('Text'), |
'description' => array('Text'), |
'image' => array('Image'), |
'textinput' => array('TextInput'), |
'updatePeriod' => array('Text'), |
'updateFrequency' => array('Text'), |
'updateBase' => array('Date'), |
'rights' => array('Text'), # dc:rights |
'description' => array('Text'), # dc:description |
'creator' => array('Text'), # dc:creator |
'publisher' => array('Text'), # dc:publisher |
'contributor' => array('Text'), # dc:contributor |
'date' => array('Date') # dc:contributor |
); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS2. |
* @var array |
*/ |
protected $compatMap = array( |
'title' => array('title'), |
'link' => array('link'), |
'subtitle' => array('description'), |
'author' => array('creator'), |
'updated' => array('date')); |
/** |
* We will be working with multiple namespaces and it is useful to |
* keep them together |
* @var array |
*/ |
protected $namespaces = array( |
'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', |
'rss' => 'http://purl.org/rss/1.0/', |
'dc' => 'http://purl.org/rss/1.0/modules/dc/', |
'content' => 'http://purl.org/rss/1.0/modules/content/', |
'sy' => 'http://web.resource.org/rss/1.0/modules/syndication/'); |
/** |
* Our constructor does nothing more than its parent. |
* |
* @param DOMDocument $xml A DOM object representing the feed |
* @param bool (optional) $string Whether or not to validate this feed |
*/ |
function __construct(DOMDocument $model, $strict = false) { |
$this->model = $model; |
if ($strict) { |
if (! $this->relaxNGValidate()) { |
throw new XML_Feed_Parser_Exception('Failed required validation'); |
} |
} |
$this->xpath = new DOMXPath($model); |
foreach ($this->namespaces as $key => $value) { |
$this->xpath->registerNamespace($key, $value); |
} |
$this->numberEntries = $this->count('item'); |
} |
/** |
* Allows retrieval of an entry by ID where the rdf:about attribute is used |
* |
* This is not really something that will work with RSS1 as it does not have |
* clear restrictions on the global uniqueness of IDs. We will employ the |
* _very_ hit and miss method of selecting entries based on the rdf:about |
* attribute. If DOMXPath::evaluate is available, we also use that to store |
* a reference to the entry in the array used by getEntryByOffset so that |
* method does not have to seek out the entry if it's requested that way. |
* |
* @param string $id any valid ID. |
* @return XML_Feed_Parser_RSS1Element |
*/ |
function getEntryById($id) { |
if (isset($this->idMappings[$id])) { |
return $this->entries[$this->idMappings[$id]]; |
} |
$entries = $this->xpath->query("//rss:item[@rdf:about='$id']"); |
if ($entries->length > 0) { |
$classname = $this->itemClass; |
$entry = new $classname($entries->item(0), $this); |
if (in_array('evaluate', get_class_methods($this->xpath))) { |
$offset = $this->xpath->evaluate("count(preceding-sibling::rss:item)", $entries->item(0)); |
$this->entries[$offset] = $entry; |
} |
$this->idMappings[$id] = $entry; |
return $entry; |
} |
return false; |
} |
/** |
* Get details of the image associated with the feed. |
* |
* @return array|false an array simply containing the child elements |
*/ |
protected function getImage() { |
$images = $this->model->getElementsByTagName('image'); |
if ($images->length > 0) { |
$image = $images->item(0); |
$details = array(); |
if ($image->hasChildNodes()) { |
$details = array( |
'title' => $image->getElementsByTagName('title')->item(0)->value, |
'link' => $image->getElementsByTagName('link')->item(0)->value, |
'url' => $image->getElementsByTagName('url')->item(0)->value); |
} else { |
$details = array('title' => false, |
'link' => false, |
'url' => $image->attributes->getNamedItem('resource')->nodeValue); |
} |
$details = array_merge($details, array('description' => false, 'height' => false, 'width' => false)); |
if (! empty($details)) { |
return $details; |
} |
} |
return false; |
} |
/** |
* The textinput element is little used, but in the interests of |
* completeness we will support it. |
* |
* @return array|false |
*/ |
protected function getTextInput() { |
$inputs = $this->model->getElementsByTagName('textinput'); |
if ($inputs->length > 0) { |
$input = $inputs->item(0); |
$results = array(); |
$results['title'] = isset( |
$input->getElementsByTagName('title')->item(0)->value) ? |
$input->getElementsByTagName('title')->item(0)->value : null; |
$results['description'] = isset( |
$input->getElementsByTagName('description')->item(0)->value) ? |
$input->getElementsByTagName('description')->item(0)->value : null; |
$results['name'] = isset( |
$input->getElementsByTagName('name')->item(0)->value) ? |
$input->getElementsByTagName('name')->item(0)->value : null; |
$results['link'] = isset( |
$input->getElementsByTagName('link')->item(0)->value) ? |
$input->getElementsByTagName('link')->item(0)->value : null; |
if (empty($results['link']) and |
$input->attributes->getNamedItem('resource')) { |
$results['link'] = |
$input->attributes->getNamedItem('resource')->nodeValue; |
} |
if (! empty($results)) { |
return $results; |
} |
} |
return false; |
} |
/** |
* Employs various techniques to identify the author |
* |
* Dublin Core provides the dc:creator, dc:contributor, and dc:publisher |
* elements for defining authorship in RSS1. We will try each of those in |
* turn in order to simulate the atom author element and will return it |
* as text. |
* |
* @return array|false |
*/ |
function getAuthor() { |
$options = array('creator', 'contributor', 'publisher'); |
foreach ($options as $element) { |
$test = $this->model->getElementsByTagName($element); |
if ($test->length > 0) { |
return $test->item(0)->value; |
} |
} |
return false; |
} |
/** |
* Retrieve a link |
* |
* In RSS1 a link is a text element but in order to ensure that we resolve |
* URLs properly we have a special function for them. |
* |
* @return string |
*/ |
function getLink($offset = 0, $attribute = 'href', $params = false) { |
$links = $this->model->getElementsByTagName('link'); |
if ($links->length <= $offset) { |
return false; |
} |
$link = $links->item($offset); |
return $this->addBase($link->nodeValue, $link); |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserRss11.php |
---|
New file |
0,0 → 1,266 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS1.1 class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS11.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class handles RSS1.1 feeds. RSS1.1 is documented at: |
* http://inamidst.com/rss1.1/ |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
* @todo Support for RDF:List |
* @todo Ensure xml:lang is accessible to users |
*/ |
class XmlFeedParserRss11 extends XmlFeedParserType { |
/** |
* The URI of the RelaxNG schema used to (optionally) validate the feed |
* @var string |
*/ |
protected $relax = 'rss11.rng'; |
/** |
* We're likely to use XPath, so let's keep it global |
* @var DOMXPath |
*/ |
protected $xpath; |
/** |
* The feed type we are parsing |
* @var string |
*/ |
public $version = 'RSS 1.0'; |
/** |
* The class used to represent individual items |
* @var string |
*/ |
protected $itemClass = 'XmlFeedParserRss11Element'; |
/** |
* The element containing entries |
* @var string |
*/ |
protected $itemElement = 'item'; |
/** |
* Here we map those elements we're not going to handle individually |
* to the constructs they are. The optional second parameter in the array |
* tells the parser whether to 'fall back' (not apt. at the feed level) or |
* fail if the element is missing. If the parameter is not set, the function |
* will simply return false and leave it to the client to decide what to do. |
* @var array |
*/ |
protected $map = array( |
'title' => array('Text'), |
'link' => array('Text'), |
'description' => array('Text'), |
'image' => array('Image'), |
'updatePeriod' => array('Text'), |
'updateFrequency' => array('Text'), |
'updateBase' => array('Date'), |
'rights' => array('Text'), # dc:rights |
'description' => array('Text'), # dc:description |
'creator' => array('Text'), # dc:creator |
'publisher' => array('Text'), # dc:publisher |
'contributor' => array('Text'), # dc:contributor |
'date' => array('Date') # dc:contributor |
); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS2. |
* @var array |
*/ |
protected $compatMap = array( |
'title' => array('title'), |
'link' => array('link'), |
'subtitle' => array('description'), |
'author' => array('creator'), |
'updated' => array('date')); |
/** |
* We will be working with multiple namespaces and it is useful to |
* keep them together. We will retain support for some common RSS1.0 modules |
* @var array |
*/ |
protected $namespaces = array( |
'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', |
'rss' => 'http://purl.org/net/rss1.1#', |
'dc' => 'http://purl.org/rss/1.0/modules/dc/', |
'content' => 'http://purl.org/rss/1.0/modules/content/', |
'sy' => 'http://web.resource.org/rss/1.0/modules/syndication/'); |
/** |
* Our constructor does nothing more than its parent. |
* |
* @param DOMDocument $xml A DOM object representing the feed |
* @param bool (optional) $string Whether or not to validate this feed |
*/ |
function __construct(DOMDocument $model, $strict = false) { |
$this->model = $model; |
if ($strict) { |
if (! $this->relaxNGValidate()) { |
throw new XML_Feed_Parser_Exception('Failed required validation'); |
} |
} |
$this->xpath = new DOMXPath($model); |
foreach ($this->namespaces as $key => $value) { |
$this->xpath->registerNamespace($key, $value); |
} |
$this->numberEntries = $this->count('item'); |
} |
/** |
* Attempts to identify an element by ID given by the rdf:about attribute |
* |
* This is not really something that will work with RSS1.1 as it does not have |
* clear restrictions on the global uniqueness of IDs. We will employ the |
* _very_ hit and miss method of selecting entries based on the rdf:about |
* attribute. Please note that this is even more hit and miss with RSS1.1 than |
* with RSS1.0 since RSS1.1 does not require the rdf:about attribute for items. |
* |
* @param string $id any valid ID. |
* @return XML_Feed_Parser_RSS1Element |
*/ |
function getEntryById($id) { |
if (isset($this->idMappings[$id])) { |
return $this->entries[$this->idMappings[$id]]; |
} |
$entries = $this->xpath->query("//rss:item[@rdf:about='$id']"); |
if ($entries->length > 0) { |
$classname = $this->itemClass; |
$entry = new $classname($entries->item(0), $this); |
return $entry; |
} |
return false; |
} |
/** |
* Get details of the image associated with the feed. |
* |
* @return array|false an array simply containing the child elements |
*/ |
protected function getImage() { |
$images = $this->model->getElementsByTagName('image'); |
if ($images->length > 0) { |
$image = $images->item(0); |
$details = array(); |
if ($image->hasChildNodes()) { |
$details = array( |
'title' => $image->getElementsByTagName('title')->item(0)->value, |
'url' => $image->getElementsByTagName('url')->item(0)->value); |
if ($image->getElementsByTagName('link')->length > 0) { |
$details['link'] = |
$image->getElementsByTagName('link')->item(0)->value; |
} |
} else { |
$details = array('title' => false, |
'link' => false, |
'url' => $image->attributes->getNamedItem('resource')->nodeValue); |
} |
$details = array_merge($details, |
array('description' => false, 'height' => false, 'width' => false)); |
if (! empty($details)) { |
return $details; |
} |
} |
return false; |
} |
/** |
* The textinput element is little used, but in the interests of |
* completeness we will support it. |
* |
* @return array|false |
*/ |
protected function getTextInput() { |
$inputs = $this->model->getElementsByTagName('textinput'); |
if ($inputs->length > 0) { |
$input = $inputs->item(0); |
$results = array(); |
$results['title'] = isset( |
$input->getElementsByTagName('title')->item(0)->value) ? |
$input->getElementsByTagName('title')->item(0)->value : null; |
$results['description'] = isset( |
$input->getElementsByTagName('description')->item(0)->value) ? |
$input->getElementsByTagName('description')->item(0)->value : null; |
$results['name'] = isset( |
$input->getElementsByTagName('name')->item(0)->value) ? |
$input->getElementsByTagName('name')->item(0)->value : null; |
$results['link'] = isset( |
$input->getElementsByTagName('link')->item(0)->value) ? |
$input->getElementsByTagName('link')->item(0)->value : null; |
if (empty($results['link']) and |
$input->attributes->getNamedItem('resource')) { |
$results['link'] = $input->attributes->getNamedItem('resource')->nodeValue; |
} |
if (! empty($results)) { |
return $results; |
} |
} |
return false; |
} |
/** |
* Attempts to discern authorship |
* |
* Dublin Core provides the dc:creator, dc:contributor, and dc:publisher |
* elements for defining authorship in RSS1. We will try each of those in |
* turn in order to simulate the atom author element and will return it |
* as text. |
* |
* @return array|false |
*/ |
function getAuthor() { |
$options = array('creator', 'contributor', 'publisher'); |
foreach ($options as $element) { |
$test = $this->model->getElementsByTagName($element); |
if ($test->length > 0) { |
return $test->item(0)->value; |
} |
} |
return false; |
} |
/** |
* Retrieve a link |
* |
* In RSS1 a link is a text element but in order to ensure that we resolve |
* URLs properly we have a special function for them. |
* |
* @return string |
*/ |
function getLink($offset = 0, $attribute = 'href', $params = false) { |
$links = $this->model->getElementsByTagName('link'); |
if ($links->length <= $offset) { |
return false; |
} |
$link = $links->item($offset); |
return $this->addBase($link->nodeValue, $link); |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserRss2.php |
---|
New file |
0,0 → 1,323 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Class representing feed-level data for an RSS2 feed |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS2.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class handles RSS2 feeds. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
*/ |
class XmlFeedParserRss2 extends XmlFeedParserType { |
/** |
* The URI of the RelaxNG schema used to (optionally) validate the feed |
* @var string |
*/ |
protected $relax = 'rss20.rng'; |
/** |
* We're likely to use XPath, so let's keep it global |
* @var DOMXPath |
*/ |
protected $xpath; |
/** |
* The feed type we are parsing |
* @var string |
*/ |
public $version = 'RSS 2.0'; |
/** |
* The class used to represent individual items |
* @var string |
*/ |
protected $itemClass = 'XmlFeedParserRss2Element'; |
/** |
* The element containing entries |
* @var string |
*/ |
protected $itemElement = 'item'; |
/** |
* Here we map those elements we're not going to handle individually |
* to the constructs they are. The optional second parameter in the array |
* tells the parser whether to 'fall back' (not apt. at the feed level) or |
* fail if the element is missing. If the parameter is not set, the function |
* will simply return false and leave it to the client to decide what to do. |
* @var array |
*/ |
protected $map = array( |
'ttl' => array('Text'), |
'pubDate' => array('Date'), |
'lastBuildDate' => array('Date'), |
'title' => array('Text'), |
'link' => array('Link'), |
'description' => array('Text'), |
'language' => array('Text'), |
'copyright' => array('Text'), |
'managingEditor' => array('Text'), |
'webMaster' => array('Text'), |
'category' => array('Text'), |
'generator' => array('Text'), |
'docs' => array('Text'), |
'ttl' => array('Text'), |
'image' => array('Image'), |
'skipDays' => array('skipDays'), |
'skipHours' => array('skipHours')); |
/** |
* Here we map some elements to their atom equivalents. This is going to be |
* quite tricky to pull off effectively (and some users' methods may vary) |
* but is worth trying. The key is the atom version, the value is RSS2. |
* @var array |
*/ |
protected $compatMap = array( |
'title' => array('title'), |
'rights' => array('copyright'), |
'updated' => array('lastBuildDate'), |
'subtitle' => array('description'), |
'date' => array('pubDate'), |
'author' => array('managingEditor')); |
protected $namespaces = array( |
'dc' => 'http://purl.org/rss/1.0/modules/dc/', |
'content' => 'http://purl.org/rss/1.0/modules/content/'); |
/** |
* Our constructor does nothing more than its parent. |
* |
* @param DOMDocument $xml A DOM object representing the feed |
* @param bool (optional) $string Whether or not to validate this feed |
*/ |
function __construct(DOMDocument $model, $strict = false) { |
$this->model = $model; |
if ($strict) { |
if (! $this->relaxNGValidate()) { |
throw new XmlFeedParserException('Failed required validation'); |
} |
} |
$this->xpath = new DOMXPath($this->model); |
foreach ($this->namespaces as $key => $value) { |
$this->xpath->registerNamespace($key, $value); |
} |
$this->numberEntries = $this->count('item'); |
} |
/** |
* Retrieves an entry by ID, if the ID is specified with the guid element |
* |
* This is not really something that will work with RSS2 as it does not have |
* clear restrictions on the global uniqueness of IDs. But we can emulate |
* it by allowing access based on the 'guid' element. If DOMXPath::evaluate |
* is available, we also use that to store a reference to the entry in the array |
* used by getEntryByOffset so that method does not have to seek out the entry |
* if it's requested that way. |
* |
* @param string $id any valid ID. |
* @return XML_Feed_Parser_RSS2Element |
*/ |
function getEntryById($id) { |
if (isset($this->idMappings[$id])) { |
return $this->entries[$this->idMappings[$id]]; |
} |
$entries = $this->xpath->query("//item[guid='$id']"); |
if ($entries->length > 0) { |
$entry = new $this->itemElement($entries->item(0), $this); |
if (in_array('evaluate', get_class_methods($this->xpath))) { |
$offset = $this->xpath->evaluate("count(preceding-sibling::item)", $entries->item(0)); |
$this->entries[$offset] = $entry; |
} |
$this->idMappings[$id] = $entry; |
return $entry; |
} |
} |
/** |
* Get a category from the element |
* |
* The category element is a simple text construct which can occur any number |
* of times. We allow access by offset or access to an array of results. |
* |
* @param string $call for compatibility with our overloading |
* @param array $arguments - arg 0 is the offset, arg 1 is whether to return as array |
* @return string|array|false |
*/ |
function getCategory($call, $arguments = array()) { |
$categories = $this->model->getElementsByTagName('category'); |
$offset = empty($arguments[0]) ? 0 : $arguments[0]; |
$array = empty($arguments[1]) ? false : true; |
if ($categories->length <= $offset) { |
return false; |
} |
if ($array) { |
$list = array(); |
foreach ($categories as $category) { |
array_push($list, $category->nodeValue); |
} |
return $list; |
} |
return $categories->item($offset)->nodeValue; |
} |
/** |
* Get details of the image associated with the feed. |
* |
* @return array|false an array simply containing the child elements |
*/ |
protected function getImage() { |
$images = $this->xpath->query("//image"); |
if ($images->length > 0) { |
$image = $images->item(0); |
$desc = $image->getElementsByTagName('description'); |
$description = $desc->length ? $desc->item(0)->nodeValue : false; |
$heigh = $image->getElementsByTagName('height'); |
$height = $heigh->length ? $heigh->item(0)->nodeValue : false; |
$widt = $image->getElementsByTagName('width'); |
$width = $widt->length ? $widt->item(0)->nodeValue : false; |
return array( |
'title' => $image->getElementsByTagName('title')->item(0)->nodeValue, |
'link' => $image->getElementsByTagName('link')->item(0)->nodeValue, |
'url' => $image->getElementsByTagName('url')->item(0)->nodeValue, |
'description' => $description, |
'height' => $height, |
'width' => $width); |
} |
return false; |
} |
/** |
* The textinput element is little used, but in the interests of |
* completeness... |
* |
* @return array|false |
*/ |
function getTextInput() { |
$inputs = $this->model->getElementsByTagName('input'); |
if ($inputs->length > 0) { |
$input = $inputs->item(0); |
return array( |
'title' => $input->getElementsByTagName('title')->item(0)->value, |
'description' => |
$input->getElementsByTagName('description')->item(0)->value, |
'name' => $input->getElementsByTagName('name')->item(0)->value, |
'link' => $input->getElementsByTagName('link')->item(0)->value); |
} |
return false; |
} |
/** |
* Utility function for getSkipDays and getSkipHours |
* |
* This is a general function used by both getSkipDays and getSkipHours. It simply |
* returns an array of the values of the children of the appropriate tag. |
* |
* @param string $tagName The tag name (getSkipDays or getSkipHours) |
* @return array|false |
*/ |
protected function getSkips($tagName) { |
$hours = $this->model->getElementsByTagName($tagName); |
if ($hours->length == 0) { |
return false; |
} |
$skipHours = array(); |
foreach($hours->item(0)->childNodes as $hour) { |
if ($hour instanceof DOMElement) { |
array_push($skipHours, $hour->nodeValue); |
} |
} |
return $skipHours; |
} |
/** |
* Retrieve skipHours data |
* |
* The skiphours element provides a list of hours on which this feed should |
* not be checked. We return an array of those hours (integers, 24 hour clock) |
* |
* @return array |
*/ |
function getSkipHours() { |
return $this->getSkips('skipHours'); |
} |
/** |
* Retrieve skipDays data |
* |
* The skipdays element provides a list of days on which this feed should |
* not be checked. We return an array of those days. |
* |
* @return array |
*/ |
function getSkipDays() { |
return $this->getSkips('skipDays'); |
} |
/** |
* Return content of the little-used 'cloud' element |
* |
* The cloud element is rarely used. It is designed to provide some details |
* of a location to update the feed. |
* |
* @return array an array of the attributes of the element |
*/ |
function getCloud() { |
$cloud = $this->model->getElementsByTagName('cloud'); |
if ($cloud->length == 0) { |
return false; |
} |
$cloudData = array(); |
foreach ($cloud->item(0)->attributes as $attribute) { |
$cloudData[$attribute->name] = $attribute->value; |
} |
return $cloudData; |
} |
/** |
* Get link URL |
* |
* In RSS2 a link is a text element but in order to ensure that we resolve |
* URLs properly we have a special function for them. We maintain the |
* parameter used by the atom getLink method, though we only use the offset |
* parameter. |
* |
* @param int $offset The position of the link within the feed. Starts from 0 |
* @param string $attribute The attribute of the link element required |
* @param array $params An array of other parameters. Not used. |
* @return string |
*/ |
function getLink($offset, $attribute = 'href', $params = array()) { |
$links = $this->model->getElementsByTagName('link'); |
if ($links->length <= $offset) { |
return false; |
} |
$link = $links->item($offset); |
return $this->addBase($link->nodeValue, $link); |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserAtomElement.php |
---|
New file |
0,0 → 1,254 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* AtomElement class for XML_Feed_Parser package |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: AtomElement.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* This class provides support for atom entries. It will usually be called by |
* XML_Feed_Parser_Atom with which it shares many methods. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
*/ |
class XmlFeedParserAtomElement extends XmlFeedParserAtom { |
/** |
* This will be a reference to the parent object for when we want |
* to use a 'fallback' rule |
* @var XML_Feed_Parser_Atom |
*/ |
protected $parent; |
/** |
* When performing XPath queries we will use this prefix |
* @var string |
*/ |
private $xpathPrefix = ''; |
/** |
* xml:base values inherited by the element |
* @var string |
*/ |
protected $xmlBase; |
/** |
* Here we provide a few mappings for those very special circumstances in |
* which it makes sense to map back to the RSS2 spec or to manage other |
* compatibilities (eg. with the Univeral Feed Parser). Key is the other version's |
* name for the command, value is an array consisting of the equivalent in our atom |
* api and any attributes needed to make the mapping. |
* @var array |
*/ |
protected $compatMap = array( |
'guid' => array('id'), |
'links' => array('link'), |
'tags' => array('category'), |
'contributors' => array('contributor')); |
/** |
* Our specific element map |
* @var array |
*/ |
protected $map = array( |
'author' => array('Person', 'fallback'), |
'contributor' => array('Person'), |
'id' => array('Text', 'fail'), |
'published' => array('Date'), |
'updated' => array('Date', 'fail'), |
'title' => array('Text', 'fail'), |
'rights' => array('Text', 'fallback'), |
'summary' => array('Text'), |
'content' => array('Content'), |
'link' => array('Link'), |
'enclosure' => array('Enclosure'), |
'category' => array('Category')); |
/** |
* Store useful information for later. |
* |
* @param DOMElement $element - this item as a DOM element |
* @param XML_Feed_Parser_Atom $parent - the feed of which this is a member |
*/ |
function __construct(DOMElement $element, $parent, $xmlBase = '') { |
$this->model = $element; |
$this->parent = $parent; |
$this->xmlBase = $xmlBase; |
$this->xpathPrefix = "//atom:entry[atom:id='" . $this->id . "']/"; |
$this->xpath = $this->parent->xpath; |
} |
/** |
* Provides access to specific aspects of the author data for an atom entry |
* |
* Author data at the entry level is more complex than at the feed level. |
* If atom:author is not present for the entry we need to look for it in |
* an atom:source child of the atom:entry. If it's not there either, then |
* we look to the parent for data. |
* |
* @param array |
* @return string |
*/ |
function getAuthor($arguments) { |
/* Find out which part of the author data we're looking for */ |
if (isset($arguments['param'])) { |
$parameter = $arguments['param']; |
} else { |
$parameter = 'name'; |
} |
$test = $this->model->getElementsByTagName('author'); |
if ($test->length > 0) { |
$item = $test->item(0); |
return $item->getElementsByTagName($parameter)->item(0)->nodeValue; |
} |
$source = $this->model->getElementsByTagName('source'); |
if ($source->length > 0) { |
$test = $this->model->getElementsByTagName('author'); |
if ($test->length > 0) { |
$item = $test->item(0); |
return $item->getElementsByTagName($parameter)->item(0)->nodeValue; |
} |
} |
return $this->parent->getAuthor($arguments); |
} |
/** |
* Returns the content of the content element or info on a specific attribute |
* |
* This element may or may not be present. It cannot be present more than |
* once. It may have a 'src' attribute, in which case there's no content |
* If not present, then the entry must have link with rel="alternate". |
* If there is content we return it, if not and there's a 'src' attribute |
* we return the value of that instead. The method can take an 'attribute' |
* argument, in which case we return the value of that attribute if present. |
* eg. $item->content("type") will return the type of the content. It is |
* recommended that all users check the type before getting the content to |
* ensure that their script is capable of handling the type of returned data. |
* (data carried in the content element can be either 'text', 'html', 'xhtml', |
* or any standard MIME type). |
* |
* @return string|false |
*/ |
protected function getContent($method, $arguments = array()) { |
$attribute = empty($arguments[0]) ? false : $arguments[0]; |
$tags = $this->model->getElementsByTagName('content'); |
if ($tags->length == 0) { |
return false; |
} |
$content = $tags->item(0); |
if (! $content->hasAttribute('type')) { |
$content->setAttribute('type', 'text'); |
} |
if (! empty($attribute)) { |
return $content->getAttribute($attribute); |
} |
$type = $content->getAttribute('type'); |
if (! empty($attribute)) { |
if ($content->hasAttribute($attribute)) |
{ |
return $content->getAttribute($attribute); |
} |
return false; |
} |
if ($content->hasAttribute('src')) { |
return $content->getAttribute('src'); |
} |
return $this->parseTextConstruct($content); |
} |
/** |
* For compatibility, this method provides a mapping to access enclosures. |
* |
* The Atom spec doesn't provide for an enclosure element, but it is |
* generally supported using the link element with rel='enclosure'. |
* |
* @param string $method - for compatibility with our __call usage |
* @param array $arguments - for compatibility with our __call usage |
* @return array|false |
*/ |
function getEnclosure($method, $arguments = array()) { |
$offset = isset($arguments[0]) ? $arguments[0] : 0; |
$query = "//atom:entry[atom:id='" . $this->getText('id', false) . |
"']/atom:link[@rel='enclosure']"; |
$encs = $this->parent->xpath->query($query); |
if ($encs->length > $offset) { |
try { |
if (! $encs->item($offset)->hasAttribute('href')) { |
return false; |
} |
$attrs = $encs->item($offset)->attributes; |
$length = $encs->item($offset)->hasAttribute('length') ? |
$encs->item($offset)->getAttribute('length') : false; |
return array( |
'url' => $attrs->getNamedItem('href')->value, |
'type' => $attrs->getNamedItem('type')->value, |
'length' => $length); |
} catch (Exception $e) { |
return false; |
} |
} |
return false; |
} |
/** |
* Get details of this entry's source, if available/relevant |
* |
* Where an atom:entry is taken from another feed then the aggregator |
* is supposed to include an atom:source element which replicates at least |
* the atom:id, atom:title, and atom:updated metadata from the original |
* feed. Atom:source therefore has a very similar structure to atom:feed |
* and if we find it we will return it as an XML_Feed_Parser_Atom object. |
* |
* @return XML_Feed_Parser_Atom|false |
*/ |
function getSource() { |
$test = $this->model->getElementsByTagName('source'); |
if ($test->length == 0) { |
return false; |
} |
$source = new XML_Feed_Parser_Atom($test->item(0)); |
} |
/** |
* Get the entry as an XML string |
* |
* Return an XML serialization of the feed, should it be required. Most |
* users however, will already have a serialization that they used when |
* instantiating the object. |
* |
* @return string XML serialization of element |
*/ |
function __toString() { |
$simple = simplexml_import_dom($this->model); |
return $simple->asXML(); |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserRss09Element.php |
---|
New file |
0,0 → 1,59 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* RSS0.9 Element class for XML_Feed_Parser |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL 2.1 |
* @version CVS: $Id: RSS09Element.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/* |
* This class provides support for RSS 0.9 entries. It will usually be called by |
* XML_Feed_Parser_RSS09 with which it shares many methods. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
*/ |
class XmlFeedParserRss09Element extends XmlFeedParserRss09 { |
/** |
* This will be a reference to the parent object for when we want |
* to use a 'fallback' rule |
* @var XML_Feed_Parser_RSS09 |
*/ |
protected $parent; |
/** |
* Our specific element map |
* @var array |
*/ |
protected $map = array( |
'title' => array('Text'), |
'link' => array('Link')); |
/** |
* Store useful information for later. |
* |
* @param DOMElement $element - this item as a DOM element |
* @param XML_Feed_Parser_RSS1 $parent - the feed of which this is a member |
*/ |
function __construct(DOMElement $element, $parent, $xmlBase = '') { |
$this->model = $element; |
$this->parent = $parent; |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/bibliotheque/xml_feed_parser/1.0.4/parsers/XmlFeedParserException.php |
---|
New file |
0,0 → 1,36 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Keeps the exception class for XML_Feed_Parser. |
* |
* PHP versions 5 |
* |
* LICENSE: This source file is subject to version 3.0 of the PHP license |
* that is available through the world-wide-web at the following URI: |
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
* the PHP License and are unable to obtain it through the web, please |
* send a note to license@php.net so we can mail you a copy immediately. |
* |
* @category XML |
* @package XML_Feed_Parser |
* @author James Stewart <james@jystewart.net> |
* @copyright 2005 James Stewart <james@jystewart.net> |
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL |
* @version CVS: $Id: Exception.php 304308 2010-10-11 12:05:50Z clockwerx $ |
* @link http://pear.php.net/package/XML_Feed_Parser/ |
*/ |
/** |
* XML_Feed_Parser_Exception is a simple extension of PEAR_Exception, existing |
* to help with identification of the source of exceptions. |
* |
* @author James Stewart <james@jystewart.net> |
* @version Release: @package_version@ |
* @package XML_Feed_Parser |
*/ |
class XmlFeedParserException extends Exception { |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/branches/v1.4-broyeur/widget/modules/photo/squelettes/css/photo.css |
---|
New file |
0,0 → 1,106 |
@charset "UTF-8"; |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Widget */ |
#cel-photo-contenu{ |
position:relative; |
padding:0 5px; |
margin:5px auto; |
font-family:Arial,verdana,sans-serif; |
font-size:12px; |
background-color:#4A4B4C; |
color:#CCC; |
} |
#cel-photo-contenu h1 { |
margin:5px; |
padding:0; |
font-size:1.6em; |
color:white; |
background-color:transparent; |
background-image:none; |
text-transform:none; |
text-align:left; |
} |
#cel-photo-contenu h1 a{ |
color:#CCC; |
} |
#cel-photo-contenu h1 #cel-photo-flux{ |
width:16px; |
height:20px; |
} |
#cel-photo-contenu img { |
border:0; |
padding:0; |
margin:0; |
} |
#cel-photo-contenu a, #cel-photo-contenu a:active, #cel-photo-contenu a:visited { |
border-bottom:1px dotted #666; |
color:#CCC; |
text-decoration:none; |
background-image:none; |
} |
#cel-photo-contenu a:active { |
outline:none; |
} |
#cel-photo-contenu a:focus { |
outline:thin dotted; |
} |
#cel-photo-contenu a:hover { |
color:#56B80E; |
border-bottom:1px dotted #56B80E; |
} |
#cel-photo-date-generation{ |
text-align:right; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Général */ |
#cel-photo-contenu .discretion { |
color:grey; |
font-family:arial; |
font-size:11px; |
font-weight:bold; |
} |
#cel-photo-contenu .nettoyage { |
clear:both; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Galerie Photos CEL */ |
#cel-photo-contenu .cel-photo a{ |
float:left; |
padding:2px; |
border:1px solid white; |
} |
#cel-photo-contenu .cel-photo a:hover{ |
border:1px dotted #FD8C13; |
} |
#cel-photo-contenu .cel-photo a img{ |
float:left; |
width:63px; |
height:63px; |
} |
#cel-photo-contenu #cel-photo-extra img{ |
height:auto; |
} |
#cel-photo-contenu .cel-infos { |
display:none; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Diaporama */ |
#cel-legende{ |
text-align:left; |
} |
#cel-legende-vei{ |
float:right; |
} |
#cel-legende p{ |
color:black; |
font-size:12px; |
margin:5px 0; |
} |
#cel-legende a { |
color:#333; |
border-bottom:1px dotted gainsboro; |
} |
#cel-legende a:hover { |
color:#56B80E; |
border-bottom:1px dotted #56B80E; |
} |
/branches/v1.4-broyeur/widget/modules/photo/squelettes/photo.tpl.html |
---|
New file |
0,0 → 1,143 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml"> |
<head> |
<title>Photographies publiques du CEL - Tela Botanica</title> |
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> |
<meta http-equiv="Content-style-type" content="text/css" /> |
<meta http-equiv="Content-script-type" content="text/javascript" /> |
<meta http-equiv="Content-language" content="fr" /> |
<meta name="revisit-after" content="15 days" /> |
<meta name="robots" content="index,follow" /> |
<meta name="author" content="Jean-Pascal MILCENT, Grégoire DUCHÉ" /> |
<meta name="keywords" content="Tela Botanica, photographie, CEL" /> |
<meta name="description" content="Widget de présentation des dernières photo publiées sur le Carnet en Ligne de Tela Botanica" /> |
<!-- Spécial mobile --> |
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> |
<!-- Favicones --> |
<link rel="icon" type="image/png" href="http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.png" /> |
<link rel="shortcut icon" type="image/x-icon" href="http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.ico" /> |
<!-- Feuilles de styles --> |
<link rel="stylesheet" type="text/css" href="http://www.tela-botanica.org/commun/jquery/fancybox/1.3.4/jquery.fancybox-1.3.4.css" media="screen" /> |
<link rel="stylesheet" type="text/css" href="<?=$url_css?>photo.css" media="screen" /> |
<style type="text/css"> |
html { |
overflow:hidden; |
} |
body{ |
overflow:hidden; |
padding:0; |
margin:0; |
width:100%; |
height:100%; |
background-color:#4A4B4C; |
color:#CCC; |
} |
#cel-photo-contenu, #cel-galerie-photo{ |
width:<?=(($colonne * 69))?>px; |
} |
#cel-galerie-photo #cel-photo-extra img{ |
width:<?=(($colonne * 69)-6)?>px; |
} |
</style> |
<!-- Javascript : bibliothèques --> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/1.4.4/jquery-1.4.4.min.js"></script> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/fancybox/1.3.4/jquery.fancybox-1.3.4.js"></script> |
</head> |
<body> |
<!-- WIDGET:CEL:PHOTO - DEBUT --> |
<div id="cel-photo-contenu"> |
<?php if (isset($erreurs) || isset($informations)) : ?> |
<h1>Erreur & informations</h1> |
<p>Impossible d'afficher le flux.</p> |
<!-- Affichage des erreurs et messages d'information : --> |
<?php if ($erreurs) : ?> |
<?php foreach ($erreurs as $erreur) : ?> |
<p class="erreur"><?=$erreur;?></p> |
<?php endforeach; ?> |
<?php endif; ?> |
<?php if ($informations) : ?> |
<?php foreach ($informations as $information) : ?> |
<p class="info"><?=$information;?></p> |
<?php endforeach; ?> |
<?php endif; ?> |
<?php else : ?> |
<h1> |
Dernières images du |
<a href="http://www.tela-botanica.org/appli:cel" title="Carnet en Ligne" onclick="window.open(this.href);return false;"> |
CEL |
</a> |
<a href="<?=$flux_rss_url?>" |
id="cel-photo-flux" |
title="Suivre les images" |
onclick="window.open(this.href);return false;"> |
<img src="http://www.tela-botanica.org/sites/commun/generique/images/rss.png" alt="Suivre les images" /> |
</a> |
</h1> |
<div id="cel-galerie-photo"> |
<?php foreach ($items as $item) : ?> |
<div class="cel-photo"> |
<a href="<?=sprintf($item['url_tpl'], 'XL')?>" class="cel-img" title="<?=$item['titre']?> - Publiée le <?=$item['date']?> - GUID : <?=$item['guid']?>" rel="galerie-princ"> |
<img src="<?=sprintf($item['url_tpl'], 'CRX2S')?>" alt="<?=$item['titre']?>"/> |
</a> |
<div id="cel-info-<?=$item['guid']?>" class="cel-infos"> |
<strong> |
<a class="cel-img-titre" href="<?=$item['eflore_url']?>" |
onclick="window.open(this.href);return false;" |
title="Cliquez pour accéder à la fiche eFlore"> |
<?=$item['titre']?> |
</a> |
</strong><br /> |
<span class="cel-img-date">Publiée le <?=$item['date']?></span> |
</div> |
</div> |
<?php endforeach; ?> |
<?php if ($extra_actif) : ?> |
<div id="cel-photo-extra" class="cel-photo"> |
<a href="<?=sprintf($extra['url_tpl'], 'XL')?>" class="cel-img" title="<?=$extra['titre']?> - Publiée le <?=$extra['date']?> - GUID : <?=$extra['guid']?>" rel="galerie-princ"> |
<img src="<?=sprintf($extra['url_tpl'], 'CRS')?>" alt="<?=$extra['titre']?>"/> |
</a> |
</div> |
</div> |
<?php endif ?> |
<p id="cel-photo-date-generation" class="discretion nettoyage">Au <?=strftime('%A %d %B %Y à %H:%M:%S')?></p> |
<script type="text/Javascript"> |
//<![CDATA[ |
function formaterTitre(titre, currentArray, currentIndex, currentOpts) { |
var motif = /GUID : ([0-9]+)$/; |
motif.exec(titre); |
var guid = RegExp.$1; |
var info = $('#cel-info-'+guid).clone().html(); |
var tpl = |
'<div id="cel-legende">'+ |
'<p id="cel-legende-vei">'+'Image n°' + (currentIndex + 1) + ' sur ' + currentArray.length +'<\/p>'+ |
(titre && titre.length ? '<p>'+info+'<\/p>' : '' )+ |
'<\/div>'; |
return tpl; |
} |
$(document).ready(function() { |
$('a.cel-img').attr('rel', 'galerie-princ').fancybox({ |
transitionIn:'elastic', |
transitionOut:'elastic', |
speedIn :600, |
speedOut:200, |
overlayShow:true, |
titleShow:true, |
titlePosition:'inside', |
titleFormat:formaterTitre |
}); |
}); |
//]]> |
</script> |
<?php endif; ?> |
</div> |
<!-- WIDGET:CEL:PHOTO - FIN --> |
</body> |
</html> |
/branches/v1.4-broyeur/widget/modules/photo/squelettes/photo_ajax.tpl.html |
---|
New file |
0,0 → 1,101 |
<!-- WIDGET:CEL:PHOTO - DEBUT --> |
<div id="cel-photo-contenu"> |
<!-- Feuilles de styles --> |
<style type="text/css"> |
#cel-photo-contenu, #cel-galerie-photo{ |
width:<?=(($colonne * 69))?>px; |
} |
#cel-galerie-photo #cel-photo-extra img{ |
width:<?=(($colonne * 69)-6)?>px; |
} |
</style> |
<!-- Javascript : bibliothèques --> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/fancybox/1.3.4/jquery.fancybox-1.3.4.pack.js"></script> |
<?php if (isset($erreurs) || isset($informations)) : ?> |
<h1>Erreur & informations</h1> |
<p>Impossible d'afficher le flux.</p> |
<!-- Affichage des erreurs et messages d'information : --> |
<?php if ($erreurs) : ?> |
<?php foreach ($erreurs as $erreur) : ?> |
<p class="erreur"><?=$erreur;?></p> |
<?php endforeach; ?> |
<?php endif; ?> |
<?php if ($informations) : ?> |
<?php foreach ($informations as $information) : ?> |
<p class="info"><?=$information;?></p> |
<?php endforeach; ?> |
<?php endif; ?> |
<?php else : ?> |
<h1> |
Dernières images du |
<a href="http://www.tela-botanica.org/appli:cel" title="Carnet en Ligne" onclick="window.open(this.href);return false;"> |
CEL |
</a> |
<a href="<?=$flux_rss_url?>" |
id="cel-photo-flux" |
title="Suivre les images" |
onclick="window.open(this.href);return false;"> |
<img src="http://www.tela-botanica.org/sites/commun/generique/images/rss.png" alt="Suivre les images" /> |
</a> |
</h1> |
<div id="cel-galerie-photo"> |
<?php foreach ($items as $item) : ?> |
<div class="cel-photo"> |
<a href="<?=sprintf($item['url_tpl'], 'XL')?>" class="cel-img" title="<?=$item['titre']?> - Publiée le <?=$item['date']?> - GUID : <?=$item['guid']?>" rel="galerie-princ"> |
<img src="<?=sprintf($item['url_tpl'], 'CRX2S')?>" alt="<?=$item['titre']?>"/> |
</a> |
<div id="cel-info-<?=$item['guid']?>" class="cel-infos"> |
<strong> |
<a class="cel-img-titre" href="<?=$item['eflore_url']?>" |
onclick="window.open(this.href);return false;" |
title="Cliquez pour accéder à la fiche eFlore"> |
<?=$item['titre']?> |
</a> |
</strong><br /> |
<span class="cel-img-date">Publiée le <?=$item['date']?></span> |
</div> |
</div> |
<?php endforeach; ?> |
<?php if ($extra_actif) : ?> |
<div id="cel-photo-extra" class="cel-photo"> |
<a href="<?=sprintf($extra['url_tpl'], 'XL')?>" class="cel-img" title="<?=$extra['titre']?> - Publiée le <?=$extra['date']?> - GUID : <?=$extra['guid']?>" rel="galerie-princ"> |
<img src="<?=sprintf($extra['url_tpl'], 'CRS')?>" alt="<?=$extra['titre']?>"/> |
</a> |
</div> |
</div> |
<?php endif ?> |
<p id="cel-photo-date-generation" class="discretion nettoyage">Au <?=strftime('%A %d %B %Y à %H:%M:%S')?></p> |
<script type="text/Javascript"> |
//<![CDATA[ |
function formaterTitre(titre, currentArray, currentIndex, currentOpts) { |
var motif = /GUID : ([0-9]+)$/; |
motif.exec(titre); |
var guid = RegExp.$1; |
var info = $('#cel-info-'+guid).clone().html(); |
var tpl = |
'<div id="cel-legende">'+ |
'<p id="cel-legende-vei">'+'Image n°' + (currentIndex + 1) + ' sur ' + currentArray.length +'<\/p>'+ |
(titre && titre.length ? '<p>'+info+'<\/p>' : '' )+ |
'<\/div>'; |
return tpl; |
} |
$(document).ready(function() { |
$('a.cel-img').attr('rel', 'galerie-princ').fancybox({ |
transitionIn:'elastic', |
transitionOut:'elastic', |
speedIn :600, |
speedOut:200, |
overlayShow:true, |
titleShow:true, |
titlePosition:'inside', |
titleFormat:formaterTitre |
}); |
}); |
//]]> |
</script> |
<?php endif; ?> |
</div> |
<!-- WIDGET:CEL:PHOTO - FIN --> |
/branches/v1.4-broyeur/widget/modules/photo/Photo.php |
---|
New file |
0,0 → 1,140 |
<?php |
// declare(encoding='UTF-8'); |
/** |
* Service affichant les dernières photo publiques du CEL ouvrable sous forme de diaporama. |
* Encodage en entrée : utf8 |
* Encodage en sortie : utf8 |
* |
* Cas d'utilisation et documentation : |
* @link http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=AideCELWidgetPhoto |
* |
* Paramètres : |
* ===> extra = booléen (1 ou 0) [par défaut : 1] |
* Affiche / Cache la vignette en taille plus importante au bas du widget. |
* ===> vignette = [0-9]+,[0-9]+ [par défaut : 4,3] |
* Indique le nombre de vignette par ligne et le nombre de ligne. |
* |
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org> |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt> |
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt> |
* @version $Id$ |
* @copyright Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org) |
*/ |
class Photo extends WidgetCommun { |
const DS = DIRECTORY_SEPARATOR; |
const SERVICE_DEFAUT = 'photo'; |
private $flux_rss_url = null; |
private $eflore_url_tpl = null; |
/** |
* Méthode appelée par défaut pour charger ce widget. |
*/ |
public function executer() { |
$retour = null; |
// Pour la création de l'id du cache nous ne tenons pas compte du paramètre de l'url callback |
unset($this->parametres['callback']); |
extract($this->parametres); |
if (!isset($mode)) { |
$mode = self::SERVICE_DEFAUT; |
} |
$this->eflore_url_tpl = $this->config['photo']['efloreUrlTpl']; |
$this->flux_rss_url = $this->config['photo']['fluxRssUrl']; |
$cache_activation = $this->config['photo.cache']['activation']; |
$cache_stockage = $this->config['photo.cache']['stockageDossier']; |
$ddv = $this->config['photo.cache']['dureeDeVie']; |
$cache = new Cache($cache_stockage, $ddv, $cache_activation); |
$id_cache = 'photo-'.hash('adler32', print_r($this->parametres, true)); |
if (! $contenu = $cache->charger($id_cache)) { |
$methode = $this->traiterNomMethodeExecuter($mode); |
if (method_exists($this, $methode)) { |
$retour = $this->$methode(); |
} else { |
$this->messages[] = "Ce type de service '$methode' n'est pas disponible."; |
} |
if (is_null($retour)) { |
$contenu = 'Un problème est survenu : '.print_r($this->messages, true); |
} else { |
$squelette = dirname(__FILE__).self::DS.'squelettes'.self::DS.$retour['squelette'].'.tpl.html'; |
$contenu = $this->traiterSquelettePhp($squelette, $retour['donnees']); |
$cache->sauver($id_cache, $contenu); |
} |
} |
if (isset($_GET['callback'])) { |
$this->envoyerJsonp(array('contenu' => $contenu)); |
} else { |
$this->envoyer($contenu); |
} |
} |
private function executerAjax() { |
$widget = $this->executerPhoto(); |
$widget['squelette'] = 'photo_ajax'; |
return $widget; |
} |
private function executerPhoto() { |
$widget = null; |
extract($this->parametres); |
$extra = (isset($extra) && $extra == 0) ? false : ($this->config['photo']['extraActif'] ? true : false); |
$vignette = (isset($vignette) && preg_match('/^[0-9]+,[0-9]+$/', $vignette)) ? $vignette : '4,3'; |
list($colonne, $ligne) = explode(',', $vignette); |
$xml = file_get_contents($this->flux_rss_url); |
if ($xml) { |
try { |
$flux = new XmlFeedParser($xml); |
$widget['donnees']['flux_rss_url'] = $this->flux_rss_url; |
$widget['donnees']['url_css'] = sprintf($this->config['chemins']['baseURLAbsoluDyn'], 'modules/photo/squelettes/css/'); |
$widget['donnees']['colonne'] = $colonne; |
$widget['donnees']['extra_actif'] = $extra; |
$max_photo = $colonne * $ligne; |
$num = 0; |
foreach ($flux as $entree) { |
if ($num == $max_photo) { |
break; |
} |
$item = array(); |
// Formatage date |
$date = $entree->updated ? $entree->updated : null; |
$date = $entree->pubDate ? $entree->pubDate : $date; |
$item['date'] = strftime('%A %d %B %Y', $date); |
$item['lien'] = $entree->link; |
$item['url_tpl'] = preg_replace('/(XS|[SML]|X(?:[23]|)L|CR(?:|X2)S|C(?:|X)S)\.jpg$/', '%s.jpg', $entree->guid); |
// Formatage titre |
$item['titre'] = $entree->title; |
$item['nn'] = ''; |
$item['eflore_url'] = '#'; |
if (preg_match('/\[nn([0-9]+)\]/', $entree->title, $match)) { |
$item['nn'] = $match[1]; |
$item['eflore_url'] = sprintf($this->eflore_url_tpl, $item['nn']); |
} |
// Récupération du GUID |
if (preg_match('/appli:cel-img:([0-9]+)[^.]+\.jpg$/', $entree->guid, $match)) { |
$item['guid'] = (int) $match[1]; |
} else { |
$item['guid'] = $entree->guid; |
} |
// Ajout aux items et si première photo à extra |
if ($num == 0) { |
$widget['donnees']['extra'] = $item; |
} |
$widget['donnees']['items'][$num++] = $item; |
} |
$widget['squelette'] = 'photo'; |
} catch (XmlFeedParserException $e) { |
trigger_error('Flux invalide : '.$e->getMessage(), E_USER_WARNING); |
} |
} |
return $widget; |
} |
} |
?> |
/branches/v1.4-broyeur/widget/modules/photo/config.ini |
---|
New file |
0,0 → 1,19 |
[photo] |
; Chemin pour l'autoload à ajouter |
autoload = "bibliotheque/;bibliotheque/xml_feed_parser/1.0.4/;bibliotheque/xml_feed_parser/1.0.4/parsers/" |
; URL ou chemin du flux RSS contenant les liens vers les photos |
fluxRssUrl = "http://www.tela-botanica.org/service:cel:CelSyndicationImage/complet/atom" |
; Squelette d'url pour accéder à la fiche eFlore |
efloreUrlTpl = "http://www.tela-botanica.org/eflore/BDNFF/4.02/nn/%s/illustration" |
; Nombre de vignette à afficher : nombre de vignettes par ligne et nombre de lignes séparés par une vigule (ex. : 4,3). |
vignette = 4,3 |
; Afficher/Cacher l'affichage en grand de la dernière image ajoutée |
extraActif = true |
[photo.cache] |
; Active/Désactive le cache |
activation = false |
; Dossier où stocker les fichiers de cache du widget |
stockageDossier = "/home/jpm/web/cache/photo/" |
; Durée de vie du fichier de cache |
dureeDeVie = 86400 |
/branches/v1.4-broyeur/widget/modules/stats/squelettes/stats_utilisateur.tpl.html |
---|
New file |
0,0 → 1,72 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> |
<head> |
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> |
<meta http-equiv="Content-style-type" content="text/css" /> |
<meta http-equiv="Content-script-type" content="text/javascript" /> |
<meta http-equiv="Content-language" content="fr" /> |
<meta name="revisit-after" content="15 days" /> |
<meta name="robots" content="index,follow" /> |
<meta name="author" content="Jean-Pascal MILCENT" /> |
<meta name="keywords" content="Statistiques, CEL, Tela Botanica, graphiques" /> |
<meta name="description" content="Graphiques et statistiques sur les observations et images du Carnet en Ligne (CEL)" /> |
<title>Statistiques du Carnet En Ligne</title> |
<style> |
img{display:block;margin:0.5em;border:1px solid black;} |
hr.nettoyeur {clear:both;width:0;} |
.flottant-gauche img{float:left;} |
</style> |
<!-- Stats : Google Analytics --> |
<script type="text/javascript"> |
//<![CDATA[ |
var _gaq = _gaq || []; |
_gaq.push(['_setAccount', 'UA-20092557-1']); |
_gaq.push(['_trackPageview']); |
(function() { |
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
})(); |
//]]> |
</script> |
</head> |
<body> |
<?php $i=0;?> |
<h1>Statistiques du CEL de <?=$utilisateur?></h1> |
<div class="flottant-gauche"> |
<h2>Observations - Activité</h2> |
<img src="<?=$url_service?>/UtilisationJournaliere/<?=date("Y-m-d", (time() - 86400))?>?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Intensité d'utilisation pour la journée d'hier" /> |
<img src="<?=$url_service?>/UtilisationJournaliere?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Intensité d'utilisation pour aujourd'hui" /> |
</div> |
<hr class="nettoyeur" /> |
<div class="flottant-gauche"> |
<h2>Observations - Données</h2> |
<img src="<?=$url_service?>/NbreObsPublicVsPrivee?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Nombre d'observations publiques versus privées" /> |
<img src="<?=$url_service?>/NbreObsDetermineeVsInconnue?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Nombre d'observations déterminées versus inconnues" /> |
<hr class="nettoyeur" /> |
<img src="<?=$url_service?>/NbreObsAvecIndicationGeo?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Nombre d'observations avec indications géographiques" /> |
</div> |
<hr class="nettoyeur" /> |
<div> |
<h2>Observations - Évolution</h2> |
<img src="<?=$url_service?>/EvolObsParMoisGlissant?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Évolutions des observation sur le dernier mois glissant" /> |
<img src="<?=$url_service?>/EvolObsParMois?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Évolutions des observation par mois" /> |
<img src="<?=$url_service?>/EvolObsParAn?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Évolutions des observation par an" /> |
</div> |
<hr class="nettoyeur" /> |
<div class="flottant-gauche"> |
<h2>Utilisateurs</h2> |
<img src="<?=$url_service?>/NuagePointsObsParHeureEtJourSemaine?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Nuage de points d'observation par heure et jour de la semaine" /> |
</div> |
<hr class="nettoyeur" /> |
<div> |
<h2>Images</h2> |
<img src="<?=$url_service?>/EvolImgParMois?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Évolutions du dépôt d'images par mois" /> |
<img src="<?=$url_service?>/EvolImgLieesParMois?serveur=<?=$i++?>&utilisateur=<?=$utilisateur?>" alt="Évolutions des images liées aux observations par mois" /> |
</div> |
<hr class="nettoyeur" /> |
</body> |
</html> |
/branches/v1.4-broyeur/widget/modules/stats/squelettes/stats.tpl.html |
---|
New file |
0,0 → 1,79 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> |
<head> |
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> |
<meta http-equiv="Content-style-type" content="text/css" /> |
<meta http-equiv="Content-script-type" content="text/javascript" /> |
<meta http-equiv="Content-language" content="fr" /> |
<meta name="revisit-after" content="15 days" /> |
<meta name="robots" content="index,follow" /> |
<meta name="author" content="Jean-Pascal MILCENT" /> |
<meta name="keywords" content="Statistiques, CEL, Tela Botanica, graphiques" /> |
<meta name="description" content="Graphiques et statistiques sur les observations et images du Carnet en Ligne (CEL)" /> |
<title>Statistiques du Carnet En Ligne</title> |
<style> |
img{display:block;margin:0.5em;border:1px solid black;} |
hr.nettoyeur {clear:both;width:0;} |
.flottant-gauche img{float:left;} |
</style> |
<!-- Stats : Google Analytics --> |
<script type="text/javascript"> |
//<![CDATA[ |
var _gaq = _gaq || []; |
_gaq.push(['_setAccount', 'UA-20092557-1']); |
_gaq.push(['_trackPageview']); |
(function() { |
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
})(); |
//]]> |
</script> |
</head> |
<body> |
<?php $i=0;?> |
<h1>Statistiques du CEL</h1> |
<div class="flottant-gauche"> |
<h2>Observations - Activité</h2> |
<img src="<?=$url_service?>/UtilisationJournaliere?serveur=<?=$i++?>/<?=date("Y-m-d", (time() - 86400))?>" alt="Intensité d'utilisation pour la journée d'hier" /> |
<img src="<?=$url_service?>/UtilisationJournaliere?serveur=<?=$i++?>" alt="Intensité d'utilisation pour aujourd'hui" /> |
</div> |
<hr class="nettoyeur" /> |
<div class="flottant-gauche"> |
<h2>Observations - Données</h2> |
<img src="<?=$url_service?>/NbreObsIdVsTest?serveur=<?=$i++?>" alt="Nombre d'observations identifiées versus tests" /> |
<img src="<?=$url_service?>/NbreObsPublicVsPrivee?serveur=<?=$i++?>" alt="Nombre d'observations publiques versus privées" /> |
<img src="<?=$url_service?>/NbreObsDetermineeVsInconnue?serveur=<?=$i++?>" alt="Nombre d'observations déterminées versus inconnues" /> |
<hr class="nettoyeur" /> |
<img src="<?=$url_service?>/NbreObsAvecIndicationGeo?serveur=<?=$i++?>" alt="Nombre d'observations avec indications géographiques" /> |
</div> |
<hr class="nettoyeur" /> |
<div> |
<h2>Observations - Évolution</h2> |
<img src="<?=$url_service?>/EvolObsParMoisGlissant?serveur=<?=$i++?>" alt="Évolutions des observation sur le dernier mois glissant" /> |
<img src="<?=$url_service?>/EvolObsParMois?serveur=<?=$i++?>" alt="Évolutions des observation par mois" /> |
<img src="<?=$url_service?>/EvolObsParAn?serveur=<?=$i++?>" alt="Évolutions des observation par an" /> |
</div> |
<hr class="nettoyeur" /> |
<div class="flottant-gauche"> |
<h2>Utilisateurs</h2> |
<img src="<?=$url_service?>/NuagePointsObsParHeureEtJourSemaine?serveur=<?=$i++?>" alt="Nuage de points d'observation par heure et jour de la semaine" /> |
<img src="<?=$url_service?>/NuagePointsObsAnciennete?serveur=<?=$i++?>" alt="Répartition des utilisateurs en fonction du nombre d'observations et de l'ancienneté" /> |
<hr class="nettoyeur" /> |
<img src="<?=$url_service?>/NbreObsParUtilisateur?serveur=<?=$i++?>" alt="Nombre d'observations par utilisateur" /> |
<img src="<?=$url_service?>/NbreObsParUtilisateurEtTest?serveur=<?=$i++?>" alt="Nombre d'observations par utilisateur et test" /> |
<hr class="nettoyeur" /> |
<img src="<?=$url_service?>/EvolUtilisateurParMois?serveur=<?=$i++?>" alt="Nombre d'observations par utilisateur et test" /> |
</div> |
<hr class="nettoyeur" /> |
<div> |
<h2>Images</h2> |
<img src="<?=$url_service?>/EvolImgParMois?serveur=<?=$i++?>" alt="Évolutions du dépôt d'images par mois" /> |
<img src="<?=$url_service?>/EvolImgLieesParMois?serveur=<?=$i++?>" alt="Évolutions des images liées aux observations par mois" /> |
</div> |
<hr class="nettoyeur" /> |
</body> |
</html> |
/branches/v1.4-broyeur/widget/modules/stats/Stats.php |
---|
New file |
0,0 → 1,64 |
<?php |
/** |
* Widget fournissant des stats graphiques du CEL. |
* Encodage en entrée : utf8 |
* Encodage en sortie : utf8 |
* |
* @author Jean-Pascal MILCENT <jpm@clapas.org> |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt> |
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt> |
* @version $Id$ |
* @copyright © 2010, Jean-Pascal MILCENT |
*/ |
class Stats extends WidgetCommun { |
const SERVICE_DEFAUT = 'defaut'; |
/** |
* Méthode appelée avec une requête de type GET. |
*/ |
public function executer() { |
$retour = null; |
extract($this->parametres); |
if (!isset($mode)) { |
$mode = self::SERVICE_DEFAUT; |
} |
$methode = $this->traiterNomMethodeExecuter($mode); |
if (method_exists($this, $methode)) { |
$retour = $this->$methode(); |
} else { |
$this->messages[] = "Ce type de carte '$methode' n'est pas disponible."; |
} |
if (is_null($retour)) { |
$info = 'Un problème est survenu : '.print_r($this->messages, true); |
$this->envoyer($info); |
} else { |
$squelette = dirname(__FILE__).DIRECTORY_SEPARATOR.'squelettes'.DIRECTORY_SEPARATOR.$retour['squelette'].'.tpl.html'; |
$html = $this->traiterSquelettePhp($squelette, $retour['donnees']); |
$this->envoyer($html); |
} |
} |
/** |
* Stats par défaut |
*/ |
public function executerDefaut() { |
$widget = null; |
$widget['donnees']['url_service'] = sprintf($this->config['chemins']['baseURLServicesCelTpl'], 'CelStatistique'); |
$widget['squelette'] = 'stats'; |
return $widget; |
} |
public function executerUtilisateur() { |
$widget = null; |
if ($this->authentifierUtilisateur()) { |
$widget['donnees']['url_service'] = sprintf($this->config['chemins']['baseURLServicesCelTpl'], 'CelStatistique'); |
$widget['donnees']['utilisateur'] = $this->getAuthIdentifiant(); |
$widget['squelette'] = 'stats_utilisateur'; |
} |
return $widget; |
} |
} |