face-orm/face

View on GitHub
lib/Face/Sql/Query/SelectBuilder/LimitOnSubQueryCompiler.php

Summary

Maintainability
B
5 hrs
Test Coverage
<?php


namespace Face\Sql\Query\SelectBuilder;


use Face\Sql\Query\Clause\GroupBy;
use Face\Sql\Query\Clause\SubQuery;
use Face\Sql\Query\SelectBuilder;
use Face\Sql\Query\Clause\From;
use Face\Sql\Query\Clause\Group;
use Face\Sql\Query\Clause\Join;
use Face\Sql\Query\Clause\Limit;
use Face\Sql\Query\Clause\Offset;
use Face\Sql\Query\Clause\OrderBy;
use Face\Sql\Query\Clause\Select;
use Face\Sql\Query\Clause\Where;
use Face\Sql\Query\SelectInterface;
use Face\Sql\Query\SelectQuery;

class LimitOnSubQueryCompiler {

    /**
     * @var SelectBuilder
     */
    protected $selectBuilder;

    function __construct(SelectInterface $selectBuilder)
    {
        $this->selectBuilder = $selectBuilder;
    }


    public function compile(){

        /* @var $facesToSelect QueryFace[] */
        $facesToSelect["this"] = $this->selectBuilder->getBaseQueryFace();
        $facesToSelect = array_merge($facesToSelect, $this->selectBuilder->getJoins());


        // SELECT
        // columns
        $columns = [];
        $primariesColumns = [];
        foreach($facesToSelect as $queryFace){
            foreach($queryFace->getColumnsReal() as $column){
                $columns[] = $column;
            }
        }

        foreach($facesToSelect["this"]->getColumnsReal() as $column){
            $columns[] = $column;

            if($column instanceof Select\Column\ElementColumn && $column->getEntityFaceElement()->isPrimary()){
                $primariesColumns[] = $column;
            }
        }

        $selectClause = new Select($columns);


        // SELECT id for subquery
        $selectClauseSubquery = new Select($primariesColumns);


        // FROM
        $fromClause = new From($this->selectBuilder->getBaseFace());


        $joinGroup = new Group();
        // JOINs
        foreach ($this->selectBuilder->getJoins() as $joinQueryFace) {
            $join = new Join($this->selectBuilder->getBaseFace(), $joinQueryFace);
            $joinGroup->addItem($join);
        }


        // SOFT JOINs
        if (is_array($this->selectBuilder->getSoftThroughJoin())) {
            foreach ($this->selectBuilder->getSoftThroughJoin() as $path => $joinQueryFace) {
                if (!$this->selectBuilder->isJoined($path)) {
                    $join = new Join($this->selectBuilder->getBaseFace(), $joinQueryFace);
                    $joinGroup->addItem($join);
                }
            }
        }

        // WHERE SUBQUERY
        $where = $this->selectBuilder->getWhere();
        if ($where) {
            $whereSubquery = $where;
        }else{
            $whereSubquery = null;
        }


        // GROUP BY SUBQUERY
        $groupBySubquery = new GroupBy($primariesColumns);


        // ORDER
        $orders = $this->selectBuilder->getOrderBy();
        $orderByClause = new OrderBy();
        foreach($orders as $order){
            $orderByClause->addItem($order);
        }

        // LIMIT
        $limit = new Limit($this->selectBuilder->getLimit());

        // OFFSET
        $offset = new Offset($this->selectBuilder->getOffset());

        // BUILD SUBQUERY
        $subqueryGroup = new Group();
        $subqueryGroup->addItem($selectClauseSubquery);
        $subqueryGroup->addItem($fromClause);
        $subqueryGroup->addItem($joinGroup);
        if($whereSubquery) {
            $subqueryGroup->addItem($whereSubquery);
        }
        $subqueryGroup->addItem($groupBySubquery);
        $subqueryGroup->addItem($orderByClause);
        $subqueryGroup->addItem($limit);
        $subqueryGroup->addItem($offset);








        // WHERE QUERY
        $whereIn = new Where\WhereInSubquery($subqueryGroup, $primariesColumns);
        $whereQuery = new Where($whereIn);

        // BUILDER QUERY
        $queryGroup = new Group();
        $queryGroup->addItem($selectClause);
        $queryGroup->addItem($fromClause);
        $queryGroup->addItem($joinGroup);
        if($this->selectBuilder->getGroupBy()){
            $queryGroup->addItem($this->selectBuilder->getGroupBy());
        }
        $queryGroup->addItem($whereQuery);
        $queryGroup->addItem($orderByClause);



        $sqlQ = $queryGroup->getSqlString($this->selectBuilder);

        return $sqlQ;
    }


}