groupdirectory.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. <?php
  2. /**
  3. * StatusNet, the distributed open-source microblogging tool
  4. *
  5. * Output a group directory
  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('GNUSOCIAL')) { exit(1); }
  30. /**
  31. * Group directory
  32. *
  33. * @category Directory
  34. * @package StatusNet
  35. * @author Zach Copley <zach@status.net>
  36. * @author Mikael Nordfeldth <mmn@hethane.se>
  37. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  38. * @link http://status.net/
  39. */
  40. class GroupdirectoryAction extends ManagedAction
  41. {
  42. /**
  43. * The page we're on
  44. *
  45. * @var integer
  46. */
  47. public $page;
  48. /**
  49. * What to filter the search results by
  50. *
  51. * @var string
  52. */
  53. public $filter;
  54. /**
  55. * Column to sort by
  56. *
  57. * @var string
  58. */
  59. public $sort;
  60. /**
  61. * How to order search results, ascending or descending
  62. *
  63. * @var string
  64. */
  65. public $reverse;
  66. /**
  67. * Query
  68. *
  69. * @var string
  70. */
  71. public $q;
  72. /**
  73. * Title of the page
  74. *
  75. * @return string Title of the page
  76. */
  77. function title()
  78. {
  79. // @fixme: This looks kinda gross
  80. if ($this->filter == 'all') {
  81. if ($this->page != 1) {
  82. // TRANS: Title for group directory page. %d is a page number.
  83. return(sprintf(_m('Group Directory, page %d'), $this->page));
  84. }
  85. // TRANS: Title for group directory page.
  86. return _m('Group directory');
  87. } else if ($this->page == 1) {
  88. return sprintf(
  89. // TRANS: Title for group directory page when it is filtered.
  90. // TRANS: %s is the filter string.
  91. _m('Group directory - %s'),
  92. strtoupper($this->filter)
  93. );
  94. } else {
  95. return sprintf(
  96. // TRANS: Title for group directory page when it is filtered.
  97. // TRANS: %1$s is the filter string, %2$d is a page number.
  98. _m('Group directory - %1$s, page %2$d'),
  99. strtoupper($this->filter),
  100. $this->page
  101. );
  102. }
  103. }
  104. /**
  105. * Instructions for use
  106. *
  107. * @return instructions for use
  108. */
  109. function getInstructions()
  110. {
  111. // TRANS: Page instructions.
  112. return _m("After you join a group you can send messages to all other members\n".
  113. "using the syntax \"!groupname\".\n\n".
  114. "Browse groups, or search for groups by their name, location or topic.\n".
  115. "Separate the terms by spaces; they must be three characters or more.") . "\n";
  116. }
  117. /**
  118. * Is this page read-only?
  119. *
  120. * @return boolean true
  121. */
  122. function isReadOnly($args)
  123. {
  124. return true;
  125. }
  126. protected function doPreparation()
  127. {
  128. $this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1;
  129. $this->filter = $this->arg('filter', 'all');
  130. $this->reverse = $this->boolean('reverse');
  131. $this->q = $this->trimmed('q');
  132. $this->sort = $this->arg('sort', 'nickname');
  133. common_set_returnto($this->selfUrl());
  134. }
  135. /**
  136. * Show the page notice
  137. *
  138. * Shows instructions for the page
  139. *
  140. * @return void
  141. */
  142. function showPageNotice()
  143. {
  144. $instr = $this->getInstructions();
  145. $output = common_markup_to_html($instr);
  146. $this->elementStart('div', 'instructions');
  147. $this->raw($output);
  148. $this->elementEnd('div');
  149. }
  150. /**
  151. * Content area
  152. *
  153. * Shows the groups
  154. *
  155. * @return void
  156. */
  157. function showContent()
  158. {
  159. if (common_logged_in()) {
  160. $this->elementStart(
  161. 'p',
  162. array(
  163. 'id' => 'new_group'
  164. )
  165. );
  166. $this->element(
  167. 'a',
  168. array(
  169. 'href' => common_local_url('newgroup'),
  170. 'class' => 'more'),
  171. // TRANS: Link to create a new group on the group list page.
  172. _m('Create a new group')
  173. );
  174. $this->elementEnd('p');
  175. }
  176. $this->showForm();
  177. $this->elementStart('div', array('id' => 'profile_directory'));
  178. // @todo FIXME: Does "All" need i18n here?
  179. $alphaNav = new AlphaNav($this, false, false, array('0-9', 'All'));
  180. $alphaNav->show();
  181. $group = null;
  182. $group = $this->getGroups();
  183. $cnt = 0;
  184. if (!empty($group)) {
  185. $groupList = new SortableGroupList(
  186. $group,
  187. common_current_user(),
  188. $this
  189. );
  190. $cnt = $groupList->show();
  191. $group->free();
  192. if (0 == $cnt) {
  193. $this->showEmptyListMessage();
  194. }
  195. }
  196. $args = array();
  197. if (isset($this->q)) {
  198. $args['q'] = $this->q;
  199. } else {
  200. $args['filter'] = $this->filter;
  201. }
  202. $this->pagination(
  203. $this->page > 1,
  204. $cnt > PROFILES_PER_PAGE,
  205. $this->page,
  206. 'groupdirectory',
  207. $args
  208. );
  209. $this->elementEnd('div');
  210. }
  211. function showForm($error=null)
  212. {
  213. $this->elementStart(
  214. 'form',
  215. array(
  216. 'method' => 'get',
  217. 'id' => 'form_search',
  218. 'class' => 'form_settings',
  219. 'action' => common_local_url('groupdirectory')
  220. )
  221. );
  222. $this->elementStart('fieldset');
  223. // TRANS: Fieldset legend.
  224. $this->element('legend', null, _m('Search groups'));
  225. $this->elementStart('ul', 'form_data');
  226. $this->elementStart('li');
  227. // TRANS: Field label for input of one or more keywords.
  228. $this->input('q', _m('Keyword(s)'), $this->q);
  229. // TRANS: Button text for searching group directory.
  230. $this->submit('search', _m('BUTTON','Search'));
  231. $this->elementEnd('li');
  232. $this->elementEnd('ul');
  233. $this->elementEnd('fieldset');
  234. $this->elementEnd('form');
  235. }
  236. /*
  237. * Get groups filtered by the current filter, sort key,
  238. * sort order, and page
  239. */
  240. function getGroups()
  241. {
  242. $group = new User_group();
  243. // Disable this to get global group searches
  244. $group->joinAdd(array('id', 'local_group:group_id'));
  245. $order = false;
  246. if (!empty($this->q)) {
  247. $wheres = array('nickname', 'fullname', 'homepage', 'description', 'location');
  248. foreach ($wheres as $where) {
  249. // Double % because of sprintf
  250. $group->whereAdd(sprintf('LOWER(%1$s.%2$s) LIKE LOWER("%%%3$s%%")',
  251. $group->escapedTableName(), $where,
  252. $group->escape($this->q)),
  253. 'OR');
  254. }
  255. $order = sprintf('%1$s.%2$s %3$s',
  256. $group->escapedTableName(),
  257. $this->getSortKey('created'),
  258. $this->reverse ? 'DESC' : 'ASC');
  259. } else {
  260. // User is browsing via AlphaNav
  261. switch($this->filter) {
  262. case 'all':
  263. // NOOP
  264. break;
  265. case '0-9':
  266. $group->whereAdd(sprintf('LEFT(%1$s.%2$s, 1) BETWEEN %3$s AND %4$s',
  267. $group->escapedTableName(),
  268. 'nickname',
  269. $group->_quote("0"),
  270. $group->_quote("9")));
  271. break;
  272. default:
  273. $group->whereAdd(sprintf('LEFT(LOWER(%1$s.%2$s), 1) = %3$s',
  274. $group->escapedTableName(),
  275. 'nickname',
  276. $group->_quote($this->filter)));
  277. }
  278. $order = sprintf('%1$s.%2$s %3$s, %1$s.%4$s ASC',
  279. $group->escapedTableName(),
  280. $this->getSortKey('nickname'),
  281. $this->reverse ? 'DESC' : 'ASC',
  282. 'nickname');
  283. }
  284. $offset = ($this->page-1) * PROFILES_PER_PAGE;
  285. $limit = PROFILES_PER_PAGE + 1;
  286. $group->selectAdd();
  287. $group->selectAdd('profile_id');
  288. $group->orderBy($order);
  289. $group->limit($offset, $limit);
  290. $group->find();
  291. return Profile::multiGet('id', $group->fetchAll('profile_id'));
  292. }
  293. /**
  294. * Filter the sort parameter
  295. *
  296. * @return string a column name for sorting
  297. */
  298. function getSortKey($def='created')
  299. {
  300. switch ($this->sort) {
  301. case 'nickname':
  302. case 'created':
  303. return $this->sort;
  304. default:
  305. return $def;
  306. }
  307. }
  308. /**
  309. * Show a nice message when there's no search results
  310. */
  311. function showEmptyListMessage()
  312. {
  313. if (!empty($this->filter) && ($this->filter != 'all')) {
  314. $this->element(
  315. 'p',
  316. 'error',
  317. sprintf(
  318. // TRANS: Empty list message for searching group directory.
  319. // TRANS: %s is the search string.
  320. _m('No groups starting with %s.'),
  321. $this->filter
  322. )
  323. );
  324. } else {
  325. // TRANS: Empty list message for searching group directory.
  326. $this->element('p', 'error', _m('No results.'));
  327. // TRANS: Help text for searching group directory.
  328. $message = _m("* Make sure all words are spelled correctly.\n".
  329. "* Try different keywords.\n".
  330. "* Try more general keywords.\n".
  331. "* Try fewer keywords.");
  332. $this->elementStart('div', 'help instructions');
  333. $this->raw(common_markup_to_html($message));
  334. $this->elementEnd('div');
  335. }
  336. }
  337. function showSections()
  338. {
  339. $gbp = new GroupsByPostsSection($this);
  340. $gbp->show();
  341. $gbm = new GroupsByMembersSection($this);
  342. $gbm->show();
  343. }
  344. }