2015-05-06 19:25:57 +00:00
|
|
|
<?php
|
2015-08-29 15:43:13 +00:00
|
|
|
/**
|
|
|
|
* FuzeWorks
|
|
|
|
*
|
|
|
|
* The FuzeWorks MVC PHP FrameWork
|
|
|
|
*
|
|
|
|
* Copyright (C) 2015 TechFuze
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* @author TechFuze
|
|
|
|
* @copyright Copyright (c) 2013 - 2015, Techfuze. (http://techfuze.net)
|
|
|
|
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
|
|
|
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
|
|
|
* @link http://fuzeworks.techfuze.net
|
|
|
|
* @since Version 0.0.1
|
|
|
|
* @version Version 0.0.1
|
|
|
|
*/
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
namespace Module\DatabaseUtils;
|
|
|
|
use \FuzeWorks\Module;
|
2015-09-05 19:47:35 +00:00
|
|
|
use \FuzeWorks\Modules;
|
2015-05-06 19:25:57 +00:00
|
|
|
use \FuzeWorks\DatabaseException;
|
2015-09-05 19:47:35 +00:00
|
|
|
use \FuzeWorks\Config;
|
|
|
|
use \FuzeWorks\Logger;
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class Query
|
2015-08-29 15:43:13 +00:00
|
|
|
* @package net.techfuze.fuzeworks.databaseutils
|
|
|
|
* @author GOScripting
|
|
|
|
* @copyright Copyright (c) 2014 - 2015, GOScripting B.V. (http://goscripting.com)
|
|
|
|
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
|
|
|
* @link http://goframework.net
|
2015-05-06 19:25:57 +00:00
|
|
|
*
|
|
|
|
* @method $this or() or(string $field, string $arg2) OR $arg2 is the value of the field, or an operator in which case the value is pushed to the third argument
|
|
|
|
* @method $this and() and(string $field, string $arg2) AND $arg2 is the value of the field, or an operator in which case the value is pushed to the third argument
|
|
|
|
*/
|
|
|
|
class Query extends Module {
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* @var array An array containing all the counted functions
|
2015-05-06 19:25:57 +00:00
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
private $functions = array();
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var null|string The table used
|
|
|
|
*/
|
|
|
|
private $table = '';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var null|\PDOStatement
|
|
|
|
*/
|
|
|
|
private $sth = null;
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* @param string $table The string to set as a table, optional
|
2015-05-06 19:25:57 +00:00
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function __construct($table = ''){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
if($table != '')
|
|
|
|
$this->setTable($table);
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
/**
|
|
|
|
* Each argument is another field to select
|
|
|
|
*
|
2015-09-06 13:42:57 +00:00
|
|
|
* @param string $field,... The field to select, if no field is given, all fields(*) will be selected
|
2015-05-06 19:25:57 +00:00
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
public function select($field = '*'){
|
|
|
|
|
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
|
|
|
|
|
|
|
private function internalSelect($field = '*')
|
|
|
|
{
|
|
|
|
return array(
|
|
|
|
'sql'=> 'SELECT ' . ($field == '*' ? '*' : implode(", ", func_get_args()) . ''),
|
|
|
|
'binds' => null
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* From
|
|
|
|
*
|
2015-09-06 13:42:57 +00:00
|
|
|
* @param $table,... null|string The table, if it is null, the table set with setTable() will be used
|
2015-05-06 19:25:57 +00:00
|
|
|
* @return $this
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function from($table = null){
|
|
|
|
|
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
|
|
|
|
|
|
|
private function internalFrom($table = null)
|
2015-05-06 19:25:57 +00:00
|
|
|
{
|
2015-05-14 11:30:40 +00:00
|
|
|
$tables = func_get_args();
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query = 'FROM ';
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-05-14 11:30:40 +00:00
|
|
|
if(count($tables) == 0)
|
2015-09-06 13:42:57 +00:00
|
|
|
$tables[] = "$this->table";
|
2015-05-14 11:30:40 +00:00
|
|
|
|
|
|
|
else foreach($tables as $i => $t) {
|
|
|
|
|
|
|
|
if ($t == '' && $this->table == '')
|
|
|
|
throw new Exception("No table given");
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$tables[$i] = strpos($t, ' ') === false ? "$t" : ''.implode(' ', explode(' ', $t));
|
2015-05-14 11:30:40 +00:00
|
|
|
}
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= implode(', ', $tables);
|
2015-05-14 11:30:40 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => $query,
|
|
|
|
'binds' => null
|
|
|
|
);
|
2015-05-14 11:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* (Inner) join
|
|
|
|
*
|
|
|
|
* @param string $table The table to join
|
|
|
|
* @param string $type The type of join to perform (JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN)
|
|
|
|
* @return $this
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function join($table, $type = ''){
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
|
|
|
|
|
|
|
private function internalJoin($table, $type = ''){
|
|
|
|
|
2015-05-14 11:30:40 +00:00
|
|
|
if($table === '') {
|
|
|
|
|
|
|
|
if ($this->table == '')
|
2015-05-06 19:25:57 +00:00
|
|
|
throw new Exception("No table given");
|
|
|
|
|
|
|
|
$table = $this->table;
|
|
|
|
}
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query = '';
|
|
|
|
|
2015-05-14 11:30:40 +00:00
|
|
|
if($type != '')
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= $type . ' ';
|
2015-05-14 11:30:40 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= 'JOIN ' . (strpos($table, ' ') === false ? "$table" : ''.implode(' ', explode(' ', $table)));
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => $query,
|
|
|
|
'binds' => null
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-05-14 11:30:40 +00:00
|
|
|
* Left join
|
2015-05-06 19:25:57 +00:00
|
|
|
*
|
2015-05-14 11:30:40 +00:00
|
|
|
* @param string $table The table to join
|
|
|
|
* @return $this
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function left_join($table){
|
|
|
|
|
|
|
|
return $this->join($table, 'LEFT');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Right join
|
|
|
|
*
|
|
|
|
* @param string $table The table to join
|
|
|
|
* @return $this
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function right_join($table){
|
|
|
|
|
|
|
|
return $this->join($table, 'RIGHT');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Full join
|
|
|
|
*
|
|
|
|
* @param string $table The table to join
|
|
|
|
* @return $this
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function full_join($table){
|
|
|
|
|
|
|
|
return $this->join($table, 'FULL');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* On
|
|
|
|
*
|
|
|
|
* @param string $field Field name, or raw SQL
|
2015-05-06 19:25:57 +00:00
|
|
|
* @param $arg2 string, The value of the field, or an operator in which case the value is pushed to $arg3
|
|
|
|
* @param null|string $arg3 The value of the field when $arg2 is used for an operator
|
|
|
|
* @return $this
|
|
|
|
*/
|
2015-05-14 11:30:40 +00:00
|
|
|
public function on($field, $arg2 = null, $arg3 = null){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-05-14 11:30:40 +00:00
|
|
|
return $this->where($field, $arg2, $arg3, 'ON');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Where
|
|
|
|
*
|
2015-09-06 13:42:57 +00:00
|
|
|
* @param string|null $field Field name, or raw SQL, If this is left empty, only the $type will be added to the query
|
2015-05-14 11:30:40 +00:00
|
|
|
* @param string $arg2, The value of the field, or an operator in which case the value is pushed to $arg3
|
|
|
|
* @param null|string $arg3 The value of the field when $arg2 is used for an operator
|
|
|
|
* @param string $type Whether this is an WHERE or ON operation
|
|
|
|
* @return $this
|
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function where($field = null, $arg2 = null, $arg3 = null, $type = 'WHERE'){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
private function internalWhere($field = null, $arg2 = null, $arg3 = null, $type = 'WHERE'){
|
2015-05-14 11:30:40 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
if($field == null)
|
|
|
|
return array('sql' => $type, 'binds' => array());
|
2015-05-14 11:30:40 +00:00
|
|
|
|
|
|
|
if($arg2 === null)
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->internalSql($type . ' '.$field);
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
//The value is the second parameter, unless the second parameter is an operator, in which case it's the third
|
2015-05-06 19:25:57 +00:00
|
|
|
$value = ($arg3 == null ? $arg2 : $arg3);
|
|
|
|
//If the third parameter is not given, the default operator should be used
|
|
|
|
$operator = strtoupper($arg3 == null ? "=" : $arg2);
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query = '';
|
|
|
|
$binds = array();
|
2015-05-14 11:30:40 +00:00
|
|
|
|
2015-05-06 19:25:57 +00:00
|
|
|
switch($operator){
|
|
|
|
|
|
|
|
case 'IN':
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= $type . ($type == '' ? '' : ' ') . $field.' IN (';
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
if(is_array($value)) {
|
|
|
|
foreach ($value as $k => $v) {
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= '?,';
|
|
|
|
$binds[] = $v;
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
//Remove the trailing comma and close it
|
|
|
|
$query = rtrim($query, ",") . ')';
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
}elseif(get_class($value) == 'System\Core\Query'){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
|
|
|
|
/** @var Query $value */
|
|
|
|
$data = $this->internalSql($value->getSql(), $value->getBinds());
|
|
|
|
$query .= $data['sql'] . ')';
|
|
|
|
$binds = array_merge($binds, $data['binds']);
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'BETWEEN':
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= $type . ($type == '' ? '' : ' ') . $field.' BETWEEN ? AND ?';
|
|
|
|
$binds[] = $value[0];
|
|
|
|
$binds[] = $value[1];
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= $type . ($type == '' ? '' : ' ') . $field.' ' . $operator . ' ?';
|
|
|
|
$binds[] = $value;
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2015-09-06 13:42:57 +00:00
|
|
|
|
|
|
|
return array(
|
|
|
|
'sql' => $query,
|
|
|
|
'binds' => $binds
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
|
2015-05-06 19:25:57 +00:00
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
*And, keep in mind this is only the OR statement. For A = B call ->where
|
|
|
|
* @return array
|
2015-05-06 19:25:57 +00:00
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
private function internalOr(){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => 'OR',
|
|
|
|
'binds' => array()
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* And, keep in mind this is only the AND statement. For A = B call ->where
|
|
|
|
* @return array
|
2015-05-06 19:25:57 +00:00
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
private function internalAnd(){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => 'AND',
|
|
|
|
'binds' => array()
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* An opening bracket
|
2015-05-06 19:25:57 +00:00
|
|
|
* @return $this
|
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function open(){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
private function internalOpen(){
|
|
|
|
|
|
|
|
return array(
|
|
|
|
'sql' => '(',
|
|
|
|
'binds' => ''
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* A closing bracket
|
2015-05-06 19:25:57 +00:00
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function close(){
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
|
|
|
|
|
|
|
private function internalClose(){
|
|
|
|
|
|
|
|
return array(
|
|
|
|
'sql' => ')',
|
|
|
|
'binds' => null
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Order By
|
|
|
|
*
|
|
|
|
* Each argument is another order. If you put a minus in front of the name, the order will be DESC instead of ASC
|
|
|
|
*
|
2015-09-06 13:42:57 +00:00
|
|
|
* @param string $field,... The field to order by, add a minus in front of the name and the order will be DESC
|
2015-05-06 19:25:57 +00:00
|
|
|
* @return $this
|
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function order($field){
|
|
|
|
|
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
|
|
|
|
|
|
|
private function internalOrder($field){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query = 'ORDER BY';
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
foreach(func_get_args() as $field){
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
if(substr($query, -2) != 'BY')
|
|
|
|
$query .= ",";
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
$mode = 'ASC';
|
|
|
|
|
|
|
|
if(substr($field, 0, 1) == '-'){
|
|
|
|
|
|
|
|
$field = substr($field, 1);
|
|
|
|
$mode = 'DESC';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= ' ' . $field . ' ' . $mode;
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => $query,
|
|
|
|
'binds' => null
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* Group by
|
2015-05-06 19:25:57 +00:00
|
|
|
*
|
2015-09-06 13:42:57 +00:00
|
|
|
* Each argument is another field to group by.
|
2015-05-06 19:25:57 +00:00
|
|
|
*
|
2015-09-06 13:42:57 +00:00
|
|
|
* @param string $field,... The field to group by
|
2015-05-06 19:25:57 +00:00
|
|
|
* @return $this
|
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function groupBy($field){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
private function internalGroupBy($field){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query = 'GROUP BY ';
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$first = true;
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
foreach(func_get_args() as $field){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
if(!$first){
|
|
|
|
$query .= ', ';
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$first = false;
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= $field;
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => $query,
|
|
|
|
'binds' => null,
|
|
|
|
);
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
/**
|
|
|
|
* limit
|
|
|
|
*
|
|
|
|
* @param $limit int Limit
|
|
|
|
* @param int $offset int Offset
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function limit($limit, $offset = 0){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
private function internalLimit($limit, $offset = 0){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => 'LIMIT ' . $offset . ', ' . $limit,
|
|
|
|
'binds' => null
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* Having
|
2015-05-06 19:25:57 +00:00
|
|
|
*
|
|
|
|
* @param $field
|
|
|
|
* @param $arg2 string, The value of the field, or an operator in which case the value is pushed to $arg3
|
|
|
|
* @param null|string $arg3 The value of the field when $arg2 is used for an operator
|
|
|
|
* @return $this
|
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function having($field = null, $arg2 = null, $arg3 = null){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->where($field, $arg2, $arg3, 'HAVING');
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update
|
|
|
|
*
|
|
|
|
* @param $table null|string Name of the table, if it is null, the table set with setTable() will be used
|
|
|
|
* @return $this
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function update($table = ''){
|
|
|
|
|
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
private function internalUpdate($table = '')
|
2015-05-06 19:25:57 +00:00
|
|
|
{
|
|
|
|
if($table === ''){
|
|
|
|
|
|
|
|
if($this->table == '')
|
|
|
|
throw new Exception("No table given");
|
|
|
|
|
|
|
|
$table = $this->table;
|
|
|
|
}
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => 'UPDATE ' . $table,
|
|
|
|
'binds' => array()
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set
|
|
|
|
*
|
2015-05-14 11:30:40 +00:00
|
|
|
* @param $data array|string Key value, $field => $value or raw SQL
|
2015-05-06 19:25:57 +00:00
|
|
|
* @return $this
|
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function set($data){
|
|
|
|
|
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
|
|
|
|
|
|
|
private function internalSet($data)
|
2015-05-06 19:25:57 +00:00
|
|
|
{
|
2015-05-14 11:30:40 +00:00
|
|
|
if(is_string($data))
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->internalSql('SET '.$data);
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query = 'SET';
|
|
|
|
$binds = array();
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
$first = true;
|
|
|
|
|
2015-05-14 11:30:40 +00:00
|
|
|
foreach($data as $field => $value){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
if(!$first)
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= ',';
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
$first = false;
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= ' ' . $field . '=?';
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$binds[] = $value;
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => $query,
|
|
|
|
'binds' => $binds
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete
|
|
|
|
*
|
|
|
|
* @return $this
|
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function delete(){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
private function internalDelete()
|
|
|
|
{
|
|
|
|
return array(
|
|
|
|
'sql' => 'DELETE',
|
|
|
|
'binds' => array()
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert
|
|
|
|
*
|
|
|
|
* @param $array array Key value, $field => $value
|
|
|
|
* @param $table string|null Table name, if it is null, the table set with setTable() will be used
|
|
|
|
* @return $this
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function insert($array, $table = ''){
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
|
|
|
|
|
|
|
private function internalInsert($array, $table = ''){
|
|
|
|
|
|
|
|
if($table === ''){
|
|
|
|
|
|
|
|
if($this->table == '')
|
|
|
|
throw new DatabaseException("No table given");
|
|
|
|
|
|
|
|
$table = $this->table;
|
|
|
|
}
|
|
|
|
|
|
|
|
$query = '';
|
|
|
|
$binds = array();
|
|
|
|
|
|
|
|
//Implode the array to get a list with the fields
|
|
|
|
$query .= 'INSERT INTO ' . $table . ' (' . implode(',', array_keys($array)) . ') VALUES (';
|
|
|
|
|
|
|
|
//Add all the values as ? and add them to the binds
|
|
|
|
foreach($array as $field => $value){
|
|
|
|
$query .= '?,';
|
|
|
|
|
|
|
|
$binds[] = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
$query = rtrim($query, ',') . ')';
|
|
|
|
|
|
|
|
return array(
|
|
|
|
'sql' => $query,
|
|
|
|
'binds' => $binds
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replace
|
|
|
|
*
|
|
|
|
* @param $array array Key value, $field => $value
|
|
|
|
* @param $table string|null Table name, if it is null, the table set with setTable() will be used
|
|
|
|
* @return $this
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function replace($array, $table = ''){
|
|
|
|
|
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
|
|
|
|
|
|
|
private function internalReplace($array, $table = ''){
|
|
|
|
|
2015-05-06 19:25:57 +00:00
|
|
|
if($table === ''){
|
|
|
|
|
|
|
|
if($this->table == '')
|
|
|
|
throw new DatabaseException("No table given");
|
|
|
|
|
|
|
|
$table = $this->table;
|
|
|
|
}
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query = '';
|
|
|
|
$binds = array();
|
|
|
|
|
2015-05-06 19:25:57 +00:00
|
|
|
//Implode the array to get a list with the fields
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= 'REPLACE INTO ' . $table . ' (' . implode(',', array_keys($array)) . ') VALUES (';
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
//Add all the values as ? and add them to the binds
|
|
|
|
foreach($array as $field => $value){
|
2015-09-06 13:42:57 +00:00
|
|
|
$query .= '?,';
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$binds[] = $value;
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$query = rtrim($query, ',') . ')';
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => $query,
|
|
|
|
'binds' => $binds
|
|
|
|
);
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
2015-05-14 11:30:40 +00:00
|
|
|
/**
|
|
|
|
* Add raw SQL to the query string
|
|
|
|
*
|
|
|
|
* @param string $sql The SQL to add
|
2015-09-06 13:42:57 +00:00
|
|
|
* @param array $binds The optional binds to add
|
|
|
|
* @return $this
|
2015-05-14 11:30:40 +00:00
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function sql($sql, $binds = array()){
|
|
|
|
|
|
|
|
return $this->__call(__FUNCTION__, func_get_args());
|
|
|
|
}
|
2015-05-14 11:30:40 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
private function internalSql($sql, $binds = array()){
|
2015-05-14 11:30:40 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return array(
|
|
|
|
'sql' => $sql,
|
|
|
|
'binds' => $binds
|
|
|
|
);
|
2015-05-14 11:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* Builds The SQL query and its binds.
|
|
|
|
* @return array
|
2015-05-14 11:30:40 +00:00
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function build(){
|
2015-05-14 11:30:40 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$sql = array();
|
|
|
|
$binds = array();
|
2015-05-14 11:30:40 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
foreach($this->functions as $i => $function){
|
|
|
|
|
|
|
|
//The current function is a WHERE or HAVING,
|
|
|
|
//and it after a or, and or open, this means we do not have to
|
|
|
|
//add the WHERE/HAVING statement again
|
|
|
|
if((
|
|
|
|
$function['name'] == 'internalWhere' ||
|
|
|
|
$function['name'] == 'internalHaving'
|
|
|
|
)&&
|
|
|
|
(
|
|
|
|
$this->functions[$i - 1]['name'] == 'internalOpen' ||
|
|
|
|
$this->functions[$i - 1]['name'] == 'internalAnd' ||
|
|
|
|
$this->functions[$i - 1]['name'] == 'internalOr'
|
|
|
|
)){
|
|
|
|
|
|
|
|
if(!isset($function['arguments'][2]))
|
|
|
|
$function['arguments'][2] = null;
|
|
|
|
|
|
|
|
$function['arguments'][3] = '';
|
|
|
|
}
|
2015-05-14 11:30:40 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
|
|
|
|
$data = call_user_func_array(array($this, $function['name']), $function['arguments']);
|
|
|
|
|
|
|
|
$sql[] = $data['sql'];
|
|
|
|
|
|
|
|
if($data['binds'] != null)
|
|
|
|
$binds = array_merge($binds, $data['binds']);
|
|
|
|
}
|
|
|
|
|
|
|
|
return array(
|
|
|
|
'sql' => implode(' ', $sql),
|
|
|
|
'binds' => $binds
|
|
|
|
);
|
|
|
|
}
|
2015-05-06 19:25:57 +00:00
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* Returns the query as an array
|
2015-05-06 19:25:57 +00:00
|
|
|
*
|
2015-09-06 13:42:57 +00:00
|
|
|
* @return array
|
2015-05-06 19:25:57 +00:00
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function getSql(){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->build()['sql'];
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* Return the built SQL query
|
2015-05-06 19:25:57 +00:00
|
|
|
*
|
2015-09-06 13:42:57 +00:00
|
|
|
* @return string
|
2015-05-06 19:25:57 +00:00
|
|
|
*/
|
|
|
|
public function getBinds(){
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return $this->build()['binds'];
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $table
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setTable($table){
|
|
|
|
|
|
|
|
$this->table = $table;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return null|string
|
|
|
|
*/
|
|
|
|
public function getTable(){
|
|
|
|
|
|
|
|
return $this->table;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function commit(){
|
|
|
|
|
2015-09-05 19:47:35 +00:00
|
|
|
Modules::get('core/database')->commit();
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function beginTransaction(){
|
|
|
|
|
2015-09-05 19:47:35 +00:00
|
|
|
Modules::get('core/database')->beginTransaction();
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function rollback(){
|
|
|
|
|
2015-09-05 19:47:35 +00:00
|
|
|
Modules::get('core/database')->rollback();
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Executes the query generated
|
|
|
|
*
|
|
|
|
* @return $this
|
|
|
|
* @throws DatabaseException
|
|
|
|
*/
|
|
|
|
public function execute(){
|
|
|
|
|
|
|
|
|
2015-09-05 19:47:35 +00:00
|
|
|
if(Config::get('database')->debug)
|
2015-09-06 13:42:57 +00:00
|
|
|
Logger::log(get_class($this).': '.$this->getSql());
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
try{
|
|
|
|
|
2015-10-11 18:14:49 +00:00
|
|
|
$this->sth = Modules::get('core/database')->prepare($this->getSql());
|
2015-09-06 13:42:57 +00:00
|
|
|
if(count($this->getBinds()) === 0){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
$this->sth->execute();
|
|
|
|
}else{
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$this->sth->execute($this->getBinds());
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
}catch (\PDOException $e) {
|
|
|
|
|
|
|
|
throw new DatabaseException('Could not execute SQL-query due PDO-exception ' . $e->getMessage());
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* Returns the results of the query in the given type. All the arguments of this function will be passed onto
|
|
|
|
* fetchAll
|
|
|
|
* @param int $type The default type is \PDO::FETCH_ASSOC, all the types that are possible for fetchAll() are valid
|
|
|
|
* @return array
|
2015-05-06 19:25:57 +00:00
|
|
|
* @throws DatabaseException
|
|
|
|
*/
|
2015-09-06 13:42:57 +00:00
|
|
|
public function getResults($type = \PDO::FETCH_ASSOC){
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
if(!isset($this->sth))
|
|
|
|
$this->execute();
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
return call_user_func_array(array(
|
|
|
|
$this->sth,
|
|
|
|
'fetchAll'
|
|
|
|
), func_get_args());
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the amount of rows that are affected. ->execute must be called first.
|
|
|
|
* @return int Amount of rows that are affected
|
|
|
|
* @throws DatabaseException
|
|
|
|
*/
|
|
|
|
public function getRowCount(){
|
|
|
|
|
|
|
|
if(!isset($this->sth))
|
|
|
|
$this->execute();
|
|
|
|
|
|
|
|
return $this->sth->rowCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getLastInsertId(){
|
|
|
|
|
2015-10-11 18:14:49 +00:00
|
|
|
return Modules::get('core/database')->lastInsertId();
|
2015-05-06 19:25:57 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-09-06 13:42:57 +00:00
|
|
|
* All the called functions are saved in an array, so when build is called, the query is built from all the functions
|
2015-05-06 19:25:57 +00:00
|
|
|
*
|
|
|
|
* @param $name string
|
|
|
|
* @param $arguments array
|
2015-09-06 13:42:57 +00:00
|
|
|
* @return $this
|
|
|
|
* @throws DatabaseException
|
2015-05-06 19:25:57 +00:00
|
|
|
*/
|
|
|
|
public function __call($name, $arguments){
|
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$name = "internal" . ucfirst($name);
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
if(!method_exists($this, $name))
|
|
|
|
throw new DatabaseException('Unknown function "' . $name . '"');
|
2015-05-06 19:25:57 +00:00
|
|
|
|
2015-09-06 13:42:57 +00:00
|
|
|
$this->functions[] = array(
|
|
|
|
'name' => $name,
|
|
|
|
'arguments' => $arguments
|
|
|
|
);
|
|
|
|
|
|
|
|
return $this;
|
2015-05-06 19:25:57 +00:00
|
|
|
}
|
|
|
|
}
|