jsonsearchresultslist.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. // This file is part of GNU social - https://www.gnu.org/software/social
  3. //
  4. // GNU social is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // GNU social is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with GNU social. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Widget for displaying a list of notices.
  18. *
  19. * @category Search
  20. * @package GNUsocial
  21. * @author Zach Copley <zach@status.net>
  22. * @copyright 2009 StatusNet, Inc.
  23. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  24. */
  25. defined('GNUSOCIAL') || die();
  26. /**
  27. * Widget-like class for showing JSON search results.
  28. *
  29. * @category Search
  30. * @package GNUsocial
  31. * @author Zach Copley <zach@status.net>
  32. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  33. *
  34. */
  35. class JSONSearchResultsList
  36. {
  37. protected $notice; // protected attrs invisible to json_encode()
  38. protected $rpp;
  39. // The below attributes are carefully named so the JSON output from
  40. // this obj matches the output from search.twitter.com
  41. public $results;
  42. public $since_id;
  43. public $max_id;
  44. public $refresh_url;
  45. public $results_per_page;
  46. public $completed_in;
  47. public $page;
  48. public $query;
  49. /**
  50. * constructor
  51. *
  52. * @param Notice $notice stream of notices from DB_DataObject
  53. * @param string $query the original search query
  54. * @param int $rpp the number of results to display per page
  55. * @param int $page a page offset
  56. * @param int $since_id only display notices newer than this
  57. */
  58. public function __construct($notice, $query, $rpp, $page, $since_id = 0)
  59. {
  60. $this->notice = $notice;
  61. $this->query = urlencode($query);
  62. $this->results_per_page = $rpp;
  63. $this->rpp = $rpp;
  64. $this->page = $page;
  65. $this->since_id = $since_id;
  66. $this->results = array();
  67. }
  68. /**
  69. * show the list of search results
  70. *
  71. * @return int $count of the search results listed.
  72. */
  73. public function show()
  74. {
  75. $cnt = 0;
  76. $this->max_id = 0;
  77. $time_start = hrtime(true);
  78. while ($this->notice->fetch() && $cnt <= $this->rpp) {
  79. $cnt++;
  80. // XXX: Hmmm. this depends on desc sort order
  81. if (!$this->max_id) {
  82. $this->max_id = (int)$this->notice->id;
  83. }
  84. if ($this->since_id && $this->notice->id <= $this->since_id) {
  85. break;
  86. }
  87. if ($cnt > $this->rpp) {
  88. break;
  89. }
  90. $profile = $this->notice->getProfile();
  91. // Don't show notices from deleted users
  92. if (!empty($profile)) {
  93. $item = new ResultItem($this->notice);
  94. array_push($this->results, $item);
  95. }
  96. }
  97. $time_end = hrtime(true);
  98. $this->completed_in = ($time_end - $time_start) / 1000000000;
  99. // Set other attrs
  100. $this->refresh_url = '?since_id=' . $this->max_id .
  101. '&q=' . $this->query;
  102. // pagination stuff
  103. if ($cnt > $this->rpp) {
  104. $this->next_page = '?page=' . ($this->page + 1) .
  105. '&max_id=' . $this->max_id;
  106. if ($this->rpp != 15) {
  107. $this->next_page .= '&rpp=' . $this->rpp;
  108. }
  109. $this->next_page .= '&q=' . $this->query;
  110. }
  111. if ($this->page > 1) {
  112. $this->previous_page = '?page=' . ($this->page - 1) .
  113. '&max_id=' . $this->max_id;
  114. if ($this->rpp != 15) {
  115. $this->previous_page .= '&rpp=' . $this->rpp;
  116. }
  117. $this->previous_page .= '&q=' . $this->query;
  118. }
  119. print json_encode($this);
  120. return $cnt;
  121. }
  122. }
  123. /**
  124. * Widget for displaying a single JSON search result.
  125. *
  126. * @category UI
  127. * @package GNUsocial
  128. * @author Zach Copley <zach@status.net>
  129. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  130. * @see JSONSearchResultsList
  131. */
  132. class ResultItem
  133. {
  134. /** The notice this item is based on. */
  135. protected $notice; // protected attrs invisible to json_encode()
  136. /** The profile associated with the notice. */
  137. protected $profile;
  138. // The below attributes are carefully named so the JSON output from
  139. // this obj matches the output from search.twitter.com
  140. public $text;
  141. public $to_user_id;
  142. public $to_user;
  143. public $from_user;
  144. public $id;
  145. public $from_user_id;
  146. public $iso_language_code;
  147. public $source = null;
  148. public $source_link = null;
  149. public $profile_image_url;
  150. public $created_at;
  151. /**
  152. * constructor
  153. *
  154. * Also initializes the profile attribute.
  155. *
  156. * @param Notice $notice The notice we'll display
  157. */
  158. public function __construct($notice)
  159. {
  160. $this->notice = $notice;
  161. $this->profile = $notice->getProfile();
  162. $this->buildResult();
  163. }
  164. /**
  165. * Build a search result object
  166. *
  167. * This populates the the result in preparation for JSON encoding.
  168. *
  169. * @return void
  170. */
  171. public function buildResult()
  172. {
  173. $this->text = $this->notice->content;
  174. $replier_profile = null;
  175. if ($this->notice->reply_to) {
  176. $reply = Notice::getKV(intval($this->notice->reply_to));
  177. if ($reply) {
  178. $replier_profile = $reply->getProfile();
  179. }
  180. }
  181. $this->to_user_id = ($replier_profile) ?
  182. intval($replier_profile->id) : null;
  183. $this->to_user = ($replier_profile) ?
  184. $replier_profile->nickname : null;
  185. $this->from_user = $this->profile->nickname;
  186. $this->id = $this->notice->id;
  187. $this->from_user_id = $this->profile->id;
  188. $this->iso_language_code = Profile_prefs::getConfigData($this->profile, 'site', 'language');
  189. // set source and source_link
  190. $this->setSourceData();
  191. $this->profile_image_url = $this->profile->avatarUrl(AVATAR_STREAM_SIZE);
  192. $this->created_at = common_date_rfc2822($this->notice->created);
  193. }
  194. /**
  195. * Set the notice's source data (api/app name and URL)
  196. *
  197. * Either the name (and link) of the API client that posted the notice,
  198. * or one of other other channels. Uses the local notice object.
  199. *
  200. * @return void
  201. */
  202. public function setSourceData()
  203. {
  204. $source = null;
  205. $source_link = null;
  206. switch ($source) {
  207. case 'web':
  208. case 'xmpp':
  209. case 'mail':
  210. case 'omb':
  211. case 'api':
  212. // Gettext translations for the below source types are available.
  213. $source = _($this->notice->source);
  214. break;
  215. default:
  216. $ns = Notice_source::getKV($this->notice->source);
  217. if ($ns instanceof Notice_source) {
  218. $source = $ns->code;
  219. if (!empty($ns->url)) {
  220. $source_link = $ns->url;
  221. if (!empty($ns->name)) {
  222. $source = $ns->name;
  223. }
  224. }
  225. }
  226. break;
  227. }
  228. $this->source = $source;
  229. $this->source_link = $source_link;
  230. }
  231. }