, Mark Dickenson , bohwaz * Copyright: 2003,2004,2005 by Paul Lockaby, 2005,2006 Mark Dickenson, 2006-2010 BohwaZ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * This object will return all the {t} blocks from a Smarty/Template_Lite template */ class Template_Lang_Parser { /** * Parse un template et renvoie les blocs {t} qu'il contient */ public static function parseTemplate($content, $strict=true) { $current_pos = 0; $line = 1; $strings = array(); // On supprime les commentaires $content = preg_replace("!\{\*.*?\*\}!se", "", $content); while (true) { // Tant que y'a des blocs {t} on continue $current_pos = strpos($content, '{t'); if ($current_pos === false) break; $plural = ''; $msgid = ''; $msgid_plural = ''; $module = false; // Sur quelle ligne somme-nous ? $line += substr_count(substr($content, 0, $current_pos), "\n"); // On vire ce qu'il y a avant le début du tag $content = substr($content, $current_pos); // On trouve la fin du tag $current_pos = strpos($content, '}') + 1; // On récupère le contenu du bloc $block_start = substr($content, 0, $current_pos); // On vire ce qu'il y a avant le contenu du tag; $content = substr($content, $current_pos); // On ne parse pas ce qui n'est pas des blocs t (genre {type} etc.) if (!preg_match('!^\{t[\s\}]!i', $block_start)) { continue; } // On trouve la fin du contenu du bloc $current_pos = strpos($content, '{'); // On récupère le contenu $block_content = substr($content, 0, $current_pos); // On efface ce qui est avant le tag de fermeture $content = substr($content, $current_pos); // On trouve la fin du tag de fermeture $current_pos = strpos($content, '}') + 1; // On récupère le tag fermant $block_end = substr($content, 0, $current_pos); // On efface ce qui est avant $content = substr($content, $current_pos); $block = $block_start . $block_content . $block_end; if ($block_end != '{/t}') { $msg = "Erreur : pas de code smarty dans les blocs {t} (ligne ".$line.")\n " . $block; if ($strict) throw new localesException($msg); else { $errors[] = $msg; continue; } } // On parse les attributs $attr_str = preg_replace('!^\{t(.*)\}$!s', '\\1', $block_start); $attr_str = trim($attr_str); $attributes = utils::parseTemplateAttributes($attr_str); if (!is_array($attributes)) { $msg = "Attributs invalides à la ligne {$line} : ".$attributes."\n ".$block; if ($strict) throw new localesException($msg); else { self::$errors[] = $msg; continue; } } foreach ($attributes as $name=>$value) { $name = strtolower($name); if ($name == 'plural' || $name == 'id') { if (strpos($value, '$') !== false) { $msg = "Erreur : variable interdite dans les arguments plural ou id des blocs {t} (ligne $line)\n " . $block; if ($strict) throw new localesException($msg); else { self::$errors[] = $msg; continue(2); } } } if ($name == 'plural') { $plural = $value; } elseif ($name == 'id') { // Un id="" (vide) ça veux dire qu'on associera la chaîne à un id plus tard, // mais qu'il n'a pas encore été défini. if (empty($value)) { continue(2); } if (!preg_match('!^[a-zA-Z0-9_-]+$!', $value)) { $msg = "Erreur : Argument id invalide dans bloc {t} : [a-zA-Z0-9_-]+ (ligne $line)\n " . $block; if ($strict) throw new localesException($msg); else { self::$errors[] = $msg; continue(2); } } $msgid = $value; } elseif ($name == 'module') { if (!preg_match('!^[a-zA-Z0-9_-]+$!', $value)) { $msg = "Erreur : nom de module invalide : [a-zA-Z0-9_-]+ (ligne $line)\n " . $block; if ($strict) throw new localesException($msg); else { self::$errors[] = $msg; continue(2); } } $module = $value; } } // Pas d'import de bloc vide ! if (empty($block_content) && !$msgid) { continue; } if ($msgid) { if ($plural) $msgid_plural = $msgid . '_PLURAL'; } else { $msgid = trim($block_content); $msgid_plural = trim($plural); } $strings[] = array( 'msgid' => $msgid, 'msgid_plural' => $msgid_plural, 'context' => $block, 'source_line' => $line, 'force_module' => $module, 'args' => $attributes, ); self::debug("Bloc trouvé : " . $block . "\n -> " . $msgid . ($plural ? "\n --> " . $msgid_plural : '')); } return $strings; } public static function parseTemplateAttributes($str) { $attributes = array(); $last_value = ''; $state = 0; // matches double quoted strings: // "foobar" // "foo\"bar" // "foobar" . "foo\"bar" $_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"'; // matches single quoted strings: // 'foobar' // 'foo\'bar' $_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\''; // matches single or double quoted strings $_qstr_regexp = '(?:' . $_db_qstr_regexp . '|' . $_si_qstr_regexp . ')'; preg_match_all('/(?:' . $_qstr_regexp . ' | (?>[^"\'=\s]+))+|[=]/x', $str, $match); foreach ($match[0] as $value) { if ($state == 0) { if (!is_string($value)) return "Invalid attribute name '".$value."'."; $attr_name = $value; $state = 1; } elseif ($state == 1) { if ($value != '=') return "Expecting '=' after '".$last_value."'"; $state = 2; } elseif ($state == 2) { if ($value == '=') return "Unexpected '=' after '".$last_value."'"; if ($value == 'yes' || $value == 'on' || $value == 'true') $value = true; elseif ($value == 'no' || $value == 'off' || $value == 'false') $value = false; elseif ($value == 'null') $value = null; elseif ($value[0] == '"' || $value[0] == "'") $value = trim(substr($value, 1, -1)); $attributes[$attr_name] = $value; $state = 0; } $last_value = $value; } if ($state == 1) return "Expecting '=' after '".$last_value."'"; elseif ($state == 2) return "Missing attribute value after '".$last_value."'"; return $attributes; } } ?>