]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Directory/actions/groupdirectory.php
Make group search in Directory use PEAR::DB
[quix0rs-gnu-social.git] / plugins / Directory / actions / groupdirectory.php
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
30 if (!defined('GNUSOCIAL')) { exit(1); }
31
32 /**
33  * Group directory
34  *
35  * @category Directory
36  * @package  StatusNet
37  * @author   Zach Copley <zach@status.net>
38  * @author   Mikael Nordfeldth <mmn@hethane.se>
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 GroupdirectoryAction extends Action
43 {
44     /**
45      * The page we're on
46      *
47      * @var integer
48      */
49     public $page;
50
51     /**
52      * What to filter the search results by
53      *
54      * @var string
55      */
56     public $filter;
57
58     /**
59      * Column to sort by
60      *
61      * @var string
62      */
63     public $sort;
64
65     /**
66      * How to order search results, ascending or descending
67      *
68      * @var string
69      */
70     public $reverse;
71
72     /**
73      * Query
74      *
75      * @var string
76      */
77     public $q;
78
79     /**
80      * Title of the page
81      *
82      * @return string Title of the page
83      */
84     function title()
85     {
86         // @fixme: This looks kinda gross
87
88         if ($this->filter == 'all') {
89             if ($this->page != 1) {
90                 // TRANS: Title for group directory page. %d is a page number.
91                 return(sprintf(_m('Group Directory, page %d'), $this->page));
92             }
93             // TRANS: Title for group directory page.
94             return _m('Group directory');
95         } else if ($this->page == 1) {
96             return sprintf(
97                 // TRANS: Title for group directory page when it is filtered.
98                 // TRANS: %s is the filter string.
99                 _m('Group directory - %s'),
100                 strtoupper($this->filter)
101             );
102         } else {
103             return sprintf(
104                 // TRANS: Title for group directory page when it is filtered.
105                 // TRANS: %1$s is the filter string, %2$d is a page number.
106                 _m('Group directory - %1$s, page %2$d'),
107                 strtoupper($this->filter),
108                 $this->page
109             );
110         }
111     }
112
113     /**
114      * Instructions for use
115      *
116      * @return instructions for use
117      */
118     function getInstructions()
119     {
120         // TRANS: Page instructions.
121         return _m("After you join a group you can send messages to all other members\n".
122                  "using the syntax \"!groupname\".\n\n".
123                  "Browse groups, or search for groups by their name, location or topic.\n".
124                  "Separate the terms by spaces; they must be three characters or more.") . "\n";
125     }
126
127     /**
128      * Is this page read-only?
129      *
130      * @return boolean true
131      */
132     function isReadOnly($args)
133     {
134         return true;
135     }
136
137     /**
138      * Take arguments for running
139      *
140      * @param array $args $_REQUEST args
141      *
142      * @return boolean success flag
143      */
144     function prepare($args)
145     {
146         parent::prepare($args);
147
148         $this->page    = ($this->arg('page')) ? ($this->arg('page') + 0) : 1;
149         $this->filter  = $this->arg('filter', 'all');
150         $this->reverse = $this->boolean('reverse');
151         $this->q       = $this->trimmed('q');
152         $this->sort    = $this->arg('sort', 'nickname');
153
154         common_set_returnto($this->selfUrl());
155
156         return true;
157     }
158
159     /**
160      * Handle request
161      *
162      * Shows the page
163      *
164      * @param array $args $_REQUEST args; handled in prepare()
165      *
166      * @return void
167      */
168     function handle($args)
169     {
170         parent::handle($args);
171         $this->showPage();
172     }
173
174     /**
175      * Show the page notice
176      *
177      * Shows instructions for the page
178      *
179      * @return void
180      */
181     function showPageNotice()
182     {
183         $instr  = $this->getInstructions();
184         $output = common_markup_to_html($instr);
185
186         $this->elementStart('div', 'instructions');
187         $this->raw($output);
188         $this->elementEnd('div');
189     }
190
191
192     /**
193      * Content area
194      *
195      * Shows the groups
196      *
197      * @return void
198      */
199     function showContent()
200     {
201         if (common_logged_in()) {
202             $this->elementStart(
203                 'p',
204                 array(
205                     'id' => 'new_group'
206                 )
207             );
208             $this->element(
209                 'a',
210                 array(
211                     'href'  => common_local_url('newgroup'),
212                     'class' => 'more'),
213                     // TRANS: Link to create a new group on the group list page.
214                     _m('Create a new group')
215             );
216             $this->elementEnd('p');
217         }
218
219         $this->showForm();
220
221         $this->elementStart('div', array('id' => 'profile_directory'));
222
223         // @todo FIXME: Does "All" need i18n here?
224         $alphaNav = new AlphaNav($this, false, false, array('0-9', 'All'));
225         $alphaNav->show();
226
227         $group   = null;
228         $group   = $this->getGroups();
229         $cnt     = 0;
230
231         if (!empty($group)) {
232             $groupList = new SortableGroupList(
233                 $group,
234                 common_current_user(),
235                 $this
236             );
237
238             $cnt = $groupList->show();
239             $group->free();
240
241             if (0 == $cnt) {
242                 $this->showEmptyListMessage();
243             }
244         }
245
246         $args = array();
247         if (isset($this->q)) {
248             $args['q'] = $this->q;
249         } else {
250             $args['filter'] = $this->filter;
251         }
252
253         $this->pagination(
254             $this->page > 1,
255             $cnt > PROFILES_PER_PAGE,
256             $this->page,
257             'groupdirectory',
258             $args
259         );
260
261         $this->elementEnd('div');
262     }
263
264     function showForm($error=null)
265     {
266         $this->elementStart(
267             'form',
268             array(
269                 'method' => 'get',
270                 'id'     => 'form_search',
271                 'class'  => 'form_settings',
272                 'action' => common_local_url('groupdirectory')
273             )
274         );
275
276         $this->elementStart('fieldset');
277
278         // TRANS: Fieldset legend.
279         $this->element('legend', null, _m('Search groups'));
280         $this->elementStart('ul', 'form_data');
281         $this->elementStart('li');
282
283         // TRANS: Field label for input of one or more keywords.
284         $this->input('q', _m('Keyword(s)'), $this->q);
285
286         // TRANS: Button text for searching group directory.
287         $this->submit('search', _m('BUTTON','Search'));
288         $this->elementEnd('li');
289         $this->elementEnd('ul');
290         $this->elementEnd('fieldset');
291         $this->elementEnd('form');
292     }
293
294     /*
295      * Get groups filtered by the current filter, sort key,
296      * sort order, and page
297      */
298     function getGroups()
299     {
300         $group = new User_group();
301
302         $offset = ($this->page-1) * PROFILES_PER_PAGE;
303         $limit  = PROFILES_PER_PAGE + 1;
304
305         if (isset($this->q)) {
306
307             // Disable this to get global group searches
308             $group->joinAdd(array('id', 'local_group:group_id'));
309
310             $wheres = array('nickname', 'fullname', 'homepage', 'description', 'location');
311             foreach ($wheres as $where) {
312                 $group->whereAdd("LOWER({$group->__table}.{$where}) LIKE LOWER('%".$group->escape($this->q)."%')", 'OR');
313             }
314
315              $order = 'user_group.created ASC';
316
317              if ($this->sort == 'nickname') {
318                  if ($this->reverse) {
319                      $order = 'user_group.nickname DESC';
320                  } else {
321                      $order = 'user_group.nickname ASC';
322                  }
323              } else {
324                  if ($this->reverse) {
325                      $order = 'user_group.created DESC';
326                  }
327              }
328
329             $group->orderBy($order);
330             $group->limit($offset, $limit);
331
332         } else {
333             // User is browsing via AlphaNav
334             $sort   = $this->getSortKey();
335
336             $sql = <<< GROUP_QUERY_END
337 SELECT user_group.*
338 FROM user_group
339 JOIN local_group ON user_group.id = local_group.group_id
340 GROUP_QUERY_END;
341
342             switch($this->filter)
343             {
344             case 'all':
345                 // NOOP
346                 break;
347             case '0-9':
348                 $sql .=
349                     '  AND LEFT(user_group.nickname, 1) BETWEEN \'0\' AND \'9\'';
350                 break;
351             default:
352                 $sql .= sprintf(
353                     ' AND LEFT(LOWER(user_group.nickname), 1) = \'%s\'',
354                     $this->filter
355                 );
356             }
357
358             $sql .= sprintf(
359                 ' ORDER BY user_group.%s %s, user_group.nickname ASC LIMIT %d, %d',
360                 $sort,
361                 $this->reverse ? 'DESC' : 'ASC',
362                 $offset,
363                 $limit
364             );
365
366             $group->query($sql);
367         }
368
369         $group->find();
370
371         return $group;
372     }
373
374     /**
375      * Filter the sort parameter
376      *
377      * @return string   a column name for sorting
378      */
379     function getSortKey()
380     {
381         switch ($this->sort) {
382         case 'nickname':
383             return $this->sort;
384             break;
385         case 'created':
386             return $this->sort;
387             break;
388         default:
389             return 'nickname';
390         }
391     }
392
393     /**
394      * Show a nice message when there's no search results
395      */
396     function showEmptyListMessage()
397     {
398         if (!empty($this->filter) && ($this->filter != 'all')) {
399             $this->element(
400                 'p',
401                 'error',
402                 sprintf(
403                     // TRANS: Empty list message for searching group directory.
404                     // TRANS: %s is the search string.
405                     _m('No groups starting with %s.'),
406                     $this->filter
407                 )
408             );
409         } else {
410             // TRANS: Empty list message for searching group directory.
411             $this->element('p', 'error', _m('No results.'));
412             // TRANS: Help text for searching group directory.
413             $message = _m("* Make sure all words are spelled correctly.\n".
414                           "* Try different keywords.\n".
415                           "* Try more general keywords.\n".
416                           "* Try fewer keywords.");
417             $this->elementStart('div', 'help instructions');
418             $this->raw(common_markup_to_html($message));
419             $this->elementEnd('div');
420         }
421     }
422
423     function showSections()
424     {
425         $gbp = new GroupsByPostsSection($this);
426         $gbp->show();
427         $gbm = new GroupsByMembersSection($this);
428         $gbm->show();
429     }
430 }