Façade pour DOTCLEAR

Eléphanteau du PHP | 24 Messages

29 avr. 2006, 13:22

Ce script permet d'utiliser dotclear comme gestionnaire de données. Concrètement, il permet d'extraire les données du blog et de les manipuler comme on veut.

Voici comment on l'utilise :
include "BlogFacade.php";

// Pour faciliter la visibilité des var_dumps...
echo "<pre>";

// Déclaration d'un objet façace pour les billets classés dans des
// catégories préfixées par 'loisirs_'.
// (à remplacer par votre propre préfixe)
$bf = new BlogFacade('loisirs_');

// Affichage (dump) de la liste des billets. 
$newsList = $bf->getNewsList();
var_dump($newsList);

// Affichage (dump) du premier billet de la liste. 
$firstNews = $bf->getNewsDetail($newsList[0]->getId());
var_dump($firstNews);

echo '</pre>';
Le fichier BlogFacade.php :
/**
 * Vous pouvez utiliser cette façade pour extraire des informations
 * d'un blog dotclear : une liste sélective de posts ou le détail d'un
 * post. Cette classe peut être utile pour utiliser dotclear comme
 * gestionnaire de données ou pour faire de dotclear un multiblog.
 */

// Lien vers le fichier de configuration de dotclear. 
require_once 'chemin/vers/dotclear/conf/config.php';

// Nous allons avoir besoin de l'entité NewsItem. 
require_once 'NewsItem.php';

/**
 * Facade du blog dotclear. 
 * 
 * @copy    (c) Guillaume Ponçon 2005
 * @author  Guillaume Ponçon
 * @licence GPL
 * @version 0.1
 * @since   23 Dec 2005
 */
class BlogFacade {

    private $mysqli = null;
    private $rubrPrefix = '';

    /**
     * Ouvre la connex à la base du blog et définit les paramètres. 
     * 
     * @param string $rubr_prefix préfixe des catégories à filtrer.
     */
    public function __construct($rubr_prefix = null) {
        $this->mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DBASE);
        if (mysqli_connect_errno()) {
            printf("Connect failed: %s\n", mysqli_connect_error());
            exit();
        }
        if ($rubr_prefix) {
            $this->rubrPrefix = $rubr_prefix;
        }
    }

    /**
     * Ferme la connex à la base du blog.
     */
    public function __destruct() {
        $this->mysqli->close();
    }

    /**
     * Renvoit un tableau de NewsItems contenant la liste
     * complète des news.
     */
    public function getNewsList() {
        $ret_val = array();
        $query = "
          SELECT post_id, user_id, post_dt, post_titre, post_titre_url, 
            post_chapo, post_content, cat_libelle
          FROM ".DB_PREFIX."post, ".DB_PREFIX."categorie
          WHERE ".DB_PREFIX."post.cat_id = ".DB_PREFIX."categorie.cat_id
          AND ".DB_PREFIX."categorie.cat_libelle LIKE '".$this->rubrPrefix."%'
          AND ".DB_PREFIX."post.post_pub =1
          ORDER BY post_dt DESC ";
        $result = $this->mysqli->query($query);
        if ($result) {
            while ($row = $result->fetch_assoc()) {
                $news = new NewsItem();
                $news->setId($row['post_id']);
                $news->setTitle($row['post_titre']);
                $news->setUrl($row['post_titre_url']);
                $news->setResume($row['post_chapo']);
                $news->setBody($row['post_content']);
                $news->setDate($row['post_dt']);
                $news->setAuthor($row['user_id']);
                $news->setCategory(substr($row['cat_libelle'], 9));
                $ret_val[] = $news;
            }
            $result->close();
        }
        return $ret_val;
    }

    /**
     * Renvoit un NewsItem correspondant à la news $news_id.
     */
    public function getNewsDetail($news_id) {
        $ret_val = null;
        $query = "
          SELECT post_id, user_id, post_dt, post_titre, post_titre_url, 
            post_chapo, post_content, cat_libelle
          FROM ".DB_PREFIX."post, ".DB_PREFIX."categorie
          WHERE ".DB_PREFIX."post.cat_id = ".DB_PREFIX."categorie.cat_id
          AND ".DB_PREFIX."categorie.cat_libelle LIKE '".$this->rubrPrefix."%'
          AND post_id='".$news_id."' LIMIT 0, 1";
        $result = $this->mysqli->query($query);
        if ($result) {
            if ($row = $result->fetch_assoc()) {
                $news = new NewsItem();
                $news->setId($row['post_id']);
                $news->setTitle($row['post_titre']);
                $news->setUrl($row['post_titre_url']);
                $news->setResume($row['post_chapo']);
                $news->setBody($row['post_content']);
                $news->setDate($row['post_dt']);
                $news->setAuthor($row['user_id']);
                $news->setCategory(substr($row['cat_libelle'], 9));
                $ret_val =& $news;
            }
            $result->close();
        }
        return $ret_val;
    }
    
    /**
     * Vérifie si le contenu est une URL (utile pour mettre en place
     * un lien vers cette url plutôt que vers la news dans un flux RSS
     * par exemple).
     */
    public function isUrl($txt) {
        $txt = trim(strip_tags($txt));
        return (boolean) preg_match('/^http(s)?:\/\/[^ ]{1,300}$/', $txt);
    }

}
Le fichier NewsItem.php :
/**
 * Classe entité représentant une news (article dotclear)
 * à utiliser avec le contrôleur BlogFacade. 
 * 
 * @copy    (c) Guillaume Ponçon 2005
 * @author  Guillaume Ponçon
 * @licence GPL
 * @version 0.1
 * @since   23 Dec 2005
 */
