A super easy PHP Framework for web development!
https://github.com/exacti/phacil-framework
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
397 lines
9.8 KiB
397 lines
9.8 KiB
1 year ago
|
<?php
|
||
|
|
||
|
/**
|
||
|
* Copyright © 2023 ExacTI Technology Solutions. All rights reserved.
|
||
|
* GPLv3 General License.
|
||
|
* https://exacti.com.br
|
||
|
* Phacil PHP Framework - https://github.com/exacti/phacil-framework
|
||
|
*/
|
||
|
|
||
|
namespace Phacil\Framework\MagiQL\Builder\Syntax;
|
||
|
|
||
|
use Phacil\Framework\MagiQL\Api\BuilderInterface;
|
||
|
use Phacil\Framework\MagiQL\Manipulation\Select;
|
||
|
use Phacil\Framework\MagiQL\Syntax\Column;
|
||
|
use Phacil\Framework\MagiQL\Syntax\OrderBy;
|
||
|
use Phacil\Framework\MagiQL\Syntax\SyntaxFactory;
|
||
|
|
||
|
/**
|
||
|
* Class SelectWriter.
|
||
|
*/
|
||
|
class SelectWriter extends AbstractBaseWriter
|
||
|
{
|
||
|
/**
|
||
|
* @param $alias
|
||
|
* @param Select $select
|
||
|
*
|
||
|
* @return Column
|
||
|
*/
|
||
|
public function selectToColumn($alias, Select $select)
|
||
|
{
|
||
|
$selectAsColumn = $this->write($select);
|
||
|
|
||
|
if (!empty($selectAsColumn)) {
|
||
|
$selectAsColumn = '('.$selectAsColumn.')';
|
||
|
}
|
||
|
|
||
|
$column = array($alias => $selectAsColumn);
|
||
|
|
||
|
return SyntaxFactory::createColumn($column, null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function write(Select $select)
|
||
|
{
|
||
|
if ($select->isJoinSelect()) {
|
||
|
return $this->writer->writeJoin($select);
|
||
|
}
|
||
|
|
||
|
return $this->writeSelectQuery($select);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function writeSelectQuery(Select $select)
|
||
|
{
|
||
|
$parts = ['SELECT'];
|
||
|
|
||
|
if ($select->isDistinct()) {
|
||
|
$parts[] = 'DISTINCT';
|
||
|
}
|
||
|
|
||
|
$this->writeSelectColumns($select, $parts);
|
||
|
$this->writeSelectFrom($select, $parts);
|
||
|
$this->writeSelectJoins($select, $parts);
|
||
|
$this->writeSelectWhere($select, $parts);
|
||
|
$this->writeSelectGroupBy($select, $parts);
|
||
|
$this->writeSelectHaving($select, $parts);
|
||
|
$this->writeSelectOrderBy($select, $parts);
|
||
|
$this->writeSelectLimit($select, $parts);
|
||
|
|
||
|
return AbstractBaseWriter::writeQueryComment($select).implode(' ', \array_filter($parts));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
* @param string[] $parts
|
||
|
*
|
||
|
* @return $this
|
||
|
*/
|
||
|
public function writeSelectColumns(Select $select, array &$parts)
|
||
|
{
|
||
|
if ($select->isCount() === false) {
|
||
|
$columns = $this->writeColumnAlias(
|
||
|
$select->getAllColumns(),
|
||
|
$this->columnWriter->writeSelectsAsColumns($select),
|
||
|
$this->columnWriter->writeValueAsColumns($select),
|
||
|
$this->columnWriter->writeFuncAsColumns($select)
|
||
|
);
|
||
|
|
||
|
$parts = \array_merge($parts, [implode(', ', $columns)]);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
$columns = $select->getColumns();
|
||
|
$column = \array_pop($columns);
|
||
|
$columnList = $column->getName();
|
||
|
|
||
|
$parts = \array_merge($parts, [$columnList]);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param $tableColumns
|
||
|
* @param $selectAsColumns
|
||
|
* @param $valueAsColumns
|
||
|
* @param $funcAsColumns
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function writeColumnAlias($tableColumns, $selectAsColumns, $valueAsColumns, $funcAsColumns)
|
||
|
{
|
||
|
$columns = \array_merge($tableColumns, $selectAsColumns, $valueAsColumns, $funcAsColumns);
|
||
|
|
||
|
\array_walk(
|
||
|
$columns,
|
||
|
function (&$column) {
|
||
|
$column = $this->columnWriter->writeColumnWithAlias($column);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
return $columns;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
* @param string[] $parts
|
||
|
*
|
||
|
* @return $this
|
||
|
*/
|
||
|
public function writeSelectFrom(Select $select, array &$parts)
|
||
|
{
|
||
|
$parts = \array_merge(
|
||
|
$parts,
|
||
|
['FROM '.$this->writer->writeTableWithAlias($select->getTable())]
|
||
|
);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
* @param array $parts
|
||
|
*
|
||
|
* @return $this
|
||
|
*/
|
||
|
public function writeSelectJoins(Select $select, array &$parts)
|
||
|
{
|
||
|
$parts = \array_merge(
|
||
|
$parts,
|
||
|
[$this->writeSelectAggrupation($select, $this->writer, 'getAllJoins', 'writeJoin', ' ')]
|
||
|
);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
* @param $writer
|
||
|
* @param string $getMethod
|
||
|
* @param string $writeMethod
|
||
|
* @param string $glue
|
||
|
* @param string $prepend
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function writeSelectAggrupation(Select $select, $writer, $getMethod, $writeMethod, $glue, $prepend = '')
|
||
|
{
|
||
|
$str = '';
|
||
|
$joins = $select->$getMethod();
|
||
|
|
||
|
if (!empty($joins)) {
|
||
|
\array_walk(
|
||
|
$joins,
|
||
|
function (&$join) use ($writer, $writeMethod) {
|
||
|
$join = $writer->$writeMethod($join);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
$str = $prepend.implode($glue, $joins);
|
||
|
}
|
||
|
|
||
|
return $str;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
* @param array $parts
|
||
|
*
|
||
|
* @return $this
|
||
|
*/
|
||
|
public function writeSelectWhere(Select $select, array &$parts)
|
||
|
{
|
||
|
$str = '';
|
||
|
$wheres = $this->writeSelectWheres($select->getAllWheres());
|
||
|
$wheres = \array_filter($wheres);
|
||
|
|
||
|
if (\count($wheres) > 0) {
|
||
|
$str = 'WHERE ';
|
||
|
$separator = ' '.$this->writer->writeConjunction($select->getWhereOperator()).' ';
|
||
|
|
||
|
$str .= \implode($separator, $wheres);
|
||
|
}
|
||
|
|
||
|
$parts = \array_merge($parts, [$str]);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param array $wheres
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function writeSelectWheres(array $wheres)
|
||
|
{
|
||
|
$whereWriter = WriterFactory::createWhereWriter($this->writer, $this->placeholderWriter);
|
||
|
|
||
|
\array_walk(
|
||
|
$wheres,
|
||
|
function (&$where) use (&$whereWriter) {
|
||
|
|
||
|
$where = $whereWriter->writeWhere($where);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
return $wheres;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
* @param array $parts
|
||
|
*
|
||
|
* @return $this
|
||
|
*/
|
||
|
public function writeSelectGroupBy(Select $select, array &$parts)
|
||
|
{
|
||
|
$groupBy = $this->writeSelectAggrupation(
|
||
|
$select,
|
||
|
$this->columnWriter,
|
||
|
'getGroupBy',
|
||
|
'writeColumn',
|
||
|
', ',
|
||
|
'GROUP BY '
|
||
|
);
|
||
|
|
||
|
$parts = \array_merge($parts, [$groupBy]);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
* @param array $parts
|
||
|
*
|
||
|
* @return $this
|
||
|
*/
|
||
|
public function writeSelectHaving(Select $select, array &$parts)
|
||
|
{
|
||
|
$str = '';
|
||
|
$havingArray = $select->getAllHavings();
|
||
|
|
||
|
if (\count($havingArray) > 0) {
|
||
|
$placeholder = $this->placeholderWriter;
|
||
|
$writer = $this->writer;
|
||
|
|
||
|
$str = 'HAVING ';
|
||
|
$separator = ' '.$select->getHavingOperator().' ';
|
||
|
$havingArray = $this->getHavingConditions($havingArray, $select, $writer, $placeholder);
|
||
|
|
||
|
$str .= \implode($separator, $havingArray);
|
||
|
}
|
||
|
|
||
|
$parts = \array_merge($parts, [$str]);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param array $havingArray
|
||
|
* @param Select $select
|
||
|
* @param BuilderInterface $writer
|
||
|
* @param PlaceholderWriter $placeholder
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
protected function getHavingConditions(
|
||
|
array &$havingArray,
|
||
|
Select $select,
|
||
|
BuilderInterface $writer,
|
||
|
PlaceholderWriter $placeholder
|
||
|
) {
|
||
|
\array_walk(
|
||
|
$havingArray,
|
||
|
function (&$having) use ($select, $writer, $placeholder) {
|
||
|
|
||
|
$whereWriter = WriterFactory::createWhereWriter($writer, $placeholder);
|
||
|
$clauses = $whereWriter->writeWhereClauses($having);
|
||
|
$having = \implode($this->writer->writeConjunction($select->getHavingOperator()), $clauses);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
return $havingArray;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
* @param array $parts
|
||
|
*
|
||
|
* @return $this
|
||
|
*/
|
||
|
protected function writeSelectOrderBy(Select $select, array &$parts)
|
||
|
{
|
||
|
$str = '';
|
||
|
if (\count($select->getAllOrderBy())) {
|
||
|
$orderByArray = $select->getAllOrderBy();
|
||
|
\array_walk(
|
||
|
$orderByArray,
|
||
|
function (&$orderBy) {
|
||
|
$orderBy = $this->writeOrderBy($orderBy);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
$str = 'ORDER BY ';
|
||
|
$str .= \implode(', ', $orderByArray);
|
||
|
}
|
||
|
|
||
|
$parts = \array_merge($parts, [$str]);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param OrderBy $orderBy
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function writeOrderBy(OrderBy $orderBy)
|
||
|
{
|
||
|
$column = $this->columnWriter->writeColumn($orderBy->getColumn());
|
||
|
|
||
|
return $column.' '.$orderBy->getDirection();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
* @param array $parts
|
||
|
*
|
||
|
* @return $this
|
||
|
*/
|
||
|
protected function writeSelectLimit(Select $select, array &$parts)
|
||
|
{
|
||
|
$mask = $this->getStartingLimit($select).$this->getLimitCount($select);
|
||
|
|
||
|
$limit = '';
|
||
|
|
||
|
if ($mask !== '00') {
|
||
|
$start = $this->placeholderWriter->add($select->getLimitStart());
|
||
|
$count = $this->placeholderWriter->add($select->getLimitCount());
|
||
|
|
||
|
$limit = "LIMIT {$start}, {$count}";
|
||
|
}
|
||
|
|
||
|
$parts = \array_merge($parts, [$limit]);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function getStartingLimit(Select $select)
|
||
|
{
|
||
|
return (null === $select->getLimitStart() || 0 == $select->getLimitStart()) ? '0' : '1';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Select $select
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function getLimitCount(Select $select)
|
||
|
{
|
||
|
return (null === $select->getLimitCount()) ? '0' : '1';
|
||
|
}
|
||
|
}
|