| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- <?php
- /**
- * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- * @link http://cakephp.org CakePHP(tm) Project
- * @since 3.0.0
- * @license http://www.opensource.org/licenses/mit-license.php MIT License
- */
- namespace Cake\Database\Expression;
- use Cake\Database\ExpressionInterface;
- use Cake\Database\ValueBinder;
- /**
- * A Comparison is a type of query expression that represents an operation
- * involving a field an operator and a value. In its most common form the
- * string representation of a comparison is `field = value`
- *
- * @internal
- */
- class Comparison extends QueryExpression {
- /**
- * The field name or expression to be used in the left hand side of the operator
- *
- * @var string
- */
- protected $_field;
- /**
- * The value to be used in the right hand side of the operation
- *
- * @var mixed
- */
- protected $_value;
- /**
- * The type to be used for casting the value to a database representation
- *
- * @var string
- */
- protected $_type;
- /**
- * Constructor
- *
- * @param string $field the field name to compare to a value
- * @param mixed $value The value to be used in comparison
- * @param string $type the type name used to cast the value
- * @param string $conjunction the operator used for comparing field and value
- */
- public function __construct($field, $value, $type, $conjunction) {
- $this->field($field);
- $this->value($value);
- $this->type($conjunction);
- if (is_string($type)) {
- $this->_type = $type;
- }
- }
- /**
- * Sets the field name
- *
- * @param string $field The field to compare with.
- * @return void
- */
- public function field($field) {
- $this->_field = $field;
- }
- /**
- * Sets the value
- *
- * @param mixed $value The value to compare
- * @return void
- */
- public function value($value) {
- $this->_value = $value;
- }
- /**
- * Returns the field name
- *
- * @return string
- */
- public function getField() {
- return $this->_field;
- }
- /**
- * Returns the value used for comparison
- *
- * @return mixed
- */
- public function getValue() {
- return $this->_value;
- }
- /**
- * Convert the expression into a SQL fragment.
- *
- * @param \Cake\Database\ValueBinder $generator Placeholder generator object
- * @return string
- */
- public function sql(ValueBinder $generator) {
- if ($this->_value instanceof ExpressionInterface) {
- $template = '%s %s (%s)';
- $value = $this->_value->sql($generator);
- } else {
- list($template, $value) = $this->_stringExpression($generator);
- }
- return sprintf($template, $this->_field, $this->_conjunction, $value);
- }
- /**
- * Returns a template and an placeholder for the value after registering it
- * with the placeholder $generator
- *
- * @param \Cake\Database\ValueBinder $generator The value binder to use.
- * @return array First position containing the template and the second a placeholder
- */
- protected function _stringExpression($generator) {
- if (strpos($this->_type, '[]') !== false) {
- $template = '%s %s (%s)';
- $type = str_replace('[]', '', $this->_type);
- $value = $this->_flattenValue($this->_value, $generator, $type);
- // To avoid SQL erros when comparing a field to a list of empty values,
- // generate a condition that will always evaluate to false
- if ($value === '') {
- return ['1 != 1', ''];
- }
- } else {
- $template = '%s %s %s';
- $value = $this->_bindValue($this->_value, $generator, $this->_type);
- }
- return [$template, $value];
- }
- /**
- * Registers a value in the placeholder generator and returns the generated placeholder
- *
- * @param mixed $value The value to bind
- * @param \Cake\Database\ValueBinder $generator The value binder to use
- * @param string $type The type of $value
- * @return string generated placeholder
- */
- protected function _bindValue($value, $generator, $type) {
- $placeholder = $generator->placeholder($this->_field);
- $generator->bind($placeholder, $value, $type);
- return $placeholder;
- }
- /**
- * Converts a traversable value into a set of placeholders generated by
- * $generator and separated by `,`
- *
- * @param array|\Traversable $value the value to flatten
- * @param \Cake\Database\ValueBinder $generator The value binder to use
- * @param string|array $type the type to cast values to
- * @return string
- */
- protected function _flattenValue($value, $generator, $type = null) {
- $parts = [];
- foreach ($value as $k => $v) {
- $parts[] = $this->_bindValue($v, $generator, $type);
- }
- return implode(',', $parts);
- }
- /**
- * Returns the number of expression this class represents
- *
- * @return int
- */
- public function count() {
- return 1;
- }
- }
|