batch.module
Search API
File
modules/batch/batch.moduleView source
- <?php
- /**
- * The main module file for the Batch module.
- *
- * Credit where credit is due: This module is largely inspired by the excellent Batch processing functionality
- * baked into Drupal (like a lot of FlightPath).
- */
-
-
-
-
- /**
- * Implementation of hook_menu
- *
- */
- function batch_menu() {
-
- $items = array();
-
- // Our test batch process, for testing...
- $items["batch-test-form"] = array(
- "title" => "Batch Test - Form",
- "page_callback" => "fp_render_form",
- "page_arguments" => array("batch_test_form"),
- "access_arguments" => array("batch_run_test"),
- "type" => MENU_TYPE_CALLBACK,
- "file" => menu_get_module_path("batch") . "/batch.test.inc",
- );
-
-
- $items["batch-processing/%"] = array(
- "page_callback" => "batch_processing_page",
- "page_arguments" => array(1),
- "access_callback" => TRUE,
- "type" => MENU_TYPE_CALLBACK,
- );
-
-
- $items["batch-finished/%"] = array(
- "page_callback" => "batch_finished_page",
- "page_arguments" => array(1),
- "access_callback" => TRUE,
- "type" => MENU_TYPE_CALLBACK,
- );
-
-
- $items["batch-ajax-callback/%"] = array(
- "page_callback" => "batch_ajax_callback",
- "page_arguments" => array(1),
- "access_callback" => TRUE,
- "type" => MENU_TYPE_CALLBACK,
- );
-
-
-
-
- return $items;
-
- }
-
-
- /**
- * This function is called by ajax, and will trigger each run of the batch operation function, then
- * return appropriate results back to our javascript.
- *
- * @param unknown_type $batch_id
- */
- function batch_ajax_callback($batch_id) {
-
- $rtn = array();
-
-
- $batch = batch_get($batch_id);
- if ($batch["token"] != batch_get_token()) {
- // Not allowed! Bad token.
- header('Content-Type: application/json');
- print json_encode(array("error" => t("An error has occured-- you are now allowed to run this batch, or the batch does not exist.")));
- exit();
- }
-
-
- ///////////////////////////////////
- // Run the batch operation.
- if (isset($batch["file"]) && $batch["file"] != "") {
- require_once($batch["file"]);
- }
- $operation_callback = $batch["operation"][0];
-
- // If the operation callback doesn't exist, throw an error.
- if (!function_exists($operation_callback)) {
- header('Content-Type: application/json');
- print json_encode(array("error" => t("An error has occured: Cannot find operation callback function @function", array("@function" => addslashes($operation_callback)))));
- exit();
- }
-
- $operation_args = $batch["operation"][1];
- // Add our $batch to the beginning of the $args array.
- //array_unshift($operation_args, $batch);
- $params = array(0 => &$batch);
- foreach ($operation_args as $val) {
- $params[] = $val;
- }
-
- call_user_func_array($operation_callback, $params);
-
-
-
- // Coming out of this, $batch should be modified
- // Save it back to the database.
- db_query("UPDATE batch_queue
- SET batch_data = '?'
- WHERE batch_id = '?' ", serialize($batch), $batch_id);
-
-
- // Output relavant results....
- $current = $batch["results"]["current"];
- $total = $batch["results"]["total"];
- $percent = "";
- if ($total > 0) {
- $percent = round(($current / $total) * 100, 1) * 1;
- }
-
-
- $rtn["progress_message"] = t($batch["progress_message"], array("@current" => $current, "@total" => $total, "@percent" => $percent));
- $rtn["percent"] = $percent;
- $rtn["display_percent"] = $batch["display_percent"];
- $rtn["finished"] = "";
- if ($batch["results"]["finished"] == TRUE) {
- $rtn["finished"] = "finished";
- }
-
-
-
-
- header('Content-Type: application/json');
- $rtn["success"] = "SUCCESS"; // let javascript know we DID finish executing correctly.
- print json_encode($rtn);
-
- exit();
- }
-
-
-
-
-
- /**
- * We redirect to this page when we have finished a batch.
- *
- * @param unknown_type $batch_id
- */
- function batch_finished_page($batch_id) {
- $batch = batch_get($batch_id);
- if ($batch["token"] != batch_get_token()) {
- return "<p>" . t("Sorry, there is a token mismatch or this batch no longer exists.") . "</p>";
- }
-
- // Otherwise, we can just return whatever their callback function is. If this is from a form submission, we will send them
- // to the form's original destination.
-
- if (isset($batch["file"]) && $batch["file"] != "") {
- require_once($batch["file"]);
- }
- $finished_callback = $batch["finished_callback"][0];
- $finished_args = $batch["finished_callback"][1];
- if (!is_array($finished_args)) $finished_args = array();
-
- $params = array();
-
- // If we are NOT going to fp_goto, then add the $batch as the first argument.
- if ($finished_callback != "fp_goto") {
- // Add our $batch to the beginning of the $args array.
- //array_unshift($finished_args, $batch);
- $params = array (0 => &$batch);
- }
-
- foreach ($finished_args as $val) {
- $params[] = $val;
- }
-
- if (isset($batch["success_message"])) {
- fp_add_message($batch["success_message"]);
- }
-
- // Okay, let's call our function:
- return call_user_func_array($finished_callback, $params);
-
-
-
-
-
- }
-
-
-
-
-
- /**
- * This is the page the user sees while a batch is being processed.
- *
- * It will contain all the AJAX and such necessary to begin the batch process.
- *
- * @param unknown_type $batch_id
- */
- function batch_processing_page($batch_id) {
- $rtn = "";
-
- $batch = batch_get($batch_id);
- if ($batch["token"] != batch_get_token()) {
- return "<p>" . t("Sorry, there is a token mismatch or this batch no longer exists.") . "</p>";
- }
-
-
-
- fp_set_title($batch["title"]);
-
- fp_add_css(fp_get_module_path("batch") . "/css/batch.css");
-
- // Set up our setting...
- fp_add_js(array("batch_id" => $batch_id), "setting");
-
- // Add our general js file...
- fp_add_js(fp_get_module_path("batch") . "/js/batch.js");
-
-
-
-
-
- $rtn .= "<div class='batch-progress-bar-wrapper'>
- <div class='batch-progress-bar' id='batch-progress-bar'></div>
- </div>
- <div id='batch-progress-message'>" . t("Initializing... please wait...") . "</div>
-
- ";
-
-
-
-
-
-
-
- return $rtn;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /**
- * Implementation of hook_cron
- *
- * Delete old batches from the batch_queue table. These would be normal "old" batches we no longer need,
- * or ones that never finished for some reason and are just taking up space.
- *
- */
- function batch_cron() {
-
- $older_than = strtotime("6 HOURS AGO");
- db_query("DELETE FROM batch_queue WHERE created < ? ", $older_than);
-
- }
-
-
-
-
- /**
- * Create a new batch process.
- *
- *
- *
- * @param $batch
- * This is an array containing everything we need to know about the batch we are creating.
- * The non-required fields will be substituted with default values if left out.
- *
- * - operation :[REQUIRED] an array containing the callback function to execute plus any arguments. Ex: "operation" => array('my_function_to_call', array($arg1, $arg2))
- * - finished_callback : an array containing the callback function and args to call once we are finished with the batch.
- * Ex: "finished_callback" => array('my_finished_function', array($arg1, $arg2))
- * Generally, this field is optional. Since batches are usually set up in a form's submit handler, the default behavior is to go to whatever the form's destination
- * was. You can override that here, however.
- * - title : A title to display to the user while the batch is running. Ex: 'title' => t('Processing Batch...')
- * - progress_message : A message to be displayed while the batch runs. It may use replacement patterns: @current, @total, @percent.
- * Ex: 'progress_message' => 'Processed @current out of @total.' // Do NOT run through t()! It will be done at run time.
- * - file : An optional file system path to a file where the batch's operation and/or finished functions reside. Ex: "file" => menu_get_module_path("my_example") . "/runme.inc"
- * - success_message : An optional message which will display to the user when the batch is complete. Ex: "The process is now complete."
- * - display_percent : boolean, default FALSE. If set to TRUE, display percentage value in progress bar.
- *
- *
- * @return $batch_id - the id from batch_queue table for this batch.
- */
- function batch_set($batch) {
- global $user;
-
-
- if (!isset($batch["title"])) {
- $batch["title"] = t("Processing Batch...");
- }
- if (!isset($batch["progress_message"])) {
- $batch["progress_message"] = t("Processed @current out of @total.");
- }
- if (!isset($batch["display_percent"])) {
- $batch["display_percent"] = FALSE;
- }
-
- // Add to the database
- $ser_batch = serialize($batch);
-
- $token = batch_get_token();
- db_query("INSERT INTO batch_queue (token, created, batch_data)
- VALUES ('?', '?', '?') ", $token, time(), $ser_batch);
- $batch_id = db_insert_id();
-
- // Set a session variable so we are aware of this batch process's existence, so we can call it from system's handle_form_submit if necessary.
- $_SESSION["fp_batch_id"] = $batch_id;
-
-
- // Return back the $bid for the next function to work with.
- return $batch_id;
-
- }
-
-
- /**
- * Return the batch_data array for this batch_id, or FALSE if it doesn't exist or can't be unserialized.
- *
- * @param unknown_type $batch_id
- */
- function batch_get($batch_id) {
- $res = db_query("SELECT * FROM batch_queue
- WHERE batch_id = ? ", $batch_id);
- $cur = db_fetch_array($res);
-
- if ($batch = unserialize($cur["batch_data"])) {
- $batch["batch_id"] = $batch_id;
- $batch["token"] = $cur["token"];
- $batch["created"] = $cur["created"];
-
- return $batch;
- }
-
- return FALSE;
-
- }
-
-
-
-
- /**
- * Return a token for this user.
- *
- */
- function batch_get_token() {
- global $user;
-
- $uid = 0;
- if (isset($user->user_id)) {
- $uid = $user->user_id;
- }
-
- // Return back md5 of user_id + session_id.
- return md5($uid . session_id());
-
- }
-
-
- /**
- * Implementation of hook_perm
- *
- */
- function batch_perm() {
-
- $perms = array (
- "batch_run_test" => array(
- "title" => t("Run test batch function"),
- "description" => t("This is only useful for developers. It allows a user to execute a test batch process by visiting example.com/batch-test-form in their browser."),
- ),
- );
-
- return $perms;
- }
-
-
- /**
- * A batch process is being initiated from a form submission.
- *
- * @param unknown_type $batch_id
- */
- function batch_start_batch_from_form_submit($batch_id, $redirect_path = "", $redirect_query = "") {
-
- // We need to confirm that this user is allowed to access THIS batch.
- $current_user_token = batch_get_token();
-
-
- $batch = batch_get($batch_id);
-
-
- if ($batch["token"] == $current_user_token) {
- // Yes, we can proceed!
-
- // If there isn't a finished_callback set, we will set it using fp_goto() to return to the original form's redirect path and query.
- if (!isset($batch["finished_callback"])) {
- $batch["finished_callback"] = array("fp_goto", array($redirect_path, $redirect_query));
- // Update the database...
- db_query("UPDATE batch_queue
- SET batch_data = '?'
- WHERE batch_id = '?'", serialize($batch), $batch_id);
- }
-
-
-
-
- // Let's fp_goto to our batch-processing page...
- fp_goto("batch-processing/$batch_id");
-
- }
- else {
- // No... some problem.
- fp_add_message(t("Sorry, this batch process could not be initialized. Bad token, or batch does not exist?"), "error");
- return;
- }
-
-
-
-
- }
-
-
-
-
-
Functions
Name | Description |
---|---|
batch_ajax_callback | This function is called by ajax, and will trigger each run of the batch operation function, then return appropriate results back to our javascript. |
batch_cron | Implementation of hook_cron |
batch_finished_page | We redirect to this page when we have finished a batch. |
batch_get | Return the batch_data array for this batch_id, or FALSE if it doesn't exist or can't be unserialized. |
batch_get_token | Return a token for this user. |
batch_menu | Implementation of hook_menu |
batch_perm | Implementation of hook_perm |
batch_processing_page | This is the page the user sees while a batch is being processed. |
batch_set | Create a new batch process. |
batch_start_batch_from_form_submit | A batch process is being initiated from a form submission. |