PHPixie/Database

View on GitHub
src/PHPixie/Database/Type/SQL/Parser/Operator.php

Summary

Maintainability
A
2 hrs
Test Coverage
<?php

namespace PHPixie\Database\Type\SQL\Parser;

abstract class Operator extends \PHPixie\Database\Parser\Operator
{
    /**
     * @var \PHPixie\Database
     */
    protected $database;

    /**
     * @var \PHPixie\Database\Type\SQL\Parser\Fragment
     */
    protected $fragmentParser;

    protected $operators = array(
        'compare' => array('<', '<=', '=', '<>', '!=', '>=', '>', '<*', '<=*', '=*', '<>*', '!=*', '>=*', '>*'),
        'pattern' => array('like', 'ilike', 'not like', 'regexp', 'not regexp'),
        'in'      => array('in', 'not in'),
        'between' => array('between', 'not between'),
    );

    public function __construct($database, $fragmentParser)
    {
        $this->database = $database;
        $this->fragmentParser = $fragmentParser;
        parent::__construct();
    }

    protected function prefix($field, $operator)
    {
        $expr = $this->database->sqlExpression();
        $this->fragmentParser->appendColumn($field, $expr);
        $expr->sql .= ' '.strtoupper($operator).' ';

        return $expr;
    }

    protected function singleValue($values, $operator)
    {
        if($values === null || count($values) !== 1)
            throw new \PHPixie\Database\Exception\Parser(strtoupper($operator)." operator requires a single parameter");

        return $values[0];
    }

    protected function parseCompare($field, $operator, $values)
    {
        $isColumn =  false;

        if (substr($operator, -1, 1) === '*') {
            $operator = substr($operator, 0, -1);
            $isColumn = true;
        }

        $value = $this->singleValue($values, $operator);

        if ($operator === '!=')
            $operator = '<>';

        if ($value === null) {
            if ($isColumn)
                throw new \PHPixie\Database\Exception\Parser("A column comparison operator '{$operator}*' was given a NULL instead of column");

            if ($operator === '=') {
                $operator = 'is';
            } elseif ($operator === '<>') {
                $operator = 'is not';
            }
        }

        $expr = $this->prefix($field, $operator);

        if ($value === null) {
            $expr->sql.= "NULL";
        } elseif ($isColumn) {
            $this->fragmentParser->appendColumn($value, $expr);
        } else {
            $this->fragmentParser->appendValue($value, $expr);
        }

        return $expr;
    }

    protected function parseBetween($field, $operator, $range)
    {
        if (count($range) !== 2)
            throw new \PHPixie\Database\Exception\Parser(strtoupper($operator)." operator parameter requires two parameters");

        $expr = $this->prefix($field, $operator);
        $this->fragmentParser->appendValue($range[0], $expr);
        $expr->sql.= " AND ";
        $this->fragmentParser->appendValue($range[1], $expr);

        return $expr;
    }

    protected function parsePattern($field, $operator, $values)
    {
        $value = $this->singleValue($values, $operator);

        $expr = $this->prefix($field, $operator);
        $this->fragmentParser->appendValue($value, $expr);

        return $expr;
    }

    protected function parseIn($field, $operator, $values)
    {
        $value = $this->singleValue($values, $operator);
        
        if(is_array($value) && count($value) === 0) {
            $condition = $operator === 'in' ? 'FALSE' : 'TRUE';
            return $this->database->sqlExpression($condition);
        }
        
        $expr = $this->prefix($field, $operator);
        if (is_array($value)) {
            $listSql = str_pad('', count($value) * 3 - 2, '?, ');
            $expr->sql.= "($listSql)";
            $expr->params = array_merge($expr->params, $value);
        } elseif ($value instanceof \PHPixie\Database\Type\SQL\Query) {
            $subquery = $value->parse();
            $expr->sql.= "( ";
            $expr->append($subquery);
            $expr->sql.= " )";
        } elseif ($value instanceof \PHPixie\Database\Type\SQL\Expression) {
            $expr->sql.= "( ";
            $expr->append($value);
            $expr->sql.= " )";
        } else {
            throw new \PHPixie\Database\Exception\Parser(strtoupper($operator)." operator parameter must be either an array, a query or an expression");
        }

        return $expr;
    }
}