Probleme avec la lib SPL

windofo Messages postés 4 Date d'inscription dimanche 22 novembre 2009 Statut Membre Dernière intervention 18 décembre 2009 - 26 nov. 2009 à 12:02
windofo Messages postés 4 Date d'inscription dimanche 22 novembre 2009 Statut Membre Dernière intervention 18 décembre 2009 - 18 déc. 2009 à 10:01
Bonjour,
j'ai mis un peu le nez dans la lib SPL, et j'ai voulu m'inspirer du code source de malalam (j'en profite pour le remercier ainsi que tous les autres (neige, etc.) pour leurs nombreuses contributions)) pour faire un parcours de répertoire tout simple et j'avoue ne pas comprendre certain fonctionnement, entre les erreurs de segmentation et les dossiers répétés plusieurs fois je suis un peu perdu...

voici le code source:
class Dossier_RecursiveDirectoryIterator extends RecursiveDirectoryIterator {

     /**
      * affiche les dossiers
      *
      * @var boolean
      */
     protected $bDir = true;

     /**
      * affiche les fichiers
      *
      * @var boolean
      */
     protected $bFile = true;

     /**
      * filtrer les dossiers suivant une expression régulière
      *
      * @var string
      */
     protected $sRegExpDir = '^.*$';

     /**
      * filtrer les fichier suivant une expression régulière
      *
      * @var string
      */
     protected $sRegExpFile = '^.*$';

     /**
      * parcours recursif
      *
      * @var boolean
      */
     protected $bRecurse = true; 

     /**
      * propriétés qui peuvent être définies
      *
      * @var array
      */
     protected $aCanBeSet = array (
     'REGEXP_DIR',
     'REGEXP_FILE',
     'DIR',
     'FILE',
     'PATH',
     'RECURSE'
     ); 

     /**
      * path
      *
      * @var string (valid path)
      */
     protected $sPath;
        

      /**
      * messages d'erreur
      *
      * @var string
      */
     const ERROR_PATH_NOT_FOUND = '{__PATH__} n\'a pas été trouvé';
     const ERROR_PROP_NOT_SETABLE = '{__PROP__} n\'est pas une propriété ';
     const ERROR_BAD_PROP_VALUE = '{__VAL__} n\'est pas une valeur correcte pour la propriété: {__PROP__}';
          
     /**
      * getChildren
      *
      * @return subiterator 
      */
      public function getChildren () {        
      	$iSub = new self ($this -> getPathname ());
$iSub -> bDir = $this -> bDir;
$iSub -> bFile = $this -> bFile;
$iSub -> sRegExpDir = $this -> sRegExpDir;
$iSub -> sRegExpFile = $this -> sRegExpFile;
return $iSub; 
      }

     /**
      * path
      *
      * @return string
      */
    public function key () {
        return $this -> getPath ();
    }

    /**
      * retourne la valeur du fichier ou du dossier courant
      *
      * @return string
      */
    public function current () {
         return $this -> getFileName ();
    }

    /**
     * vérifie si il y a un élément existant apres avoir appelé rewind() ou next().
     *
     * @return boolean
     */
     public function valid () {     	
     	if (true === parent::valid ()) {
        	if (true === $this -> isDir ()) {
    			if (false === $this -> bDir || !preg_match ($this -> sRegExpDir, $this -> current())) {
                 $this -> next ();
                 return $this -> valid ();
            } else {
            	return true;
            }        
        } else {
    			if (false === $this -> bFile || !preg_match ($this -> sRegExpFile, $this -> current())) {
                 $this -> next ();
                 return $this -> valid ();
            } else {
            	return true;
            }
        }
     	}
        return false;
    }

