PHPixie/Database

View on GitHub
src/PHPixie/Database/Driver/Mongo/Parser/Operator.php

Summary

Maintainability
A
3 hrs
Test Coverage
<?php

namespace PHPixie\Database\Driver\Mongo\Parser;

class Operator extends \PHPixie\Database\Parser\Operator
{
    protected $operators = array(
        'generic' => array('<','<=','=','!=','ne', '>=','>','exists','type','mod','where','all','elemMatch','size' ),
        'between' => array('between', 'not between'),
        'in'      => array('in', 'nin', 'not in'),
        'regex'   => array('regex', 'not regex')
    );

    protected $operatorMap = array(
        '<'      => 'lt',
        '<='     => 'lte',
        '!='     => 'ne',
        '>='     => 'gte',
        '>'      => 'gt'
    );

    protected $negationMap = array(
        'lt'  => 'gte',
        'lte' => 'gt',
        '='   => 'ne',
        'gt'  => 'lte',
        'gte' => 'lt',
        'ne'  => '=',
        'in'  => 'nin',
        'nin' => 'in'
    );
    
    protected $allowedIdOperators = array('<','<=','=','!=','ne', '>=','>', 'in', 'nin', 'not in', 'between', 'not between');
    
    public function parse($condition, $convertMongoId = true)
    {
        $field = $condition->field();
        $operator = $condition->operator();
        $method = $this->getMethodName($operator);
        
        if($convertMongoId && $field === '_id') {

            if(!in_array($operator, $this->allowedIdOperators, true)) {
                throw new \PHPixie\Database\Exception\Parser("The '{$operator}' operator is not supported for _id field");
            }
            
            return $this->$method(
                $field,
                $operator,
                $condition->values(),
                $condition->isNegated(),
                true
            );
        }
        
        return $this->$method(
            $field,
            $operator,
            $condition->values(),
            $condition->isNegated()
        );
    }
    
    protected function parseRegex($field, $operator, $value, $negated)
    {
        if (count($value)!==1 && !is_string($value[0]))
            throw new \PHPixie\Database\Exception\Parser("The '$operator' operator requires a single string parameter to be passed");

        $value[0] = new \MongoDB\BSON\Regex($value[0], '');

        if ($operator == 'not regex') {
            $negated = !$negated;
            $operator = 'regex';
        }

        return $this->parseGeneric($field, $operator, $value, $negated);
    }

    protected function parseIn($field, $operator, $value, $negated, $convertMongoId = false)
    {
        if (count($value)!==1 && !is_array($value[0]))
            throw new \PHPixie\Database\Exception\Parser("The '$operator' operator requires a single array parameter to be passed");
        
        if($convertMongoId) {
            foreach($value[0] as $key => $id) {
                $value[0][$key] = new \MongoDB\BSON\ObjectID($id);
            }
        }
        
        if ($operator == 'not in')
            $operator = 'nin';

        return $this->parseGeneric($field, $operator, $value, $negated);
    }

    protected function parseGeneric($field, $operator, $value, $negated, $convertMongoId = false)
    {
        if (!is_array($value) || count($value) !== 1)
            throw new \PHPixie\Database\Exception\Parser("The '$operator' operator requires a single array parameter to be passed");
        
        if(isset($this->operatorMap[$operator]))
            $operator = $this->operatorMap[$operator];
        if ($negated && isset($this->negationMap[$operator])) {
            $operator = $this->negationMap[$operator];
            $negated = false;
        }

        $value = $value[0];
        
        if($convertMongoId) {
            $value = new \MongoDB\BSON\ObjectID($value);
        }

        if ($operator === '=') {
            $condition = $value;
        } else {
            $condition =  array(('$'.$operator) => $value);
            if ($negated)
                $condition = array('$not' => $condition);
        }

        return array($field => $condition);
    }

    protected function parseBetween($field, $operator, $range, $negated, $convertMongoId = false)
    {
        if (!is_array($range) || count($range) !== 2)
            throw new \PHPixie\Database\Exception\Parser("The '$operator' operator requires two parameters to be passed");
        if($operator === 'not between')
            $negated = !$negated;
        
        if($convertMongoId) {
            foreach($range as $key => $id) {
                $range[$key] = new \MongoDB\BSON\ObjectID($id);
            }
        }
        
        $left  = !$negated ? '$gte' : '$lt';
        $right = !$negated ? '$lte' : '$gt';

        return array(
            $field => array(
                    $left  => $range[0],
                    $right => $range[1]
                )
            );
    }

}