showprofiletag.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. <?php
  2. /**
  3. * StatusNet - the distributed open-source microblogging tool
  4. * Copyright (C) 2008, 2009, StatusNet, Inc.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. * @category Actions
  20. * @package Actions
  21. * @license GNU Affero General Public License http://www.gnu.org/licenses/
  22. * @link http://status.net
  23. */
  24. if (!defined('STATUSNET') && !defined('LACONICA')) {
  25. exit(1);
  26. }
  27. require_once INSTALLDIR.'/lib/profileminilist.php';
  28. require_once INSTALLDIR.'/lib/peopletaglist.php';
  29. require_once INSTALLDIR.'/lib/noticelist.php';
  30. require_once INSTALLDIR.'/lib/feedlist.php';
  31. class ShowprofiletagAction extends Action
  32. {
  33. var $notice, $tagger, $peopletag, $userProfile;
  34. function isReadOnly($args)
  35. {
  36. return true;
  37. }
  38. function prepare($args)
  39. {
  40. parent::prepare($args);
  41. if (common_config('singleuser', 'enabled')) {
  42. $tagger_arg = User::singleUserNickname();
  43. } else {
  44. $tagger_arg = $this->arg('tagger');
  45. }
  46. $tag_arg = $this->arg('tag');
  47. $tagger = common_canonical_nickname($tagger_arg);
  48. $tag = common_canonical_tag($tag_arg);
  49. // Permanent redirect on non-canonical nickname
  50. if ($tagger_arg != $tagger || $tag_arg != $tag) {
  51. $args = array('tagger' => $nickname, 'tag' => $tag);
  52. if ($this->page != 1) {
  53. $args['page'] = $this->page;
  54. }
  55. common_redirect(common_local_url('showprofiletag', $args), 301);
  56. }
  57. if (!$tagger) {
  58. // TRANS: Client error displayed when a tagger is expected but not provided.
  59. $this->clientError(_('No tagger.'), 404);
  60. }
  61. $user = User::getKV('nickname', $tagger);
  62. if (!$user) {
  63. // TRANS: Client error displayed trying to perform an action related to a non-existing user.
  64. $this->clientError(_('No such user.'), 404);
  65. }
  66. $this->tagger = $user->getProfile();
  67. $this->peopletag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag));
  68. $current = common_current_user();
  69. $can_see = !empty($this->peopletag) && (!$this->peopletag->private ||
  70. ($this->peopletag->private && $this->peopletag->tagger === $current->id));
  71. if (!$can_see) {
  72. // TRANS: Client error displayed trying to reference a non-existing list.
  73. $this->clientError(_('No such list.'), 404);
  74. }
  75. $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
  76. $this->userProfile = Profile::current();
  77. $stream = new PeopletagNoticeStream($this->peopletag, $this->userProfile);
  78. $this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE,
  79. NOTICES_PER_PAGE + 1);
  80. if ($this->page > 1 && $this->notice->N == 0) {
  81. // TRANS: Client error when page not found (404).
  82. $this->clientError(_('No such page.'), 404);
  83. }
  84. return true;
  85. }
  86. function handle($args)
  87. {
  88. parent::handle($args);
  89. if (!$this->peopletag) {
  90. // TRANS: Client error displayed trying to perform an action related to a non-existing user.
  91. $this->clientError(_('No such user.'));
  92. }
  93. $this->showPage();
  94. }
  95. function title()
  96. {
  97. if ($this->page > 1) {
  98. if($this->peopletag->private) {
  99. // TRANS: Title for private list timeline.
  100. // TRANS: %1$s is a list, %2$s is a page number.
  101. return sprintf(_('Private timeline for %1$s list by you, page %2$d'),
  102. $this->peopletag->tag, $this->page);
  103. }
  104. $current = common_current_user();
  105. if (!empty($current) && $current->id == $this->peopletag->tagger) {
  106. // TRANS: Title for public list timeline where the viewer is the tagger.
  107. // TRANS: %1$s is a list, %2$s is a page number.
  108. return sprintf(_('Timeline for %1$s list by you, page %2$d'),
  109. $this->peopletag->tag, $this->page);
  110. }
  111. // TRANS: Title for private list timeline.
  112. // TRANS: %1$s is a list, %2$s is the tagger's nickname, %3$d is a page number.
  113. return sprintf(_('Timeline for %1$s list by %2$s, page %3$d'),
  114. $this->peopletag->tag,
  115. $this->tagger->nickname,
  116. $this->page
  117. );
  118. } else {
  119. if($this->peopletag->private) {
  120. // TRANS: Title for private list timeline.
  121. // TRANS: %s is a list.
  122. return sprintf(_('Private timeline of %s list by you'),
  123. $this->peopletag->tag);
  124. }
  125. $current = common_current_user();
  126. if (!empty($current) && $current->id == $this->peopletag->tagger) {
  127. // TRANS: Title for public list timeline where the viewer is the tagger.
  128. // TRANS: %s is a list.
  129. return sprintf(_('Timeline for %s list by you'),
  130. $this->peopletag->tag);
  131. }
  132. // TRANS: Title for private list timeline.
  133. // TRANS: %1$s is a list, %2$s is the tagger's nickname.
  134. return sprintf(_('Timeline for %1$s list by %2$s'),
  135. $this->peopletag->tag,
  136. $this->tagger->nickname
  137. );
  138. }
  139. }
  140. function getFeeds()
  141. {
  142. #XXX: make these actually work
  143. return array(new Feed(Feed::JSON,
  144. common_local_url(
  145. 'ApiTimelineList', array(
  146. 'user' => $this->tagger->id,
  147. 'id' => $this->peopletag->id,
  148. 'format' => 'as'
  149. )
  150. ),
  151. // TRANS: Feed title.
  152. // TRANS: %s is tagger's nickname.
  153. sprintf(_('Feed for friends of %s (Activity Streams JSON)'), $this->tagger->nickname)),
  154. new Feed(Feed::RSS2,
  155. common_local_url(
  156. 'ApiTimelineList', array(
  157. 'user' => $this->tagger->id,
  158. 'id' => $this->peopletag->id,
  159. 'format' => 'rss'
  160. )
  161. ),
  162. // TRANS: Feed title.
  163. // TRANS: %s is tagger's nickname.
  164. sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->tagger->nickname)),
  165. new Feed(Feed::ATOM,
  166. common_local_url(
  167. 'ApiTimelineList', array(
  168. 'user' => $this->tagger->id,
  169. 'id' => $this->peopletag->id,
  170. 'format' => 'atom'
  171. )
  172. ),
  173. // TRANS: Feed title.
  174. // TRANS: %1$s is a list, %2$s is tagger's nickname.
  175. sprintf(_('Feed for %1$s list by %2$s (Atom)'),
  176. $this->peopletag->tag, $this->tagger->nickname
  177. )
  178. )
  179. );
  180. }
  181. function showObjectNav()
  182. {
  183. $nav = new PeopletagGroupNav($this);
  184. $nav->show();
  185. }
  186. function showEmptyListMessage()
  187. {
  188. // TRANS: Empty list message for list timeline.
  189. // TRANS: %1$s is a list, %2$s is a tagger's nickname.
  190. $message = sprintf(_('This is the timeline for %1$s list by %2$s but no one has posted anything yet.'),
  191. $this->peopletag->tag,
  192. $this->tagger->nickname) . ' ';
  193. if (common_logged_in()) {
  194. $current_user = common_current_user();
  195. if ($this->tagger->id == $current_user->id) {
  196. // TRANS: Additional empty list message for list timeline for currently logged in user tagged tags.
  197. $message .= _('Try tagging more people.');
  198. }
  199. } else {
  200. // TRANS: Additional empty list message for list timeline.
  201. // TRANS: This message contains Markdown links in the form [description](link).
  202. $message .= _('Why not [register an account](%%%%action.register%%%%) and start following this timeline!');
  203. }
  204. $this->elementStart('div', 'guide');
  205. $this->raw(common_markup_to_html($message));
  206. $this->elementEnd('div');
  207. }
  208. function showContent()
  209. {
  210. $this->showPeopletag();
  211. $this->showNotices();
  212. }
  213. function showPeopletag()
  214. {
  215. $cur = common_current_user();
  216. $tag = new Peopletag($this->peopletag, $cur, $this);
  217. $tag->show();
  218. }
  219. function showNotices()
  220. {
  221. if (Event::handle('StartShowProfileTagContent', array($this))) {
  222. $nl = new PrimaryNoticeList($this->notice, $this, array('show_n'=>NOTICES_PER_PAGE));
  223. $cnt = $nl->show();
  224. if (0 == $cnt) {
  225. $this->showEmptyListMessage();
  226. }
  227. $this->pagination($this->page > 1,
  228. $cnt > NOTICES_PER_PAGE,
  229. $this->page,
  230. 'showprofiletag',
  231. array('tag' => $this->peopletag->tag,
  232. 'tagger' => $this->tagger->nickname)
  233. );
  234. Event::handle('EndShowProfileTagContent', array($this));
  235. }
  236. }
  237. function showSections()
  238. {
  239. $this->showTagged();
  240. if (!$this->peopletag->private) {
  241. $this->showSubscribers();
  242. }
  243. # $this->showStatistics();
  244. }
  245. function showPageTitle()
  246. {
  247. $this->element('h1', null, $this->title());
  248. }
  249. function showTagged()
  250. {
  251. $profile = $this->peopletag->getTagged(0, PROFILES_PER_MINILIST + 1);
  252. $this->elementStart('div', array('id' => 'entity_tagged',
  253. 'class' => 'section'));
  254. if (Event::handle('StartShowTaggedProfilesMiniList', array($this))) {
  255. $title = '';
  256. // TRANS: Header on show list page.
  257. $this->element('h2', null, _('Listed'));
  258. $cnt = 0;
  259. if (!empty($profile)) {
  260. $pml = new ProfileMiniList($profile, $this);
  261. $cnt = $pml->show();
  262. if ($cnt == 0) {
  263. // TRANS: Content of "Listed" page if there are no listed users.
  264. $this->element('p', null, _('(None)'));
  265. }
  266. }
  267. if ($cnt > PROFILES_PER_MINILIST) {
  268. $this->elementStart('p');
  269. $this->element('a', array('href' => common_local_url('taggedprofiles',
  270. array('nickname' => $this->tagger->nickname,
  271. 'profiletag' => $this->peopletag->tag)),
  272. 'class' => 'more'),
  273. // TRANS: Link for more "People in list x by a user"
  274. // TRANS: if there are more than the mini list's maximum.
  275. _('Show all'));
  276. $this->elementEnd('p');
  277. }
  278. Event::handle('EndShowTaggedProfilesMiniList', array($this));
  279. }
  280. $this->elementEnd('div');
  281. }
  282. function showSubscribers()
  283. {
  284. $profile = $this->peopletag->getSubscribers(0, PROFILES_PER_MINILIST + 1);
  285. $this->elementStart('div', array('id' => 'entity_subscribers',
  286. 'class' => 'section'));
  287. if (Event::handle('StartShowProfileTagSubscribersMiniList', array($this))) {
  288. // TRANS: Header for tag subscribers.
  289. $this->element('h2', null, _('Subscribers'));
  290. $cnt = 0;
  291. if (!empty($profile)) {
  292. $pml = new ProfileMiniList($profile, $this);
  293. $cnt = $pml->show();
  294. if ($cnt == 0) {
  295. // TRANS: Content of "People following tag x" if there are no subscribed users.
  296. $this->element('p', null, _('(None)'));
  297. }
  298. }
  299. // FIXME: link to full list
  300. Event::handle('EndShowProfileTagSubscribersMiniList', array($this));
  301. }
  302. $this->elementEnd('div');
  303. }
  304. }
  305. class Peopletag extends PeopletagListItem
  306. {
  307. protected $avatarSize = AVATAR_PROFILE_SIZE;
  308. function showStart()
  309. {
  310. $mode = $this->peopletag->private ? 'private' : 'public';
  311. $this->out->elementStart('div', array('class' => 'h-entry peopletag peopletag-profile mode-'.$mode,
  312. 'id' => 'peopletag-' . $this->peopletag->id));
  313. }
  314. function showEnd()
  315. {
  316. $this->out->elementEnd('div');
  317. }
  318. }