queue_example.module

Same filename in other branches
  1. 3.x modules/queue_example/queue_example.module
  2. 4.0.x modules/queue_example/queue_example.module

Examples demonstrating the Drupal Queue API.

File

queue_example/queue_example.module

View source
<?php


/**
 * @file
 * Examples demonstrating the Drupal Queue API.
 */

/**
 * @defgroup queue_example Example: Queue
 * @ingroup examples
 * @{
 * Demonstrating the Queue API
 *
 * The Queue API provides a traditional FIFO (first-in-first-out) queue,
 * but also provides the concepts of:
 * - "Creating" a queued item, which means inserting it into a queue.
 * - "Claiming" a queued item, which essentially means requesting the next item
 *   from the queue and holding a lock on that item for a specified period of
 *   time.
 * - "Releasing" an item, which means giving up a claim but leaving the item in
 *   the queue.
 * - "Deleting" an item, which means finally removing it from the queue.
 *
 * This example demonstrates only basic queue functionality, and will use the
 * default queue implementation, which is SystemQueue, managed using
 * persistent database storage.
 *
 * Further resources include the limited @link queue @endlink documentation.
 * More:
 *
 * @link http://www.ent.iastate.edu/it/Batch_and_Queue.pdf Batch vs Queue Presentation slides by John VanDyk @endlink
 * @link http://sf2010.drupal.org/conference/sessions/batch-vs-queue-api-smackdown session video. @endlink
 *
 * @see system.queue.inc
 */

/**
 * Implements hook_menu().
 */
function queue_example_menu() {
    $items = array();
    $items['queue_example/insert_remove'] = array(
        'title' => 'Queue Example: Insert and remove',
        'page callback' => 'drupal_get_form',
        'page arguments' => array(
            'queue_example_add_remove_form',
        ),
        'access callback' => TRUE,
    );
    return $items;
}

/**
 * Form generator for managing the queue.
 *
 * Provides an interface to add items to the queue, to retrieve (claim)
 * an item from the head of the queue, and to claim and delete. Also
 * allows the user to run cron manually, so that claimed items can be
 * released.
 */
function queue_example_add_remove_form($form, &$form_state) {
    // Simple counter that makes it possible to put auto-incrementing default
    // string into the string to insert.
    if (empty($form_state['storage']['insert_counter'])) {
        $form_state['storage']['insert_counter'] = 1;
    }
    $queue_name = !empty($form_state['values']['queue_name']) ? $form_state['values']['queue_name'] : 'queue_example_first_queue';
    $items = queue_example_retrieve_queue($queue_name);
    // Add CSS to make the form a bit denser.
    $form['#attached']['css'] = array(
        drupal_get_path('module', 'queue_example') . '/queue_example.css',
    );
    $form['help'] = array(
        '#type' => 'markup',
        '#markup' => '<div>' . t('This page is an interface on the Drupal queue API. You can add new items to the queue, "claim" one (retrieve the next item and keep a lock on it), and delete one (remove it from the queue). Note that claims are not expired until cron runs, so there is a special button to run cron to perform any necessary expirations.') . '</div>',
    );
    $form['queue_name'] = array(
        '#type' => 'select',
        '#title' => t('Choose queue to examine'),
        '#options' => drupal_map_assoc(array(
            'queue_example_first_queue',
            'queue_example_second_queue',
        )),
        '#default_value' => $queue_name,
    );
    $form['queue_show'] = array(
        '#type' => 'submit',
        '#value' => t('Show queue'),
        '#submit' => array(
            'queue_example_show_queue',
        ),
    );
    $form['status_fieldset'] = array(
        '#type' => 'fieldset',
        '#title' => t('Queue status for @name', array(
            '@name' => $queue_name,
        )),
        '#collapsible' => TRUE,
    );
    $form['status_fieldset']['status'] = array(
        '#type' => 'markup',
        '#markup' => theme('queue_items', array(
            'items' => $items,
        )),
    );
    $form['insert_fieldset'] = array(
        '#type' => 'fieldset',
        '#title' => t('Insert into @name', array(
            '@name' => $queue_name,
        )),
    );
    $form['insert_fieldset']['string_to_add'] = array(
        '#type' => 'textfield',
        '#size' => 10,
        '#default_value' => t('item @counter', array(
            '@counter' => $form_state['storage']['insert_counter'],
        )),
    );
    $form['insert_fieldset']['add_item'] = array(
        '#type' => 'submit',
        '#value' => t('Insert into queue'),
        '#submit' => array(
            'queue_example_add_remove_form_insert',
        ),
    );
    $form['claim_fieldset'] = array(
        '#type' => 'fieldset',
        '#title' => t('Claim from queue'),
        '#collapsible' => TRUE,
    );
    $form['claim_fieldset']['claim_time'] = array(
        '#type' => 'radios',
        '#title' => t('Claim time, in seconds'),
        '#options' => array(
            0 => t('none'),
            5 => t('5 seconds'),
            60 => t('60 seconds'),
        ),
        '#description' => t('This time is only valid if cron runs during this time period. You can run cron manually below.'),
        '#default_value' => !empty($form_state['values']['claim_time']) ? $form_state['values']['claim_time'] : 5,
    );
    $form['claim_fieldset']['claim_item'] = array(
        '#type' => 'submit',
        '#value' => t('Claim the next item from the queue'),
        '#submit' => array(
            'queue_example_add_remove_form_claim',
        ),
    );
    $form['claim_fieldset']['claim_and_delete_item'] = array(
        '#type' => 'submit',
        '#value' => t('Claim the next item and delete it'),
        '#submit' => array(
            'queue_example_add_remove_form_delete',
        ),
    );
    $form['claim_fieldset']['run_cron'] = array(
        '#type' => 'submit',
        '#value' => t('Run cron manually to expire claims'),
        '#submit' => array(
            'queue_example_add_remove_form_run_cron',
        ),
    );
    $form['delete_queue'] = array(
        '#type' => 'submit',
        '#value' => t('Delete the queue and items in it'),
        '#submit' => array(
            'queue_example_add_remove_form_clear_queue',
        ),
    );
    return $form;
}

