]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - lib/profileaction.php
Merge branch 'master' of git.gnu.io:gnu/gnu-social
[quix0rs-gnu-social.git] / lib / profileaction.php
1 <?php
2 /**
3  * StatusNet, the distributed open-source microblogging tool
4  *
5  * Common parent of Personal and Profile actions
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  Personal
23  * @package   StatusNet
24  * @author    Evan Prodromou <evan@status.net>
25  * @author    Sarven Capadisli <csarven@status.net>
26  * @copyright 2008-2011 StatusNet, Inc.
27  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
28  * @link      http://status.net/
29  */
30
31 if (!defined('GNUSOCIAL')) { exit(1); }
32
33 /**
34  * Profile action common superclass
35  *
36  * Abstracts out common code from profile and personal tabs
37  *
38  * @category Personal
39  * @package  StatusNet
40  * @author   Evan Prodromou <evan@status.net>
41  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
42  * @link     http://status.net/
43  */
44 abstract class ProfileAction extends ManagedAction
45 {
46     var $page    = null;
47     var $tag     = null;
48
49     protected $target  = null;    // Profile that we're showing
50
51     protected function doPreparation()
52     {
53         try {
54             $nickname_arg = $this->arg('nickname');
55             $nickname     = common_canonical_nickname($nickname_arg);
56
57             // Permanent redirect on non-canonical nickname
58
59             if ($nickname_arg != $nickname) {
60                 $args = array('nickname' => $nickname);
61                 if ($this->arg('page') && $this->arg('page') != 1) {
62                     $args['page'] = $this->arg['page'];
63                 }
64                 common_redirect(common_local_url($this->getActionName(), $args), 301);
65             }
66             $this->user = User::getKV('nickname', $nickname);
67
68             if (!$this->user) {
69                 $group = Local_group::getKV('nickname', $nickname);
70                 if ($group instanceof Local_group) {
71                     common_redirect($group->getProfile()->getUrl());
72                 }
73                 // TRANS: Client error displayed when calling a profile action without specifying a user.
74                 $this->clientError(_('No such user.'), 404);
75             }
76
77             $this->target = $this->user->getProfile();
78         } catch (NicknameException $e) {
79             $id = (int)$this->arg('id');
80             $this->target = Profile::getKV('id', $id);
81
82             if (!$this->target instanceof Profile) {
83                 // TRANS: Error message displayed when referring to a user without a profile.
84                 $this->serverError(_m('Profile ID does not exist.'));
85             }
86
87             if ($this->target->isLocal()) {
88                 // For local users when accessed by id number, redirect to
89                 // the same action but using the nickname as argument.
90                 common_redirect(common_local_url($this->getActionName(),
91                                                 array('nickname'=>$user->getNickname())));
92             }
93         }
94
95         if ($this->target->hasRole(Profile_role::SILENCED) &&
96             (empty($this->scoped) || !$this->scoped->hasRight(Right::SILENCEUSER))) {
97             throw new ClientException(_('This profile has been silenced by site moderators'), 403);
98         }
99
100         // backwards compatibility until all actions are fixed to use $this->target
101         $this->profile = $this->target;
102
103         $this->tag = $this->trimmed('tag');
104         $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
105         common_set_returnto($this->selfUrl());
106
107         return $this->profileActionPreparation();
108     }
109
110     protected function profileActionPreparation()
111     {
112         // No-op by default.
113     }
114
115     function isReadOnly($args)
116     {
117         return true;
118     }
119
120     function showSections()
121     {
122         $this->showSubscriptions();
123         $this->showSubscribers();
124         $this->showGroups();
125         $this->showLists();
126         $this->showStatistics();
127     }
128
129     /**
130      * Convenience function for common pattern of links to subscription/groups sections.
131      *
132      * @param string $actionClass
133      * @param string $title
134      * @param string $cssClass
135      */
136     private function statsSectionLink($actionClass, $title, $cssClass='')
137     {
138         $this->element('a', array('href' => common_local_url($actionClass,
139                                                              array('nickname' => $this->target->getNickname())),
140                                   'class' => $cssClass),
141                        $title);
142     }
143
144     function showSubscriptions()
145     {
146         $this->elementStart('div', array('id' => 'entity_subscriptions',
147                                          'class' => 'section'));
148         if (Event::handle('StartShowSubscriptionsMiniList', array($this))) {
149             $this->elementStart('h2');
150             // TRANS: H2 text for user subscription statistics.
151             $this->statsSectionLink('subscriptions', _('Following'));
152             $this->text(' ');
153             $this->text($this->target->subscriptionCount());
154             $this->elementEnd('h2');
155         
156             try {
157                 $profile = $this->target->getSubscribed(0, PROFILES_PER_MINILIST + 1);
158                 $pml = new ProfileMiniList($profile, $this);
159                 $pml->show();
160             } catch (NoResultException $e) {
161                 // TRANS: Text for user subscription statistics if the user has no subscription
162                 $this->element('p', null, _('(None)'));
163             }
164
165             Event::handle('EndShowSubscriptionsMiniList', array($this));
166         }
167         $this->elementEnd('div');
168     }
169
170     function showSubscribers()
171     {
172         $this->elementStart('div', array('id' => 'entity_subscribers',
173                                          'class' => 'section'));
174
175         if (Event::handle('StartShowSubscribersMiniList', array($this))) {
176
177             $this->elementStart('h2');
178             // TRANS: H2 text for user subscriber statistics.
179             $this->statsSectionLink('subscribers', _('Followers'));
180             $this->text(' ');
181             $this->text($this->target->subscriberCount());
182             $this->elementEnd('h2');
183
184             try {
185                 $profile = $this->target->getSubscribers(0, PROFILES_PER_MINILIST + 1);
186                 $sml = new SubscribersMiniList($profile, $this);
187                 $sml->show();
188             } catch (NoResultException $e) {
189                 // TRANS: Text for user subscriber statistics if user has no subscribers.
190                 $this->element('p', null, _('(None)'));
191             }
192
193             Event::handle('EndShowSubscribersMiniList', array($this));
194         }
195
196         $this->elementEnd('div');
197     }
198
199     function showStatistics()
200     {
201         $notice_count = $this->target->noticeCount();
202         $age_days     = (time() - strtotime($this->target->created)) / 86400;
203         if ($age_days < 1) {
204             // Rather than extrapolating out to a bajillion...
205             $age_days = 1;
206         }
207         $daily_count = round($notice_count / $age_days);
208
209         $this->elementStart('div', array('id' => 'entity_statistics',
210                                          'class' => 'section'));
211
212         // TRANS: H2 text for user statistics.
213         $this->element('h2', null, _('Statistics'));
214
215         $profile = $this->target;
216         $actionParams = array('nickname' => $profile->nickname);
217         $stats = array(
218             array(
219                 'id' => 'user-id',
220                 // TRANS: Label for user statistics.
221                 'label' => _('User ID'),
222                 'value' => $profile->id,
223             ),
224             array(
225                 'id' => 'member-since',
226                 // TRANS: Label for user statistics.
227                 'label' => _('Member since'),
228                 'value' => date('j M Y', strtotime($profile->created))
229             ),
230             array(
231                 'id' => 'notices',
232                 // TRANS: Label for user statistics.
233                 'label' => _('Notices'),
234                 'value' => $notice_count,
235             ),
236             array(
237                 'id' => 'daily_notices',
238                 // TRANS: Label for user statistics.
239                 // TRANS: Average count of posts made per day since account registration.
240                 'label' => _('Daily average'),
241                 'value' => $daily_count
242             )
243         );
244
245         // Give plugins a chance to add stats entries
246         Event::handle('ProfileStats', array($profile, &$stats));
247
248         foreach ($stats as $row) {
249             $this->showStatsRow($row);
250         }
251         $this->elementEnd('div');
252     }
253
254     private function showStatsRow($row)
255     {
256         $this->elementStart('dl', 'entity_' . $row['id']);
257         $this->elementStart('dt');
258         if (!empty($row['link'])) {
259             $this->element('a', array('href' => $row['link']), $row['label']);
260         } else {
261             $this->text($row['label']);
262         }
263         $this->elementEnd('dt');
264         $this->element('dd', null, $row['value']);
265         $this->elementEnd('dl');
266     }
267
268     function showGroups()
269     {
270         $groups = $this->target->getGroups(0, GROUPS_PER_MINILIST + 1);
271
272         $this->elementStart('div', array('id' => 'entity_groups',
273                                          'class' => 'section'));
274         if (Event::handle('StartShowGroupsMiniList', array($this))) {
275             $this->elementStart('h2');
276             // TRANS: H2 text for user group membership statistics.
277             $this->statsSectionLink('usergroups', _('Groups'));
278             $this->text(' ');
279             $this->text($this->target->getGroupCount());
280             $this->elementEnd('h2');
281
282             if ($groups instanceof User_group) {
283                 $gml = new GroupMiniList($groups, $this->target, $this);
284                 $cnt = $gml->show();
285             } else {
286                 // TRANS: Text for user user group membership statistics if user is not a member of any group.
287                 $this->element('p', null, _('(None)'));
288             }
289
290             Event::handle('EndShowGroupsMiniList', array($this));
291         }
292             $this->elementEnd('div');
293     }
294
295     function showLists()
296     {
297         $lists = $this->target->getLists($this->scoped);
298
299         if ($lists->N > 0) {
300             $this->elementStart('div', array('id' => 'entity_lists',
301                                              'class' => 'section'));
302
303             if (Event::handle('StartShowListsMiniList', array($this))) {
304
305                 $url = common_local_url('peopletagsbyuser',
306                                         array('nickname' => $this->target->getNickname()));
307
308                 $this->elementStart('h2');
309                 $this->element('a',
310                                array('href' => $url),
311                                // TRANS: H2 text for user list membership statistics.
312                                _('Lists'));
313                 $this->text(' ');
314                 $this->text($lists->N);
315                 $this->elementEnd('h2');
316
317                 $this->elementStart('ul');
318
319
320                 $first = true;
321
322                 while ($lists->fetch()) {
323                     if (!empty($lists->mainpage)) {
324                         $url = $lists->mainpage;
325                     } else {
326                         $url = common_local_url('showprofiletag',
327                                                 array('tagger' => $this->target->getNickname(),
328                                                       'tag'    => $lists->tag));
329                     }
330                     if (!$first) {
331                         $this->text(', ');
332                     } else {
333                         $first = false;
334                     }
335
336                     $this->element('a', array('href' => $url),
337                                    $lists->tag);
338                 }
339
340                 $this->elementEnd('ul');
341
342                 Event::handle('EndShowListsMiniList', array($this));
343             }
344             $this->elementEnd('div');
345         }
346     }
347 }
348
349 class SubscribersMiniList extends ProfileMiniList
350 {
351     function newListItem($profile)
352     {
353         return new SubscribersMiniListItem($profile, $this->action);
354     }
355 }
356
357 class SubscribersMiniListItem extends ProfileMiniListItem
358 {
359     function linkAttributes()
360     {
361         $aAttrs = parent::linkAttributes();
362         if (common_config('nofollow', 'subscribers')) {
363             $aAttrs['rel'] .= ' nofollow';
364         }
365         return $aAttrs;
366     }
367 }