object-cache.inc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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(':session_id' => $sid, ':object' => $obj, ':name' => $name))
  43. ->fetchObject();
  44. if ($data) {
  45. $cache[$key] = unserialize($data->data);
  46. }
  47. }
  48. return isset($cache[$key]) ? $cache[$key] : NULL;
  49. }
  50. /**
  51. * Store an object in the non-volatile ctools cache.
  52. *
  53. * @param $obj
  54. * A 128 character or less string to define what kind of object is being
  55. * stored; primarily this is used to prevent collisions.
  56. * @param $name
  57. * The name of the object being stored.
  58. * @param $cache
  59. * The object to be cached. This will be serialized prior to writing.
  60. * @param $sid
  61. * The session id, allowing someone to use Session API or their own solution;
  62. * defaults to session_id().
  63. */
  64. function ctools_object_cache_set($obj, $name, $cache, $sid = NULL) {
  65. // Store the CTools session id in the user session to force a
  66. // session for anonymous users in Drupal 7 and Drupal 6 Pressflow.
  67. // see http://drupal.org/node/562374, http://drupal.org/node/861778
  68. if (empty($GLOBALS['user']->uid) && empty($_SESSION['ctools_session_id'])) {
  69. $_SESSION['ctools_hold_session'] = TRUE;
  70. }
  71. ctools_object_cache_clear($obj, $name, $sid);
  72. if (!$sid) {
  73. $sid = session_id();
  74. }
  75. db_insert('ctools_object_cache')
  76. ->fields(array(
  77. 'sid' => $sid,
  78. 'obj' => $obj,
  79. 'name' => $name,
  80. 'data' => serialize($cache),
  81. 'updated' => REQUEST_TIME,
  82. ))
  83. ->execute();
  84. }
  85. /**
  86. * Remove an object from the non-volatile ctools cache.
  87. *
  88. * @param $obj
  89. * A 128 character or less string to define what kind of object is being
  90. * stored; primarily this is used to prevent collisions.
  91. * @param $name
  92. * The name of the object being removed.
  93. * @param $sid
  94. * The session id, allowing someone to use Session API or their own solution;
  95. * defaults to session_id().
  96. */
  97. function ctools_object_cache_clear($obj, $name, $sid = NULL) {
  98. if (!$sid) {
  99. $sid = session_id();
  100. }
  101. db_delete('ctools_object_cache')
  102. ->condition('sid', $sid)
  103. ->condition('obj', $obj)
  104. ->condition('name', $name)
  105. ->execute();
  106. // Ensure the static cache is emptied of this obj:name set.
  107. drupal_static_reset('ctools_object_cache_get');
  108. }
  109. /**
  110. * Determine if another user has a given object cached.
  111. *
  112. * This is very useful for 'locking' objects so that only one user can
  113. * modify them.
  114. *
  115. * @param $obj
  116. * A 128 character or less string to define what kind of object is being
  117. * stored; primarily this is used to prevent collisions.
  118. * @param $name
  119. * The name of the object being removed.
  120. * @param $sid
  121. * The session id, allowing someone to use Session API or their own solution;
  122. * defaults to session_id().
  123. *
  124. * @return
  125. * An object containing the UID and updated date if found; NULL if not.
  126. */
  127. function ctools_object_cache_test($obj, $name, $sid = NULL) {
  128. if (!$sid) {
  129. $sid = session_id();
  130. }
  131. 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(':session_id' => $sid, ':obj' => $obj, ':name' => $name))
  132. ->fetchObject();
  133. }
  134. /**
  135. * Get the cache status of a group of objects.
  136. *
  137. * This is useful for displaying lock status when listing a number of objects
  138. * an an administration UI.
  139. *
  140. * @param $obj
  141. * A 128 character or less string to define what kind of object is being
  142. * stored; primarily this is used to prevent collisions.
  143. * @param $names
  144. * An array of names of objects
  145. *
  146. * @return
  147. * An array of objects containing the UID and updated date for each name found.
  148. */
  149. function ctools_object_cache_test_objects($obj, $names) {
  150. 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))
  151. ->fetchAllAssoc('name');
  152. }
  153. /**
  154. * Remove an object from the non-volatile ctools cache for all session IDs.
  155. *
  156. * This is useful for clearing a lock.
  157. *
  158. * @param $obj
  159. * A 128 character or less string to define what kind of object is being
  160. * stored; primarily this is used to prevent collisions.
  161. * @param $name
  162. * The name of the object being removed.
  163. */
  164. function ctools_object_cache_clear_all($obj, $name) {
  165. db_delete('ctools_object_cache')
  166. ->condition('obj', $obj)
  167. ->condition('name', $name)
  168. ->execute();
  169. // Ensure the static cache is emptied of this obj:name set.
  170. $cache = &drupal_static('ctools_object_cache_get', array());
  171. unset($cache["$obj:$name"]);
  172. }
  173. /**
  174. * Remove all objects in the object cache that are older than the
  175. * specified age.
  176. *
  177. * @param $age
  178. * The minimum age of objects to remove, in seconds. For example, 86400 is
  179. * one day. Defaults to 7 days.
  180. */
  181. function ctools_object_cache_clean($age = NULL) {
  182. if (empty($age)) {
  183. // 7 days.
  184. $age = 86400 * 7;
  185. }
  186. db_delete('ctools_object_cache')
  187. ->condition('updated', REQUEST_TIME - $age, '<')
  188. ->execute();
  189. }