entitycache.module

  1. cis7 sites/all/modules/ulmus/entitycache/entitycache.module
  2. cle7 sites/all/modules/ulmus/entitycache/entitycache.module
  3. ecd7 sites/all/modules/ulmus/entitycache/entitycache.module
  4. elmsmedia7 sites/all/modules/ulmus/entitycache/entitycache.module
  5. harmony7 sites/all/modules/ulmus/entitycache/entitycache.module
  6. icor7 sites/all/modules/ulmus/entitycache/entitycache.module
  7. meedjum_blog7 sites/all/modules/ulmus/entitycache/entitycache.module
  8. mooc7 sites/all/modules/ulmus/entitycache/entitycache.module

Allows for caching of core entities.

Functions

Classes

Namesort descending Description
EntityCacheControllerHelper Entity cache helper.
EntityCacheDefaultEntityController Default entity controller with persistent cache.
EntityCacheNodeController Node entity controller with persistent cache.
EntityCacheUserController User entity controller with persistent cache.

File

sites/all/modules/ulmus/entitycache/entitycache.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * Allows for caching of core entities.
  5. */
  6. /**
  7. * Implements hook_entity_info_alter().
  8. */
  9. function entitycache_entity_info_alter(&$entity_info) {
  10. foreach (entitycache_supported_core_entities(TRUE) as $type => $controller) {
  11. $entity_info[$type]['field cache'] = FALSE;
  12. $entity_info[$type]['entity cache'] = TRUE;
  13. $entity_info[$type]['controller class'] = $controller;
  14. }
  15. }
  16. /**
  17. * Entity cache helper.
  18. *
  19. * Note: while this class is not a real entity controller it needs to extend
  20. * DrupalDefaultEntityController to get access to protected properties.
  21. */
  22. class EntityCacheControllerHelper extends DrupalDefaultEntityController {
  23. public static function resetEntityCache($controller, array $ids = NULL) {
  24. // Reset the persistent cache.
  25. if (!empty($ids)) {
  26. cache_clear_all($ids, 'cache_entity_' . $controller->entityType);
  27. }
  28. else {
  29. // Force all cached entries to be deleted.
  30. cache_clear_all('*', 'cache_entity_' . $controller->entityType, TRUE);
  31. }
  32. // Give modules the chance to act on any entity.
  33. foreach (module_implements('entitycache_reset') as $module) {
  34. $function = $module . '_entitycache_reset';
  35. $function($ids, $controller->entityType);
  36. }
  37. // Give modules the chance to act on a specific entity type.
  38. foreach (module_implements('entitycache_' . $controller->entityType . '_reset') as $module) {
  39. $function = $module . '_entitycache_' . $controller->entityType . '_reset';
  40. $function($ids);
  41. }
  42. }
  43. public static function entityCacheLoad($controller, $ids = array(), $conditions = array()) {
  44. $entities = array();
  45. $cached_entities = array();
  46. $queried_entities = array();
  47. // Revisions are not statically cached, and require a different query to
  48. // other conditions, so separate the revision id into its own variable.
  49. if ($controller->revisionKey && isset($conditions[$controller->revisionKey])) {
  50. $revision_id = $conditions[$controller->revisionKey];
  51. unset($conditions[$controller->revisionKey]);
  52. }
  53. else {
  54. $revision_id = FALSE;
  55. }
  56. // Create a new variable which is either a prepared version of the $ids
  57. // array for later comparison with the entity cache, or FALSE if no $ids
  58. // were passed. The $ids array is reduced as items are loaded from cache,
  59. // and we need to know if it's empty for this reason to avoid querying the
  60. // database when all requested entities are loaded from cache.
  61. $passed_ids = !empty($ids) ? array_flip($ids) : FALSE;
  62. // Try to load entities from the static cache, if the entity type supports
  63. // static caching.
  64. if ($controller->cache && !$revision_id) {
  65. $entities += $controller->cacheGet($ids, $conditions);
  66. // If any entities were loaded, remove them from the ids still to load.
  67. if ($passed_ids) {
  68. $ids = array_keys(array_diff_key($passed_ids, $entities));
  69. }
  70. }
  71. if (!empty($controller->entityInfo['entity cache']) && !$revision_id && $ids && !$conditions) {
  72. $entities += $cached_entities = self::entityCacheGet($controller, $ids, $conditions);
  73. // If any entities were loaded, remove them from the ids still to load.
  74. $ids = array_diff($ids, array_keys($cached_entities));
  75. if ($controller->cache) {
  76. // Add entities to the cache if we are not loading a revision.
  77. if (!empty($cached_entities) && !$revision_id) {
  78. $controller->cacheSet($cached_entities);
  79. }
  80. }
  81. }
  82. // Load any remaining entities from the database. This is the case if $ids
  83. // is set to FALSE (so we load all entities), if there are any ids left to
  84. // load, if loading a revision, or if $conditions was passed without $ids.
  85. if ($ids === FALSE || $ids || $revision_id || ($conditions && !$passed_ids)) {
  86. // Build the query.
  87. $query = $controller->buildQuery($ids, $conditions, $revision_id);
  88. $queried_entities = $query
  89. ->execute()
  90. ->fetchAllAssoc($controller->idKey);
  91. }
  92. // Pass all entities loaded from the database through $controller->attachLoad(),
  93. // which attaches fields (if supported by the entity type) and calls the
  94. // entity type specific load callback, for example hook_node_load().
  95. if (!empty($queried_entities)) {
  96. $controller->attachLoad($queried_entities, $revision_id);
  97. $entities += $queried_entities;
  98. }
  99. if (!empty($controller->entityInfo['entity cache'])) {
  100. // Add entities to the entity cache if we are not loading a revision.
  101. if (!empty($queried_entities) && !$revision_id) {
  102. self::entityCacheSet($controller, $queried_entities);
  103. }
  104. }
  105. if ($controller->cache) {
  106. // Add entities to the cache if we are not loading a revision.
  107. if (!empty($queried_entities) && !$revision_id) {
  108. $controller->cacheSet($queried_entities);
  109. }
  110. }
  111. // Ensure that the returned array is ordered the same as the original
  112. // $ids array if this was passed in and remove any invalid ids.
  113. if ($passed_ids) {
  114. // Remove any invalid ids from the array.
  115. $passed_ids = array_intersect_key($passed_ids, $entities);
  116. foreach ($entities as $entity) {
  117. $passed_ids[$entity->{$controller->idKey}] = $entity;
  118. }
  119. $entities = $passed_ids;
  120. }
  121. return $entities;
  122. }
  123. public static function entityCacheGet($controller, $ids, $conditions = array()) {
  124. $cached_entities = array();
  125. if ($ids && !$conditions) {
  126. $cached = cache_get_multiple($ids, 'cache_entity_' . $controller->entityType);
  127. if ($cached) {
  128. foreach ($cached as $item) {
  129. $cached_entities[$item->cid] = $item->data;
  130. }
  131. self::entityCacheAttachLoad($controller, $cached_entities);
  132. }
  133. }
  134. return $cached_entities;
  135. }
  136. public static function entityCacheSet($controller, $entities) {
  137. foreach ($entities as $item) {
  138. cache_set($item->{$controller->idKey}, $item, 'cache_entity_' . $controller->entityType);
  139. }
  140. }
  141. /**
  142. * Allow modules to implement uncached entity hooks.
  143. *
  144. * Perform two additional hook invocations for modules needing to add
  145. * uncacheable data to objects while serving the request.
  146. *
  147. * @see entitycache_entitycache_node_load()
  148. */
  149. public static function entityCacheAttachLoad($controller, $entities) {
  150. // Give modules the chance to act on any entity.
  151. foreach (module_implements('entitycache_load') as $module) {
  152. $function = $module . '_entitycache_load';
  153. $function($entities, $controller->entityType);
  154. }
  155. // Give modules the chance to act on a specific entity type.
  156. foreach (module_implements('entitycache_' . $controller->entityType . '_load') as $module) {
  157. $function = $module . '_entitycache_' . $controller->entityType . '_load';
  158. $function($entities);
  159. }
  160. }
  161. }
  162. /**
  163. * Default entity controller with persistent cache.
  164. */
  165. class EntityCacheDefaultEntityController extends DrupalDefaultEntityController {
  166. public function resetCache(array $ids = NULL) {
  167. EntityCacheControllerHelper::resetEntityCache($this, $ids);
  168. parent::resetCache($ids);
  169. }
  170. public function load($ids = array(), $conditions = array()) {
  171. return EntityCacheControllerHelper::entityCacheLoad($this, $ids, $conditions);
  172. }
  173. }
  174. /**
  175. * Node entity controller with persistent cache.
  176. */
  177. class EntityCacheNodeController extends NodeController {
  178. public function resetCache(array $ids = NULL) {
  179. EntityCacheControllerHelper::resetEntityCache($this, $ids);
  180. parent::resetCache($ids);
  181. }
  182. public function load($ids = array(), $conditions = array()) {
  183. return EntityCacheControllerHelper::entityCacheLoad($this, $ids, $conditions);
  184. }
  185. }
  186. /**
  187. * Implements hook_flush_caches().
  188. */
  189. function entitycache_flush_caches() {
  190. $bins = array();
  191. $entities = entitycache_supported_core_entities(TRUE);
  192. foreach (array_keys($entities) as $type) {
  193. $bins[] = 'cache_entity_' . $type;
  194. }
  195. return $bins;
  196. }
  197. /**
  198. * User entity controller with persistent cache.
  199. */
  200. class EntityCacheUserController extends UserController {
  201. public function resetCache(array $ids = NULL) {
  202. EntityCacheControllerHelper::resetEntityCache($this, $ids);
  203. parent::resetCache($ids);
  204. }
  205. public function load($ids = array(), $conditions = array()) {
  206. return EntityCacheControllerHelper::entityCacheLoad($this, $ids, $conditions);
  207. }
  208. }
  209. /**
  210. * Helper function to list all supported core entities.
  211. *
  212. * @param $enabled
  213. * If set, only return enabled modules.
  214. *
  215. * @return
  216. * An array of core entities.
  217. */
  218. function entitycache_supported_core_entities($enabled = FALSE) {
  219. $return = array(
  220. 'comment' => 'EntityCacheCommentController',
  221. 'file' => 'EntityCacheDefaultEntityController',
  222. 'node' => 'EntityCacheNodeController',
  223. 'taxonomy_term' => 'EntityCacheTaxonomyTermController',
  224. 'taxonomy_vocabulary' => 'EntityCacheTaxonomyVocabularyController',
  225. 'user' => 'EntityCacheUserController',
  226. );
  227. // If the $enabled param is past, remove modules from the array if they're
  228. // not enabled.
  229. if ($enabled) {
  230. if (!module_exists('comment')) {
  231. unset($return['comment']);
  232. }
  233. if (!module_exists('taxonomy')) {
  234. unset($return['taxonomy_term']);
  235. unset($return['taxonomy_vocabulary']);
  236. }
  237. $return = array_diff_key($return, drupal_map_assoc(variable_get('entitycache_disabled_entity_types', array())));
  238. }
  239. return $return;
  240. }
  241. /**
  242. * Implements hook_entity_insert().
  243. */
  244. function entitycache_entity_insert($entity, $type) {
  245. // It is possible for other _insert() hooks to load an entity before it has
  246. // been properly saved, for example file_field_insert(). This may cause
  247. // an incomplete entity to be cached, since hooks which run after the one
  248. // loading the entity do not have a chance to run. Therefore ensure the cache
  249. // is always cleared when inserting new entities.
  250. // Since hook_entity_insert() runs last, there's a good chance of acting
  251. // after other modules are finished loading.
  252. $info = entity_get_info($type);
  253. list($id) = entity_extract_ids($type, $entity);
  254. if (!empty($info['entity cache']) && empty($entity->migrate)) {
  255. // file_field_insert() no longer exists. Don't take this out
  256. // just yet though because other modules might also misbehave.
  257. // cache_clear_all($id, 'cache_entity_' . $type);
  258. }
  259. }
  260. /**
  261. * Implements hook_entity_delete().
  262. */
  263. function entitycache_entity_delete($entity, $type) {
  264. $info = entity_get_info($type);
  265. list($id) = entity_extract_ids($type, $entity);
  266. if (!empty($info['entity cache'])) {
  267. cache_clear_all($id, 'cache_entity_' . $type);
  268. }
  269. }
  270. /**
  271. * Implements hook_entity_update().
  272. */
  273. function entitycache_entity_update($entity, $type) {
  274. // It is possible for other _update() hooks to load an entity before it has
  275. // been properly saved, for example file_field_update(). This may cause
  276. // an incomplete entity to be cached, since hooks which run after the one
  277. // loading the entity do not have a chance to run. Therefore ensure the cache
  278. // is always cleared when updating entities.
  279. // Since hook_entity_insert() runs last, there's a good chance of acting
  280. // after other modules are finished loading.
  281. $info = entity_get_info($type);
  282. list($id) = entity_extract_ids($type, $entity);
  283. if (!empty($info['entity cache']) && empty($entity->migrate)) {
  284. cache_clear_all($id, 'cache_entity_' . $type);
  285. }
  286. }
  287. /**
  288. * Implements hook_entitycache_node_load().
  289. *
  290. * This forces book information to be added on each request, to avoid expensive
  291. * cache clears.
  292. */
  293. function book_entitycache_node_load($nodes) {
  294. book_node_load($nodes, array());
  295. }
  296. /**
  297. * Implements hook_entitycache_node_load().
  298. *
  299. * This forces poll information to be loaded on each request, since it loads
  300. * user-specific information during the request.
  301. */
  302. function poll_entitycache_node_load($nodes) {
  303. $polls = array();
  304. foreach ($nodes as $node) {
  305. if ($node->type == 'poll') {
  306. $polls[$node->nid] = $node;
  307. }
  308. }
  309. if (!empty($polls)) {
  310. poll_load($polls);
  311. }
  312. }
  313. /**
  314. * Implements hook_comment_publish().
  315. *
  316. * @todo: core should not call this hook outside of a comment_save().
  317. */
  318. function entitycache_comment_publish($comment) {
  319. if (empty($comment->migrate)) {
  320. cache_clear_all($comment->cid, 'cache_entity_comment');
  321. cache_clear_all($comment->nid, 'cache_entity_node');
  322. }
  323. }
  324. /**
  325. * Implements hook_comment_unpublish().
  326. *
  327. * @todo: core should not call this hook outside of a comment_save().
  328. */
  329. function entitycache_comment_unpublish($comment) {
  330. if (empty($comment->migrate)) {
  331. cache_clear_all($comment->cid, 'cache_entity_comment');
  332. cache_clear_all($comment->nid, 'cache_entity_node');
  333. }
  334. }
  335. /**
  336. * Implements hook_comment_insert().
  337. */
  338. function entitycache_comment_insert($comment) {
  339. cache_clear_all($comment->nid, 'cache_entity_node');
  340. }
  341. /**
  342. * Implements hook_comment_update().
  343. */
  344. function entitycache_comment_update($comment) {
  345. cache_clear_all($comment->nid, 'cache_entity_node');
  346. }
  347. /**
  348. * Implements hook_entitycache_ENTITY_TYPE_load().
  349. */
  350. function entitycache_entitycache_comment_load($comments) {
  351. foreach ($comments as $comment) {
  352. $comment->new = $comment->new = node_mark($comment->nid, $comment->changed);
  353. }
  354. }
  355. /**
  356. * Implements hook_comment_update().
  357. */
  358. function entitycache_comment_delete($comment) {
  359. cache_clear_all($comment->nid, 'cache_entity_node');
  360. }
  361. /**
  362. * Implements hook_user_cancel().
  363. */
  364. function entitycache_user_cancel($edit, $account, $method) {
  365. cache_clear_all($account->uid, 'cache_entity_user');
  366. }
  367. /**
  368. * Implements hook_user_logout().
  369. */
  370. function entitycache_user_logout($account) {
  371. cache_clear_all($account->uid, 'cache_entity_user');
  372. }
  373. /**
  374. * Implements hook_user_login().
  375. */
  376. function entitycache_user_login(&$edit, $account) {
  377. cache_clear_all($account->uid, 'cache_entity_user');
  378. }
Error | ELMSLN API

Error

×

Error message

  • Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/elmsln_community/api.elmsln.org/includes/common.inc:2791) in drupal_send_headers() (line 1499 of /var/www/html/elmsln_community/api.elmsln.org/includes/bootstrap.inc).
  • Error: Call to undefined function apc_delete() in DrupalAPCCache->clear() (line 289 of /var/www/html/elmsln_community/api.elmsln.org/sites/all/modules/apc/drupal_apc_cache.inc).
The website encountered an unexpected error. Please try again later.