Drupal is a registered trademark of Dries Buytaert

Codit: Batch Operations is for Drupal developers to easily invoke batch operations in hook_update_n, Drush Deploy hooks, cron, with Drush, or using the UI.

Features

  • Baked-in reporting of operations performed in the batch into a BatchOpLog entity.
  • If the Batch Operation gets interrupted (error, exception, ctrl-c, navigating away from the batch run ...), the operation is still logged. The state is kept, so the next time it runs, it picks up where it left off.
  • Custom batch process scripts live in a local/custom module.
  • Batch Operation scripts can be used the same way in:
    • hook_update_n()
    • post_update functions
    • Drush deploy and post-deploy functions
    • Drush command to execute Batch Operation scripts - drush codit-batch-operations:run {script class name}
    • cron
    • Optional UI
  • Option to stop on first error, or to skip items that error and keep going.

You need this module if you want

  • Custom Drupal cron jobs
  • Make changes to Drupal content during deployment
  • Make custom Drush commands that can be run in other ways
  • Complete logging and auditing of Drupal operations
  • Flexibility of how large scale content operations can be performed

Post-Installation

  • Assign any roles to the permission to manage the configuration.
  • Assign any roles to the permissions to View Batch operation logs, and to execute batch operation scripts via the UI.
  • Visit /admin/config/development/batch_operations/settings and set the following:
    • The machine name of the local module that will contain the scripts.
    • The user id of the user that will get named in entity saves.
  • Go to the custom module that you identified, and add the directory src/cbo_scripts/. This is where you will add your Batch Operations scripts.
  • Optionally, enable the sub-module Codit: Batch operations UI.

Additional Requirements

None

Recommended modules/libraries

None

Similar projects

None

How to try a demo?

  1. Go to SimplyTest.me https://www.simplytest.me/project/codit_batch_operations
  2. Follow the prompts to "Launch Sandbox"
  3. Login with admin : admin
  4. Go to /admin/modules#edit-modules-development and enable the 'Codit: Batch Operations UI' submodule
  5. Go to settings /admin/config/development/batch_operations/settings
  6. For Machine name of local module, enter codit_batch_operations This fools it into showing the test Batch Operations.
  7. Set the User Id to 1.
  8. Save the configuration.
  9. Go here /admin/config/development/batch_operations and run some Batch Operations and view the resulting logs.

Create your own BatchOperation script

  1. Copy the StarterScript.php.txt from this module in to your src/cbo_scripts directory that you created in the Post-Installation steps.
  2. Rename the file to be a MeaningfulName.php
  3. Open the file and change the name of the class, to match the filename.
  4. Change the namespace entry to use the module_name of where this script now resides.
  5. Adjust each of the methods in the script to return what is needed.

Examples

Running Batch Operation from hook_update_n()

hook_update_n() runs before config import before hook_post_update() and before deploy (when using drush deploy) They live in any module's install file. (MY_MODULE_NAME.install.php) Full documentation about hook_update_n(): https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Extension%21module.api.php/function/hook_update_N/

  1. In whatever local/custom module you want to run this Batch Operation, add or use the existing MY_MODULE_NAME.install and add the following
      /**
       * A description of what this update will do.
       */
      function MY_MODULE_NAME_update_90??(&$sandbox) {
        $script = \Drupal::classResolver('\Drupal\MY_MODULE_NAME\cbo_scripts\SCRIPT_NAME');
        return $script->run($sandbox, 'hook_update');
      }
    
  2. Change the function name to match the module it resides in.
  3. Make the number be one higher than the previous hook_update_N().
  4. Change the MY_MODULE_NAME in the class to match where the script lives.
  5. Change the SCRIPT_NAME to match the class name of the script you want to run.
  6. This hook_update_N() you just created will run once when you use one of the following:
    • drush updb
    • drush deploy
    • visit /update.php and run updates in the UI.

Running Batch Operation from hook_post_update()

Post update runs after all the hook_update_N have run. Post update hooks live in their own file (MY_MODULE_NAME.post_update.php). Hook_post_updates are not sequentially numbered, though they could be. They are suffixed with a name. I suggest using the same name as your BatchOp script or anything else that is meaningful.

  1. In whatever local/custom module you want to run this Batch Operation, add or use the existing MY_MODULE_NAME.post_update.php and add the following
      /**
       * A description of what this post update will do.
       */
      function MY_MODULE_NAME_post_update_SCRIPT_NAME(&$sandbox) {
        $script = \Drupal::classResolver('\Drupal\MY_MODULE_NAME\cbo_scripts\SCRIPT_NAME');
        return $script->run($sandbox, 'post_update');
      }
    

    hook_post_update functions are only ever run once. The function name is tracked, but is not sequential. Drupal is more stable and fully operational than it is during hook_update_N().

Running Batch Operation from hook_deploy()

