Preloader.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <?php
  2. namespace Elgg\Likes;
  3. class Preloader {
  4. /**
  5. * @var DataService
  6. */
  7. protected $data;
  8. public function __construct(DataService $data) {
  9. $this->data = $data;
  10. }
  11. /**
  12. * @param \ElggRiverItem[]|\ElggEntity[] $items
  13. * @return void
  14. */
  15. public function preloadForList(array $items) {
  16. $guids = $this->getGuidsToPreload($items);
  17. if (count($guids) < 2) {
  18. return;
  19. }
  20. $this->preloadCurrentUserLikes($guids);
  21. $guids_remaining = $this->preloadCountsFromHook($this->getEntities($guids));
  22. if ($guids_remaining) {
  23. $this->preloadCountsFromQuery($guids_remaining);
  24. }
  25. }
  26. /**
  27. * @param int[] $guids
  28. */
  29. protected function preloadCountsFromQuery(array $guids) {
  30. $count_rows = elgg_get_annotations(array(
  31. 'annotation_names' => 'likes',
  32. 'guids' => $guids,
  33. 'selects' => array('e.guid', 'COUNT(*) AS cnt'),
  34. 'group_by' => 'e.guid',
  35. 'callback' => false,
  36. ));
  37. foreach ($guids as $guid) {
  38. $this->data->setNumLikes($guid, 0);
  39. }
  40. foreach ($count_rows as $row) {
  41. $this->data->setNumLikes($row->guid, $row->cnt);
  42. }
  43. }
  44. /**
  45. * @param \ElggEntity[] $entities
  46. * @return int[]
  47. */
  48. protected function preloadCountsFromHook(array $entities) {
  49. $guids_not_loaded = array();
  50. foreach ($entities as $entity) {
  51. // BC with likes_count(). If this hook is used this preloader may not be of much help.
  52. $type = $entity->getType();
  53. $params = array('entity' => $entity);
  54. $num_likes = elgg_trigger_plugin_hook('likes:count', $type, $params, false);
  55. if ($num_likes) {
  56. $this->data->setNumLikes($entity->guid, $num_likes);
  57. } else {
  58. $guids_not_loaded[] = $entity->guid;
  59. }
  60. }
  61. return $guids_not_loaded;
  62. }
  63. /**
  64. * @param int[] $guids
  65. */
  66. protected function preloadCurrentUserLikes(array $guids) {
  67. $owner_guid = elgg_get_logged_in_user_guid();
  68. if (!$owner_guid) {
  69. return;
  70. }
  71. $annotation_rows = elgg_get_annotations(array(
  72. 'annotation_names' => 'likes',
  73. 'annotation_owner_guids' => $owner_guid,
  74. 'guids' => $guids,
  75. 'callback' => false,
  76. ));
  77. foreach ($guids as $guid) {
  78. $this->data->setLikedByCurrentUser($guid, false);
  79. }
  80. foreach ($annotation_rows as $row) {
  81. $this->data->setLikedByCurrentUser($row->entity_guid, true);
  82. }
  83. }
  84. /**
  85. * @param \ElggRiverItem[]|\ElggEntity[] $items
  86. * @return int[]
  87. */
  88. protected function getGuidsToPreload(array $items) {
  89. $guids = array();
  90. foreach ($items as $item) {
  91. // TODO remove duplication of @link likes_river_menu_setup()
  92. if ($item instanceof \ElggRiverItem) {
  93. // only like group creation #3958
  94. if ($item->type == "group" && $item->view != "river/group/create") {
  95. continue;
  96. }
  97. // don't like users #4116
  98. if ($item->type == "user") {
  99. continue;
  100. }
  101. if ($item->annotation_id != 0) {
  102. continue;
  103. }
  104. if ($item->object_guid) {
  105. $guids[$item->object_guid] = true;
  106. }
  107. } elseif ($item instanceof \ElggEntity) {
  108. if (!$item instanceof \ElggUser) {
  109. continue;
  110. }
  111. $guids[$item->guid] = true;
  112. }
  113. }
  114. return array_keys($guids);
  115. }
  116. /**
  117. * Get entities in any order checking cache first
  118. *
  119. * @param int[] $guids
  120. * @return \ElggEntity[]
  121. */
  122. protected function getEntities(array $guids) {
  123. // most objects are already preloaded
  124. $entities = array();
  125. $fetch_guids = array();
  126. foreach ($guids as $guid) {
  127. $entity = _elgg_retrieve_cached_entity($guid);
  128. if ($entity) {
  129. $entities[] = $entity;
  130. } else {
  131. $fetch_guids[] = $guid;
  132. }
  133. }
  134. if ($fetch_guids) {
  135. $fetched = elgg_get_entities(array(
  136. 'guids' => $fetch_guids,
  137. ));
  138. array_splice($entities, count($entities), 0, $fetched);
  139. }
  140. return $entities;
  141. }
  142. }