IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Analyser un fichier PHP avec token_get_all [PHP 5.3]


Sujet :

Langage PHP

  1. #1
    Membre régulier
    Inscrit en
    mai 2007
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : mai 2007
    Messages : 182
    Points : 120
    Points
    120
    Par défaut Analyser un fichier PHP avec token_get_all
    Bonjour à tous.

    Contexte :

    Je souhaite utiliser la fonction token_get_all : Cette fonction éclate un code source php en multiple "jeton" identifiant le type d'élément php utilisé.

    Mon problème:

    Mais bien sur cette fonction marche correctement uniquement si on lui passe en paramètre du code php... et uniquement du code php. Or je veux analyser un fichier PHP, même lorsque celui-ci contient de l'HTML mélangé avec des parties en PHP...

    Je souhaite donc parser un fichier PHP, et en extraire les parties uniquement PHP (si possible en identifiant les lignes) pour utiliser token_get_all : grosso modo ce que fait tidy en HTML (nettoyer et manipuler les documents HTML, et les traiter sous forme de balises hiérarchisées.)..
    ..mais en PHP (repérer les blocs php) !

    Connaissez-vous une fonction ou une extension qui ferait cela ?

    Merci aux experts (et à leur mémoire ).

  2. #2
    Membre éclairé Avatar de micetf
    Homme Profil pro
    Professeur des Ecoles
    Inscrit en
    mai 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Professeur des Ecoles
    Secteur : Enseignement

    Informations forums :
    Inscription : mai 2009
    Messages : 552
    Points : 821
    Points
    821
    Par défaut
    Peut-être qu'une fonction de ce type suffirait ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function extrairePHP($source,$destination) {
    	$string=file_get_contents($source);
     
    	preg_match_all('/(<\?php)(.*?)(\?>)/s',$string,$result);
     
    	$codePhp='<?php ';
    	foreach ($result[2] as $bloc) {
    		$codePhp .= $bloc."\n";
    	}
    	$codePhp .= ' ?>';
     
    	file_put_contents($destination,$codePhp);
    }
    Fred

  3. #3
    Membre régulier
    Inscrit en
    mai 2007
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : mai 2007
    Messages : 182
    Points : 120
    Points
    120
    Par défaut
    Merci,
    mais je cherche une solution plus carré, qui marcherait à tous les coups.
    Ce que je veux dire c'est que ta solution ne marcherais pas par exemple avec un php qui contiendrait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type='text/javascript'>
    function mafonctionjavascript()
    {
    // commentaire avec un malencontreux <%
    }
    </script>
    </head>
    <body onload="mafonctionjavascript('un autre malencontreux <%');" >
    <?php
     $message= "un autre malencontreux <%";
     echo $message;
    ?>
    </body>
    </html>
    Bref, au lieu de ré-inventer la poudre (au risque de faire du code foireux), je chercher un outil qui ferais déjà ça proprement (et ca serait étonnant que ça n'existe pas).

  4. #4
    Membre éclairé Avatar de micetf
    Homme Profil pro
    Professeur des Ecoles
    Inscrit en
    mai 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Professeur des Ecoles
    Secteur : Enseignement

    Informations forums :
    Inscription : mai 2009
    Messages : 552
    Points : 821
    Points
    821
    Par défaut
    Je ne peux garantir ma solution,
    je l'ai d'ailleurs modifiée pour le cas d'une dernière balise non fermée.
    Néanmoins,
    pour l'exemple que tu donnes,
    elle fonctionne parfaitement.
    Je donne donc le code modifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function extrairePHP($source,$destination) {
    	$string=file_get_contents($source);
     
    	preg_match_all('/(<\?php)(.*?)(\?>|$)/s',$string,$result);
     
    	$codePhp='<?php ';
    	foreach ($result[2] as $bloc) {
    		$codePhp .= $bloc;
    	}
    	$codePhp .= ' ?>';
     
    	file_put_contents($destination,$codePhp);
    }
    On ne sait jamais,
    je n'ai peut-être pas réinventé la poudre,
    et l'outil que tu cherches n'existe peut-être pas.
    Après tout, ce n'est qu'une expression régulière qui fait tout le travail.

    Fred

  5. #5
    Membre régulier
    Inscrit en
    mai 2007
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : mai 2007
    Messages : 182
    Points : 120
    Points
    120
    Par défaut
    Merci Fred pour l'attention que tu porte à mon problême,

    Quand je parlais de ré-inventer la poudre ou de code foireux, je ne parlais pas de toi mais de moi ("je"). D'autre part, les limites d'une simple expression rationnelle ne me convienne pas, même dans ta seconde version modifiée. Mon exemple était a l'évidence pas assez clair, je te présente (moi aussi ) une seconde version de mon exemple qui montre les limites de l'expression rationnelle:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Document sans nom</title>
    <script type='text/javascript'>
    function mafonctionjavascript()
    {
    //  <% Ceci n'est pas du php %>
    }
    </script>
    </head>
    <body onload="mafonctionjavascript('<% Ceci n'est pas du php %>');" >
    <?php
     $message= "<?php Ceci n'est pas du php ?>";
     echo $message;
    ?>
    </body>
    </html>
    Extraire correctement toute les balises implique de passer par l'equivalent d'un parser (mais à la sauce HTML-PHP.. pas en XML),
    et il me parait étrange qu'il n'existe pas d'outils déjà fait..
    ..je continue donc de chercher !

  6. #6
    Membre éclairé Avatar de micetf
    Homme Profil pro
    Professeur des Ecoles
    Inscrit en
    mai 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Professeur des Ecoles
    Secteur : Enseignement

    Informations forums :
    Inscription : mai 2009
    Messages : 552
    Points : 821
    Points
    821
    Par défaut
    D'autre part, les limites d'une simple expression rationnelle ne me conviennent pas, même dans ta seconde version modifiée.
    OK !
    Ce n'est pas grave.
    Mais comme je suis têtu,
    je propose une dernière mouture
    qui ne se laisse pas piéger par ton dernier exemple.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function extrairePHP($source,$destination) {
    	$string=file_get_contents($source);
     
    	preg_match_all('/(<\?php)(((<\?php.*?\?>)|.)*?)(\?>|$)/s',$string,$result);
     
    	$codePhp='<?php ';
    	foreach ($result[2] as $bloc) {
    		$codePhp .= $bloc;
    	}
    	$codePhp .= ' ?>';
     
    	file_put_contents($destination,$codePhp);
    }
    avant de te souhaiter bonne chance dans ta recherche.
    Fred

  7. #7
    Membre régulier
    Inscrit en
    mai 2007
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : mai 2007
    Messages : 182
    Points : 120
    Points
    120
    Par défaut
    Pour le developpement être têtu est une qualité..
    .. même si ton dernier code que j'ai testé retourne ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <?php 
     $message= "<?php Ceci n'est pas du php  ?>
    Alors que le résultat attendu est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <?php
     $message= "<?php Ceci n'est pas du php ?>";
     echo $message;
    ?>
    Je sais, je suis perfectionniste..
    ..mais c'est aussi une qualité dans le developpement .

    Merci Fred.

  8. #8
    Membre éclairé Avatar de micetf
    Homme Profil pro
    Professeur des Ecoles
    Inscrit en
    mai 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Professeur des Ecoles
    Secteur : Enseignement

    Informations forums :
    Inscription : mai 2009
    Messages : 552
    Points : 821
    Points
    821
    Par défaut
    Que neni !
    Refais le test,
    mais ma dernière (3ème) version renvoie bien :
    <?php
    $message= "<?php Ceci n'est pas du php ?>";
    echo $message;
    ?>
    Fred

  9. #9
    Membre régulier
    Inscrit en
    mai 2007
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : mai 2007
    Messages : 182
    Points : 120
    Points
    120
    Par défaut
    Autant pour moi Fred..
    .. par contre cet exemple ne fonctionne pas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type='text/javascript'>
    function mafonctionjavascript()
    {
    //  <% Ceci n'est pas du php %>
    }
    </script>
    </head>
    <body onload='mafonctionjavascript('<?php Ceci est du php ?>');' >
    <?php
    /*
    Ceci est une fin de balise ?> dans un commentaire
    */
     $message= "<?php Ceci n'est pas du php ?>";
     echo $message;
    ?>
    </body>
    </html>
    car il retourne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <?php  Ceci est du php 
    /*
    Ceci est une fin de balise  Ceci n'est pas du php  ?>
    (Je suis aussi un peu joueur )

    A part de la bidouille, personne n'a d'idée sur l'existence d'une fonction ou d'une extension qui extrairerais la partie PHP (idéalement qui permettrait d'identifier la ligne correspondante du fichier original)?

  10. #10
    Membre régulier
    Inscrit en
    mai 2007
    Messages
    182
    Détails du profil
    Informations forums :
    Inscription : mai 2007
    Messages : 182
    Points : 120
    Points
    120
    Par défaut
    Attention à l'utilisation de get_token_all () - (Constaté sur WAMP, PHP 5.3.0)

    1: les numéros de ligne bug

    Depuis PHP 5.2.2 token_get_all () doit retourner le nombre de ligne dans l'élément 2 ..
    .. mais par exemple (5.3.0 sur WAMP), il fonctionne parfaitement avec du code PHP (sans HMTL mélangé), mais si vous avez des T_INLINE_HTML détecté par token_get_all (), parfois, vous trouverez les numéros de ligne décalé (ligne suivante) ...

    2: bug des messages d'alertes qui peuvent avoir un impact sur les boucles

    Attention l'analyse de code PHP non complet (ex: code php ligne par ligne):
    par exemple, si une balise de commentaire n'est pas fermé token_get_all (), les boucles peuvent être impacté par cet avertissement:
    Warning: Unterminated commentaire ligne de départ

    Ce problème ne semble pas se produire dans CLI mod (php en ligne de commande), mais seulement sur le Web mod.

    En attendant plus de stabilité, utiliser token_get_all () seulement sur du code PHP complet (avec les balise d'ouverture et de fermeture PHP incluse) :
    1. Tout d'abord extraire entièrement du code PHP (avec php et à proximité tag),
    2. Utilisation token_get_all () sur le code PHP pur.


    3: Pourquoi n'y at-il pas la fonction d'extraire du code PHP (extrait de HTML, nous avons Tidy ..) ?

    En attendant, je propose donc ma fonction.
    Attention elle prend pas en charge:
    - les anciennes notations : <? ?> Et <% %>
    - Heredoc syntaxe
    - Nowdoc syntaxe (depuis PHP 5.3.0)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
     
    function extract_php_blocks($arg_path)
    {
    	$dbg=false;
    	if(!is_file($arg_path)) exit ("extract_php_blocks() : ".$arg_path." file not found");
    	$handle = @fopen($arg_path, "r");
    	if ($handle) {
    		$bloc = array();
    		$php_bloc_number=0; //fisrt bloc = 0
    		$line_number=1; // first row number  = 1
    		$multiline_php_code="";
    		$double_increment=false;
    		$in_php_code=false;
    		$in_single_quoted=false;
    		$in_double_quoted=false;
    		$in_comment_multi_line=false;
    		$in_comment_single_line=false;
    		while (!feof($handle)) {
    			$line_mixed_code= fgets($handle, 4096);
    			$nb_char=strlen($line_mixed_code);
    			$i_inline=0;
    			while($i_inline<$nb_char)
    			{// scanning line
    				if(!$in_php_code)
    				{// searching php open tag : with strpos
    					if($dbg) echo "\n".$line_number."---- OUT PHP ----\n".substr($line_mixed_code,$i_inline);
    					$pos_open_tag = strpos(substr($line_mixed_code,$i_inline) ,'<?php');
    					if ($pos_open_tag !== false)
    					{
    						$i_inline+=$pos_open_tag;
    						$bloc[$php_bloc_number]=array("start_line" => $line_number,"start_pos" => $i_inline,"end_line" => null,"end_pos" => null,"code" => null);
    						if($dbg) echo "\n".$line_number."-".$i_inline."\n";
    						$in_php_code=true;
    					}
    				}// end  searching php open tag
    				else
    				{// searching php close tag : char by char
    					$multiline_php_code.=$line_mixed_code[$i_inline];
    					if($double_increment){$i_inline++;$multiline_php_code.=$line_mixed_code[$i_inline];$double_increment=false;	}
    					if($dbg) echo "\n".$line_number."---- IN PHP ----\n".substr($line_mixed_code,$i_inline);
    					if($dbg&&$in_comment_single_line) echo "\n [in_comment_single_line] \n";
    
    					// specification in http://fr.php.net/manual/fr/language.types.string.php
    					if($in_comment_multi_line)
    					{// search ending sequence
    						if($dbg) echo "\n [in_comment_multi_line] \n";
    						if (($line_mixed_code[$i_inline]=='*')&&(($i_inline+1)<$nb_char)&&($line_mixed_code[$i_inline+1]=='/')){$in_comment_multi_line=false;;$double_increment=true;}
    					}
    					elseif($in_single_quoted)
    					{// search ending sequence 
    						if($dbg) echo "\n [in_single_quoted] \n";
    						if (($line_mixed_code[$i_inline]=='\\')&&(($i_inline+1)<$nb_char)&&(
    						($line_mixed_code[($i_inline+1)]=='\'')||($line_mixed_code[$i_inline+1]=='\\')
    						))$double_increment=true;
    						elseif ($line_mixed_code[$i_inline]=='\'') $in_single_quoted=false;
    					}
    					elseif($in_double_quoted)
    					{// search ending sequence
    						if($dbg) echo "\n [in_double_quoted] \n";
    						if (($line_mixed_code[$i_inline]=='\\')&&(($i_inline+1)<$nb_char)&&(
    						($line_mixed_code[($i_inline+1)]=='\'')||($line_mixed_code[$i_inline+1]=='\\')
    						||($line_mixed_code[$i_inline+1]=='n')||($line_mixed_code[$i_inline+1]=='r')
    						||($line_mixed_code[$i_inline+1]=='t')||($line_mixed_code[$i_inline+1]=='v')
    						||($line_mixed_code[$i_inline+1]=='f')||($line_mixed_code[$i_inline+1]=='$')
    						||($line_mixed_code[$i_inline+1]=='"')
    						))$double_increment=true;
    						elseif ($line_mixed_code[$i_inline]=='"') $in_double_quoted=false;					
    					}
    					elseif ((($i_inline+1)<$nb_char)&&($line_mixed_code[$i_inline]=='?')&&($line_mixed_code[($i_inline+1)]=='>')) {
    						$bloc[$php_bloc_number]["end_line"] = $line_number ;
    						$bloc[$php_bloc_number]["end_pos"] = $i_inline+2;
    						$bloc[$php_bloc_number]["code"] = '<'.$multiline_php_code.'>';
    						// reset in_php_code values
    						$multiline_php_code="";
    						$php_bloc_number++;
    						$in_php_code=false;
    						$in_comment_single_line=false;
    						$double_increment=true;
    					}
    					elseif((!$in_comment_multi_line)&&!$in_comment_single_line)
    					{// not in comment
    						if ($line_mixed_code[$i_inline]=='\'') $in_single_quoted=true;
    						elseif ($line_mixed_code[$i_inline]=='"') $in_double_quoted=true;
    						elseif ($line_mixed_code[$i_inline]=='#') $in_comment_single_line=true;
    						elseif (($i_inline+1)<$nb_char)
    						{// next char exist
    							if($dbg) echo "\n [found char+1] \n".substr($line_mixed_code,$i_inline);
    							if (($line_mixed_code[$i_inline]=='/')&&($line_mixed_code[($i_inline+1)]=='*')) {$in_comment_multi_line=true;;$double_increment=true;}
    							elseif (($line_mixed_code[$i_inline]=='/')&&($line_mixed_code[($i_inline+1)]=='/')) {$in_comment_single_line=true;;$double_increment=true;}
    						}// end next char exist
    					}//end :  not in comment
     
    				}// end  searching php close tag
    				$i_inline++;
    			}// end scanning line
    			$line_number++;
    			if($dbg) echo "\n [newline] \n";
    			$in_comment_single_line=false;
    		}
    		fclose($handle);
    	}
    	return $bloc;
    }
     
    function view_php_blocks(&$list_php_bloc)
    {
    	if(!is_array($list_php_bloc)) return false;
    	foreach($list_php_bloc as $key => $value)
    	{
    		$multiline_php_code.="\nBloc ".$key." (line ".$value["start_line"]." at char ".$value["start_pos"]." - line ".$value["end_line"]." at char ".$value["end_pos"].") :\n".$value["code"]."\n";
    	}
    	return $multiline_php_code;
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Appel d'un fichier PHP avec passage de paramètre
    Par Claude_Azoulai dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 25/09/2008, 16h27
  2. Ouverture de fichier PHP avec PHPEclipse
    Par youenn dans le forum Eclipse PHP
    Réponses: 4
    Dernier message: 25/03/2008, 18h59
  3. Lire un fichier PHP avec du code PHP et l'afficher
    Par Prosis dans le forum Langage
    Réponses: 4
    Dernier message: 10/01/2008, 01h21
  4. [SimpleXML] Analyser un fichier XML avec PHP
    Par Someone86 dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 10/08/2007, 10h43
  5. Réponses: 9
    Dernier message: 17/11/2005, 11h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo