object-cache.inc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <?php
  2. /**
  3. * @file
  4. * The non-volatile object cache is used to store an object while it is
  5. * being edited, so that we don't have to save until we're completely
  6. * done. The cache should be 'cleaned' on a regular basis, meaning to
  7. * remove old objects from the cache, but otherwise the data in this
  8. * cache must remain stable, as it includes unsaved changes.
  9. */
  10. /**
  11. * Get an object from the non-volatile ctools cache.
  12. *
  13. * This function caches in memory as well, so that multiple calls to this
  14. * will not result in multiple database reads.
  15. *
  16. * @param $obj
  17. * A 128 character or less string to define what kind of object is being
  18. * stored; primarily this is used to prevent collisions.
  19. * @param $name
  20. * The name of the object being stored.
  21. * @param $skip_cache
  22. * Skip the memory cache, meaning this must be read from the db again.
  23. * @param $sid
  24. * The session id, allowing someone to use Session API or their own solution;
  25. * defaults to session_id().
  26. *
  27. * @deprecated $skip_cache is deprecated in favor of drupal_static*
  28. *
  29. * @return
  30. * The data that was cached.
  31. */
  32. function ctools_object_cache_get($obj, $name, $skip_cache = FALSE, $sid = NULL) {
  33. $cache = &drupal_static(__FUNCTION__, array());
  34. $key = "$obj:$name";
  35. if ($skip_cache) {
  36. unset($cache[$key]);
  37. }
  38. if (!$sid) {
  39. $sid = session_id();
  40. }
  41. if (!array_key_exists($key, $cache)) {
  42. $data = db_query('SELECT * FROM {ctools_object_cache} WHERE sid = :session_id AND obj = :object AND name = :name', array(
  43. ':session_id' => $sid,
  44. ':object' => $obj,
  45. ':name' => md5($name),
  46. ))->fetchObject();
  47. if ($data) {
  48. $cache[$key] = unserialize($data->data);
  49. }
  50. }
  51. return isset($cache[$key]) ? $cache[$key] : NULL;
  52. }
  53. /**
  54. * Store an object in the non-volatile ctools cache.
  55. *
  56. * @param $obj
  57. * A 128 character or less string to define what kind of object is being
  58. * stored; primarily this is used to prevent collisions.
  59. * @param $name
  60. * The name of the object being stored.
  61. * @param $cache
  62. * The object to be cached. This will be serialized prior to writing.
  63. * @param $sid
  64. * The session id, allowing someone to use Session API or their own solution;
  65. * defaults to session_id().
  66. */
  67. function ctools_object_cache_set($obj, $name, $cache, $sid = NULL) {
  68. // Store the CTools session id in the user session to force a
  69. // session for anonymous users in Drupal 7 and Drupal 6 Pressflow.
  70. // see http://drupal.org/node/562374, http://drupal.org/node/861778
  71. if (empty($GLOBALS['user']->uid) && empty($_SESSION['ctools_session_id'])) {
  72. $_SESSION['ctools_hold_session'] = TRUE;
  73. }
  74. ctools_object_cache_clear($obj, $name, $sid);
  75. if (!$sid) {
  76. $sid = session_id();
  77. }
  78. db_insert('ctools_object_cache')
  79. ->fields(array(
  80. 'sid' => $sid,
  81. 'obj' => $obj,
  82. 'name' => md5($name),
  83. 'data' => serialize($cache),
  84. 'updated' => REQUEST_TIME,
  85. ))
  86. ->execute();
  87. }
  88. /**
  89. * Remove an object from the non-volatile ctools cache.
  90. *
  91. * @param $obj
  92. * A 128 character or less string to define what kind of object is being
  93. * stored; primarily this is used to prevent collisions.
  94. * @param $name
  95. * The name of the object being removed.
  96. * @param $sid
  97. * The session id, allowing someone to use Session API or their own solution;
  98. * defaults to session_id().
  99. */
  100. function ctools_object_cache_clear($obj, $name, $sid = NULL) {
  101. if (!$sid) {
  102. $sid = session_id();
  103. }
  104. db_delete('ctools_object_cache')
  105. ->condition('sid', $sid)
  106. ->condition('obj', $obj)
  107. ->condition('name', md5($name))
  108. ->execute();
  109. // Ensure the static cache is emptied of this obj:name set.
  110. drupal_static_reset('ctools_object_cache_get');
  111. }
  112. /**
  113. * Determine if another user has a given object cached.
  114. *
  115. * This is very useful for 'locking' objects so that only one user can
  116. * modify them.
  117. *
  118. * @param $obj
  119. * A 128 character or less string to define what kind of object is being
  120. * stored; primarily this is used to prevent collisions.
  121. * @param $name
  122. * The name of the object being removed.
  123. * @param $sid
  124. * The session id, allowing someone to use Session API or their own solution;
  125. * defaults to session_id().
  126. *
  127. * @return
  128. * An object containing the UID and updated date if found; NULL if not.
  129. */
  130. function ctools_object_cache_test($obj, $name, $sid = NULL) {
  131. if (!$sid) {
  132. $sid = session_id();
  133. }
  134. return db_query('SELECT s.uid, c.updated FROM {ctools_object_cache} c INNER JOIN {sessions} s ON c.sid = s.sid WHERE s.sid <> :session_id AND c.obj = :obj AND c.name = :name ORDER BY c.updated ASC', array(
  135. ':session_id' => $sid,
  136. ':obj' => $obj,
  137. ':name' => md5($name),
  138. ))->fetchObject();
  139. }
  140. /**
  141. * Get the cache status of a group of objects.
  142. *
  143. * This is useful for displaying lock status when listing a number of objects
  144. * an an administration UI.
  145. *
  146. * @param $obj
  147. * A 128 character or less string to define what kind of object is being
  148. * stored; primarily this is used to prevent collisions.
  149. * @param $names
  150. * An array of names of objects
  151. *
  152. * @return
  153. * An array of objects containing the UID and updated date for each name found.
  154. */
  155. function ctools_object_cache_test_objects($obj, $names) {
  156. array_walk($names, 'md5');
  157. return db_query("SELECT c.name, s.uid, c.updated FROM {ctools_object_cache} c INNER JOIN {sessions} s ON c.sid = s.sid WHERE c.obj = :obj AND c.name IN (:names) ORDER BY c.updated ASC", array(':obj' => $obj, ':names' => $names))
  158. ->fetchAllAssoc('name');
  159. }
  160. /**
  161. * Remove an object from the non-volatile ctools cache for all session IDs.
  162. *
  163. * This is useful for clearing a lock.
  164. *
  165. * @param $obj
  166. * A 128 character or less string to define what kind of object is being
  167. * stored; primarily this is used to prevent collisions.
  168. * @param $name
  169. * The name of the object being removed.
  170. */
  171. function ctools_object_cache_clear_all($obj, $name) {
  172. db_delete('ctools_object_cache')
  173. ->condition('obj', $obj)
  174. ->condition('name', md5($name))
  175. ->execute();
  176. // Ensure the static cache is emptied of this obj:name set.
  177. $cache = &drupal_static('ctools_object_cache_get', array());
  178. unset($cache["$obj:$name"]);
  179. }
  180. /**
  181. * Remove all objects in the object cache that are older than the
  182. * specified age.
  183. *
  184. * @param $age
  185. * The minimum age of objects to remove, in seconds. For example, 86400 is
  186. * one day. Defaults to 7 days.
  187. */
  188. function ctools_object_cache_clean($age = NULL) {
  189. if (empty($age)) {
  190. // 7 days.
  191. $age = 86400 * 7;
  192. }
  193. db_delete('ctools_object_cache')
  194. ->condition('updated', REQUEST_TIME - $age, '<')
  195. ->execute();
  196. }