WP Manifestindependent plugin directory
manifest / developer / raza-batchpress

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

0stars
0forks

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.zip

Ships 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:

  1. Build a list of items that need to be processed.
  2. 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

  1. Download or clone the plugin.
  2. Copy the raza-batchpress folder into:
wp-content/plugins/
  1. Activate Raza BatchPress from WordPress → Plugins.
  2. Open WordPress → Tools → Raza BatchPress.
  3. Select a job and click Run.

The Composer metadata is included for development/package management, but do not use a composer require command 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_options capability 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.

Read the full README on GitHub →