    /**
     * vérification des propriétés via la méthode magique __set
     *
     * @param string $sProp
     * @param mixed $mVal
     */
     public function __set ($sProp, $mVal) {
          if (!in_array ($sProp, $this -> aCanBeSet)) {
               throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_PROP_NOT_SETABLE));
          }
          switch ($sProp) {
               case 'REGEXP_DIR' :
               		if (!is_string ($mVal)) {
                         throw new Exception (str_replace (array ('{__VAL__}', '{__PROP__}'), array ($mVal, $sProp), self::ERROR_BAD_PROP_VALUE));
                    }
                    $this -> sRegExpDir = $mVal;
                    break;
               case 'REGEXP_FILE' :
                    if (!is_string ($mVal)) {
                         throw new Exception (str_replace (array ('{__VAL__}', '{__PROP__}'), array ($mVal, $sProp), self::ERROR_BAD_PROP_VALUE));
                    }
                    $this -> sRegExpFile = $mVal;
                    break;
               case 'DIR' :
                    if (!is_bool ($mVal)) {
                         throw new Exception (str_replace (array ('{__VAL__}', '{__PROP__}'), array ($mVal, $sProp), self::ERROR_BAD_PROP_VALUE));
                    }
                    $this -> bDir = $mVal;
                    break;
               case 'FILE' :
                    if (!is_bool ($mVal)) {
                         throw new Exception (str_replace (array ('{__VAL__}', '{__PROP__}'), array ($mVal, $sProp), self::ERROR_BAD_PROP_VALUE));;
                    }
                    $this -> bFile = $mVal;
                    break;
               case 'RECURSE' :
                    if (!is_bool ($mVal)) {
                         throw new Exception (str_replace (array ('{__VAL__}', '{__PROP__}'), array ($mVal, $sProp), self::ERROR_BAD_PROP_VALUE));
                    }
                    $this -> bRecurse = $mVal;
                    break;
               case 'PATH' :
                    if (!is_dir ($mVal)) {
                         throw new Exception (str_replace ('{__PATH__}', $mVal, self::ERROR_PATH_NOT_FOUND));
                    }
                    $this -> sPath = $mVal;
                    break;
          }
     }
} 

class Dossier_Dir extends Dossier_RecursiveDirectoryIterator {

     /**
      * Itérateur
      *
      * @var iterator
      */
    private $iterator = null;

     /**
      * messages d'erreur
      *
      * @var string
      */
      const ERROR_NBR_ARG = 'Le nombre d\'arguments est incorrect';
      const ERROR_TYPE_ARG = 'Le type d\'argument est incorrect';

    /**
     * Constructeur
     * 
     *
     * @param string $sPath (valid path)
     */
public function __construct ($sPath) {
    	if (!is_dir ($sPath)) {
        	throw new Exception (str_replace ('{__PATH__}', $sPath, self::ERROR_PATH_NOT_FOUND));
        }
        $this -> sPath = $sPath;
    }

    /**
     * construction d'un itérateur du répertoire venant d'un chemin (string)
     *
     * @return iterator
     */
public function getDir () {
parent::__construct ($this -> sPath, 0);
if (true === $this -> bRecurse) {
$this -> iterator = new RecursiveIteratorIterator ($this, RecursiveIteratorIterator::LEAVES_ONLY);
} else {
$this -> iterator = $this;	
}

        return $this -> iterator;
    }
    
    /**
     * ajout de filtres 
     * - addFilter ('filtre_1', 'val', 'filtre_2', true, etc.)
     * - addFilter (array('filtre_1' => 'val', 'filtre_2' => true, etc.))
     *
     * @param mixed
     */
    public function addFilter () {
    	$oArg = new ArrayObject (func_get_args ());
    	$it = $oArg -> getIterator ();
    	$numbArg = $it -> count ();
    	if ($numbArg > 1 && 0 == bcmod ($numbArg, 2)) {
    		while ($it -> valid ()) { 
    			$prop = $it -> current ();
    			$it -> next ();
    			$val = $it -> current ();
    			if (is_string ($prop) && !empty ($prop)) {
    				$this -> $prop = $val;
    				$it -> next (); 
    			} else {
    				throw new Exception (self::ERROR_TYPE_ARG);
    			} 
    	}  		
    	} else if (1 == $numbArg) {
    		$aArg = $it -> current ();
    		if (is_array ($aArg) && !empty ($aArg)) {
    			foreach($aArg AS $prop => $val) {
    				if (is_string ($prop) && !empty ($prop)) {
    					$this -> $prop = $val;
    			} else {
    				throw new Exception (self::ERROR_TYPE_ARG);
    			} 
    			}
    		} else {
    			throw new Exception (self::ERROR_TYPE_ARG);
    		}    		
    	} else if ($numbArg > 1) {
    		throw new Exception (self::ERROR_NBR_ARG);
    	}	    
 }
    
    
} 



