Skip to content
This repository
Browse code

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.
  • Loading branch information...
commit 90ae0ed18d279d7c41161ed4d42c6116824e218a 1 parent 0da62b9
Julian Seidenberg authored April 18, 2012
174  i18n/i18nTextCollector.php
@@ -193,136 +193,80 @@ protected function processModule($module) {
193 193
 
194 194
 		return $entities;
195 195
 	}
196  
-	
197  
-	public function collectFromCode($content, $module) {
198  
-		$entitiesArr = array();
199  
-
200  
-		$newRegexRule = '/_t\s*\(\s*(.+?)\s*\)\s*;\s*/is';
201  
-
202  
-		$matchesArray = array();    //array for the matches to go into
203  
-		if (preg_match_all($newRegexRule, $content, $matchesArray) > 0) {   //we have at least one match
204  
-
205  
-			//take all the matched _t entities
206  
-			foreach($matchesArray[1] as $match) {
207  
-				//replace all commas with backticks (unique character to explode on later)
208  
-				$replacedMatch = preg_replace('/("|\'|_LOW|_MEDIUM|_HIGH)\s*,\s*([\'"]|"|\'|array|PR)/','$1`$2',$match);  //keep array text
209  
-
210  
-				//$replacedMatch = trim($replacedMatch," \"'\n");  //remove starting and ending quotes
211  
-				$replacedMatch = trim($replacedMatch," \n");  //remove starting and ending spaces and newlines
212  
-
213  
-				$parts = explode('`',$replacedMatch);   //cut up the _t call
214 196
 
215  
-				$partsWOQuotes = array();
216  
-				foreach($parts as $part) {
217  
-					$part = trim($part,"\n");  //remove spaces and newlines from part
218  
-
219  
-					$firstChar = substr($part,0,1);
220  
-					if ($firstChar == "'" || $firstChar == '"') {
221  
-						//remove wrapping quotes
222  
-						$part = substr($part,1,-1);
223  
-
224  
-						//remove inner concatenation
225  
-						$part = preg_replace("/$firstChar\\s*\\.\\s*$firstChar/",'',$part);
226  
-					}
  197
+	public function collectFromCode($content, $module) {
  198
+		$entities = array();
227 199
 
228  
-					$partsWOQuotes[] = $part;  //remove starting and ending quotes from inner parts
  200
+		$tokens = token_get_all("<?php\n" . $content);
  201
+		$inTransFn = false;
  202
+		$inConcat = false;
  203
+		$finalTokenDueToArray = false;
  204
+		$currentEntity = array();
  205
+		foreach($tokens as $token) {
  206
+			if(is_array($token)) {
  207
+				list($id, $text) = $token;
  208
+
  209
+				if($inTransFn && $id == T_ARRAY) {
  210
+					//raw 'array' token found in _t function, stop processing the tokens for this _t now
  211
+					$finalTokenDueToArray = true;
229 212
 				}
230 213
 
231  
-				if ($parts && count($partsWOQuotes) > 0) {
  214
+				if($id == T_STRING && $text == '_t') {
  215
+					// start definition
  216
+					$inTransFn = true;
  217
+				} elseif($inTransFn && $id == T_VARIABLE) {
  218
+					// Dynamic definition from provideEntities - skip
  219
+					$inTransFn = false;
  220
+					$inConcat = false;
  221
+					$currentEntity = array();
  222
+				} elseif($inTransFn && $id == T_CONSTANT_ENCAPSED_STRING) {
  223
+					// Fixed quoting escapes, and remove leading/trailing quotes
  224
+					if(preg_match('/^\'/', $text)) {
  225
+						$text = str_replace("\'", "'", $text);
  226
+						$text = preg_replace('/^\'/', '', $text);
  227
+						$text = preg_replace('/\'$/', '', $text);
  228
+					} else {
  229
+						$text = str_replace('\"', '"', $text);
  230
+						$text = preg_replace('/^"/', '', $text);
  231
+						$text = preg_replace('/"$/', '', $text);
  232
+					}
232 233
 
233  
-					$entitiesArr = array_merge($entitiesArr, (array)$this->entitySpecFromNewParts($partsWOQuotes));
  234
+					if($inConcat) {
  235
+						$currentEntity[count($currentEntity)-1] .= $text;
  236
+					} else {
  237
+						$currentEntity[] = $text;
  238
+					}
234 239
 				}
  240
+			} elseif($inTransFn && $token == '.') {
  241
+				$inConcat = true;
  242
+			} elseif($inTransFn && $token == ',') {
  243
+				$inConcat = false;
  244
+			} elseif($inTransFn && ($token == ')' || $finalTokenDueToArray)) {
  245
+				// finalize definition
  246
+				$inTransFn = false;
  247
+				$inConcat = false;
  248
+				$entity = array_shift($currentEntity);
  249
+				$entities[$entity] = $currentEntity;
  250
+				$currentEntity = array();
  251
+				$finalTokenDueToArray = false;
235 252
 			}
236 253
 		}
237 254
 
238  
-		ksort($entitiesArr);
239  
-
240  
-		return $entitiesArr;
241  
-	}
242  
-
243  
-
244  
-	/**
245  
-	 * Test if one string starts with another
246  
-	 */
247  
-	protected function startsWith($haystack, $needle) {
248  
-        $length = strlen($needle);
249  
-        return (substr($haystack, 0, $length) === $needle);
250  
-	}
251  
-
252  
-	/**
253  
-	 * Converts a parts array from explode function into an array of entities for the i18n text collector
254  
-	 * @return array
255  
-	 */
256  
-	protected function entitySpecFromNewParts($parts, $namespace = null) {
257  
-		// first thing in the parts array will always be the entity
258  
-		// split fullname into entity parts
259  
-		//set defaults
260  
-		$value = "";
261  
-		$prio = null;
262  
-		$comment = null;
263  
-
264  
-		$entityParts = explode('.', $parts[0]);
265  
-		if(count($entityParts) > 1) {
266  
-			// templates don't have a custom namespace
267  
-			$entity = array_pop($entityParts);
268  
-			// namespace might contain dots, so we explode
269  
-			$namespace = implode('.',$entityParts);
270  
-		} else {
271  
-			$entity = array_pop($entityParts);
272  
-			$namespace = $namespace;
273  
-		}
274  
-
275  
-		//find the array (if found, then we are dealing with the new _t syntax
276  
-		$newSyntax = false;
277  
-		$offset = 0;
278  
-		foreach($parts as $p) {
279  
-			if ($this->startsWith($p,'array')) {    //remove everything after (and including) the array
280  
-				$newSyntax = true;
281  
-				$parts = array_splice($parts,0,$offset);
282  
-				break;
283  
-			}
284  
-			$offset++;
285  
-		}
286  
-
287  
-		//2nd part of array is always "string"
288  
-		if (isset($parts[1])) $value = $parts[1];
289  
-
290  
-
291  
-		//3rd part can either be priority or context, if old or now syntax is used
292  
-		if (isset($parts[2])) {
293  
-			if ($newSyntax) {
294  
-				$prio = 40; //default priority
295  
-				$comment = $parts[2];
296  
-			} else {
297  
-				if (stripos($parts[2], 'PR_LOW') !== false ||
298  
-				    stripos($parts[2], 'PR_MEDIUM') !== false ||
299  
-				    stripos($parts[2], 'PR_HIGH') !== false) {  //definitely old syntax
300  
-					$prio = $parts[2];
301  
-				} else {    //default to new syntax (3rd position is comment/context
302  
-					$prio = 40; //default priority
303  
-					$comment = $parts[2];
304  
-				}
  255
+		foreach($entities as $entity => $spec) {
  256
+			// call without master language definition
  257
+			if(!$spec) {
  258
+				unset($entities[$entity]);
  259
+				continue;
305 260
 			}
306  
-		}
307 261
 
308  
-		//if 4th position is set then this is old syntax and it is the context
309  
-		//it would be array in the new syntax and therefore should have already been spliced off
310  
-		if (isset($parts[3])) {
311  
-			$comment = $parts[3];
312  
-			$prio = $parts[2];  //3rd position is now definitely priority
  262
+			unset($entities[$entity]);
  263
+			$entities[$this->normalizeEntity($entity, $module)] = $spec;
313 264
 		}
  265
+		ksort($entities);
314 266
 
315  
-		return array(
316  
-			"{$namespace}.{$entity}" => array(
317  
-				$value,
318  
-				$prio,
319  
-				$comment
320  
-			)
321  
-		);
  267
+		return $entities;
322 268
 	}
323 269
 
324  
-
325  
-
326 270
 	public function collectFromTemplate($content, $fileName, $module) {
327 271
 		$entities = array();
328 272
 		
13  tests/i18n/i18nTextCollectorTest.php
@@ -58,7 +58,7 @@ function testConcatenationInEntityValues() {
58 58
 
59 59
 _t(
60 60
 'Test.CONCATENATED2',
61  
-"Line "4" and " .
  61
+"Line \"4\" and " . 
62 62
 "Line 5");
63 63
 PHP;
64 64
 		$this->assertEquals(
@@ -87,7 +87,7 @@ function testCollectFromNewTemplateSyntaxUsingParserSubclass() {
87 87
 		$this->assertEquals(
88 88
 			$c->collectFromTemplate($html, 'mymodule', 'Test'),
89 89
 			array(
90  
-				'Test.SINGLEQUOTE' => array('Single Quote',null,null),
  90
+				'Test.SINGLEQUOTE' => array('Single Quote'),
91 91
 				'i18nTestModule.NEWMETHODSIG' => array("New _t method signature test",null,null),
92 92
 				'i18nTestModule.INJECTIONS_0' => array("Hello {name} {greeting}. But it is late, {goodbye}", null, null),
93 93
 				'i18nTestModule.INJECTIONS_1' => array("Hello {name} {greeting}. But it is late, {goodbye}", null, null),
@@ -328,11 +328,10 @@ function testCollectFromCodeNewSignature() {
328 328
 		$collectedTranslatables = $c->collectFromCode($php, 'mymodule');
329 329
 
330 330
 		$expectedArray = (array(
331  
-			'i18nTestModule.NEWMETHODSIG' => array("New _t method signature test", null, null),
332  
-			'i18nTestModule.INJECTIONS1' => array("_DOES_NOT_EXIST", 40, "Hello {name} {greeting}. But it is late, {goodbye}"),
333  
-			'i18nTestModule.INJECTIONS2' => array("Hello {name} {greeting}. But it is late, {goodbye}", null, null),
334  
-			'i18nTestModule.INJECTIONS3' => array("Hello {name} {greeting}. But it is late, {goodbye}", 40, "New context (this should be ignored)"),
335  
-			'i18nTestModule.INJECTIONS4' => array(null, null, null),
  331
+			'i18nTestModule.NEWMETHODSIG' => array("New _t method signature test"),
  332
+			'i18nTestModule.INJECTIONS1' => array("_DOES_NOT_EXIST", "Hello {name} {greeting}. But it is late, {goodbye}"),
  333
+			'i18nTestModule.INJECTIONS2' => array("Hello {name} {greeting}. But it is late, {goodbye}"),
  334
+			'i18nTestModule.INJECTIONS3' => array("Hello {name} {greeting}. But it is late, {goodbye}", "New context (this should be ignored)"),
336 335
 		));
337 336
 
338 337
 		ksort($expectedArray);

0 notes on commit 90ae0ed

Please sign in to comment.
Something went wrong with that request. Please try again.