diff --git a/core/includes/batch.inc b/core/includes/batch.inc
index 2640fc4..3a835e5 100644
--- a/core/includes/batch.inc
+++ b/core/includes/batch.inc
@@ -15,11 +15,6 @@
*/
use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Component\Utility\Timer;
-use Drupal\Component\Utility\UrlHelper;
-use Drupal\Core\Batch\Percentage;
-use Drupal\Core\Form\FormState;
-use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -69,13 +64,15 @@ function _batch_page(Request $request) {
}
}
+ /** @var \Drupal\Core\Batch\BatchProcessorInterface */
+ $batch_processor = \Drupal::service('batch.processor');
$op = $request->get('op', '');
switch ($op) {
case 'start':
case 'do_nojs':
// Display the full progress page on startup and on each additional
// non-JavaScript iteration.
- $current_set = \Drupal::service('batch.processor')->currentSet();
+ $current_set = $batch_processor->currentSet();
$build['#title'] = $current_set['title'];
$build['content'] = _batch_progress_page();
break;
@@ -87,7 +84,7 @@ function _batch_page(Request $request) {
case 'finished':
// \Drupal\Core\Batch\BatchProcessorInterface::finished() returns a
// RedirectResponse.
- return \Drupal::service('batch.processor')->finished();
+ return $batch_processor->finished();
}
return $build;
@@ -97,11 +94,13 @@ function _batch_page(Request $request) {
* Does one execution pass with JavaScript and returns progress to the browser.
*
* @see _batch_progress_page_js()
- * @see \Drupal\Core\Batch\BatchProcessorInterface::process()
+ * @see \Drupal\Core\Batch\BatchProcessorInterface::processBatchSet()
*/
function _batch_do() {
// Perform actual processing.
- list($percentage, $message, $label) = \Drupal::service('batch.processor')->process();
+ /** @var \Drupal\Core\Batch\BatchProcessorInterface */
+ $batch_processor = \Drupal::service('batch.processor');
+ list($percentage, $message, $label) = $batch_processor->process();
return new JsonResponse(array('status' => TRUE, 'percentage' => $percentage, 'message' => $message, 'label' => $label));
}
@@ -109,12 +108,14 @@ function _batch_do() {
/**
* Outputs a batch processing page.
*
- * @see \Drupal\Core\Batch\BatchProcessorInterface::process()
+ * @see \Drupal\Core\Batch\BatchProcessorInterface::processBatchSet()
*/
function _batch_progress_page() {
$batch = &batch_get();
- $current_set = \Drupal::service('batch.processor')->currentSet();
+ /** @var \Drupal\Core\Batch\BatchProcessorInterface */
+ $batch_processor = \Drupal::service('batch.processor');
+ $current_set = $batch_processor->currentSet();
$new_op = 'do_nojs';
@@ -150,7 +151,7 @@ function _batch_progress_page() {
print $fallback;
// Perform actual processing.
- list($percentage, $message, $label) = \Drupal::service('batch.processor')->process($batch);
+ list($percentage, $message, $label) = $batch_processor->process($batch);
if ($percentage == 100) {
$new_op = 'finished';
}
diff --git a/core/includes/form.inc b/core/includes/form.inc
index ba28053..8f381ae 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -795,102 +795,18 @@ function batch_set($batch_definition) {
* A redirect response if the batch is progressive. No return value otherwise.
*/
function batch_process($redirect = NULL, Url $url = NULL, $redirect_callback = NULL) {
- $batch =& batch_get();
-
- if (isset($batch)) {
- // Add process information
- $process_info = array(
- 'current_set' => 0,
- 'progressive' => TRUE,
- 'url' => isset($url) ? $url : Url::fromRoute('system.batch_page.html'),
- 'source_url' => Url::fromRouteMatch(\Drupal::routeMatch()),
- 'batch_redirect' => $redirect,
- 'theme' => \Drupal::theme()->getActiveTheme()->getName(),
- 'redirect_callback' => $redirect_callback,
- );
- $batch += $process_info;
-
- // The batch is now completely built. Allow other modules to make changes
- // to the batch so that it is easier to reuse batch processes in other
- // environments.
- \Drupal::moduleHandler()->alter('batch', $batch);
-
- // Assign an arbitrary id: don't rely on a serial column in the 'batch'
- // table, since non-progressive batches skip database storage completely.
- $batch['id'] = db_next_id();
-
- // Move operations to a job queue. Non-progressive batches will use a
- // memory-based queue.
- foreach ($batch['sets'] as $key => $batch_set) {
- _batch_populate_queue($batch, $key);
- }
-
- // Initiate processing.
- if ($batch['progressive']) {
- // Now that we have a batch id, we can generate the redirection link in
- // the generic error message.
- /** @var \Drupal\Core\Url $batch_url */
- $batch_url = $batch['url'];
- /** @var \Drupal\Core\Url $error_url */
- $error_url = clone $batch_url;
- $query_options = $error_url->getOption('query');
- $query_options['id'] = $batch['id'];
- $query_options['op'] = 'finished';
- $error_url->setOption('query', $query_options);
-
- $batch['error_message'] = t('Please continue to the error page', array('@error_url' => $error_url->toString(TRUE)->getGeneratedUrl()));
-
- // Clear the way for the redirection to the batch processing page, by
- // saving and unsetting the 'destination', if there is any.
- $request = \Drupal::request();
- if ($request->query->has('destination')) {
- $batch['destination'] = $request->query->get('destination');
- $request->query->remove('destination');
- }
-
- // Store safe strings.
- // @todo Ensure we are not storing an excessively large string list in:
- // https://www.drupal.org/node/2295823
- $batch['safe_strings'] = SafeMarkup::getAll();
-
- // Store the batch.
- \Drupal::service('batch.storage')->create($batch);
-
- // Set the batch number in the session to guarantee that it will stay alive.
- $_SESSION['batches'][$batch['id']] = TRUE;
-
- // Redirect for processing.
- $query_options = $error_url->getOption('query');
- $query_options['op'] = 'start';
- $query_options['id'] = $batch['id'];
- $batch_url->setOption('query', $query_options);
- if (($function = $batch['redirect_callback']) && function_exists($function)) {
- $function($batch_url->toString(), ['query' => $query_options]);
- }
- else {
- return new RedirectResponse($batch_url->setAbsolute()->toString(TRUE)->getGeneratedUrl());
- }
- }
- else {
- // Non-progressive execution: bypass the whole progressbar workflow
- // and execute the batch in one pass.
- \Drupal::service('batch.processor')->process();
- }
- }
+ /** @var \Drupal\Core\Batch\BatchProcessorInterface */
+ $batch_processor = \Drupal::service('batch.processor');
+ return $batch_processor->process($redirect, $url, $redirect_callback);
}
/**
* Retrieves the current batch.
*/
function &batch_get() {
- // Not drupal_static(), because Batch API operates at a lower level than most
- // use-cases for resetting static variables, and we specifically do not want a
- // global drupal_static_reset() resetting the batch information. Functions
- // that are part of the Batch API and need to reset the batch information may
- // call batch_get() and manipulate the result by reference. Functions that are
- // not part of the Batch API can also do this, but shouldn't.
- static $batch = array();
- return $batch;
+ /** @var \Drupal\Core\Batch\BatchProcessorInterface $batch_processor */
+ $batch_processor = \Drupal::service('batch.processor');
+ return $batch_processor->getBatch();
}
/**
diff --git a/core/lib/Drupal/Core/Batch/BatchProcessor.php b/core/lib/Drupal/Core/Batch/BatchProcessor.php
index 13b0b98..e1507ba 100644
--- a/core/lib/Drupal/Core/Batch/BatchProcessor.php
+++ b/core/lib/Drupal/Core/Batch/BatchProcessor.php
@@ -7,6 +7,7 @@
namespace Drupal\Core\Batch;
+use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Timer;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Datetime\DateFormatter;
@@ -97,9 +98,118 @@ public function __construct($root, BatchQueueHandlerInterface $batch_queue, Date
}
/**
+ * Processes the batch.
+ *
+ * This function is generally not needed in form submit handlers;
+ * Form API takes care of batches that were set during form submission.
+ *
+ * @param \Drupal\Core\Url|string $redirect
+ * (optional) Either path or Url object to redirect to when the batch has
+ * finished processing. Note that to simply force a batch to (conditionally)
+ * redirect to a custom location after it is finished processing but to
+ * otherwise allow the standard form API batch handling to occur, it is not
+ * necessary to call batch_process() and use this parameter. Instead, make
+ * the batch 'finished' callback return an instance of
+ * \Symfony\Component\HttpFoundation\RedirectResponse, which will be used
+ * automatically by the standard batch processing pipeline (and which takes
+ * precedence over this parameter).
+ * @param \Drupal\Core\Url $url
+ * (optional - should only be used for separate scripts like update.php)
+ * URL of the batch processing page.
+ * @param $redirect_callback
+ * (optional) Specify a function to be called to redirect to the progressive
+ * processing page.
+ *
+ * @return \Symfony\Component\HttpFoundation\RedirectResponse|null
+ * A redirect response if the batch is progressive. No return value otherwise.
+ */
+ public function process($redirect = NULL, Url $url = NULL, $redirect_callback = NULL) {
+ if (isset($this->batch)) {
+ // Add process information
+ $process_info = array(
+ 'current_set' => 0,
+ 'progressive' => TRUE,
+ 'url' => isset($url) ? $url : Url::fromRoute('system.batch_page.html'),
+ 'source_url' => Url::fromRouteMatch(\Drupal::routeMatch() ),
+ 'batch_redirect' => $redirect,
+ 'theme' => \Drupal::theme()->getActiveTheme()->getName(),
+ 'redirect_callback' => $redirect_callback,
+ );
+ $this->batch += $process_info;
+
+ // The batch is now completely built. Allow other modules to make changes
+ // to the batch so that it is easier to reuse batch processes in other
+ // environments.
+ \Drupal::moduleHandler()->alter('batch', $this->batch);
+
+ // Assign an arbitrary id: don't rely on a serial column in the 'batch'
+ // table, since non-progressive batches skip database storage completely.
+ $this->batch['id'] = db_next_id();
+
+ // Move operations to a job queue. Non-progressive batches will use a
+ // memory-based queue.
+ foreach ($this->batch['sets'] as $key => $batch_set) {
+ _batch_populate_queue($this->batch, $key);
+ }
+
+ // Initiate processing.
+ if ($this->batch['progressive']) {
+ // Now that we have a batch id, we can generate the redirection link in
+ // the generic error message.
+ /** @var \Drupal\Core\Url $batch_url */
+ $batch_url = $this->batch['url'];
+ /** @var \Drupal\Core\Url $error_url */
+ $error_url = clone $batch_url;
+ $query_options = $error_url->getOption('query');
+ $query_options['id'] = $this->batch['id'];
+ $query_options['op'] = 'finished';
+ $error_url->setOption('query', $query_options);
+
+ $this->batch['error_message'] = t('Please continue to the error page', array('@error_url' => $error_url->toString(TRUE)->getGeneratedUrl()));
+
+ // Clear the way for the redirection to the batch processing page, by
+ // saving and unsetting the 'destination', if there is any.
+ $request = \Drupal::request();
+ if ($request->query->has('destination')) {
+ $this->batch['destination'] = $request->query->get('destination');
+ $request->query->remove('destination');
+ }
+
+ // Store safe strings.
+ // @todo Ensure we are not storing an excessively large string list in:
+ // https://www.drupal.org/node/2295823
+ $this->batch['safe_strings'] = SafeMarkup::getAll();
+
+ // Store the batch.
+ $this->batchStorage->create($this->batch);
+
+ // Set the batch number in the session to guarantee that it will stay alive.
+ $_SESSION['batches'][$this->batch['id']] = TRUE;
+
+ // Redirect for processing.
+ $query_options = $error_url->getOption('query');
+ $query_options['op'] = 'start';
+ $query_options['id'] = $this->batch['id'];
+ $batch_url->setOption('query', $query_options);
+ if (($function = $this->batch['redirect_callback']) && function_exists($function)) {
+ $function($batch_url->toString(), ['query' => $query_options]);
+ }
+ else {
+ return new RedirectResponse($batch_url->setAbsolute()->toString(TRUE)->getGeneratedUrl());
+ }
+ }
+ else {
+ // Non-progressive execution: bypass the whole progressbar workflow
+ // and execute the batch in one pass.
+ $this->processBatchSet();
+ }
+ }
+ }
+
+ /**
* {@inheritdoc}
*/
- public function process() {
+ public function processBatchSet() {
$current_set = $this->currentSet();
// Indicate that this batch set needs to be initialized.
$set_changed = TRUE;
@@ -235,6 +345,13 @@ public function currentSet() {
}
/**
+ * @return array
+ */
+ public function getBatch() {
+ return $this->batch;
+ }
+
+ /**
* {@inheritdoc}
*/
public function nextSet() {
diff --git a/core/lib/Drupal/Core/Batch/BatchProcessorInterface.php b/core/lib/Drupal/Core/Batch/BatchProcessorInterface.php
index 4ccb995..145c30a 100644
--- a/core/lib/Drupal/Core/Batch/BatchProcessorInterface.php
+++ b/core/lib/Drupal/Core/Batch/BatchProcessorInterface.php
@@ -6,7 +6,6 @@
*/
namespace Drupal\Core\Batch;
-use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Processes batch requests.
@@ -24,7 +23,7 @@
* @return array
* An array containing a completion value (in percent) and a status message.
*/
- public function process();
+ public function processBatchSet();
/**
* Returns the batch set being currently processed.
@@ -57,4 +56,9 @@ public function nextSet();
*/
public function finished();
+ /**
+ * @return array
+ */
+ public function &getBatch();
+
}
diff --git a/core/lib/Drupal/Core/Batch/Percentage.php b/core/lib/Drupal/Core/Batch/Percentage.php
index 0eb30e2..9a5d234 100644
--- a/core/lib/Drupal/Core/Batch/Percentage.php
+++ b/core/lib/Drupal/Core/Batch/Percentage.php
@@ -29,7 +29,7 @@ class Percentage {
* until we are finished, but we also never print more decimal places than
* are meaningful.
*
- * @see \Drupal\Core\Batch\BatchProcessorInterface::process()
+ * @see \Drupal\Core\Batch\BatchProcessorInterface::processBatchSet()
*/
public static function format($total, $current) {
if (!$total || $total == $current) {
diff --git a/core/tests/Drupal/Tests/Core/Batch/BatchProcessorTest.php b/core/tests/Drupal/Tests/Core/Batch/BatchProcessorTest.php
index 3dbcd64..c4af0be 100644
--- a/core/tests/Drupal/Tests/Core/Batch/BatchProcessorTest.php
+++ b/core/tests/Drupal/Tests/Core/Batch/BatchProcessorTest.php
@@ -71,4 +71,13 @@ protected function setupBatchProcessor() {
return new BatchProcessor('core', $this->batchQueue->reveal(), $this->dateFormatter->reveal(), $this->formSubmitter->reveal(), $this->batchStorage->reveal(), $this->requestStack);
}
+ /**
+ * @covers ::getBatch
+ */
+ public function testGetEmptyBatch() {
+ $batch = $this->setupBatchProcessor();
+
+ $this->assertEquals(['sets' => []], $batch->getBatch());
+ }
+
}