Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- // Наш скрипт будет жить в папке replacer/
- $excludes = array('includes/db/', 'replacer/');
- // См. формат возвращаемых значений в документации к token_get_all
- function parse_token($tok, &$type, &$text, &$line)
- {
- if (is_array($tok)) list($type, $text, $line) = $tok;
- else $type = $text = $tok;
- }
- function rewrite_tokens($in_tokens)
- {
- static $string_types = array(T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, '"');
- $type = $text = null;
- $line = 1;
- // для начала проверим, что запрос начинается со строки, для обработки, к примеру, такого случая:
- // ($action == 'add') ? 'INSERT INTO ' . EXTENSION_GROUPS_TABLE . ' ' : 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' SET '
- parse_token($in_tokens[0], $type, $text, $line);
- if ($type === T_WHITESPACE) parse_token($in_tokens[1], $type, $text, $line);
- if (!in_array($type, $string_types, true)) return "Expected first token to be string (got $type)";
- $out_params = $out_tokens = array();
- // разобьем токены на группы, считая за разделитель оператор конкатенации:
- //
- // 'SELECT * FROM ' . TABLE_SOMETHING . ' WHERE lang_id = ' . intval($lang_id)
- //
- // будет превращено в
- //
- // array(array('SELECT * FROM ', TABLE_SOMETHING), array(' WHERE lang_id = ', intval($lang_id)))
- //
- // заметим, что первый токен всегда должен быть строкой, а второй может быть любым
- $state = 'begin';
- $left_tokens = $right_tokens = $groups = array();
- $depth = 0; // глубина скобок
- foreach ($in_tokens as $tok) {
- parse_token($tok, $type, $text, $line);
- if ($type === '(') $depth++;
- else if ($type === ')') $depth--;
- if ($depth < 0) return "Brace depth less than zero";
- if ($state == 'begin') {
- // добавляем в массив «левых» токенов, пока не встретим оператор конкатенации
- if ($depth > 0 || $type !== '.') {
- $left_tokens[] = $tok;
- } else {
- $state = 'end';
- }
- } else {
- // всё аналогично предыдущему, но в конце мы добавим нашу группу в массив $groups
- if ($depth > 0 || $type !== '.') {
- $right_tokens[] = $tok;
- } else {
- $state = 'begin';
- $groups[] = array($left_tokens, $right_tokens);
- $left_tokens = $right_tokens = array();
- }
- }
- }
- // если осталось что-то в конце, добавим это в группу
- if (count($left_tokens)) $groups[] = array($left_tokens, $right_tokens);
- foreach ($groups as $grp) {
- list($left_tokens, $right_tokens) = $grp;
- // как мы заметили ранее, первый токен в группе должен быть строкой
- parse_token($left_tokens[0], $type, $text, $line);
- if ($type === T_WHITESPACE) parse_token($left_tokens[1], $type, $text, $line);
- if (!in_array($type, $string_types, true)) return "first token in a group is not string";
- // пересоберем всё обратно, заменив значения на плейсхолдеры
- foreach ($left_tokens as $tok) {
- parse_token($left_tokens[0], $type, $text, $line);
- $out_tokens[] = $tok;
- }
- if (!count($right_tokens)) break;
- $out_tokens[] = '.';
- // если значение - это константа вида *_TABLE, оставим её, как есть
- $param = tokens_to_string($right_tokens, true);
- if (preg_match('/^\\s*([A-Z0-9_]+)_TABLE\\s*$/s', $param)) {
- foreach ($right_tokens as $tok) $out_tokens[] = $tok;
- } else {
- // вставим просто строку '?r', «сырое» значение
- $out_tokens[] = array(T_CONSTANT_ENCAPSED_STRING, "'?r'", $line);
- $out_params[] = $param;
- }
- $out_tokens[] = '.';
- }
- // если мы последним токеном вставили символ конкатенации,
- // уберем его, чтобы не было syntax error
- parse_token(end($out_tokens), $type, $text, $line);
- if ($type === '.') array_pop($out_tokens);
- return array(
- 'tokens' => $out_tokens,
- 'params' => $out_params,
- );
- }
- function tokens_to_string($tokens, $skip_replace = false)
- {
- $str = '';
- $type = $text = null;
- $line = 1;
- foreach ($tokens as $tok) {
- parse_token($tok, $type, $text, $line);
- $str .= $text;
- }
- if (!$skip_replace) $str = preg_replace(array("/[\t ]+/s", '/^/m'), array(' ', ' '), $str);
- return $str;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement