Subversion Repositories Sites.tela-botanica.org

Rev

Rev 609 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
/*vim: set expandtab tabstop=4 shiftwidth=4: */ 
// +------------------------------------------------------------------------------------------------------+
// | PHP version 4.1                                                                                      |
// +------------------------------------------------------------------------------------------------------+
// | Copyright (C) 2004 Tela Botanica (accueil@tela-botanica.org)                                         |
// +------------------------------------------------------------------------------------------------------+
// | This library is free software; you can redistribute it and/or                                        |
// | modify it under the terms of the GNU General Public                                                  |
// | License as published by the Free Software Foundation; either                                         |
// | version 2.1 of the License, or (at your option) any later version.                                   |
// |                                                                                                      |
// | This library is distributed in the hope that it will be useful,                                      |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of                                       |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                                    |
// | General Public License for more details.                                                             |
// |                                                                                                      |
// | You should have received a copy of the GNU General Public                                            |
// | License along with this library; if not, write to the Free Software                                  |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                            |
// +------------------------------------------------------------------------------------------------------+
// CVS : $Id:$
/**
* Application projet
*
* Script pour calculer les statistiques
*
*@package projet
//Auteur original :
*@author        Alexandre Granier <alexandre@tela-botanica.org>
//Autres auteurs :
*@author        Julien Grillot <julien.grillot@gmail.com>
*@copyright     Tela-Botanica 2000-2005
*@version       $Revision:$
// +------------------------------------------------------------------------------------------------------+
*/

// +------------------------------------------------------------------------------------------------------+
// |                                            ENTETE du PROGRAMME                                       |
// +------------------------------------------------------------------------------------------------------+


include_once PROJET_CHEMIN_APPLI.'classes/ezmlmAccessObject.class.php';
include_once PROJET_CHEMIN_BIBLIOTHEQUE_API.'pear/XML/RSS.php';

// Ne pas changer : les groupes Yahoo se basent toujours sur la semaine
define("NB_SEC_INSERT", 7*24*3600);
define("NB_SEC_UPDATE", 2*3600);
define("URL_WIKINI", "http://www.tela-botanica.org/wikini/");

/**
 * Retourne le contenu de la page $adresse de facon asynchrone
 * @param string $adresse URL de la page dont le contenu doit etre recupere
 * @param int timeout temps d'attente maximum avant abandon de la recuperation 
 */
function monFileGetContents($adresse, $timeout = 30){
        $url = parse_url($adresse);
        $url['port'] = isset($url['port']) ? $url['port'] : '80';
        $url['scheme'] = isset($url['scheme']) ? strtoupper($url['scheme']) : 'HTTP';
        $fp = fsockopen($url['host'], $url['port'], $errno, $errstr, $timeout);
        if (!$fp) {
                echo "Erreur de socket: $errno - $errstr<br />\n";
                return false;
        } else {
                $header  = 'GET '.$url['path'].' '.$url['scheme']."/1.1\r\n";
        
                $header .= "Host: www.yahoo.com\r\n";
                $header .= "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20021204\r\n";
                $header .= "Referer: http://www.yahoo.com/\r\n";

                $header .= 'Connection: Close\r\n\r\n';

                fputs($fp, $header);
                stream_set_timeout($fp, $timeout);
                while (!feof($fp)) {
                        $page .= fread($fp, 262144);
                }
                $stream  = stream_get_meta_data($fp);
                fclose($fp);    
                if ($stream['timed_out']) {
                        echo 'Le d�lai de r�ponse de la page <b>'.$adresse.'</b> a d�pass� le timeout de <b>'.$timeout.'</b> sec.';
                        return false;
                }else{
                        return $page;
                }
        }
}

/**
 * Procedure retrouvant le nombre de contribution, de message et le contenu de la page a partir des informations de la BDD
 * @param object $ligne resultat d'un fetch row contenant l'url du document a analyser
 * @param int $nombre_contrib recupere le nombre de contributions du projet 
 * @param int $nombre_message recupere le nombre de nouveaux messages du projet
 * @param int $nombre_membre recupere le nombre de nouveaux messages du projet
 * @param int $nombre_photo recupere le nombre de nouveaux messages du projet
 * @return false si la fonction echoue lors de la tentative de recuperation des donnees utiles
 */
