]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/FacebookSSO/FacebookSSOPlugin.php
Merge branch '0.9.x' into facebook-upgrade
[quix0rs-gnu-social.git] / plugins / FacebookSSO / FacebookSSOPlugin.php
1 <?php
2 /**
3  * StatusNet - the distributed open-source microblogging tool
4  * Copyright (C) 2010, StatusNet, Inc.
5  *
6  * A plugin for single-sign-in (SSO) with Facebook
7  *
8  * PHP version 5
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Affero General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Affero General Public License for more details.
19  *
20  * You should have received a copy of the GNU Affero General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * @category  Pugin
24  * @package   StatusNet
25  * @author    Zach Copley <zach@status.net>
26  * @copyright 2010 StatusNet, Inc.
27  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
28  * @link      http://status.net/
29  */
30
31 if (!defined('STATUSNET')) {
32     exit(1);
33 }
34
35 /**
36  * Main class for Facebook single-sign-on plugin
37  *
38  *
39  * Simple plugins can be implemented as a single module. Others are more complex
40  * and require additional modules; these should use their own directory, like
41  * 'local/plugins/{$name}/'. All files related to the plugin, including images,
42  * JavaScript, CSS, external libraries or PHP modules should go in the plugin
43  * directory.
44  *
45  * @category  Plugin
46  * @package   StatusNet
47  * @author    Zach Copley <zach@status.net>
48  * @copyright 2010 StatusNet, Inc.
49  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
50  * @link      http://status.net/
51  */
52 class FacebookSSOPlugin extends Plugin
53 {
54     public $appId    = null; // Facebook application ID
55     public $secret   = null; // Facebook application secret
56     public $facebook = null; // Facebook application instance
57     public $dir      = null; // Facebook SSO plugin dir
58
59     /**
60      * Initializer for this plugin
61      *
62      * Plugins overload this method to do any initialization they need,
63      * like connecting to remote servers or creating paths or so on.
64      *
65      * @return boolean hook value; true means continue processing, false means stop.
66      */
67     function initialize()
68     {
69         common_debug("XXXXXXXXXXXX " . $this->appId);
70         // Check defaults and configuration for application ID and secret
71         if (empty($this->appId)) {
72             $this->appId = common_config('facebook', 'appid');
73         }
74
75         if (empty($this->secret)) {
76             $this->secret = common_config('facebook', 'secret');
77         }
78
79         if (empty($this->facebook)) {
80             common_debug('instantiating facebook obj');
81             $this->facebook = new Facebook(
82                 array(
83                     'appId'  => $this->appId,
84                     'secret' => $this->secret,
85                     'cookie' => true
86                 )
87             );
88         }
89         
90         common_debug("FACEBOOK = " . var_export($this->facebook, true));
91
92         return true;
93     }
94
95     /**
96      * Cleanup for this plugin
97      *
98      * Plugins overload this method to do any cleanup they need,
99      * like disconnecting from remote servers or deleting temp files or so on.
100      *
101      * @return boolean hook value; true means continue processing, false means stop.
102      */
103     function cleanup()
104     {
105         return true;
106     }
107
108     /**
109      * Load related modules when needed
110      *
111      * Most non-trivial plugins will require extra modules to do their work. Typically
112      * these include data classes, action classes, widget classes, or external libraries.
113      *
114      * This method receives a class name and loads the PHP file related to that class. By
115      * tradition, action classes typically have files named for the action, all lower-case.
116      * Data classes are in files with the data class name, initial letter capitalized.
117      *
118      * Note that this method will be called for *all* overloaded classes, not just ones
119      * in this plugin! So, make sure to return true by default to let other plugins, and
120      * the core code, get a chance.
121      *
122      * @param string $cls Name of the class to be loaded
123      *
124      * @return boolean hook value; true means continue processing, false means stop.
125      */
126     function onAutoload($cls)
127     {
128
129         $dir = dirname(__FILE__);
130
131         //common_debug("class = " . $cls);
132
133         switch ($cls)
134         {
135         case 'Facebook':
136             include_once $dir . '/extlib/facebook.php';
137             return false;
138         case 'FacebookloginAction':
139         case 'FacebookadminpanelAction':
140             include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
141             return false;
142         default:
143             return true;
144         }
145
146     }
147
148     /**
149      * Map URLs to actions
150      *
151      * This event handler lets the plugin map URLs on the site to actions (and
152      * thus an action handler class). Note that the action handler class for an
153      * action will be named 'FoobarAction', where action = 'foobar'. The class
154      * must be loaded in the onAutoload() method.
155      *
156      * @param Net_URL_Mapper $m path-to-action mapper
157      *
158      * @return boolean hook value; true means continue processing, false means stop.
159      */
160     function onRouterInitialized($m)
161     {
162         // Always add the admin panel route
163         $m->connect('admin/facebook', array('action' => 'facebookadminpanel'));
164
165         // Only add these routes if an application has been setup on
166         // Facebook for the plugin to use.
167         if ($this->hasApplication()) {
168             $m->connect('main/facebooklogin', array('action' => 'facebooklogin'));
169         }
170
171         return true;
172     }
173
174     /*
175      * Add a login tab for Facebook, but only if there's a Facebook
176      * application defined for the plugin to use.
177      *
178      * @param Action &action the current action
179      *
180      * @return void
181      */
182     function onEndLoginGroupNav(&$action)
183     {
184         $action_name = $action->trimmed('action');
185
186         if ($this->hasApplication()) {
187
188             $action->menuItem(
189                 common_local_url('facebooklogin'),
190                 _m('MENU', 'Facebook'),
191                 // TRANS: Tooltip for menu item "Facebook".
192                 _m('Login or register using Facebook'),
193                'facebooklogin' === $action_name
194             );
195         }
196
197         return true;
198     }
199
200     /**
201      * Add a Facebook tab to the admin panels
202      *
203      * @param Widget $nav Admin panel nav
204      *
205      * @return boolean hook value
206      */
207     function onEndAdminPanelNav($nav)
208     {
209         if (AdminPanelAction::canAdmin('facebook')) {
210
211             $action_name = $nav->action->trimmed('action');
212
213             $nav->out->menuItem(
214                 common_local_url('facebookadminpanel'),
215                 // TRANS: Menu item.
216                 _m('MENU','Facebook'),
217                 // TRANS: Tooltip for menu item "Facebook".
218                 _m('Facebook integration configuration'),
219                 $action_name == 'facebookadminpanel',
220                 'nav_facebook_admin_panel'
221             );
222         }
223
224         return true;
225     }
226
227     /*
228      * Is there a Facebook application for the plugin to use?
229      */
230     function hasApplication()
231     {
232         if (!empty($this->appId) && !empty($this->secret)) {
233             return true;
234         } else {
235             return false;
236         }
237     }
238
239     function onStartShowHeader($action)
240     {
241         // output <div id="fb-root"></div> as close to <body> as possible
242         $action->element('div', array('id' => 'fb-root'));
243
244         $session = $this->facebook->getSession();
245         $dir = dirname(__FILE__);
246
247         // XXX: minify this
248         $script = <<<ENDOFSCRIPT
249         window.fbAsyncInit = function() {
250
251     FB.init({
252       appId   : %s,
253       session : %s,   // don't refetch the session when PHP already has it
254       status  : true, // check login status
255       cookie  : true, // enable cookies to allow the server to access the session
256       xfbml   : true  // parse XFBML
257     });
258
259     // whenever the user logs in, refresh the page
260     FB.Event.subscribe(
261         'auth.login',
262         function() {
263             window.location.reload();
264         }
265     );
266 };
267
268 (function() {
269     var e = document.createElement('script');
270     e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
271     e.async = true;
272     document.getElementById('fb-root').appendChild(e);
273 }());
274 ENDOFSCRIPT;
275
276         $action->inlineScript(
277             sprintf($script,
278                 json_encode($this->appId),
279                 json_encode($this->session)
280             )
281         );
282         
283         return true;
284     }
285
286     function onStartHtmlElement($action, $attrs) {
287         $attrs = array_merge($attrs, array('xmlns:fb' => 'http://www.facebook.com/2008/fbml'));
288         return true;
289     }
290
291     function onPluginVersion(&$versions)
292     {
293         $versions[] = array('name' => 'Facebook Single-Sign-On',
294                             'version' => STATUSNET_VERSION,
295                             'author' => 'Zach Copley',
296                             'homepage' => 'http://status.net/wiki/Plugin:FacebookSSO',
297                             'rawdescription' =>
298                             _m('A plugin for single-sign-on with Facebook.'));
299         return true;
300     }
301 }