PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/Lampcms/Controllers/Logintwitter.php

https://github.com/snytkine/LampCMS
PHP | 769 lines | 317 code | 115 blank | 337 comment | 33 complexity | 6f4e182c5fa78ff1877014ce457c2fca MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /**
  3. *
  4. * License, TERMS and CONDITIONS
  5. *
  6. * This software is licensed under the GNU LESSER GENERAL PUBLIC LICENSE (LGPL) version 3
  7. * Please read the license here : http://www.gnu.org/licenses/lgpl-3.0.txt
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. The name of the author may not be used to endorse or promote products
  17. * derived from this software without specific prior written permission.
  18. *
  19. * ATTRIBUTION REQUIRED
  20. * 4. All web pages generated by the use of this software, or at least
  21. * the page that lists the recent questions (usually home page) must include
  22. * a link to the http://www.lampcms.com and text of the link must indicate that
  23. * the website's Questions/Answers functionality is powered by lampcms.com
  24. * An example of acceptable link would be "Powered by <a href="http://www.lampcms.com">LampCMS</a>"
  25. * The location of the link is not important, it can be in the footer of the page
  26. * but it must not be hidden by style attributes
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
  29. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  30. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  31. * IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
  32. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  33. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  35. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  36. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  37. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. * This product includes GeoLite data created by MaxMind,
  40. * available from http://www.maxmind.com/
  41. *
  42. *
  43. * @author Dmitri Snytkine <cms@lampcms.com>
  44. * @copyright 2005-2012 (or current year) Dmitri Snytkine
  45. * @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU LESSER GENERAL PUBLIC LICENSE (LGPL) version 3
  46. * @link http://www.lampcms.com Lampcms.com project
  47. * @version Release: @package_version@
  48. *
  49. *
  50. */
  51. namespace Lampcms\Controllers;
  52. use \Lampcms\WebPage;
  53. use \Lampcms\Request;
  54. use \Lampcms\Cookie;
  55. use \Lampcms\Responder;
  56. use \Lampcms\Mongo\Doc as MongoDoc;
  57. use \Lampcms\Twitter;
  58. /**
  59. * Class for generating a popup page that starts the oauth dance
  60. * and this also serves as a callback url
  61. * to which twitter redirects after authorization
  62. *
  63. * Dependency is pecl OAuth extension!
  64. *
  65. * @author Dmitri Snytkine
  66. *
  67. */
  68. class Logintwitter extends WebPage
  69. {
  70. const REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token';
  71. const ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token';
  72. const AUTHORIZE_URL = 'https://api.twitter.com/oauth/authorize';
  73. const VERIFY_CREDENTIALS_URL = 'https://api.twitter.com/1.1/account/verify_credentials.json';
  74. /**
  75. * Array of data returned from Twitter
  76. * This is the main user's profile and stuff
  77. *
  78. * @var array
  79. */
  80. protected $aUserData;
  81. /**
  82. * Object php OAuth
  83. *
  84. * @var object of type php OAuth
  85. * must have oauth extension for this
  86. */
  87. protected $oAuth;
  88. protected $bInitPageDoc = false;
  89. /**
  90. * Configuration of Twitter API
  91. * this is array of values TWITTER section
  92. * in !config.ini
  93. *
  94. * @var array
  95. */
  96. protected $aTW = array();
  97. /**
  98. * Flag means new account will
  99. * be created for this
  100. * 'signed in with twitter' user
  101. *
  102. * @var bool
  103. */
  104. protected $isNewAccount = false;
  105. /**
  106. * Object of type UserTwitter
  107. *
  108. * We cannot just update the Viewer object because
  109. * we need to create an object of type UserTwitter
  110. * we will then replace the Viewer object with this new object
  111. * via processLogin()
  112. *
  113. * @var object of type UserTwitter
  114. */
  115. protected $User;
  116. /**
  117. * Flag indicates that this is the
  118. * request to connect Twitter account
  119. * with existing user account.
  120. *
  121. * @var bool
  122. */
  123. protected $bConnect = false;
  124. /**
  125. * The main purpose of this class is to
  126. * generate the oAuth token
  127. * and then redirect browser to twitter url with
  128. * this unique token
  129. *
  130. * No actual page generation will take place
  131. *
  132. * @see classes/WebPage#main()
  133. */
  134. protected function main()
  135. {
  136. if (!extension_loaded('oauth')) {
  137. throw new \Lampcms\Exception('@@Unable to use Twitter API because OAuth extension is not available@@');
  138. }
  139. /**
  140. * If user is logged in then this is
  141. * a request to connect Twitter Account
  142. * with existing account.
  143. *
  144. * @todo check that user does not already have
  145. * Twitter credentials and if yes then call
  146. * closeWindows as it would indicate that user
  147. * is already connected with Twitter
  148. */
  149. if ($this->isLoggedIn()) {
  150. $this->bConnect = true;
  151. }
  152. d('$this->bConnect: ' . $this->bConnect);
  153. $this->aTW = $this->Registry->Ini['TWITTER'];
  154. try {
  155. $this->oAuth = new \OAuth($this->aTW['TWITTER_OAUTH_KEY'], $this->aTW['TWITTER_OAUTH_SECRET']); // , OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_AUTHORIZATION
  156. $this->oAuth->disableSSLChecks();
  157. $this->oAuth->enableDebug(); // This will generate debug output in your error_log
  158. } catch ( \OAuthException $e ) {
  159. e('OAuthException: ' . $e->getMessage());
  160. throw new \Lampcms\Exception('@@Something went wrong during authorization. Please try again later@@' . $e->getMessage());
  161. }
  162. /**
  163. * If this is start of dance then
  164. * generate token, secret and store them
  165. * in session and redirect to twitter authorization page
  166. */
  167. if (empty($_SESSION['oauth']) || empty($this->Request['oauth_token'])) {
  168. $this->startOauthDance();
  169. } else {
  170. $this->finishOauthDance();
  171. }
  172. }
  173. /**
  174. * Generate oAuth request token
  175. * and redirect to twitter for authentication
  176. *
  177. * @throws Exception
  178. * @throws \Exception in case something goes wrong during
  179. * this stage
  180. * @return object $this
  181. */
  182. protected function startOauthDance()
  183. {
  184. try {
  185. $uri = $this->Registry->Ini->SITE_URL . '{_WEB_ROOT_}/{_logintwitter_}';
  186. $routerCallback = $this->Registry->Router->getCallback();
  187. $callbackUrl = $routerCallback($uri);
  188. /**
  189. * urlencode() is not longer necessary since now callback url is passed in header
  190. * but if you are having problems with this method try to uncomment urlencode() line below
  191. * This behaviour may depend on version of php oauth extension
  192. */
  193. //$callbackUrl = \urlencode($callbackUrl);
  194. d('$callbackUrl' . $callbackUrl);
  195. // State 0 - Generate request token and redirect user to Twitter to authorize
  196. $_SESSION['oauth'] = $this->oAuth->getRequestToken(self::REQUEST_TOKEN_URL, $callbackUrl);
  197. $aDebug = $this->oAuth->getLastResponseInfo();
  198. d('debug: ' . \print_r($aDebug, 1));
  199. d('$_SESSION[\'oauth\']: ' . print_r($_SESSION['oauth'], 1));
  200. if (!empty($_SESSION['oauth']) && !empty($_SESSION['oauth']['oauth_token'])) {
  201. $authorizeUrl = self::AUTHORIZE_URL . '?oauth_token=' . $_SESSION['oauth']['oauth_token'];
  202. d('redirecting to url: ' . $authorizeUrl);
  203. Responder::redirectToPage($authorizeUrl);
  204. } else {
  205. /**
  206. * Here throw regular Exception, not Lampcms\Exception
  207. * so that it will be caught ONLY by the index.php and formatted
  208. * on a clean page, without any template
  209. */
  210. throw new \Exception("@@Failed fetching request token, response was@@: " . $this->oAuth->getLastResponse());
  211. }
  212. } catch ( \OAuthException $e ) {
  213. e('OAuthException: ' . $e->getMessage());
  214. $aDebug = $this->oAuth->getLastResponseInfo();
  215. d('debug: ' . print_r($aDebug, 1));
  216. throw new \Exception('@@Something went wrong during authorization. Please try again later@@' . $e->getMessage());
  217. }
  218. return $this;
  219. }
  220. /**
  221. * Step 2 in oAuth process
  222. * this is when Twitter redirected the user back
  223. * to our callback url, which calls this controller
  224. *
  225. * @return object $this
  226. *
  227. * @throws Exception in case something goes wrong with oAuth class
  228. */
  229. protected function finishOauthDance()
  230. {
  231. d('Looks like we are at step 2 of authentication. Request: ' . print_r($_REQUEST, 1));
  232. try {
  233. /**
  234. * This is a callback (redirected back from twitter page
  235. * after user authorized us)
  236. * In this case we must: create account or update account
  237. * in USER table
  238. * Re-create oViewer object
  239. * send cookie to remember user
  240. * and then send out HTML with js instruction to close the popup window
  241. */
  242. /**
  243. * Get 'oauth_verifier' request param which was sent from LinkedIn
  244. */
  245. $ver = $this->Registry->Request->get('oauth_verifier', 's', '');
  246. d('$ver: ' . $ver);
  247. if (empty($ver)) {
  248. $ver = null;
  249. }
  250. // State 1 - Handle callback from Twitter and get and store an access token
  251. /**
  252. * @todo check first to make sure we do have oauth_token
  253. * on REQUEST, else close the window
  254. */
  255. $this->oAuth->setToken($this->Request['oauth_token'], $_SESSION['oauth']['oauth_token_secret']);
  256. $aAccessToken = $this->oAuth->getAccessToken(self::ACCESS_TOKEN_URL, null, $ver);
  257. d('$aAccessToken: ' . \json_encode($aAccessToken));
  258. unset($_SESSION['oauth']);
  259. /**
  260. * @todo
  261. * there is a slight possibility that
  262. * we don't get the oData back like if
  263. * request for verify_credentials with token/secret fails
  264. * This should not happen because user has just authorized us - this
  265. * is a callback url after all.
  266. * But still, what if... what if Twitter hickups and does not
  267. * return valid response, then what should be do?
  268. *
  269. * Probably throw some generic exception telling user to try
  270. * again in a few minutes
  271. *
  272. * So basically we should delegate this whole process to
  273. * the Twitter->verifyCredentials()
  274. *
  275. */
  276. $this->oAuth->setToken($aAccessToken['oauth_token'], $aAccessToken['oauth_token_secret']);
  277. $this->oAuth->fetch(self::VERIFY_CREDENTIALS_URL, null, OAUTH_HTTP_METHOD_GET, array('Connection'=> 'close'));
  278. $aDebug = $this->oAuth->getLastResponseInfo();
  279. d('debug: ' . \print_r($aDebug, 1));
  280. $lastResponseHeaders = $this->oAuth->getLastResponseHeaders();
  281. d('$lastResponseHeaders: ' . $lastResponseHeaders);
  282. if (false === $this->aUserData = \json_decode($this->oAuth->getLastResponse(), true)) {
  283. e('Unable to json_decode data returned by Twitter API: ' . $this->oAuth->getLastResponse());
  284. $this->closeWindow();
  285. exit;
  286. }
  287. if (isset($this->aUserData['status'])) {
  288. unset($this->aUserData['status']);
  289. }
  290. d('json: ' . \print_r($this->aUserData, true));
  291. $this->aUserData = \array_merge($this->aUserData, $aAccessToken);
  292. d('$this->aUserData ' . \print_r($this->aUserData, 1));
  293. $this->aUserData['_id'] = (!empty($this->aUserData['id_str'])) ? $this->aUserData['id_str'] : (string)$this->aUserData['id'];
  294. unset($this->aUserData['user_id']);
  295. $this->updateTwitterUserRecord();
  296. $this->createOrUpdate();
  297. if (!$this->bConnect) {
  298. Cookie::sendLoginCookie($this->Registry->Viewer->getUid(), $this->User->rs);
  299. } else {
  300. /**
  301. * Set flag to session indicating that user just
  302. * connected Twitter Account
  303. */
  304. $this->Registry->Viewer['b_tw'] = true;
  305. }
  306. $this->closeWindow();
  307. } catch ( \OAuthException $e ) {
  308. e('OAuthException: ' . $e->getMessage());
  309. $aDebug = $this->oAuth->getLastResponseInfo();
  310. d('debug: ' . print_r($aDebug, 1));
  311. $lastResponseHeaders = $this->oAuth->getLastResponseHeaders();
  312. d('$lastResponseHeaders: ' . $lastResponseHeaders);
  313. /**
  314. * Cannot throw exception because then it would be
  315. * displayed as regular page, with login block
  316. * but the currently opened window is a popup window
  317. * for showing twitter oauth page and we don't need
  318. * a login form or any other elements of regular page there
  319. */
  320. $err = '@@Something went wrong during authorization. Please try again later@@' . $e->getMessage();
  321. exit(\Lampcms\Responder::makeErrorPage($err));
  322. }
  323. return $this;
  324. }
  325. /**
  326. * Test to see if user with the twitter ID already exists
  327. * by requesting tid_ key from cache
  328. * this is faster than even a simple SELECT because
  329. * the user object may already exist in cache
  330. *
  331. * If user not found, then create a record for
  332. * a new user, otherwise update record
  333. *
  334. * @todo special case if this is 'connect' type of action
  335. * where existing logged in user is adding twitter to his account
  336. * then we should delegate to connect() method which
  337. * does different things - adds twitter data to $this->Registry->Viewer
  338. * but also first checks if another user already has
  339. * this twitter account in which case must show error - cannot
  340. * use same Twitter account by different users
  341. *
  342. * @throws \Exception
  343. * @return object $this
  344. */
  345. protected function createOrUpdate()
  346. {
  347. $tid = $this->aUserData['_id']; // it will be string!
  348. d('$tid: ' . $tid);
  349. $aUser = $this->getUserByTid($tid);
  350. if (!empty($this->bConnect)) {
  351. d('this is connect action');
  352. $this->User = $this->Registry->Viewer;
  353. $this->connect($tid);
  354. } elseif (!empty($aUser)) {
  355. $this->User = $User = \Lampcms\UserTwitter::userFactory($this->Registry, $aUser);
  356. $this->updateUser();
  357. } else {
  358. $this->isNewAccount = true;
  359. $this->createNewUser();
  360. }
  361. try {
  362. $this->processLogin($this->User);
  363. } catch ( \Lampcms\LoginException $e ) {
  364. /**
  365. * re-throw as regular exception
  366. * so that it can be caught and shown in popup window
  367. */
  368. e('Unable to process login: ' . $e->getMessage());
  369. throw new \Exception($e->getMessage());
  370. }
  371. $this->Registry->Dispatcher->post($this, 'onTwitterLogin');
  372. if ($this->isNewAccount) {
  373. $this->postTweetStatus();
  374. }
  375. return $this;
  376. }
  377. /**
  378. * Add Twitter credentials to existing user
  379. *
  380. * @param $tid
  381. *
  382. * @return $this
  383. */
  384. protected function connect($tid)
  385. {
  386. $aUser = $this->getUserByTid($tid);
  387. d('$aUser: ' . print_r($aUser, 1));
  388. if (!empty($aUser) && ($aUser['_id'] != $this->User->getUid())) {
  389. $name = '';
  390. if (!empty($aUser['fn'])) {
  391. $name .= $aUser['fn'];
  392. }
  393. if (!empty($aUser['ln'])) {
  394. $name .= ' ' . $aUser['fn'];
  395. }
  396. $trimmed = \trim($name);
  397. $name = (!empty($trimmed)) ? \trim($name) : $aUser['username'];
  398. /**
  399. * This error message will appear inside the
  400. * Small extra browser Window that Login with Twitter
  401. * opens
  402. *
  403. */
  404. $err = '<div class="larger"><p>This Twitter account is already connected to
  405. another registered user: <strong>' . $name . '</strong><br>
  406. <br>
  407. A Twitter account cannot be associated with more than one account on this site<br>
  408. If you still want to connect Twitter account to this account you must use a different Twitter account</p>';
  409. $err .= '<br><br>
  410. <input type="button" class="btn-m" onClick="window.close();" value="&nbsp;OK&nbsp;">&nbsp;
  411. <input type="button" class="btn-m" onClick="window.close();" value="&nbsp;Close&nbsp;">
  412. </div>';
  413. $s = Responder::makeErrorPage($err);
  414. echo ($s);
  415. exit;
  416. }
  417. $this->updateUser(false);
  418. }
  419. protected function createNewUser()
  420. {
  421. d('cp');
  422. $aUser = array();
  423. if (!empty($this->aUserData['utc_offset'])) {
  424. $timezone = \Lampcms\TimeZone::getTZbyoffset($this->aUserData['utc_offset']);
  425. } elseif (false !== $tzn = Cookie::get('tzn')) {
  426. $timezone = $tzn;
  427. } else {
  428. $timezone = $this->Registry->Ini->SERVER_TIMEZONE;
  429. }
  430. $username = $this->makeUsername();
  431. $sid = Cookie::getSidCookie();
  432. d('sid is: ' . $sid);
  433. $aUser['username'] = $username;
  434. $aUser['username_lc'] = \mb_strtolower($username, 'utf-8');
  435. $aUser['fn'] = $this->aUserData['name'];
  436. $aUser['avatar_external'] = $this->aUserData['profile_image_url'];
  437. $aUser['lang'] = $this->aUserData['lang'];
  438. $aUser['i_reg_ts'] = time();
  439. $aUser['date_reg'] = date('r');
  440. $aUser['role'] = 'external_auth';
  441. $aUser['tz'] = $timezone;
  442. $aUser['rs'] = (false !== $sid) ? $sid : \Lampcms\String::makeSid();
  443. $aUser['twtr_username'] = $this->aUserData['screen_name'];
  444. $aUser['oauth_token'] = $this->aUserData['oauth_token'];
  445. $aUser['oauth_token_secret'] = $this->aUserData['oauth_token_secret'];
  446. $aUser['twitter_uid'] = $this->aUserData['_id'];
  447. $aUser['i_rep'] = 1;
  448. $aUser = \array_merge($this->Registry->Geo->Location->data, $aUser);
  449. if (!empty($this->aUserData['url'])) {
  450. $aUser['url'] = $this->aUserData['url'];
  451. }
  452. if (!empty($this->aUserData['description'])) {
  453. $aUser['description'] = $this->aUserData['description'];
  454. }
  455. d('aUser: ' . print_r($aUser, 1));
  456. $this->User = \Lampcms\UserTwitter::userFactory($this->Registry, $aUser);
  457. /**
  458. * This will mark this userobject is new user
  459. * and will be persistent for the duration of this session ONLY
  460. * This way we can know it's a newly registered user
  461. * and ask the user to provide email address but only
  462. * during the same session
  463. */
  464. //$this->User->setNewUser();
  465. //d('isNewUser: '.$this->User->isNewUser());
  466. $this->User->save();
  467. \Lampcms\PostRegistration::createReferrerRecord($this->Registry, $this->User);
  468. $this->Registry->Dispatcher->post($this->User, 'onNewUser');
  469. $this->Registry->Dispatcher->post($this->User, 'onNewTwitterUser');
  470. return $this;
  471. }
  472. /**
  473. * The currect Viewer object may be updated with the data
  474. * we got from Twitter api
  475. *
  476. * This means we found record for existing user by twitter uid
  477. *
  478. */
  479. protected function updateUser($bUpdateAvatar = true)
  480. {
  481. d('adding Twitter credentials to User object');
  482. $this->User['oauth_token'] = $this->aUserData['oauth_token'];
  483. $this->User['oauth_token_secret'] = $this->aUserData['oauth_token_secret'];
  484. $this->User['twitter_uid'] = $this->aUserData['_id'];
  485. if (!empty($this->aUserData['screen_name'])) {
  486. $this->User['twtr_username'] = $this->aUserData['screen_name'];
  487. }
  488. $avatarTwitter = $this->User['avatar_external'];
  489. if (empty($avatarTwitter)) {
  490. $this->User['avatar_external'] = $this->aUserData['profile_image_url'];
  491. $srcAvatar = \trim($this->User->offsetGet('avatar'));
  492. /**
  493. * If user also did not have any avatar
  494. * then
  495. * after this update we should also update
  496. * the welcome block (removing it from SESSION will
  497. * ensure that it updates on next page load) so that
  498. * avatar on the welcome block will change to the
  499. * external avatar
  500. */
  501. if (empty($srcAvatar)) {
  502. if (!empty($_SESSION) && !empty($_SESSION['welcome'])) {
  503. unset($_SESSION['welcome']);
  504. }
  505. }
  506. }
  507. $this->User->save();
  508. return $this;
  509. }
  510. /**
  511. * Post tweet like
  512. * "Joined this site"
  513. * Also can and probably should add
  514. * the person to follow
  515. * our site's account
  516. */
  517. protected function postTweetStatus()
  518. {
  519. $sToFollow = $this->aTW['TWITTER_USERNAME'];
  520. d('$sToFollow: ' . $sToFollow);
  521. if (empty($sToFollow)) {
  522. return $this;
  523. }
  524. $follow = (!empty($sToFollow)) ? ' #follow @' . $sToFollow : '';
  525. $siteName = $this->Registry->Ini->SITE_TITLE;
  526. $ourTwitterUsername = $this->Registry->Ini->SITE_URL . $follow;
  527. $oTwitter = new Twitter($this->Registry);
  528. if (!empty($ourTwitterUsername)) {
  529. register_shutdown_function(function() use ($oTwitter, $siteName, $ourTwitterUsername, $sToFollow)
  530. {
  531. try {
  532. $oTwitter->followUser($sToFollow);
  533. } catch ( \Exception $e ) {
  534. $message = 'Error in: ' . $e->getFile() . ' line: ' . $e->getLine() . ' message: ' . $e->getMessage();
  535. if (function_exists('d')) {
  536. d($message);
  537. }
  538. }
  539. /**
  540. * Auto-posting tweet on user signup is a bad idea
  541. * and may anger some users.
  542. * Don't do this unless you really need this feature!
  543. */
  544. /*try{
  545. $oTwitter->postMessage('I Joined '.$siteName. ' '.$stuff);
  546. } catch (\Exception $e){
  547. $message = 'Exception in: '.$e->getFile(). ' line: '.$e->getLine().' message: '.$e->getMessage();
  548. if (function_exists('d')) {
  549. d($message);
  550. }
  551. }*/
  552. });
  553. }
  554. return $this;
  555. }
  556. /**
  557. * Create a new record in USERS_TWITTER table
  558. * or update an existing record
  559. *
  560. * @return \Lampcms\Controllers\Logintwitter
  561. */
  562. protected function updateTwitterUserRecord()
  563. {
  564. $this->Registry->Mongo->USERS_TWITTER->save($this->aUserData);
  565. return $this;
  566. }
  567. /**
  568. * Get user object ty twitter id (tid)
  569. *
  570. * @param string $tid Twitter id
  571. *
  572. * @return mixed array or null
  573. *
  574. */
  575. protected function getUserByTid($tid)
  576. {
  577. $coll = $this->Registry->Mongo->USERS;
  578. $coll->ensureIndex(array('twitter_uid' => 1));
  579. $aUser = $coll->findOne(array('twitter_uid' => $this->aUserData['_id']));
  580. return $aUser;
  581. }
  582. /**
  583. * Return html that contains JS window.close
  584. * code and nothing else
  585. *
  586. * @todo instead of just closing window
  587. * can show a small form with pre-populated
  588. * text to be posted to Twitter,
  589. * for example "I just joined SITE_NAME, awesome site
  590. * + link +
  591. *
  592. * And there will be 2 buttons Submit and Cancel
  593. * Cancel will close window
  594. *
  595. * @param array $a
  596. *
  597. * @return void
  598. */
  599. protected function closeWindow(array $a = array())
  600. {
  601. d('cp a: ' . print_r($a, 1));
  602. $js = '';
  603. /*if(!empty($a)){
  604. $o = json_encode($a);
  605. $js = 'window.opener.oSL.processLogin('.$o.')';
  606. }*/
  607. $tpl = '
  608. var myclose = function(){
  609. window.close();
  610. }
  611. if(window.opener){
  612. %s
  613. setTimeout(myclose, 300); // give opener window time to process login and cancell intervals
  614. }else{
  615. alert("not a popup window or opener window gone away");
  616. }';
  617. d('cp');
  618. $script = \sprintf($tpl, $js);
  619. $s = Responder::PAGE_OPEN . Responder::JS_OPEN .
  620. $script .
  621. Responder::JS_CLOSE .
  622. '<h2>@@You have successfully logged in. You should close this window now@@</h2>' .
  623. //print_r($_SESSION, 1).
  624. Responder::PAGE_CLOSE;
  625. d('cp s: ' . $s);
  626. echo $s;
  627. fastcgi_finish_request();
  628. exit;
  629. }
  630. /**
  631. * Checks in username of twitter user
  632. * already exists in our regular USERS table
  633. * and if it does then prepends the @ to the username
  634. * otherwise returns twitter username
  635. *
  636. * The result is that we will use the value of
  637. * Twitter username as our username OR the
  638. *
  639. * @username
  640. * if username is already taken
  641. *
  642. * @return string the value of username that will
  643. * be used as our own username
  644. *
  645. */
  646. protected function makeUsername()
  647. {
  648. $res = $this->Registry->Mongo->USERS->findOne(array('username_lc' => \mb_strtolower($this->aUserData['screen_name'])));
  649. $ret = (empty($res)) ? $this->aUserData['screen_name'] : '@' . $this->aUserData['screen_name'];
  650. d('ret: ' . $ret);
  651. return $ret;
  652. }
  653. }