11bbb5a8f2e9c2986db758dfe2057db678b3991b
[yaffs-website] / vendor / drush / drush / commands / core / drupal / batch_6.inc
1 <?php
2 /**
3  * @file
4  *   Drupal 6 engine for the Batch API
5  */
6
7 use Drush\Log\LogLevel;
8
9 /**
10  * Main loop for the Drush batch API.
11  *
12  * Saves a record of the batch into the database, and progressively call $command to
13  * process the operations.
14  *
15  * @param command
16  *    The command to call to process the batch.
17  *
18  */
19 function _drush_backend_batch_process($command = 'batch-process', $args, $options) {
20   $batch =& batch_get();
21
22   if (isset($batch)) {
23     $process_info = array(
24       'current_set' => 0,
25     );
26     $batch += $process_info;
27
28     // Initiate db storage in order to get a batch id. We have to provide
29     // at least an empty string for the (not null) 'token' column.
30     db_query("INSERT INTO {batch} (token, timestamp) VALUES ('', %d)", time());
31     $batch['id'] = db_last_insert_id('batch', 'bid');
32     $args[] = $batch['id'];
33
34     // Actually store the batch data and the token generated form the batch id.
35     db_query("UPDATE {batch} SET token = '%s', batch = '%s' WHERE bid = %d", drupal_get_token($batch['id']), serialize($batch), $batch['id']);
36
37     $finished = FALSE;
38
39     while (!$finished) {
40       $data = drush_invoke_process('@self', $command, $args, $options);
41       $finished = drush_get_error() || !$data || (isset($data['context']['drush_batch_process_finished']) && $data['context']['drush_batch_process_finished'] == TRUE);
42     }
43   }
44 }
45
46 /**
47  * Initialize the batch command and call the worker function.
48  *
49  * Loads the batch record from the database and sets up the requirements
50  * for the worker, such as registering the shutdown function.
51  *
52  * @param id
53  *   The batch id of the batch being processed.
54  */
55 function _drush_batch_command($id) {
56   $batch =& batch_get();
57   // Retrieve the current state of batch from db.
58   if ($data = db_result(db_query("SELECT batch FROM {batch} WHERE bid = %d", $id))) {
59     $batch = unserialize($data);
60   }
61   else {
62     return FALSE;
63   }
64   if (!isset($batch['running'])) {
65     $batch['running'] = TRUE;
66   }
67
68   // Register database update for end of processing.
69   register_shutdown_function('_drush_batch_shutdown');
70
71   if (_drush_batch_worker()) {
72     _drush_batch_finished();
73   }
74 }
75
76 /**
77  * Process batch operations
78  *
79  * Using the current $batch process each of the operations until the batch
80  * has been completed or half of the available memory for the process has been
81  * reached.
82  */
83 function _drush_batch_worker() {
84   $batch =& batch_get();
85   $current_set =& _batch_current_set();
86   $set_changed = TRUE;
87
88   timer_start('batch_processing');
89
90   while (!$current_set['success']) {
91     // If this is the first time we iterate this batch set in the current
92     // request, we check if it requires an additional file for functions
93     // definitions.
94     if ($set_changed && isset($current_set['file']) && is_file($current_set['file'])) {
95       include_once($current_set['file']);
96     }
97
98     $finished = 1;
99     $task_message = '';
100     if ((list($function, $args) = reset($current_set['operations'])) && function_exists($function)) {
101       // Build the 'context' array, execute the function call,
102       // and retrieve the user message.
103       $batch_context = array('sandbox' => &$current_set['sandbox'], 'results' => &$current_set['results'], 'finished' => &$finished, 'message' => &$task_message);
104       // Magic wrap to catch changes to 'message' key.
105       $batch_context = new DrushBatchContext($batch_context);
106       // Process the current operation.
107       call_user_func_array($function, array_merge($args, array(&$batch_context)));
108       $finished = $batch_context['finished'];
109     }
110
111     if ($finished >= 1) {
112       // Make sure this step isn't counted double when computing $current.
113       $finished = 0;
114       // Remove the operation and clear the sandbox.
115       array_shift($current_set['operations']);
116       $current_set['sandbox'] = array();
117     }
118
119     // If the batch set is completed, browse through the remaining sets,
120     // executing 'control sets' (stored form submit handlers) along the way -
121     // this might in turn insert new batch sets.
122     // Stop when we find a set that actually has operations.
123     $set_changed = FALSE;
124     $old_set = $current_set;
125     while (empty($current_set['operations']) && ($current_set['success'] = TRUE) && _batch_next_set()) {
126       $current_set =& _batch_current_set();
127       $set_changed = TRUE;
128     }
129     // At this point, either $current_set is a 'real' batch set (has operations),
130     // or all sets have been completed.
131
132
133     // TODO - replace with memory check!
134     // If we're in progressive mode, stop after 1 second.
135     if ((memory_get_usage() * 2) >= drush_memory_limit()) {
136       drush_log(dt("Batch process has consumed in excess of 50% of available memory. Starting new thread"), LogLevel::BATCH);
137       break;
138     }
139   }
140
141   // Gather progress information.
142
143   // Reporting 100% progress will cause the whole batch to be considered
144   // processed. If processing was paused right after moving to a new set,
145   // we have to use the info from the new (unprocessed) one.
146   if ($set_changed && isset($current_set['operations'])) {
147     // Processing will continue with a fresh batch set.
148     $remaining = count($current_set['operations']);
149     $total = $current_set['total'];
150     $task_message = '';
151   }
152   else {
153     $remaining = count($old_set['operations']);
154     $total = $old_set['total'];
155   }
156
157   $current    = $total - $remaining + $finished;
158   $percentage = $total ? floor($current / $total * 100) : 100;
159
160   return ($percentage == 100);
161 }
162
163 /**
164  * End the batch processing:
165  * Call the 'finished' callbacks to allow custom handling of results,
166  * and resolve page redirection.
167  */
168 function _drush_batch_finished() {
169   $batch =& batch_get();
170
171   // Execute the 'finished' callbacks for each batch set.
172   foreach ($batch['sets'] as $key => $batch_set) {
173     if (isset($batch_set['finished'])) {
174       // Check if the set requires an additional file for functions definitions.
175       if (isset($batch_set['file']) && is_file($batch_set['file'])) {
176         include_once($batch_set['file']);
177       }
178       if (function_exists($batch_set['finished'])) {
179         $batch_set['finished']($batch_set['success'], $batch_set['results'], $batch_set['operations']);
180       }
181     }
182   }
183
184   // Cleanup the batch table and unset the global $batch variable.
185   db_query("DELETE FROM {batch} WHERE bid = %d", $batch['id']);
186   $_batch = $batch;
187   $batch = NULL;
188   drush_set_option('drush_batch_process_finished', TRUE);
189 }
190
191 /**
192  * Shutdown function: store the batch data for next request,
193  * or clear the table if the batch is finished.
194  */
195 function _drush_batch_shutdown() {
196   if ($batch = batch_get()) {
197     db_query("UPDATE {batch} SET batch = '%s' WHERE bid = %d", serialize($batch), $batch['id']);
198   }
199 }