surcharge d'une fonction, conversion vers un objet plus larg

Petit nouveau ! | 6 Messages

04 sept. 2011, 17:28

Bonjour, je désire faire un lecteur de flux RSS en utilisant la POO.
Voila comment j'organise mon lecteur :

un objet FeedReader : il possède une liste de flux, il a la capacité d'en ajouter, et surtout de les afficher.
un objet Feed : il représente le flux. Il étend de DOMDocument. il est une liste d'item qu'il doit être capable de ranger dans un ordre quelconque. Il connaît aussi
un objet FeedItem : il représente un item du flux. Il étend de DOMNode. Il connait les données de l'information.

Lorsque je crée ma liste de FeedItem, dans l'objet Feed, j'utilise getElementsByTagName(). Celui-ci me renvoie une DOMNodeListe qui ne contient que des DOMNode, et pas des FeedItem.
Il me faudrait donc que cette fonction me renvoie des feedItem.

Voici mes objets (la plupart des fonctions ne sont pas encore implémentées):
FeedReader
<?php

class FeedReader {
    const FULL_MODE=1;
    const SHORT_MODE=2;
    const DISPLAY_ALL=1;
    /**
     *
     * @var SPLObjectStorage stockage des flux
     */
    protected $feeds;
    
    public function __construct(){
        $this->feeds=new SplObjectStorage();
    }
    
    public function load($url){
        $feed=new DOMDocument();
        $feed->load($url);
        $this->feeds->attach($feed, $url);
        
    }
    public function display($mode,$feed=null){
        if(is_array($feed)){
            
        }
        else if($feed instanceof Feed && $this->feeds->offsetExists($feed)){
            
        }
        else if($feed == self::DISPLAY_ALL){
            
        }
        else{
            throw new InvalidArgumentException('Mauvais argument donné à display : attendu DISPLAY_ALL, DISPLAY_FIRST, DISPLAY_LAST, Feed ou array '
                    .  print_r($feed,true));
        }
    }
    
}
Feed
<?php 
class Feed extends DOMDocument{
    /**
     *
     * @var DOMNodeList
     */
    protected $liste;
    
    const ASC_SORT_MODE=1;
    const DESC_SORT_MODE=2;
    
    public function getElementsByTagName($name) {
    }
    
    public function sort($mode=self::DESC_SORT_MODE){
        
    }
}
FeedItem
<?php
class FeedItem extends DOMNode implements ArrayAccess{
    
    /**
     * 
     * @return DateTime la date du flux
     */
    public function getDate(){
        
    }
    
    public function getAutor(){
        
    }
    
    public function getContent(){
        
    }
    
    public function getDescription(){
        
    }
    
    public function offsetExists($offset) {
        return is_callable(array($this, 'get'.ucfirst($offset)));
    }
    public function offsetGet($offset) {
       
    }
    public function offsetSet($offset, $value) {
        
    }
    public function offsetUnset($offset) {
        throw new RuntimeException('Impossible de supprimer un attribut');
    }
}

peut être puis-je faire autrement sinon?

ViPHP
xTG
ViPHP | 7331 Messages

04 sept. 2011, 20:38

Pour ce que je comprends du problème avec une lecture en diagonale je ferrai ainsi :
public function getElementsByTagName($name) {
  $retour_non_formate = parent::getElementsByTagName($name);
  // formatage du retour ......
   
  return $retour_formate;
}
Cela pourrait-il convenir ? :)

Et donc cela impliquerai un constructeur par "copie" pour la class FeedItem pour faire la conversion.

Petit nouveau ! | 6 Messages

04 sept. 2011, 21:11

oui, mais ce que je voudrais savoir justement c'est comment formater le retour. Et surtout comment rendre ça logique par rapport à mon organisation.

ViPHP
xTG
ViPHP | 7331 Messages

05 sept. 2011, 07:44

C'est du même acabit que de copier en un tableau dans un autre en effectuant une opération entre les deux (une addition par exemple sur chacune des cases).

