From cc41d94d0ffba99b2a167fbb680a3d4fa23c70ac Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Mon, 8 Feb 2021 15:53:53 +0000
Subject: [PATCH] Issue #3128548 by anmolgoyal74, yonailo, sokru, joelpittet,
 daffie, johnwebdev, alexpott, mradcliffe, DuneBL, catch, xjm, mondrake: Add
 optional parameters to StatementInterface::fetchObject() to be in line with
 the PDO implementation of the method fetchObject()

---
 .../Drupal/Core/Database/StatementEmpty.php   |  2 +-
 .../Core/Database/StatementInterface.php      | 15 ++++++++++++-
 .../Core/Database/StatementPrefetch.php       |  4 ++--
 .../Drupal/Core/Database/StatementWrapper.php |  4 ++--
 .../src/Functional/Database/FakeRecord.php    | 21 ++++++++++++++++++-
 .../KernelTests/Core/Database/FetchTest.php   |  3 ++-
 6 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/core/lib/Drupal/Core/Database/StatementEmpty.php b/core/lib/Drupal/Core/Database/StatementEmpty.php
index a87bca920a86..0bf78c664f26 100644
--- a/core/lib/Drupal/Core/Database/StatementEmpty.php
+++ b/core/lib/Drupal/Core/Database/StatementEmpty.php
@@ -68,7 +68,7 @@ public function fetchField($index = 0) {
   /**
    * {@inheritdoc}
    */
-  public function fetchObject() {
+  public function fetchObject(string $class_name = NULL, array $constructor_arguments = NULL) {
     return NULL;
   }
 
diff --git a/core/lib/Drupal/Core/Database/StatementInterface.php b/core/lib/Drupal/Core/Database/StatementInterface.php
index 917eb8b9bffd..90a25c50dd1f 100644
--- a/core/lib/Drupal/Core/Database/StatementInterface.php
+++ b/core/lib/Drupal/Core/Database/StatementInterface.php
@@ -127,8 +127,21 @@ public function fetchField($index = 0);
    *
    * The object will be of the class specified by StatementInterface::setFetchMode()
    * or stdClass if not specified.
+   *
+   * phpcs:disable Drupal.Commenting
+   * @todo Remove PHPCS overrides https://www.drupal.org/node/3194677.
+   *
+   * @param string|null $class_name
+   *   Name of the created class.
+   * @param array|null $constructor_arguments
+   *   Elements of this array are passed to the constructor.
+   * phpcs:enable
+   *
+   * @return mixed
+   *   The object of specified class or \stdClass if not specified. Returns
+   *   FALSE or NULL if there is no next row.
    */
-  public function fetchObject();
+  public function fetchObject(/* string $class_name = NULL, array $constructor_arguments = NULL */);
 
   /**
    * Fetches the next row and returns it as an associative array.
diff --git a/core/lib/Drupal/Core/Database/StatementPrefetch.php b/core/lib/Drupal/Core/Database/StatementPrefetch.php
index 3f6efdf3644d..5e71c0947894 100644
--- a/core/lib/Drupal/Core/Database/StatementPrefetch.php
+++ b/core/lib/Drupal/Core/Database/StatementPrefetch.php
@@ -418,7 +418,7 @@ public function fetchField($index = 0) {
   /**
    * {@inheritdoc}
    */
-  public function fetchObject($class_name = NULL, $constructor_args = []) {
+  public function fetchObject(string $class_name = NULL, array $constructor_arguments = NULL) {
     if (isset($this->currentRow)) {
       if (!isset($class_name)) {
         // Directly cast to an object to avoid a function call.
@@ -428,7 +428,7 @@ public function fetchObject($class_name = NULL, $constructor_args = []) {
         $this->fetchStyle = \PDO::FETCH_CLASS;
         $this->fetchOptions = [
           'class' => $class_name,
-          'constructor_args' => $constructor_args,
+          'constructor_args' => $constructor_arguments,
         ];
         // Grab the row in the format specified above.
         $result = $this->current();
diff --git a/core/lib/Drupal/Core/Database/StatementWrapper.php b/core/lib/Drupal/Core/Database/StatementWrapper.php
index eff40102f46b..d770964f07ce 100644
--- a/core/lib/Drupal/Core/Database/StatementWrapper.php
+++ b/core/lib/Drupal/Core/Database/StatementWrapper.php
@@ -190,9 +190,9 @@ public function fetchAssoc() {
   /**
    * {@inheritdoc}
    */
-  public function fetchObject(string $class_name = NULL) {
+  public function fetchObject(string $class_name = NULL, array $constructor_arguments = NULL) {
     if ($class_name) {
-      return $this->clientStatement->fetchObject($class_name);
+      return $this->clientStatement->fetchObject($class_name, $constructor_arguments);
     }
     return $this->clientStatement->fetchObject();
   }
diff --git a/core/modules/system/tests/src/Functional/Database/FakeRecord.php b/core/modules/system/tests/src/Functional/Database/FakeRecord.php
index aa3a5fe35b37..e14f0cf7a303 100644
--- a/core/modules/system/tests/src/Functional/Database/FakeRecord.php
+++ b/core/modules/system/tests/src/Functional/Database/FakeRecord.php
@@ -9,4 +9,23 @@
  * rather than just a stdClass or array. This class is for testing that
  * functionality. (See testQueryFetchClass() below)
  */
-class FakeRecord {}
+class FakeRecord {
+
+  /**
+   * A class variable.
+   *
+   * @var int
+   */
+  public $fakeArg;
+
+  /**
+   * Constructs a FakeRecord object with an optional constructor argument.
+   *
+   * @param int $fakeArg
+   *   A class variable.
+   */
+  public function __construct($fakeArg = 0) {
+    $this->fakeArg = $fakeArg;
+  }
+
+}
diff --git a/core/tests/Drupal/KernelTests/Core/Database/FetchTest.php b/core/tests/Drupal/KernelTests/Core/Database/FetchTest.php
index 2713e6db7cb4..bf499492d649 100644
--- a/core/tests/Drupal/KernelTests/Core/Database/FetchTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Database/FetchTest.php
@@ -88,10 +88,11 @@ public function testQueryFetchClass() {
   public function testQueryFetchObjectClass() {
     $records = 0;
     $query = $this->connection->query('SELECT [name] FROM {test} WHERE [age] = :age', [':age' => 25]);
-    while ($result = $query->fetchObject(FakeRecord::class)) {
+    while ($result = $query->fetchObject(FakeRecord::class, [1])) {
       $records += 1;
       $this->assertInstanceOf(FakeRecord::class, $result);
       $this->assertSame('John', $result->name, '25 year old is John.');
+      $this->assertSame(1, $result->fakeArg, 'The record has received an argument through its constructor.');
     }
     $this->assertSame(1, $records, 'There is only one record.');
   }
-- 
GitLab