[$parameters]]. * The field name is stored as the key * * E.g. * * $assignments['ID'] = ['?' => [1]]; * * This allows for complex, parameterised updates, or explict field values set * without any prameters * * @var array */ protected $assignments = []; /** * Instantiate a new SQLAssignmentRow object with the given values * * @param array $values */ function __construct(array $values = []) { $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 [$sql => [$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 ['?' => [$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. // ['MAX(?,?)' => [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 = [$parameters]; } // @todo Some input sanitisation checking the key contains the // correct number of ? placeholders as the number of parameters return [$sql => $parameters]; } } throw new InvalidArgumentException( "Nested field assignments should be given as a single parameterised item array in " . "['?' => ['value']] format)" ); } /** * Given a list of assignments in any user-acceptible format, normalise the * value to a common ['SQL' => [parameters]] format * * @param array $assignments 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 = []; 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([ * '"Object"."Title"' => 'Bob', * '"Object"."Description"' => 'Bob was here' * ]) * * // Parameterised assignments * $query->addAssignments([ * '"Object"."Title"' => ['?' => 'Bob'], * '"Object"."Description"' => ['?' => null] * ]) * * // Complex parameters * $query->addAssignments([ * '"Object"."Score"' => ['MAX(?,?)' => [1, 3]] * ]); * * // Assignment of literal SQL for a field. The empty array is * // important to denote the zero-number paramater list * $query->addAssignments([ * '"Object"."Score"' => ['NOW()' => []] * ]); * * * * @param array $assignments The list of fields to assign * @return $this 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 $this 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 * ['SQL' => [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"', ['?' => 'Bob']); * * // Complex parameters * $query->assign('"Object"."Score"', ['MAX(?,?)' => [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 $this The self reference to this row */ public function assign($field, $value) { return $this->addAssignments([$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 $this The self reference to this row */ public function assignSQL($field, $sql) { return $this->assign($field, [$sql => []]); } /** * 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 $this The self reference to this row */ public function clear() { $this->assignments = []; return $this; } }