BUGFIX: reverting back to Ingo's text collector from code, but using the parser to get from templates. Adding special case for _t functions in code that have an array in them. Fixing unit tests for all this.

This commit is contained in:
Julian Seidenberg 2012-04-18 17:23:57 +12:00
parent 0da62b9552
commit 90ae0ed18d
2 changed files with 65 additions and 122 deletions

View File

@ -193,136 +193,80 @@ class i18nTextCollector extends Object {
return $entities; return $entities;
} }
public function collectFromCode($content, $module) { public function collectFromCode($content, $module) {
$entitiesArr = array(); $entities = array();
$newRegexRule = '/_t\s*\(\s*(.+?)\s*\)\s*;\s*/is'; $tokens = token_get_all("<?php\n" . $content);
$inTransFn = false;
$inConcat = false;
$finalTokenDueToArray = false;
$currentEntity = array();
foreach($tokens as $token) {
if(is_array($token)) {
list($id, $text) = $token;
$matchesArray = array(); //array for the matches to go into if($inTransFn && $id == T_ARRAY) {
if (preg_match_all($newRegexRule, $content, $matchesArray) > 0) { //we have at least one match //raw 'array' token found in _t function, stop processing the tokens for this _t now
$finalTokenDueToArray = true;
}
//take all the matched _t entities if($id == T_STRING && $text == '_t') {
foreach($matchesArray[1] as $match) { // start definition
//replace all commas with backticks (unique character to explode on later) $inTransFn = true;
$replacedMatch = preg_replace('/("|\'|_LOW|_MEDIUM|_HIGH)\s*,\s*([\'"]|"|\'|array|PR)/','$1`$2',$match); //keep array text } elseif($inTransFn && $id == T_VARIABLE) {
// Dynamic definition from provideEntities - skip
//$replacedMatch = trim($replacedMatch," \"'\n"); //remove starting and ending quotes $inTransFn = false;
$replacedMatch = trim($replacedMatch," \n"); //remove starting and ending spaces and newlines $inConcat = false;
$currentEntity = array();
$parts = explode('`',$replacedMatch); //cut up the _t call } elseif($inTransFn && $id == T_CONSTANT_ENCAPSED_STRING) {
// Fixed quoting escapes, and remove leading/trailing quotes
$partsWOQuotes = array(); if(preg_match('/^\'/', $text)) {
foreach($parts as $part) { $text = str_replace("\'", "'", $text);
$part = trim($part,"\n"); //remove spaces and newlines from part $text = preg_replace('/^\'/', '', $text);
$text = preg_replace('/\'$/', '', $text);
$firstChar = substr($part,0,1); } else {
if ($firstChar == "'" || $firstChar == '"') { $text = str_replace('\"', '"', $text);
//remove wrapping quotes $text = preg_replace('/^"/', '', $text);
$part = substr($part,1,-1); $text = preg_replace('/"$/', '', $text);
//remove inner concatenation
$part = preg_replace("/$firstChar\\s*\\.\\s*$firstChar/",'',$part);
} }
$partsWOQuotes[] = $part; //remove starting and ending quotes from inner parts if($inConcat) {
} $currentEntity[count($currentEntity)-1] .= $text;
} else {
if ($parts && count($partsWOQuotes) > 0) { $currentEntity[] = $text;
}
$entitiesArr = array_merge($entitiesArr, (array)$this->entitySpecFromNewParts($partsWOQuotes));
} }
} elseif($inTransFn && $token == '.') {
$inConcat = true;
} elseif($inTransFn && $token == ',') {
$inConcat = false;
} elseif($inTransFn && ($token == ')' || $finalTokenDueToArray)) {
// finalize definition
$inTransFn = false;
$inConcat = false;
$entity = array_shift($currentEntity);
$entities[$entity] = $currentEntity;
$currentEntity = array();
$finalTokenDueToArray = false;
} }
} }
ksort($entitiesArr); foreach($entities as $entity => $spec) {
// call without master language definition
return $entitiesArr; if(!$spec) {
} unset($entities[$entity]);
continue;
/**
* Test if one string starts with another
*/
protected function startsWith($haystack, $needle) {
$length = strlen($needle);
return (substr($haystack, 0, $length) === $needle);
}
/**
* Converts a parts array from explode function into an array of entities for the i18n text collector
* @return array
*/
protected function entitySpecFromNewParts($parts, $namespace = null) {
// first thing in the parts array will always be the entity
// split fullname into entity parts
//set defaults
$value = "";
$prio = null;
$comment = null;
$entityParts = explode('.', $parts[0]);
if(count($entityParts) > 1) {
// templates don't have a custom namespace
$entity = array_pop($entityParts);
// namespace might contain dots, so we explode
$namespace = implode('.',$entityParts);
} else {
$entity = array_pop($entityParts);
$namespace = $namespace;
}
//find the array (if found, then we are dealing with the new _t syntax
$newSyntax = false;
$offset = 0;
foreach($parts as $p) {
if ($this->startsWith($p,'array')) { //remove everything after (and including) the array
$newSyntax = true;
$parts = array_splice($parts,0,$offset);
break;
} }
$offset++;
unset($entities[$entity]);
$entities[$this->normalizeEntity($entity, $module)] = $spec;
} }
ksort($entities);
//2nd part of array is always "string" return $entities;
if (isset($parts[1])) $value = $parts[1];
//3rd part can either be priority or context, if old or now syntax is used
if (isset($parts[2])) {
if ($newSyntax) {
$prio = 40; //default priority
$comment = $parts[2];
} else {
if (stripos($parts[2], 'PR_LOW') !== false ||
stripos($parts[2], 'PR_MEDIUM') !== false ||
stripos($parts[2], 'PR_HIGH') !== false) { //definitely old syntax
$prio = $parts[2];
} else { //default to new syntax (3rd position is comment/context
$prio = 40; //default priority
$comment = $parts[2];
}
}
}
//if 4th position is set then this is old syntax and it is the context
//it would be array in the new syntax and therefore should have already been spliced off
if (isset($parts[3])) {
$comment = $parts[3];
$prio = $parts[2]; //3rd position is now definitely priority
}
return array(
"{$namespace}.{$entity}" => array(
$value,
$prio,
$comment
)
);
} }
public function collectFromTemplate($content, $fileName, $module) { public function collectFromTemplate($content, $fileName, $module) {
$entities = array(); $entities = array();

View File

@ -58,7 +58,7 @@ _t(
_t( _t(
'Test.CONCATENATED2', 'Test.CONCATENATED2',
"Line "4" and " . "Line \"4\" and " .
"Line 5"); "Line 5");
PHP; PHP;
$this->assertEquals( $this->assertEquals(
@ -87,7 +87,7 @@ SS;
$this->assertEquals( $this->assertEquals(
$c->collectFromTemplate($html, 'mymodule', 'Test'), $c->collectFromTemplate($html, 'mymodule', 'Test'),
array( array(
'Test.SINGLEQUOTE' => array('Single Quote',null,null), 'Test.SINGLEQUOTE' => array('Single Quote'),
'i18nTestModule.NEWMETHODSIG' => array("New _t method signature test",null,null), 'i18nTestModule.NEWMETHODSIG' => array("New _t method signature test",null,null),
'i18nTestModule.INJECTIONS_0' => array("Hello {name} {greeting}. But it is late, {goodbye}", null, null), 'i18nTestModule.INJECTIONS_0' => array("Hello {name} {greeting}. But it is late, {goodbye}", null, null),
'i18nTestModule.INJECTIONS_1' => array("Hello {name} {greeting}. But it is late, {goodbye}", null, null), 'i18nTestModule.INJECTIONS_1' => array("Hello {name} {greeting}. But it is late, {goodbye}", null, null),
@ -328,11 +328,10 @@ PHP;
$collectedTranslatables = $c->collectFromCode($php, 'mymodule'); $collectedTranslatables = $c->collectFromCode($php, 'mymodule');
$expectedArray = (array( $expectedArray = (array(
'i18nTestModule.NEWMETHODSIG' => array("New _t method signature test", null, null), 'i18nTestModule.NEWMETHODSIG' => array("New _t method signature test"),
'i18nTestModule.INJECTIONS1' => array("_DOES_NOT_EXIST", 40, "Hello {name} {greeting}. But it is late, {goodbye}"), 'i18nTestModule.INJECTIONS1' => array("_DOES_NOT_EXIST", "Hello {name} {greeting}. But it is late, {goodbye}"),
'i18nTestModule.INJECTIONS2' => array("Hello {name} {greeting}. But it is late, {goodbye}", null, null), 'i18nTestModule.INJECTIONS2' => array("Hello {name} {greeting}. But it is late, {goodbye}"),
'i18nTestModule.INJECTIONS3' => array("Hello {name} {greeting}. But it is late, {goodbye}", 40, "New context (this should be ignored)"), 'i18nTestModule.INJECTIONS3' => array("Hello {name} {greeting}. But it is late, {goodbye}", "New context (this should be ignored)"),
'i18nTestModule.INJECTIONS4' => array(null, null, null),
)); ));
ksort($expectedArray); ksort($expectedArray);