lithium\g11n\catalog\adapter\Code::_parsePhp()

protected method

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

array

Source

	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;
	}