/**
 * Submit function for the insert-into-queue button.
 */
function queue_example_add_remove_form_insert($form, &$form_state) {
    // Get a queue (of the default type) called 'queue_example_queue'.
    // If the default queue class is SystemQueue this creates a queue that stores
    // its items in the database.
    $queue = DrupalQueue::get($form_state['values']['queue_name']);
    // There is no harm in trying to recreate existing.
    $queue->createQueue();
    // Queue the string.
    $queue->createItem($form_state['values']['string_to_add']);
    $count = $queue->numberOfItems();
    drupal_set_message(t('Queued your string (@string_to_add). There are now @count items in the queue.', array(
        '@count' => $count,
        '@string_to_add' => $form_state['values']['string_to_add'],
    )));
    // Setting 'rebuild' to TRUE allows us to keep information in $form_state.
    $form_state['rebuild'] = TRUE;
    // Unsetting the string_to_add allows us to set the incremented default value
    // for the user so they don't have to type anything.
    unset($form_state['input']['string_to_add']);
    $form_state['storage']['insert_counter']++;
}

/**
 * Submit function for the show-queue button.
 */
function queue_example_show_queue($form, &$form_state) {
    $queue = DrupalQueue::get($form_state['values']['queue_name']);
    // There is no harm in trying to recreate existing.
    $queue->createQueue();
    // Get the number of items.
    $count = $queue->numberOfItems();
    // Update the form item counter.
    $form_state['storage']['insert_counter'] = $count + 1;
    // Unset the string_to_add textbox.
    unset($form_state['input']['string_to_add']);
    $form_state['rebuild'] = TRUE;
}

/**
 * Submit function for the "claim" button.
 *
 * Claims (retrieves) an item from the queue and reports the results.
 */
function queue_example_add_remove_form_claim($form, &$form_state) {
    $queue = DrupalQueue::get($form_state['values']['queue_name']);
    // There is no harm in trying to recreate existing.
    $queue->createQueue();
    $item = $queue->claimItem($form_state['values']['claim_time']);
    $count = $queue->numberOfItems();
    if (!empty($item)) {
        drupal_set_message(t('Claimed item id=@item_id string=@string for @seconds seconds. There are @count items in the queue.', array(
            '@count' => $count,
            '@item_id' => $item->item_id,
            '@string' => $item->data,
            '@seconds' => $form_state['values']['claim_time'],
        )));
    }
    else {
        drupal_set_message(t('There were no items in the queue available to claim. There are @count items in the queue.', array(
            '@count' => $count,
        )));
    }
    $form_state['rebuild'] = TRUE;
}

/**
 * Submit function for "Claim and delete" button.
 */
