Changeset 54041 in spip-zone


Ignore:
Timestamp:
Nov 5, 2011, 9:01:47 AM (8 years ago)
Author:
esj@…
Message:

langonet On sépare en plusieurs RegExp? le répérage de <: :>, de _T("...") et de _T('...') afin de pouvoir répérer des apostrophes dans des guillemets et réciproquement, et ces deux caractères dans les chevrons.

Par ailleurs, on scinde en plusieurs fonctions ces recherches afin de pouvoir faire des appels directs avec des fichiers arbitraires.

Location:
_plugins_/langonet
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/langonet/formulaires/langonet_verifier.php

    r53957 r54041  
    507507                        else continue;
    508508                } else {
    509                   // si les item n'ont pas que des lettres, normaliser
    510                         $re = strpos($fichier, '.xml') ? _LANGONET_TROUVER_ITEM_X : _LANGONET_TROUVER_ITEM_HP;           
    511                         if (!preg_match($re, $val, $m)) continue;
    512                         if ($m[0][0] !== '<') continue;
     509                        // si c'est un <: ... :> normaliser au besoin
     510                        if ($val[0]!=='<') continue;
     511                        if (!preg_match(_LANGONET_ITEM_H, $val, $m)) continue;
    513512                        if (preg_match(',^\w+$,', $occ = $m[2])) continue;
    514513                }
  • _plugins_/langonet/inc/langonet_verifier_items.php

    r53957 r54041  
    66// (voir le fichier regexp.txt pour des exemples)
    77
    8 // -- pour les fichiers .html et .php
    9 // sans detection de _L mais avec variables PHP eventuelles dans l'argument de _T
    10 define("_LANGONET_TROUVER_ITEM_HP",
    11         "#" .
    12         "(?:<:|_[TU]\(['\"])" . // designation (<: pour squelette, T|U pour PHP)
    13         "(?:([a-z0-9_]+):)?" .  // nom du module eventuel
    14        "(" . "(?:\\$|[\"\']\s*\.\s*\\$*)?" . // delimiteur ' ou " pour T|U
    15                 "[A-Za-z0-9@_&;,.?!\s()-]+" . // item nu, pas forcement normalise
    16                ")" .
    17         "(" . "(?:{(?:[^\|=>]*=[^\|>]*)})?" . // argument entre accolades
    18                 "(?:(?:\|[^>]*)?)" . // filtre
    19                 "(?:['\"]\s*\.\s*[^\s]+)?" . // delimiteur ' ou " pour T|U
    20         ")" .
    21         "#iS"
    22        );
    23 
    24 // -- pour les fichiers .xml
    25 define("_LANGONET_TROUVER_ITEM_X", ",<[a-z0-9_]+>[\n|\t|\s]*([a-z0-9_]+):([a-z0-9_]+)[\n|\t|\s]*</[a-z0-9_]+()>,iS");
     8// Fontions PHP _T ou _U avec apostrophe
     9define("_LANGONET_ITEM_A",
     10       '%_[TU]\s*[(]\s*\'(?:([a-z0-9_]+):)?([^\']*)\'\s*([^.,)]*[^)]*)%S');
     11// Fontions PHP _T ou _U avec guillemet
     12define("_LANGONET_ITEM_G",
     13       '%_[TU]\s*[(]\s*"(?:([a-z0-9_]+):)?([^"]*)"\s*([^.,)]*[^)]*)%S');
     14// squelette avec <: ... :>
     15define("_LANGONET_ITEM_H",
     16       "%<:(?:([a-z0-9_]+):)?([^:|{}>]+)([^>]*)%S");
     17// pour plugin.xml (obsolete a terme)
     18define("_LANGONET_ITEM_X", ",<[a-z0-9_]+>[\n|\t|\s]*([a-z0-9_]+):([a-z0-9_]+)[\n|\t|\s]*</[a-z0-9_]+()>,iS");
     19
     20include_spip('inc/langonet_verifier_l');
    2621
    2722/**
     
    4540function inc_langonet_verifier_items($rep, $module, $langue, $ou_langue, $ou_fichier, $verification) {
    4641
    47         // Initialisation du tableau des resultats
    48         // Si une erreur se produit lors du deroulement de la fonction, le tableau contient le libelle
    49         // de l'erreur dans $resultats['erreur'].
    50         // Sinon, cet index n'existe pas
    51         $item_non = $definition_non_mais_nok = $item_md5 = $fichier_non = $resultats = array();
     42        // On ignore les ultimes sous-repertoires charsets/ , lang/ , req/ .
     43        // On n'analyse que les fichiers php, html, xml ou yaml
     44        // (voir le fichier regexp.txt).
     45        $files = preg_files(_DIR_RACINE.$ou_fichier, '(?<!/charsets|/lang|/req)(/[^/]*\.(html|php|xml|yaml))$');
     46        $resultats =  langonet_collecter_items($files);
    5247
    5348        // On charge le fichier de langue a verifier
     
    5550        // (evite le mecanisme standard de surcharge SPIP)
    5651        include_spip('inc/traduire');
    57         include_spip('inc/langonet_verifier_l');
     52        $fichier_langue = $ou_langue.$module.'_'.$langue.'.php';
    5853        $var_source = "i18n_".$module."_".$langue;
    5954        if (empty($GLOBALS[$var_source])) {
    6055                $GLOBALS['idx_lang'] = $var_source;
    61                 include(_DIR_RACINE.$ou_langue.$module.'_'.$langue.'.php');
    62         }
    63 
    64         // On cherche l'ensemble des items utilises dans l'arborescence $ou_fichier
    65         $utilises = array('items' => array(), 'suffixes' => array(), 'modules' => array());
    66         // On ignore les ultimes sous-repertoires charsets/ ,
    67         // lang/ , req/ . On ne scanne que les fichiers php, html ou xml
    68         // (voir le fichier regexp.txt).
    69         $files = preg_files(_DIR_RACINE.$ou_fichier, '(?<!/charsets|/lang|/req)(/[^/]*\.(html|php|xml|yaml))$');
     56                include(_DIR_RACINE.$fichier_langue);
     57        }
     58        if ($verification == 'definition') {
     59                // Les chaines definies sont dans les fichiers definies par la RegExp ci-dessous
     60                // Autrement dit les fichiers francais du repertoire lang/ sont la reference
     61                $files = preg_files(_DIR_RACINE, '/lang/[^/]+_fr\.php$');
     62                $resultats = langonet_classer_items($module, $resultats, $GLOBALS[$var_source], $files);
     63        } elseif ($GLOBALS[$var_source])
     64                $resultats = langonet_reperer_items($resultats, $GLOBALS[$var_source]);
     65        $resultats['module'] = $module;
     66        $resultats['langue'] = $fichier_langue;
     67        $resultats['ou_fichier'] = $ou_fichier;
     68        return $resultats;
     69}
     70
     71// On cherche l'ensemble des items utilises dans l'arborescence
     72// ligne par ligne (tant pis pour les items sur plusieurs lignes),
     73// a l'aide des RegExp definies ci-dessus
     74
     75function langonet_collecter_items($files) {
     76
     77        $utilises = array('items' => array(), 'suffixes' => array(), 'modules' => array(), 'tous' => array());
    7078        foreach ($files as $_fichier) {
    71                 $re = strpos($_fichier, '.xml') ? _LANGONET_TROUVER_ITEM_X : _LANGONET_TROUVER_ITEM_HP;
     79                $xml = strpos($_fichier, '.xml');
     80                foreach ($contenu = file($_fichier) as $ligne => $t) {
     81                        if ($xml) {
     82                                if (preg_match_all(_LANGONET_ITEM_X, $t, $m, PREG_SET_ORDER))
     83                                        foreach ($m as $occ) langonet_match($utilises, $occ, $_fichier, $ligne);
     84                        } else {
     85                                if (preg_match_all(_LANGONET_ITEM_A, $t, $m, PREG_SET_ORDER))
     86                                        foreach ($m as $occ) langonet_match($utilises, $occ, $_fichier, $ligne);
     87                                if (preg_match_all(_LANGONET_ITEM_G, $t, $m, PREG_SET_ORDER))
     88                                        foreach ($m as $occ) langonet_match($utilises, $occ, $_fichier, $ligne, true);
     89                                if (preg_match_all(_LANGONET_ITEM_H, $t, $m, PREG_SET_ORDER))
     90                                        foreach ($m as $occ) langonet_match($utilises, $occ, $_fichier, $ligne);
     91                        }
     92                }
     93        }
     94        return $utilises;
     95}
     96
     97/// Memorise le resultat d'un preg_match ci-dessus
     98// et analyse au passage si l'item est dynamique (_T avec $ ou concatenation)
     99
     100function langonet_match(&$utilises, $occ, $_fichier, $ligne, $eval=false)
     101{
     102        $index = langonet_index_l($occ[2], $utilises['items']);
     103        $utilises['items'][$index] = $occ[2];
     104        $utilises['modules'][$index] = $occ[1];
     105        $utilises['item_tous'][$index][$_fichier][$ligne][] = trim($occ[0]);
     106        $utilises['suffixes'][$index] = (($occ[3][0]==='.') OR ($eval AND strpos($occ[2], '$')));
     107}
     108
     109//  Construire la liste des items definis mais apparament pas utilises
     110
     111function langonet_reperer_items($utilises, $init)
     112{
     113        $item_non = $item_peut_etre = $fichier_peut_etre = array();
     114        foreach ($init as $_item => $_traduction) {
     115                if (!in_array ($_item, $utilises['items'])) {
     116                        // L'item est soit non utilise, soit utilise dans un contexte variable
     117                        $contexte_variable = false;
     118                        foreach($utilises['items'] as $_cle => $_valeur) {
     119                                if ($utilises['suffixes'][$_cle]) {
     120                                        if (substr($_item, 0, strlen($_valeur)) == $_valeur) {
     121                                                $contexte_variable = true;
     122                                                break;
     123                                        }
     124                                }
     125                        }
     126                        if (!$contexte_variable) {
     127                                // L'item est vraiment non utilise
     128                                $item_non[] = $_item;
     129                        } else {
     130                                // L'item est utilise dans un contexte variable
     131                                $item_peut_etre[] = $_item;
     132                                if (is_array($utilises['item_tous'][$_item])) {
     133                                        $fichier_peut_etre[$_item] = $utilises['item_tous'][$_item];
     134                                }
     135                        }
     136                }
     137        }
     138        return array(
     139                   'item_non' => $item_non,
     140                   'item_peut_etre' => $item_peut_etre,
     141                   'fichier_peut_etre' => $fichier_peut_etre,
     142               );
     143}
     144
     145// On construit la liste de tous les items definis dans les fichiers de langues fournis
     146// Ensuite on construit la liste des items utilises mais non definis
     147
     148function langonet_classer_items($module, $utilises, $init=array(), $files=array()) {
     149
     150        foreach ($files as $_fichier) {
    72151                foreach ($contenu = file($_fichier) as $ligne => $texte) {
    73                         if (preg_match_all($re, $texte,  $m, PREG_SET_ORDER)) {
    74                                 foreach ($m as $occ) {
    75                                         $suffixe = preg_replace(',\s*,', '', $occ[2]);
    76                                 // On traite les cas particuliers ou l'item est entierement une expression ou une variable:
    77                                         if ((substr($suffixe, 0, 1) == "$") OR (substr($suffixe, 0, 2) == "'.") OR (substr($suffixe, 0, 2) == '".')) {
    78                                                 $suffixe = str_replace('$', '\$', $suffixe);
    79                                         } else $suffixe = $occ[3];
    80                                         $index = langonet_index_l($occ[2], $utilises['items']);
    81                                         $utilises['items'][$index] = $occ[2];
    82                                         $utilises['modules'][$index] = $occ[1];
    83                                         $item_tous[$index][$_fichier][$ligne][] = trim($occ[0]);
    84                                         // l'item est-il dynamique, hormis tableau d'arguments ou filtre ?
    85                                         // (si oui c'est sale et on pourra pas faire grand chose)
    86                                         $utilises['suffixes'][$index] = ($suffixe AND (strpos('|{', $suffixe[0] !== false)));
    87                                 }
    88                         }
    89                 }
    90         }
    91 
    92         if ($verification == 'definition') {
    93                 // On construit la liste de tous les items definis
    94                 // dans tous les fichiers de langue presents sur le site.
    95                 // Par economie, on se limite au scan des '/lang/xxxx_fr.php'
    96                 foreach (preg_files(_DIR_RACINE, '/lang/[^/]+_fr\.php$') as $_fichier) {
    97                         foreach ($contenu = file($_fichier) as $ligne => $texte) {
    98                                 if (preg_match_all("#^[\s\t]*['\"]([a-z0-9_]+)['\"][\s\t]*=>#i", $texte, $matches)) {
    99                                         foreach ($matches[1] as $cet_item) {
    100                                                 $tous_lang[$cet_item][] = $_fichier;
    101                                         }
    102                                 }
    103                         }
    104                 }
    105                 // On construit la liste des items utilises mais non definis
    106                 foreach ($utilises['items'] as $_cle => $_valeur) {
    107 
    108                         if (!isset($GLOBALS[$var_source][$_valeur])) {
    109                                 if (!$utilises['suffixes'][$_cle]) {
    110                                         if ($utilises['modules'][$_cle] == $module) {
    111                                                 // L'item est vraiment non defini et c'est une erreur
    112                                                 $item_non[] = $_valeur;
    113                                                 if (is_array($item_tous[$_cle])) {
    114                                                         $fichier_non[$_cle] = $item_tous[$_cle];
    115                                                 }
    116                                         }
    117                                         else {
    118                                                 // L'item est a priori defini dans un autre module. Le fait qu'il ne soit pas
    119                                                 // defini dans le fichier en cours de verification n'est pas forcement une erreur.
    120                                                 // On l'identifie donc a part
    121                                                 $definition_ok = false;
    122                                                 $definitions = array();
    123                                                 if (array_key_exists($_valeur, $tous_lang)) {
    124                                                         $definitions = $tous_lang[$_valeur];
    125                                                         while ((list($_index, $_fichier) = each($definitions)) AND !$definition_ok)  {
    126                                                                 preg_match(',/lang/([^/]+)_fr\.php$,i', $_fichier, $module_trouve);
    127                                                                 if ($module_trouve[1]) {
    128                                                                         if ($module_trouve[1] == $utilises['modules'][$_cle]) {
    129                                                                                 $definition_ok = true;
    130                                                                         }
    131                                                                         else {
    132                                                                                 $definition_ok = ((($module_trouve[1]=='spip') OR ($module_trouve[1]=='ecrire') OR ($module_trouve[1]=='public')) AND (!$utilises['modules'][$_cle]));
    133                                                                         }
     152                        if (preg_match_all("#^[\s\t]*['\"]([a-z0-9_]+)['\"][\s\t]*=>#i", $texte, $matches)) {
     153                                foreach ($matches[1] as $cet_item) {
     154                                        $tous_lang[$cet_item][] = $_fichier;
     155                                }
     156                        }
     157                }
     158        }
     159
     160        $item_non = $definition_non_mais_nok = $item_md5 = $fichier_non = array();
     161        foreach ($utilises['items'] as $_cle => $_valeur) {
     162
     163                if (!isset($init[$_valeur])) {
     164                        if (!$utilises['suffixes'][$_cle]) {
     165                                if ($utilises['modules'][$_cle] == $module) {
     166                                        // Item indefini alors que le module est explicite, c'est une erreur
     167                                        $item_non[] = $_valeur;
     168                                        if (is_array($utilises['item_tous'][$_cle])) {
     169                                                $fichier_non[$_cle] = $utilises['item_tous'][$_cle];
     170                                        }
     171                                }
     172                                else {
     173                                        // L'item est a priori defini dans un autre module. Le fait qu'il ne soit pas
     174                                        // defini dans le fichier en cours de verification n'est pas forcement une erreur.
     175                                        // On l'identifie donc a part
     176                                        $definition_ok = false;
     177                                        $definitions = array();
     178                                        if (array_key_exists($_valeur, $tous_lang)) {
     179                                                $definitions = $tous_lang[$_valeur];
     180                                                while ((list($_index, $_fichier) = each($definitions)) AND !$definition_ok)  {
     181                                                        preg_match(',/lang/([^/]+)_fr\.php$,i', $_fichier, $module_trouve);
     182                                                        if ($module_trouve[1]) {
     183                                                                if ($module_trouve[1] == $utilises['modules'][$_cle]) {
     184                                                                        $definition_ok = true;
     185                                                                }
     186                                                                else {
     187                                                                        $definition_ok = ((($module_trouve[1]=='spip') OR ($module_trouve[1]=='ecrire') OR ($module_trouve[1]=='public')) AND (!$utilises['modules'][$_cle]));
    134188                                                                }
    135189                                                        }
    136190                                                }
    137                                                 if ($definition_ok) {
    138                                                         $item_non_mais[] = $_valeur;
    139                                                         if (is_array($item_tous[$_cle])) {
    140                                                                 $fichier_non_mais[$_cle] = $item_tous[$_cle];
     191                                        }
     192                                        if ($definition_ok) {
     193                                                $item_non_mais[] = $_valeur;
     194                                                if (is_array($utilises['item_tous'][$_cle])) {
     195                                                        $fichier_non_mais[$_cle] = $utilises['item_tous'][$_cle];
     196                                                }
     197                                                if ($definitions)
     198                                                        $definition_non_mais[$_valeur] = $definitions;
     199                                        }
     200                                        else {
     201                                                $item_non_mais_nok[] = $_cle;
     202                                                if (is_array($utilises['item_tous'][$_cle])) {
     203                                                        $fichier_non_mais_nok[$_cle] = $utilises['item_tous'][$_cle];
     204                                        // Si pas normalise, c'est une auto-definition
     205                                                        if (!preg_match(',^\w+$,', $_valeur)) {
     206                                                                $item_md5[$_cle] = $_valeur;
    141207                                                        }
    142                                                         if ($definitions)
    143                                                                 $definition_non_mais[$_valeur] = $definitions;
    144                                                 }
    145                                                 else {
    146                                                         $item_non_mais_nok[] = $_cle;
    147                                                         if (is_array($item_tous[$_cle])) {
    148                                                                 $fichier_non_mais_nok[$_cle] = $item_tous[$_cle];
    149                                                 // Si pas normalise, c'est une auto-definition
    150                                                                 if (!preg_match(',^\w+$,', $_valeur)) {
    151                                                                         $item_md5[$_cle] = $_valeur;
    152                                                                 }
    153                                                         }
    154                                                         if ($definitions)
    155                                                                 $definition_non_mais_nok[$_cle] = $definitions;
    156                                                 }
    157                                         }
    158                                 }
    159                                 else {
    160                                         // L'item est defini dynamiquement (i.e. a l'execution)
    161                                         // Il ne peut etre trouve directement dans le fichier de
    162                                         // langue, donc on verifie que des items ressemblant
    163                                         // existent dans le fichier de langue
    164                                         $item_trouve = false;
    165                                         foreach($GLOBALS[$var_source] as $_item => $_traduction) {
    166                                                 if (substr($_item, 0, strlen($_valeur)) == $_valeur) {
    167                                                         $item_peut_etre[] = $_valeur;
    168                                                         if (is_array($item_tous[$_cle])) {
    169                                                                 $fichier_peut_etre[$_item] = $item_tous[$_cle];
    170                                                         }
    171                                                         $item_trouve = true;
    172                                                 }
    173                                         }
    174                                         // Si on a pas trouve d'item pouvant correspondre c'est peut-etre que
    175                                         // cet item est en fait une variable ou une expression.
    176                                         // On ajoute ces cas aussi aux incertains (pas essentiel)
    177                                         if (!$item_trouve) {
    178                                                 $_item = ltrim($_valeur, '\'".\\');
    179                                                 $item_peut_etre[] = $_item;
    180                                                 if (is_array($item_tous[$_cle])) {
    181                                                         $fichier_peut_etre[$_item] = $item_tous[$_cle];
    182                                                 }
    183                                         }
    184                                 }
    185                         }
    186                 }
    187         }
    188         else {
    189                 // On construit la liste des items definis mais plus utilises
    190                 if ($GLOBALS[$var_source]) {
    191                         foreach ($GLOBALS[$var_source] as $_item => $_traduction) {
    192                                 if (!in_array ($_item, $utilises['items'])) {
    193                                         // L'item est soit non utilise, soit utilise dans un contexte variable
    194                                         $contexte_variable = false;
    195                                         foreach($utilises['items'] as $_cle => $_valeur) {
    196                                                 if ($utilises['suffixes'][$_cle]) {
    197                                                         if (substr($_item, 0, strlen($_valeur)) == $_valeur) {
    198                                                                 $contexte_variable = true;
    199                                                                 break;
    200                                                         }
    201                                                 }
    202                                         }
    203                                         if (!$contexte_variable) {
    204                                                 // L'item est vraiment non utilise
    205                                                 $item_non[] = $_item;
    206                                         }
    207                                         else {
    208                                                 // L'item est utilise dans un contexte variable
    209                                                 $item_peut_etre[] = $_item;
    210                                                 if (is_array($item_tous[$_valeur])) {
    211                                                         $fichier_peut_etre[$_item] = $item_tous[$_valeur];
    212                                                 }
    213                                         }
    214                                 }
    215                         }
    216                 }
    217         }
    218 
    219         // On prepare le tableau des resultats
    220         $resultats['module'] = $module;
    221         $resultats['ou_fichier'] = $ou_fichier;
    222         $resultats['langue'] = $ou_langue.$module.'_'.$langue.'.php';
    223         $resultats['item_non'] = $item_non;
    224         $resultats['item_non_mais'] = $item_non_mais;
    225         $resultats['item_non_mais_nok'] = $item_non_mais_nok;
    226         $resultats['fichier_non'] = $fichier_non;
    227         $resultats['fichier_non_mais'] = $fichier_non_mais;
    228         $resultats['fichier_non_mais_nok'] = $fichier_non_mais_nok;
    229         $resultats['definition_non_mais'] = $definition_non_mais;
    230         $resultats['definition_non_mais_nok'] = $definition_non_mais_nok;
    231         $resultats['item_peut_etre'] = $item_peut_etre;
    232         $resultats['fichier_peut_etre'] = $fichier_peut_etre;
    233         $resultats['item_md5'] = $item_md5;
    234 
    235         return $resultats;
     208                                                }
     209                                                if ($definitions)
     210                                                        $definition_non_mais_nok[$_cle] = $definitions;
     211                                        }
     212                                }
     213                        }
     214                        else {
     215                                // L'item est defini dynamiquement (i.e. a l'execution)
     216                                // Il ne peut etre trouve directement dans le fichier de
     217                                // langue, donc on verifie que des items ressemblant
     218                                // existent dans le fichier de langue
     219                                $item_trouve = false;
     220                                foreach($init as $_item => $_traduction) {
     221                                        if (substr($_item, 0, strlen($_valeur)) == $_valeur) {
     222                                                $item_peut_etre[] = $_valeur;
     223                                                if (is_array($utilises['item_tous'][$_cle])) {
     224                                                        $fichier_peut_etre[$_item] = $utilises['item_tous'][$_cle];
     225                                                }
     226                                                $item_trouve = true;
     227                                        }
     228                                }
     229                                // Si on a pas trouve d'item pouvant correspondre c'est peut-etre que
     230                                // cet item est en fait une variable ou une expression.
     231                                // On ajoute ces cas aussi aux incertains (pas essentiel)
     232                                if (!$item_trouve) {
     233                                        $_item = ltrim($_valeur, '\'".\\');
     234                                        $item_peut_etre[] = $_item;
     235                                        if (is_array($utilises['item_tous'][$_cle])) {
     236                                                $fichier_peut_etre[$_item] = $utilises['item_tous'][$_cle];
     237                                        }
     238                                }
     239                        }
     240                }
     241        }
     242
     243        return array(
     244                   'item_non' => $item_non,
     245                   'item_non_mais' => $item_non_mais,
     246                   'item_non_mais_nok' => $item_non_mais_nok,
     247                   'fichier_non' => $fichier_non,
     248                   'fichier_non_mais' => $fichier_non_mais,
     249                   'fichier_non_mais_nok' => $fichier_non_mais_nok,
     250                   'definition_non_mais' => $definition_non_mais,
     251                   'definition_non_mais_nok' => $definition_non_mais_nok,
     252                   'item_peut_etre' => $item_peut_etre,
     253                   'fichier_peut_etre' => $fichier_peut_etre,
     254                   'item_md5' => $item_md5,
     255               );
    236256}
    237257
Note: See TracChangeset for help on using the changeset viewer.