Skip to content

Commit

Permalink
Documenting and cleaning up, adding missing file
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Aug 6, 2013
1 parent 4bd9fae commit 14e36a6
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 22 deletions.
122 changes: 101 additions & 21 deletions lib/Cake/Database/Expression/Comparison.php
@@ -1,33 +1,62 @@
<?php
/**
*
* PHP Version 5.4
*
* CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The Open Group Test Suite License
* 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 2005-2013, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
* @package Cake.Test.Case.Model.Datasource.Database
* @since CakePHP(tm) v 3.0
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 3.0.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace Cake\Database\Expression;

use Cake\Database\ExpressionInterface;
use Cake\Database\ValueBinder;

/**
* A Comparisson 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`
*
*/
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 $conjuntion the operator used for comparing field and value
* @return void
*/
public function __construct($field, $value, $type, $conjuntion) {
$this->_field = $field;
$this->_value = $value;
Expand All @@ -43,18 +72,40 @@ public function __construct($field, $value, $type, $conjuntion) {
$this->_conditions[$field] = $value;
}

/**
* Sets the field name
*
* @param string $field
* @return void
*/
public function field($field) {
$this->_field = $field;
}

/**
* Sets the value
*
* @param mixed $value
* @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;
}
Expand All @@ -66,30 +117,54 @@ public function getValue() {
* @return string
*/
public function sql(ValueBinder $generator) {
$value = $this->_value;
$template = '%s %s (%s)';

if (!($this->_value instanceof ExpressionInterface)) {
$type = $this->_type;
if (strpos($this->_type, '[]') !== false) {
$value = $this->_flattenValue($generator);
} else {
$template = '%s %s %s';
$value = $this->_bindValue($generator, $value, $this->_type);
}
if ($this->_value instanceof ExpressionInterface) {
$template = '%s %s (%s)';
$value = $this->_value->sql($generator);
} else {
$value = $value->sql($generator);
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 ValueBinder $generator
* @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)';
$value = $this->_flattenValue($generator);
} else {
$template = '%s %s %s';
$value = $this->_bindValue($generator, $this->_value, $this->_type);
}
return [$template, $value];
}

/**
* Register a value in the placeholder generator and returns the generated placeholder
*
* @param ValueBinder $generator
* @param mixed $value
* @param string $type
* @return string generated placeholder
*/
protected function _bindValue($generator, $value, $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 ValueBinder $generator
* @return string
*/
protected function _flattenValue($generator) {
$parts = [];
$type = str_replace('[]', '', $this->_type);
Expand All @@ -99,6 +174,11 @@ protected function _flattenValue($generator) {
return implode(',', $parts);
}

/**
* Returns the number of expression this class represents
*
* @return integer
*/
public function count() {
return 1;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Cake/Database/Query.php
Expand Up @@ -1527,7 +1527,7 @@ public function bind($param, $value, $type) {
* default one will be returned
* @return Query|ValueBinder
*/
public function valuebinder($binder = null) {
public function valueBinder($binder = null) {
if ($binder === null) {
if ($this->_valueBinder === null) {
$this->_valueBinder = new ValueBinder;
Expand Down
102 changes: 102 additions & 0 deletions lib/Cake/Database/ValueBinder.php
@@ -0,0 +1,102 @@
<?php
/**
* PHP Version 5.4
*
* 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 CakePHP(tm) v 3.0.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace Cake\Database;

class ValueBinder {

/**
* Array containing a list of bound values to the conditions on this
* object. Each array entry is another array structure containing the actual
* bound value, its type and the placeholder it is bound to.
*
* @var array
*/
protected $_bindings = [];

/**
* A counter of the number of parameters bound in this expression object
*
* @var integer
*/
protected $_bindingsCount = 0;

/**
* Associates a query placeholder to a value and a type
*
* @param string|integer $token placeholder to be replaced with quoted version
* of $value
* @param mixed $value the value to be bound
* @param string|integer $type the mapped type name, used for casting when sending
* to database
* @return void
*/
public function bind($param, $value, $type) {
$this->_bindings[$param] = compact('value', 'type') + [
'placeholder' => is_numeric($param) ? $param : substr($param, 1)
];
}

/**
* Creates a unique placeholder name if the token provided does not start with ":"
* otherwise, it will return the same string and internally increment the number
* of placeholders generated by this object.
*
* @param string $token string from which the placeholder will be derived from,
* if it starts with a colon, then the same string is returned
* @return string to be used as a placeholder in a query expression
*/
public function placeholder($token) {
$param = $token;
$number = $this->_bindingsCount++;

if ($param[0] !== ':' || $param !== '?') {
$param = sprintf(':c%s', $number);
}

return $param;
}

/**
* Returns all values bound to this expression object at this nesting level.
* Subexpression bound values will not be returned with this function.
*
* @return array
*/
public function bindings() {
return $this->_bindings;
}

/**
* Clears any bindings taht were previously registered
*
* @return void
*/
public function reset() {
$this->_bindings = [];
$this->_bindingsCount = 0;
}

/**
* Resets the bindings count without clearing previously bound values
*
* @return void
*/
public function resetCount() {
$this->_bindingsCount = 0;
}

}

0 comments on commit 14e36a6

Please sign in to comment.