lithium\g11n\catalog\adapter\Code::_parsePhp()
Parses a PHP file for messages marked as translatable. Recognized as message
marking are $t()
and $tn()
which are implemented in the View
class. This
is a rather simple and stupid parser but also fast and easy to grasp. It doesn't
actively attempt to detect and work around syntax errors in marker functions.
Parameters
-
string
$file
Absolute path to a PHP file.
Returns
arraySource
protected function _parsePhp($file) {
$contents = file_get_contents($file);
$contents = Compiler::compile($contents);
$defaults = [
'ids' => [],
'context' => null,
'open' => false,
'position' => 0,
'occurrence' => ['file' => $file, 'line' => null]
];
extract($defaults);
$data = [];
if (strpos($contents, '$t(') === false && strpos($contents, '$tn(') === false) {
return $data;
}
$tokens = token_get_all($contents);
unset($contents);
$findContext = function ($position) use ($tokens) {
$ignore = [T_WHITESPACE, '(', ')', T_ARRAY, ','];
$open = 1;
$options = [];
$depth = 0;
while (isset($tokens[$position]) && $token = $tokens[$position]) {
if (!is_array($token)) {
$token = [0 => null, 1 => $token, 2 => null];
}
if ($token[1] === '[' || $token[1] === '(') {
$open++;
} elseif (($token[1] === ']' || $token[1] === ')') && --$open === 0) {
break;
}
if ($token[1] === '[' || $token[0] === T_ARRAY) {
$depth++;
} elseif ($depth > 1 && ($token[1] === ']' || $token[1] === ')')) {
$depth--;
}
if ($depth === 1 && $open === 2) {
if (!in_array($token[0] ? : $token[1], $ignore)) {
$options[] = $token;
}
}
$position++;
}
foreach ($options as $i => $token) {
if (!(isset($options[$i + 1]) && isset($options[$i + 2]))) {
break;
}
$condition1 = substr($token[1], 1, -1) === 'context';
$condition2 = $options[$i + 1][0] === T_DOUBLE_ARROW;
$condition3 = $options[$i + 2][0] === T_CONSTANT_ENCAPSED_STRING;
if ($condition1 && $condition2 && $condition3) {
return $options[$i + 2][1];
}
}
return null;
};
foreach ($tokens as $key => $token) {
if (!is_array($token)) {
$token = [0 => null, 1 => $token, 2 => null];
}
if ($open) {
if ($position >= ($open === 'singular' ? 1 : 2)) {
$data = $this->_merge($data, [
'id' => $ids['singular'],
'ids' => $ids,
'occurrences' => [$occurrence],
'context' => $context
]);
extract($defaults, EXTR_OVERWRITE);
} elseif ($token[0] === T_CONSTANT_ENCAPSED_STRING) {
$ids[$ids ? 'plural' : 'singular'] = $token[1];
$position++;
}
} else {
if (isset($tokens[$key + 1]) && $tokens[$key + 1] === '(') {
if ($token[1] === '$t') {
$open = 'singular';
} elseif ($token[1] === '$tn') {
$open = 'plural';
} else {
continue;
}
$occurrence['line'] = $token[2];
$context = $findContext($key + 2);
}
}
}
return $data;
}