Drush deploy hooks run after all the hook_update_N and Post update hooks run. They live in their own file (MY_MODULE_NAME.deploy.php). Drush deploy hooks are not sequentially numbered, though they could be. They are suffixed with a name. I suggest using the same name as your BatchOp script or anything else that is meaningful.

  1. In whatever local/custom module you want to run this Batch Operation, add or use the existing MY_MODULE_NAME.deploy.php and add the following
      /**
       * A description of what this post update will do.
       */
      function MY_MODULE_NAME_deploy_SCRIPT_NAME(array &$sandbox) {
        $script = \Drupal::classResolver('\Drupal\MY_MODULE_NAME\cbo_scripts\SCRIPT_NAME');
        return $script->run($sandbox, 'deploy');
      }
    

Running Batch Operation from the user interface

Enabling the sub-module Codit: Batch operations UI creates a user interface for properly credentialed users to execute Batch Operations. This uses the Batch API and logs things exactly the same as they would be if run another way. The UI has separate permissions for access. The permissions are part of the parent module, so the UI module can be disabled on most sites, and then turned on when needed. This is similar to turning on the master power switch for the laboratory. The path for the UI is /admin/config/development/batch_operations/operations

Running a Batch Operation via cron

When coding your batch operation, define a public function getCronTiming() and have it return an acceptable pattern. The patterns used are human readable. Example:

  • 'every 10 minutes'
  • 'every 2 days'
  • 'every 2 weeks
  • 'every 3 months'
  • 'every 2 years'
  • 'every 10 days after 16:00'
  • 'on the 6th of every 1 month'
  • 'on the 15th of every 1 months after 16:00'
  • 'on the 4th of July'
  • 'on the 4th of July after 14:00'

Running Batch Operation from within custom code

It is possible to run a BatchOperation within custom code (event subscriber, submit handler...) However, calling it from within custom code does not run it as a true Drupal Batch, so it is at risk for php timeouts. However if it does timeout, it will pick up where it left off.

  1. In whatever local/custom code you want to use, add the following
      $script = \Drupal::classResolver('\Drupal\MY_MODULE_NAME\cbo_scripts\SCRIPT_NAME');
      $script->runByCustomCode('CUSTOM EXECUTOR IDENTIFIER', $allow_skip = TRUE);
    
    

FAQs

  • How do I run my script and have it keep going if there are errors? The third argument in the run() method is optional. Set it to TRUE if you want your script to skip items with errors.
  • How do I run my script with Drush? The Drush command is drush codit-batch-operations:run {script class name} it has an optional flag --allow-skip. The flag allows you to skip any errors or failures that occur. Leaving the flag off makes it fail on the first error or exception.
  • Can I list all the Batch Operations with Drush? You can list all available Batch Operations with drush codit-batch-operations:list Use the option --tests to also see the test Batch Operations.
  • When trying to run script, I get an error telling me a script is already running, but one should not be. How do I fix this? First, check with your team to make sure someone else is not running a Batch Operation script. If they confirm that nothing should be running, you can reset the flag by using drush codit-batch-operations:running --reset or visit the settings page /admin/config/development/batch_operations/settings
  • How do I have the script run as someone other than the default user? There are two methods to switch users:
    1. Call switchUser() in preRun();
    2. If executing in a hook, you can call switchUser() before calling run().
    3. In your processOne() method you can call switchUser(). Only choose this option if you must change users more than once in your processing. Otherwise use option 1.
  • How do I delete all the Batch Operation Logs so that I can uninstall the module. You will find a 'Delete all batch operation logs' link on the settings page.
  • Why do the cron time settings say 'after' instead of 'at'? Cron timings on cron jobs from this module are evaluated every time cron runs. Due to the settings of your cron, you may have a cron that only runs every 2 hours, so the timings of the cron job can only be tested every 2 hours. If you want your times to be more accurate, set cron to run more often (warning this can have performance issues).
  • How do I have a BatchOperation only have the option to run once? If you have a process that would be damaging to have it run more than once, add a public function getAllowOnlyOneCompleteRun() {return TRUE; } to your BatchOperation.
  • I defined my BatchOperation to only run once, but I need it to run again. How do I force it to run again? The state of it running before is stored in the BatchOpLog that shows as Completed. Delete the BatchOpLog that shows as completed and the BatchOperation will be allowed to run again.
  • How do I see all the built-in test BatchOperations in the UI? The tests are not usually shown in the UI. To see them, go to the setting page and delete the setting for the machine name of the local module where your scripts are stored. The UI will now show the test BatchOperations.
  • Are there supporting functions I can use within processOne()? Yes there are Node and Term related functions that can be very helpful. Look in BatchOperationsNodeTrait.php and BatchOperationsVocabularyTrait.php.

Activity

Total releases
5
First release
Jan 2025
Latest release
10 months ago
Release cadence
19 days
Stability
100% stable

Release Timeline

Releases

Version Type Release date
1.0.12 Stable Apr 2, 2025
1.0.11 Stable Mar 22, 2025
1.0.10 Stable Mar 18, 2025
1.0.9 Stable Feb 26, 2025
1.0.8 Stable Jan 15, 2025