Batch Processing To Update Nodes In Drupal And Download Updated Nods In CSV Format

28 / Jul / 2023 by Yash Malviya 0 comments

What is Batch Processing:

In Drupal, batch processing is a mechanism that allows you to execute time-consuming operations in smaller, manageable chunks. It helps prevent PHP timeouts and allows long-running processes to be executed successfully. Batch processing is commonly used for tasks such as data migration, large-scale updates, or any operation involving a significant amount of data.

Batch processing is a powerful feature in Drupal that allows you to efficiently update a large number of nodes. In this blog post, we will walk you through implementing batch processing to update nodes in Drupal.

Batch processing for updating nodes and downloading updated nodes in CSV format in your Drupal application:

Step 1:

Create the custom module with the name batch_process, then create the .info.yml File Start by creating a file called batch_process.info.yml In your custom module’s root directory. The .info.yml file provides metadata about your module to Drupal. Here’s an example of its contents:

name: "Batch Process"

type: module

description: "Example module demonstrating batch processing in Drupal"

package: Custom

version: "1.0"

core_version_requirement: ^8 || ^9

Step 2:

Create the .module File Next, create a file called batch_process.module in your custom module’s root directory. The .module file is where you define the module’s functionality and hook implementations. Here’s an example of its contents:

 

<?php

use Drupal\Core\Routing\RouteMatchInterface;

/**
* Implements hook_help().
*/
function batch_process_help($route_name, RouteMatchInterface $route_match)
{
switch ($route_name) {
case 'help.page.batch_process':
return '<p>' . t('Help text for My Module.') . '</p>';
}
}

/**
* Implements hook_menu().
*/
function batch_process_menu()
{
$items['admin/config/batch-process/update-nodes'] = array(
'title' => 'Update Nodes',
'description' => 'Update nodes using batch processing',
'route_name' => 'batch_process.update_nodes',
'weight' => 0,
);

$items['admin/config/batch-process/download-csv'] = array(
'title' => 'Download CSV',
'route_name' => 'batch_process.download_csv',
'weight' => 1,
);

return $items;
}

/**
* Implements hook_theme().
*/
function batch_process_theme()
{
return array(
'batch_process_update_nodes_form' => array(
'render element' => 'form',
),
);
}


Step 3:

Define the Routing File Create a file called batch_process.routing.yml in your custom module’s root directory. The routing file defines the URLs and corresponding controller methods for your module. Here’s an example of its contents:

 

batch_process.update_nodes:

path:"/update-nodes"

defaults:

_form:'\Drupal\batch_process\Form\UpdateNodesForm'

_title:"Update Nodes"

requirements:

_permission:"access content"

_access:"TRUE"

batch_process.download_csv:

path:"/batch-process/download-csv"

defaults:

_controller:'\Drupal\batch_process\Controller\BatchProcessController::downloadCsv'

requirements:

_permission:"access content"

Step 4:

Create the Controller File Next, create a file called BatchProcessController.php in your custom module’s src/Controller Directory. This file will handle the batch-processing functionality. Here’s an example of its contents:
<?php

namespace Drupal\batch_process\Controller;

use Drupal\Core\Controller\ControllerBase;

use Drupal\batch_process\Batch\BatchProcessUpdateNodes;

use Symfony\Component\HttpFoundation\Response;

use Symfony\Component\Serializer\Encoder\CsvEncoder;

/**

* Class BatchProcessController.

*/

class BatchProcessController extends ControllerBase

{

/**

* Download the updated nodes as a CSV file.

*/

publicfunctiondownloadCsv()

{

$csvData =BatchProcessUpdateNodes::generateCsvData();

$csvContent ='';

if(!empty($csvData)){

$csvEncoder =newCsvEncoder();

$csvContent =$csvEncoder->encode($csvData,'csv');

}

$response =newResponse($csvContent);

$response->headers->set('Content-Type','text/csv');

$response->headers->set('Content-Disposition','attachment; filename="updated_nodes.csv"');

return$response;

}
}

Step 5:

Build the Form File Next, we need to create a form that allows users to specify the parameters for the update operation. Create a file called UpdateNodesForm.php in your custom module’s src/Form Directory. This form will include a button “Download Updated Nodes (CSV)” by clicking on the user can download the updated nodes in csv format. Here’s an example of its contents:
<?php

namespace Drupal\batch_process\Form;

use Drupal\Core\Form\FormBase;

use Drupal\Core\Form\FormStateInterface;

use Drupal\Core\Url;

use Drupal\batch_process\Batch\BatchProcessUpdateNodes;

/**

* Class UpdateNodesForm.

*/

class UpdateNodesForm extends FormBase

