diff options
Diffstat (limited to 'mod/twitter_api')
18 files changed, 952 insertions, 230 deletions
diff --git a/mod/twitter_api/actions/twitter_api/interstitial_settings.php b/mod/twitter_api/actions/twitter_api/interstitial_settings.php new file mode 100644 index 000000000..880623973 --- /dev/null +++ b/mod/twitter_api/actions/twitter_api/interstitial_settings.php @@ -0,0 +1,53 @@ +<?php +/** + * Save settings for first time logins with twitter + */ +elgg_make_sticky_form('twitter_api_interstitial'); + +$display_name = get_input('display_name'); +$email = get_input('email'); +$password_1 = get_input('password_1', null, false); +$password_2 = get_input('password_2', null, false); + +if (!$display_name) { + register_error(elgg_echo('twitter_api:interstitial:no_display_name')); + forward(REFERER); +} + +if ($email && !is_email_address($email)) { + register_error(elgg_echo('twitter_api:interstitial:invalid_email')); + forward(REFERER); +} + +$existing_user = get_user_by_email($email); +if ($email && $existing_user) { + register_error(elgg_echo('twitter_api:interstitial:existing_email')); + forward(REFERER); +} + +if ($password_1 && !($password_1 == $password_2)) { + register_error(elgg_echo('twitter_api:interstitial:password_mismatch')); + forward(REFERER); +} + +$user = elgg_get_logged_in_user_entity(); +$user->name = $display_name; + +if ($email) { + $user->email = $email; +} + +if ($password_1) { + $user->salt = generate_random_cleartext_password(); + $user->password = generate_user_password($user, $password_1); +} + +if (!$user->save()) { + register_error(elgg_echo('twitter_api:interstitial:cannot_save')); + forward(REFERER); +} + +elgg_clear_sticky_form('twitter_api_interstitial'); + +system_message(elgg_echo('twitter_api:interstitial:saved')); +forward('/');
\ No newline at end of file diff --git a/mod/twitter_api/graphics/sign-in-with-twitter-d.png b/mod/twitter_api/graphics/sign-in-with-twitter-d.png Binary files differnew file mode 100644 index 000000000..b49a0ba59 --- /dev/null +++ b/mod/twitter_api/graphics/sign-in-with-twitter-d.png diff --git a/mod/twitter_api/graphics/sign-in-with-twitter-l.png b/mod/twitter_api/graphics/sign-in-with-twitter-l.png Binary files differnew file mode 100644 index 000000000..834d43cfd --- /dev/null +++ b/mod/twitter_api/graphics/sign-in-with-twitter-l.png diff --git a/mod/twitter_api/languages/en.php b/mod/twitter_api/languages/en.php index b63cebcf8..a6f4b40a5 100644 --- a/mod/twitter_api/languages/en.php +++ b/mod/twitter_api/languages/en.php @@ -11,24 +11,52 @@ $english = array( 'twitter_api:consumer_key' => 'Consumer Key', 'twitter_api:consumer_secret' => 'Consumer Secret', - 'twitter_api:settings:instructions' => 'You must obtain a consumer key and secret from <a href="https://twitter.com/oauth_clients" target="_blank">Twitter</a>. Most of the fields are self explanatory, the one piece of data you will need is the callback url which takes the form http://[yoursite]/action/twitterlogin/return - [yoursite] is the url of your Elgg network.', + 'twitter_api:settings:instructions' => 'You must obtain a consumer key and secret from <a href="https://dev.twitter.com/apps/new" target="_blank">Twitter</a>. Fill out the new app application. Select "Browser" as the application type and "Read & Write" for the access type. The callback url is %stwitter_api/authorize', 'twitter_api:usersettings:description' => "Link your %s account with Twitter.", 'twitter_api:usersettings:request' => "You must first <a href=\"%s\">authorize</a> %s to access your Twitter account.", + 'twitter_api:usersettings:cannot_revoke' => "You cannot unlink you account with Twitter because you haven't provided an email address or password. <a href=\"%s\">Provide them now</a>.", 'twitter_api:authorize:error' => 'Unable to authorize Twitter.', 'twitter_api:authorize:success' => 'Twitter access has been authorized.', 'twitter_api:usersettings:authorized' => "You have authorized %s to access your Twitter account: @%s.", 'twitter_api:usersettings:revoke' => 'Click <a href="%s">here</a> to revoke access.', + 'twitter_api:usersettings:site_not_configured' => 'An administrator must first configure Twitter before it can be used.', + 'twitter_api:revoke:success' => 'Twitter access has been revoked.', - 'twitter_api:login' => 'Allow existing users who have connected their Twitter account to sign in with Twitter?', - 'twitter_api:new_users' => 'Allow new users to sign up using their Twitter account even if manual registration is disabled?', + 'twitter_api:post_to_twitter' => "Send users' wire posts to Twitter?", + + 'twitter_api:login' => 'Allow users to sign in with Twitter?', + 'twitter_api:new_users' => 'Allow new users to sign up using their Twitter account even if user registration is disabled?', 'twitter_api:login:success' => 'You have been logged in.', 'twitter_api:login:error' => 'Unable to login with Twitter.', 'twitter_api:login:email' => "You must enter a valid email address for your new %s account.", + 'twitter_api:invalid_page' => 'Invalid page', + 'twitter_api:deprecated_callback_url' => 'The callback URL has changed for Twitter API to %s. Please ask your administrator to change it.', + + 'twitter_api:interstitial:settings' => 'Configure your settings', + 'twitter_api:interstitial:description' => 'You\'re almost ready to use %s! We need a few more details before you can continue. These are optional, but will allow you login if Twitter goes down or you decide to unlink your accounts.', + + 'twitter_api:interstitial:username' => 'This is your username. It cannot be changed. If you set a password, you can use the username or your email address to log in.', + + 'twitter_api:interstitial:name' => 'This is the name people will see when interacting with you.', + + 'twitter_api:interstitial:email' => 'Your email address. Users cannot see this by default.', + + 'twitter_api:interstitial:password' => 'A password to login if Twitter is down or you decide to unlink your accounts.', + 'twitter_api:interstitial:password2' => 'The same password, again.', + + 'twitter_api:interstitial:no_thanks' => 'No thanks', + + 'twitter_api:interstitial:no_display_name' => 'You must have a display name.', + 'twitter_api:interstitial:invalid_email' => 'You must enter a valid email address or nothing.', + 'twitter_api:interstitial:existing_email' => 'This email address is already registered on this site.', + 'twitter_api:interstitial:password_mismatch' => 'Your passwords do not match.', + 'twitter_api:interstitial:cannot_save' => 'Cannot save account details.', + 'twitter_api:interstitial:saved' => 'Account details saved!', ); add_translation('en', $english); diff --git a/mod/twitter_api/lib/twitter_api.php b/mod/twitter_api/lib/twitter_api.php index 0621c2b13..a7b971876 100644 --- a/mod/twitter_api/lib/twitter_api.php +++ b/mod/twitter_api/lib/twitter_api.php @@ -6,6 +6,27 @@ */ /** + * Get the API wrapper object + * + * @param string $oauth_token User's OAuth token + * @param string $oauth_token_secret User's OAuth secret + * @return TwitterOAuth|null + */ +function twitter_api_get_api_object($oauth_token = null, $oauth_token_secret = null) { + $consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); + $consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); + if (!($consumer_key && $consumer_secret)) { + return null; + } + + $api = new TwitterOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret); + if ($api) { + $api->host = "https://api.twitter.com/1.1/"; + } + return $api; +} + +/** * Tests if the system admin has enabled Sign-On-With-Twitter * * @param void @@ -24,11 +45,13 @@ function twitter_api_allow_sign_on_with_twitter() { } /** - * Forwards + * Forwards the user to twitter to authenticate * - * @todo what is this? + * This includes the login URL as the callback */ function twitter_api_forward() { + global $SESSION; + // sanity check if (!twitter_api_allow_sign_on_with_twitter()) { forward(); @@ -37,13 +60,40 @@ function twitter_api_forward() { $callback = elgg_normalize_url("twitter_api/login"); $request_link = twitter_api_get_authorize_url($callback); + // capture metadata about login to persist through redirects + $login_metadata = array( + 'persistent' => (bool) get_input("persistent"), + ); + // capture referrer if in site, but not the twitter_api + if (!empty($SESSION['last_forward_from'])) { + $login_metadata['forward'] = $SESSION['last_forward_from']; + } elseif (!empty($_SERVER['HTTP_REFERER']) + && 0 === strpos($_SERVER['HTTP_REFERER'], elgg_get_site_url()) + && 0 !== strpos($_SERVER['HTTP_REFERER'], elgg_get_site_url() . 'twitter_api/')) { + $login_metadata['forward'] = $_SERVER['HTTP_REFERER']; + } + $SESSION['twitter_api_login_metadata'] = $login_metadata; + forward($request_link, 'twitter_api'); } /** - * Log in a user with twitter. + * Log in a user referred from Twitter's OAuth API + * + * If the user has already linked their account with Twitter, it is a seamless + * login. If this is a first time login (or a user from deprecated twitter login + * plugin), we create a new account (update the account). + * + * If a plugin wants to be notified when someone logs in with twitter or a new + * twitter user signs up, register for the standard login or create user events + * and check for 'twitter_api' context. + * + * The user has to be redirected from Twitter for this to work. It depends on + * the Twitter OAuth data. */ function twitter_api_login() { + /* @var ElggSession $SESSION */ + global $SESSION; // sanity check if (!twitter_api_allow_sign_on_with_twitter()) { @@ -51,7 +101,21 @@ function twitter_api_login() { } $token = twitter_api_get_access_token(get_input('oauth_verifier')); - if (!isset($token['oauth_token']) or !isset($token['oauth_token_secret'])) { + + $persistent = false; + $forward = ''; + + // fetch login metadata from session + $login_metadata = $SESSION['twitter_api_login_metadata']; + unset($SESSION['twitter_api_login_metadata']); + if (!empty($login_metadata['persistent'])) { + $persistent = true; + } + if (!empty($login_metadata['forward'])) { + $forward = $login_metadata['forward']; + } + + if (!isset($token['oauth_token']) || !isset($token['oauth_token_secret'])) { register_error(elgg_echo('twitter_api:login:error')); forward(); } @@ -64,32 +128,24 @@ function twitter_api_login() { 'access_key' => $token['oauth_token'], 'access_secret' => $token['oauth_token_secret'], ), - 'limit' => 0 + 'limit' => 0, ); $users = elgg_get_entities_from_plugin_user_settings($options); if ($users) { - if (count($users) == 1 && login($users[0])) { + if (count($users) == 1 && login($users[0], $persistent)) { system_message(elgg_echo('twitter_api:login:success')); - - // trigger login hook - elgg_trigger_plugin_hook('login', 'twitter_api', array('user' => $users[0])); + forward($forward); } else { - system_message(elgg_echo('twitter_api:login:error')); + register_error(elgg_echo('twitter_api:login:error')); + forward(); } - - forward(); } else { - // need Twitter account credentials - elgg_load_library('twitter_oauth'); - - $consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); - $consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); - $api = new TwitterOAuth($consumer_key, $consumer_secret, $token['oauth_token'], $token['oauth_token_secret']); + $api = twitter_api_get_api_object($token['oauth_token'], $token['oauth_token_secret']); $twitter = $api->get('account/verify_credentials'); - // backward compatibility for stalled-development Twitter Login plugin + // backward compatibility for deprecated Twitter Login plugin $user = FALSE; if ($twitter_user = get_user_by_username($token['screen_name'])) { if (($screen_name = $twitter_user->twitter_screen_name) && ($screen_name == $token['screen_name'])) { @@ -101,48 +157,10 @@ function twitter_api_login() { // create new user if (!$user) { - // check new registration allowed - if (!twitter_api_allow_new_users_with_twitter()) { - register_error(elgg_echo('registerdisabled')); - forward(); - } - - // trigger a hook for plugin authors to intercept - if (!elgg_trigger_plugin_hook('new_twitter_user', 'twitter_service', array('account' => $twitter), TRUE)) { - // halt execution - register_error(elgg_echo('twitter_api:login:error')); - forward(); - } - - // Elgg-ify Twitter credentials - $username = $twitter->screen_name; - while (get_user_by_username($username)) { - $username = $twitter->screen_name . '_' . rand(1000, 9999); - } - - $password = generate_random_cleartext_password(); - $name = $twitter->name; - - $user = new ElggUser(); - $user->username = $username; - $user->name = $name; - $user->access_id = ACCESS_PUBLIC; - $user->salt = generate_random_cleartext_password(); - $user->password = generate_user_password($user, $password); - $user->owner_guid = 0; - $user->container_guid = 0; - - if (!$user->save()) { - register_error(elgg_echo('registerbad')); - forward(); - } - - // @todo require email address? - + $user = twitter_api_create_user($twitter); $site_name = elgg_get_site_entity()->name; system_message(elgg_echo('twitter_api:login:email', array($site_name))); - - $forward = "settings/user/{$user->username}"; + $forward = "twitter_api/interstitial"; } // set twitter services tokens @@ -156,9 +174,6 @@ function twitter_api_login() { // login new user if (login($user)) { system_message(elgg_echo('twitter_api:login:success')); - - // trigger login hook for new user - elgg_trigger_plugin_hook('first_login', 'twitter_api', array('user' => $user)); } else { system_message(elgg_echo('twitter_api:login:error')); } @@ -172,37 +187,70 @@ function twitter_api_login() { } /** + * Create a new user from Twitter information + * + * @param object $twitter Twitter OAuth response + * @return ElggUser + */ +function twitter_api_create_user($twitter) { + // check new registration allowed + if (!twitter_api_allow_new_users_with_twitter()) { + register_error(elgg_echo('registerdisabled')); + forward(); + } + + // Elgg-ify Twitter credentials + $username = $twitter->screen_name; + while (get_user_by_username($username)) { + // @todo I guess we just hope this is good enough + $username = $twitter->screen_name . '_' . rand(1000, 9999); + } + + $password = generate_random_cleartext_password(); + $name = $twitter->name; + + $user = new ElggUser(); + $user->username = $username; + $user->name = $name; + $user->access_id = ACCESS_PUBLIC; + $user->salt = generate_random_cleartext_password(); + $user->password = generate_user_password($user, $password); + $user->owner_guid = 0; + $user->container_guid = 0; + + if (!$user->save()) { + register_error(elgg_echo('registerbad')); + forward(); + } + + return $user; +} + +/** * Pull in the latest avatar from twitter. * - * @param unknown_type $user - * @param unknown_type $file_location + * @param ElggUser $user + * @param string $file_location */ function twitter_api_update_user_avatar($user, $file_location) { // twitter's images have a few suffixes: // _normal - // _resonably_small + // _reasonably_small // _mini // the twitter app here returns _normal. We want standard, so remove the suffix. // @todo Should probably check that it's an image file. $file_location = str_replace('_normal.jpg', '.jpg', $file_location); - $sizes = array( - 'topbar' => array(16, 16, TRUE), - 'tiny' => array(25, 25, TRUE), - 'small' => array(40, 40, TRUE), - 'medium' => array(100, 100, TRUE), - 'large' => array(200, 200, FALSE), - 'master' => array(550, 550, FALSE), - ); + $icon_sizes = elgg_get_config('icon_sizes'); $filehandler = new ElggFile(); $filehandler->owner_guid = $user->getGUID(); - foreach ($sizes as $size => $dimensions) { + foreach ($icon_sizes as $size => $dimensions) { $image = get_resized_image_from_existing_file( $file_location, - $dimensions[0], - $dimensions[1], - $dimensions[2] + $dimensions['w'], + $dimensions['h'], + $dimensions['square'] ); $filehandler->setFilename("profile/$user->guid$size.jpg"); @@ -213,8 +261,6 @@ function twitter_api_update_user_avatar($user, $file_location) { // update user's icontime $user->icontime = time(); - - return TRUE; } /** @@ -228,7 +274,7 @@ function twitter_api_update_user_avatar($user, $file_location) { * to establish session request tokens. */ function twitter_api_authorize() { - $token = twitter_api_get_access_token(); + $token = twitter_api_get_access_token(get_input('oauth_verifier')); if (!isset($token['oauth_token']) || !isset($token['oauth_token_secret'])) { register_error(elgg_echo('twitter_api:authorize:error')); forward('settings/plugins', 'twitter_api'); @@ -243,7 +289,6 @@ function twitter_api_authorize() { ), 'limit' => 0 ); - $users = elgg_get_entities_from_plugin_user_settings($options); if ($users) { @@ -281,19 +326,15 @@ function twitter_api_revoke() { } /** - * Returns the url to authorize a user. + * Gets the url to authorize a user. * * @param string $callback The callback URL */ -function twitter_api_get_authorize_url($callback = NULL) { +function twitter_api_get_authorize_url($callback = NULL, $login = true) { global $SESSION; - elgg_load_library('twitter_oauth'); - - $consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); - $consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); // request tokens from Twitter - $twitter = new TwitterOAuth($consumer_key, $consumer_secret); + $twitter = twitter_api_get_api_object(); $token = $twitter->getRequestToken($callback); // save token in session for use after authorization @@ -302,28 +343,26 @@ function twitter_api_get_authorize_url($callback = NULL) { 'oauth_token_secret' => $token['oauth_token_secret'], ); - return $twitter->getAuthorizeURL($token['oauth_token']); + return $twitter->getAuthorizeURL($token['oauth_token'], $login); } /** * Returns the access token to use in twitter calls. * - * @param unknown_type $oauth_verifier + * @param bool $oauth_verifier + * @return array */ function twitter_api_get_access_token($oauth_verifier = FALSE) { + /* @var ElggSession $SESSION */ global $SESSION; - elgg_load_library('twitter_oauth'); - - $consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); - $consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); // retrieve stored tokens $oauth_token = $SESSION['twitter_api']['oauth_token']; $oauth_token_secret = $SESSION['twitter_api']['oauth_token_secret']; - $SESSION->offsetUnset('twitter_api'); + unset($SESSION['twitter_api']); // fetch an access token - $api = new TwitterOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret); + $api = twitter_api_get_api_object($oauth_token, $oauth_token_secret); return $api->getAccessToken($oauth_verifier); } @@ -341,4 +380,4 @@ function twitter_api_allow_new_users_with_twitter() { } return false; -}
\ No newline at end of file +} diff --git a/mod/twitter_api/manifest.xml b/mod/twitter_api/manifest.xml index 38b1dc9a7..3af866bba 100644 --- a/mod/twitter_api/manifest.xml +++ b/mod/twitter_api/manifest.xml @@ -2,20 +2,16 @@ <plugin_manifest xmlns="http://www.elgg.org/plugin_manifest/1.8"> <name>Twitter API</name> <author>Core developers</author> - <version>1.8</version> + <version>1.8.15</version> <description>Allows users to authenticate their Elgg account with Twitter.</description> <category>api</category> <category>bundled</category> <website>http://www.elgg.org/</website> <copyright>See COPYRIGHT.txt</copyright> - <license>GNU Public License version 2</license> + <license>GNU General Public License version 2</license> <requires> - <type>elgg_version</type> - <version>2010040201</version> - </requires> - <requires> - <type>plugin</type> - <name>oauth_api</name> + <type>elgg_release</type> + <version>1.8</version> </requires> <requires> <type>php_extension</type> @@ -24,6 +20,10 @@ <conflicts> <type>plugin</type> + <name>oauth_api</name> + </conflicts> + <conflicts> + <type>plugin</type> <name>twitterservice</name> </conflicts> </plugin_manifest> diff --git a/mod/twitter_api/pages/twitter_api/interstitial.php b/mod/twitter_api/pages/twitter_api/interstitial.php new file mode 100644 index 000000000..23b5069cb --- /dev/null +++ b/mod/twitter_api/pages/twitter_api/interstitial.php @@ -0,0 +1,19 @@ +<?php +/** + * An interstitial page for newly created Twitter users. + * + * This prompts them to enter an email address and set a password in case Twitter goes down or they + * want to disassociate their account from twitter. + */ + +$title = elgg_echo('twitter_api:interstitial:settings'); + +$content = elgg_view_form('twitter_api/interstitial_settings'); + +$params = array( + 'content' => $content, + 'title' => $title, +); +$body = elgg_view_layout('one_sidebar', $params); + +echo elgg_view_page($title, $body); diff --git a/mod/twitter_api/start.php b/mod/twitter_api/start.php index 8a49db719..7318ac55d 100644 --- a/mod/twitter_api/start.php +++ b/mod/twitter_api/start.php @@ -12,14 +12,15 @@ function twitter_api_init() { // require libraries $base = elgg_get_plugins_path() . 'twitter_api'; - elgg_register_library('twitter_oauth', "$base/vendors/twitteroauth/twitterOAuth.php"); + elgg_register_class('TwitterOAuth', "$base/vendors/twitteroauth/twitterOAuth.php"); elgg_register_library('twitter_api', "$base/lib/twitter_api.php"); - elgg_load_library('twitter_api'); // extend site views - elgg_extend_view('metatags', 'twitter_api/metatags'); - elgg_extend_view('css', 'twitter_api/css'); + //elgg_extend_view('metatags', 'twitter_api/metatags'); + elgg_extend_view('css/elgg', 'twitter_api/css'); + elgg_extend_view('css/admin', 'twitter_api/css'); + elgg_extend_view('js/elgg', 'twitter_api/js'); // sign on with twitter if (twitter_api_allow_sign_on_with_twitter()) { @@ -34,14 +35,20 @@ function twitter_api_init() { // register Walled Garden public pages elgg_register_plugin_hook_handler('public_pages', 'walled_garden', 'twitter_api_public_pages'); - // allow plugin authors to hook into this service - elgg_register_plugin_hook_handler('tweet', 'twitter_service', 'twitter_api_tweet'); + // push wire post messages to twitter + if (elgg_get_plugin_setting('wire_posts', 'twitter_api') == 'yes') { + elgg_register_plugin_hook_handler('status', 'user', 'twitter_api_tweet'); + } + + $actions = dirname(__FILE__) . '/actions/twitter_api'; + elgg_register_action('twitter_api/interstitial_settings', "$actions/interstitial_settings.php", 'logged_in'); } /** * Handles old pg/twitterservice/ handler * - * @param array$page + * @param array $page + * @return bool */ function twitter_api_pagehandler_deprecated($page) { $url = elgg_get_site_url() . 'pg/twitter_api/authorize'; @@ -55,11 +62,12 @@ function twitter_api_pagehandler_deprecated($page) { /** * Serves pages for twitter. * - * @param array$page + * @param array $page + * @return bool */ function twitter_api_pagehandler($page) { if (!isset($page[0])) { - forward(); + return false; } switch ($page[0]) { @@ -75,66 +83,64 @@ function twitter_api_pagehandler($page) { case 'login': twitter_api_login(); break; - default: - forward(); + case 'interstitial': + gatekeeper(); + // only let twitter users do this. + $guid = elgg_get_logged_in_user_guid(); + $twitter_name = elgg_get_plugin_user_setting('twitter_name', $guid, 'twitter_api'); + if (!$twitter_name) { + register_error(elgg_echo('twitter_api:invalid_page')); + forward(); + } + $pages = dirname(__FILE__) . '/pages/twitter_api'; + include "$pages/interstitial.php"; break; + default: + return false; } + return true; } /** - * Push a tweet to twitter. + * Push a status update to twitter. * - * @param unknown_type $hook - * @param unknown_type $entity_type - * @param unknown_type $returnvalue - * @param unknown_type $params + * @param string $hook + * @param string $type + * @param null $returnvalue + * @param array $params */ -function twitter_api_tweet($hook, $entity_type, $returnvalue, $params) { - static $plugins; - if (!$plugins) { - $plugins = elgg_trigger_plugin_hook('plugin_list', 'twitter_service', NULL, array()); - } +function twitter_api_tweet($hook, $type, $returnvalue, $params) { - // ensure valid plugin - if (!in_array($params['plugin'], $plugins)) { - return NULL; + if (!elgg_instanceof($params['user'])) { + return; } - // check admin settings - $consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); - $consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); - if (!($consumer_key && $consumer_secret)) { - return NULL; - } + // @todo - allow admin to select origins? // check user settings - $user_id = elgg_get_logged_in_user_guid(); + $user_id = $params['user']->getGUID(); $access_key = elgg_get_plugin_user_setting('access_key', $user_id, 'twitter_api'); $access_secret = elgg_get_plugin_user_setting('access_secret', $user_id, 'twitter_api'); if (!($access_key && $access_secret)) { - return NULL; + return; } - // send tweet - $api = new TwitterOAuth($consumer_key, $consumer_secret, $access_key, $access_secret); - $response = $api->post('statuses/update', array('status' => $params['message'])); + $api = twitter_api_get_api_object($access_key, $access_secret); + if (!$api) { + return; + } - return TRUE; + $api->post('statuses/update', array('status' => $params['message'])); } /** - * Return tweets for a user. + * Get tweets for a user. * - * @param int $user_id The Elgg user GUID + * @param int $user_guid The Elgg user GUID * @param array $options + * @return array */ -function twitter_api_fetch_tweets($user_guid, $options=array()) { - // check admin settings - $consumer_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); - $consumer_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); - if (!($consumer_key && $consumer_secret)) { - return FALSE; - } +function twitter_api_fetch_tweets($user_guid, $options = array()) { // check user settings $access_key = elgg_get_plugin_user_setting('access_key', $user_guid, 'twitter_api'); @@ -143,18 +149,22 @@ function twitter_api_fetch_tweets($user_guid, $options=array()) { return FALSE; } - // fetch tweets - $api = new TwitterOAuth($consumer_key, $consumer_secret, $access_key, $access_secret); + $api = twitter_api_get_api_object($access_key, $access_secret); + if (!$api) { + return FALSE; + } + return $api->get('statuses/user_timeline', $options); } /** * Register as public pages for walled garden. * - * @param unknown_type $hook - * @param unknown_type $type - * @param unknown_type $return_value - * @param unknown_type $params + * @param string $hook + * @param string $type + * @param array $return_value + * @param array $params + * @return array */ function twitter_api_public_pages($hook, $type, $return_value, $params) { $return_value[] = 'twitter_api/forward'; diff --git a/mod/twitter_api/vendors/twitteroauth/OAuth.php b/mod/twitter_api/vendors/twitteroauth/OAuth.php index b0e3cfd5e..e76304146 100644 --- a/mod/twitter_api/vendors/twitteroauth/OAuth.php +++ b/mod/twitter_api/vendors/twitteroauth/OAuth.php @@ -1,6 +1,12 @@ <?php // vim: foldmethod=marker +/* Generic exception class + */ +class OAuthException extends Exception { + // pass +} + class OAuthConsumer { public $key; public $secret; @@ -46,12 +52,56 @@ class OAuthToken { } } -class twitterOAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod_HMAC_SHA1 {/*{{{*/ - function get_name() {/*{{{*/ +/** + * A class for implementing a Signature Method + * See section 9 ("Signing Requests") in the spec + */ +abstract class OAuthSignatureMethod { + /** + * Needs to return the name of the Signature Method (ie HMAC-SHA1) + * @return string + */ + abstract public function get_name(); + + /** + * Build up the signature + * NOTE: The output of this function MUST NOT be urlencoded. + * the encoding is handled in OAuthRequest when the final + * request is serialized + * @param OAuthRequest $request + * @param OAuthConsumer $consumer + * @param OAuthToken $token + * @return string + */ + abstract public function build_signature($request, $consumer, $token); + + /** + * Verifies that a given signature is correct + * @param OAuthRequest $request + * @param OAuthConsumer $consumer + * @param OAuthToken $token + * @param string $signature + * @return bool + */ + public function check_signature($request, $consumer, $token, $signature) { + $built = $this->build_signature($request, $consumer, $token); + return $built == $signature; + } +} + +/** + * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104] + * where the Signature Base String is the text and the key is the concatenated values (each first + * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&' + * character (ASCII code 38) even if empty. + * - Chapter 9.2 ("HMAC-SHA1") + */ +class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod { + function get_name() { return "HMAC-SHA1"; - }/*}}}*/ + } - public function build_signature($request, $consumer, $token) {/*{{{*/ + public function build_signature($request, $consumer, $token) { $base_string = $request->get_signature_base_string(); $request->base_string = $base_string; @@ -63,21 +113,117 @@ class twitterOAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod_HMAC_SH $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); $key = implode('&', $key_parts); - return base64_encode( hash_hmac('sha1', $base_string, $key, true)); - }/*}}}*/ + return base64_encode(hash_hmac('sha1', $base_string, $key, true)); + } +} - public function check_signature(&$request, $consumer, $token, $signature) { - $built = $this->build_signature($request, $consumer, $token); - return $built == $signature; +/** + * The PLAINTEXT method does not provide any security protection and SHOULD only be used + * over a secure channel such as HTTPS. It does not use the Signature Base String. + * - Chapter 9.4 ("PLAINTEXT") + */ +class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod { + public function get_name() { + return "PLAINTEXT"; + } + + /** + * oauth_signature is set to the concatenated encoded values of the Consumer Secret and + * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is + * empty. The result MUST be encoded again. + * - Chapter 9.4.1 ("Generating Signatures") + * + * Please note that the second encoding MUST NOT happen in the SignatureMethod, as + * OAuthRequest handles this! + */ + public function build_signature($request, $consumer, $token) { + $key_parts = array( + $consumer->secret, + ($token) ? $token->secret : "" + ); + + $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); + $key = implode('&', $key_parts); + $request->base_string = $key; + + return $key; } -}/*}}}*/ +} + +/** + * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in + * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for + * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a + * verified way to the Service Provider, in a manner which is beyond the scope of this + * specification. + * - Chapter 9.3 ("RSA-SHA1") + */ +abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { + public function get_name() { + return "RSA-SHA1"; + } + + // Up to the SP to implement this lookup of keys. Possible ideas are: + // (1) do a lookup in a table of trusted certs keyed off of consumer + // (2) fetch via http using a url provided by the requester + // (3) some sort of specific discovery code based on request + // + // Either way should return a string representation of the certificate + protected abstract function fetch_public_cert(&$request); + + // Up to the SP to implement this lookup of keys. Possible ideas are: + // (1) do a lookup in a table of trusted certs keyed off of consumer + // + // Either way should return a string representation of the certificate + protected abstract function fetch_private_cert(&$request); + + public function build_signature($request, $consumer, $token) { + $base_string = $request->get_signature_base_string(); + $request->base_string = $base_string; + + // Fetch the private key cert based on the request + $cert = $this->fetch_private_cert($request); + + // Pull the private key ID from the certificate + $privatekeyid = openssl_get_privatekey($cert); + + // Sign using the key + $ok = openssl_sign($base_string, $signature, $privatekeyid); + + // Release the key resource + openssl_free_key($privatekeyid); + + return base64_encode($signature); + } + + public function check_signature($request, $consumer, $token, $signature) { + $decoded_sig = base64_decode($signature); + + $base_string = $request->get_signature_base_string(); + + // Fetch the public key cert based on the request + $cert = $this->fetch_public_cert($request); + + // Pull the public key ID from the certificate + $publickeyid = openssl_get_publickey($cert); -class twitterOAuthRequest extends OAuthRequest { + // Check the computed signature against the one passed in the query + $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); + + // Release the key resource + openssl_free_key($publickeyid); + + return $ok == 1; + } +} + +class OAuthRequest { private $parameters; private $http_method; private $http_url; // for debug purposes public $base_string; + public static $version = '1.0'; public static $POST_INPUT = 'php://input'; function __construct($http_method, $http_url, $parameters=NULL) { @@ -137,7 +283,7 @@ class twitterOAuthRequest extends OAuthRequest { } - return new twitterOAuthRequest($http_method, $http_url, $parameters); + return new OAuthRequest($http_method, $http_url, $parameters); } /** @@ -145,16 +291,16 @@ class twitterOAuthRequest extends OAuthRequest { */ public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) { @$parameters or $parameters = array(); - $defaults = array("oauth_version" => '1.0', - "oauth_nonce" => twitterOAuthRequest::generate_nonce(), - "oauth_timestamp" => twitterOAuthRequest::generate_timestamp(), + $defaults = array("oauth_version" => OAuthRequest::$version, + "oauth_nonce" => OAuthRequest::generate_nonce(), + "oauth_timestamp" => OAuthRequest::generate_timestamp(), "oauth_consumer_key" => $consumer->key); if ($token) $defaults['oauth_token'] = $token->key; $parameters = array_merge($defaults, $parameters); - return new twitterOAuthRequest($http_method, $http_url, $parameters); + return new OAuthRequest($http_method, $http_url, $parameters); } public function set_parameter($name, $value, $allow_duplicates = true) { @@ -332,6 +478,217 @@ class twitterOAuthRequest extends OAuthRequest { } } +class OAuthServer { + protected $timestamp_threshold = 300; // in seconds, five minutes + protected $version = '1.0'; // hi blaine + protected $signature_methods = array(); + + protected $data_store; + + function __construct($data_store) { + $this->data_store = $data_store; + } + + public function add_signature_method($signature_method) { + $this->signature_methods[$signature_method->get_name()] = + $signature_method; + } + + // high level functions + + /** + * process a request_token request + * returns the request token on success + */ + public function fetch_request_token(&$request) { + $this->get_version($request); + + $consumer = $this->get_consumer($request); + + // no token required for the initial token request + $token = NULL; + + $this->check_signature($request, $consumer, $token); + + // Rev A change + $callback = $request->get_parameter('oauth_callback'); + $new_token = $this->data_store->new_request_token($consumer, $callback); + + return $new_token; + } + + /** + * process an access_token request + * returns the access token on success + */ + public function fetch_access_token(&$request) { + $this->get_version($request); + + $consumer = $this->get_consumer($request); + + // requires authorized request token + $token = $this->get_token($request, $consumer, "request"); + + $this->check_signature($request, $consumer, $token); + + // Rev A change + $verifier = $request->get_parameter('oauth_verifier'); + $new_token = $this->data_store->new_access_token($token, $consumer, $verifier); + + return $new_token; + } + + /** + * verify an api call, checks all the parameters + */ + public function verify_request(&$request) { + $this->get_version($request); + $consumer = $this->get_consumer($request); + $token = $this->get_token($request, $consumer, "access"); + $this->check_signature($request, $consumer, $token); + return array($consumer, $token); + } + + // Internals from here + /** + * version 1 + */ + private function get_version(&$request) { + $version = $request->get_parameter("oauth_version"); + if (!$version) { + // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present. + // Chapter 7.0 ("Accessing Protected Ressources") + $version = '1.0'; + } + if ($version !== $this->version) { + throw new OAuthException("OAuth version '$version' not supported"); + } + return $version; + } + + /** + * figure out the signature with some defaults + */ + private function get_signature_method(&$request) { + $signature_method = + @$request->get_parameter("oauth_signature_method"); + + if (!$signature_method) { + // According to chapter 7 ("Accessing Protected Ressources") the signature-method + // parameter is required, and we can't just fallback to PLAINTEXT + throw new OAuthException('No signature method parameter. This parameter is required'); + } + + if (!in_array($signature_method, + array_keys($this->signature_methods))) { + throw new OAuthException( + "Signature method '$signature_method' not supported " . + "try one of the following: " . + implode(", ", array_keys($this->signature_methods)) + ); + } + return $this->signature_methods[$signature_method]; + } + + /** + * try to find the consumer for the provided request's consumer key + */ + private function get_consumer(&$request) { + $consumer_key = @$request->get_parameter("oauth_consumer_key"); + if (!$consumer_key) { + throw new OAuthException("Invalid consumer key"); + } + + $consumer = $this->data_store->lookup_consumer($consumer_key); + if (!$consumer) { + throw new OAuthException("Invalid consumer"); + } + + return $consumer; + } + + /** + * try to find the token for the provided request's token key + */ + private function get_token(&$request, $consumer, $token_type="access") { + $token_field = @$request->get_parameter('oauth_token'); + $token = $this->data_store->lookup_token( + $consumer, $token_type, $token_field + ); + if (!$token) { + throw new OAuthException("Invalid $token_type token: $token_field"); + } + return $token; + } + + /** + * all-in-one function to check the signature on a request + * should guess the signature method appropriately + */ + private function check_signature(&$request, $consumer, $token) { + // this should probably be in a different method + $timestamp = @$request->get_parameter('oauth_timestamp'); + $nonce = @$request->get_parameter('oauth_nonce'); + + $this->check_timestamp($timestamp); + $this->check_nonce($consumer, $token, $nonce, $timestamp); + + $signature_method = $this->get_signature_method($request); + + $signature = $request->get_parameter('oauth_signature'); + $valid_sig = $signature_method->check_signature( + $request, + $consumer, + $token, + $signature + ); + + if (!$valid_sig) { + throw new OAuthException("Invalid signature"); + } + } + + /** + * check that the timestamp is new enough + */ + private function check_timestamp($timestamp) { + if( ! $timestamp ) + throw new OAuthException( + 'Missing timestamp parameter. The parameter is required' + ); + + // verify that timestamp is recentish + $now = time(); + if (abs($now - $timestamp) > $this->timestamp_threshold) { + throw new OAuthException( + "Expired timestamp, yours $timestamp, ours $now" + ); + } + } + + /** + * check that the nonce is not repeated + */ + private function check_nonce($consumer, $token, $nonce, $timestamp) { + if( ! $nonce ) + throw new OAuthException( + 'Missing nonce parameter. The parameter is required' + ); + + // verify that the nonce is uniqueish + $found = $this->data_store->lookup_nonce( + $consumer, + $token, + $nonce, + $timestamp + ); + if ($found) { + throw new OAuthException("Nonce already used: $nonce"); + } + } + +} + class OAuthDataStore { function lookup_consumer($consumer_key) { // implement me @@ -513,5 +870,3 @@ class OAuthUtil { return implode('&', $pairs); } } - -?> diff --git a/mod/twitter_api/vendors/twitteroauth/README b/mod/twitter_api/vendors/twitteroauth/README index 33cb91f21..c9a17ce4b 100644 --- a/mod/twitter_api/vendors/twitteroauth/README +++ b/mod/twitter_api/vendors/twitteroauth/README @@ -1,7 +1,114 @@ -Abraham Williams | abraham@poseurte.ch | http://abrah.am | @abraham +TwitterOAuth +------------ -The first PHP library for working with Twitter's OAuth API. +PHP library for working with Twitter's OAuth API. -Documentation: http://wiki.github.com/abraham/twitteroauth/documentation -Source: http://github.com/abraham/twitteroauth -Twitter: http://apiwiki.twitter.com +Flow Overview +============= + +1. Build TwitterOAuth object using client credentials. +2. Request temporary credentials from Twitter. +3. Build authorize URL for Twitter. +4. Redirect user to authorize URL. +5. User authorizes access and returns from Twitter. +6. Rebuild TwitterOAuth object with client credentials and temporary credentials. +7. Get token credentials from Twitter. +8. Rebuild TwitterOAuth object with client credentials and token credentials. +9. Query Twitter API. + +Terminology +=========== + +The terminology has changed since 0.1.x to better match the draft-hammer-oauth IETF +RFC. You can read that at http://tools.ietf.org/html/draft-hammer-oauth. Some of the +terms will differ from those Twitter uses as well. + +client credentials - Consumer key/secret you get when registering an app with Twitter. +temporary credentials - Previously known as the request token. +token credentials - Previously known as the access token. + +Parameters +========== + +There are a number of parameters you can modify after creating a TwitterOAuth object. + +Switch an existing TwitterOAuth install to use version 1.1 of the API. + + $connection->$host = "https://api.twitter.com/1.1/"; + +Custom useragent. + + $connection->useragent = 'Custom useragent string'; + +Verify Twitters SSL certificate. + + $connection->ssl_verifypeer = TRUE; + +There are several more you can find in TwitterOAuth.php. + +Extended flow using example code +================================ + +To use TwitterOAuth with the Twitter API you need *TwitterOAuth.php*, *OAuth.php* and +client credentials. You can get client credentials by registering your application at +[dev.twitter.com/apps](https://dev.twitter.com/apps). + +Users start out on connect.php which displays the "Sign in with Twitter" image hyperlinked +to redirect.php. This button should be displayed on your homepage in your login section. The +client credentials are saved in config.php as `CONSUMER_KEY` and `CONSUMER_SECRET`. You can +save a static callback URL in the app settings page, in the config file or use a dynamic +callback URL later in step 2. In example use https://example.com/callback.php. + +1) When a user lands on redirect.php we build a new TwitterOAuth object using the client credentials. +If you have your own configuration method feel free to use it instead of config.php. + + $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET); // Use config.php client credentials + $connection = new TwitterOAuth('abc890', '123xyz'); + +2) Using the built $connection object you will ask Twitter for temporary credentials. The `oauth_callback` value is required. + + $temporary_credentials = $connection->getRequestToken(OAUTH_CALLBACK); // Use config.php callback URL. + +3) Now that we have temporary credentials the user has to go to Twitter and authorize the app +to access and updates their data. You can also pass a second parameter of FALSE to not use [Sign +in with Twitter](https://dev.twitter.com/docs/auth/sign-twitter). + + $redirect_url = $connection->getAuthorizeURL($temporary_credentials); // Use Sign in with Twitter + $redirect_url = $connection->getAuthorizeURL($temporary_credentials, FALSE); + +4) You will now have a Twitter URL that you must send the user to. + + https://api.twitter.com/oauth/authenticate?oauth_token=xyz123 + +5) The user is now on twitter.com and may have to login. Once authenticated with Twitter they will +will either have to click on allow/deny, or will be automatically redirected back to the callback. + +6) Now that the user has returned to callback.php and allowed access we need to build a new +TwitterOAuth object using the temporary credentials. + + $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $_SESSION['oauth_token'], + $_SESSION['oauth_token_secret']); + +7) Now we ask Twitter for long lasting token credentials. These are specific to the application +and user and will act like password to make future requests. Normally the token credentials would +get saved in your database but for this example we are just using sessions. + + $token_credentials = $connection->getAccessToken($_REQUEST['oauth_verifier']); + +8) With the token credentials we build a new TwitterOAuth object. + + $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $token_credentials['oauth_token'], + $token_credentials['oauth_token_secret']); + +9) And finally we can make requests authenticated as the user. You can GET, POST, and DELETE API +methods. Directly copy the path from the API documentation and add an array of any parameter +you wish to include for the API method such as curser or in_reply_to_status_id. + + $account = $connection->get('account/verify_credentials'); + $status = $connection->post('statuses/update', array('status' => 'Text of status here', 'in_reply_to_status_id' => 123456)); + $status = $connection->delete('statuses/destroy/12345'); + +Contributors +============ + +* [Abraham Williams](https://twitter.com/abraham) - Main developer, current maintainer. diff --git a/mod/twitter_api/vendors/twitteroauth/twitterOAuth.php b/mod/twitter_api/vendors/twitteroauth/twitterOAuth.php index a1021ce6f..4c2447c46 100644 --- a/mod/twitter_api/vendors/twitteroauth/twitterOAuth.php +++ b/mod/twitter_api/vendors/twitteroauth/twitterOAuth.php @@ -43,8 +43,8 @@ class TwitterOAuth { * Set API URLS */ function accessTokenURL() { return 'https://api.twitter.com/oauth/access_token'; } - function authenticateURL() { return 'https://twitter.com/oauth/authenticate'; } - function authorizeURL() { return 'https://twitter.com/oauth/authorize'; } + function authenticateURL() { return 'https://api.twitter.com/oauth/authenticate'; } + function authorizeURL() { return 'https://api.twitter.com/oauth/authorize'; } function requestTokenURL() { return 'https://api.twitter.com/oauth/request_token'; } /** @@ -57,7 +57,7 @@ class TwitterOAuth { * construct TwitterOAuth object */ function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) { - $this->sha1_method = new twitterOAuthSignatureMethod_HMAC_SHA1(); + $this->sha1_method = new OAuthSignatureMethod_HMAC_SHA1(); $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret); if (!empty($oauth_token) && !empty($oauth_token_secret)) { $this->token = new OAuthConsumer($oauth_token, $oauth_token_secret); @@ -72,11 +72,9 @@ class TwitterOAuth { * * @returns a key/value array containing oauth_token and oauth_token_secret */ - function getRequestToken($oauth_callback = NULL) { + function getRequestToken($oauth_callback) { $parameters = array(); - if (!empty($oauth_callback)) { - $parameters['oauth_callback'] = $oauth_callback; - } + $parameters['oauth_callback'] = $oauth_callback; $request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters); $token = OAuthUtil::parse_parameters($request); $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']); @@ -108,11 +106,9 @@ class TwitterOAuth { * "user_id" => "9436992", * "screen_name" => "abraham") */ - function getAccessToken($oauth_verifier = FALSE) { + function getAccessToken($oauth_verifier) { $parameters = array(); - if (!empty($oauth_verifier)) { - $parameters['oauth_verifier'] = $oauth_verifier; - } + $parameters['oauth_verifier'] = $oauth_verifier; $request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters); $token = OAuthUtil::parse_parameters($request); $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']); @@ -179,7 +175,7 @@ class TwitterOAuth { if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) { $url = "{$this->host}{$url}.{$this->format}"; } - $request = twitterOAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters); + $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters); $request->sign_request($this->sha1_method, $this->consumer, $this->token); switch ($method) { case 'GET': diff --git a/mod/twitter_api/views/default/forms/twitter_api/interstitial_settings.php b/mod/twitter_api/views/default/forms/twitter_api/interstitial_settings.php new file mode 100644 index 000000000..b4882bb7f --- /dev/null +++ b/mod/twitter_api/views/default/forms/twitter_api/interstitial_settings.php @@ -0,0 +1,67 @@ +<?php +/** + * Make the user set up some alternative ways to login. + */ + +echo '<div>'; +$site = get_config('site'); +echo elgg_echo('twitter_api:interstitial:description', array($site->name)); +echo '</div>'; + +$user = elgg_get_logged_in_user_entity(); + +if (elgg_is_sticky_form('twitter_api_interstitial')) { + extract(elgg_get_sticky_values('twitter_api_interstitial')); + elgg_clear_sticky_form('twitter_api_interstitial'); +} + +if (!isset($display_name)) { + $display_name = $user->name; +} + +// username +$title = elgg_echo('username'); + +$body = elgg_echo('twitter_api:interstitial:username'); +$body .= elgg_view('input/text', array('value' => $user->username, 'disabled' => 'disabled')); + +echo elgg_view_module('info', $title, $body); + +// display name +$title = elgg_echo('name'); + +$body = elgg_echo('twitter_api:interstitial:name'); +$body .= elgg_view('input/text', array('name' => 'display_name', 'value' => $display_name)); + +echo elgg_view_module('info', $title, $body); + +// email +$title = elgg_echo('email'); + +$body = elgg_echo('twitter_api:interstitial:email'); +$body .= elgg_view('input/email', array('name' => 'email', 'value' => $email)); + +echo elgg_view_module('info', $title, $body); + +// password +$title = elgg_echo('password'); + +$body = elgg_echo('twitter_api:interstitial:password'); +$body .= elgg_view('input/password', array('name' => 'password_1')); +$body .= elgg_echo('twitter_api:interstitial:password2'); +$body .= elgg_view('input/password', array('name' => 'password_2')); + +echo elgg_view_module('info', $title, $body); + +// buttons + +echo elgg_view('input/submit', array( + 'value' => elgg_echo('save') +)); + +echo elgg_view('output/url', array( + 'class' => 'float-alt', + 'text' => elgg_echo('twitter_api:interstitial:no_thanks'), + 'href' => '/', + 'is_trusted' => true, +));
\ No newline at end of file diff --git a/mod/twitter_api/views/default/settings/twitter_api/edit.php b/mod/twitter_api/views/default/plugins/twitter_api/settings.php index 9deac3989..3a3ec93a2 100644 --- a/mod/twitter_api/views/default/settings/twitter_api/edit.php +++ b/mod/twitter_api/views/default/plugins/twitter_api/settings.php @@ -1,21 +1,22 @@ <?php /** - * + * Twitter API plugin settings */ -$insert_view = elgg_view('twittersettings/extend'); + +$instructions = elgg_echo('twitter_api:settings:instructions', array(elgg_get_site_url())); $consumer_key_string = elgg_echo('twitter_api:consumer_key'); $consumer_key_view = elgg_view('input/text', array( 'name' => 'params[consumer_key]', 'value' => $vars['entity']->consumer_key, - 'class' => 'text_input', + 'class' => 'elgg-input-thin', )); $consumer_secret_string = elgg_echo('twitter_api:consumer_secret'); $consumer_secret_view = elgg_view('input/text', array( 'name' => 'params[consumer_secret]', 'value' => $vars['entity']->consumer_secret, - 'class' => 'text_input', + 'class' => 'elgg-input-thin', )); $sign_on_with_twitter_string = elgg_echo('twitter_api:login'); @@ -38,12 +39,27 @@ $new_users_with_twitter_view = elgg_view('input/dropdown', array( 'value' => $vars['entity']->new_users ? $vars['entity']->new_users : 'no', )); +$post_to_twitter = ''; +if (elgg_is_active_plugin('thewire')) { + $post_to_twitter_string = elgg_echo('twitter_api:post_to_twitter'); + $post_to_twitter_view = elgg_view('input/dropdown', array( + 'name' => 'params[wire_posts]', + 'options_values' => array( + 'yes' => elgg_echo('option:yes'), + 'no' => elgg_echo('option:no'), + ), + 'value' => $vars['entity']->wire_posts ? $vars['entity']->wire_posts : 'no', + )); + $post_to_twitter = "<div>$post_to_twitter_string $post_to_twitter_view</div>"; +} + $settings = <<<__HTML -<div>$insert_view</div> -<div>$consumer_key_string $consumer_key_view</div> -<div>$consumer_secret_string $consumer_secret_view</div> +<div class="elgg-content-thin mtm"><p>$instructions</p></div> +<div><label>$consumer_key_string</label><br /> $consumer_key_view</div> +<div><label>$consumer_secret_string</label><br /> $consumer_secret_view</div> <div>$sign_on_with_twitter_string $sign_on_with_twitter_view</div> <div>$new_users_with_twitter $new_users_with_twitter_view</div> +$post_to_twitter __HTML; echo $settings; diff --git a/mod/twitter_api/views/default/plugins/twitter_api/usersettings.php b/mod/twitter_api/views/default/plugins/twitter_api/usersettings.php new file mode 100644 index 000000000..edcea2f0d --- /dev/null +++ b/mod/twitter_api/views/default/plugins/twitter_api/usersettings.php @@ -0,0 +1,37 @@ +<?php +/** + * User settings for Twitter API + */ + +$user = elgg_get_logged_in_user_entity(); +$user_guid = $user->getGUID(); +$twitter_name = elgg_get_plugin_user_setting('twitter_name', $user_guid, 'twitter_api'); +$access_key = elgg_get_plugin_user_setting('access_key', $user_guid, 'twitter_api'); +$access_secret = elgg_get_plugin_user_setting('access_secret', $user_guid, 'twitter_api'); + +$site_key = elgg_get_plugin_setting('consumer_key', 'twitter_api'); +$site_secret = elgg_get_plugin_setting('consumer_secret', 'twitter_api'); + +if (!($site_key && $site_secret)) { + echo '<div>' . elgg_echo('twitter_api:usersettings:site_not_configured') . '</div>'; + return true; +} + +$site_name = elgg_get_site_entity()->name; +echo '<div>' . elgg_echo('twitter_api:usersettings:description', array($site_name)) . '</div>'; + +if (!$access_key || !$access_secret) { + // send user off to validate account + $request_link = twitter_api_get_authorize_url(null, false); + echo '<div>' . elgg_echo('twitter_api:usersettings:request', array($request_link, $site_name)) . '</div>'; +} else { + // if this user logged in through twitter and never set up an email address, don't + // let them disassociate their account. + if ($user->email) { + $url = elgg_get_site_url() . "twitter_api/revoke"; + echo '<div>' . elgg_echo('twitter_api:usersettings:authorized', array($site_name, $twitter_name)) . '</div>'; + echo '<div>' . sprintf(elgg_echo('twitter_api:usersettings:revoke'), $url) . '</div>'; + } else { + echo elgg_echo('twitter_api:usersettings:cannot_revoke', array(elgg_normalize_url('twitter_api/interstitial'))); + } +} diff --git a/mod/twitter_api/views/default/twitter_api/css.php b/mod/twitter_api/views/default/twitter_api/css.php index 140ce6a52..2d081d361 100644 --- a/mod/twitter_api/views/default/twitter_api/css.php +++ b/mod/twitter_api/views/default/twitter_api/css.php @@ -4,9 +4,10 @@ */ ?> -#twitter_api_site_settings .text_input { - width: 350px; -} -#login_with_twitter { +.login_with_twitter { padding: 10px 0 0 0; } + +.twitter-secret { + width: 400px; +}
\ No newline at end of file diff --git a/mod/twitter_api/views/default/twitter_api/js.php b/mod/twitter_api/views/default/twitter_api/js.php new file mode 100644 index 000000000..3d2905a44 --- /dev/null +++ b/mod/twitter_api/views/default/twitter_api/js.php @@ -0,0 +1,16 @@ +<?php if (0): ?><script><?php endif; ?> + +// add ?persistent to login link +elgg.register_hook_handler('init', 'system', function() { + $('form.elgg-form-login').each(function () { + var link = $('.login_with_twitter a', this).get(0), + $input = $('input[name="persistent"]', this); + function sync() { + link.href = link.href.replace(/\?.*/, '') + ($input[0].checked ? '?persistent' : ''); + } + if (link && $input.length) { + sync(); + $input.change(sync); + } + }); +}); diff --git a/mod/twitter_api/views/default/twitter_api/login.php b/mod/twitter_api/views/default/twitter_api/login.php index d0aca87ac..7b4b4ecb1 100644 --- a/mod/twitter_api/views/default/twitter_api/login.php +++ b/mod/twitter_api/views/default/twitter_api/login.php @@ -1,13 +1,13 @@ <?php /** - * + * Extension of login form for Twitter sign in */ $url = elgg_get_site_url() . 'twitter_api/forward'; -$img_url = elgg_get_site_url() . 'mod/twitter_api/graphics/sign_in_with_twitter.gif'; +$img_url = elgg_get_site_url() . 'mod/twitter_api/graphics/sign-in-with-twitter-d.png'; $login = <<<__HTML -<div id="login_with_twitter"> +<div class="login_with_twitter"> <a href="$url"> <img src="$img_url" alt="Twitter" /> </a> diff --git a/mod/twitter_api/views/default/usersettings/twitter_api/edit.php b/mod/twitter_api/views/default/usersettings/twitter_api/edit.php deleted file mode 100644 index 77dd5cc5d..000000000 --- a/mod/twitter_api/views/default/usersettings/twitter_api/edit.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php -/** - * - */ - -$user_id = elgg_get_logged_in_user_guid(); -$twitter_name = get_plugin_usersetting('twitter_name', $user_id, 'twitter_api'); -$access_key = get_plugin_usersetting('access_key', $user_id, 'twitter_api'); -$access_secret = get_plugin_usersetting('access_secret', $user_id, 'twitter_api'); - -$site_name = elgg_get_site_entity()->name; -echo '<div>' . elgg_echo('twitter_api:usersettings:description', array($site_name)) . '</div>'; - -if (!$access_key || !$access_secret) { - // send user off to validate account - $request_link = twitter_api_get_authorize_url(); - echo '<div>' . elgg_echo('twitter_api:usersettings:request', array($request_link, $site_name)) . '</div>'; -} else { - $url = elgg_get_site_url() . "twitter_api/revoke"; - echo '<div class="twitter_anywhere">' . elgg_echo('twitter_api:usersettings:authorized', array($site_name, $twitter_name)) . '</div>'; - echo '<div>' . sprintf(elgg_echo('twitter_api:usersettings:revoke'), $url) . '</div>'; -} |
