Raza BatchPress self-updates
Run custom WordPress and WooCommerce data jobs in manageable AJAX batches with progress logs and optional CSV input.
by Ahmad Raza · github.com/razaahmad9/raza-batchpress · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/razaahmad9/raza-batchpress/archive/refs/heads/main.zipShips its own WordPress updater (built-in updater), so new versions show up under Dashboard → Updates.
Readme
Raza BatchPress
Raza BatchPress is a lightweight WordPress admin utility for running custom data-processing jobs in small AJAX batches instead of trying to process everything in a single request.
It is useful for WooCommerce migrations, taxonomy assignments, metadata updates, imports, cleanup tasks, and other operations that may involve hundreds or thousands of records.
Author: Ahmad Raza
GitHub: https://github.com/RazaAhmad9
License: GPL-2.0-or-later
What the plugin does
A BatchPress job has two main responsibilities:
- Build a list of items that need to be processed.
- Process one item at a time while Raza BatchPress handles the queue, AJAX requests, batching, progress state, and log output.
The general flow is:
Select a job
↓
items() builds the queue
↓
Queue is stored temporarily in WordPress options
↓
Raza BatchPress takes the next batch
↓
process($item) runs for every item
↓
Returned messages appear in the admin log
↓
Repeat until the queue is empty
Because only a limited number of items are processed per request, long-running maintenance jobs are less likely to hit PHP execution-time or memory limits.
Included WooCommerce jobs
This version currently includes five ready-to-run WooCommerce jobs:
| Job | Source | Target | Matching rule |
|---|---|---|---|
| Assign Product Brands From Tags | product_tag |
product_brand |
Exact slug match |
| Assign Product Functions From Tags | product_tag |
product_functions |
Exact slug match |
| Assign Product Materials From Tags | product_tag |
product_material |
Exact slug match |
| Assign Product Conditions From Tags | product_tag |
product_conditions |
Exact slug match |
| Assign Product Case Sizes From Tags | product_tag |
product_case_size |
Exact slug match |
These jobs only use existing taxonomy terms. They do not create missing terms, delete Product Tags, or remove terms that are already assigned.
For example, if a product has the Product Tag slug rolex and an existing product_brand term also has the slug rolex, the Brands job assigns that existing brand to the product.
If no exact slug match exists, nothing is changed.
Installation
Manual installation
- Download or clone the plugin.
- Copy the
raza-batchpressfolder into:
wp-content/plugins/
- Activate Raza BatchPress from WordPress → Plugins.
- Open WordPress → Tools → Raza BatchPress.
- Select a job and click Run.
The Composer metadata is included for development/package management, but do not use a
composer requirecommand unless this fork has been published to a Composer repository or installed through a repository declaration in your own project.
Plugin structure
raza-batchpress/
├── assets/
│ ├── scripts/
│ │ └── admin.js
│ └── styles/
│ ├── admin.css
│ └── admin.scss
├── includes/
│ ├── class-assign-product-brands-from-tags.php
│ ├── class-assign-product-case-sizes-from-tags.php
│ ├── class-assign-product-conditions-from-tags.php
│ ├── class-assign-product-functions-from-tags.php
│ ├── class-assign-product-materials-from-tags.php
│ ├── helpers.php
│ ├── page.php
│ ├── setup.php
│ └── updater.php
├── composer.json
├── LICENSE
├── README.md
└── raza-batchpress.php
Understanding a job class
A normal job usually contains these members:
| Member | Required? | Purpose |
|---|---|---|
$label |
Yes | Name shown in the admin interface. |
items() |
Yes for normal jobs | Returns the complete array of items to process. |
process($item) |
Yes | Processes one item and may return a log message. |
$batch |
No | Number of items processed per AJAX request. Default is 10. |
$description |
No | Extra information shown under the job name. |
$upload |
No | Set to true when the job requires a CSV upload. |
Create a new job
Suppose you want to create a job that updates a custom field on every published product.
Step 1: Create the job class
Create:
includes/class-update-product-example.php
Add:
<?php
namespace RazaAhmad\BatchPress;
use WP_Query;
if (!defined('ABSPATH')) {
exit;
}
class UpdateProductExample
{
/**
* Process 20 products per AJAX request.
*/
public $batch = 20;
/**
* Name shown in Tools → Raza BatchPress.
*/
public $label = 'Update Product Example';
/**
* Optional explanation shown below the job name.
*/
public $description = 'Example job that processes published WooCommerce products.';
/**
* Return the items that should be processed.
*/
public function items(): array
{
$query = new WP_Query([
'post_type' => 'product',
'post_status' => 'publish',
'fields' => 'ids',
'posts_per_page' => -1,
'no_found_rows' => true,
]);
return array_map('intval', $query->posts);
}
/**
* Process one queued item.
*/
public function process($item)
{
$product_id = absint($item);
if (!$product_id) {
return 'SKIPPED: Invalid product ID.';
}
update_post_meta($product_id, '_example_processed', 'yes');
return sprintf(
'UPDATED #%d: Product processed successfully.',
$product_id
);
}
}
Step 2: Include the class file
Open raza-batchpress.php and add the file inside Init::includes():
require_once RAZA_BATCHPRESS_INCLUDES . 'class-update-product-example.php';
Step 3: Register the class
Add the class to the $defaults array inside Init::register_default_jobs():
$defaults = [
AssignProductBrandsFromTags::class,
AssignProductFunctionsFromTags::class,
AssignProductMaterialsFromTags::class,
AssignProductConditionsFromTags::class,
AssignProductCaseSizesFromTags::class,
UpdateProductExample::class,
];
The new job will now appear automatically under Tools → Raza BatchPress.
Register a job without editing the main job array
Raza BatchPress keeps the original public filter:
batchpress/jobs
That means another plugin or custom integration can register a class without modifying the bundled job list.
add_filter('batchpress/jobs', function (array $jobs): array {
$jobs[] = MyCustomJob::class;
return $jobs;
});
The callback should append to the existing $jobs array and return it. Do not replace the array unless you intentionally want to remove previously registered jobs.
Minimal job example
namespace RazaAhmad\BatchPress;
class MyCustomJob
{
public $batch = 10;
public $label = 'My Custom Job';
public $description = 'A short explanation of what this job changes.';
public function items(): array
{
return [101, 102, 103];
}
public function process($item)
{
// Perform the work for this item.
return sprintf('Processed item %s.', $item);
}
}
How items() works
For a standard job, items() is called at the beginning of the run.
It must return an array.
Examples of valid items include:
return [12, 24, 36];
or:
return [
['id' => 12, 'value' => 'one'],
['id' => 24, 'value' => 'two'],
];
Raza BatchPress stores that array as the temporary processing queue.
How process($item) works
process() is called once for every queued item.
public function process($item)
{
// Change something here.
return 'Item processed.';
}
If process() returns a non-empty value, that value is added to the BatchPress log.
This is useful for messages such as:
ASSIGNED #123 "Rolex Submariner": Brand [Rolex].
ALREADY ASSIGNED #456 "Omega Seamaster": Nothing changed.
NO TAGS #789 "Example Product": Nothing changed.
ERROR #900 "Example Product": Could not read terms.
If you do not need a log entry for an item, return null, an empty string, or nothing.
Batch size
The optional $batch property controls how many items are processed in a single AJAX request.
public $batch = 10;
Smaller batches are safer for expensive operations. Larger batches can finish faster when each item requires very little work.
The plugin defaults to 10 if a job does not define $batch.
Job descriptions
Use $description to explain the job before an administrator runs it:
public $description = 'Assign existing Product Brand terms using exact Product Tag slug matches.';
The description appears directly below the job name in the admin screen.
CSV upload jobs
A job can request a CSV file by setting:
public $upload = true;
Example:
namespace RazaAhmad\BatchPress;
class ImportExample
{
public $batch = 10;
public $upload = true;
public $label = 'Import Example';
/**
* Optional for an upload job.
* Receives parsed CSV rows and can normalize/filter them.
*/
public function items(array $data): array
{
return array_filter($data);
}
public function process($item)
{
return sprintf('Imported %s.', $item['name'] ?? 'row');
}
}
The first CSV row is treated as the header row. Headers are normalized and used as array keys for each subsequent row.
Helpers trait
The plugin includes a Helpers trait for common media operations.
use RazaAhmad\BatchPress\Helpers;
class ImportImages
{
use Helpers;
public function process($item)
{
$attachment_id = $this->uploadImage(
$item['url'],
(int) $item['post_id'],
$item['title'] ?? null
);
return $attachment_id
? "Uploaded attachment {$attachment_id}."
: 'Image upload failed.';
}
}
Available helper methods include:
$this->uploadImage($url, $post_id, $title);
$this->uploadFile($url, $post_id, $title);
Built-in taxonomy job safeguards
The bundled WooCommerce jobs are intentionally conservative:
- They process existing WooCommerce products only.
- They require the source and target taxonomies to exist.
- They match terms by exact slug only.
- They do not create target terms.
- They do not delete or rename Product Tags.
- They do not remove existing target taxonomy terms.
- They only append target terms that are not already assigned.
- They return a readable result for every processed product.
Admin access and request security
The BatchPress screen is available only to users with the manage_options capability.
AJAX processing also validates:
- the current user's capability;
- the BatchPress AJAX action;
- a WordPress nonce;
- the requested processing operation;
- the selected registered job.
Stopping a job
Click Stop processing to stop the active run and clear its stored queue and log.
A job can then be started again from the beginning.
Important development notes
Back up before destructive jobs
Batch-processing tools can change large amounts of data quickly. Test new jobs on staging and create a database backup before running destructive operations on production.
Keep jobs idempotent where possible
A good job should be safe to run more than once.
For example, the bundled taxonomy jobs check which terms are already assigned before adding anything. Running them again therefore does not duplicate or remove existing assignments.
Return useful log messages
Readable logs make large migrations much easier to verify. Include the item ID, title, result, and reason whenever practical.
Requirements
- WordPress installation with wp-admin access
- PHP 7.4 or newer
manage_optionscapability to run jobs- WooCommerce only for the bundled WooCommerce-specific jobs
The core batch runner can also be used for non-WooCommerce WordPress jobs.
Developer API
Public job registration filter:
apply_filters('batchpress/jobs', []);
Example registration:
add_filter('batchpress/jobs', function (array $jobs): array {
$jobs[] = MyCustomJob::class;
return $jobs;
});
Author
Ahmad Raza
GitHub: https://github.com/RazaAhmad9
License and upstream acknowledgement
Raza BatchPress is distributed under the GPL-2.0-or-later license.
This project is a customized and extended fork of the original GPL-licensed BatchPress project. The current fork is maintained and extended by Ahmad Raza and includes additional WooCommerce batch jobs, documentation, rebranding, and maintenance changes.