514 lines
13 KiB
Plaintext
514 lines
13 KiB
Plaintext
|
<?php
|
||
|
|
||
|
/**
|
||
|
* @file
|
||
|
* Helper module for the Batch API tests.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Implement hook_menu().
|
||
|
*/
|
||
|
function batch_test_menu() {
|
||
|
$items = array();
|
||
|
|
||
|
$items['batch-test'] = array(
|
||
|
'title' => 'Batch test',
|
||
|
'page callback' => 'drupal_get_form',
|
||
|
'page arguments' => array('batch_test_simple_form'),
|
||
|
'access callback' => TRUE,
|
||
|
);
|
||
|
// Simple form: one submit handler, setting a batch.
|
||
|
$items['batch-test/simple'] = array(
|
||
|
'title' => 'Simple',
|
||
|
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||
|
'weight' => 0,
|
||
|
);
|
||
|
// Multistep form: two steps, each setting a batch.
|
||
|
$items['batch-test/multistep'] = array(
|
||
|
'title' => 'Multistep',
|
||
|
'page callback' => 'drupal_get_form',
|
||
|
'page arguments' => array('batch_test_multistep_form'),
|
||
|
'access callback' => TRUE,
|
||
|
'type' => MENU_LOCAL_TASK,
|
||
|
'weight' => 1,
|
||
|
);
|
||
|
// Chained form: four submit handlers, several of which set a batch.
|
||
|
$items['batch-test/chained'] = array(
|
||
|
'title' => 'Chained',
|
||
|
'page callback' => 'drupal_get_form',
|
||
|
'page arguments' => array('batch_test_chained_form'),
|
||
|
'access callback' => TRUE,
|
||
|
'type' => MENU_LOCAL_TASK,
|
||
|
'weight' => 2,
|
||
|
);
|
||
|
// Programmatic form: the page submits the 'Chained' form through
|
||
|
// drupal_form_submit().
|
||
|
$items['batch-test/programmatic'] = array(
|
||
|
'title' => 'Programmatic',
|
||
|
'page callback' => 'batch_test_programmatic',
|
||
|
'access callback' => TRUE,
|
||
|
'type' => MENU_LOCAL_TASK,
|
||
|
'weight' => 3,
|
||
|
);
|
||
|
// No form: fire a batch simply by accessing a page.
|
||
|
$items['batch-test/no-form'] = array(
|
||
|
'title' => 'Simple page',
|
||
|
'page callback' => 'batch_test_no_form',
|
||
|
'access callback' => TRUE,
|
||
|
'type' => MENU_LOCAL_TASK,
|
||
|
'weight' => 4,
|
||
|
);
|
||
|
// No form: fire a batch; return > 100% complete
|
||
|
$items['batch-test/large-percentage'] = array(
|
||
|
'title' => 'Simple page with batch over 100% complete',
|
||
|
'page callback' => 'batch_test_large_percentage',
|
||
|
'access callback' => TRUE,
|
||
|
'type' => MENU_LOCAL_TASK,
|
||
|
'weight' => 5,
|
||
|
);
|
||
|
// Tests programmatic form submission within a batch operation.
|
||
|
$items['batch-test/nested-programmatic'] = array(
|
||
|
'title' => 'Nested programmatic',
|
||
|
'page callback' => 'batch_test_nested_drupal_form_submit',
|
||
|
'access callback' => TRUE,
|
||
|
'type' => MENU_LOCAL_TASK,
|
||
|
'weight' => 6,
|
||
|
);
|
||
|
// Landing page to test redirects.
|
||
|
$items['batch-test/redirect'] = array(
|
||
|
'title' => 'Redirect',
|
||
|
'page callback' => 'batch_test_redirect_page',
|
||
|
'access callback' => TRUE,
|
||
|
'type' => MENU_LOCAL_TASK,
|
||
|
'weight' => 7,
|
||
|
);
|
||
|
// This item lives under 'admin' so that the page uses the admin theme.
|
||
|
$items['admin/batch-test/test-theme'] = array(
|
||
|
'page callback' => 'batch_test_theme_batch',
|
||
|
'access callback' => TRUE,
|
||
|
'type' => MENU_CALLBACK,
|
||
|
);
|
||
|
|
||
|
return $items;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Simple form.
|
||
|
*/
|
||
|
function batch_test_simple_form() {
|
||
|
$form['batch'] = array(
|
||
|
'#type' => 'select',
|
||
|
'#title' => 'Choose batch',
|
||
|
'#options' => array(
|
||
|
'batch_0' => 'batch 0',
|
||
|
'batch_1' => 'batch 1',
|
||
|
'batch_2' => 'batch 2',
|
||
|
'batch_3' => 'batch 3',
|
||
|
'batch_4' => 'batch 4',
|
||
|
),
|
||
|
);
|
||
|
$form['submit'] = array(
|
||
|
'#type' => 'submit',
|
||
|
'#value' => 'Submit',
|
||
|
);
|
||
|
|
||
|
return $form;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Submit handler for the simple form.
|
||
|
*/
|
||
|
function batch_test_simple_form_submit($form, &$form_state) {
|
||
|
batch_test_stack(NULL, TRUE);
|
||
|
|
||
|
$function = '_batch_test_' . $form_state['values']['batch'];
|
||
|
batch_set($function());
|
||
|
|
||
|
$form_state['redirect'] = 'batch-test/redirect';
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Multistep form.
|
||
|
*/
|
||
|
function batch_test_multistep_form($form, &$form_state) {
|
||
|
if (empty($form_state['storage']['step'])) {
|
||
|
$form_state['storage']['step'] = 1;
|
||
|
}
|
||
|
|
||
|
$form['step_display'] = array(
|
||
|
'#markup' => 'step ' . $form_state['storage']['step'] . '<br/>',
|
||
|
);
|
||
|
$form['submit'] = array(
|
||
|
'#type' => 'submit',
|
||
|
'#value' => 'Submit',
|
||
|
);
|
||
|
|
||
|
return $form;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Submit handler for the multistep form.
|
||
|
*/
|
||
|
function batch_test_multistep_form_submit($form, &$form_state) {
|
||
|
batch_test_stack(NULL, TRUE);
|
||
|
|
||
|
switch ($form_state['storage']['step']) {
|
||
|
case 1:
|
||
|
batch_set(_batch_test_batch_1());
|
||
|
break;
|
||
|
case 2:
|
||
|
batch_set(_batch_test_batch_2());
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ($form_state['storage']['step'] < 2) {
|
||
|
$form_state['storage']['step']++;
|
||
|
$form_state['rebuild'] = TRUE;
|
||
|
}
|
||
|
|
||
|
// This will only be effective on the last step.
|
||
|
$form_state['redirect'] = 'batch-test/redirect';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Form with chained submit callbacks.
|
||
|
*/
|
||
|
function batch_test_chained_form() {
|
||
|
// This value is used to test that $form_state persists through batched
|
||
|
// submit handlers.
|
||
|
$form['value'] = array(
|
||
|
'#type' => 'textfield',
|
||
|
'#title' => 'Value',
|
||
|
'#default_value' => 1,
|
||
|
);
|
||
|
$form['submit'] = array(
|
||
|
'#type' => 'submit',
|
||
|
'#value' => 'Submit',
|
||
|
);
|
||
|
$form['#submit'] = array(
|
||
|
'batch_test_chained_form_submit_1',
|
||
|
'batch_test_chained_form_submit_2',
|
||
|
'batch_test_chained_form_submit_3',
|
||
|
'batch_test_chained_form_submit_4',
|
||
|
);
|
||
|
|
||
|
return $form;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Submit handler #1 for the chained form.
|
||
|
*/
|
||
|
function batch_test_chained_form_submit_1($form, &$form_state) {
|
||
|
batch_test_stack(NULL, TRUE);
|
||
|
|
||
|
batch_test_stack('submit handler 1');
|
||
|
batch_test_stack('value = ' . $form_state['values']['value']);
|
||
|
|
||
|
$form_state['values']['value']++;
|
||
|
batch_set(_batch_test_batch_1());
|
||
|
|
||
|
// This redirect should not be taken into account.
|
||
|
$form_state['redirect'] = 'should/be/discarded';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Submit handler #2 for the chained form.
|
||
|
*/
|
||
|
function batch_test_chained_form_submit_2($form, &$form_state) {
|
||
|
batch_test_stack('submit handler 2');
|
||
|
batch_test_stack('value = ' . $form_state['values']['value']);
|
||
|
|
||
|
$form_state['values']['value']++;
|
||
|
batch_set(_batch_test_batch_2());
|
||
|
|
||
|
// This redirect should not be taken into account.
|
||
|
$form_state['redirect'] = 'should/be/discarded';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Submit handler #3 for the chained form.
|
||
|
*/
|
||
|
function batch_test_chained_form_submit_3($form, &$form_state) {
|
||
|
batch_test_stack('submit handler 3');
|
||
|
batch_test_stack('value = ' . $form_state['values']['value']);
|
||
|
|
||
|
$form_state['values']['value']++;
|
||
|
|
||
|
// This redirect should not be taken into account.
|
||
|
$form_state['redirect'] = 'should/be/discarded';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Submit handler #4 for the chained form.
|
||
|
*/
|
||
|
function batch_test_chained_form_submit_4($form, &$form_state) {
|
||
|
batch_test_stack('submit handler 4');
|
||
|
batch_test_stack('value = ' . $form_state['values']['value']);
|
||
|
|
||
|
$form_state['values']['value']++;
|
||
|
batch_set(_batch_test_batch_3());
|
||
|
|
||
|
// This is the redirect that should prevail.
|
||
|
$form_state['redirect'] = 'batch-test/redirect';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Menu callback: programmatically submits the 'Chained' form.
|
||
|
*/
|
||
|
function batch_test_programmatic($value = 1) {
|
||
|
$form_state = array(
|
||
|
'values' => array('value' => $value)
|
||
|
);
|
||
|
drupal_form_submit('batch_test_chained_form', $form_state);
|
||
|
return 'Got out of a programmatic batched form.';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Menu callback: programmatically submits a form within a batch.
|
||
|
*/
|
||
|
function batch_test_nested_drupal_form_submit($value = 1) {
|
||
|
// Set the batch and process it.
|
||
|
$batch['operations'] = array(
|
||
|
array('_batch_test_nested_drupal_form_submit_callback', array($value)),
|
||
|
);
|
||
|
batch_set($batch);
|
||
|
batch_process('batch-test/redirect');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Batch operation: submits form_test_mock_form using drupal_form_submit().
|
||
|
*/
|
||
|
function _batch_test_nested_drupal_form_submit_callback($value) {
|
||
|
$state['values']['test_value'] = $value;
|
||
|
drupal_form_submit('batch_test_mock_form', $state);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* A simple form with a textfield and submit button.
|
||
|
*/
|
||
|
function batch_test_mock_form($form, $form_state) {
|
||
|
$form['test_value'] = array(
|
||
|
'#type' => 'textfield',
|
||
|
);
|
||
|
$form['submit'] = array(
|
||
|
'#type' => 'submit',
|
||
|
'#value' => t('Submit'),
|
||
|
);
|
||
|
|
||
|
return $form;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Submit handler for the batch_test_mock form.
|
||
|
*/
|
||
|
function batch_test_mock_form_submit($form, &$form_state) {
|
||
|
batch_test_stack('mock form submitted with value = ' . $form_state['values']['test_value']);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Menu callback: fire a batch process without a form submission.
|
||
|
*/
|
||
|
function batch_test_no_form() {
|
||
|
batch_test_stack(NULL, TRUE);
|
||
|
|
||
|
batch_set(_batch_test_batch_1());
|
||
|
batch_process('batch-test/redirect');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Menu callback: fire a batch process without a form submission.
|
||
|
*/
|
||
|
function batch_test_large_percentage() {
|
||
|
batch_test_stack(NULL, TRUE);
|
||
|
|
||
|
batch_set(_batch_test_batch_5());
|
||
|
batch_process('batch-test/redirect');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Menu callback: successful redirection.
|
||
|
*/
|
||
|
function batch_test_redirect_page() {
|
||
|
return 'Redirection successful.';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Batch 0: no operation.
|
||
|
*/
|
||
|
function _batch_test_batch_0() {
|
||
|
$batch = array(
|
||
|
'operations' => array(),
|
||
|
'finished' => '_batch_test_finished_0',
|
||
|
'file' => drupal_get_path('module', 'batch_test'). '/batch_test.callbacks.inc',
|
||
|
);
|
||
|
return $batch;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Batch 1: repeats a simple operation.
|
||
|
*
|
||
|
* Operations: op 1 from 1 to 10.
|
||
|
*/
|
||
|
function _batch_test_batch_1() {
|
||
|
// Ensure the batch takes at least two iterations.
|
||
|
$total = 10;
|
||
|
$sleep = (1000000 / $total) * 2;
|
||
|
|
||
|
$operations = array();
|
||
|
for ($i = 1; $i <= $total; $i++) {
|
||
|
$operations[] = array('_batch_test_callback_1', array($i, $sleep));
|
||
|
}
|
||
|
$batch = array(
|
||
|
'operations' => $operations,
|
||
|
'finished' => '_batch_test_finished_1',
|
||
|
'file' => drupal_get_path('module', 'batch_test'). '/batch_test.callbacks.inc',
|
||
|
);
|
||
|
return $batch;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Batch 2: single multistep operation.
|
||
|
*
|
||
|
* Operations: op 2 from 1 to 10.
|
||
|
*/
|
||
|
function _batch_test_batch_2() {
|
||
|
// Ensure the batch takes at least two iterations.
|
||
|
$total = 10;
|
||
|
$sleep = (1000000 / $total) * 2;
|
||
|
|
||
|
$operations = array(
|
||
|
array('_batch_test_callback_2', array(1, $total, $sleep)),
|
||
|
);
|
||
|
$batch = array(
|
||
|
'operations' => $operations,
|
||
|
'finished' => '_batch_test_finished_2',
|
||
|
'file' => drupal_get_path('module', 'batch_test') . '/batch_test.callbacks.inc',
|
||
|
);
|
||
|
return $batch;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Batch 3: both single and multistep operations.
|
||
|
*
|
||
|
* Operations:
|
||
|
* - op 1 from 1 to 5,
|
||
|
* - op 2 from 1 to 5,
|
||
|
* - op 1 from 6 to 10,
|
||
|
* - op 2 from 6 to 10.
|
||
|
*/
|
||
|
function _batch_test_batch_3() {
|
||
|
// Ensure the batch takes at least two iterations.
|
||
|
$total = 10;
|
||
|
$sleep = (1000000 / $total) * 2;
|
||
|
|
||
|
$operations = array();
|
||
|
for ($i = 1; $i <= round($total / 2); $i++) {
|
||
|
$operations[] = array('_batch_test_callback_1', array($i, $sleep));
|
||
|
}
|
||
|
$operations[] = array('_batch_test_callback_2', array(1, $total / 2, $sleep));
|
||
|
for ($i = round($total / 2) + 1; $i <= $total; $i++) {
|
||
|
$operations[] = array('_batch_test_callback_1', array($i, $sleep));
|
||
|
}
|
||
|
$operations[] = array('_batch_test_callback_2', array(6, $total / 2, $sleep));
|
||
|
$batch = array(
|
||
|
'operations' => $operations,
|
||
|
'finished' => '_batch_test_finished_3',
|
||
|
'file' => drupal_get_path('module', 'batch_test') . '/batch_test.callbacks.inc',
|
||
|
);
|
||
|
return $batch;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Batch 4: batch within a batch.
|
||
|
*
|
||
|
* Operations:
|
||
|
* - op 1 from 1 to 5,
|
||
|
* - set batch 2 (op 2 from 1 to 10, should run at the end)
|
||
|
* - op 1 from 6 to 10,
|
||
|
*/
|
||
|
function _batch_test_batch_4() {
|
||
|
// Ensure the batch takes at least two iterations.
|
||
|
$total = 10;
|
||
|
$sleep = (1000000 / $total) * 2;
|
||
|
|
||
|
$operations = array();
|
||
|
for ($i = 1; $i <= round($total / 2); $i++) {
|
||
|
$operations[] = array('_batch_test_callback_1', array($i, $sleep));
|
||
|
}
|
||
|
$operations[] = array('_batch_test_nested_batch_callback', array());
|
||
|
for ($i = round($total / 2) + 1; $i <= $total; $i++) {
|
||
|
$operations[] = array('_batch_test_callback_1', array($i, $sleep));
|
||
|
}
|
||
|
$batch = array(
|
||
|
'operations' => $operations,
|
||
|
'finished' => '_batch_test_finished_4',
|
||
|
'file' => drupal_get_path('module', 'batch_test') . '/batch_test.callbacks.inc',
|
||
|
);
|
||
|
return $batch;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Batch 5: repeats a simple operation.
|
||
|
*
|
||
|
* Operations: op 1 from 1 to 10.
|
||
|
*/
|
||
|
function _batch_test_batch_5() {
|
||
|
// Ensure the batch takes at least two iterations.
|
||
|
$total = 10;
|
||
|
$sleep = (1000000 / $total) * 2;
|
||
|
|
||
|
$operations = array();
|
||
|
for ($i = 1; $i <= $total; $i++) {
|
||
|
$operations[] = array('_batch_test_callback_5', array($i, $sleep));
|
||
|
}
|
||
|
$batch = array(
|
||
|
'operations' => $operations,
|
||
|
'finished' => '_batch_test_finished_5',
|
||
|
'file' => drupal_get_path('module', 'batch_test'). '/batch_test.callbacks.inc',
|
||
|
);
|
||
|
return $batch;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Menu callback: run a batch for testing theme used on the progress page.
|
||
|
*/
|
||
|
function batch_test_theme_batch() {
|
||
|
batch_test_stack(NULL, TRUE);
|
||
|
$batch = array(
|
||
|
'operations' => array(
|
||
|
array('_batch_test_theme_callback', array()),
|
||
|
),
|
||
|
);
|
||
|
batch_set($batch);
|
||
|
batch_process('batch-test/redirect');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Batch callback function for testing the theme used on the progress page.
|
||
|
*/
|
||
|
function _batch_test_theme_callback() {
|
||
|
// Because drupalGet() steps through the full progressive batch before
|
||
|
// returning control to the test function, we cannot test that the correct
|
||
|
// theme is being used on the batch processing page by viewing that page
|
||
|
// directly. Instead, we save the theme being used in a variable here, so
|
||
|
// that it can be loaded and inspected in the thread running the test.
|
||
|
global $theme;
|
||
|
batch_test_stack($theme);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Helper function: store or retrieve traced execution data.
|
||
|
*/
|
||
|
function batch_test_stack($data = NULL, $reset = FALSE) {
|
||
|
if ($reset) {
|
||
|
variable_del('batch_test_stack');
|
||
|
}
|
||
|
if (!isset($data)) {
|
||
|
return variable_get('batch_test_stack', array());
|
||
|
}
|
||
|
$stack = variable_get('batch_test_stack', array());
|
||
|
$stack[] = $data;
|
||
|
variable_set('batch_test_stack', $stack);
|
||
|
}
|