/[drupal]/contributions/docs/developer/examples/batch_example.module
ViewVC logotype

Contents of /contributions/docs/developer/examples/batch_example.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Mon Jun 22 20:35:24 2009 UTC (5 months ago) by jhodgdon
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +2 -2 lines
File MIME type: text/x-php
#471716 by Kiam@avpnet.org - fix error message in batch example module
1 <?php
2 // $Id: batch_example.module,v 1.4 2008/10/12 08:52:36 davereid Exp $
3
4 /**
5 * @file
6 * This is an example outlining how a module can define batches.
7 *
8 * Batches allow heavy processing to be spread out over several page
9 * requests, thus ensuring that the processing does not get interrupted
10 * because of a PHP timeout, while allowing the user to receive feedback
11 * on the progress of the ongoing operations.
12 */
13
14 /**
15 * 2 'harmless' batches are defined :
16 * batch 1 : Load 100 times the node with the lowest nid
17 * batch 2 : Load all nodes, 20 times
18 * (uses a progressive op : load nodes by groups of 5)
19 *
20 * The module defines the following pages :
21 * /batch_example/example_1 :
22 * Simple form, lets you pick the batch that should be executed
23 * /batch_example/example_2 :
24 * Multistep form : perform batch 1 and batch 2 as separate submission steps.
25 * /batch_example/example_3
26 * No form - start a batch simply by clicking a link
27 * (not really user friendly, should probably be avoided)
28 */
29
30 /**
31 * Implementation of hook_menu().
32 */
33 function batch_example_menu() {
34 $items = array();
35 $items['batch_example'] = array(
36 'title' => 'Batch example',
37 'page callback' => 'drupal_get_form',
38 'page arguments' => array('batch_example_simple_form'),
39 'access callback' => TRUE,
40 );
41 $items['batch_example/example_1'] = array(
42 'title' => 'Simple form',
43 'type' => MENU_DEFAULT_LOCAL_TASK,
44 'weight' => 0,
45 );
46 $items['batch_example/example_2'] = array(
47 'title' => 'Multistep form',
48 'page callback' => 'drupal_get_form',
49 'page arguments' => array('batch_example_multistep_form'),
50 'access callback' => TRUE,
51 'type' => MENU_LOCAL_TASK,
52 'weight' => 1,
53 );
54 $items['batch_example/example_3'] = array(
55 'title' => 'No form',
56 'page callback' => 'batch_example_page',
57 'access callback' => TRUE,
58 'type' => MENU_LOCAL_TASK,
59 'weight' => 2,
60 );
61 return $items;
62 }
63
64 /**
65 * Test 1 :
66 * Simple form
67 */
68 function batch_example_simple_form() {
69 $form['batch'] = array(
70 '#type' => 'select',
71 '#title' => 'Choose batch',
72 '#options' => array(
73 'batch_1' => 'batch 1 - load a node 100 times',
74 'batch_2' => 'batch 2 - load all nodes, 20 times')
75 );
76 $form['submit'] = array(
77 '#type' => 'submit',
78 '#value' => 'Go',
79 );
80
81 return $form;
82 }
83
84 function batch_example_simple_form_submit($form, &$form_state) {
85 $values =& $form_state['values'];
86
87 $function = 'batch_example_' . $values['batch'];
88 $batch = $function();
89 batch_set($batch);
90
91 // Redirection takes place as usual.
92 $form_state['redirect'] = 'batch_example/example_2';
93 }
94
95 /**
96 * Multistep form
97 */
98 function batch_example_multistep_form($form_state = NULL) {
99 $step = isset($form_state['storage']['step']) ? $form_state['storage']['step'] : 1;
100
101 $form['step_display'] = array(
102 '#type' => 'item',
103 '#value' => 'step ' . $step,
104 );
105
106 if ($step < 3) {
107 $form['submit'] = array(
108 '#type' => 'submit',
109 '#value' => 'Go',
110 );
111 }
112
113 return $form;
114 }
115
116 function batch_example_multistep_form_submit($form, &$form_state) {
117 $step = isset($form_state['storage']['step']) ? $form_state['storage']['step'] : 1;
118
119 switch ($step) {
120 case 1:
121 drupal_set_message('step 1 submitted');
122 batch_set(batch_example_batch_1());
123 break;
124 case 2:
125 drupal_set_message('step 2 submitted');
126 batch_set(batch_example_batch_2());
127 // this does not seem to work ?
128 $form_state['redirect'] = 'batch_example/example_3';
129 break;
130 }
131
132 $form_state['storage']['step'] = $step + 1;
133 }
134
135 function batch_example_page() {
136 batch_set(batch_example_batch_1());
137
138 // We're not inside a form submission workflow, so we have to manually
139 // trigger the batch processing - this issues a drupal_goto and thus ends
140 // current request.
141 // We also specify here where we want to redirect after batch processing.
142 batch_process('batch_example/example_1');
143 }
144
145 /**
146 * @defgroup batch_definitions Example batch definitions
147 * @{
148 * Definitions of the batches used in this module.
149 */
150
151 /**
152 * Batch 1 : Load 100 times the node with the lowest nid
153 */
154 function batch_example_batch_1() {
155 $nid = db_result(db_query_range("SELECT nid FROM {node} ORDER BY nid ASC", 0, 1));
156
157 $operations = array();
158 for ($i = 0; $i<100; $i++) {
159 $operations[] = array('batch_example_op_1', array($nid));
160 }
161 $batch = array(
162 'operations' => $operations,
163 'finished' => 'batch_example_finished',
164 );
165 return $batch;
166 }
167
168 /**
169 * Batch operation for batch 1 : lode a node...
170 */
171 function batch_example_op_1($nid, &$context) {
172 $node = node_load($nid, NULL, TRUE);
173
174 // Store some result for post-processing in the finished callback.
175 $context['results'][] = $node->nid . ' : ' . $node->title;
176
177 // Optional message displayed under the progressbar.
178 $context['message'] = 'Loading ' . $node->title;
179 }
180
181 /**
182 * Batch 2 : load all nodes 5 by 5, 20 times (Multipart operation)
183 */
184 function batch_example_batch_2() {
185 $operations = array();
186 for ($i = 0; $i<20; $i++) {
187 $operations[] = array('batch_example_op_2', array());
188 }
189 $batch = array(
190 'operations' => $operations,
191 'finished' => 'batch_example_finished',
192 // We can define custom messages instead of the default ones.
193 'title' => t('Processing batch 2'),
194 'init_message' => t('Batch 2 is starting.'),
195 'progress_message' => t('Processed @current out of @total.'),
196 'error_message' => t('Batch 2 has encountered an error.'),
197 );
198 return $batch;
199 }
200
201 /**
202 * Batch operation for batch 2 : load all nodes, 5 by five
203 * This is a multipart operation, using the
204 */
205 function batch_example_op_2(&$context) {
206 // Use the $context['sandbox'] at your convenience to store the
207 // information needed to track progression between successive calls.
208 if (!isset($context['sandbox']['progress'])) {
209 $context['sandbox']['progress'] = 0;
210 $context['sandbox']['current_node'] = 0;
211 $context['sandbox']['max'] = db_result(db_query('SELECT COUNT(DISTINCT nid) FROM {node}'));
212 }
213
214 // Process nodes by groups of 5 (arbitrary value).
215 // When a group of five is processed, the batch update engine determines
216 // whether it should continue processing in the same request or provide
217 // progress feedback to the user and wait for the next request.
218 $limit = 5;
219
220 // Retrieve the next group of nids.
221 $result = db_query_range("SELECT nid FROM {node} WHERE nid > %d ORDER BY nid ASC", $context['sandbox']['current_node'], 0, $limit);
222 while ($row = db_fetch_array($result)) {
223 // Here we actually perform our dummy 'processing' on the current node.
224 $node = node_load($row['nid'], NULL, TRUE);
225
226 // Store some result for post-processing in the finished callback.
227 $context['results'][] = $node->nid . ' : ' . $node->title;
228
229 // Update our progress information.
230 $context['sandbox']['progress']++;
231 $context['sandbox']['current_node'] = $node->nid;
232 $context['message'] = $node->title;
233 }
234
235 // Inform the batch engine that we are not finished,
236 // and provide an estimation of the completion level we reached.
237 if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
238 $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
239 }
240 }
241
242 /**
243 * Batch 'finished' callback used by both batch 1 and batch 2
244 */
245 function batch_example_finished($success, $results, $operations) {
246 if ($success) {
247 // Here we could do something meaningful with the results.
248 // We just display the number of nodes we processed...
249 $message = count($results) . ' processed.';
250 }
251 else {
252 // An error occurred.
253 // $operations contains the operations that remained unprocessed.
254 $error_operation = reset($operations);
255 $message = 'An error occurred while processing ' . $error_operation[0] . ' with arguments :' . print_r($error_operation[0], TRUE);
256 }
257 drupal_set_message($message);
258 }
259
260 /**
261 * @} End of "defgroup batch_definitions".
262 */

  ViewVC Help
Powered by ViewVC 1.1.2