progress.module 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <?php
  2. /**
  3. * @file
  4. *
  5. * Progress framework for keeping track of progresses
  6. *
  7. * @todo Force MyISAM for table {progress} to avoid transaction/isolation level problems, and use INSERT DELAYED for performance?
  8. */
  9. define('PROGRESS_AGE', 86400);
  10. /**
  11. * Initialize a progress
  12. *
  13. * @param string $name
  14. * Name of progress
  15. * @param string $message
  16. * Message for progress
  17. * @return mixed
  18. * Result from db execute()
  19. */
  20. function progress_initialize_progress($name, $message) {
  21. progress_remove_progress($name);
  22. $current = microtime(TRUE);
  23. return db_insert('progress')
  24. ->fields(array(
  25. 'name' => $name,
  26. 'progress' => 0,
  27. 'message' => $message,
  28. 'start_stamp' => $current,
  29. 'current_stamp' => $current,
  30. ))
  31. ->execute();
  32. }
  33. /**
  34. * Set progress
  35. *
  36. * @param string $name
  37. * Name of progress
  38. * @param string $message
  39. * Message for progress
  40. * @param double $progress
  41. * Current progress (0 - 1)
  42. * @return mixed
  43. * Result from db execute()
  44. */
  45. function progress_set_progress($name, $message, $progress) {
  46. $current = microtime(TRUE);
  47. $result = db_update('progress')
  48. ->fields(array(
  49. 'progress' => $progress,
  50. 'message' => $message,
  51. 'current_stamp' => $current,
  52. ))
  53. ->condition('name', $name)
  54. ->execute();
  55. if (module_exists('nodejs')) {
  56. $start_stamp = db_query("SELECT start_stamp FROM {progress} WHERE name = :name", array(':name' => $name))->fetchField();
  57. $object = (object) array(
  58. 'name' => $name,
  59. 'progress' => $progress,
  60. 'message' => $message,
  61. 'current_stamp' => $current,
  62. 'start_stamp' => $start_stamp,
  63. );
  64. $message = (object) array(
  65. 'channel' => 'progress',
  66. 'data' => (object) array(
  67. 'action' => 'setProgress',
  68. 'progress' => $object,
  69. 'timestamp' => microtime(TRUE),
  70. ),
  71. 'callback' => 'nodejsProgress',
  72. );
  73. drupal_alter('progress_message', $message);
  74. nodejs_send_content_channel_message($message);
  75. }
  76. return $result;
  77. }
  78. /**
  79. * Set progress start time
  80. *
  81. * @param string $name
  82. * Name of progress
  83. * @param float $start
  84. * Start time of progress
  85. */
  86. function progress_set_progress_start($name, $start) {
  87. return db_update('progress')
  88. ->fields(array(
  89. 'start_stamp' => $start,
  90. ))
  91. ->condition('name', $name)
  92. ->execute();
  93. }
  94. /**
  95. * Set intervalled progress
  96. * Use when you don't need to spam the progress table every time.
  97. *
  98. * @param string $name
  99. * Name of progress
  100. * @param string $message
  101. * Message for progress
  102. * @param double $progress
  103. * Current progress (0 - 1)
  104. * @param double $interval
  105. * Interval in seconds
  106. * @return mixed
  107. * Result from db execute()
  108. */
  109. function progress_set_intervalled_progress($name, $message, $progress, $interval = NULL) {
  110. static $set = array();
  111. if (isset($interval, $set[$name])) {
  112. if ($set[$name] + $interval > microtime(TRUE)) {
  113. return TRUE;
  114. }
  115. }
  116. $result = progress_set_progress($name, $message, $progress);
  117. $set[$name] = microtime(TRUE);
  118. return $result;
  119. }
  120. /**
  121. * Get progress
  122. *
  123. * @param string $name
  124. * Name of progress
  125. * @return object
  126. * Object containing all the progress data
  127. */
  128. function progress_get_progress($name) {
  129. $result = db_query("SELECT name, progress, message, start_stamp, end_stamp, current_stamp FROM {progress} WHERE name = :name", array(':name' => $name))->fetchObject();
  130. if ($result) {
  131. $result->start = $result->start_stamp;
  132. $result->end = $result->end_stamp;
  133. $result->current = $result->current_stamp;
  134. }
  135. return $result;
  136. }
  137. /**
  138. * End a progress. Sets to 100% (=1)
  139. *
  140. * @param string $name
  141. * Name of progress
  142. * @param string $message
  143. * Message for progress
  144. * @return boolean
  145. * TRUE on success, FALSE on fail
  146. */
  147. function progress_end_progress($name, $message) {
  148. $current = microtime(TRUE);
  149. return db_update('progress')
  150. ->fields(array(
  151. 'progress' => 1,
  152. 'message' => $message,
  153. 'end_stamp' => $current,
  154. ))
  155. ->condition('name', $name)
  156. ->execute();
  157. }
  158. /**
  159. * Remove a progress
  160. *
  161. * @param string $name
  162. * Name of progress
  163. * @return boolean
  164. * TRUE on success, FALSE on fail
  165. */
  166. function progress_remove_progress($name) {
  167. return db_delete('progress')
  168. ->condition('name', $name)
  169. ->execute();
  170. }
  171. /**
  172. * Get all progresses
  173. *
  174. * @return array
  175. * Array of objects containing all progress data
  176. */
  177. function progress_get_progresses() {
  178. $result = db_select('progress', 'p')
  179. ->fields('p', array('name', 'progress', 'message', 'start_stamp', 'end_stamp', 'current_stamp'))
  180. ->execute();
  181. $progresses = array();
  182. foreach ($result as $progress) {
  183. $progress->start = $progress->start_stamp;
  184. $progress->end = $progress->end_stamp;
  185. $progress->current = $progress->current_stamp;
  186. $progresses[$progress->name] = $progress;
  187. }
  188. return $progresses;
  189. }
  190. /**
  191. * Estimate completion time of a progress
  192. *
  193. * @param object $progress
  194. * Progress object
  195. * @return double
  196. * Estimated unix timestamp of completion in microseconds
  197. */
  198. function progress_estimate_completion($progress) {
  199. if ($progress->progress) {
  200. $progress->estimate = $progress->start + 1 / $progress->progress * ($progress->current - $progress->start);
  201. }
  202. else {
  203. $progress->estimate = NULL;
  204. }
  205. return $progress->estimate;
  206. }
  207. /**
  208. * Implements hook_cron().
  209. *
  210. * Clean up finished progresses
  211. */
  212. function progress_cron() {
  213. return db_delete('progress')
  214. ->condition('end_stamp', 0, '>')
  215. ->condition('end_stamp', time() - variable_get('progress_age', PROGRESS_AGE), '<')
  216. ->execute();
  217. }
  218. /**
  219. * Implements hook_cronapi().
  220. */
  221. function progress_cronapi($op, $job = NULL) {
  222. switch ($op) {
  223. case 'list':
  224. return array('progress_cron' => t('Cleanup old progresses'));
  225. }
  226. }