From cdd8b0522bb3cf50ccd0116dc87b2a9d46816d17 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Sun, 26 Feb 2023 12:21:20 +0000
Subject: [PATCH] Issue #3083106 by mfb, dogamboar, alexpott, smustgrave:
 Method _batch_current_set is called without include core/includes/batch.inc

---
 .../system/src/Controller/BatchController.php | 39 +++++++++++-------
 .../src/Unit/Batch/BatchControllerTest.php    | 40 +++++++++++++++++++
 2 files changed, 64 insertions(+), 15 deletions(-)
 create mode 100644 core/modules/system/tests/src/Unit/Batch/BatchControllerTest.php

diff --git a/core/modules/system/src/Controller/BatchController.php b/core/modules/system/src/Controller/BatchController.php
index 761c32a08ddd..d234a4e7e79a 100644
--- a/core/modules/system/src/Controller/BatchController.php
+++ b/core/modules/system/src/Controller/BatchController.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\system\Controller;
 
+use Drupal\Core\Batch\BatchStorageInterface;
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -13,21 +14,14 @@
  */
 class BatchController implements ContainerInjectionInterface {
 
-  /**
-   * The app root.
-   *
-   * @var string
-   */
-  protected $root;
-
   /**
    * Constructs a new BatchController.
-   *
-   * @param string $root
-   *   The app root.
    */
-  public function __construct($root) {
-    $this->root = $root;
+  public function __construct(
+    protected string $root,
+    protected BatchStorageInterface $batchStorage
+  ) {
+    require_once $this->root . '/core/includes/batch.inc';
   }
 
   /**
@@ -35,7 +29,8 @@ public function __construct($root) {
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->getParameter('app.root')
+      $container->getParameter('app.root'),
+      $container->get('batch.storage'),
     );
   }
 
@@ -51,7 +46,6 @@ public static function create(ContainerInterface $container) {
    * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
    */
   public function batchPage(Request $request) {
-    require_once $this->root . '/core/includes/batch.inc';
     $output = _batch_page($request);
 
     if ($output === FALSE) {
@@ -87,7 +81,22 @@ public function batchPage(Request $request) {
    * @return string
    *   The page title.
    */
-  public function batchPageTitle() {
+  public function batchPageTitle(Request $request) {
+    $batch = &batch_get();
+
+    if (!($request_id = $request->query->get('id'))) {
+      return '';
+    }
+
+    // Retrieve the current state of the batch.
+    if (!$batch) {
+      $batch = $this->batchStorage->load($request_id);
+    }
+
+    if (!$batch) {
+      return '';
+    }
+
     $current_set = _batch_current_set();
     return !empty($current_set['title']) ? $current_set['title'] : '';
   }
diff --git a/core/modules/system/tests/src/Unit/Batch/BatchControllerTest.php b/core/modules/system/tests/src/Unit/Batch/BatchControllerTest.php
new file mode 100644
index 000000000000..e68649fd37a6
--- /dev/null
+++ b/core/modules/system/tests/src/Unit/Batch/BatchControllerTest.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Drupal\Tests\system\Unit\Batch;
+
+use Drupal\Core\Batch\BatchStorageInterface;
+use Drupal\system\Controller\BatchController;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Tests for the batch controller class.
+ *
+ * @coversDefaultClass \Drupal\system\Controller\BatchController
+ * @runTestsInSeparateProcesses
+ * @group system
+ */
+class BatchControllerTest extends UnitTestCase {
+
+  /**
+   * Tests title callback.
+   *
+   * @covers ::batchPageTitle
+   */
+  public function testBatchPageTitle() {
+    $batch_storage = $this->createMock(BatchStorageInterface::class);
+    $controller = new BatchController($this->root, $batch_storage);
+    require_once $this->root . '/core/includes/form.inc';
+    $this->assertSame('', $controller->batchPageTitle(new Request()));
+    // Test no batch loaded from storage and batch loaded from storage cases.
+    $batch = ['sets' => [['title' => 'foobar']], 'current_set' => 0];
+    $batch_storage->method('load')->will($this->onConsecutiveCalls(FALSE, $batch));
+    $this->assertSame('', $controller->batchPageTitle(new Request(['id' => 1234])));
+    $this->assertSame('foobar', $controller->batchPageTitle(new Request(['id' => 1234])));
+    // Test batch returned by &batch_get() call.
+    $batch = &batch_get();
+    $batch['sets']['0']['title'] = 'Updated title';
+    $this->assertSame('Updated title', $controller->batchPageTitle(new Request(['id' => 1234])));
+  }
+
+}
-- 
GitLab