-
Notifications
You must be signed in to change notification settings - Fork 1
/
views_data_export.module
300 lines (260 loc) · 8.38 KB
/
views_data_export.module
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
<?php
/**
* @file
* Provides the ability to export to specific
*/
define('VIEWS_DATA_EXPORT_HEADER', 'header');
define('VIEWS_DATA_EXPORT_BODY', 'body');
define('VIEWS_DATA_EXPORT_FOOTER', 'footer');
define('VIEWS_DATA_EXPORT_FINISHED', 'finished');
define('VIEWS_DATA_EXPORT_INDEX_TABLE_PREFIX', 'views_data_export_index_');
/**
* Implements hook_init().
*/
function views_data_export_init() {
// We have to include our theme preprocessors here until:
// http://drupal.org/node/1096770 is fixed.
module_load_include('inc', 'views_data_export', 'theme/views_data_export.theme');
}
/**
* Implementation of hook_views_api().
*/
function views_data_export_views_api() {
return array(
'api' => 2,
);
}
/**
* Implements hook_file_download().
*/
function views_data_export_file_download($filepath) {
if (views_data_export_is_export_file($filepath)) {
$result = -1;
// Allow only owners to access export files.
$file = db_fetch_object(db_query("SELECT * FROM {files} WHERE filepath = '%s'", array('%s' => $filepath)));
if ($file && $file->uid == $GLOBALS['user']->uid) {
// This is only necessary for file_download_headers() to return a result
// evaluating to TRUE, in case no other module added any header.
$result = array('X-Drupal-ViewsDataExport' => 1);
}
return $result;
}
}
/**
* Checks whether the passed URI identifies an export file.
*
* @param string $filepath
* A filepath.
*
* @return bool
* TRUE if the filepath identifies an export file, FALSE otherwise.
*/
function views_data_export_is_export_file($filepath) {
return strpos($filepath, file_directory_temp() . '/views_plugin_display') === 0;
}
/**
* Implementation of hook_theme().
*/
function views_data_export_theme() {
// Make sure that views picks up the preprocess functions.
module_load_include('inc', 'views_data_export', 'theme/views_data_export.theme');
$hooks = array();
$hooks['views_data_export_feed_icon'] = array(
'pattern' => 'views_data_export_feed_icon__',
'arguments' => array(
'image_path' => NULL,
'url' => NULL,
'query' => '',
'text' => '',
),
'file' => 'theme/views_data_export.theme.inc',
);
$hooks['views_data_export_complete_page'] = array (
'arguments' => array(
'file' => '',
'errors' => array(),
'return_url'=> '',
),
'file' => 'theme/views_data_export.theme.inc',
);
$hooks['views_data_export_message'] = array (
'arguments' => array(
'message' => '',
'type' => 'info',
),
'file' => 'theme/views_data_export.theme.inc',
);
return $hooks;
}
/**
* Implementation of hook_cron().
*/
function views_data_export_cron() {
views_data_export_garbage_collect();
}
/**
* Removes any temporary index tables that have been left
* behind. This is caused by batch processes which are
* started but never finished.
*
* Removes all trace of exports from the database that
* were created more than $expires seconds ago
*
* @param $expires
* Seconds ago. Defaults to that given in the settings.
* @param $chunk
* The number of tables to test for and delete.
* Defaults to that given in the settings. Pass -1
* for this setting to remove any restriction and to
* garbage collect all exports.
*/
function views_data_export_garbage_collect($expires = NULL, $chunk = NULL) {
if (lock_acquire('views_data_export_gc')) {
if (!isset($expires)) {
$expires = variable_get('views_data_export_gc_expires', 604800); // one week
}
if (!isset($chunk)) {
$chunk = variable_get('views_data_export_gc_chunk', 30);
}
if ($chunk == -1) {
$qry = db_query("SELECT eid FROM {views_data_export} WHERE time_stamp <= %d ORDER BY time_stamp ASC", time() - $expires);
}
else {
$qry = db_query_range("SELECT eid FROM {views_data_export} WHERE time_stamp <= %d ORDER BY time_stamp ASC", time() - $expires, 0, $chunk);
}
$eids_to_clear = array();
while ($row = db_fetch_array($qry)) {
$eids_to_clear[] = $row['eid'];
}
// We do two things to exports we want to garbage collect
// 1. Delete the index table for it, if it is still around
// 2. Delete the row from the exports table
// 3. Delete the view from the object_cache
if (count($eids_to_clear)) {
$ret = array();
foreach ($eids_to_clear as $eid) {
// 1. Delete index table, if it is still around for some reason
$table = VIEWS_DATA_EXPORT_INDEX_TABLE_PREFIX . $eid;
if (db_table_exists($table)) {
db_drop_table($ret, $table);
}
}
// 2. Delete the entries in the exports table.
db_query("DELETE FROM {views_data_export} WHERE eid IN (" . db_placeholders($eids_to_clear) . ")", $eids_to_clear);
// 3. Clear the cached views
views_data_export_view_clear($eids_to_clear);
}
lock_release('views_data_export_gc');
}
}
/**
* Batch API callback.
* Handles all batching operations by executing the appropriate view.
*/
function _views_data_export_batch_process($export_id, $display_id, $exposed_input, &$context) {
// Don't show the admin menu on batch page, some people don't like it.
if (module_exists('admin_menu')) {
module_invoke('admin_menu', 'suppress');
}
// Fetch the view in question from our cache
$view = views_data_export_view_retrieve($export_id);
$view->set_display($display_id);
if (!empty($exposed_input)) {
$view->set_exposed_input($exposed_input);
}
// Inform the data_export display which export it corresponds to and execute
if (!isset($view->display_handler->batched_execution_state)) {
$view->display_handler->batched_execution_state = new stdClass();
}
$view->display_handler->batched_execution_state->eid = $export_id;
$view->execute_display($display_id);
// Update batch api progress information
$sandbox = $view->display_handler->batched_execution_state->sandbox;
$context['finished'] = $sandbox['finished'];
$context['message'] = $sandbox['message'];
views_data_export_view_store($export_id, $view);
}
/**********/
/** CRUD **/
/**********/
/**
* Save a new export into the database.
*/
function views_data_export_new($view_name, $view_display_id, $file) {
// Insert new row into exports table
$record = (object) array(
'view_name' => $view_name,
'view_display_id' => $view_display_id,
'time_stamp' => time(),
'fid' => $file,
'batch_state' => VIEWS_DATA_EXPORT_HEADER,
'sandbox' => array(),
);
drupal_write_record('views_data_export', $record);
return $record;
}
/**
* Update an export row in the database
*/
function views_data_export_update($state) {
// Note, drupal_write_record handles serializing
// the sandbox field as per our schema definition
drupal_write_record('views_data_export', $state, 'eid');
}
/**
* Get the information about a previous export.
*/
function views_data_export_get($export_id) {
$qry = db_query("SELECT * FROM {views_data_export} WHERE eid = %d", (int)$export_id);
$object = db_fetch_object($qry);
if ($object) {
$object->sandbox = unserialize($object->sandbox);
}
return $object;
}
/**
* Remove the information about an export.
*/
function views_data_export_clear($export_id) {
db_query("DELETE FROM {views_data_export} WHERE eid = %d", $export_id);
views_data_export_view_clear($export_id);
}
/**
* Store a view in the object cache.
*/
function views_data_export_view_store($export_id, $view) {
// Store a clean copy of the view.
$_view = $view->clone_view();
views_data_export_view_clear($export_id);
$record = array(
'eid' => $export_id,
'data' => $_view,
'updated' => time(),
);
drupal_write_record('views_data_export_object_cache', $record);
}
/**
* Retrieve a view from the object cache.
*/
function views_data_export_view_retrieve($export_id) {
views_include('view');
$data = db_fetch_object(db_query("SELECT * FROM {views_data_export_object_cache} WHERE eid = '%s'", $export_id));
if ($data) {
$view = unserialize($data->data);
}
return $view;
}
/**
* Clear a view from the object cache.
*
* @param $export_id
* An export ID or an array of export IDs to clear from the object cache.
*/
function views_data_export_view_clear($export_id) {
if (is_array($export_id)) {
db_query("DELETE FROM {views_data_export_object_cache} WHERE eid IN (" . db_placeholders($export_id) . ")", $export_id);
}
else {
db_query("DELETE FROM {views_data_export_object_cache} WHERE eid = '%s'", $export_id);
}
}