From 02e0aff3b9f286dc01cb13f6bbf2900fa5743c4c Mon Sep 17 00:00:00 2001 From: romanb Date: Sat, 24 Nov 2007 18:12:02 +0000 Subject: [PATCH] Added missing file --- lib/Doctrine/Query/Tokenizer.php | 380 +++++++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 lib/Doctrine/Query/Tokenizer.php diff --git a/lib/Doctrine/Query/Tokenizer.php b/lib/Doctrine/Query/Tokenizer.php new file mode 100644 index 000000000..0e8dfaeaa --- /dev/null +++ b/lib/Doctrine/Query/Tokenizer.php @@ -0,0 +1,380 @@ +. + */ + +/** + * Doctrine_Query_Tokenizer + * + * @package Doctrine + * @subpackage Query + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.com + * @since 1.0 + * @version $Revision$ + */ +class Doctrine_Query_Tokenizer +{ + + /** + * tokenizeQuery + * splits the given dql query into an array where keys + * represent different query part names and values are + * arrays splitted using sqlExplode method + * + * example: + * + * parameter: + * $query = "SELECT u.* FROM User u WHERE u.name LIKE ?" + * returns: + * array('select' => array('u.*'), + * 'from' => array('User', 'u'), + * 'where' => array('u.name', 'LIKE', '?')) + * + * @param string $query DQL query + * @throws Doctrine_Query_Exception if some generic parsing error occurs + * @return array an array containing the query string parts + */ + public function tokenizeQuery($query) + { + $parts = array(); + $tokens = Doctrine_Tokenizer::sqlExplode($query, ' '); + + foreach ($tokens as $index => $token) { + $token = strtolower(trim($token)); + switch ($token) { + case 'delete': + case 'update': + case 'select': + case 'set': + case 'from': + case 'where': + case 'limit': + case 'offset': + case 'having': + $p = $token; + //$parts[$token] = array(); + $parts[$token] = ''; + break; + case 'order': + case 'group': + $i = ($index + 1); + if (isset($tokens[$i]) && strtolower($tokens[$i]) === 'by') { + $p = $token; + $parts[$token] = ''; + //$parts[$token] = array(); + } else { + $parts[$p] .= "$token "; + //$parts[$p][] = $token; + } + break; + case 'by': + continue; + default: + if ( ! isset($p)) { + throw new Doctrine_Query_Tokenizer_Exception( + "Couldn't tokenize query. Encountered invalid token: '$token'."); + } + + $parts[$p] .= "$token "; + //$parts[$p][] = $token; + } + } + return $parts; + } + + /** + * trims brackets + * + * @param string $str + * @param string $e1 the first bracket, usually '(' + * @param string $e2 the second bracket, usually ')' + */ + public function bracketTrim($str, $e1 = '(', $e2 = ')') + { + if (substr($str, 0, 1) === $e1 && substr($str, -1) === $e2) { + return substr($str, 1, -1); + } else { + return $str; + } + } + + /** + * bracketExplode + * + * example: + * + * parameters: + * $str = (age < 20 AND age > 18) AND email LIKE 'John@example.com' + * $d = ' AND ' + * $e1 = '(' + * $e2 = ')' + * + * would return an array: + * array("(age < 20 AND age > 18)", + * "email LIKE 'John@example.com'") + * + * @param string $str + * @param string $d the delimeter which explodes the string + * @param string $e1 the first bracket, usually '(' + * @param string $e2 the second bracket, usually ')' + * + */ + public function bracketExplode($str, $d = ' ', $e1 = '(', $e2 = ')') + { + if (is_array($d)) { + $a = preg_split('#('.implode('|', $d).')#', $str); + $d = stripslashes($d[0]); + } else { + $a = explode($d, $str); + } + + $i = 0; + $term = array(); + foreach($a as $key=>$val) { + if (empty($term[$i])) { + $term[$i] = trim($val); + $s1 = substr_count($term[$i], $e1); + $s2 = substr_count($term[$i], $e2); + + if ($s1 == $s2) { + $i++; + } + } else { + $term[$i] .= $d . trim($val); + $c1 = substr_count($term[$i], $e1); + $c2 = substr_count($term[$i], $e2); + + if ($c1 == $c2) { + $i++; + } + } + } + return $term; + } + + /** + * quoteExplode + * + * example: + * + * parameters: + * $str = email LIKE 'John@example.com' + * $d = ' LIKE ' + * + * would return an array: + * array("email", "LIKE", "'John@example.com'") + * + * @param string $str + * @param string $d the delimeter which explodes the string + */ + public function quoteExplode($str, $d = ' ') + { + if (is_array($d)) { + $a = preg_split('/('.implode('|', $d).')/', $str); + $d = stripslashes($d[0]); + } else { + $a = explode($d, $str); + } + + $i = 0; + $term = array(); + foreach ($a as $key => $val) { + if (empty($term[$i])) { + $term[$i] = trim($val); + + if ( ! (substr_count($term[$i], "'") & 1)) { + $i++; + } + } else { + $term[$i] .= $d . trim($val); + + if ( ! (substr_count($term[$i], "'") & 1)) { + $i++; + } + } + } + return $term; + } + + /** + * sqlExplode + * + * explodes a string into array using custom brackets and + * quote delimeters + * + * + * example: + * + * parameters: + * $str = "(age < 20 AND age > 18) AND name LIKE 'John Doe'" + * $d = ' ' + * $e1 = '(' + * $e2 = ')' + * + * would return an array: + * array('(age < 20 AND age > 18)', + * 'name', + * 'LIKE', + * 'John Doe') + * + * @param string $str + * @param string $d the delimeter which explodes the string + * @param string $e1 the first bracket, usually '(' + * @param string $e2 the second bracket, usually ')' + * + * @return array + */ + public function sqlExplode($str, $d = ' ', $e1 = '(', $e2 = ')') + { + if ($d == ' ') { + $d = array(' ', '\s'); + } + if (is_array($d)) { + $d = array_map('preg_quote', $d); + + if (in_array(' ', $d)) { + $d[] = '\s'; + } + + $split = '#(' . implode('|', $d) . ')#'; + + $str = preg_split($split, $str); + $d = stripslashes($d[0]); + } else { + $str = explode($d, $str); + } + + $i = 0; + $term = array(); + + foreach ($str as $key => $val) { + if (empty($term[$i])) { + $term[$i] = trim($val); + + $s1 = substr_count($term[$i], $e1); + $s2 = substr_count($term[$i], $e2); + + if (strpos($term[$i], '(') !== false) { + if ($s1 == $s2) { + $i++; + } + } else { + if ( ! (substr_count($term[$i], "'") & 1) && + ! (substr_count($term[$i], "\"") & 1)) { + $i++; + } + } + } else { + $term[$i] .= $d . trim($val); + $c1 = substr_count($term[$i], $e1); + $c2 = substr_count($term[$i], $e2); + + if (strpos($term[$i], '(') !== false) { + if ($c1 == $c2) { + $i++; + } + } else { + if ( ! (substr_count($term[$i], "'") & 1) && + ! (substr_count($term[$i], "\"") & 1)) { + $i++; + } + } + } + } + return $term; + } + + /** + * clauseExplode + * + * explodes a string into array using custom brackets and + * quote delimeters + * + * + * example: + * + * parameters: + * $str = "(age < 20 AND age > 18) AND name LIKE 'John Doe'" + * $d = ' ' + * $e1 = '(' + * $e2 = ')' + * + * would return an array: + * array('(age < 20 AND age > 18)', + * 'name', + * 'LIKE', + * 'John Doe') + * + * @param string $str + * @param string $d the delimeter which explodes the string + * @param string $e1 the first bracket, usually '(' + * @param string $e2 the second bracket, usually ')' + * + * @return array + */ + public function clauseExplode($str, array $d, $e1 = '(', $e2 = ')') + { + if (is_array($d)) { + $d = array_map('preg_quote', $d); + + if (in_array(' ', $d)) { + $d[] = '\s'; + } + + $split = '#(' . implode('|', $d) . ')#'; + + $str = preg_split($split, $str, -1, PREG_SPLIT_DELIM_CAPTURE); + } + + $i = 0; + $term = array(); + + foreach ($str as $key => $val) { + if ($key & 1) { + if (isset($term[($i - 1)]) && ! is_array($term[($i - 1)])) { + $term[($i - 1)] = array($term[($i - 1)], $val); + } + continue; + } + if (empty($term[$i])) { + $term[$i] = $val; + } else { + $term[$i] .= $str[($key - 1)] . $val; + } + + $c1 = substr_count($term[$i], $e1); + $c2 = substr_count($term[$i], $e2); + + if (strpos($term[$i], '(') !== false) { + if ($c1 == $c2) { + $i++; + } + } else { + if ( ! (substr_count($term[$i], "'") & 1) && + ! (substr_count($term[$i], "\"") & 1)) { + $i++; + } + } + } + $term[$i - 1] = array($term[$i - 1], ''); + + return $term; + } +} \ No newline at end of file