function analyser($ligne, &$res, &$nombre_contrib, &$nombre_message, &$nombre_membre, &$nombre_photo) {
        $nombre_contrib='0';
        $nombre_msg='0';
        $r=false;

        // Recuperation du nbre de message
        $xml_parser = &new ezmlmAccessObject('nombre_messages', $ligne->pl_domaine, $ligne->pl_nom_liste, $GLOBALS['lang']) ;
        $xml_parser->load();
        
        ob_start();
        $xml_parser->parse();
        $nombre_message = ob_get_contents();
        if(!$nombre_message)$nombre_message='0';
        ob_end_clean();
        
        // Si AGO_A_NOMGRP alors il n'y a pas de flux RSS (groupe Yahoo, cad pas Tela)
        if($ligne->AGO_A_NOMGRP) {
                $url='http://fr.groups.yahoo.com/group/'.$ligne->AGO_A_NOMGRP;
                
                // Recherche du schema retrouvant le nombre de nouveaux message dans la semaine
                $pattern1='>([0-9]+)</span> .ouveaux? .embres?';
                $pattern2='>([0-9]+)</span> .ouveaux? .essages?';
                $pattern3='>([0-9]+)</span> .ouvelles? .hotos?';
                
                // Quelques soucis avec la version asynchrone
                //$contenu=monFileGetContents($url);
                $contenu=file_get_contents($url);
                usleep(3000000);
                $r=($contenu?true:false);
                ereg($pattern2, $contenu, $no);
                $nombre_message=$no[1];

                ereg($pattern1, $contenu, $no);
                $nombre_membre=$no[1];

                ereg($pattern3, $contenu, $no);
                $nombre_photo=$no[1];

        } else {
                // Parse le flux RSS g�n�r� par wikini
                $rss =& new XML_RSS(URL_WIKINI.$ligne->p_wikini.'/wakka.php?wiki=DerniersChangementsRSS/xml');
                $rss->parse();
                
                // On va compter le nombre de modification depuis les x derniers jours (voirs constantes)
                foreach ($rss->getItems() as $item) {
                        // Le script doit �tre compatiable avec plusieurs formats de date
                        if ($item['pubDate']) {
                                if (strtotime($item['pubDate'])>time()-NB_SEC_INSERT) $nombre_contrib++;
                        
                        } else {
                                $date = substr($item['title'], strlen($item['title'])-18);
                                if ($date>date("Y m d - H:i", time()-NB_SEC_INSERT)) $nombre_contrib++;
                        }
                }
                
                $r=true;
                
        }
        
        return $r;
}

// Pour calculer le temps d'execution du script
$start=microtime(true);


// +------------------------------------------------------------------------------------------------------+
// |                                            CORPS du PROGRAMME                                       |
// +------------------------------------------------------------------------------------------------------+


// requete pour recuperer la liste des projets
$requete = 'select count(distinct psu_id_utilisateur) as nb_utilisateur, count(distinct pil_id_utilisateur) as nb_utilisateur_liste, count(distinct projet_documents.pd_id) as nb_doc, p_wikini, ' .
                'p_id, p_titre, p_resume, projet_lien_liste.pl_id_liste, pl_domaine,pl_nom_liste,AGO_A_NOMGRP ' .
                'from projet left join projet_lien_liste on p_id=projet_lien_liste.pl_id_projet ' .
                'left join projet_liste on projet_lien_liste.pl_id_liste=projet_liste.pl_id_liste ' .
                'left join projet_inscription_liste on (projet_inscription_liste.pil_id_liste=projet_liste.pl_id_liste and pil_date_inscription > date_sub(now(), interval 1 week)) ' .
                'left join projet_documents on (p_id=pd_ce_projet and  pd_date_de_mise_a_jour > date_sub(now(), interval 1 week)) ' .
                'left join projet_statut_utilisateurs on p_id=psu_id_projet ' .
                'left join projet_lien_liste_externe on plle_id_projet=p_id ' .
                'left join agora on plle_id_liste=AGO_A_ID ' .
                'group by p_id order by p_titre limit 0,15' ;

$resultat = $this->_db->query($requete) ;
if (DB::isError($resultat)) {
        return ("Echec de la requete<br />".$resultat->getMessage()."<br />".$resultat->getDebugInfo()) ;
}
$res .= '<h1>Statistiques des projets</h1>';

// Un tableau c'est bien mais un beau tableau c'est mieux.
$res .= '<style type="text/css">';
$res .= '.stats { border-spacing: 0px; }';
$res .= '.stats .stat_nb { text-align: center; }';
$res .= '.stats th { font-weight: bold; }';
$res .= '.stats td { border-bottom: 1px #ddd solid; }';
$res .= '.warning { color: #800; font-weight: bold; }';
$res .= '</style>';

$calculs=false;

$res .= '<table cellspacing="0" class="stats" style="width: 100%"><tr><th>Nom du projet</th><th>Nom liste</th><th>Inscrits</th><th>Utilisateurs</th><th>Nb msg</th><th>Nb doc</th><th>Nb contrib</th></tr>';

$nombre_contrib = 0;
$nombre_message = 0;