class NewsItem {

    private $title;
    private $resume;
    private $body;
    private $author;
    private $date;
    private $url;
    private $id;
    private $category;

    /**
     * Getters & Setters
     */
    
    public final function getTitle()
    {
        return $this->title;
    }
    
    public final function setTitle($title)
    {
        $this->title = $title;
        return true;
    }   
    
    public final function getResume()
    {
        return $this->resume;
    }
    
    public final function setResume($resume)
    {
        $this->resume = $resume;
        return true;
    }   
    
    public final function getBody()
    {
        return $this->body;
    }
    
    public final function setBody($body)
    {
        $this->body = $body;
        return true;
    }   
    
    public final function getAuthor()
    {
        return $this->author;
    }
    
    public final function setAuthor($author)
    {
        $this->author = $author;
        return true;
    }   
    
    public final function getDate()
    {
        return $this->date;
    }
    
    public final function setDate($date)
    {
        $this->date = $date;
        return true;
    }   
    
    public final function getUrl()
    {
        return $this->url;
    }
    
    public final function setUrl($url)
    {
        $this->url = $url;
        return true;
    }   
    
    public final function getId()
    {
        return $this->id;
    }
    
    public final function setId($id)
    {
        $this->id = $id;
        return true;
    }   

    public final function getCategory()
    {
        return $this->category;
    }
    
    public final function setCategory($category)
    {
        $this->category = $category;
        return true;
    }
}
Pour plus d'infos :
http://masterflow.ath.cx/blog/index.php ... r-dotclear
Besoin de repères pour une utilisation PRO de PHP ?
Best practices PHP 5 (ouvrage en français !)

Eléphant du PHP | 493 Messages

30 avr. 2006, 21:05

Je n'aime pas trop ta dernière classe, c'est pourquoi je te propose la mienne, en remplacement. Elle utilise les fonctions magiques de PHP5 __get et __set.
class NewsItem
{
    private $data = array
    (
        'title' => '',
        'resume' => '',
        'body' => '',
        'author' => '',
        'date' => '',
        'url' => '',
        'id' => 0,
        'category' => 0
    );

    public function __get( $item )
    {
        if ( isset( $this->data[ $item ] ) )
        {
            return $this->data[ $item ];
        }
    }

    public function __set( $item, $value )
    {
        if ( isset( $this->data[ $item ] ) )
        {
            $this->data[ $item ] = $value;
        }
    }
}
Pour l'utiliser, il suffit de faire des appels standards : $object->prop qui va être en fait lire $object->data[ 'prop' ].

EDIT: Je viens de remarquer ta variable $rubrPrefix, inutile dans ton script :P

Eléphanteau du PHP | 24 Messages

02 mai 2006, 01:44

Je n'aime pas trop ta dernière classe, c'est pourquoi je te propose la mienne, en remplacement. Elle utilise les fonctions magiques de PHP5 __get et __set.
class NewsItem
{
    private $data = array
    (
        'title' => '',
        'resume' => '',
        'body' => '',
        'author' => '',
        'date' => '',
        'url' => '',
        'id' => 0,
        'category' => 0
    );

    public function __get( $item )
    {
        if ( isset( $this->data[ $item ] ) )
        {
            return $this->data[ $item ];
        }
    }

    public function __set( $item, $value )
    {
        if ( isset( $this->data[ $item ] ) )
        {
            $this->data[ $item ] = $value;
        }
    }
}
Pour l'utiliser, il suffit de faire des appels standards : $object->prop qui va être en fait lire $object->data[ 'prop' ].
Je connais cette pratique, que j'explicite d'ailleurs dans mon livre page 217 en simulant des accesseurs plutôt que des propriétés. C'est vrai que les méthodes magiques sont pratiques. Mais si je ne les utilisent pas pour les classes valuées comme celle-ci, c'est que j'y trouve à force quelques petits inconvénients :
  • Introduction de traitements supplémentaires (c'est peu, mais quand on multiplie les classes ça peut se ressentir).
  • Les petits traitements que l'on peut gérer dans chaque accesseurs (cast, vérifications d'intégrité, conversions en tous genres) sont souvent reportés dans les méthodes magiques qui du coup grossissent.
  • Enfin, les bons éditeurs PHP disposent d'une complétion sur les propriétés et les méthodes qui ne fonctionne plus avec une simulation par les méthodes magiques.
Maintenant, chaque est libre de faire ce qu'il veut en fonction de son expérience et de ses goûts :).
EDIT: Je viens de remarquer ta variable $rubrPrefix, inutile dans ton script :P
Cette variable sert à proposer une deuxième niveau de catégorisation.

Petit exemple : sur ton site de langages pour le web tu disposes de pages (rangées dans des rubriques), d'une liste de nouvelles, d'un annuaire et d'une page d'annonces.

Dans ce cas, chaque rubrPrefix va représenter un type de donnée : page, news, annuaire ou annonce, il faut alors déclarer des catégories comme ceci :
  • page_ruby
  • page_php
  • page_perl
  • news_ruby
  • news_php
  • news_perl
  • annonce_ruby
  • annonce_php
  • annonce_perl
  • (...)
Ainsi il est possible de batir un site dynamique complet et très facile à administrer, ou un multiblog, avec un simple dotclear.
Besoin de repères pour une utilisation PRO de PHP ?
Best practices PHP 5 (ouvrage en français !)

Eléphant du PHP | 493 Messages

02 mai 2006, 10:53

Autant pour moi, je n'avais pas vu ceci :
 ... "categorie.cat_libelle LIKE '".$this->rubrPrefix."%' AND " ...