<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Db\Sql\Predicate;

use 
Zend\Db\Sql\Exception;

class 
Operator implements PredicateInterface
{
    const 
OPERATOR_EQUAL_TO                  '=';
    const 
OP_EQ                              '=';

    const 
OPERATOR_NOT_EQUAL_TO              '!=';
    const 
OP_NE                              '!=';

    const 
OPERATOR_LESS_THAN                 '<';
    const 
OP_LT                              '<';

    const 
OPERATOR_LESS_THAN_OR_EQUAL_TO     '<=';
    const 
OP_LTE                             '<=';

    const 
OPERATOR_GREATER_THAN              '>';
    const 
OP_GT                              '>';

    const 
OPERATOR_GREATER_THAN_OR_EQUAL_TO  '>=';
    const 
OP_GTE                             '>=';

    protected 
$allowedTypes  = array(
        
self::TYPE_IDENTIFIER,
        
self::TYPE_VALUE,
    );

    protected 
$left          null;
    protected 
$leftType      self::TYPE_IDENTIFIER;
    protected 
$operator      self::OPERATOR_EQUAL_TO;
    protected 
$right         null;
    protected 
$rightType     self::TYPE_VALUE;

    
/**
     * Constructor
     *
     * @param  int|float|bool|string $left
     * @param  string $operator
     * @param  int|float|bool|string $right
     * @param  string $leftType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_IDENTIFIER {@see allowedTypes}
     * @param  string $rightType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_VALUE {@see allowedTypes}
     */
    
public function __construct($left null$operator self::OPERATOR_EQUAL_TO$right null$leftType self::TYPE_IDENTIFIER$rightType self::TYPE_VALUE)
    {
        if (
$left !== null) {
            
$this->setLeft($left);
        }

        if (
$operator !== self::OPERATOR_EQUAL_TO) {
            
$this->setOperator($operator);
        }

        if (
$right !== null) {
            
$this->setRight($right);
        }

        if (
$leftType !== self::TYPE_IDENTIFIER) {
            
$this->setLeftType($leftType);
        }

        if (
$rightType !== self::TYPE_VALUE) {
            
$this->setRightType($rightType);
        }
    }

    
/**
     * Set left side of operator
     *
     * @param  int|float|bool|string $left
     * @return Operator
     */
    
public function setLeft($left)
    {
        
$this->left $left;
        return 
$this;
    }

    
/**
     * Get left side of operator
     *
     * @return int|float|bool|string
     */
    
public function getLeft()
    {
        return 
$this->left;
    }

    
/**
     * Set parameter type for left side of operator
     *
     * @param  string $type TYPE_IDENTIFIER or TYPE_VALUE {@see allowedTypes}
     * @throws Exception\InvalidArgumentException
     * @return Operator
     */
    
public function setLeftType($type)
    {
        if (!
in_array($type$this->allowedTypes)) {
            throw new 
Exception\InvalidArgumentException(sprintf(
                
'Invalid type "%s" provided; must be of type "%s" or "%s"',
                
$type,
                
__CLASS__ '::TYPE_IDENTIFIER',
                
__CLASS__ '::TYPE_VALUE'
            
));
        }
        
$this->leftType $type;
        return 
$this;
    }

    
/**
     * Get parameter type on left side of operator
     *
     * @return string
     */
    
public function getLeftType()
    {
        return 
$this->leftType;
    }

    
/**
     * Set operator string
     *
     * @param  string $operator
     * @return Operator
     */
    
public function setOperator($operator)
    {
        
$this->operator $operator;
        return 
$this;
    }

    
/**
     * Get operator string
     *
     * @return string
     */
    
public function getOperator()
    {
        return 
$this->operator;
    }

    
/**
     * Set right side of operator
     *
     * @param  int|float|bool|string $value
     * @return Operator
     */
    
public function setRight($value)
    {
        
$this->right $value;
        return 
$this;
    }

    
/**
     * Get right side of operator
     *
     * @return int|float|bool|string
     */
    
public function getRight()
    {
        return 
$this->right;
    }

    
/**
     * Set parameter type for right side of operator
     *
     * @param  string $type TYPE_IDENTIFIER or TYPE_VALUE {@see allowedTypes}
     * @throws Exception\InvalidArgumentException
     * @return Operator
     */
    
public function setRightType($type)
    {
        if (!
in_array($type$this->allowedTypes)) {
            throw new 
Exception\InvalidArgumentException(sprintf(
                
'Invalid type "%s" provided; must be of type "%s" or "%s"',
                
$type,
                
__CLASS__ '::TYPE_IDENTIFIER',
                
__CLASS__ '::TYPE_VALUE'
            
));
        }
        
$this->rightType $type;
        return 
$this;
    }

    
/**
     * Get parameter type on right side of operator
     *
     * @return string
     */
    
public function getRightType()
    {
        return 
$this->rightType;
    }

    
/**
     * Get predicate parts for where statement
     *
     * @return array
     */
    
public function getExpressionData()
    {
        return array(array(
            
'%s ' $this->operator ' %s',
            array(
$this->left$this->right),
            array(
$this->leftType$this->rightType)
        ));
    }
}