PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/FBConnect/FBConnectPlugin.php

https://github.com/Br3nda/laconica
PHP | 395 lines | 238 code | 90 blank | 67 comment | 24 complexity | ba59c6d907cf976b2e83da9e60b8ff4b MD5 | raw file
Possible License(s): AGPL-3.0
  1. <?php
  2. /**
  3. * Laconica, the distributed open-source microblogging tool
  4. *
  5. * Plugin to enable Facebook Connect
  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 Plugin
  23. * @package Laconica
  24. * @author Zach Copley <zach@controlyourself.ca>
  25. * @copyright 2009 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. if (!defined('LACONICA')) {
  30. exit(1);
  31. }
  32. define("FACEBOOK_CONNECT_SERVICE", 3);
  33. require_once INSTALLDIR . '/lib/facebookutil.php';
  34. require_once INSTALLDIR . '/plugins/FBConnect/FBConnectAuth.php';
  35. require_once INSTALLDIR . '/plugins/FBConnect/FBConnectLogin.php';
  36. require_once INSTALLDIR . '/plugins/FBConnect/FBConnectSettings.php';
  37. require_once INSTALLDIR . '/plugins/FBConnect/FBCLoginGroupNav.php';
  38. require_once INSTALLDIR . '/plugins/FBConnect/FBCSettingsNav.php';
  39. require_once INSTALLDIR . '/plugins/FBConnect/FBC_XDReceiver.php';
  40. /**
  41. * Plugin to enable Facebook Connect
  42. *
  43. * @category Plugin
  44. * @package Laconica
  45. * @author Zach Copley <zach@controlyourself.ca>
  46. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  47. * @link http://laconi.ca/
  48. */
  49. class FBConnectPlugin extends Plugin
  50. {
  51. function __construct()
  52. {
  53. parent::__construct();
  54. }
  55. // Hook in new actions
  56. function onRouterInitialized(&$m) {
  57. $m->connect('main/facebookconnect', array('action' => 'FBConnectAuth'));
  58. $m->connect('main/facebooklogin', array('action' => 'FBConnectLogin'));
  59. $m->connect('settings/facebook', array('action' => 'FBConnectSettings'));
  60. $m->connect('xd_receiver.html', array('action' => 'FBC_XDReceiver'));
  61. }
  62. // Add in xmlns:fb
  63. function onStartShowHTML($action)
  64. {
  65. if ($this->reqFbScripts($action)) {
  66. // XXX: Horrible hack to make Safari, FF2, and Chrome work with
  67. // Facebook Connect. These browser cannot use Facebook's
  68. // DOM parsing routines unless the mime type of the page is
  69. // text/html even though Facebook Connect uses XHTML. This is
  70. // A bug in Facebook Connect, and this is a temporary solution
  71. // until they fix their JavaScript libs.
  72. header('Content-Type: text/html');
  73. $action->extraHeaders();
  74. $action->startXML('html',
  75. '-//W3C//DTD XHTML 1.0 Strict//EN',
  76. 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd');
  77. $language = $action->getLanguage();
  78. $action->elementStart('html',
  79. array('xmlns' => 'http://www.w3.org/1999/xhtml',
  80. 'xmlns:fb' => 'http://www.facebook.com/2008/fbml',
  81. 'xml:lang' => $language,
  82. 'lang' => $language));
  83. return false;
  84. } else {
  85. return true;
  86. }
  87. }
  88. // Note: this script needs to appear in the <body>
  89. function onStartShowHeader($action)
  90. {
  91. if ($this->reqFbScripts($action)) {
  92. $apikey = common_config('facebook', 'apikey');
  93. $plugin_path = common_path('plugins/FBConnect');
  94. $login_url = common_local_url('FBConnectAuth');
  95. $logout_url = common_local_url('logout');
  96. // XXX: Facebook says we don't need this FB_RequireFeatures(),
  97. // but we actually do, for IE and Safari. Gar.
  98. $html = sprintf('<script type="text/javascript">
  99. window.onload = function () {
  100. FB_RequireFeatures(
  101. ["XFBML"],
  102. function() {
  103. FB.Facebook.init("%s", "../xd_receiver.html");
  104. }
  105. ); }
  106. function goto_login() {
  107. window.location = "%s";
  108. }
  109. function goto_logout() {
  110. window.location = "%s";
  111. }
  112. </script>', $apikey,
  113. $login_url, $logout_url);
  114. $action->raw($html);
  115. }
  116. }
  117. // Note: this script needs to appear as close as possible to </body>
  118. function onEndShowFooter($action)
  119. {
  120. if ($this->reqFbScripts($action)) {
  121. $action->element('script',
  122. array('type' => 'text/javascript',
  123. 'src' => 'http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php'),
  124. '');
  125. }
  126. }
  127. function onEndShowLaconicaStyles($action)
  128. {
  129. if ($this->reqFbScripts($action)) {
  130. $action->element('link', array('rel' => 'stylesheet',
  131. 'type' => 'text/css',
  132. 'href' => common_path('plugins/FBConnect/FBConnectPlugin.css')));
  133. }
  134. }
  135. /**
  136. * Does the Action we're plugged into require the FB Scripts? We only
  137. * want to output FB namespace, scripts, CSS, etc. on the pages that
  138. * really need them.
  139. *
  140. * @param Action the action in question
  141. *
  142. * @return boolean true
  143. */
  144. function reqFbScripts($action) {
  145. // If you're logged in w/FB Connect, you always need the FB stuff
  146. $fbuid = $this->loggedIn();
  147. if (!empty($fbuid)) {
  148. return true;
  149. }
  150. // List of actions that require FB stuff
  151. $needy = array('FBConnectLoginAction',
  152. 'FBConnectauthAction',
  153. 'FBConnectSettingsAction');
  154. if (in_array(get_class($action), $needy)) {
  155. return true;
  156. }
  157. return false;
  158. }
  159. /**
  160. * Is the user currently logged in with FB Connect?
  161. *
  162. * @return mixed $fbuid the Facebook ID of the logged in user, or null
  163. */
  164. function loggedIn()
  165. {
  166. $user = common_current_user();
  167. if (!empty($user)) {
  168. $flink = Foreign_link::getByUserId($user->id,
  169. FACEBOOK_CONNECT_SERVICE);
  170. $fbuid = 0;
  171. if (!empty($flink)) {
  172. try {
  173. $facebook = getFacebook();
  174. $fbuid = getFacebook()->get_loggedin_user();
  175. } catch (Exception $e) {
  176. common_log(LOG_WARNING,
  177. 'Problem getting Facebook client: ' .
  178. $e->getMessage());
  179. }
  180. if ($fbuid > 0) {
  181. return $fbuid;
  182. }
  183. }
  184. }
  185. return null;
  186. }
  187. function onStartPrimaryNav($action)
  188. {
  189. $user = common_current_user();
  190. if (!empty($user)) {
  191. $fbuid = $this->loggedIn();
  192. if (!empty($fbuid)) {
  193. /* Default FB silhouette pic for FB users who haven't
  194. uploaded a profile pic yet. */
  195. $silhouetteUrl =
  196. 'http://static.ak.fbcdn.net/pics/q_silhouette.gif';
  197. $url = $this->getProfilePicURL($fbuid);
  198. $action->elementStart('li', array('id' => 'nav_fb'));
  199. $action->element('img', array('id' => 'fbc_profile-pic',
  200. 'src' => (!empty($url)) ? $url : $silhouetteUrl,
  201. 'alt' => 'Facebook Connect User',
  202. 'width' => '16'), '');
  203. $iconurl = common_path('plugins/FBConnect/fbfavicon.ico');
  204. $action->element('img', array('id' => 'fb_favicon',
  205. 'src' => $iconurl));
  206. $action->elementEnd('li');
  207. }
  208. $action->menuItem(common_local_url('all', array('nickname' => $user->nickname)),
  209. _('Home'), _('Personal profile and friends timeline'), false, 'nav_home');
  210. $action->menuItem(common_local_url('profilesettings'),
  211. _('Account'), _('Change your email, avatar, password, profile'), false, 'nav_account');
  212. if (common_config('xmpp', 'enabled')) {
  213. $action->menuItem(common_local_url('imsettings'),
  214. _('Connect'), _('Connect to IM, SMS, Twitter'), false, 'nav_connect');
  215. } else {
  216. $action->menuItem(common_local_url('smssettings'),
  217. _('Connect'), _('Connect to SMS, Twitter'), false, 'nav_connect');
  218. }
  219. if (common_config('invite', 'enabled')) {
  220. $action->menuItem(common_local_url('invite'),
  221. _('Invite'),
  222. sprintf(_('Invite friends and colleagues to join you on %s'),
  223. common_config('site', 'name')),
  224. false, 'nav_invitecontact');
  225. }
  226. // Need to override the Logout link to make it do FB stuff
  227. if (!empty($fbuid)) {
  228. $logout_url = common_local_url('logout');
  229. $title = _('Logout from the site');
  230. $text = _('Logout');
  231. $html = sprintf('<li id="nav_logout"><a href="%s" title="%s" ' .
  232. 'onclick="FB.Connect.logout(function() { goto_logout() })">%s</a></li>',
  233. $logout_url, $title, $text);
  234. $action->raw($html);
  235. } else {
  236. $action->menuItem(common_local_url('logout'),
  237. _('Logout'), _('Logout from the site'), false, 'nav_logout');
  238. }
  239. }
  240. else {
  241. if (!common_config('site', 'closed')) {
  242. $action->menuItem(common_local_url('register'),
  243. _('Register'), _('Create an account'), false, 'nav_register');
  244. }
  245. $action->menuItem(common_local_url('login'),
  246. _('Login'), _('Login to the site'), false, 'nav_login');
  247. }
  248. $action->menuItem(common_local_url('doc', array('title' => 'help')),
  249. _('Help'), _('Help me!'), false, 'nav_help');
  250. $action->menuItem(common_local_url('peoplesearch'),
  251. _('Search'), _('Search for people or text'), false, 'nav_search');
  252. return false;
  253. }
  254. function onStartShowLocalNavBlock($action)
  255. {
  256. $action_name = get_class($action);
  257. $login_actions = array('LoginAction', 'RegisterAction',
  258. 'OpenidloginAction', 'FBConnectLoginAction');
  259. if (in_array($action_name, $login_actions)) {
  260. $nav = new FBCLoginGroupNav($action);
  261. $nav->show();
  262. return false;
  263. }
  264. $connect_actions = array('SmssettingsAction', 'ImsettingsAction',
  265. 'TwittersettingsAction', 'FBConnectSettingsAction');
  266. if (in_array($action_name, $connect_actions)) {
  267. $nav = new FBCSettingsNav($action);
  268. $nav->show();
  269. return false;
  270. }
  271. return true;
  272. }
  273. function onStartLogout($action)
  274. {
  275. $action->logout();
  276. $fbuid = $this->loggedIn();
  277. if (!empty($fbuid)) {
  278. try {
  279. $facebook = getFacebook();
  280. $facebook->expire_session();
  281. } catch (Exception $e) {
  282. common_log(LOG_WARNING, 'Could\'t logout of Facebook: ' .
  283. $e->getMessage());
  284. }
  285. }
  286. return true;
  287. }
  288. function getProfilePicURL($fbuid)
  289. {
  290. $facebook = getFacebook();
  291. $url = null;
  292. try {
  293. $fqry = 'SELECT pic_square FROM user WHERE uid = %s';
  294. $result = $facebook->api_client->fql_query(sprintf($fqry, $fbuid));
  295. if (!empty($result)) {
  296. $url = $result[0]['pic_square'];
  297. }
  298. } catch (Exception $e) {
  299. common_log(LOG_WARNING, "Facebook client failure requesting profile pic!");
  300. }
  301. return $url;
  302. }
  303. }