Tu parcours ton DomNodeList et tu réupères chaque DomNode.
Ensuite vu qu'il y a y pas l'air d'avoir de constructeur, tu remplaces chaque DomNode (http://fr2.php.net/manual/en/domnode.replacechild.php) avec sa copie créée à partir de ta nouvelle class FeedItem (à laquelle il faudra ajouter un constructeur).
Après j'ai pas testé, mais le principe est là.
replaceChild() attend un objet DomNode mais comme ta class hérite de cette class, feedItem EST un DomNode.

Petit nouveau ! | 6 Messages

05 sept. 2011, 07:49

j'avais pas pensé à replaceChild tiens.
maintenant j'ai plus qu'à tester en ce qui concerne la création d'un FeedItem à partir d'un DOMNode

Petit nouveau ! | 6 Messages

05 sept. 2011, 13:57

Bon, voila ce que j'ai fait, je n'ai pas encore testé mais ça va venir :
<?php

/**
 * Represents a RSS/ATOM feed item. 
 *
 * @author isen
 */
class FeedItem extends DOMElement implements ArrayAccess{
    const LABEL='item';
    /**
     * 
     * @return DateTime la date du flux
     */
    public function getDate(){
        
    }
    
    public function getAutor(){
        
    }
    
    public function getContent(){
        
    }
    
    public function getDescription(){
        
    }
    
    public function offsetExists($offset) {
        return is_callable(array($this, 'get'.ucfirst($offset)));
    }
    public function offsetGet($offset) {
       
    }
    public function offsetSet($offset, $value) {
        
    }
    /**
     * delete an option. forbidden action.
     * @param mixed $offset 
     */
    public function offsetUnset($offset) {
        throw new RuntimeException('Impossible de supprimer un attribut');
    }
    public function __construct($value='',$uri=''){
        parent::__construct(self::LABEL, $value, $uri);
    }
    /**
     * create a FeedItem from a DOMNode node. 
     * @param DOMNode $node
     * @return FeedItem 
     */
    public static function createFromNode(DOMNode $node){
        $instance=new FeedItem();
       foreach($node->childnodes as $cnode){
           $instance->appendChild($cnode);
       }
       return $instance;
    }
}

/**
 * Represents a RSS/Atom feed with his list of items. 
 *
 * @author isen
 */
class Feed extends DOMDocument{
    
    
    const ASC_SORT_MODE=1;
    const DESC_SORT_MODE=-1;
    /**
     *
     * @param string $name name of tag to fetch
     * @return ArrayObject
     */
    private function getElementsByTagName($name) {
        $parentListe=parent::getElementsByTagName($name);
        $newList=new ArrayObject();
        foreach($parentListe as $node){
            $newList[]=FeedItem::createFromNode($node);
            
        }
        return $newList;
    }
    
    /**
     *
     * @param int $mode sort mode
     * @return ArrayObject
     */
    public function sort($mode=self::DESC_SORT_MODE){
        $liste=$this->getElementsByTagName('item');
        if($mode===self::DESC_SORT_MODE)
        $liste->uasort(function(FeedItem $feed1, FeedItem $feed2){
            if($feed1->getDate()==$feed2->getDate())return 0;
            else return ($feed1->getDate()>$feed2->getDate())?1:-1;
            
        });    
        else $liste->uasort(function(FeedItem $feed1, FeedItem $feed2){
            if($feed1->getDate()==$feed2->getDate())return 0;
            else return ($feed1->getDate()>$feed2->getDate())?-1:1;
            
        });
        
        return $liste;
    }
}

Petit nouveau ! | 6 Messages

07 sept. 2011, 09:35

Je viens, grâce à l'aide d'un membre du site du zéro, de découvrir une fonction native de php qui permet de faire ce que je veux sans problèmes :
Il suffit que dans le constructeur de Feed je mette : $this>registerNodeClass('DOMNode', 'FeedItem');