function queue_example_add_remove_form_delete($form, &$form_state) {
    $queue = DrupalQueue::get($form_state['values']['queue_name']);
    // There is no harm in trying to recreate existing.
    $queue->createQueue();
    $count = $queue->numberOfItems();
    $item = $queue->claimItem(60);
    if (!empty($item)) {
        drupal_set_message(t('Claimed and deleted item id=@item_id string=@string for @seconds seconds. There are @count items in the queue.', array(
            '@count' => $count,
            '@item_id' => $item->item_id,
            '@string' => $item->data,
            '@seconds' => $form_state['values']['claim_time'],
        )));
        $queue->deleteItem($item);
        $count = $queue->numberOfItems();
        drupal_set_message(t('There are now @count items in the queue.', array(
            '@count' => $count,
        )));
    }
    else {
        $count = $queue->numberOfItems();
        drupal_set_message(t('There were no items in the queue available to claim/delete. There are currently @count items in the queue.', array(
            '@count' => $count,
        )));
    }
    $form_state['rebuild'] = TRUE;
}

/**
 * Submit function for "run cron" button.
 *
 * Runs cron (to release expired claims) and reports the results.
 */
function queue_example_add_remove_form_run_cron($form, &$form_state) {
    drupal_cron_run();
    $queue = DrupalQueue::get($form_state['values']['queue_name']);
    // There is no harm in trying to recreate existing.
    $queue->createQueue();
    $count = $queue->numberOfItems();
    drupal_set_message(t('Ran cron. If claimed items expired, they should be expired now. There are now @count items in the queue', array(
        '@count' => $count,
    )));
    $form_state['rebuild'] = TRUE;
}

/**
 * Submit handler for clearing/deleting the queue.
 */
function queue_example_add_remove_form_clear_queue($form, &$form_state) {
    $queue = DrupalQueue::get($form_state['values']['queue_name']);
    $queue->deleteQueue();
    drupal_set_message(t('Deleted the @queue_name queue and all items in it', array(
        '@queue_name' => $form_state['values']['queue_name'],
    )));
}

/**
 * Retrieves the queue from the database for display purposes only.
 *
 * It is not recommended to access the database directly, and this is only here
 * so that the user interface can give a good idea of what's going on in the
 * queue.
 *
 * @param array $queue_name
 *   The name of the queue from which to fetch items.
 */
function queue_example_retrieve_queue($queue_name) {
    $items = array();
    $result = db_query("SELECT item_id, data, expire, created FROM {queue} WHERE name = :name ORDER BY item_id", array(
        ':name' => $queue_name,
    ), array(
        'fetch' => PDO::FETCH_ASSOC,
    ));
    foreach ($result as $item) {
        $items[] = $item;
    }
    return $items;
}

/**
 * Themes the queue display.
 *
 * Again, this is not part of the demonstration of the queue API, but is here
 * just to make the user interface more understandable.
 *
 * @param array $variables
 *   Our variables.
 */
function theme_queue_items($variables) {
    $items = $variables['items'];
    $rows = array();
    foreach ($items as &$item) {
        if ($item['expire'] > 0) {
            $item['expire'] = t("Claimed: expires %expire", array(
                '%expire' => date('r', $item['expire']),
            ));
        }
        else {
            $item['expire'] = t('Unclaimed');
        }
        $item['created'] = date('r', $item['created']);
        $item['content'] = check_plain(unserialize($item['data']));
        unset($item['data']);
        $rows[] = $item;
    }
    if (!empty($rows)) {
        $header = array(
            t('Item ID'),
            t('Claimed/Expiration'),
            t('Created'),
            t('Content/Data'),
        );
        $output = theme('table', array(
            'header' => $header,
            'rows' => $rows,
        ));
        return $output;
    }
    else {
        return t('There are no items in the queue.');
    }
}

/**
 * Implements hook_theme().
 */
function queue_example_theme() {
    return array(
        'queue_items' => array(
            'variables' => array(
                'items' => NULL,
            ),
        ),
    );
}

/**
 * @} End of "defgroup queue_example".
 */

Functions

Title Deprecated Summary
queue_example_add_remove_form Form generator for managing the queue.
queue_example_add_remove_form_claim Submit function for the "claim" button.
queue_example_add_remove_form_clear_queue Submit handler for clearing/deleting the queue.
queue_example_add_remove_form_delete Submit function for "Claim and delete" button.
queue_example_add_remove_form_insert Submit function for the insert-into-queue button.
queue_example_add_remove_form_run_cron Submit function for "run cron" button.
queue_example_menu Implements hook_menu().
queue_example_retrieve_queue Retrieves the queue from the database for display purposes only.
queue_example_show_queue Submit function for the show-queue button.
queue_example_theme Implements hook_theme().
theme_queue_items Themes the queue display.