]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/UserFlag/actions/adminprofileflag.php
Merge remote-tracking branch 'upstream/master' into social-master
[quix0rs-gnu-social.git] / plugins / UserFlag / actions / adminprofileflag.php
1 <?php
2 /**
3  * Show latest and greatest profile flags
4  *
5  * PHP version 5
6  *
7  * @category Action
8  * @package  StatusNet
9  * @author   Evan Prodromou <evan@status.net>
10  * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
11  * @link     http://status.net/
12  *
13  * StatusNet - the distributed open-source microblogging tool
14  * Copyright (C) 2009, StatusNet, Inc.
15  *
16  * This program is free software: you can redistribute it and/or modify
17  * it under the terms of the GNU Affero General Public License as published by
18  * the Free Software Foundation, either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU Affero General Public License for more details.
25  *
26  * You should have received a copy of the GNU Affero General Public License
27  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
28  */
29
30 if (!defined('STATUSNET')) {
31     exit(1);
32 }
33
34 /**
35  * Show the latest and greatest profile flags
36  *
37  * @category Action
38  * @package  StatusNet
39  * @author   Evan Prodromou <evan@status.net>
40  * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
41  * @link     http://status.net/
42  */
43 class AdminprofileflagAction extends Action
44 {
45     var $page     = null;
46     var $profiles = null;
47
48     /**
49      * Take arguments for running
50      *
51      * @param array $args $_REQUEST args
52      *
53      * @return boolean success flag
54      */
55     function prepare(array $args=array())
56     {
57         parent::prepare($args);
58
59         $user = common_current_user();
60
61         // User must be logged in.
62
63         if (!common_logged_in()) {
64             // TRANS: Error message displayed when trying to perform an action that requires a logged in user.
65             $this->clientError(_m('Not logged in.'));
66         }
67
68         $user = common_current_user();
69
70         // ...because they're logged in
71
72         assert(!empty($user));
73
74         // It must be a "real" login, not saved cookie login
75
76         if (!common_is_real_login()) {
77             // Cookie theft is too easy; we require automatic
78             // logins to re-authenticate before admining the site
79             common_set_returnto($this->selfUrl());
80             if (Event::handle('RedirectToLogin', array($this, $user))) {
81                 common_redirect(common_local_url('login'), 303);
82             }
83         }
84
85         // User must have the right to review flags
86
87         if (!$user->hasRight(UserFlagPlugin::REVIEWFLAGS)) {
88             // TRANS: Error message displayed when trying to review profile flags while not authorised.
89             $this->clientError(_m('You cannot review profile flags.'));
90         }
91
92         $this->page = $this->trimmed('page');
93
94         if (empty($this->page)) {
95             $this->page = 1;
96         }
97
98         $this->profiles = $this->getProfiles();
99
100         return true;
101     }
102
103     /**
104      * Handle request
105      *
106      * @param array $args $_REQUEST args; handled in prepare()
107      *
108      * @return void
109      */
110     function handle(array $args=array())
111     {
112         parent::handle($args);
113
114         $this->showPage();
115     }
116
117     /**
118      * Title of this page
119      *
120      * @return string Title of the page
121      */
122     function title()
123     {
124         // TRANS: Title for page with a list of profiles that were flagged for review.
125         return _m('Flagged profiles');
126     }
127
128     /**
129      * save the profile flag
130      *
131      * @return void
132      */
133     function showContent()
134     {
135         $pl = new FlaggedProfileList($this->profiles, $this);
136
137         $cnt = $pl->show();
138
139         $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
140                           $this->page, 'adminprofileflag');
141     }
142
143     /**
144      * Retrieve this action's profiles
145      *
146      * @return Profile $profile Profile query results
147      */
148     function getProfiles()
149     {
150         $ufp = new User_flag_profile();
151
152         $ufp->selectAdd();
153         $ufp->selectAdd('profile_id');
154         $ufp->selectAdd('count(*) as flag_count');
155
156         $ufp->whereAdd('cleared is NULL');
157
158         $ufp->groupBy('profile_id');
159         $ufp->orderBy('flag_count DESC, profile_id DESC');
160
161         $offset = ($this->page-1) * PROFILES_PER_PAGE;
162         $limit  = PROFILES_PER_PAGE + 1;
163
164         $ufp->limit($offset, $limit);
165
166         $profiles = array();
167
168         if ($ufp->find()) {
169             while ($ufp->fetch()) {
170                 $profile = Profile::getKV('id', $ufp->profile_id);
171                 if (!empty($profile)) {
172                     $profiles[] = $profile;
173                 }
174             }
175         }
176
177         $ufp->free();
178
179         return new ArrayWrapper($profiles);
180     }
181 }
182
183 /**
184  * Specialization of ProfileList to show flagging information
185  *
186  * Most of the hard part is done in FlaggedProfileListItem.
187  *
188  * @category Widget
189  * @package  StatusNet
190  * @author   Evan Prodromou <evan@status.net>
191  * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
192  * @link     http://status.net/
193  */
194 class FlaggedProfileList extends ProfileList
195 {
196     /**
197      * Factory method for creating new list items
198      *
199      * @param Profile $profile Profile to create an item for
200      *
201      * @return ProfileListItem newly-created item
202      */
203     function newListItem(Profile $profile)
204     {
205         return new FlaggedProfileListItem($this->profile, $this->action);
206     }
207 }
208
209 /**
210  * Specialization of ProfileListItem to show flagging information
211  *
212  * @category Widget
213  * @package  StatusNet
214  * @author   Evan Prodromou <evan@status.net>
215  * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
216  * @link     http://status.net/
217  */
218 class FlaggedProfileListItem extends ProfileListItem
219 {
220     const MAX_FLAGGERS = 5;
221
222     var $user   = null;
223     var $r2args = null;
224
225     /**
226      * Overload parent's action list with our own moderation-oriented buttons
227      *
228      * @return void
229      */
230     function showActions()
231     {
232         $this->user = common_current_user();
233
234         list($action, $this->r2args) = $this->out->returnToArgs();
235
236         $this->r2args['action'] = $action;
237
238         $this->startActions();
239         if (Event::handle('StartProfileListItemActionElements', array($this))) {
240             $this->out->elementStart('li', 'entity_moderation');
241             // TRANS: Header for moderation menu with action buttons for flagged profiles (like 'sandbox', 'silence', ...).
242             $this->out->element('p', null, _m('Moderate'));
243             $this->out->elementStart('ul');
244             $this->showSandboxButton();
245             $this->showSilenceButton();
246             $this->showDeleteButton();
247             $this->showClearButton();
248             $this->out->elementEnd('ul');
249             $this->out->elementEnd('li');
250             Event::handle('EndProfileListItemActionElements', array($this));
251         }
252         $this->endActions();
253     }
254
255     /**
256      * Show a button to sandbox the profile
257      *
258      * @return void
259      */
260     function showSandboxButton()
261     {
262         if ($this->user->hasRight(Right::SANDBOXUSER)) {
263             $this->out->elementStart('li', 'entity_sandbox');
264             if ($this->profile->isSandboxed()) {
265                 $usf = new UnSandboxForm($this->out, $this->profile, $this->r2args);
266                 $usf->show();
267             } else {
268                 $sf = new SandboxForm($this->out, $this->profile, $this->r2args);
269                 $sf->show();
270             }
271             $this->out->elementEnd('li');
272         }
273     }
274
275     /**
276      * Show a button to silence the profile
277      *
278      * @return void
279      */
280     function showSilenceButton()
281     {
282         if ($this->user->hasRight(Right::SILENCEUSER)) {
283             $this->out->elementStart('li', 'entity_silence');
284             if ($this->profile->isSilenced()) {
285                 $usf = new UnSilenceForm($this->out, $this->profile, $this->r2args);
286                 $usf->show();
287             } else {
288                 $sf = new SilenceForm($this->out, $this->profile, $this->r2args);
289                 $sf->show();
290             }
291             $this->out->elementEnd('li');
292         }
293     }
294
295     /**
296      * Show a button to delete user and profile
297      *
298      * @return void
299      */
300     function showDeleteButton()
301     {
302
303         if ($this->user->hasRight(Right::DELETEUSER)) {
304             $this->out->elementStart('li', 'entity_delete');
305             $df = new DeleteUserForm($this->out, $this->profile, $this->r2args);
306             $df->show();
307             $this->out->elementEnd('li');
308         }
309     }
310
311     /**
312      * Show a button to clear flags
313      *
314      * @return void
315      */
316     function showClearButton()
317     {
318         if ($this->user->hasRight(UserFlagPlugin::CLEARFLAGS)) {
319             $this->out->elementStart('li', 'entity_clear');
320             $cf = new ClearFlagForm($this->out, $this->profile, $this->r2args);
321             $cf->show();
322             $this->out->elementEnd('li');
323         }
324     }
325
326     /**
327      * Overload parent function to add flaggers list
328      *
329      * @return void
330      */
331     function endProfile()
332     {
333         $this->showFlaggersList();
334         parent::endProfile();
335     }
336
337     /**
338      * Show a list of people who've flagged this profile
339      *
340      * @return void
341      */
342     function showFlaggersList()
343     {
344         $flaggers = array();
345
346         $ufp = new User_flag_profile();
347
348         $ufp->selectAdd();
349         $ufp->selectAdd('user_id');
350         $ufp->profile_id = $this->profile->id;
351         $ufp->orderBy('created');
352
353         if ($ufp->find()) { // XXX: this should always happen
354             while ($ufp->fetch()) {
355                 $user = User::getKV('id', $ufp->user_id);
356                 if (!empty($user)) { // XXX: this would also be unusual
357                     $flaggers[] = clone($user);
358                 }
359             }
360         }
361
362         $cnt    = count($flaggers);
363         $others = 0;
364
365         if ($cnt > self::MAX_FLAGGERS) {
366             $flaggers = array_slice($flaggers, 0, self::MAX_FLAGGERS);
367             $others   = $cnt - self::MAX_FLAGGERS;
368         }
369
370         $lnks = array();
371
372         foreach ($flaggers as $flagger) {
373
374             $url = common_local_url('showstream',
375                                     array('nickname' => $flagger->nickname));
376
377             $lnks[] = XMLStringer::estring('a', array('href' => $url,
378                                                       'class' => 'flagger'),
379                                            $flagger->nickname);
380         }
381
382         if ($cnt > 0) {
383             if ($others > 0) {
384                 $flagging_users = implode(', ', $lnks);
385                 // TRANS: Message displayed on a profile if it has been flagged.
386                 // TRANS: %1$s is a comma separated list of at most 5 user nicknames that flagged.
387                 // TRANS: %2$d is a positive integer of additional flagging users. Also used for plural.
388                 $text .= sprintf(_m('Flagged by %1$s and %2$d other', 'Flagged by %1$s and %2$d others', $others), $flagging_users, $others);
389             } else {
390                 // TRANS: Message displayed on a profile if it has been flagged.
391                 // TRANS: %s is a comma separated list of at most 5 user nicknames that flagged.
392                 $text .= sprintf(_m('Flagged by %s'), $flagging_users);
393             }
394
395             $this->out->elementStart('p', array('class' => 'flaggers'));
396             $this->out->raw($text);
397             $this->out->elementEnd('p');
398         }
399     }
400 }