Lire le contenu d'un répertoire
La base de la class ProjectStat est la fonction récursive permettant de lister le contenu d'un répertoire avec PHP. Ensuite on y ajoute la détection du type de fichier en 4 catégories:
- FILETYPE_PHP: class de programmation contenu du code source PHP,
- FILETYPE_WEB: contenu ou fonction du site internet, à savoir page HTML, fonction Javascript ou feuille de style css,
- FILETYPE_DATA: fichier de données au format csv ou dat, par exemple les traductions en plusieurs langues,
- FILETYPE_OTHER: ce sont les fichiers binaires: image, pdf, ...
Pour les class PHP et les données au format ASCII, la class ProjectStat détermine le nombre de ligne que contient chaque fichier et les additionne.
<?php
/**
* Obtenir le contenu d'un projet internet
* Auteur BlackBear le 09/07/2014
* http://www.fobec.com/php5/1149/obtenir-contenu-projet-internet.html
*/
class ProjectStat {
public $filesinfo = array();
private $path_root = '';
const FILETYPE_PHP = 1; //prog
const FILETYPE_WEB = 2; //web
const FILETYPE_DATA = 3; //dat csv
const FILETYPE_OTHER = 5; // img
/**
* Lancer le scan d'un dossier
* @param type $path_root
* @param type $recursif
*/
public function scan($path_root, $recursif = FALSE) {
if (is_dir($path_root)) {
$this->path_root = $path_root;
$this->scan_internal($path_root, $recursif);
}
}
/**
* Lister le contenu d'un dossier
* @param string $path
* @param type $recursif
*/
private function scan_internal($path, $recursif) {
$dhandle = opendir($path);
if ($dhandle) {
$path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
while (($file = readdir($dhandle)) !== false) {
if ($file != '.' && $file != '..' && substr($file, -1) != '~') {
if (!is_dir($path . $file)) {
if ($this->file_isBinary($path . $file) == FALSE) {
$n = array('path' => $path, 'name' => $file,
'linecount' => $this->fileLineCount($path . $file),
'size' => @filesize($path . $file));
$file_type = $this->filetype($path . $file);
$n['type'] = $file_type;
} else {
$n = array('path' => $path, 'name' => $file,
'linecount' => 0, 'size' => @filesize($path . $file),
'type' => self::FILETYPE_OTHER);
}
$this->filesinfo[] = $n;
} //end is_dir
else if ($recursif == TRUE) {
$this->scan_internal($path . $file, $recursif);
}
}
}
closedir($dhandle);
}
}
/**
* Retourne les statistiques d'un projet internet
* @param type $asString
* @return type
*/
public function stat_type($asString = false) {
$nstat = array(self::FILETYPE_PHP => array('filecount' => 0, 'linecount' => 0, 'filesize' => 0),
self::FILETYPE_WEB => array('filecount' => 0, 'linecount' => 0, 'filesize' => 0),
self::FILETYPE_DATA => array('filecount' => 0, 'linecount' => 0, 'filesize' => 0),
self::FILETYPE_OTHER => array('filecount' => 0, 'linecount' => 0, 'filesize' => 0));
$size = 0;
$sub_dir = array();
$count_file = 0;
$count_code_line = 0;
$count_code_data = 0;
foreach ($this->filesinfo as $file) {
$nstat[$file['type']]['filecount']++;
$nstat[$file['type']]['linecount']+=$file['linecount'];
$nstat[$file['type']]['filesize']+=$file['size'];
$size+=$file['size'];
//String
$sub_dir[] = $file['path'];
$count_file++;
if ($file['type'] == self::FILETYPE_PHP) {
$count_code_line+=$file['linecount'];
} else if ($file['type'] == self::FILETYPE_DATA) {
$count_code_data+=$file['linecount'];
}
}
if ($asString == false) {
return $nstat;
}
//Function toString() de JAVA
else {
$count_subdir = count(array_unique($sub_dir)) - 1;
$buf = 'Analyse du dossier ' . $this->path_root . "n";
$buf.= $count_subdir . ' sous dossier ' . "n";
$buf.= $count_file . ' fichiers ' . "n";
$buf.= $count_code_line . ' lignes de code ' . "n";
$buf.= $count_code_data . ' lignes de donnee ' . "n";
echo $buf;
}
}
/**
* Lister le contenu d'un dossier et des sous-répertoires
* @return type
*/
public function stat_dir() {
$nstat = array();
foreach ($this->filesinfo as $file) {
if (isset($nstat[$file['path']])) {
$nstat[$file['path']]['count']++;
$nstat[$file['path']]['fnames'].="n" . $file['name'];
} else {
$nstat[$file['path']]['count'] = 1;
$nstat[$file['path']]['fnames'] = $file['name'];
}
}
return $nstat;
}
/**
* Compter le nombre de ligne dans un fichier
* @param type $file
* @return int
*/
private function fileLineCount($file) {
$fhandle = @fopen($file, 'rb');
$lines = 0;
if ($fhandle) {
while (!feof($fhandle)) {
$buf = fread($fhandle, 8192);
$lines += substr_count($buf, "n");
}
$lines+=1;
fclose($fhandle);
}
return $lines;
}
/**
* Déterminer le type de fichier à partir de son extension
* @param type $file
* @return type
*/
private function filetype($file) {
$ext = strtolower(strrchr($file, '.'));
//Fichier de programmation PHP
if (in_array($ext, array('.php', '.php3', '.php4', '.php5'))) {
return self::FILETYPE_PHP;
}
//Fichier de page internet
else if (in_array($ext, array('.htm', '.html', '.xml', '.css', '.js'))) {
return self::FILETYPE_WEB;
}
//Fichier de données
else if (in_array($ext, array('.dat', '.csv'))) {
return self::FILETYPE_DATA;
}
//Autre fichier par exemple image
else {
return self::FILETYPE_OTHER;
}
}
/**
* Savoir si le contenu d'un fichier est ASCII ou binaire
* @param type $file
* @return boolean
*/
private function file_isBinary($file) {
$buf = '';
if (file_exists($file)) {
$fhandle = @fopen($file, "r");
if ($fhandle) {
$buf = fread($fhandle, 512);
fclose($fhandle);
}
if (substr_count($buf, "x00") > 0) {
return TRUE;
}
}
return FALSE;
}
}
?>
Afficher les stats d'un répertoire
Prenons un projet au hasard sur le serveur LAMP de développement. Lorsque l'on veut savoir ce que contient le dossier, y compris les sous-dossier, les fonctions du script sont appelées ainsi:
<?php
//Nouvelle instance de la class
$projectStat = new ProjectStat();
//Lance le scan y compris les sous-dossier
$projectStat->scan($_SERVER['DOCUMENT_ROOT'] . '/project1/', TRUE);
//Affiche le résultat au format texte
echo $projectStat->stat_type(true);
?>
Analyse du dossier /var/www/project1/
5 sous dossier
195 fichiers
13954 lignes de code
73244 lignes de donnee
Pas beacoup de ligne de code !!! En effet, le projet internet en question contient une dizaine d'interface web et les données sont directement dans des fichiers CSV.
Lister le détail du dossier
La class ProjectStat sait aussi retourner les contenus des répertoires sous forme d'un tableau. Lorsque l'on souhaiter savoir ce que contient les dossiers pour ensuite faire des traitements dans un script de back-office, la class est utilisée ainsi:<?php
//Nouvelle instance
$projectStat = new ProjectStat();
//Scan le dossier de manière recursive
$projectStat->scan($_SERVER['DOCUMENT_ROOT'] . '/project1/', TRUE);
//liste le contenu
$files=$projectStat->stat_dir();
//zffiche le tableau
print_r($files);
?>
Résultats
Array
(
[/var/www/project1/] => Array
(
[count] => 37
[fnames] => index.php
home.html
php.ini
...
)
[/var/www/project1/controller/] => Array
(
[count] => 29
[fnames] => controller1.php
...
)
...
)
A quoi sert cette class ?
A mesurer le travail des développeurs !!! plus ils écrivent des lignes plus ils sont payés
C'est une blaque. En fait, au moment de rendre le projet au client, nous nous servons d'une class PHP dans le même genre pour expliquer ce que nous avons fait. Votre application internet contient ... lignes de code PHP, ... page HTML, etc...
En plus de la documentation et les diagrammes diagramme de fonctionnement, les statistiques du contenu du projet aide à comprendre comment l'application web a été construit.