]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - lib/facebookaction.php
Merge branch 'master' of /var/www/trunk
[quix0rs-gnu-social.git] / lib / facebookaction.php
1 <?php
2 /**
3  * Laconica, 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   Laconica
24  * @author    Zach Copley <zach@controlyourself.ca>
25  * @copyright 2008 Control Yourself, Inc.
26  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
27  * @link      http://laconi.ca/
28  */
29
30 if (!defined('LACONICA'))
31 {
32     exit(1);
33 }
34
35 require_once INSTALLDIR.'/lib/facebookutil.php';
36 require_once INSTALLDIR.'/lib/noticeform.php';
37
38
39 class FacebookAction extends Action
40 {
41     
42     var $facebook = null;
43     var $fbuid    = null;
44     var $flink    = null;
45     var $action   = null;
46     var $app_uri  = null;
47     var $app_name = null;
48   
49     /**
50      * Constructor
51      *
52      * Just wraps the HTMLOutputter constructor.
53      *
54      * @param string  $output URI to output to, default = stdout
55      * @param boolean $indent Whether to indent output, default true
56      *
57      * @see XMLOutputter::__construct
58      * @see HTMLOutputter::__construct
59      */
60     function __construct($output='php://output', $indent=true, $facebook=null, $flink=null)
61     {
62         parent::__construct($output, $indent);
63         
64         $this->facebook = $facebook;
65         $this->flink = $flink;
66         
67         if ($this->flink) {
68             $this->fbuid = $flink->foreign_id; 
69             $this->user = $flink->getUser();
70         }
71     }
72   
73     function prepare($argarray)
74     {        
75         parent::prepare($argarray);
76           
77         $this->facebook = getFacebook();
78         $this->fbuid = $this->facebook->require_login();
79         
80         $this->action = $this->trimmed('action');
81         
82         $app_props = $this->facebook->api_client->Admin_getAppProperties(
83                 array('canvas_name', 'application_name'));
84         
85         $this->app_uri = 'http://apps.facebook.com/' . $app_props['canvas_name'];
86         $this->app_name = $app_props['application_name'];
87
88         $this->flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_SERVICE);
89         
90         return true;
91         
92     }
93   
94     function showStylesheets()
95     {
96         
97         $this->element('link', array('rel' => 'stylesheet',
98                                      'type' => 'text/css',
99                                      'href' => getFacebookBaseCSS()));
100
101         $this->element('link', array('rel' => 'stylesheet',
102                                      'type' => 'text/css',
103                                      'href' => getFacebookThemeCSS()));
104     }
105   
106     function showScripts()
107     {
108         $this->element('script', array('type' => 'text/javascript',
109                                        'src' => getFacebookJS()),
110                        ' ');
111     }
112     
113     /**
114      * Start an Facebook ready HTML document
115      *
116      *  For Facebook we don't want to actually output any headers,
117      *  DTD info, etc.
118      *
119      * If $type isn't specified, will attempt to do content negotiation.
120      *
121      * @param string $type MIME type to use; default is to do negotation.
122      *
123      * @return void
124      */
125
126     function startHTML($type=null) 
127     {          
128         $this->elementStart('div', array('class' => 'facebook-page'));
129     }
130
131     /**
132     *  Ends a Facebook ready HTML document
133     *
134     *  @return void
135     */
136     function endHTML()
137     {
138         $this->elementEnd('div');
139         $this->endXML();
140     }
141
142     /**
143      * Show notice form.
144      *
145      * MAY overload if no notice form needed... or direct message box????
146      *
147      * @return nothing
148      */
149     function showNoticeForm()
150     {
151         // don't do it for most of the Facebook pages
152     }
153
154     function showBody()
155     {
156         $this->elementStart('div', 'wrap');
157         $this->showHeader();
158         $this->showCore();
159         $this->showFooter();
160         $this->elementEnd('div');
161     }
162       
163     function showAside()
164     {
165     }
166
167     function showHead($error, $success)
168     {
169         $this->showStylesheets();
170         $this->showScripts();
171         
172         if ($error) {
173             $this->element("h1", null, $error);
174         }
175         
176         if ($success) {
177             $this->element("h1", null, $success);
178         }
179
180         $this->elementStart('fb:if-section-not-added', array('section' => 'profile'));
181         $this->elementStart('span', array('id' => 'add_to_profile'));
182         $this->element('fb:add-section-button', array('section' => 'profile'));
183         $this->elementEnd('span');
184         $this->elementEnd('fb:if-section-not-added');
185         
186     }
187
188     
189     // Make this into a widget later
190     function showLocalNav()
191     {
192                 
193         $this->elementStart('ul', array('class' => 'nav'));
194
195         $this->elementStart('li', array('class' =>
196             ($this->action == 'facebookhome') ? 'current' : 'facebook_home'));
197         $this->element('a',
198             array('href' => 'index.php', 'title' => _('Home')), _('Home'));
199         $this->elementEnd('li');
200
201         $this->elementStart('li',
202             array('class' =>
203                 ($this->action == 'facebookinvite') ? 'current' : 'facebook_invite'));
204         $this->element('a',
205             array('href' => 'invite.php', 'title' => _('Invite')), _('Invite'));
206         $this->elementEnd('li');
207
208         $this->elementStart('li',
209             array('class' =>
210                 ($this->action == 'facebooksettings') ? 'current' : 'facebook_settings'));
211         $this->element('a',
212             array('href' => 'settings.php',
213                 'title' => _('Settings')), _('Settings'));
214         $this->elementEnd('li');
215
216         $this->elementEnd('ul');
217
218     }     
219
220     /**
221      * Show primary navigation.
222      *
223      * @return nothing
224      */
225     function showPrimaryNav()
226     {
227         // we don't want to show anything for this
228     }
229     
230     /**
231      * Show header of the page.
232      *
233      * Calls template methods
234      *
235      * @return nothing
236      */
237     function showHeader()
238     {
239         $this->elementStart('div', array('id' => 'header'));
240         $this->showLogo();
241         $this->showNoticeForm();
242         $this->showPrimaryNav();
243         $this->elementEnd('div');
244     }
245     
246     /**
247      * Show page, a template method.
248      *
249      * @return nothing
250      */
251     function showPage($error = null, $success = null)
252     {
253         $this->startHTML();
254         $this->showHead($error, $success);
255         $this->showBody();
256         $this->endHTML();
257     }
258     
259
260     function showInstructions()
261     {
262
263         $this->elementStart('dl', array('class' => 'system_notice'));
264         $this->element('dt', null, 'Page Notice');
265
266         $loginmsg_part1 = _('To use the %s Facebook Application you need to login ' .
267             'with your username and password. Don\'t have a username yet? ');
268
269         $loginmsg_part2 = _(' a new account.');
270
271         $this->elementStart('dd');
272         $this->elementStart('p');
273         $this->text(sprintf($loginmsg_part1, common_config('site', 'name')));
274         $this->element('a',
275             array('href' => common_local_url('register')), _('Register'));
276         $this->text($loginmsg_part2);
277         $this->elementEnd('dd');
278         $this->elementEnd('dl');
279     }
280
281
282     function showLoginForm($msg = null)
283     {
284
285         $this->elementStart('div', array('class' => 'content'));
286         $this->element('h1', null, _('Login'));
287
288         if ($msg) {
289              $this->element('fb:error', array('message' => $msg));
290         }
291
292         $this->showInstructions();
293
294         $this->elementStart('div', array('id' => 'content_inner'));
295
296         $this->elementStart('form', array('method' => 'post',
297                                                'class' => 'form_settings',
298                                                'id' => 'login',
299                                                'action' => 'index.php'));
300
301         $this->elementStart('fieldset');
302         $this->element('legend', null, _('Login to site'));
303
304         $this->elementStart('ul', array('class' => 'form_datas'));
305         $this->elementStart('li');
306         $this->input('nickname', _('Nickname'));
307         $this->elementEnd('li');
308         $this->elementStart('li');
309         $this->password('password', _('Password'));
310         $this->elementEnd('li');
311         $this->elementEnd('ul');
312
313         $this->submit('submit', _('Login'));
314         $this->elementEnd('form');
315
316         $this->elementStart('p');
317         $this->element('a', array('href' => common_local_url('recoverpassword')),
318                        _('Lost or forgotten password?'));
319         $this->elementEnd('p');
320
321         $this->elementEnd('div');
322
323     }
324     
325     
326     function updateProfileBox($notice)
327     {
328
329         // Need to include inline CSS for styling the Profile box
330
331         $style = '<style>
332          #notices {
333              clear: both;
334              margin: 0 auto;
335              padding: 0;
336              list-style-type: none;
337              width: 600px;
338              border-top: 1px solid #dec5b5;
339          }
340          #notices a:hover {
341              text-decoration: underline;
342          }
343          .notice_single {
344              clear: both;
345              display: block;
346              margin: 0;
347              padding: 5px 5px 5px 0;
348              min-height: 48px;
349              font-family: Georgia, "Times New Roman", Times, serif;
350              font-size: 13px;
351              line-height: 16px;
352              border-bottom: 1px solid #dec5b5;
353              background-color:#FCFFF5;
354              opacity:1;
355          }
356          .notice_single:hover {
357              background-color: #f7ebcc;
358          }
359          .notice_single p {
360              display: inline;
361              margin: 0;
362              padding: 0;
363          }
364          </style>';        
365
366         $this->xw->openMemory();
367
368         $item = new FacebookNoticeListItem($notice, $this);
369         $item->show();
370
371         $fbml = "<fb:wide>$style " . $this->xw->outputMemory(false) . "</fb:wide>";
372         $fbml .= "<fb:narrow>$style " . $this->xw->outputMemory(false) . "</fb:narrow>";
373
374         $fbml_main = "<fb:narrow>$style " . $this->xw->outputMemory(false) . "</fb:narrow>";
375
376         $this->facebook->api_client->profile_setFBML(null, $this->fbuid, $fbml, null, null, $fbml_main);  
377
378         $this->xw->openURI('php://output');
379     }
380     
381     
382     /**
383      * Generate pagination links
384      *
385      * @param boolean $have_before is there something before?
386      * @param boolean $have_after  is there something after?
387      * @param integer $page        current page
388      * @param string  $action      current action
389      * @param array   $args        rest of query arguments
390      *
391      * @return nothing
392      */
393     function pagination($have_before, $have_after, $page, $action, $args=null)
394     {
395         // Does a little before-after block for next/prev page
396         if ($have_before || $have_after) {
397             $this->elementStart('div', array('class' => 'pagination'));
398             $this->elementStart('dl', null);
399             $this->element('dt', null, _('Pagination'));
400             $this->elementStart('dd', null);
401             $this->elementStart('ul', array('class' => 'nav'));
402         }
403         if ($have_before) {
404             $pargs   = array('page' => $page-1);
405             $newargs = $args ? array_merge($args, $pargs) : $pargs;
406             $this->elementStart('li', array('class' => 'nav_prev'));
407             $this->element('a', array('href' => "$this->app_uri/$action?page=$newargs[page]", 'rel' => 'prev'),
408                            _('After'));
409             $this->elementEnd('li');
410         }
411         if ($have_after) {
412             $pargs   = array('page' => $page+1);
413             $newargs = $args ? array_merge($args, $pargs) : $pargs;
414             $this->elementStart('li', array('class' => 'nav_next'));
415             $this->element('a', array('href' => "$this->app_uri/$action?page=$newargs[page]", 'rel' => 'next'),
416                            _('Before'));
417             $this->elementEnd('li');
418         }
419         if ($have_before || $have_after) {
420             $this->elementEnd('ul');
421             $this->elementEnd('dd');
422             $this->elementEnd('dl');
423             $this->elementEnd('div');
424         }
425     }
426     
427
428 }
429
430 class FacebookNoticeForm extends NoticeForm 
431 {
432     
433     var $post_action = null;
434     
435     /**
436      * Constructor
437      *
438      * @param HTMLOutputter $out     output channel
439      * @param string        $action  action to return to, if any
440      * @param string        $content content to pre-fill
441      */
442
443     function __construct($out=null, $action=null, $content=null, 
444         $post_action=null, $user=null)
445     {
446         parent::__construct($out, $action, $content, $user);
447         $this->post_action = $post_action;
448     }
449     
450     /**
451      * Action of the form
452      *
453      * @return string URL of the action
454      */
455
456     function action()
457     {
458         return $this->post_action;
459     }
460
461 }
462
463 class FacebookNoticeList extends NoticeList
464 {
465     /**
466      * show the list of notices
467      *
468      * "Uses up" the stream by looping through it. So, probably can't
469      * be called twice on the same list.
470      *
471      * @return int count of notices listed.
472      */
473
474     function show()
475     {
476         $this->out->elementStart('div', array('id' =>'notices_primary'));
477         $this->out->element('h2', null, _('Notices'));
478         $this->out->elementStart('ul', array('class' => 'notices'));
479
480         $cnt = 0;
481
482         while ($this->notice->fetch() && $cnt <= NOTICES_PER_PAGE) {
483             $cnt++;
484
485             if ($cnt > NOTICES_PER_PAGE) {
486                 break;
487             }
488
489             $item = $this->newListItem($this->notice);
490             $item->show();
491         }
492
493         $this->out->elementEnd('ul');
494         $this->out->elementEnd('div');
495
496         return $cnt;
497     }
498
499     /**
500      * returns a new list item for the current notice
501      *
502      * Overridden to return a Facebook specific list item.
503      *
504      * @param Notice $notice the current notice
505      *
506      * @return FacebookNoticeListItem a list item for displaying the notice
507      * formatted for display in the Facebook App.
508      */
509
510     function newListItem($notice)
511     {
512         return new FacebookNoticeListItem($notice, $this);
513     }
514
515 }
516
517 class FacebookNoticeListItem extends NoticeListItem
518 {    
519     /**
520      * recipe function for displaying a single notice in the Facebook App.
521      *
522      * Overridden to strip out some of the controls that we don't
523      * want to be available.
524      *
525      * @return void
526      */
527
528     function show()
529     {
530         $this->showStart();
531
532         $this->out->elementStart('div', 'entry-title');
533         $this->showAuthor();
534         $this->showContent();
535         $this->out->elementEnd('div');
536
537         $this->out->elementStart('div', 'entry-content');
538         $this->showNoticeLink();
539         $this->showNoticeSource();
540         $this->showReplyTo();
541         $this->out->elementEnd('div');
542
543         $this->showEnd();
544     }
545
546     function showNoticeLink()
547     {
548         $noticeurl = common_local_url('shownotice',
549                                       array('notice' => $this->notice->id));
550         // XXX: we need to figure this out better. Is this right?
551         if (strcmp($this->notice->uri, $noticeurl) != 0 &&
552             preg_match('/^http/', $this->notice->uri)) {
553             $noticeurl = $this->notice->uri;
554         }
555
556         $this->out->elementStart('dl', 'timestamp');
557         $this->out->element('dt', null, _('Published'));
558         $this->out->elementStart('dd', null);
559         $this->out->elementStart('a', array('rel' => 'bookmark',
560                                         'href' => $noticeurl));
561         $dt = common_date_iso8601($this->notice->created);
562         $this->out->element('abbr', array('class' => 'published',
563                                      'title' => $dt),
564         common_date_string($this->notice->created));
565         $this->out->elementEnd('a');
566         $this->out->elementEnd('dd');
567         $this->out->elementEnd('dl');
568     }
569
570 }