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.
		
		
		
		
		
			
		
			
				
					
					
						
							631 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
	
	
							631 lines
						
					
					
						
							12 KiB
						
					
					
				<?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\Syntax;
 | 
						|
 | 
						|
use Phacil\Framework\MagiQL\Manipulation\QueryException;
 | 
						|
use Phacil\Framework\MagiQL\Manipulation\QueryFactory;
 | 
						|
use Phacil\Framework\MagiQL\Api\QueryInterface;
 | 
						|
use Phacil\Framework\MagiQL\Api\WhereInterface;
 | 
						|
use Phacil\Framework\MagiQL\Manipulation\Select;
 | 
						|
 | 
						|
/**
 | 
						|
 * Class Where.
 | 
						|
 */
 | 
						|
class Where implements WhereInterface
 | 
						|
{
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $comparisons = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $betweens = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $isNull = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $isNotNull = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $booleans = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $match = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $ins = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $notIns = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $subWheres = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var string
 | 
						|
     */
 | 
						|
    protected $conjunction = WhereInterface::CONJUNCTION_AND;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var QueryInterface
 | 
						|
     */
 | 
						|
    protected $query;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var Table
 | 
						|
     */
 | 
						|
    protected $table;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $exists = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $notExists = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $notBetweens = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param QueryInterface $query
 | 
						|
     */
 | 
						|
    public function __construct(QueryInterface $query)
 | 
						|
    {
 | 
						|
        $this->query = $query;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Deep copy for nested references.
 | 
						|
     *
 | 
						|
     * @return mixed
 | 
						|
     */
 | 
						|
    public function __clone()
 | 
						|
    {
 | 
						|
        return \unserialize(\serialize($this));
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return bool
 | 
						|
     */
 | 
						|
    public function isEmpty()
 | 
						|
    {
 | 
						|
        $empty = \array_merge(
 | 
						|
            $this->comparisons,
 | 
						|
            $this->booleans,
 | 
						|
            $this->betweens,
 | 
						|
            $this->isNotNull,
 | 
						|
            $this->isNull,
 | 
						|
            $this->ins,
 | 
						|
            $this->notIns,
 | 
						|
            $this->subWheres,
 | 
						|
            $this->exists
 | 
						|
        );
 | 
						|
 | 
						|
        return 0 == \count($empty);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    public function getConjunction()
 | 
						|
    {
 | 
						|
        return $this->conjunction;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $operator
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     *
 | 
						|
     * @throws QueryException
 | 
						|
     */
 | 
						|
    public function conjunction($operator)
 | 
						|
    {
 | 
						|
        if (false === \in_array(
 | 
						|
                $operator,
 | 
						|
                [WhereInterface::CONJUNCTION_AND, WhereInterface::CONJUNCTION_OR, WhereInterface::CONJUNCTION_OR_NOT, WhereInterface::CONJUNCTION_AND_NOT]
 | 
						|
            )
 | 
						|
        ) {
 | 
						|
            throw new QueryException(
 | 
						|
                "Invalid conjunction specified, must be one of AND or OR, but '".$operator."' was found."
 | 
						|
            );
 | 
						|
        }
 | 
						|
        $this->conjunction = $operator;
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getSubWheres()
 | 
						|
    {
 | 
						|
        return $this->subWheres;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param $operator
 | 
						|
     *
 | 
						|
     * @return Where
 | 
						|
     */
 | 
						|
    public function subWhere($operator = 'OR')
 | 
						|
    {
 | 
						|
        /** @var Where $filter */
 | 
						|
        $filter = QueryFactory::createWhere($this->query);
 | 
						|
        $filter->conjunction($operator);
 | 
						|
        $filter->setTable($this->getTable());
 | 
						|
 | 
						|
        $this->subWheres[] = $filter;
 | 
						|
 | 
						|
        return $filter;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return Table
 | 
						|
     */
 | 
						|
    public function getTable()
 | 
						|
    {
 | 
						|
        return $this->query->getTable();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Used for subWhere query building.
 | 
						|
     *
 | 
						|
     * @param Table $table string
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function setTable($table)
 | 
						|
    {
 | 
						|
        $this->table = $table;
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * equals alias.
 | 
						|
     *
 | 
						|
     * @param     $column
 | 
						|
     * @param int $value
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function eq($column, $value)
 | 
						|
    {
 | 
						|
        return $this->equals($column, $value);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param $column
 | 
						|
     * @param $value
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function equals($column, $value)
 | 
						|
    {
 | 
						|
        return $this->compare($column, $value, WhereInterface::OPERATOR_EQUAL);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param        $column
 | 
						|
     * @param        $value
 | 
						|
     * @param string $operator
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    protected function compare($column, $value, $operator)
 | 
						|
    {
 | 
						|
        $column = $this->prepareColumn($column);
 | 
						|
 | 
						|
        $this->comparisons[] = [
 | 
						|
            'subject' => $column,
 | 
						|
            'conjunction' => $operator,
 | 
						|
            'target' => $value,
 | 
						|
        ];
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param $column
 | 
						|
     *
 | 
						|
     * @return Column|Select
 | 
						|
     */
 | 
						|
    protected function prepareColumn($column)
 | 
						|
    {
 | 
						|
        //This condition handles the "Select as a a column" special case.
 | 
						|
        //or when compare column is customized.
 | 
						|
        if ($column instanceof Select || $column instanceof Column) {
 | 
						|
            return $column;
 | 
						|
        }
 | 
						|
 | 
						|
        $newColumn = [$column];
 | 
						|
 | 
						|
        return SyntaxFactory::createColumn($newColumn, $this->getTable());
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int    $value
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function notEquals($column, $value)
 | 
						|
    {
 | 
						|
        return $this->compare($column, $value, WhereInterface::OPERATOR_NOT_EQUAL);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int    $value
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function greaterThan($column, $value)
 | 
						|
    {
 | 
						|
        return $this->compare($column, $value, WhereInterface::OPERATOR_GREATER_THAN);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int    $value
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function greaterThanOrEqual($column, $value)
 | 
						|
    {
 | 
						|
        return $this->compare($column, $value, WhereInterface::OPERATOR_GREATER_THAN_OR_EQUAL);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int    $value
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function lessThan($column, $value)
 | 
						|
    {
 | 
						|
        return $this->compare($column, $value, WhereInterface::OPERATOR_LESS_THAN);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int    $value
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function lessThanOrEqual($column, $value)
 | 
						|
    {
 | 
						|
        return $this->compare($column, $value, WhereInterface::OPERATOR_LESS_THAN_OR_EQUAL);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param        $value
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function like($column, $value)
 | 
						|
    {
 | 
						|
        return $this->compare($column, $value, WhereInterface::OPERATOR_LIKE);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int    $value
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function notLike($column, $value)
 | 
						|
    {
 | 
						|
        return $this->compare($column, $value, WhereInterface::OPERATOR_NOT_LIKE);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string[] $columns
 | 
						|
     * @param mixed[]  $values
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function match(array $columns, array $values)
 | 
						|
    {
 | 
						|
        return $this->genericMatch($columns, $values, 'natural');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string[] $columns
 | 
						|
     * @param mixed[]  $values
 | 
						|
     * @param string   $mode
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    protected function genericMatch(array &$columns, array &$values, $mode)
 | 
						|
    {
 | 
						|
        $this->match[] = [
 | 
						|
            'columns' => $columns,
 | 
						|
            'values' => $values,
 | 
						|
            'mode' => $mode,
 | 
						|
        ];
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $literal
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function asLiteral($literal)
 | 
						|
    {
 | 
						|
        $this->comparisons[] = $literal;
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string[] $columns
 | 
						|
     * @param mixed[]  $values
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function matchBoolean(array $columns, array $values)
 | 
						|
    {
 | 
						|
        return $this->genericMatch($columns, $values, 'boolean');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string[] $columns
 | 
						|
     * @param mixed[]  $values
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function matchWithQueryExpansion(array $columns, array $values)
 | 
						|
    {
 | 
						|
        return $this->genericMatch($columns, $values, 'query_expansion');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int[]  $values
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function in($column, array $values)
 | 
						|
    {
 | 
						|
        $this->ins[$column] = $values;
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int[] $values
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function notIn($column, array $values)
 | 
						|
    {
 | 
						|
        $this->notIns[$column] = $values;
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int $a
 | 
						|
     * @param int $b
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function between($column, $a, $b)
 | 
						|
    {
 | 
						|
        $column = $this->prepareColumn($column);
 | 
						|
        $this->betweens[] = ['subject' => $column, 'a' => $a, 'b' => $b];
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int $a
 | 
						|
     * @param int $b
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function notBetween($column, $a, $b)
 | 
						|
    {
 | 
						|
        $column = $this->prepareColumn($column);
 | 
						|
        $this->notBetweens[] = ['subject' => $column, 'a' => $a, 'b' => $b];
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     *
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public function isNull($column)
 | 
						|
    {
 | 
						|
        $column = $this->prepareColumn($column);
 | 
						|
        $this->isNull[] = ['subject' => $column];
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function isNotNull($column)
 | 
						|
    {
 | 
						|
        $column = $this->prepareColumn($column);
 | 
						|
        $this->isNotNull[] = ['subject' => $column];
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $column
 | 
						|
     * @param int $value
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function addBitClause($column, $value)
 | 
						|
    {
 | 
						|
        $column = $this->prepareColumn($column);
 | 
						|
        $this->booleans[] = ['subject' => $column, 'value' => $value];
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Select $select
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function exists(Select $select)
 | 
						|
    {
 | 
						|
        $this->exists[] = $select;
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getExists()
 | 
						|
    {
 | 
						|
        return $this->exists;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Select $select
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function notExists(Select $select)
 | 
						|
    {
 | 
						|
        $this->notExists[] = $select;
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getNotExists()
 | 
						|
    {
 | 
						|
        return $this->notExists;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getMatches()
 | 
						|
    {
 | 
						|
        return $this->match;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getIns()
 | 
						|
    {
 | 
						|
        return $this->ins;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getNotIns()
 | 
						|
    {
 | 
						|
        return $this->notIns;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getBetweens()
 | 
						|
    {
 | 
						|
        return $this->betweens;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getNotBetweens()
 | 
						|
    {
 | 
						|
        return $this->notBetweens;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getBooleans()
 | 
						|
    {
 | 
						|
        return $this->booleans;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getComparisons()
 | 
						|
    {
 | 
						|
        return $this->comparisons;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getNotNull()
 | 
						|
    {
 | 
						|
        return $this->isNotNull;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getNull()
 | 
						|
    {
 | 
						|
        return $this->isNull;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return QueryInterface|\Phacil\Framework\MagiQL\Manipulation\AbstractBaseQuery
 | 
						|
     */
 | 
						|
    public function end()
 | 
						|
    {
 | 
						|
       return $this->query;
 | 
						|
    }
 | 
						|
}
 | 
						|
 |