]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - actions/showstream.php
move opening brace of class declaration to next line
[quix0rs-gnu-social.git] / actions / showstream.php
1 <?php
2 /*
3  * Laconica - a distributed open-source microblogging tool
4  * Copyright (C) 2008, Controlez-Vous, Inc.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 if (!defined('LACONICA')) { exit(1); }
21
22 require_once(INSTALLDIR.'/lib/stream.php');
23
24 define('SUBSCRIPTIONS_PER_ROW', 4);
25 define('SUBSCRIPTIONS', 80);
26
27 class ShowstreamAction extends StreamAction
28 {
29
30     function handle($args)
31     {
32
33         parent::handle($args);
34
35         $nickname_arg = $this->arg('nickname');
36         $nickname = common_canonical_nickname($nickname_arg);
37
38         # Permanent redirect on non-canonical nickname
39
40         if ($nickname_arg != $nickname) {
41             $args = array('nickname' => $nickname);
42             if ($this->arg('page') && $this->arg('page') != 1) {
43                 $args['page'] = $this->arg['page'];
44             }
45             common_redirect(common_local_url('showstream', $args), 301);
46             return;
47         }
48
49         $user = User::staticGet('nickname', $nickname);
50
51         if (!$user) {
52             $this->no_such_user();
53             return;
54         }
55
56         $profile = $user->getProfile();
57
58         if (!$profile) {
59             common_server_error(_('User has no profile.'));
60             return;
61         }
62
63         # Looks like we're good; start output
64
65         # For YADIS discovery, we also have a <meta> tag
66
67         header('X-XRDS-Location: '. common_local_url('xrds', array('nickname' =>
68                                                                    $user->nickname)));
69
70         common_show_header($profile->nickname,
71                            array($this, 'show_header'), $user,
72                            array($this, 'show_top'));
73
74         $this->show_profile($profile);
75
76         $this->show_notices($user);
77
78         common_show_footer();
79     }
80
81     function show_top($user)
82     {
83         $cur = common_current_user();
84
85         if ($cur && $cur->id == $user->id) {
86             common_notice_form('showstream');
87         }
88
89         $this->views_menu();
90
91         $this->show_feeds_list(array(0=>array('href'=>common_local_url('userrss', array('nickname' => $user->nickname)),
92                                               'type' => 'rss',
93                                               'version' => 'RSS 1.0',
94                                               'item' => 'notices'),
95                                      1=>array('href'=>common_local_url('usertimeline', array('nickname' => $user->nickname)),
96                                               'type' => 'atom',
97                                               'version' => 'Atom 1.0',
98                                               'item' => 'usertimeline'),
99
100                                      2=>array('href'=>common_local_url('foaf',array('nickname' => $user->nickname)),
101                                               'type' => 'rdf',
102                                               'version' => 'FOAF',
103                                               'item' => 'foaf')));
104     }
105
106     function show_header($user)
107     {
108         # Feeds
109         common_element('link', array('rel' => 'alternate',
110                                      'href' => common_local_url('api',
111                                                                 array('apiaction' => 'statuses',
112                                                                       'method' => 'user_timeline.rss',
113                                                                       'argument' => $user->nickname)),
114                                      'type' => 'application/rss+xml',
115                                      'title' => sprintf(_('Notice feed for %s'), $user->nickname)));
116         common_element('link', array('rel' => 'alternate feed',
117                                      'href' => common_local_url('api',
118                                                                 array('apiaction' => 'statuses',
119                                                                       'method' => 'user_timeline.atom',
120                                                                       'argument' => $user->nickname)),
121                                      'type' => 'application/atom+xml',
122                                      'title' => sprintf(_('Notice feed for %s'), $user->nickname)));
123         common_element('link', array('rel' => 'alternate',
124                                      'href' => common_local_url('userrss', array('nickname' =>
125                                                                                $user->nickname)),
126                                      'type' => 'application/rdf+xml',
127                                      'title' => sprintf(_('Notice feed for %s'), $user->nickname)));
128         # FOAF
129         common_element('link', array('rel' => 'meta',
130                                      'href' => common_local_url('foaf', array('nickname' =>
131                                                                               $user->nickname)),
132                                      'type' => 'application/rdf+xml',
133                                      'title' => 'FOAF'));
134         # for remote subscriptions etc.
135         common_element('meta', array('http-equiv' => 'X-XRDS-Location',
136                                      'content' => common_local_url('xrds', array('nickname' =>
137                                                                                $user->nickname))));
138         $profile = $user->getProfile();
139         if ($profile->bio) {
140             common_element('meta', array('name' => 'description',
141                                          'content' => $profile->bio));
142         }
143
144         if ($user->emailmicroid && $user->email && $profile->profileurl) {
145             common_element('meta', array('name' => 'microid',
146                                          'content' => "mailto+http:sha1:" . sha1(sha1('mailto:' . $user->email) . sha1($profile->profileurl))));
147         }
148         if ($user->jabbermicroid && $user->jabber && $profile->profileurl) {
149             common_element('meta', array('name' => 'microid',
150                                          'content' => "xmpp+http:sha1:" . sha1(sha1('xmpp:' . $user->jabber) . sha1($profile->profileurl))));
151         }
152
153         # See https://wiki.mozilla.org/Microsummaries
154
155         common_element('link', array('rel' => 'microsummary',
156                                      'href' => common_local_url('microsummary',
157                                                                 array('nickname' => $profile->nickname))));
158     }
159
160     function no_such_user()
161     {
162         $this->client_error(_('No such user.'), 404);
163     }
164
165     function show_profile($profile)
166     {
167
168         common_element_start('div', array('id' => 'profile', 'class' => 'vcard'));
169
170         $this->show_personal($profile);
171
172         $this->show_last_notice($profile);
173
174         $cur = common_current_user();
175
176         $this->show_subscriptions($profile);
177
178         common_element_end('div');
179     }
180
181     function show_personal($profile)
182     {
183
184         $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
185         common_element_start('div', array('id' => 'profile_avatar'));
186         common_element('img', array('src' => ($avatar) ? common_avatar_display_url($avatar) : common_default_avatar(AVATAR_PROFILE_SIZE),
187                                     'class' => 'avatar profile photo',
188                                     'width' => AVATAR_PROFILE_SIZE,
189                                     'height' => AVATAR_PROFILE_SIZE,
190                                     'alt' => $profile->nickname));
191
192         common_element_start('ul', array('id' => 'profile_actions'));
193
194         common_element_start('li', array('id' => 'profile_subscribe'));
195         $cur = common_current_user();
196         if ($cur) {
197             if ($cur->id != $profile->id) {
198                 if ($cur->isSubscribed($profile)) {
199                     common_unsubscribe_form($profile);
200                 } else {
201                     common_subscribe_form($profile);
202                 }
203             }
204         } else {
205             $this->show_remote_subscribe_link($profile);
206         }
207         common_element_end('li');
208
209         $user = User::staticGet('id', $profile->id);
210         common_profile_new_message_nudge($cur, $user, $profile);
211
212         if ($cur && $cur->id != $profile->id) {
213             $blocked = $cur->hasBlocked($profile);
214             common_element_start('li', array('id' => 'profile_block'));
215             if ($blocked) {
216                 common_unblock_form($profile, array('action' => 'showstream',
217                                                     'nickname' => $profile->nickname));
218             } else {
219                 common_block_form($profile, array('action' => 'showstream',
220                                                   'nickname' => $profile->nickname));
221             }
222             common_element_end('li');
223         }
224
225         common_element_end('ul');
226
227         common_element_end('div');
228
229         common_element_start('div', array('id' => 'profile_information'));
230
231         if ($profile->fullname) {
232             common_element('h1', array('class' => 'fn'), $profile->fullname . ' (' . $profile->nickname . ')');
233         } else {
234             common_element('h1', array('class' => 'fn nickname'), $profile->nickname);
235         }
236
237         if ($profile->location) {
238             common_element('p', 'location', $profile->location);
239         }
240         if ($profile->bio) {
241             common_element('p', 'description note', $profile->bio);
242         }
243         if ($profile->homepage) {
244             common_element_start('p', 'website');
245             common_element('a', array('href' => $profile->homepage,
246                                       'rel' => 'me', 'class' => 'url'),
247                            $profile->homepage);
248             common_element_end('p');
249         }
250
251         $this->show_statistics($profile);
252
253         common_element_end('div');
254     }
255
256     function show_remote_subscribe_link($profile)
257     {
258         $url = common_local_url('remotesubscribe',
259                                 array('nickname' => $profile->nickname));
260         common_element('a', array('href' => $url,
261                                   'id' => 'remotesubscribe'),
262                        _('Subscribe'));
263     }
264
265     function show_unsubscribe_form($profile)
266     {
267         common_element_start('form', array('id' => 'unsubscribe', 'method' => 'post',
268                                            'action' => common_local_url('unsubscribe')));
269         common_hidden('token', common_session_token());
270         common_element('input', array('id' => 'unsubscribeto',
271                                       'name' => 'unsubscribeto',
272                                       'type' => 'hidden',
273                                       'value' => $profile->nickname));
274         common_element('input', array('type' => 'submit',
275                                       'class' => 'submit',
276                                       'value' => _('Unsubscribe')));
277         common_element_end('form');
278     }
279
280     function show_subscriptions($profile)
281     {
282         global $config;
283
284         $subs = DB_DataObject::factory('subscription');
285         $subs->subscriber = $profile->id;
286         $subs->whereAdd('subscribed != ' . $profile->id);
287
288         $subs->orderBy('created DESC');
289
290         # We ask for an extra one to know if we need to do another page
291
292         $subs->limit(0, SUBSCRIPTIONS + 1);
293
294         $subs_count = $subs->find();
295
296         common_element_start('div', array('id' => 'subscriptions'));
297
298         common_element('h2', null, _('Subscriptions'));
299
300         if ($subs_count > 0) {
301
302             common_element_start('ul', array('id' => 'subscriptions_avatars'));
303
304             for ($i = 0; $i < min($subs_count, SUBSCRIPTIONS); $i++) {
305
306                 if (!$subs->fetch()) {
307                     common_debug('Weirdly, broke out of subscriptions loop early', __FILE__);
308                     break;
309                 }
310
311                 $other = Profile::staticGet($subs->subscribed);
312
313                 if (!$other) {
314                     common_log_db_error($subs, 'SELECT', __FILE__);
315                     continue;
316                 }
317
318                 common_element_start('li', 'vcard');
319                 common_element_start('a', array('title' => ($other->fullname) ?
320                                                 $other->fullname :
321                                                 $other->nickname,
322                                                 'href' => $other->profileurl,
323                                                 'rel' => 'contact',
324                                                  'class' => 'subscription fn url'));
325                 $avatar = $other->getAvatar(AVATAR_MINI_SIZE);
326                 common_element('img', array('src' => (($avatar) ? common_avatar_display_url($avatar) :  common_default_avatar(AVATAR_MINI_SIZE)),
327                                             'width' => AVATAR_MINI_SIZE,
328                                             'height' => AVATAR_MINI_SIZE,
329                                             'class' => 'avatar mini photo',
330                                             'alt' =>  ($other->fullname) ?
331                                             $other->fullname :
332                                             $other->nickname));
333                 common_element_end('a');
334                 common_element_end('li');
335             }
336
337             common_element_end('ul');
338         }
339
340         if ($subs_count > SUBSCRIPTIONS) {
341             common_element_start('p', array('id' => 'subscriptions_viewall'));
342
343             common_element('a', array('href' => common_local_url('subscriptions',
344                                                                  array('nickname' => $profile->nickname)),
345                                       'class' => 'moresubscriptions'),
346                            _('All subscriptions'));
347             common_element_end('p');
348         }
349
350         common_element_end('div');
351     }
352
353     function show_statistics($profile)
354     {
355
356         // XXX: WORM cache this
357         $subs = DB_DataObject::factory('subscription');
358         $subs->subscriber = $profile->id;
359         $subs_count = (int) $subs->count() - 1;
360
361         $subbed = DB_DataObject::factory('subscription');
362         $subbed->subscribed = $profile->id;
363         $subbed_count = (int) $subbed->count() - 1;
364
365         $notices = DB_DataObject::factory('notice');
366         $notices->profile_id = $profile->id;
367         $notice_count = (int) $notices->count();
368
369         common_element_start('div', 'statistics');
370         common_element('h2', 'statistics', _('Statistics'));
371
372         # Other stats...?
373         common_element_start('dl', 'statistics');
374         common_element('dt', 'membersince', _('Member since'));
375         common_element('dd', 'membersince', date('j M Y',
376                                                  strtotime($profile->created)));
377
378         common_element_start('dt', 'subscriptions');
379         common_element('a', array('href' => common_local_url('subscriptions',
380                                                              array('nickname' => $profile->nickname))),
381                        _('Subscriptions'));
382         common_element_end('dt');
383         common_element('dd', 'subscriptions', (is_int($subs_count)) ? $subs_count : '0');
384         common_element_start('dt', 'subscribers');
385         common_element('a', array('href' => common_local_url('subscribers',
386                                                              array('nickname' => $profile->nickname))),
387                        _('Subscribers'));
388         common_element_end('dt');
389         common_element('dd', 'subscribers', (is_int($subbed_count)) ? $subbed_count : '0');
390         common_element('dt', 'notices', _('Notices'));
391         common_element('dd', 'notices', (is_int($notice_count)) ? $notice_count : '0');
392         # XXX: link these to something
393         common_element('dt', 'tags', _('Tags'));
394         common_element_start('dd', 'tags');
395         $tags = Profile_tag::getTags($profile->id, $profile->id);
396
397         common_element_start('ul', 'tags xoxo');
398         foreach ($tags as $tag) {
399             common_element_start('li');
400             common_element('a', array('rel' => 'bookmark tag',
401                                       'href' => common_local_url('peopletag',
402                                                                  array('tag' => $tag))),
403                            $tag);
404             common_element_end('li');
405         }
406         common_element_end('ul');
407         common_element_end('dd');
408
409         common_element_end('dl');
410
411         common_element_end('div');
412     }
413
414     function show_notices($user)
415     {
416
417         $page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
418
419         $notice = $user->getNotices(($page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
420
421         $pnl = new ProfileNoticeList($notice);
422         $cnt = $pnl->show();
423
424         common_pagination($page>1, $cnt>NOTICES_PER_PAGE, $page,
425                           'showstream', array('nickname' => $user->nickname));
426     }
427
428     function show_last_notice($profile)
429     {
430
431         common_element('h2', null, _('Currently'));
432
433         $notice = $profile->getCurrentNotice();
434
435         if ($notice) {
436             # FIXME: URL, image, video, audio
437             common_element_start('p', array('class' => 'notice_current'));
438             if ($notice->rendered) {
439                 common_raw($notice->rendered);
440             } else {
441                 # XXX: may be some uncooked notices in the DB,
442                 # we cook them right now. This can probably disappear in future
443                 # versions (>> 0.4.x)
444                 common_raw(common_render_content($notice->content, $notice));
445             }
446             common_element_end('p');
447         }
448     }
449 }
450
451 # We don't show the author for a profile, since we already know who it is!
452
453 class ProfileNoticeList extends NoticeList
454 {
455     function newListItem($notice)
456     {
457         return new ProfileNoticeListItem($notice);
458     }
459 }
460
461 class ProfileNoticeListItem extends NoticeListItem
462 {
463     function showAuthor()
464     {
465         return;
466     }
467 }