sortablegrouplist.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <?php
  2. /**
  3. * StatusNet, the distributed open-source microblogging tool
  4. *
  5. * Widget to show a sortable list of profiles
  6. *
  7. * PHP version 5
  8. *
  9. * LICENCE: This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * @category Public
  23. * @package StatusNet
  24. * @author Zach Copley <zach@status.net>
  25. * @copyright 2011 StatusNet, Inc.
  26. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  27. * @link http://status.net/
  28. */
  29. if (!defined('STATUSNET')) {
  30. exit(1);
  31. }
  32. require_once INSTALLDIR . '/lib/subscriptionlist.php';
  33. /**
  34. * Widget to show a sortable list of subscriptions
  35. *
  36. * @category Public
  37. * @package StatusNet
  38. * @author Zach Copley <zach@status.net>
  39. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  40. * @link http://status.net/
  41. */
  42. class SortableGroupList extends SortableSubscriptionList
  43. {
  44. /** Owner of this list */
  45. var $owner = null;
  46. function __construct($profile, $owner=null, $action=null)
  47. {
  48. parent::__construct($profile, $owner, $action);
  49. $this->owner = $owner;
  50. }
  51. function startList()
  52. {
  53. $this->out->elementStart('table', array('class' => 'profile_list xoxo'));
  54. $this->out->elementStart('thead');
  55. $this->out->elementStart('tr');
  56. $tableHeaders = array(
  57. // TRANS: Column header in table for user nickname.
  58. 'nickname' => _m('Nickname'),
  59. // TRANS: Column header in table for timestamp when user was created.
  60. 'created' => _m('Created')
  61. );
  62. foreach ($tableHeaders as $id => $label) {
  63. $attrs = array('id' => $id);
  64. $current = (!empty($this->action->sort) && $this->action->sort == $id);
  65. if ($current || empty($this->action->sort) && $id == 'nickname') {
  66. $attrs['class'] = 'current';
  67. }
  68. if ($current && $this->action->reverse) {
  69. $attrs['class'] .= ' reverse';
  70. $attrs['class'] = trim($attrs['class']);
  71. }
  72. $this->out->elementStart('th', $attrs);
  73. $linkAttrs = array();
  74. $params = array('sort' => $id);
  75. if (!empty($this->action->q)) {
  76. $params['q'] = $this->action->q;
  77. }
  78. if ($current && !$this->action->reverse) {
  79. $params['reverse'] = 'true';
  80. }
  81. $args = array();
  82. $filter = $this->action->arg('filter');
  83. if (!empty($filter)) {
  84. $args['filter'] = $filter;
  85. }
  86. $linkAttrs['href'] = common_local_url(
  87. $this->action->arg('action'), $args, $params
  88. );
  89. $this->out->element('a', $linkAttrs, $label);
  90. $this->out->elementEnd('th');
  91. }
  92. // TRANS: Column header in table for members of a group.
  93. $this->out->element('th', array('id' => 'Members'), _m('Members'));
  94. $this->out->element('th', array('id' => 'controls'), null);
  95. $this->out->elementEnd('tr');
  96. $this->out->elementEnd('thead');
  97. $this->out->elementStart('tbody');
  98. }
  99. function newListItem($profile, $odd)
  100. {
  101. return new SortableGroupListItem($profile, $this->owner, $this->action, $odd);
  102. }
  103. }
  104. class SortableGroupListItem extends SortableSubscriptionListItem
  105. {
  106. /** Owner of this list */
  107. var $owner = null;
  108. function __construct($profile, $owner, $action, $alt)
  109. {
  110. parent::__construct($profile, $owner, $action, $alt);
  111. $this->alt = $alt; // is this row alternate?
  112. $this->owner = $owner;
  113. }
  114. function showHomepage()
  115. {
  116. if (!empty($this->profile->homepage)) {
  117. $this->out->text(' ');
  118. $aAttrs = $this->homepageAttributes();
  119. $this->out->elementStart('a', $aAttrs);
  120. $this->out->raw($this->highlight($this->profile->homepage));
  121. $this->out->elementEnd('a');
  122. }
  123. }
  124. function showDescription()
  125. {
  126. if (!empty($this->profile->description)) {
  127. $cutoff = 140; // XXX Should this be configurable?
  128. $description = htmlspecialchars($this->profile->description);
  129. if (mb_strlen($description) > $cutoff) {
  130. $description = mb_substr($description, 0, $cutoff - 1)
  131. .'<a href="' . $this->profile->homeUrl() .'">…</a>';
  132. }
  133. $this->out->elementStart('p', 'note');
  134. $this->out->raw($description);
  135. $this->out->elementEnd('p');
  136. }
  137. }
  138. // TODO: Make sure we can do ->getAvatar() for group profiles too!
  139. function showAvatar(Profile $profile, $size=null)
  140. {
  141. $logo = $profile->getGroup()->stream_logo ?: User_group::defaultLogo($size ?: $this->avatarSize());
  142. $this->out->element('img', array('src' => $logo,
  143. 'class' => 'avatar u-photo',
  144. 'width' => AVATAR_STREAM_SIZE,
  145. 'height' => AVATAR_STREAM_SIZE,
  146. 'alt' => $profile->getBestName()));
  147. }
  148. function show()
  149. {
  150. if (Event::handle('StartProfileListItem', array($this))) {
  151. $this->startItem();
  152. if (Event::handle('StartProfileListItemProfile', array($this))) {
  153. $this->showProfile();
  154. Event::handle('EndProfileListItemProfile', array($this));
  155. }
  156. // XXX Add events?
  157. $this->showCreatedDate();
  158. $this->showMemberCount();
  159. if (Event::handle('StartProfileListItemActions', array($this))) {
  160. $this->showActions();
  161. Event::handle('EndProfileListItemActions', array($this));
  162. }
  163. $this->endItem();
  164. Event::handle('EndProfileListItem', array($this));
  165. }
  166. }
  167. function showProfile()
  168. {
  169. $this->startProfile();
  170. $this->showAvatar($this->profile->getProfile());
  171. $this->out->element('a', array('href' => $this->profile->homeUrl(),
  172. 'class' => 'p-org p-nickname',
  173. 'rel' => 'contact group'),
  174. $this->profile->getNickname());
  175. $this->showFullName();
  176. $this->showLocation();
  177. $this->showHomepage();
  178. $this->showDescription(); // groups have this instead of bios
  179. // Relevant portion!
  180. $this->showTags();
  181. $this->endProfile();
  182. }
  183. function endActions()
  184. {
  185. // delete button
  186. $cur = common_current_user();
  187. list($action, $r2args) = $this->out->returnToArgs();
  188. $r2args['action'] = $action;
  189. if ($cur instanceof User && $cur->hasRight(Right::DELETEGROUP)) {
  190. $this->out->elementStart('li', 'entity_delete');
  191. $df = new DeleteGroupForm($this->out, $this->profile, $r2args);
  192. $df->show();
  193. $this->out->elementEnd('li');
  194. }
  195. $this->out->elementEnd('ul');
  196. $this->out->elementEnd('td');
  197. }
  198. function showActions()
  199. {
  200. $this->startActions();
  201. if (Event::handle('StartProfileListItemActionElements', array($this))) {
  202. $this->showJoinButton();
  203. Event::handle('EndProfileListItemActionElements', array($this));
  204. }
  205. $this->endActions();
  206. }
  207. function showJoinButton()
  208. {
  209. $user = $this->owner;
  210. if ($user) {
  211. $this->out->elementStart('li', 'entity_subscribe');
  212. // XXX: special-case for user looking at own
  213. // subscriptions page
  214. if ($user->isMember($this->profile)) {
  215. $lf = new LeaveForm($this->out, $this->profile);
  216. $lf->show();
  217. } else if (!Group_block::isBlocked($this->profile, $user->getProfile())) {
  218. $jf = new JoinForm($this->out, $this->profile);
  219. $jf->show();
  220. }
  221. $this->out->elementEnd('li');
  222. }
  223. }
  224. function showMemberCount()
  225. {
  226. $this->out->elementStart('td', 'entry_member_count');
  227. $this->out->raw($this->profile->getMemberCount());
  228. $this->out->elementEnd('td');
  229. }
  230. function showCreatedDate()
  231. {
  232. $this->out->elementStart('td', 'entry_created');
  233. // @todo FIXME: Should we provide i18n for timestamps in core?
  234. $this->out->raw(date('j M Y', strtotime($this->profile->created)));
  235. $this->out->elementEnd('td');
  236. }
  237. function showAdmins()
  238. {
  239. $this->out->elementStart('td', 'entry_admins');
  240. // @todo
  241. $this->out->raw('gargargar');
  242. $this->out->elementEnd('td');
  243. }
  244. /**
  245. * Only show the tags if we're logged in
  246. */
  247. function showTags()
  248. {
  249. if (common_logged_in()) {
  250. parent::showTags();
  251. }
  252. }
  253. }