From ffecc0bccfc1c27ae5e3784c1430f6e5077a161e Mon Sep 17 00:00:00 2001 From: Dave Long <dave@longwaveconsulting.com> Date: Mon, 7 Oct 2024 12:45:42 +0100 Subject: [PATCH] Issue #2005626 by sukr_s, gold, jhedstrom, neelam_wadhwani, neslee canil pinto, jweowu, Mixologic, quietone, daffie, smustgrave, longwave, mondrake: Implement \Drupal\Core\Database\Query\Update::arguments (cherry picked from commit ea261a9d1a58b736c08adf51f0c1306962acc396) --- .../lib/Drupal/Core/Database/Query/Update.php | 68 +++++++++++++------ .../KernelTests/Core/Database/UpdateTest.php | 26 +++++++ 2 files changed, 73 insertions(+), 21 deletions(-) diff --git a/core/lib/Drupal/Core/Database/Query/Update.php b/core/lib/Drupal/Core/Database/Query/Update.php index b10514c5b21b..6d8b924e19ed 100644 --- a/core/lib/Drupal/Core/Database/Query/Update.php +++ b/core/lib/Drupal/Core/Database/Query/Update.php @@ -120,27 +120,9 @@ public function expression($field, $expression, ?array $arguments = NULL) { * actually didn't have to be updated because the values didn't change. */ public function execute() { - // Expressions take priority over literal fields, so we process those first - // and remove any literal fields that conflict. - $fields = $this->fields; - $update_values = []; - foreach ($this->expressionFields as $field => $data) { - if (!empty($data['arguments'])) { - $update_values += $data['arguments']; - } - if ($data['expression'] instanceof SelectInterface) { - $data['expression']->compile($this->connection, $this); - $update_values += $data['expression']->arguments(); - } - unset($fields[$field]); - } - // Because we filter $fields the same way here and in __toString(), the - // placeholders will all match up properly. - $max_placeholder = 0; - foreach ($fields as $value) { - $update_values[':db_update_placeholder_' . ($max_placeholder++)] = $value; - } + [$args, $update_values] = $this->getQueryArguments(); + $update_values += $args; if (count($this->condition)) { $this->condition->compile($this->connection, $this); @@ -182,8 +164,10 @@ public function __toString() { } $max_placeholder = 0; + [$args] = $this->getQueryArguments(); + $placeholders = array_keys($args); foreach ($fields as $field => $value) { - $update_fields[] = $this->connection->escapeField($field) . '=:db_update_placeholder_' . ($max_placeholder++); + $update_fields[] = $this->connection->escapeField($field) . '=' . $placeholders[$max_placeholder++]; } $query = $comments . 'UPDATE {' . $this->connection->escapeTable($this->table) . '} SET ' . implode(', ', $update_fields); @@ -197,4 +181,46 @@ public function __toString() { return $query; } + /** + * {@inheritdoc} + */ + public function arguments() { + [$args] = $this->getQueryArguments(); + return $this->condition->arguments() + $args; + } + + /** + * Returns the query arguments with placeholders mapped to their values. + * + * @return array + * An array containing arguments and update values. + * Both arguments and update values are associative array where the keys + * are the placeholder names and the values are the placeholder values. + */ + protected function getQueryArguments(): array { + // Expressions take priority over literal fields, so we process those first + // and remove any literal fields that conflict. + $fields = $this->fields; + $update_values = []; + foreach ($this->expressionFields as $field => $data) { + if (!empty($data['arguments'])) { + $update_values += $data['arguments']; + } + if ($data['expression'] instanceof SelectInterface) { + $data['expression']->compile($this->connection, $this); + $update_values += $data['expression']->arguments(); + } + unset($fields[$field]); + } + + // Because we filter $fields the same way here and in __toString(), the + // placeholders will all match up properly. + $max_placeholder = 0; + $args = []; + foreach ($fields as $value) { + $args[':db_update_placeholder_' . ($max_placeholder++)] = $value; + } + return [$args, $update_values]; + } + } diff --git a/core/tests/Drupal/KernelTests/Core/Database/UpdateTest.php b/core/tests/Drupal/KernelTests/Core/Database/UpdateTest.php index 260237c06b3c..52d74dbb02d4 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/UpdateTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/UpdateTest.php @@ -172,4 +172,30 @@ public function testUpdateValueInSerial(): void { ->execute(); } + /** + * Tests the Update::__toString() method. + */ + public function testToString(): void { + // Prepare query for testing. + $query = $this->connection->update('test') + ->fields(['a' => 27, 'b' => 42]) + ->condition('c', [1, 2], 'IN'); + + // Confirm placeholders are present. + $query_string = (string) $query; + $this->assertStringContainsString(':db_update_placeholder_0', $query_string); + $this->assertStringContainsString(':db_update_placeholder_1', $query_string); + $this->assertStringContainsString(':db_condition_placeholder_0', $query_string); + $this->assertStringContainsString(':db_condition_placeholder_1', $query_string); + + // Test arguments. + $expected = [ + ':db_update_placeholder_0' => 27, + ':db_update_placeholder_1' => 42, + ':db_condition_placeholder_0' => 1, + ':db_condition_placeholder_1' => 2, + ]; + $this->assertEquals($expected, $query->arguments()); + } + } -- GitLab