views_data_export.module 7.3 KB

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