[php5] smartdir : les itérateurs en php - lecture intelligente de répertoire

Description

J'ai décidé de montrer toute la puissance de la SPL (Standard PHP Library) et des itérateurs en PHP5.
Ce package est à personnaliser. Il permet la lecture récursive ou non de répertoire, en appliquant, ou non, des filtres.
FILTER_ON fait un filtre montrant uniquement les fichiers correspondant aux masques :
oSmartDir::FILTER_ON = 'php';
Va filtrer sur les fichiers contenant'php'.
oSmartDir::FILTER_ON = array ('php, 'html', 'js');
va filtrer sur les fichiers contenant php, html, ou js.

FILTER_OFF faut un filtre négatif :
oSmartDir::FILTER_OFF = 'php';
ne montrera que les fichiers ne contenant pas 'php'.
Peut aussi être un tableau de masques.

oSmartDir::DIr = false;
Ne lira pas les répertoire

oSmartDir::FILE = false;
ne montrera pas les fichiers

oSmartDir::RECURSE = false;
Ne lira pas récursivement.

On peut évidemment modifier ces filtres via la méthode myFilter::valid ()

Méthodes :
oSmartDir::getDir ();
permet simplement de récupérer l'itérateur pour l'arborescence définie via les filtres (ou non, d'ailleurs).
Plus tard, j'implémenterai de nouvelles méthodes "outils" : copie, déplacement etc...en tenant compte des filtres.
//////
J'ai mis une méthode copy ().
Attention, elle est effective sur le fichier d'exemple : le zip contient toute une arborescence. Le fichier exemple lit cette arbo avec divers filtres, pour donner quelques exemples, puis crée un répertoire copie/ dans lequel il copie toute l'arborescence, mais en ne prenan t en compte que les fichiers contenant 'php'.
//////

J'ai volontairement montré un package assez complexe...mais la lecture d'un répertoire de manière récursive peut se faire en 3 lignes grâce aux itérateurs :
<?php

$dir = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('.'), true);

foreach ( $dir as $file ) {
echo str_repeat('-', $dir->getDepth()) . ' '.$file.'<br />';
}
?>
Essayez ce code : il va lire récursivement le répertoire courant (donc, avec ses sous-répertoires), tout en indentant en fonction de l'arborescence.
Si si...!

Source / Exemple :


<?php
/**

  • smartDir package
  • @author Johan Barbier <johan.barbier@gmail.com>
  • @version 20011120
  • /
/**
  • class myFilter
  • check active filters
  • RecursiveFilterIterator child
  • /
class myFilter extends RecursiveFilterIterator { /**
  • active filter ON (keep these)
*
  • @var mixed
  • /
private $mFilterOn; /**
  • active filter OFF (do not keep these)
*
  • @var mixed
  • /
private $mFilterOff; /**
  • iterator
*
  • @var iterator
  • /
private $it = null; /**
  • error message
*
  • @var string
  • /
const ERROR_NO_VALID_FILTER = '{__FILTER__} is not a valid setable filter'; /**
  • Constructor
*
  • @param iterator $it
  • @param mixed $mFilterOn
  • @param mixed $mFilterOff
  • /
public function __construct ($it, $mFilterOn, $mFilterOff) { parent::__construct ($it); $this -> it = $it; $this -> mFilterOn = $mFilterOn; $this -> mFilterOff = $mFilterOff; } /**
  • Function accept ()
  • returns true or false if the current element is accepted or not
*
  • @return boolean
  • /
public function accept () { if (!is_null ($this -> mFilterOn)) { if (!is_array ($this -> mFilterOn)) { $mPos = strpos ($this -> it -> getFileName (), (string)$this -> mFilterOn); if (false === $mPos) { return false; } } else { foreach ($this -> mFilterOn as $sFilter) { $mPos = strpos ($this -> it -> getFileName (), (string)$sFilter); if (false !== $mPos) { return true; } } return false; } } if (!is_null ($this -> mFilterOff)) { if (!is_array ($this -> mFilterOff)) { $mPos = strpos ($this -> it -> getFileName (), (string)$this -> mFilterOff); if (false !== $mPos) { return false; } } else { foreach ($this -> mFilterOff as $sFilter) { $mPos = strpos ($this -> it -> getFileName (), (string)$sFilter); if (false !== $mPos) { return false; } else { return true; } } return false; } } return true; } } /**
  • Class MyRecursiveDirectoryIterator
  • parent of main class, RecursiveDirectoryIterator child
*
  • /
class MyRecursiveDirectoryIterator extends RecursiveDirectoryIterator { /**
  • are dir valid
*
  • @var boolean
  • /
protected $bDir = true; /**
  • are files valid
*
  • @var boolean
  • /
protected $bFile = true; /**
  • filter ON (keep these)
*
  • @var mixed
  • /
protected $mFilterOn = null; /**
  • filter OFF (do not keep these)
*
  • @var mixed
  • /
protected $mFilterOff = null; /**
  • Recursive dir or not
*
  • @var boolean
  • /
protected $bRecurse = true; /**
  • props that can be set
*
  • @var array
  • /
protected $aCanBeSet = array ( 'FLAG', 'FILTER_ON', 'FILTER_OFF', 'DIR', 'FILE', 'PATH', 'RECURSE' ); /**
  • filter ON (keep these)
*
  • @var RecursiveDirectoryIterator class constant
  • /
protected $cFlag = 0; /**
  • path to be read
*
  • @var string (valid path)
  • /
protected $sPath; protected $sCreatedDir = null; /**
  • error messages
*
  • @var string
  • /
const ERROR_PATH_NOT_FOUND = '{__PATH__} has not been found'; const ERROR_PROP_NOT_SETABLE = '{__PROP__} is not a setable property'; const ERROR_BAD_PROP_VALUE = '{__VAL__} is not a correct value for {__PROP__}'; const ERROR_NO_BOOLEAN = '{__PROP__} value must be a boolean'; /**
  • getChildren will retrieve sub path
*
  • @return subiterator
  • /
public function getChildren () { $iSub = new self ($this -> getPathname ()); $iSub -> bDir = $this -> bDir; $iSub -> bFile = $this -> bFile; $iSub -> mFilterOn = $this -> mFilterOn; $iSub -> mFilterOff = $this -> mFilterOff; return $iSub; } /**
  • get current key
*
  • @return string
  • /
public function key () { return $this -> getPath (); } /**
  • get current file
*
  • @return string
  • /
public function current () { return $this -> getFileName (); } /**
  • is the current element valid or not
*
  • @return boolean
  • /
public function valid () { if (!is_null ($this -> sCreatedDir)) { if ($this -> current () === $this -> sCreatedDir) { return false; } } $oFilter = new myFilter ($this, $this -> mFilterOn, $this -> mFilterOff); if (true === parent::valid ()) { if (false === $oFilter -> accept ()) { if (false === $this -> isDir ()) { parent::next (); return $this -> valid (); } else { return true; } } if (false === $this -> bDir) { if (true === $this -> isDir ()) { parent::next (); return $this -> valid (); } } if (false === $this -> bFile) { if (true === $this -> isFile ()) { parent::next (); return $this -> valid (); } } return true; } return false; } /**
  • Setter
*
  • @param string $sProp
  • @param mixed $mVal
  • /
public function __set ($sProp, $mVal) { if (!in_array ($sProp, $this -> aCanBeSet)) { throw new Exception (str_replace ('{__PATH__}', $sProp, self::ERROR_PROP_NOT_SETABLE)); } switch ($sProp) { case 'FLAG' : if (!in_array ($mVal, array (parent::CURRENT_AS_FILEINFO, parent::KEY_AS_FILENAME, parent::NEW_CURRENT_AND_KEY, 0))) { throw new Exception (str_replace (array ('{__VAL__}', '{__PROP__}'), array ($mVal, $sProp), self::ERROR_PATH_NOT_FOUND)); } $this -> cFlag = $mVal; break; case 'FILTER_ON' : $this -> mFilterOn = $mVal; $this -> mFilterOff = null; break; case 'FILTER_OFF' : $this -> mFilterOff = $mVal; $this -> mFilterOn = null; break; case 'DIR' : if (!is_bool ($mVal)) { throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_NO_BOOLEAN)); } $this -> bDir = $mVal; break; case 'FILE' : if (!is_bool ($mVal)) { throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_NO_BOOLEAN)); } $this -> bFile = $mVal; break; case 'RECURSE' : if (!is_bool ($mVal)) { throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_NO_BOOLEAN)); } $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 oSmartDir
  • MyRecursiveDirectoryIterator child
*
  • /
class oSmartDir extends MyRecursiveDirectoryIterator { /**
  • Constructor
*
  • @param string $sPath (valid path)
  • /
const ERROR_COPY_FAILED = 'Failed to copy {__FROM__} to {__TO__}'; public function __construct ($sPath) { if (!is_dir ($sPath)) { throw new Exception (str_replace ('{__PATH__}', $sPath, self::ERROR_PATH_NOT_FOUND)); } $this -> sPath = $sPath; } /**
  • getDir will retrieve the asked directory
*
  • @return iterator
  • /
public function getDir () { parent::__construct ($this -> sPath, $this -> cFlag); if (true === $this -> bRecurse) { return new RecursiveIteratorIterator ($this, true); } else { return $this; } } public function copy ($sTo) { $aDir = $this -> getDir (); if (!is_dir ($sTo)) { mkdir ($sTo, '0755'); } $this -> sCreatedDir = $sTo; while ($aDir -> valid ()) { if ($aDir -> current () !== $sTo && !$aDir -> isDot ()) { if (!$aDir -> isDir ()) { if (!@copy ($aDir -> getPathName (), $sTo.'/'.$aDir -> getPathName ())) { throw new Exception (str_replace (array ('{__FROM__}', '{__TO__}'), array ($aDir -> getPathName (), $sTo.'/'.$aDir -> getPathName ()), self::ERROR_COPY_FAILED)); } } else { if (!@mkdir ($sTo.'/'.$aDir -> getPathName (), '0755')) { throw new Exception (str_replace (array ('{__FROM__}', '{__TO__}'), array ($aDir -> getPathName (), $sTo.'/'.$aDir -> getPathName ()), self::ERROR_COPY_FAILED)); } } } $aDir -> next (); } $this -> sCreatedDir = null; } } /**
  • STARTING EXAMPLES
  • /
try { $oDir = new oSmartDir ('.'); } catch (Exception $e) { echo $e -> getMessage (); } try { echo '<br /><strong>ALL NO RECURSIVE</strong><br />'; $oDir -> RECURSE = false; // no recursivity $aDir = $oDir -> getDir (); while ($aDir -> valid ()) { if ($aDir -> isDot ()) { $aDir -> next (); } $sHtml = ''; if ($aDir -> isDir ()) { $sHtml.= '<strong>'.$aDir -> current ().'</strong>'; } else { $sHtml.= '<em>'.$aDir -> current ().'</em>'; } $sHtml .= '<br />'; echo $sHtml; $aDir -> next (); } echo '<br /><strong>ALL</strong><br />'; $oDir -> RECURSE = true; // recursivity back to true $aDir = $oDir -> getDir (); while ($aDir -> valid ()) { if ($aDir -> isDot ()) { $aDir -> next (); } $sHtml = str_repeat ('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;', $aDir -> getDepth ()); if ($aDir -> isDir ()) { $sHtml.= '<strong>'.$aDir -> current ().'</strong>'; } else { $sHtml.= '<em>'.$aDir -> current ().'</em>'; } $sHtml .= '<br />'; echo $sHtml; $aDir -> next (); } echo '<br /><strong>ALL + fileSize</strong><br />'; $oDir -> RECURSE = true; // recursivity back to true $aDir = $oDir -> getDir (); while ($aDir -> valid ()) { if ($aDir -> isDot ()) { $aDir -> next (); } $sHtml = str_repeat ('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;', $aDir -> getDepth ()); if ($aDir -> isDir ()) { $sHtml.= '<strong>'.$aDir -> current ().'</strong>'; } else { $sHtml.= '<em>'.$aDir -> current ().' '.round (($aDir -> getSize()/1024), 2).' Ko</em>'; } $sHtml .= '<br />'; echo $sHtml; $aDir -> next (); } echo '<br /><strong>ALL</strong><br />'; $aDir = $oDir -> getDir (); foreach ($aDir as $sK => $sV) { echo str_repeat ('-----', $aDir -> getDepth()), $sK, ' => ', $sV, '<br />'; } echo '<br /><strong>FILTRE ON SUR PHP</strong><br />'; $oDir -> FILTER_ON = 'php'; // only shows files with "php" in them $aDir = $oDir -> getDir (); foreach ($aDir as $sK => $sV) { echo str_repeat ('-----', $aDir -> getDepth()), $sK, ' => ', $sV, '<br />'; } echo '<br /><strong>DIR = FALSE</strong><br />'; $oDir -> DIR = false; // No directory $oDir -> FILTER_ON = null; // no filter ON $aDir = $oDir -> getDir (); foreach ($aDir as $sK => $sV) { echo str_repeat ('-----', $aDir -> getDepth()), $sK, ' => ', $sV, '<br />'; } echo '<br /><strong>FILE = FALSE</strong><br />'; $oDir -> DIR = true; // show directories $oDir -> FILE = false; // No files $aDir = $oDir -> getDir (); foreach ($aDir as $sK => $sV) { echo str_repeat ('-----', $aDir -> getDepth()), $sK, ' => ', $sV, '<br />'; } echo '<br /><strong>PATH = bla ET FILTRE OFF SUR PHP</strong><br />'; $oDir -> PATH = 'bla'; // parth = 'bla' $oDir -> FILE = true; // show files $oDir -> FILTER_OFF = 'php'; // do not show files with "php" in them $aDir = $oDir -> getDir (); foreach ($aDir as $sK => $sV) { //echo $sK, ' => ', $sV, '<br />'; echo str_repeat ('-----', $aDir -> getDepth()), $sK, ' => ', $sV, '<br />'; } /**
  • Create a copy of the whole directory recursively, but ONLY copy files with php in them ;-)
  • /
$oDir -> FILTER_ON = 'php'; $oDir -> PATH = '.'; $oDir -> copy ('copie'); } catch (Exception $e) { echo $e -> getMessage (), ' => ', $e -> getLine (); } ?>

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.