voici mon test:
try {
     $oDir = new Dossier_Dir ('/usr/dossier/');
} catch (Exception $e) {
     echo $e -> getMessage ();
} 

$oDir -> addFilter ('RECURSE', true, 'REGEXP_DIR', '/^[0-9]{2}$/', 'REGEXP_FILE', '/^FILE$/');
$aDir = $oDir -> getDir (); 

while ($aDir -> valid ()) {
if ($aDir -> isDot ()) {
$aDir -> next ();
}
if ($aDir -> isDir ()) {
print "dossier: " . $aDir -> current (). "\n";
} else {
print "fichier: " . $aDir -> current () . "\n";
}
$aDir -> next ();
}


dans mon exemple j'ai une série de répertoire avec les fichiers comme ci dessous:
01
- FILE1
- FILE2
02
- FILE3
- FILE4
03
04
tmp

mon test devrait m'afficher:
01
- FILE1
- FILE2
02
- FILE3
- FILE4
03
04

pourtant j'ai ce résultat:
01
01
- FILE1
- FILE2
02
- FILE3
- FILE4
03
04

et si je ne précise pas d'expression régulière j'ai en plus des résultats précédents plein de lignes avec des warnings
Warning: preg_match(): No ending delimiter '^' found in /Dossier/RecursiveDirectoryIterator.php on line 142
etc..

si vous avez une idée...

merci d'avance
Wind

2 réponses

neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
30 nov. 2009 à 21:27
Salut,

Pourquoi utilises-tu une boucle while et pas une boucle foreach ? Foreach sert justement à itérer sur des tableaux, ou des objets implémentant Traversable. Foreach va automatiquement exécuter rewind(), valid(), next(), etc.
Avec ta boucle while(), tu cherches à reproduire le comportement de l'itération produite par foreach, mais je me demande si tu ne la reproduis pas avec une erreur qui expliquerait la duplication du premier répertoire.
Idem dans ta méthode addFilter()...
Sincèrement, utilise foreach() qui sert spécialement à l'itération, alors que while() pas du tout.

Concernant isDot(), par défaut, RecursiveDirectoryIterator ne tient pas compte des dossiers points. En tout cas, dans ma source (dont il me semble que tu t'es inspirée sur certains points), je ne m'occupe pas de isDot()...

Pour tes expressions réulières, le problème est qu'elles ne sont effectivement pas valides, comme l'indique le message d'erreur ;)
protected $sRegExpDir = '^.*$';
protected $sRegExpFile = '^.*$';


Ce sont des PCRE, il faut spécifier le délimiteur... Par exemple :
protected $sRegExpDir = '`^.*$`';
protected $sRegExpFile = '`^.*$`';


Du coup, je constate que tu exécutes à CHAQUE itération l'expression régulière... Si c'est pour tout laisser passer, je trouve dommage de bouffer des ressources en PCRE inutile...

--
Neige

Souvent la réponse à votre question se trouve dans la doc. Commencez par là ;)
0
windofo Messages postés 4 Date d'inscription dimanche 22 novembre 2009 Statut Membre Dernière intervention 18 décembre 2009
18 déc. 2009 à 10:01
je te remercie pour ta réponse, je vais bricoler ca ce we
Wind
0
Rejoignez-nous