array($parameters)). * The field name is stored as the key * * E.g. * * $assignments['ID'] = array('?' => array(1)); * * This allows for complex, parameterised updates, or explict field values set * without any prameters * * @var array */ protected $assignments = array(); /** * Instantiate a new SQLAssignmentRow object with the given values * * @param array $values */ function __construct(array $values = array()) { $this->setAssignments($values); } /** * Given a key / value pair, extract the predicate and any potential paramaters * in a format suitable for storing internally as a list of paramaterised conditions. * * @param mixed $value Either a literal field value, or an array with * placeholder => parameter(s) as a pair * @return array A single item array in the format array($sql => array($parameters)) */ protected function parseAssignment($value) { // Assume string values (or values saved as customised array objects) // represent simple assignment if(!is_array($value) || isset($value['type'])) { return array('?' => array($value)); } // If given as array then extract and check both the SQL as well as the parameter(s) // Note that there could be multiple parameters, e.g. // array('MAX(?,?)' => array(1,2)) although the container should // have a single item if(count($value) == 1) { foreach($value as $sql => $parameters) { if(!is_string($sql)) continue; if(!is_array($parameters)) $parameters = array($parameters); // @todo Some input sanitisation checking the key contains the // correct number of ? placeholders as the number of parameters return array($sql => $parameters); } } user_error("Nested field assignments should be given as a single parameterised item array in " . "array('?' => array('value')) format)", E_USER_ERROR); } /** * Given a list of assignments in any user-acceptible format, normalise the * value to a common array('SQL' => array(parameters)) format * * @param array $predicates List of assignments. * The key of this array should be the field name, and the value the assigned * literal value, or an array with parameterised information. * @return array List of normalised assignments */ protected function normaliseAssignments(array $assignments) { $normalised = array(); foreach($assignments as $field => $value) { $normalised[$field] = $this->parseAssignment($value); } return $normalised; } /** * Adds assignments for a list of several fields * * Note that field values must not be escaped, as these will be internally * parameterised by the database engine. * * * * // Basic assignments * $query->addAssignments(array( * '"Object"."Title"' => 'Bob', * '"Object"."Description"' => 'Bob was here' * )) * * // Parameterised assignments * $query->addAssignments(array( * '"Object"."Title"' => array('?' => 'Bob')), * '"Object"."Description"' => array('?' => null)) * )) * * // Complex parameters * $query->addAssignments(array( * '"Object"."Score"' => array('MAX(?,?)' => array(1, 3)) * )); * * // Assigment of literal SQL for a field. The empty array is * // important to denote the zero-number paramater list * $query->addAssignments(array( * '"Object"."Score"' => array('NOW()' => array()) * )); * * * * @param array $assignments The list of fields to assign * @return self The self reference to this row */ public function addAssignments(array $assignments) { $assignments = $this->normaliseAssignments($assignments); $this->assignments = array_merge($this->assignments, $assignments); return $this; } /** * Sets the list of assignments to the given list * * @see SQLWriteExpression::addAssignments() for syntax examples * * @param array $assignments * @return self The self reference to this row */ public function setAssignments(array $assignments) { return $this->clear()->addAssignments($assignments); } /** * Retrieves the list of assignments in parameterised format * * @return array List of assigments. The key of this array will be the * column to assign, and the value a parameterised array in the format * array('SQL' => array(parameters)); */ public function getAssignments() { return $this->assignments; } /** * Set the value for a single field * * E.g. * * * // Literal assignment * $query->assign('"Object"."Description"', 'lorum ipsum'); * * // Single parameter * $query->assign('"Object"."Title"', array('?' => 'Bob')); * * // Complex parameters * $query->assign('"Object"."Score"', array('MAX(?,?)' => array(1, 3)); * * * @param string $field The field name to update * @param mixed $value The value to assign to this field. This could be an * array containing a parameterised SQL query of any number of parameters, * or a single literal value. * @return self The self reference to this row */ public function assign($field, $value) { return $this->addAssignments(array($field => $value)); } /** * Assigns a value to a field using the literal SQL expression, rather than * a value to be escaped * * @param string $field The field name to update * @param string $sql The SQL to use for this update. E.g. "NOW()" * @return self The self reference to this row */ public function assignSQL($field, $sql) { return $this->assign($field, array($sql => array())); } /** * Determine if this assignment is empty * * @return boolean Flag indicating that this assignment is empty */ public function isEmpty() { return empty($this->assignments); } /** * Retrieves the list of columns updated * * @return array */ public function getColumns() { return array_keys($this->assignments); } /** * Clears all assignment values * * @return self The self reference to this row */ public function clear() { $this->assignments = array(); return $this; } }