PageRenderTime 75ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/nooku/libraries/koowa/database/query/query.php

https://github.com/bhar1red/anahita
PHP | 481 lines | 226 code | 75 blank | 180 comment | 23 complexity | cc49bb363485c6a3d570781377fb1260 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * @version $Id: query.php 4628 2012-05-06 19:56:43Z johanjanssens $
  4. * @package Koowa_Database
  5. * @subpackage Query
  6. * @copyright Copyright (C) 2007 - 2012 Johan Janssens. All rights reserved.
  7. * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
  8. * @link http://www.nooku.org
  9. */
  10. /**
  11. * Database Select Class for database select statement generation
  12. *
  13. * @author Johan Janssens <johan@nooku.org>
  14. * @package Koowa_Database
  15. * @subpackage Query
  16. */
  17. class KDatabaseQuery
  18. {
  19. /**
  20. * Count operation
  21. *
  22. * @var boolean
  23. */
  24. public $count = false;
  25. /**
  26. * Distinct operation
  27. *
  28. * @var boolean
  29. */
  30. public $distinct = false;
  31. /**
  32. * The columns
  33. *
  34. * @var array
  35. */
  36. public $columns = array();
  37. /**
  38. * The from element
  39. *
  40. * @var array
  41. */
  42. public $from = array();
  43. /**
  44. * The join element
  45. *
  46. * @var array
  47. */
  48. public $join = array();
  49. /**
  50. * The where element
  51. *
  52. * @var array
  53. */
  54. public $where = array();
  55. /**
  56. * The group element
  57. *
  58. * @var array
  59. */
  60. public $group = array();
  61. /**
  62. * The having element
  63. *
  64. * @var array
  65. */
  66. public $having = array();
  67. /**
  68. * The order element
  69. *
  70. * @var string
  71. */
  72. public $order = array();
  73. /**
  74. * The limit element
  75. *
  76. * @var integer
  77. */
  78. public $limit = null;
  79. /**
  80. * The limit offset element
  81. *
  82. * @var integer
  83. */
  84. public $offset = null;
  85. /**
  86. * Database connector
  87. *
  88. * @var object
  89. */
  90. protected $_adapter;
  91. /**
  92. * Table prefix
  93. *
  94. * @var object
  95. */
  96. protected $_prefix;
  97. /**
  98. * Object constructor
  99. *
  100. * Can be overloaded/supplemented by the child class
  101. *
  102. * @param object An optional KConfig object with configuration options.
  103. */
  104. public function __construct( KConfig $config )
  105. {
  106. //If no config is passed create it
  107. if(!isset($config)) $config = new KConfig();
  108. //Initialise the object
  109. $this->_initialize($config);
  110. //set the model adapter
  111. $this->_adapter = $config->adapter;
  112. }
  113. /**
  114. * Initializes the options for the object
  115. *
  116. * @param object An optional KConfig object with configuration options.
  117. */
  118. protected function _initialize(KConfig $config)
  119. {
  120. $config->append(array(
  121. 'adapter' => '',
  122. ));
  123. }
  124. /**
  125. * Gets the database adapter for this particular KDatabaseQuery object.
  126. *
  127. * @return KDatabaseAdapterInterface
  128. */
  129. public function getAdapter()
  130. {
  131. return $this->_adapter;
  132. }
  133. /**
  134. * Set the database adapter for this particular KDatabaseQuery object.
  135. *
  136. * @param object A KDatabaseAdapterInterface object
  137. * @return KDatabaseQuery
  138. */
  139. public function setAdapter(KDatabaseAdapterInterface $adapter)
  140. {
  141. $this->_adapter = $adapter;
  142. return $this;
  143. }
  144. /**
  145. * Built a select query
  146. *
  147. * @param array|string A string or an array of column names
  148. * @return KDatabaseQuery
  149. */
  150. public function select( $columns = '*')
  151. {
  152. settype($columns, 'array');
  153. $this->columns = array_unique( array_merge( $this->columns, $columns ) );
  154. return $this;
  155. }
  156. /**
  157. * Built a count query
  158. *
  159. * @return KDatabaseQuery
  160. */
  161. public function count()
  162. {
  163. $this->count = true;
  164. $this->columns = array();
  165. return $this;
  166. }
  167. /**
  168. * Make the query distinct
  169. *
  170. * @return KDatabaseQuery
  171. */
  172. public function distinct()
  173. {
  174. $this->distinct = true;
  175. return $this;
  176. }
  177. /**
  178. * Built the from clause of the query
  179. *
  180. * @param array|string A string or array of table names
  181. * @return KDatabaseQuery
  182. */
  183. public function from( $tables )
  184. {
  185. settype($tables, 'array');
  186. //The table needle
  187. $needle = $this->_adapter->getTableNeedle();
  188. //Prepent the table prefix
  189. foreach($tables as &$table)
  190. {
  191. if(strpos($table, $needle) !== 0) {
  192. $table = $needle.$table;
  193. }
  194. }
  195. $this->from = array_unique(array_merge($this->from, $tables));
  196. return $this;
  197. }
  198. /**
  199. * Built the join clause of the query
  200. *
  201. * @param string The type of join; empty for a plain JOIN, or "LEFT", "INNER", etc.
  202. * @param string The table name to join to.
  203. * @param string|array Join on this condition.
  204. * @return KDatabaseQuery
  205. */
  206. public function join($type, $table, $condition)
  207. {
  208. settype($condition, 'array');
  209. //The table needle
  210. $needle = $this->_adapter->getTableNeedle();
  211. if(strpos($table, $needle) !== 0) {
  212. $table = $needle.$table;
  213. }
  214. $this->join[] = array(
  215. 'type' => strtoupper($type),
  216. 'table' => $table,
  217. 'condition' => $condition,
  218. );
  219. return $this;
  220. }
  221. /**
  222. * Built the where clause of the query
  223. *
  224. * @param string The name of the property the constraint applies too, or a SQL function or statement
  225. * @param string The comparison used for the constraint
  226. * @param string|array The value compared to the property value using the constraint
  227. * @param string The where condition, defaults to 'AND'
  228. * @return KDatabaseQuery
  229. */
  230. public function where( $property, $constraint = null, $value = null, $condition = 'AND' )
  231. {
  232. if(!empty($property))
  233. {
  234. $where = array();
  235. $where['property'] = $property;
  236. if(isset($constraint))
  237. {
  238. $constraint = strtoupper($constraint);
  239. $condition = strtoupper($condition);
  240. $where['constraint'] = $constraint;
  241. $where['value'] = $value;
  242. }
  243. $where['condition'] = count($this->where) ? $condition : '';
  244. //Make sure we don't store the same where clauses twice
  245. $signature = md5($property.$constraint.$value);
  246. if(!isset($this->where[$signature])) {
  247. $this->where[$signature] = $where;
  248. }
  249. }
  250. return $this;
  251. }
  252. /**
  253. * Built the group clause of the query
  254. *
  255. * @param array|string A string or array of ordering columns
  256. * @return KDatabaseQuery
  257. */
  258. public function group( $columns )
  259. {
  260. settype($columns, 'array'); //force to an array
  261. $this->group = array_unique( array_merge( $this->group, $columns));
  262. return $this;
  263. }
  264. /**
  265. * Built the having clause of the query
  266. *
  267. * @param array|string A string or array of ordering columns
  268. * @return KDatabaseQuery
  269. */
  270. public function having( $columns )
  271. {
  272. settype($columns, 'array'); //force to an array
  273. $this->having = array_unique( array_merge( $this->having, $columns ));
  274. return $this;
  275. }
  276. /**
  277. * Build the order clause of the query
  278. *
  279. * @param array|string A string or array of ordering columns
  280. * @param string Either DESC or ASC
  281. * @return KDatabaseQuery
  282. */
  283. public function order( $columns, $direction = 'ASC' )
  284. {
  285. settype($columns, 'array'); //force to an array
  286. foreach($columns as $column)
  287. {
  288. $this->order[] = array(
  289. 'column' => $column,
  290. 'direction' => $direction
  291. );
  292. }
  293. return $this;
  294. }
  295. /**
  296. * Built the limit element of the query
  297. *
  298. * @param integer Number of items to fetch.
  299. * @param integer Offset to start fetching at.
  300. * @return KDatabaseQuery
  301. */
  302. public function limit( $limit, $offset = 0 )
  303. {
  304. $this->limit = (int) $limit;
  305. $this->offset = (int) $offset;
  306. return $this;
  307. }
  308. /**
  309. * Render the query to a string
  310. *
  311. * @return string The completed query
  312. */
  313. public function __toString()
  314. {
  315. $query = '';
  316. if(!empty($this->columns) || $this->count)
  317. {
  318. $query = 'SELECT';
  319. if($this->distinct) {
  320. $query .= ' DISTINCT';
  321. }
  322. if($this->count) {
  323. $query .= ' COUNT(*)';
  324. }
  325. }
  326. if (!empty($this->columns) && ! $this->count)
  327. {
  328. $columns = array();
  329. foreach($this->columns as $column) {
  330. $columns[] = $this->_adapter->quoteName($column);
  331. }
  332. $query .= ' '.implode(' , ', $columns);
  333. }
  334. if (!empty($this->from))
  335. {
  336. $tables = array();
  337. foreach($this->from as $table) {
  338. $tables[] = $this->_adapter->quoteName($table);
  339. }
  340. $query .= ' FROM '.implode(' , ', $tables);
  341. }
  342. if (!empty($this->join))
  343. {
  344. $joins = array();
  345. foreach ($this->join as $join)
  346. {
  347. $tmp = ' ';
  348. if (! empty($join['type'])) {
  349. $tmp .= $join['type'] . ' ';
  350. }
  351. $tmp .= ' JOIN ' . $this->_adapter->quoteName($join['table']);
  352. $tmp .= ' ON (' . implode(' AND ', $this->_adapter->quoteName($join['condition'])) . ')';
  353. $joins[] = $tmp;
  354. }
  355. $query .= implode(' ', $joins);
  356. }
  357. if (!empty($this->where))
  358. {
  359. $query .= ' WHERE';
  360. foreach($this->where as $where)
  361. {
  362. if(isset($where['condition'])) {
  363. $query .= ' '.$where['condition'];
  364. }
  365. $query .= ' '. $this->_adapter->quoteName($where['property']);
  366. if(isset($where['constraint']))
  367. {
  368. $value = $this->_adapter->quoteValue($where['value']);
  369. if(in_array($where['constraint'], array('IN', 'NOT IN'))) {
  370. $value = ' ( '.$value. ' ) ';
  371. }
  372. $query .= ' '.$where['constraint'].' '.$value;
  373. }
  374. }
  375. }
  376. if (!empty($this->group))
  377. {
  378. $columns = array();
  379. foreach($this->group as $column) {
  380. $columns[] = $this->_adapter->quoteName($column);
  381. }
  382. $query .= ' GROUP BY '.implode(' , ', $columns);
  383. }
  384. if (!empty($this->having))
  385. {
  386. $columns = array();
  387. foreach($this->having as $column) {
  388. $columns[] = $this->_adapter->quoteName($column);
  389. }
  390. $query .= ' HAVING '.implode(' , ', $columns);
  391. }
  392. if (!empty($this->order) )
  393. {
  394. $query .= ' ORDER BY ';
  395. $list = array();
  396. foreach ($this->order as $order) {
  397. $list[] = $this->_adapter->quoteName($order['column']).' '.$order['direction'];
  398. }
  399. $query .= implode(' , ', $list);
  400. }
  401. if (!empty($this->limit)) {
  402. $query .= ' LIMIT '.$this->offset.' , '.$this->limit;
  403. }
  404. return $query;
  405. }
  406. }