]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - lib/facebookaction.php
Merge branch '0.8.x' into 0.9.x
[quix0rs-gnu-social.git] / lib / facebookaction.php
1 <?php
2 /**
3  * StatusNet, the distributed open-source microblogging tool
4  *
5  * Low-level generator for HTML
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  Faceboook
23  * @package   StatusNet
24  * @author    Zach Copley <zach@status.net>
25  * @copyright 2008 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('STATUSNET') && !defined('LACONICA'))
31 {
32     exit(1);
33 }
34
35 require_once INSTALLDIR.'/lib/facebookutil.php';
36 require_once INSTALLDIR.'/lib/noticeform.php';
37
38 class FacebookAction extends Action
39 {
40
41     var $facebook = null;
42     var $fbuid    = null;
43     var $flink    = null;
44     var $action   = null;
45     var $app_uri  = null;
46     var $app_name = null;
47
48     /**
49      * Constructor
50      *
51      * Just wraps the HTMLOutputter constructor.
52      *
53      * @param string  $output URI to output to, default = stdout
54      * @param boolean $indent Whether to indent output, default true
55      *
56      * @see XMLOutputter::__construct
57      * @see HTMLOutputter::__construct
58      */
59     function __construct($output='php://output', $indent=true, $facebook=null, $flink=null)
60     {
61         parent::__construct($output, $indent);
62
63         $this->facebook = $facebook;
64         $this->flink = $flink;
65
66         if ($this->flink) {
67             $this->fbuid = $flink->foreign_id;
68             $this->user = $flink->getUser();
69         }
70
71         $this->args = array();
72     }
73
74     function prepare($argarray)
75     {
76         parent::prepare($argarray);
77
78         $this->facebook = getFacebook();
79         $this->fbuid = $this->facebook->require_login();
80
81         $this->action = $this->trimmed('action');
82
83         $app_props = $this->facebook->api_client->Admin_getAppProperties(
84                 array('canvas_name', 'application_name'));
85
86         $this->app_uri = 'http://apps.facebook.com/' . $app_props['canvas_name'];
87         $this->app_name = $app_props['application_name'];
88
89         $this->flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_SERVICE);
90
91         return true;
92
93     }
94
95     function showStylesheets()
96     {
97         $this->cssLink('css/display.css', 'base');
98         $this->cssLink('css/display.css',null,'screen, projection, tv');
99         $this->cssLink('css/facebookapp.css', 'base');
100     }
101
102     function showScripts()
103     {
104         $this->script('js/facebookapp.js');
105     }
106
107     /**
108      * Start an Facebook ready HTML document
109      *
110      *  For Facebook we don't want to actually output any headers,
111      *  DTD info, etc.  Just Stylesheet and JavaScript links.
112      *
113      * If $type isn't specified, will attempt to do content negotiation.
114      *
115      * @param string $type MIME type to use; default is to do negotation.
116      *
117      * @return void
118      */
119
120     function startHTML($type=null)
121     {
122         $this->showStylesheets();
123         $this->showScripts();
124
125         $this->elementStart('div', array('class' => 'facebook-page'));
126     }
127
128     /**
129     *  Ends a Facebook ready HTML document
130     *
131     *  @return void
132     */
133     function endHTML()
134     {
135         $this->elementEnd('div');
136         $this->endXML();
137     }
138
139     /**
140      * Show notice form.
141      *
142      * MAY overload if no notice form needed... or direct message box????
143      *
144      * @return nothing
145      */
146     function showNoticeForm()
147     {
148         // don't do it for most of the Facebook pages
149     }
150
151     function showBody()
152     {
153         $this->elementStart('div', array('id' => 'wrap'));
154         $this->showHeader();
155         $this->showCore();
156         $this->showFooter();
157         $this->elementEnd('div');
158     }
159
160     function showAside()
161     {
162     }
163
164     function showHead($error, $success)
165     {
166
167         if ($error) {
168             $this->element("h1", null, $error);
169         }
170
171         if ($success) {
172             $this->element("h1", null, $success);
173         }
174
175         $this->elementStart('fb:if-section-not-added', array('section' => 'profile'));
176         $this->elementStart('span', array('id' => 'add_to_profile'));
177         $this->element('fb:add-section-button', array('section' => 'profile'));
178         $this->elementEnd('span');
179         $this->elementEnd('fb:if-section-not-added');
180
181     }
182
183     // Make this into a widget later
184     function showLocalNav()
185     {
186         $this->elementStart('ul', array('class' => 'nav'));
187
188         $this->elementStart('li', array('class' =>
189             ($this->action == 'facebookhome') ? 'current' : 'facebook_home'));
190         $this->element('a',
191             array('href' => 'index.php', 'title' => _('Home')), _('Home'));
192         $this->elementEnd('li');
193
194         if (common_config('invite', 'enabled')) {
195             $this->elementStart('li',
196                 array('class' =>
197                     ($this->action == 'facebookinvite') ? 'current' : 'facebook_invite'));
198             $this->element('a',
199                 array('href' => 'invite.php', 'title' => _('Invite')), _('Invite'));
200             $this->elementEnd('li');
201         }
202
203         $this->elementStart('li',
204             array('class' =>
205                 ($this->action == 'facebooksettings') ? 'current' : 'facebook_settings'));
206         $this->element('a',
207             array('href' => 'settings.php',
208                 'title' => _('Settings')), _('Settings'));
209         $this->elementEnd('li');
210
211         $this->elementEnd('ul');
212     }
213
214     /**
215      * Show header of the page.
216      *
217      * Calls template methods
218      *
219      * @return nothing
220      */
221     function showHeader()
222     {
223         $this->elementStart('div', array('id' => 'header'));
224         $this->showLogo();
225         $this->showNoticeForm();
226         $this->elementEnd('div');
227     }
228
229     /**
230      * Show page, a template method.
231      *
232      * @return nothing
233      */
234     function showPage($error = null, $success = null)
235     {
236         $this->startHTML();
237         $this->showHead($error, $success);
238         $this->showBody();
239         $this->endHTML();
240     }
241
242     function showInstructions()
243     {
244
245         $this->elementStart('div', array('class' => 'facebook_guide'));
246
247         $this->elementStart('dl', array('class' => 'system_notice'));
248         $this->element('dt', null, 'Page Notice');
249
250         $loginmsg_part1 = _('To use the %s Facebook Application you need to login ' .
251             'with your username and password. Don\'t have a username yet? ');
252         $loginmsg_part2 = _(' a new account.');
253
254         $this->elementStart('dd');
255         $this->elementStart('p');
256         $this->text(sprintf($loginmsg_part1, common_config('site', 'name')));
257         $this->element('a',
258             array('href' => common_local_url('register')), _('Register'));
259         $this->text($loginmsg_part2);
260     $this->elementEnd('p');
261         $this->elementEnd('dd');
262
263         $this->elementEnd('dl');
264         $this->elementEnd('div');
265     }
266
267     function showLoginForm($msg = null)
268     {
269
270         $this->elementStart('div', array('id' => 'content'));
271         $this->element('h1', null, _('Login'));
272
273         if ($msg) {
274              $this->element('fb:error', array('message' => $msg));
275         }
276
277         $this->showInstructions();
278
279         $this->elementStart('div', array('id' => 'content_inner'));
280
281         $this->elementStart('form', array('method' => 'post',
282                                                'class' => 'form_settings',
283                                                'id' => 'login',
284                                                'action' => 'index.php'));
285
286         $this->elementStart('fieldset');
287
288         $this->elementStart('ul', array('class' => 'form_datas'));
289         $this->elementStart('li');
290         $this->input('nickname', _('Nickname'));
291         $this->elementEnd('li');
292         $this->elementStart('li');
293         $this->password('password', _('Password'));
294         $this->elementEnd('li');
295         $this->elementEnd('ul');
296
297         $this->submit('submit', _('Login'));
298     $this->elementEnd('fieldset');
299         $this->elementEnd('form');
300
301         $this->elementStart('p');
302         $this->element('a', array('href' => common_local_url('recoverpassword')),
303                        _('Lost or forgotten password?'));
304         $this->elementEnd('p');
305
306         $this->elementEnd('div');
307         $this->elementEnd('div');
308
309     }
310
311     function updateProfileBox($notice)
312     {
313
314         // Need to include inline CSS for styling the Profile box
315
316     $app_props = $this->facebook->api_client->Admin_getAppProperties(array('icon_url'));
317     $icon_url = $app_props['icon_url'];
318
319         $style = '<style>
320      .entry-title *,
321      .entry-content * {
322      font-size:14px;
323      font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif;
324      }
325      .entry-title a,
326      .entry-content a {
327      color:#002E6E;
328      }
329
330          .entry-title .vcard .photo {
331          float:left;
332          display:inline;
333      margin-right:11px;
334      margin-bottom:11px
335          }
336      .entry-title {
337      margin-bottom:11px;
338      }
339          .entry-title p.entry-content {
340          display:inline;
341      margin-left:5px;
342          }
343
344      div.entry-content {
345      clear:both;
346      }
347          div.entry-content dl,
348          div.entry-content dt,
349          div.entry-content dd {
350          display:inline;
351      text-transform:lowercase;
352          }
353
354          div.entry-content dd,
355      div.entry-content .device dt {
356      margin-left:0;
357      margin-right:5px;
358          }
359          div.entry-content dl.timestamp dt,
360      div.entry-content dl.response dt {
361          display:none;
362          }
363          div.entry-content dd a {
364          display:inline-block;
365          }
366
367      #facebook_statusnet_app {
368      text-indent:-9999px;
369      height:16px;
370      width:16px;
371      display:block;
372      background:url('.$icon_url.') no-repeat 0 0;
373      float:right;
374      }
375          </style>';
376
377         $this->xw->openMemory();
378
379         $item = new FacebookProfileBoxNotice($notice, $this);
380         $item->show();
381
382         $fbml = "<fb:wide>$style " . $this->xw->outputMemory(false) . "</fb:wide>";
383         $fbml .= "<fb:narrow>$style " . $this->xw->outputMemory(false) . "</fb:narrow>";
384
385         $fbml_main = "<fb:narrow>$style " . $this->xw->outputMemory(false) . "</fb:narrow>";
386
387         $this->facebook->api_client->profile_setFBML(null, $this->fbuid, $fbml, null, null, $fbml_main);
388
389         $this->xw->openURI('php://output');
390     }
391
392     /**
393      * Generate pagination links
394      *
395      * @param boolean $have_before is there something before?
396      * @param boolean $have_after  is there something after?
397      * @param integer $page        current page
398      * @param string  $action      current action
399      * @param array   $args        rest of query arguments
400      *
401      * @return nothing
402      */
403     function pagination($have_before, $have_after, $page, $action, $args=null)
404     {
405         // Does a little before-after block for next/prev page
406         if ($have_before || $have_after) {
407             $this->elementStart('div', array('class' => 'pagination'));
408             $this->elementStart('dl', null);
409             $this->element('dt', null, _('Pagination'));
410             $this->elementStart('dd', null);
411             $this->elementStart('ul', array('class' => 'nav'));
412         }
413         if ($have_before) {
414             $pargs   = array('page' => $page-1);
415             $newargs = $args ? array_merge($args, $pargs) : $pargs;
416             $this->elementStart('li', array('class' => 'nav_prev'));
417             $this->element('a', array('href' => "$this->app_uri/$action?page=$newargs[page]", 'rel' => 'prev'),
418                            _('After'));
419             $this->elementEnd('li');
420         }
421         if ($have_after) {
422             $pargs   = array('page' => $page+1);
423             $newargs = $args ? array_merge($args, $pargs) : $pargs;
424             $this->elementStart('li', array('class' => 'nav_next'));
425             $this->element('a', array('href' => "$this->app_uri/$action?page=$newargs[page]", 'rel' => 'next'),
426                            _('Before'));
427             $this->elementEnd('li');
428         }
429         if ($have_before || $have_after) {
430             $this->elementEnd('ul');
431             $this->elementEnd('dd');
432             $this->elementEnd('dl');
433             $this->elementEnd('div');
434         }
435     }
436
437     function saveNewNotice()
438     {
439
440         $user = $this->flink->getUser();
441
442         $content = $this->trimmed('status_textarea');
443
444         if (!$content) {
445             $this->showPage(_('No notice content!'));
446             return;
447         } else {
448             $content_shortened = common_shorten_links($content);
449
450             if (Notice::contentTooLong($content_shortened)) {
451                 $this->showPage(sprintf(_('That\'s too long. Max notice size is %d chars.'),
452                                         Notice::maxContent()));
453                 return;
454             }
455         }
456
457         $inter = new CommandInterpreter();
458
459         $cmd = $inter->handle_command($user, $content_shortened);
460
461         if ($cmd) {
462
463             // XXX fix this
464
465             $cmd->execute(new WebChannel());
466             return;
467         }
468
469         $replyto = $this->trimmed('inreplyto');
470
471         try {
472             $notice = Notice::saveNew($user->id, $content,
473                                       'web', 1, ($replyto == 'false') ? null : $replyto);
474         } catch (Exception $e) {
475             $this->showPage($e->getMessage());
476             return;
477         }
478
479         common_broadcast_notice($notice);
480
481         // Also update the user's Facebook status
482         facebookBroadcastNotice($notice);
483
484     }
485
486 }
487
488 class FacebookNoticeForm extends NoticeForm
489 {
490
491     var $post_action = null;
492
493     /**
494      * Constructor
495      *
496      * @param HTMLOutputter $out     output channel
497      * @param string        $action  action to return to, if any
498      * @param string        $content content to pre-fill
499      */
500
501     function __construct($out=null, $action=null, $content=null,
502         $post_action=null, $user=null)
503     {
504         parent::__construct($out, $action, $content, $user);
505         $this->post_action = $post_action;
506     }
507
508     /**
509      * Action of the form
510      *
511      * @return string URL of the action
512      */
513
514     function action()
515     {
516         return $this->post_action;
517     }
518
519 }
520
521 class FacebookNoticeList extends NoticeList
522 {
523
524     /**
525      * constructor
526      *
527      * @param Notice $notice stream of notices from DB_DataObject
528      */
529
530     function __construct($notice, $out=null)
531     {
532         parent::__construct($notice, $out);
533     }
534
535     /**
536      * show the list of notices
537      *
538      * "Uses up" the stream by looping through it. So, probably can't
539      * be called twice on the same list.
540      *
541      * @return int count of notices listed.
542      */
543
544     function show()
545     {
546         $this->out->elementStart('div', array('id' =>'notices_primary'));
547         $this->out->element('h2', null, _('Notices'));
548         $this->out->elementStart('ul', array('class' => 'notices'));
549
550         $cnt = 0;
551
552         while ($this->notice->fetch() && $cnt <= NOTICES_PER_PAGE) {
553             $cnt++;
554
555             if ($cnt > NOTICES_PER_PAGE) {
556                 break;
557             }
558
559             $item = $this->newListItem($this->notice);
560             $item->show();
561         }
562
563         $this->out->elementEnd('ul');
564         $this->out->elementEnd('div');
565
566         return $cnt;
567     }
568
569     /**
570      * returns a new list item for the current notice
571      *
572      * Overridden to return a Facebook specific list item.
573      *
574      * @param Notice $notice the current notice
575      *
576      * @return FacebookNoticeListItem a list item for displaying the notice
577      * formatted for display in the Facebook App.
578      */
579
580     function newListItem($notice)
581     {
582         return new FacebookNoticeListItem($notice, $this);
583     }
584
585 }
586
587 class FacebookNoticeListItem extends NoticeListItem
588 {
589
590     /**
591      * constructor
592      *
593      * Also initializes the profile attribute.
594      *
595      * @param Notice $notice The notice we'll display
596      */
597
598     function __construct($notice, $out=null)
599     {
600         parent::__construct($notice, $out);
601     }
602
603     /**
604      * recipe function for displaying a single notice in the Facebook App.
605      *
606      * Overridden to strip out some of the controls that we don't
607      * want to be available.
608      *
609      * @return void
610      */
611
612     function show()
613     {
614         $this->showStart();
615         $this->showNotice();
616         $this->showNoticeInfo();
617
618         // XXX: Need to update to show attachements and controls
619
620         $this->showEnd();
621     }
622
623 }
624
625 class FacebookProfileBoxNotice extends FacebookNoticeListItem
626 {
627
628     /**
629      * constructor
630      *
631      * Also initializes the profile attribute.
632      *
633      * @param Notice $notice The notice we'll display
634      */
635
636     function __construct($notice, $out=null)
637     {
638         parent::__construct($notice, $out);
639     }
640
641     /**
642      * Recipe function for displaying a single notice in the
643      * Facebook App profile notice box
644      *
645      * @return void
646      */
647
648     function show()
649     {
650         $this->showNotice();
651         $this->showNoticeInfo();
652         $this->showAppLink();
653     }
654
655     function showAppLink()
656     {
657
658         $this->facebook = getFacebook();
659
660         $app_props = $this->facebook->api_client->Admin_getAppProperties(
661                 array('canvas_name', 'application_name'));
662
663         $this->app_uri = 'http://apps.facebook.com/' . $app_props['canvas_name'];
664         $this->app_name = $app_props['application_name'];
665
666         $this->out->elementStart('a', array('id' => 'facebook_statusnet_app',
667                                             'href' => $this->app_uri));
668         $this->out->text($this->app_name);
669         $this->out->elementEnd('a');
670     }
671
672 }