{

/**

* {@inheritdoc}

*/

publicfunctiongetFormId()

{

return'batch_process_update_nodes_form';

}

/**

* {@inheritdoc}

*/

publicfunctionbuildForm(array$form,FormStateInterface$form_state)

{

$form['#title']=$this->t('Update Nodes');

$form['csv_download']=[

'#type'=>'link',

'#title'=>$this->t('Download Updated Nodes (CSV)'),

'#url'=>Url::fromRoute('batch_process.download_csv'),

'#attributes'=>[

'class'=>['button'],

],

];

$form['submit']=[

'#type'=>'submit',

'#value'=>$this->t('Start Batch Processing'),

];

return$form;

}

/**

* {@inheritdoc}

*/

publicfunctionsubmitForm(array&$form,FormStateInterface$form_state)

{

$batch =array(

'title'=>t('Updating nodes'),

'init_message'=>t('Starting node update...'),

'progress_message'=>t('Processed @current out of @total nodes.'),

'error_message'=>t('An error occurred during processing.'),

'operations'=>array(

array(

'\Drupal\batch_process\Batch\BatchProcessUpdateNodes::processBatch',

array(),

),

),

'finished'=>'\Drupal\batch_process\Batch\BatchProcessUpdateNodes::finishBatch',

);

batch_set($batch);

$redirect_url =Url::fromRoute('batch_process.update_nodes')->toString();

$form_state->setRedirectUrl(Url::fromRoute('batch_process.update_nodes'));

}

}

Step 6:

Implement the Batch Process Now, let’s implement the batch process logic. Create a file called BatchProcessUpdateNodes.php in your custom module’s src/Batch directory. This file will contain the functions responsible for the batch process.

The processBatch() Method: This method is the main batch callback function. It processes nodes in batches by updating their status to “Published” and performing any other necessary updates. It keeps track of the progress and current node count, and when all nodes have been processed, it marks the batch as finished.

ThefinishBatch() Method: This method is called after the batch processing is complete. It displays a success or error message using Drupal’s messenger service, indicating the status of the node update process. It provides feedback to the user regarding the outcome of the batch processing.

ThegenerateCsvData() Method: This method generates CSV data containing information about the updated nodes. It retrieves the published nodes and extracts the required information, such as the node ID, title, and updated status. The method returns the CSV data array, which can be used for further processing or generating reports.

<?php

namespace Drupal\batch_process\Batch;

use Drupal\Component\Serialization\Csv;

use Drupal\Core\Url;

use Drupal\node\Entity\Node;

use Symfony\Component\HttpFoundation\Response;

/**

* Class BatchProcessUpdateNodes.

*/

class BatchProcessUpdateNodes

{

/**

* Batch callback.

*/

publicstaticfunctionprocessBatch(&$context)

{

if(empty($context['sandbox'])){

$context['sandbox']['progress']=0;

$context['sandbox']['max']=1000;// Total number of nodes to process

$context['sandbox']['current_node']=0;

}

$limit =10;// Number of nodes to process in each batch

$query =\Drupal::entityQuery('node')

->condition('status',[0,1],'IN')// Published and unpublished nodes

->range($context['sandbox']['current_node'],$limit)// Process only a limited number of nodes

->sort('nid','ASC');// Sort by node ID in ascending order

$nids =$query->execute();

$nodes =Node::loadMultiple($nids);

foreach($nodes as$node){

// Update the status of the node to "Processed"

$node->set('status',1);// 1 means "Published"

$node->save();

// Perform other necessary updates to the newly added nodes

// Increment the current node count

$context['sandbox']['current_node']++;

// Update the progress

$context['sandbox']['progress']=($context['sandbox']['current_node']/$context['sandbox']['max'])*100;

// If all nodes have been processed, mark the batch as finished

if($context['sandbox']['current_node']>=$context['sandbox']['max']){

$context['finished']=1;

break;

}

}

// Set the progress message

$context['message']=t('Processed @current out of @total nodes.',array(

'@current'=>$context['sandbox']['current_node'],

'@total'=>$context['sandbox']['max'],

));

}

/**

* Batch finished callback.

*/

publicstaticfunctionfinishBatch($success,$results,$operations)

{

if($success){

\Drupal::messenger()->addMessage(t('Node update completed successfully.'));

}else{

\Drupal::messenger()->addMessage(t('Node update completed with errors.'),'error');

}

}

/**

* Generate CSV data for updated nodes.

*/

publicstaticfunctiongenerateCsvData()

{

$csvData =array(

array('Node ID','Title','Updated Status'),

);

// Retrieve the updated nodes.

$query =\Drupal::entityQuery('node')

->condition('status',1)// Published nodes

->range(0,1000)// Limit the query to the maximum number of nodes

->sort('nid','ASC');// Sort by node ID in ascending order

$nids =$query->execute();

$nodes =Node::loadMultiple($nids);

// Extract the required information from the updated nodes.

foreach($nodes as$node){

$csvData[]=array(

$node->id(),

$node->label(),

'Published',

);

}

return$csvData;

}

}

Step 7:

Create the Template File To render the form structure, we must create a template file. Create a file called batch-process-update-nodes-form.html.twig in your custom module’s templates directory. This template file will render the form elements defined in the form class.
{{ form }}

{{ csv_download }}

Go to your drupal site and open the form : /update-nodes

 

Before Updating the nodes

 

 

Click on the “Start Batch Processing” Button and start the batch processing. All the nodes will updated.


After updating the nodes

Now, you can download the updated node by clicking “Download Updated Nodes (CSV)” Button.

You can see the updated nodes in CSV format.

 

 

Thank You.

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *