1
|
<?php
|
2
|
|
3
|
/**
|
4
|
* @file
|
5
|
* Provides the ability to export to specific
|
6
|
*/
|
7
|
|
8
|
define('VIEWS_DATA_EXPORT_HEADER', 'header');
|
9
|
define('VIEWS_DATA_EXPORT_BODY', 'body');
|
10
|
define('VIEWS_DATA_EXPORT_FOOTER', 'footer');
|
11
|
define('VIEWS_DATA_EXPORT_FINISHED', 'finished');
|
12
|
|
13
|
define('VIEWS_DATA_EXPORT_INDEX_TABLE_PREFIX', 'views_data_export_index_');
|
14
|
|
15
|
/**
|
16
|
* Implements hook_init().
|
17
|
*/
|
18
|
function views_data_export_init() {
|
19
|
// We have to include our theme preprocessors here until:
|
20
|
// http://drupal.org/node/1096770 is fixed.
|
21
|
module_load_include('inc', 'views_data_export', 'theme/views_data_export.theme');
|
22
|
}
|
23
|
|
24
|
/**
|
25
|
* Implementation of hook_views_api().
|
26
|
*/
|
27
|
function views_data_export_views_api() {
|
28
|
return array(
|
29
|
'api' => 2,
|
30
|
);
|
31
|
}
|
32
|
|
33
|
/**
|
34
|
/**
|
35
|
* Checks whether the passed URI identifies an export file.
|
36
|
*
|
37
|
* @param string $uri
|
38
|
* A file URI.
|
39
|
*
|
40
|
* @return bool
|
41
|
* TRUE if the URI identifies an export file, FALSE otherwise.
|
42
|
*/
|
43
|
function views_data_export_is_export_file($uri) {
|
44
|
foreach (entity_load('file', FALSE, array('uri' => $uri)) as $file) {
|
45
|
// See if this is an export file.
|
46
|
$usages = file_usage_list($file);
|
47
|
return !empty($usages['views_data_export']['eid']);
|
48
|
}
|
49
|
return FALSE;
|
50
|
}
|
51
|
|
52
|
/**
|
53
|
* Implementation of hook_theme().
|
54
|
*/
|
55
|
function views_data_export_theme() {
|
56
|
// Make sure that views picks up the preprocess functions.
|
57
|
module_load_include('inc', 'views_data_export', 'theme/views_data_export.theme');
|
58
|
$hooks = array();
|
59
|
$hooks['views_data_export_feed_icon'] = array(
|
60
|
'pattern' => 'views_data_export_feed_icon__',
|
61
|
'variables' => array(
|
62
|
'image_path' => NULL,
|
63
|
'url' => NULL,
|
64
|
'query' => '',
|
65
|
'text' => '',
|
66
|
),
|
67
|
'file' => 'theme/views_data_export.theme.inc',
|
68
|
);
|
69
|
|
70
|
$hooks['views_data_export_complete_page'] = array (
|
71
|
'variables' => array(
|
72
|
'file' => '',
|
73
|
'errors' => array(),
|
74
|
'return_url'=> '',
|
75
|
),
|
76
|
'file' => 'theme/views_data_export.theme.inc',
|
77
|
);
|
78
|
|
79
|
$hooks['views_data_export_message'] = array (
|
80
|
'variables' => array(
|
81
|
'message' => '',
|
82
|
'type' => 'info',
|
83
|
),
|
84
|
'file' => 'theme/views_data_export.theme.inc',
|
85
|
);
|
86
|
|
87
|
return $hooks;
|
88
|
}
|
89
|
|
90
|
|
91
|
/**
|
92
|
* Implementation of hook_cron().
|
93
|
*/
|
94
|
function views_data_export_cron() {
|
95
|
views_data_export_garbage_collect();
|
96
|
}
|
97
|
|
98
|
/**
|
99
|
* Removes any temporary index tables that have been left
|
100
|
* behind. This is caused by batch processes which are
|
101
|
* started but never finished.
|
102
|
*
|
103
|
* Removes all trace of exports from the database that
|
104
|
* were created more than $expires seconds ago
|
105
|
*
|
106
|
* @param $expires
|
107
|
* Seconds ago. Defaults to that given in the settings.
|
108
|
* @param $chunk
|
109
|
* The number of tables to test for and delete.
|
110
|
* Defaults to that given in the settings. Pass -1
|
111
|
* for this setting to remove any restriction and to
|
112
|
* garbage collect all exports.
|
113
|
*/
|
114
|
function views_data_export_garbage_collect($expires = NULL, $chunk = NULL) {
|
115
|
if (lock_acquire('views_data_export_gc')) {
|
116
|
if (!isset($expires)) {
|
117
|
$expires = variable_get('views_data_export_gc_expires', 604800); // one week
|
118
|
}
|
119
|
if (!isset($chunk)) {
|
120
|
$chunk = variable_get('views_data_export_gc_chunk', 30);
|
121
|
}
|
122
|
|
123
|
if ($chunk == -1) {
|
124
|
$result = db_query("SELECT eid FROM {views_data_export} WHERE time_stamp <= :timestamp ORDER BY time_stamp ASC", array(':timestamp' => REQUEST_TIME - $expires));
|
125
|
}
|
126
|
else {
|
127
|
$result = db_query_range("SELECT eid FROM {views_data_export} WHERE time_stamp <= :timestamp ORDER BY time_stamp ASC", 0, $chunk, array(':timestamp' => REQUEST_TIME - $expires));
|
128
|
}
|
129
|
|
130
|
$eids_to_clear = array();
|
131
|
foreach ($result as $row) {
|
132
|
$eids_to_clear[] = $row->eid;
|
133
|
}
|
134
|
|
135
|
// We do two things to exports we want to garbage collect
|
136
|
// 1. Delete the index table for it, if it is still around.
|
137
|
// 2. Delete the files used during the export.
|
138
|
// 3. Delete the row from the exports table.
|
139
|
// 4. Delete the view from the object_cache.
|
140
|
if (count($eids_to_clear)) {
|
141
|
foreach ($eids_to_clear as $eid) {
|
142
|
// 1. Delete index table, if it is still around for some reason
|
143
|
$table = VIEWS_DATA_EXPORT_INDEX_TABLE_PREFIX . $eid;
|
144
|
if (db_table_exists($table)) {
|
145
|
db_drop_table($table);
|
146
|
}
|
147
|
|
148
|
// 2. Delete the files used during the export.
|
149
|
foreach (views_data_export_export_list_files($eid) as $file) {
|
150
|
file_delete($file, TRUE);
|
151
|
}
|
152
|
}
|
153
|
|
154
|
// 3. Delete the entries in the exports table.
|
155
|
db_delete('views_data_export')
|
156
|
->condition('eid', $eids_to_clear, 'IN')
|
157
|
->execute();
|
158
|
|
159
|
// 4. Clear the cached views
|
160
|
views_data_export_view_clear($eids_to_clear);
|
161
|
}
|
162
|
|
163
|
lock_release('views_data_export_gc');
|
164
|
}
|
165
|
}
|
166
|
|
167
|
/**
|
168
|
* Determines where a file is used.
|
169
|
*
|
170
|
* @param $eid
|
171
|
* The ID of a Views Data Export.
|
172
|
*
|
173
|
* @return array
|
174
|
* An array of loaded files objects used by the specified export.
|
175
|
*/
|
176
|
function views_data_export_export_list_files($eid) {
|
177
|
$result = db_select('file_usage', 'f')
|
178
|
->fields('f', array('fid'))
|
179
|
->condition('id', $eid)
|
180
|
->condition('type', 'eid')
|
181
|
->condition('module', 'views_data_export')
|
182
|
->execute();
|
183
|
return file_load_multiple($result->fetchCol());
|
184
|
}
|
185
|
|
186
|
|
187
|
/**
|
188
|
* Batch API callback.
|
189
|
* Handles all batching operations by executing the appropriate view.
|
190
|
*/
|
191
|
function _views_data_export_batch_process($export_id, $display_id, $exposed_input, &$context) {
|
192
|
// Don't show the admin menu on batch page, some people don't like it.
|
193
|
if (module_exists('admin_menu')) {
|
194
|
module_invoke('admin_menu', 'suppress');
|
195
|
}
|
196
|
|
197
|
// Fetch the view in question from our cache
|
198
|
$view = views_data_export_view_retrieve($export_id);
|
199
|
$view->set_display($display_id);
|
200
|
if (!empty($exposed_input)) {
|
201
|
$view->set_exposed_input($exposed_input);
|
202
|
}
|
203
|
// Inform the data_export display which export it corresponds to and execute
|
204
|
if (!isset($view->display_handler->batched_execution_state)) {
|
205
|
$view->display_handler->batched_execution_state = new stdClass();
|
206
|
}
|
207
|
$view->display_handler->batched_execution_state->eid = $export_id;
|
208
|
$view->display_handler->views_data_export_cached_view_loaded = TRUE;
|
209
|
$view->execute_display($display_id);
|
210
|
|
211
|
// Update batch api progress information
|
212
|
$sandbox = $view->display_handler->batched_execution_state->sandbox;
|
213
|
$context['finished'] = $sandbox['finished'];
|
214
|
$context['message'] = $sandbox['message'];
|
215
|
|
216
|
views_data_export_view_store($export_id, $view);
|
217
|
}
|
218
|
|
219
|
|
220
|
|
221
|
/**********/
|
222
|
/** CRUD **/
|
223
|
/**********/
|
224
|
|
225
|
/**
|
226
|
* Save a new export into the database.
|
227
|
*/
|
228
|
function views_data_export_new($view_name, $view_display_id, $file) {
|
229
|
// Insert new row into exports table
|
230
|
$record = (object) array(
|
231
|
'view_name' => $view_name,
|
232
|
'view_display_id' => $view_display_id,
|
233
|
'time_stamp' => REQUEST_TIME,
|
234
|
'fid' => $file,
|
235
|
'batch_state' => VIEWS_DATA_EXPORT_HEADER,
|
236
|
'sandbox' => array(),
|
237
|
);
|
238
|
drupal_write_record('views_data_export', $record);
|
239
|
return $record;
|
240
|
}
|
241
|
|
242
|
|
243
|
/**
|
244
|
* Update an export row in the database
|
245
|
*/
|
246
|
function views_data_export_update($state) {
|
247
|
// Note, drupal_write_record handles serializing
|
248
|
// the sandbox field as per our schema definition
|
249
|
drupal_write_record('views_data_export', $state, 'eid');
|
250
|
}
|
251
|
|
252
|
|
253
|
|
254
|
/**
|
255
|
* Get the information about a previous export.
|
256
|
*/
|
257
|
function views_data_export_get($export_id) {
|
258
|
$object = db_query("SELECT * FROM {views_data_export} WHERE eid = :eid", array(':eid' => (int)$export_id))->fetch();
|
259
|
if ($object) {
|
260
|
$object->sandbox = unserialize($object->sandbox);
|
261
|
}
|
262
|
return $object;
|
263
|
}
|
264
|
|
265
|
/**
|
266
|
* Remove the information about an export.
|
267
|
*/
|
268
|
function views_data_export_clear($export_id) {
|
269
|
db_delete('views_data_export')
|
270
|
->condition('eid', $export_id)
|
271
|
->execute();
|
272
|
views_data_export_view_clear($export_id);
|
273
|
}
|
274
|
|
275
|
|
276
|
/**
|
277
|
* Store a view in the object cache.
|
278
|
*/
|
279
|
function views_data_export_view_store($export_id, $view) {
|
280
|
// Store a clean copy of the view.
|
281
|
$_view = $view->clone_view();
|
282
|
|
283
|
views_data_export_view_clear($export_id);
|
284
|
$record = array(
|
285
|
'eid' => $export_id,
|
286
|
'data' => $_view,
|
287
|
'updated' => REQUEST_TIME,
|
288
|
);
|
289
|
drupal_write_record('views_data_export_object_cache', $record);
|
290
|
}
|
291
|
|
292
|
/**
|
293
|
* Retrieve a view from the object cache.
|
294
|
*/
|
295
|
function views_data_export_view_retrieve($export_id) {
|
296
|
views_include('view');
|
297
|
$data = db_query("SELECT * FROM {views_data_export_object_cache} WHERE eid = :eid", array(':eid' => $export_id))->fetch();
|
298
|
if ($data) {
|
299
|
$view = unserialize($data->data);
|
300
|
}
|
301
|
return $view;
|
302
|
}
|
303
|
|
304
|
/**
|
305
|
* Clear a view from the object cache.
|
306
|
*
|
307
|
* @param $export_id
|
308
|
* An export ID or an array of export IDs to clear from the object cache.
|
309
|
*/
|
310
|
function views_data_export_view_clear($export_id) {
|
311
|
db_delete('views_data_export_object_cache')
|
312
|
->condition('eid', $export_id)
|
313
|
->execute();
|
314
|
}
|