Parser un fichier pour récupérer les classes, méthodes...

Eléphanteau du PHP | 46 Messages

10 sept. 2014, 14:49

Bonjour à tous,

Je fais souvent de la reverse-engineering dans le cadre de mon boulot.
J'essaye de me faire un petit script PHP qui parse un projet pour récupérer toutes les classes avec leurs attributs et méthode.

Voici l'actuel :
define('ROOT', dirname(__FILE__) . '/');
define('PROJECT_PATH', ROOT . 'project/'); // Changer ici le chemin du projet

// Récupération des fichiers PHP
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(PROJECT_PATH), RecursiveIteratorIterator::SELF_FIRST);
$targets = array();
foreach ($files as $name => $object) if (preg_match('/\.(php|php5)$/i', $name)) {
	$targets[] = $object;
}

// On ouvre chaque fichier pour récupérer les classes
$classes = array();
foreach ($targets as $file) {
	$content = file_get_contents($file->getPathName());
	$content = preg_replace('/[ ]{2,}/', ' ', $content);
	$matches = preg_match_all( '/(abstract ){0,1}class ([a-z0-9\_]+) ((extends|implements) ([a-z0-9\_]+))*/im', $content, $result, PREG_SET_ORDER);
	if ($matches) foreach ($result as $match) {
		$def = $match[0];
		$isAbstract = !empty($match[1]);
		$className = $match[2];
		$action = !empty($match[4]) ? $match[4] : null;
		$father = !empty($match[5]) ? $match[5] : null;
		$classes[$className] = array(
			'def' => $def,
			'isAbstract' => $isAbstract,
			'action' => $action,
			'father' => $father,
		);
	}
}
ksort($classes);

echo '<pre>' . print_r($classes, true) . '</pre>';
Qui me donne en retour un truc du genre :

Code : Tout sélectionner

Array ( [BaseCtrl] => Array ( [def] => abstract class BaseCtrl [isAbstract] => 1 [action] => [father] => ) [IndexCtrl] => Array ( [def] => class IndexCtrl extends BaseCtrl [isAbstract] => [action] => extends [father] => BaseCtrl ) [BaseDB] => Array ( [def] => abstract class BaseDB [isAbstract] => 1 [action] => [father] => ) [Mails] => Array ( [def] => class Mails [isAbstract] => [action] => [father] => ) [Objects] => Array ( [def] => Class Objects [isAbstract] => [action] => [father] => ) [PHPMailer] => Array ( [def] => class PHPMailer [isAbstract] => [action] => [father] => ) [SSHException] => Array ( [def] => class SSHException extends Exception [isAbstract] => [action] => extends [father] => Exception ) [SelectHtml] => Array ( [def] => class SelectHtml [isAbstract] => [action] => [father] => ) [Tools] => Array ( [def] => class Tools [isAbstract] => [action] => [father] => ) [User] => Array ( [def] => class User [isAbstract] => [action] => [father] => ) [phpmailerException] => Array ( [def] => class phpmailerException extends Exception [isAbstract] => [action] => extends [father] => Exception ) )
J'aimerais, à cet endrois du code :

Code : Tout sélectionner

$classes[$className] = array( 'def' => $def, 'isAbstract' => $isAbstract, 'action' => $action, 'father' => $father, );
Récupérer aussi la liste des attributs et des méthodes. Je pense qu'il faut que l'améliore la regex '/(abstract ){0,1}class ([a-z0-9\_]+) ((extends|implements) ([a-z0-9\_]+))*/im' pour récupérer derrière le code entre les { } mais comment ne récupérer que les { } de la classe en cours ?
Quelqu'un à une idée pour récupérer un tableau contenant la liste des méthodes et un autre la liste des attributs ?

Sachant qu'un fichier peut contenir plusieurs classes, peut être mélangé avec tout autre code PHP.

Merci par avance pour votre aide.

Bonne journée

EDIT : Je pense que c'est un truc de ce genre : http://php.net/manual/fr/regexp.reference.recursive.php mais je ne connais pas (je ne suis pas sûr). C'est un problème style 'automate à pile.
Kal747
---
Envie de faire des rencontres gratuites ? Essayez mon site de rencontre
A la recherche d'une maison ou d'un appartement ? Trouvez le meilleur prix sur annonces immobilières

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

10 sept. 2014, 22:07

salut,

autre piste l'instropection (reflection).
a partir du moment ou tu as les noms classe (ce qui est le cas avec ton code) tu auras le reste ;)

juste pour info, histoire de rendre ton code plus lisble tu peux te baser sur les recommandation PSR-1 et PSR-2. je leur préfère les conventions java au niveau emplacements des accolades mais cela reste mon avis :)

@+
Il en faut peu pour être heureux ......