Advertisement
Guest User

replacer/rewrite.php

a guest
Jan 21st, 2013
321
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 4.65 KB | None | 0 0
  1. <?php
  2. // Наш скрипт будет жить в папке replacer/
  3. $excludes = array('includes/db/', 'replacer/');
  4.  
  5. // См. формат возвращаемых значений в документации к token_get_all
  6. function parse_token($tok, &$type, &$text, &$line)
  7. {
  8.     if (is_array($tok)) list($type, $text, $line) = $tok;
  9.     else $type = $text = $tok;
  10. }
  11.  
  12. function rewrite_tokens($in_tokens)
  13. {
  14.     static $string_types = array(T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, '"');
  15.  
  16.     $type = $text = null;
  17.     $line = 1;
  18.  
  19.     // для начала проверим, что запрос начинается со строки, для обработки, к примеру, такого случая:
  20.     // ($action == 'add') ? 'INSERT INTO ' . EXTENSION_GROUPS_TABLE . ' ' : 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' SET '
  21.  
  22.     parse_token($in_tokens[0], $type, $text, $line);
  23.     if ($type === T_WHITESPACE) parse_token($in_tokens[1], $type, $text, $line);
  24.     if (!in_array($type, $string_types, true)) return "Expected first token to be string (got $type)";
  25.  
  26.     $out_params = $out_tokens = array();
  27.    
  28.     //    разобьем токены на группы, считая за разделитель оператор конкатенации:
  29.     //
  30.     // 'SELECT * FROM ' . TABLE_SOMETHING . ' WHERE lang_id = ' . intval($lang_id)
  31.     //
  32.     //    будет превращено в
  33.     //
  34.     // array(array('SELECT * FROM ', TABLE_SOMETHING), array(' WHERE lang_id = ', intval($lang_id)))
  35.     //
  36.     //    заметим, что первый токен всегда должен быть строкой, а второй может быть любым
  37.  
  38.     $state = 'begin';
  39.     $left_tokens = $right_tokens = $groups = array();
  40.     $depth = 0; // глубина скобок
  41.  
  42.     foreach ($in_tokens as $tok) {
  43.         parse_token($tok, $type, $text, $line);
  44.  
  45.         if ($type === '(') $depth++;
  46.         else if ($type === ')') $depth--;
  47.  
  48.         if ($depth < 0) return "Brace depth less than zero";
  49.  
  50.         if ($state == 'begin') {
  51.             // добавляем в массив «левых» токенов, пока не встретим оператор конкатенации
  52.             if ($depth > 0 || $type !== '.') {
  53.                 $left_tokens[] = $tok;
  54.             } else {
  55.                 $state = 'end';
  56.             }
  57.         } else {
  58.             // всё аналогично предыдущему, но в конце мы добавим нашу группу в массив $groups
  59.             if ($depth > 0 || $type !== '.') {
  60.                 $right_tokens[] = $tok;
  61.             } else {
  62.                 $state = 'begin';
  63.                 $groups[] = array($left_tokens, $right_tokens);
  64.                 $left_tokens = $right_tokens = array();
  65.             }
  66.         }
  67.     }
  68.  
  69.     // если осталось что-то в конце, добавим это в группу
  70.     if (count($left_tokens)) $groups[] = array($left_tokens, $right_tokens);
  71.  
  72.     foreach ($groups as $grp) {
  73.         list($left_tokens, $right_tokens) = $grp;
  74.  
  75.         // как мы заметили ранее, первый токен в группе должен быть строкой
  76.         parse_token($left_tokens[0], $type, $text, $line);
  77.         if ($type === T_WHITESPACE) parse_token($left_tokens[1], $type, $text, $line);
  78.         if (!in_array($type, $string_types, true)) return "first token in a group is not string";
  79.  
  80.         // пересоберем всё обратно, заменив значения на плейсхолдеры
  81.         foreach ($left_tokens as $tok) {
  82.             parse_token($left_tokens[0], $type, $text, $line);
  83.             $out_tokens[] = $tok;
  84.         }
  85.         if (!count($right_tokens)) break;
  86.  
  87.         $out_tokens[] = '.';
  88.  
  89.         // если значение - это константа вида *_TABLE, оставим её, как есть
  90.         $param = tokens_to_string($right_tokens, true);
  91.         if (preg_match('/^\\s*([A-Z0-9_]+)_TABLE\\s*$/s', $param)) {
  92.             foreach ($right_tokens as $tok) $out_tokens[] = $tok;
  93.         } else {
  94.             // вставим просто строку '?r', «сырое» значение
  95.             $out_tokens[] = array(T_CONSTANT_ENCAPSED_STRING, "'?r'", $line);
  96.             $out_params[] = $param;
  97.         }
  98.         $out_tokens[] = '.';
  99.        
  100.     }
  101.  
  102.     // если мы последним токеном вставили символ конкатенации,
  103.     // уберем его, чтобы не было syntax error
  104.     parse_token(end($out_tokens), $type, $text, $line);
  105.     if ($type === '.') array_pop($out_tokens);
  106.  
  107.     return array(
  108.         'tokens' => $out_tokens,
  109.         'params' => $out_params,
  110.     );
  111. }
  112.  
  113. function tokens_to_string($tokens, $skip_replace = false)
  114. {
  115.     $str = '';
  116.     $type = $text = null;
  117.     $line = 1;
  118.  
  119.     foreach ($tokens as $tok) {
  120.         parse_token($tok, $type, $text, $line);
  121.         $str .= $text;
  122.     }
  123.  
  124.     if (!$skip_replace) $str = preg_replace(array("/[\t ]+/s", '/^/m'), array(' ', '      '), $str);
  125.  
  126.     return $str;
  127. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement