Repository navigation
Expand file tree
/
Copy pathviews_data_export.drush.inc
More file actions
362 lines (309 loc) · 11.5 KB
/
Copy pathviews_data_export.drush.inc
File metadata and controls
362 lines (309 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
<?php
/**
* Implementation of hook_drush_command().
*/
function views_data_export_drush_command() {
$items = array();
$items['views-data-export'] = array (
'aliases' => array (
'vde',
),
'description' => 'Fully executes a views_data_export display of a view and writes the output to file.',
'arguments' => array (
'view_name' => 'The name of the view',
'display_id' => 'The id of the views_data_export display to execute on the view',
'output_file' => 'The file to write the results to - will be overwritten if it already exists',
),
'options' => array (
'--format' => 'csv,doc,txt,xls or xml. These options are ignored if the display_id passed is a "views_data_export" display.',
'--separator' => 'csv only: What character separates the fields (default:,)',
'--trim-whitespace' => 'csv only: Trim whitespace from either side of fields (default:1)',
'--header-row' => 'csv only: Make the first row a row of headers (default:1)',
'--quote-values' => 'csv only: Surround each field in quotes (default:1)',
),
'examples' => array (
'drush views-data-export myviewname views_data_export_1 output.csv' => 'Export myviewname:views_data_export_1 and write the output to output.csv in the current directory',
),
'drupal dependencies' => array (
'views_data_export',
),
'core' => array('6'),
);
return $items;
}
/**
* Implementation of hook_drush_help().
*
* This function is called whenever a drush user calls
* 'drush help <name-of-your-command>'
*
* @param
* A string with the help section (prepend with 'drush:')
*
* @return
* A string with the help text for your command.
*/
function views_data_export_drush_help($section) {
switch ($section) {
case 'drush:views-data-export':
return dt("This command may be used to fully execute a views_data_export display of a view, batched if need be, and write the output to a file.");
}
}
/**
* Implementation of drush_hook_COMMAND_validate().
*/
function drush_views_data_export_validate() {
// Because of a bug in the way that Drush 4 computes the name of functions to
// call from a Drush command, we may end up getting called twice, so we just
// don't do anything on subsequent invocations.
static $already_run = FALSE;
if ($already_run) {
return;
}
$already_run = TRUE;
$args = drush_get_arguments();
array_shift($args);
if (count($args) !== 3) {
return drush_set_error('ARGUMENTS_REQUIRED', dt('All arguments are required.'));
}
if (!$view = views_get_view($args[0])) {
return drush_set_error('VIEW_DOES_NOT_EXIST', dt('The view !view does not exist.', array ('!view' => $args[0])));
}
if (!$view->set_display($args[1])) {
return drush_set_error('VIEW_DOES_NOT_EXIST', dt('The view !view does not have the !display display.', array ('!view' => $args[0], '!display' => $args[1])));
}
else {
if ($view->current_display != $args[1]) {
drush_log(dt('Using different display from specified display: @display', array('@display' => $view->current_display)), 'notice');
}
drush_set_option('views_data_export_display_id', $view->current_display);
}
$format = drush_get_option('format');
$valid_formats = array('csv', 'doc', 'txt', 'xls', 'xml');
if (!empty($format) && !in_array($format, $valid_formats)) {
return drush_set_error('VIEWS_DATA_EXPORT_INVALID_OPTION', dt('The "--format" option is invalid, please supply one of the following: !formats', array('!formats' => implode(', ', $valid_formats))));
}
}
/**
* Drush command callback to export a views data to a file.
*
* @see drush_views_data_export_validate().
* @see views_data_export_views_data_export_batch_alter().
*/
function drush_views_data_export($view_name, $display_id, $output_file) {
// Because of a bug in the way that Drush 4 computes the name of functions to
// call from a Drush command, we may end up getting called twice, so we just
// don't do anything on subsequent invocations.
static $already_run = FALSE;
if ($already_run) {
return;
}
$already_run = TRUE;
// Set the display to the one that we computed earlier.
$display_id = drush_get_option('views_data_export_display_id', 'default');
$view = views_get_view($view_name);
// If the given display_id is not views_data_alter then
// we programatically clone it to a views_data_alter display
// and then execute that one instead
if ($view->display[$display_id]->display_plugin != 'views_data_export') {
//drush_log("Display '$display_id' is not views_data_export. Making one that is and executing that instead =).", 'success');
$format = drush_get_option('format');
$settings = array();
switch ($format) {
case 'doc':
case 'xls':
case 'xml':
case 'txt':
$settings['display_options']['style_plugin'] = 'views_data_export_' . $format;
break;
case 'csv':
default:
$settings['display_options']['style_plugin'] = 'views_data_export_csv';
if ($separator = drush_get_option('separator')) {
$settings['display_options']['style_options']['separator'] = $separator;
}
if (!$trim = drush_get_option('trim-whitespace')) {
$settings['display_options']['style_options']['trim'] = 0;
}
if (!$header = drush_get_option('header-row')) {
$settings['display_options']['style_options']['header'] = 0;
}
if (!$quote = drush_get_option('quote-values')) {
$settings['display_options']['style_options']['quote'] = 0;
}
// Seperator
}
$display_id = _drush_views_data_export_clone_display($view, $display_id, $settings);
}
$view->set_display($display_id);
// We execute the view normally, and take advantage
// of an alter function to interject later and batch it ourselves
$options = array (
'output_file' => realpath(drush_get_context('DRUSH_OLDCWD', getcwd())) . '/' . $output_file,
);
_drush_views_data_export_override_batch($view_name, $display_id, $options);
$view->execute_display($display_id);
}
/**
* Helper function that indicates that we want to
* override the batch that the views_data_export view creates
* on it's initial time through.
*
* Also provides a place to stash options that need to stay around
* until the end of the batch
*/
function _drush_views_data_export_override_batch($view = NULL, $display = NULL, $options = TRUE) {
static $_views;
if (isset($view)) {
$_views[$view][$display] = $options;
}
return $_views;
}
/**
* Implementation of hook_views_data_export_batch_alter()
*/
function views_data_export_views_data_export_batch_alter(&$batch, &$final_destination, &$querystring) {
// Copy the batch, because we're going to monkey with it, a lot!
$new_batch = $batch;
$view_name = $new_batch['view_name'];
$display_id = $new_batch['display_id'];
$ok_to_override = _drush_views_data_export_override_batch();
// Make sure we do nothing if we are called not following the execution of
// our drush command. This could happen if the file with this function in it
// is included during the normal execution of the view
if (!$ok_to_override[$view_name][$display_id]) {
return;
}
$options = $ok_to_override[$view_name][$display_id];
// We actually never return from the drupal_alter, but
// use drush's batch system to run the same batch
// Add a final callback
$new_batch['operations'][] = array(
'_drush_views_data_export_batch_finished', array($batch['eid'], $options['output_file']),
);
batch_set($new_batch);
$new_batch =& batch_get();
// Drush handles the different processes, so instruct BatchAPI not to.
$new_batch['progressive'] = FALSE;
// Process the batch using drush.
drush_backend_batch_process();
// Instruct the view display plugin that it shouldn't set a batch.
$batch = array();
}
/**
* Get's called at the end of the drush batch process that generated our export
*/
function _drush_views_data_export_batch_finished($eid, $output_file, &$context) {
// Fetch export info
$export = views_data_export_get($eid);
// Perform cleanup
$view = views_data_export_view_retrieve($eid);
$view->set_display($export->view_display_id);
$view->display_handler->batched_execution_state = $export;
$view->display_handler->remove_index();
// Get path to temp file
$temp_file = $view->display_handler->outputfile_path();
// Copy file over
if (@drush_op('copy', $temp_file, $output_file)) {
drush_log("Data export saved to " . $output_file, 'success');
}
else {
drush_set_error('VIEWS_DATA_EXPORT_COPY_ERROR', dt("The file could not be copied to the selected destination"));
}
}
/**
* Helper function that takes a view and returns a clone of it
* that has cloned a given display to one of type views_data_export
*
* @param &$view
* Modified to contain the new display
*
* @return
* The new display_id
*/
function _drush_views_data_export_clone_display(&$view, $display_id, $settings = array()) {
// Create the new display
$new_display_id = _drush_views_data_export_generate_display_id($view, 'views_data_export');
$view->display[$new_display_id] = drupal_clone($view->display[$display_id]);
// Ensure we have settings we'll need for our display
$default_settings = array (
'id' => $new_display_id,
'display_plugin' => 'views_data_export',
'position' => 99,
'display_options' => array (
'style_plugin' => 'views_data_export_csv',
'style_options' => array(
'attach_text' => 'CSV',
'provide_file' => 1,
'filename' => 'view-%view.csv',
'parent_sort' => 1,
'separator' => ',',
'quote' => 1,
'trim' => 1,
'header' => 1,
),
'use_batch' => 'batch',
'path' => '',
'displays' => array (
'default' => 'default',
),
),
);
$settings = array_replace_recursive($default_settings, $settings);
$view->display[$new_display_id] = (object)array_replace_recursive((array)$view->display[$new_display_id], $settings);
return $new_display_id;
}
/**
* Generate a display id of a certain plugin type.
* See http://drupal.org/files/issues/348975-clone-display.patch
*
* @param $type
* Which plugin should be used for the new display id.
*/
function _drush_views_data_export_generate_display_id($view, $type) {
// 'default' is singular and is unique, so just go with 'default'
// for it. For all others, start counting.
if ($type == 'default') {
return 'default';
}
// Initial id.
$id = $type . '_1';
$count = 1;
// Loop through IDs based upon our style plugin name until
// we find one that is unused.
while (!empty($view->display[$id])) {
$id = $type . '_' . ++$count;
}
return $id;
}
/**
* If we're using PHP < 5.3.0 then we'll need
* to define this function ourselves.
* See: http://phpmyanmar.com/phpcodes/manual/function.array-replace-recursive.php
*/
if (!function_exists('array_replace_recursive')) {
function array_replace_recursive($array, $array1) {
// Get array arguments
$arrays = func_get_args();
// Define the original array
$original = array_shift($arrays);
// Loop through arrays
foreach ($arrays as $array) {
// Loop through array key/value pairs
foreach ($array as $key => $value) {
// Value is an array
if (is_array($value)) {
// Traverse the array; replace or add result to original array
$original[$key] = array_replace_recursive($original[$key], $array[$key]);
}
// Value is not an array
else {
// Replace or add current value to original array
$original[$key] = $value;
}
}
}
// Return the joined array
return $original;
}
}