ulmus/src/QueryBuilder.php

274 lines
6.6 KiB
PHP

<?php
namespace Ulmus;
class QueryBuilder
{
public Query\Where $where;
/**
* Those are the parameters we are going to bind to PDO.
*/
public array $parameters = [];
/**
*
* Those values are to be inserted or updated
*/
public array $values = [];
public string $conditionOperator = Query\Where::CONDITION_AND;
protected int $parameterIndex = 0;
protected array $queryStack = [];
public function select($field) : self
{
if ( false !== ( $select = $this->has(Query\Select::class) ) ) {
$select->add($field);
}
else {
$select = new Query\Select();
$select->set($field);
$this->push($select);
}
return $this;
}
public function insert(array $fieldlist, string $table, ? string $alias = null, ? string $database = null, ? string $schema = null) : self
{
if ( ! $this->has(Query\Insert::class) ) {
if ( $database ) {
$table = "\"$database\".$table";
}
if ( $schema ) {
$table = "\"$schema\".$table";
}
$insert = new Query\Insert();
$this->push($insert);
$insert->fieldlist = $fieldlist;
$insert->alias = $alias;
$insert->table = $table;
}
return $this;
}
public function values(array $dataset) : self
{
if ( false === ( $values = $this->has(Query\Values::class) ) ) {
$values = new Query\Values($this);
$this->push($values);
}
$values->add($dataset);
return $this;
}
public function update(string $table, ? string $alias = null, ? string $database = null, ? string $schema = null) : self
{
if ( ! $this->has(Query\Update::class) ) {
if ( $database ) {
$table = "\"$database\".$table";
}
if ( $schema ) {
$table = "\"$schema\".$table";
}
$update = new Query\Update();
$this->push($update);
$update->alias = $alias;
$update->table = $table;
}
return $this;
}
public function set(array $dataset) : self
{
if ( false === ( $values = $this->has(Query\Set::class) ) ) {
$set = new Query\Set($this);
$this->push($set);
}
$set->set($dataset);
return $this;
}
public function delete() : self
{
if ( ! $this->has(Query\Delete::class) ) {
$this->push(new Query\Delete());
}
return $this;
}
public function from(string $table, ? string $alias = null, ? string $database = null, ? string $schema = null) : self
{
if ( $database ) {
$table = "\"$database\".$table";
}
if ( $schema ) {
$table = "\"$schema\".$table";
}
if ( false !== ( $from = $this->has(Query\From::class) ) ) {
$from->add($alias ? [ $alias => $table ] : $table);
}
else {
$from = new Query\From($this);
$this->push($from);
$from->set($alias ? [ $alias => $table ] : $table);
}
return $this;
}
public function open(string $condition = Query\Where::CONDITION_AND) : self
{
if ( false !== ($this->where ?? false) ) {
$this->where->conditionList[] = $new = new Query\Where($this, $condition);
$this->where = $new;
}
return $this;
}
public function close() : self
{
if ( false !== ($this->where ?? false) && $this->where->parent ) {
$this->where = $this->where->parent;
}
return $this;
}
public function where($field, $value, string $operator = Query\Where::OPERATOR_EQUAL, string $condition = Query\Where::CONDITION_AND, bool $not = false) : self
{
if ( $this->where ?? false ) {
$where = $this->where;
}
elseif ( false === ( $where = $this->has(Query\Where::class) ) ) {
$this->where = $where = new Query\Where($this);
$this->push($where);
}
$this->conditionOperator = $operator;
$where->add($field, $value, $operator, $condition, $not);
return $this;
}
public function notWhere($field, $value, string $operator = Query\Where::CONDITION_AND) : self
{
return $this->where($field, $value, $operator, true);
}
public function groupBy() : self
{
//$this->queryBuilder->groupBy();
return $this;
}
public function limit(int $value) : self
{
if ( false === $limit = $this->has(Query\Limit::class) ) {
$limit = new Query\Limit();
$this->push($limit);
}
$limit->set($value);
return $this;
}
public function offset(int $value) : self
{
if ( false === $offset = $this->has(Query\Offset::class) ) {
$offset = new Query\Offset();
$this->push($offset);
}
$offset->set($value);
return $this;
}
public function orderBy(string $field, ? string $direction = null) : self
{
if ( false === $orderBy = $this->has(Query\OrderBy::class) ) {
$orderBy = new Query\OrderBy();
$this->push($orderBy);
}
$orderBy->add($field, $direction);
return $this;
}
public function push(Query\Fragment $queryFragment) : self
{
$this->queryStack[] = $queryFragment;
return $this;
}
public function render() : string
{
$sql = [];
usort($this->queryStack, function($q1, $q2) {
return $q1->order <=> $q2->order;
});
foreach($this->queryStack as $fragment) {
$sql[] = $fragment->render();
}
return implode(" ", $sql);
}
public function has($class) {
foreach($this->queryStack as $item) {
if ( get_class($item) === $class ) {
return $item;
}
}
return false;
}
public function __toString() : string
{
return $this->render();
}
public function addParameter($value, string $key = null) : string
{
if ( $key === null ) {
$key = ":p" . $this->parameterIndex++;
}
$this->parameters[$key] = $value;
return $key;
}
public function addValues(array $values) : void
{
$this->values = $values;
}
}