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; } }