PageRenderTime 56ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Query/Tokenizer.php

https://github.com/Kazuhiro-Murota/OpenPNE3
PHP | 387 lines | 271 code | 18 blank | 98 comment | 28 complexity | 06ebdc4dce7469a845c160810065ebb4 MD5 | raw file
  1. <?php
  2. /*
  3. * $Id$
  4. *
  5. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. *
  17. * This software consists of voluntary contributions made by many individuals
  18. * and is licensed under the LGPL. For more information, see
  19. * <http://www.phpdoctrine.org>.
  20. */
  21. /**
  22. * Doctrine_Query_Tokenizer
  23. *
  24. * @package Doctrine
  25. * @subpackage Query
  26. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
  27. * @link www.phpdoctrine.org
  28. * @since 1.0
  29. * @version $Revision$
  30. * @todo Give the tokenizer state, make it better work together with Doctrine_Query and maybe
  31. * take out commonly used string manipulation methods
  32. * into a stateless StringUtil? class. This tokenizer should be concerned with tokenizing
  33. * DQL strings.
  34. */
  35. class Doctrine_Query_Tokenizer
  36. {
  37. /**
  38. * tokenizeQuery
  39. * splits the given dql query into an array where keys
  40. * represent different query part names and values are
  41. * arrays splitted using sqlExplode method
  42. *
  43. * example:
  44. *
  45. * parameter:
  46. * $query = "SELECT u.* FROM User u WHERE u.name LIKE ?"
  47. * returns:
  48. * array('select' => array('u.*'),
  49. * 'from' => array('User', 'u'),
  50. * 'where' => array('u.name', 'LIKE', '?'))
  51. *
  52. * @param string $query DQL query
  53. * @throws Doctrine_Query_Exception if some generic parsing error occurs
  54. * @return array an array containing the query string parts
  55. */
  56. public function tokenizeQuery($query)
  57. {
  58. $parts = array();
  59. $tokens = $this->sqlExplode($query, ' ');
  60. foreach ($tokens as $index => $token) {
  61. $token = trim($token);
  62. switch (strtolower($token)) {
  63. case 'delete':
  64. case 'update':
  65. case 'select':
  66. case 'set':
  67. case 'from':
  68. case 'where':
  69. case 'limit':
  70. case 'offset':
  71. case 'having':
  72. $p = $token;
  73. //$parts[$token] = array();
  74. $parts[$token] = '';
  75. break;
  76. case 'order':
  77. case 'group':
  78. $i = ($index + 1);
  79. if (isset($tokens[$i]) && strtolower($tokens[$i]) === 'by') {
  80. $p = $token;
  81. $parts[$token] = '';
  82. //$parts[$token] = array();
  83. } else {
  84. $parts[$p] .= "$token ";
  85. //$parts[$p][] = $token;
  86. }
  87. break;
  88. case 'by':
  89. continue;
  90. default:
  91. if ( ! isset($p)) {
  92. throw new Doctrine_Query_Tokenizer_Exception(
  93. "Couldn't tokenize query. Encountered invalid token: '$token'.");
  94. }
  95. $parts[$p] .= "$token ";
  96. //$parts[$p][] = $token;
  97. }
  98. }
  99. return $parts;
  100. }
  101. /**
  102. * trims brackets
  103. *
  104. * @param string $str
  105. * @param string $e1 the first bracket, usually '('
  106. * @param string $e2 the second bracket, usually ')'
  107. */
  108. public function bracketTrim($str, $e1 = '(', $e2 = ')')
  109. {
  110. if (substr($str, 0, 1) === $e1 && substr($str, -1) === $e2) {
  111. return substr($str, 1, -1);
  112. } else {
  113. return $str;
  114. }
  115. }
  116. /**
  117. * bracketExplode
  118. *
  119. * example:
  120. *
  121. * parameters:
  122. * $str = (age < 20 AND age > 18) AND email LIKE 'John@example.com'
  123. * $d = ' AND '
  124. * $e1 = '('
  125. * $e2 = ')'
  126. *
  127. * would return an array:
  128. * array("(age < 20 AND age > 18)",
  129. * "email LIKE 'John@example.com'")
  130. *
  131. * @param string $str
  132. * @param string $d the delimeter which explodes the string
  133. * @param string $e1 the first bracket, usually '('
  134. * @param string $e2 the second bracket, usually ')'
  135. *
  136. */
  137. public function bracketExplode($str, $d = ' ', $e1 = '(', $e2 = ')')
  138. {
  139. if (is_array($d)) {
  140. $a = preg_split('#('.implode('|', $d).')#i', $str);
  141. $d = stripslashes($d[0]);
  142. } else {
  143. $a = explode($d, $str);
  144. }
  145. $i = 0;
  146. $term = array();
  147. foreach($a as $key=>$val) {
  148. if (empty($term[$i])) {
  149. $term[$i] = trim($val);
  150. $s1 = substr_count($term[$i], $e1);
  151. $s2 = substr_count($term[$i], $e2);
  152. if ($s1 == $s2) {
  153. $i++;
  154. }
  155. } else {
  156. $term[$i] .= $d . trim($val);
  157. $c1 = substr_count($term[$i], $e1);
  158. $c2 = substr_count($term[$i], $e2);
  159. if ($c1 == $c2) {
  160. $i++;
  161. }
  162. }
  163. }
  164. return $term;
  165. }
  166. /**
  167. * quoteExplode
  168. *
  169. * example:
  170. *
  171. * parameters:
  172. * $str = email LIKE 'John@example.com'
  173. * $d = ' LIKE '
  174. *
  175. * would return an array:
  176. * array("email", "LIKE", "'John@example.com'")
  177. *
  178. * @param string $str
  179. * @param string $d the delimeter which explodes the string
  180. */
  181. public function quoteExplode($str, $d = ' ')
  182. {
  183. if (is_array($d)) {
  184. $a = preg_split('/('.implode('|', $d).')/', $str);
  185. $d = stripslashes($d[0]);
  186. } else {
  187. $a = explode($d, $str);
  188. }
  189. $i = 0;
  190. $term = array();
  191. foreach ($a as $key => $val) {
  192. if (empty($term[$i])) {
  193. $term[$i] = trim($val);
  194. if ( ! (substr_count($term[$i], "'") & 1)) {
  195. $i++;
  196. }
  197. } else {
  198. $term[$i] .= $d . trim($val);
  199. if ( ! (substr_count($term[$i], "'") & 1)) {
  200. $i++;
  201. }
  202. }
  203. }
  204. return $term;
  205. }
  206. /**
  207. * sqlExplode
  208. *
  209. * explodes a string into array using custom brackets and
  210. * quote delimeters
  211. *
  212. *
  213. * example:
  214. *
  215. * parameters:
  216. * $str = "(age < 20 AND age > 18) AND name LIKE 'John Doe'"
  217. * $d = ' '
  218. * $e1 = '('
  219. * $e2 = ')'
  220. *
  221. * would return an array:
  222. * array('(age < 20 AND age > 18)',
  223. * 'name',
  224. * 'LIKE',
  225. * 'John Doe')
  226. *
  227. * @param string $str
  228. * @param string $d the delimeter which explodes the string
  229. * @param string $e1 the first bracket, usually '('
  230. * @param string $e2 the second bracket, usually ')'
  231. *
  232. * @return array
  233. */
  234. public function sqlExplode($str, $d = ' ', $e1 = '(', $e2 = ')')
  235. {
  236. if ($d == ' ') {
  237. $d = array(' ', '\s');
  238. }
  239. if (is_array($d)) {
  240. $d = array_map('preg_quote', $d);
  241. if (in_array(' ', $d)) {
  242. $d[] = '\s';
  243. }
  244. $split = '#(' . implode('|', $d) . ')#';
  245. $str = preg_split($split, $str);
  246. $d = stripslashes($d[0]);
  247. } else {
  248. $str = explode($d, $str);
  249. }
  250. $i = 0;
  251. $term = array();
  252. foreach ($str as $key => $val) {
  253. if (empty($term[$i])) {
  254. $term[$i] = trim($val);
  255. $s1 = substr_count($term[$i], $e1);
  256. $s2 = substr_count($term[$i], $e2);
  257. if (strpos($term[$i], '(') !== false) {
  258. if ($s1 == $s2) {
  259. $i++;
  260. }
  261. } else {
  262. if ( ! (substr_count($term[$i], "'") & 1) &&
  263. ! (substr_count($term[$i], "\"") & 1)) {
  264. $i++;
  265. }
  266. }
  267. } else {
  268. $term[$i] .= $d . trim($val);
  269. $c1 = substr_count($term[$i], $e1);
  270. $c2 = substr_count($term[$i], $e2);
  271. if (strpos($term[$i], '(') !== false) {
  272. if ($c1 == $c2) {
  273. $i++;
  274. }
  275. } else {
  276. if ( ! (substr_count($term[$i], "'") & 1) &&
  277. (substr_count($term[$i], "\\\'") & 1) &&
  278. ! (substr_count($term[$i], "\"") & 1)) {
  279. $i++;
  280. }
  281. }
  282. }
  283. }
  284. return $term;
  285. }
  286. /**
  287. * clauseExplode
  288. *
  289. * explodes a string into array using custom brackets and
  290. * quote delimeters
  291. *
  292. *
  293. * example:
  294. *
  295. * parameters:
  296. * $str = "(age < 20 AND age > 18) AND name LIKE 'John Doe'"
  297. * $d = ' '
  298. * $e1 = '('
  299. * $e2 = ')'
  300. *
  301. * would return an array:
  302. * array('(age < 20 AND age > 18)',
  303. * 'name',
  304. * 'LIKE',
  305. * 'John Doe')
  306. *
  307. * @param string $str
  308. * @param string $d the delimeter which explodes the string
  309. * @param string $e1 the first bracket, usually '('
  310. * @param string $e2 the second bracket, usually ')'
  311. *
  312. * @return array
  313. */
  314. public function clauseExplode($str, array $d, $e1 = '(', $e2 = ')')
  315. {
  316. if (is_array($d)) {
  317. $d = array_map('preg_quote', $d);
  318. if (in_array(' ', $d)) {
  319. $d[] = '\s';
  320. }
  321. $split = '#(' . implode('|', $d) . ')#';
  322. $str = preg_split($split, $str, -1, PREG_SPLIT_DELIM_CAPTURE);
  323. }
  324. $i = 0;
  325. $term = array();
  326. foreach ($str as $key => $val) {
  327. if ($key & 1) {
  328. if (isset($term[($i - 1)]) && ! is_array($term[($i - 1)])) {
  329. $term[($i - 1)] = array($term[($i - 1)], $val);
  330. }
  331. continue;
  332. }
  333. if (empty($term[$i])) {
  334. $term[$i] = $val;
  335. } else {
  336. $term[$i] .= $str[($key - 1)] . $val;
  337. }
  338. $c1 = substr_count($term[$i], $e1);
  339. $c2 = substr_count($term[$i], $e2);
  340. if (strpos($term[$i], '(') !== false) {
  341. if ($c1 == $c2) {
  342. $i++;
  343. }
  344. } else {
  345. if ( ! (substr_count($term[$i], "'") & 1) &&
  346. ! (substr_count($term[$i], "\"") & 1)) {
  347. $i++;
  348. }
  349. }
  350. }
  351. if (isset($term[$i - 1])) {
  352. $term[$i - 1] = array($term[$i - 1], '');
  353. }
  354. return $term;
  355. }
  356. }