object-cache.inc 6.4 KB

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