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

  1. #1
    Membre régulier
    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é
    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
    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é
    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
    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é
    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
    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é
    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
    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. ###raw>post.musername###
    Membre régulier
    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;
    }
      0  0

###raw>template_hook.ano_emploi###