while ($ligne = $resultat->fetchRow(DB_FETCHMODE_OBJECT)) {
        $nombre_contrib = 0;
        $nombre_message = 0;

        // On verifie la date de derniere mise � jour
        $requete_verif='SELECT * FROM projet_statistiques WHERE ps_ce_projet="'.$ligne->p_id.'" ORDER BY ps_date DESC LIMIT 1';
        $resultat_verif = $this->_db->query($requete_verif);
        if (DB::isError($resultat_verif)) {
                return $resultat_verif->getMessage().$resultat_verif;
        }
        $ligne_verif = $resultat_verif->fetchRow(DB_FETCHMODE_OBJECT);
        
        // Si elle remonte a plus de deux heure, on sauvegarde, et a plus de 7 jours, on archive et cr�� une nouvelle entr�e
        if($ligne_verif->ps_date > date("Y-m-d H:i:s", time()-NB_SEC_INSERT)) {
                if($ligne_verif->ps_maj < date("Y-m-d H:i:s", time()-NB_SEC_UPDATE)) {
                
                        // Recupere nombre_contrib et nombre_message
                        $calculs=analyser($ligne, $res, $nombre_contrib, $nombre_message, $nombre_membre, $nombre_photo);
                        
                        $requete_maj = 'UPDATE projet_statistiques SET ps_msg_derniere_semaine="'.$nombre_message.'", ps_doc_derniere_semaine="'.$ligne->nb_doc.'", ps_nombre_inscrit="'.$ligne->nb_utilisateur.'", ps_nombre_inscrit_liste="'.$ligne->nb_utilisateur_liste.'", ps_modifwiki_derniere_semaine="'.$nombre_contrib.'", ps_maj=NOW() WHERE ps_ce_projet="'.$ligne->p_id.'" AND ps_date="'.$ligne->ps_date.'"';
                        $resultat_maj = $this->_db->query($requete_maj);
                        if (DB::isError($resultat_maj)) {
                                return $resultat_maj->getMessage().$requete_maj;
                        }
                } else {
                
                        $nombre_contrib = $ligne_verif->ps_modifwiki_derniere_semaine;
                        $nombre_message = $ligne_verif->ps_msg_derniere_semaine;
                
                }
        
        } else {
        
                // Recupere nombre_contrib et nombre_message
                $calculs=analyser($ligne, $nombre_contrib, $nombre_message);

                $requete_maj = 'INSERT INTO projet_statistiques (ps_ce_projet, ps_msg_derniere_semaine, ps_doc_derniere_semaine, ps_nombre_inscrit, ps_nombre_inscrit_liste, ps_modifwiki_derniere_semaine, ps_date, ps_maj) '.
                                                'VALUES ("'.$ligne->p_id.'", "'.$nombre_message.'", "'.$ligne->nb_doc.'", "'.$ligne->nb_utilisateur.'", "'.$ligne->nb_utilisateur_liste.'", "'.$nombre_contrib.'", NOW(), NOW())';
                $resultat_maj = $this->_db->query($requete_maj);
                if (DB::isError($resultat_maj)) {
                        return $resultat_maj->getMessage().$requete_maj;
                }
        }
        
        // Et on affiche les stats courantes
        $res .= '<tr><td>'.$ligne->p_titre.'</td><td>'.($ligne->pl_nom_liste?$ligne->pl_nom_liste:$ligne->AGO_A_NOMGRP.' (Yahoo)').'</td><td class="stat_nb">'.$ligne->nb_utilisateur_liste.'</td><td class="stat_nb">'.$ligne->nb_utilisateur.'</td><td class="stat_nb">'.$nombre_message.'</td><td class="stat_nb">'.$ligne->nb_doc.'</td><td class="stat_nb">'.$nombre_contrib.'</td></tr>';
}
$res .= '</table>';

// Met a jour les statistiques et somme d'activite
$sql="update `projet_statistiques` set ps_somme=(ps_msg_derniere_semaine +ps_doc_derniere_semaine+ps_nombre_inscrit_liste+ps_modifwiki_derniere_semaine);";
$resultat = $this->_db->query($sql);
if (DB::isError($resultat)) {
        return $resultat->getMessage().$sql;
}

// On cherche le max pour ponderer les sommes
$sql='SELECT MAX( ps_somme ) AS max FROM projet_statistiques WHERE ps_date>=CURDATE()';
$resultat = $this->_db->query($sql);
if (DB::isError($resultat)) {
        return $resultat->getMessage().$sql;
}
$tresultat = $resultat->fetchRow(DB_FETCHMODE_OBJECT);

// On pondere
$sql="UPDATE `projet_statistiques` SET ps_pourcent=ps_somme / ".($tresultat->max?$tresultat->max:1)." * 100 WHERE ps_date>=CURDATE();";
$resultat = $this->_db->query($sql);
if (DB::isError($resultat)) {
        return $resultat->getMessage().$sql;
}

// On affiche quelques infos inutiles mais indispensables
$res .= '<p>';
if(!$calculs)$res .= '<span class="warning">Les variables nb_msg et nb_contrib n\'ont pas &eacute;t&eacute; calcul&eacute;es (datent de moins de '.round(NB_SEC_UPDATE/3600).' heures)</span><br />';
$res .= 'Execut&eacute; en '.(round((microtime(true)-$start)*1000)/1000).' secondes.</p>';

return $res;

/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log:$
* +--Fin du code ----------------------------------------------------------------------------------------+
*/
?>