| 1 | <?php |
|---|
| 2 | /** |
|---|
| 3 | * Twitter Silo |
|---|
| 4 | */ |
|---|
| 5 | class TwitterSilo extends Plugin implements MediaSilo |
|---|
| 6 | { |
|---|
| 7 | const SILO_NAME = 'Twitter'; |
|---|
| 8 | const CONSUMER_KEY = 'xBsV65xckJicZlcjHorQ'; |
|---|
| 9 | const CONSUMER_SECRET = 'm6HEFdJBYAd45mbo33GIgnSmmcbyx3Wo1YCymgUlc'; |
|---|
| 10 | |
|---|
| 11 | protected $Twitter; |
|---|
| 12 | /** |
|---|
| 13 | * Return basic information about this silo |
|---|
| 14 | * name- The name of the silo, used as the root directory for media in this silo |
|---|
| 15 | * icon- An icon to represent the silo |
|---|
| 16 | */ |
|---|
| 17 | public function silo_info() |
|---|
| 18 | { |
|---|
| 19 | return array( 'name' => self::SILO_NAME ); |
|---|
| 20 | } |
|---|
| 21 | |
|---|
| 22 | /** |
|---|
| 23 | * Return directory contents for the silo path |
|---|
| 24 | * @param string $path The path to retrieve the contents of |
|---|
| 25 | * @return array An array of MediaAssets describing the contents of the directory |
|---|
| 26 | **/ |
|---|
| 27 | public function silo_dir( $path ) |
|---|
| 28 | { |
|---|
| 29 | switch ( strtok( $path, '/' ) ) { |
|---|
| 30 | case '': |
|---|
| 31 | return array( |
|---|
| 32 | new MediaAsset( self::SILO_NAME . '/mine/', true ), |
|---|
| 33 | new MediaAsset( self::SILO_NAME . '/friends/', true ), |
|---|
| 34 | new MediaAsset( self::SILO_NAME . '/custom/', true ), |
|---|
| 35 | ); |
|---|
| 36 | break; // (for good measure) |
|---|
| 37 | |
|---|
| 38 | case 'custom': |
|---|
| 39 | return array( |
|---|
| 40 | new MediaAsset( |
|---|
| 41 | self::SILO_NAME . '/mine/custom', |
|---|
| 42 | false, |
|---|
| 43 | array( |
|---|
| 44 | 'url' => 'http://twitter.com/home', |
|---|
| 45 | 'filetype' => 'twittertweetcustom', |
|---|
| 46 | ) |
|---|
| 47 | ), |
|---|
| 48 | ); |
|---|
| 49 | break; // (for good measure) |
|---|
| 50 | |
|---|
| 51 | case 'mine': |
|---|
| 52 | return $this->get_mine(); |
|---|
| 53 | break; // (for good measure) |
|---|
| 54 | |
|---|
| 55 | case 'friends': |
|---|
| 56 | $friend = strtok( '/' ); |
|---|
| 57 | if ( $friend === false ) { |
|---|
| 58 | return $this->get_friends(); |
|---|
| 59 | } |
|---|
| 60 | else { |
|---|
| 61 | return $this->get_friend_tweets( $friend ); |
|---|
| 62 | } |
|---|
| 63 | break; // (for good measure) |
|---|
| 64 | } |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | /** |
|---|
| 68 | * Get the file from the specified path |
|---|
| 69 | * @param string $path The path of the file to retrieve |
|---|
| 70 | * @param array $qualities Qualities that specify the version of the file to retrieve. |
|---|
| 71 | * @return MediaAsset The requested asset |
|---|
| 72 | **/ |
|---|
| 73 | public function silo_get( $path, $qualities = null ) |
|---|
| 74 | { |
|---|
| 75 | return MediaAsset( 'foo', false ); |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | /** |
|---|
| 79 | * Store the specified media at the specified path |
|---|
| 80 | * @param string $path The path of the file to retrieve |
|---|
| 81 | * @param MediaAsset The asset to store |
|---|
| 82 | **/ |
|---|
| 83 | public function silo_put( $path, $filedata ) {} |
|---|
| 84 | |
|---|
| 85 | /** |
|---|
| 86 | * Delete the file at the specified path |
|---|
| 87 | * @param string $path The path of the file to retrieve |
|---|
| 88 | **/ |
|---|
| 89 | public function silo_delete( $path ) {} |
|---|
| 90 | |
|---|
| 91 | /** |
|---|
| 92 | * Retrieve a set of highlights from this silo |
|---|
| 93 | * This would include things like recently uploaded assets, or top downloads |
|---|
| 94 | * @return array An array of MediaAssets to highlihgt from this silo |
|---|
| 95 | **/ |
|---|
| 96 | public function silo_highlights() {} |
|---|
| 97 | |
|---|
| 98 | /** |
|---|
| 99 | * Retrieve the permissions for the current user to access the specified path |
|---|
| 100 | * @param string $path The path to retrieve permissions for |
|---|
| 101 | * @return array An array of permissions constants (MediaSilo::PERM_READ, MediaSilo::PERM_WRITE) |
|---|
| 102 | **/ |
|---|
| 103 | public function silo_permissions( $path ) {} |
|---|
| 104 | |
|---|
| 105 | |
|---|
| 106 | public function action_admin_footer( $theme ) |
|---|
| 107 | { |
|---|
| 108 | if ( Controller::get_var( 'page' ) == 'publish' ) { |
|---|
| 109 | ?><script type="text/javascript"> |
|---|
| 110 | function inject_tweet(text, url, user, img) { |
|---|
| 111 | habari.editor.insertSelection('<!-- TWEET --><div class="twitter-tweet"><div class="tweet-text"><a href="' + url + '"><img src="' + img + '" class="tweet-image" /></a>' + text + '</div><div class="tweet-author"><a href="' + url + '">' + user + '</a></div></div><!-- /TWEET -->'); |
|---|
| 112 | } |
|---|
| 113 | //$('.media_controls').css('display', 'none'); |
|---|
| 114 | habari.media.output.twittertweet = {'Insert': function(fileindex, fileobj) { |
|---|
| 115 | inject_tweet(fileobj.tweet_text, fileobj.url, fileobj.tweet_user, fileobj.tweet_user_img); |
|---|
| 116 | }} |
|---|
| 117 | habari.media.preview.twittertweet = function(fileindex, fileobj) { |
|---|
| 118 | return '<div class="mediatitle"><a href="' + fileobj.url + '" target="_new" class="medialink">media</a>' + fileobj.tweet_user_screen_name + '</div>' + fileobj.tweet_text_short; |
|---|
| 119 | } |
|---|
| 120 | habari.media.output.twittertweetcustom = {'Insert': function(fileindex, fileobj) { |
|---|
| 121 | $.get("<?php echo Site::get_url('habari'); ?>/auth_ajax/tweetcustom?tweet=" + escape($('#tweetcustom').val()), function( data ){ |
|---|
| 122 | if (data.text) { |
|---|
| 123 | inject_tweet(data.text, 'http://twitter.com/' + escape(data.user.screen_name) + '/statuses/' + escape(data.id), data.user.screen_name, data.user.profile_image_url); |
|---|
| 124 | } |
|---|
| 125 | }, {}, 'json' ); |
|---|
| 126 | }} |
|---|
| 127 | habari.media.preview.twittertweetcustom = function(fileindex, fileobj) { |
|---|
| 128 | return '<div class="mediatitle">CUSTOM</div>Tweet ID/URL: <input id="tweetcustom" type="text" />'; |
|---|
| 129 | } |
|---|
| 130 | </script><?php |
|---|
| 131 | } |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| 134 | |
|---|
| 135 | public function action_auth_ajax_tweetcustom( $handler ) |
|---|
| 136 | { |
|---|
| 137 | $tweet = isset( $_GET['tweet'] ) ? $_GET['tweet'] : ''; |
|---|
| 138 | $tweet = preg_replace( '@http://(www\.)?twitter.com/([^/]+)/([^/]+)/([0-9]+)@', '$4', $tweet ); |
|---|
| 139 | if ( ctype_digit( $tweet ) ) { |
|---|
| 140 | $ret = self::twitter_status( $tweet ); |
|---|
| 141 | } |
|---|
| 142 | else { |
|---|
| 143 | $ret = false; |
|---|
| 144 | } |
|---|
| 145 | echo json_encode( $ret ); |
|---|
| 146 | } |
|---|
| 147 | |
|---|
| 148 | public function theme_header() |
|---|
| 149 | { |
|---|
| 150 | // add CSS |
|---|
| 151 | return '<link rel="stylesheet" type="text/css" media="screen" href="' |
|---|
| 152 | . $this->get_url( true ) . 'twittersilo.css" />'; |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | protected function get_mine() |
|---|
| 156 | { |
|---|
| 157 | return $this->to_assets( self::twitter_mine(), 'mine' ); |
|---|
| 158 | } |
|---|
| 159 | |
|---|
| 160 | protected function get_friend_tweets ( $id ) |
|---|
| 161 | { |
|---|
| 162 | return $this->to_assets( self::twitter_friend_tweets( $id ), 'friends' ); |
|---|
| 163 | } |
|---|
| 164 | |
|---|
| 165 | protected function get_friends() |
|---|
| 166 | { |
|---|
| 167 | $friends = array(); |
|---|
| 168 | $friendsObj = self::twitter_friends(); |
|---|
| 169 | if ( ! empty( $friendsObj ) ) { |
|---|
| 170 | foreach ( $friendsObj as $friend ) { |
|---|
| 171 | $friends[] = new MediaAsset( self::SILO_NAME . '/friends/' . $friend->screen_name, true ); |
|---|
| 172 | } |
|---|
| 173 | } |
|---|
| 174 | return $friends; |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | protected function to_assets( $objs, $type ) |
|---|
| 178 | { |
|---|
| 179 | foreach ($objs as $obj) { |
|---|
| 180 | $tweets[] = new MediaAsset( |
|---|
| 181 | self::SILO_NAME . '/' . $type . '/' . $obj->user->name . '/' . $obj->id, |
|---|
| 182 | false, |
|---|
| 183 | array( |
|---|
| 184 | 'tweet_id' => $obj->id, |
|---|
| 185 | 'url' => 'http://twitter.com/' . $obj->user->screen_name . '/statuses/' . $obj->id, |
|---|
| 186 | 'tweet_user' => (string) $obj->user->name, |
|---|
| 187 | 'tweet_user_img' => (string) $obj->user->profile_image_url, |
|---|
| 188 | 'tweet_user_screen_name' => (string) $obj->user->screen_name, |
|---|
| 189 | 'tweet_text_short' => substr( $obj->text, 0, 20 ) . ( strlen( $obj->text ) > 20 ? '...' : '' ), |
|---|
| 190 | 'tweet_text' => (string) $obj->text, |
|---|
| 191 | 'filetype' => 'twittertweet', |
|---|
| 192 | ) |
|---|
| 193 | ); |
|---|
| 194 | } |
|---|
| 195 | return $tweets; |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | /** |
|---|
| 199 | * Add actions to the plugin page for this plugin |
|---|
| 200 | * The authorization should probably be done per-user. |
|---|
| 201 | * |
|---|
| 202 | * @param array $actions An array of actions that apply to this plugin |
|---|
| 203 | * @param string $plugin_id The string id of a plugin, generated by the system |
|---|
| 204 | * @return array The array of actions to attach to the specified $plugin_id |
|---|
| 205 | */ |
|---|
| 206 | public function filter_plugin_config( $actions, $plugin_id ) |
|---|
| 207 | { |
|---|
| 208 | if ( User::identify()->info->twittersilo__access_token ) { |
|---|
| 209 | $actions['deauthorize'] = _t( 'De-Authorize' ); |
|---|
| 210 | } |
|---|
| 211 | else { |
|---|
| 212 | $actions['authorize'] = _t( 'Authorize' ); |
|---|
| 213 | } |
|---|
| 214 | return $actions; |
|---|
| 215 | } |
|---|
| 216 | |
|---|
| 217 | /** |
|---|
| 218 | * Respond to the user selecting an action on the plugin page |
|---|
| 219 | * |
|---|
| 220 | * @param string $plugin_id The string id of the acted-upon plugin |
|---|
| 221 | * @param string $action The action string supplied via the filter_plugin_config hook |
|---|
| 222 | */ |
|---|
| 223 | public function action_plugin_ui( $plugin_id, $action ) |
|---|
| 224 | { |
|---|
| 225 | $ui = new FormUI( strtolower( __CLASS__ ) ); |
|---|
| 226 | $user = User::identify(); |
|---|
| 227 | require_once dirname( __FILE__ ) . '/lib/twitteroauth/twitteroauth.php'; |
|---|
| 228 | |
|---|
| 229 | switch ( $action ){ |
|---|
| 230 | case 'authorize': |
|---|
| 231 | unset( $_SESSION['TwitterSiloReqToken'] ); // Just being safe. |
|---|
| 232 | $oauth = new TwitterOAuth(TwitterSilo::CONSUMER_KEY, TwitterSilo::CONSUMER_SECRET ); |
|---|
| 233 | $oauth_token = $oauth->getRequestToken( URL::get( 'admin', array( 'page' => 'plugins', 'configure' => $this->plugin_id(), 'configaction' => 'confirm' ) ) ); |
|---|
| 234 | $request_link = $oauth->getAuthorizeURL( $oauth_token ); |
|---|
| 235 | $reqToken = array( "request_link" => $request_link, "request_token" => $oauth_token['oauth_token'], "request_token_secret" => $oauth_token['oauth_token_secret'] ); |
|---|
| 236 | $_SESSION['TwitterSiloReqToken'] = serialize( $reqToken ); |
|---|
| 237 | $ui->append( 'static', 'nocontent', '<h3>Authorize the Habari TwitterSilo Plugin</h3> |
|---|
| 238 | <p>Authorize your blog to have access to your Twitter account.</p> |
|---|
| 239 | <p>Click the button below, and you will be taken to Twitter.com. If you\'re already logged in, you will be presented with the option to authorize your blog. Press the "Allow" button to do so, and you will come right back here.</p> |
|---|
| 240 | <br><p style="text-align:center"><a href="'.$reqToken['request_link'].'"><img src="'. URL::get_from_filesystem( __FILE__ ) .'/lib/twitter_connect.png" alt="Sign in with Twitter" /></a></p> |
|---|
| 241 | '); |
|---|
| 242 | $ui->out(); |
|---|
| 243 | break; |
|---|
| 244 | |
|---|
| 245 | case 'confirm': |
|---|
| 246 | if( !isset( $_SESSION['TwitterSiloReqToken'] ) ){ |
|---|
| 247 | $auth_url = URL::get( 'admin', array( 'page' => 'plugins', 'configure' => $this->plugin_id(), 'configaction' => 'authorize' ) ); |
|---|
| 248 | $ui->append( 'static', 'nocontent', '<p>'._t( 'Either you have already authorized Habari to access your Twitter account, or you have not yet done so. Please ' ).'<strong><a href="' . $auth_url . '">'._t( 'try again' ).'</a></strong>.</p>'); |
|---|
| 249 | $ui->out(); |
|---|
| 250 | } |
|---|
| 251 | else { |
|---|
| 252 | $reqToken = unserialize( $_SESSION['TwitterSiloReqToken'] ); |
|---|
| 253 | $oauth = new TwitterOAuth( TwitterSilo::CONSUMER_KEY, TwitterSilo::CONSUMER_SECRET, $reqToken['request_token'], $reqToken['request_token_secret'] ); |
|---|
| 254 | $token = $oauth->getAccessToken($_GET['oauth_verifier']); |
|---|
| 255 | //$config_url = URL::get( 'admin', array( 'page' => 'plugins', 'configure' => $this->plugin_id(), 'configaction' => 'Configure' ) ); |
|---|
| 256 | |
|---|
| 257 | if( ! empty( $token ) && isset( $token['oauth_token'] ) ){ |
|---|
| 258 | $user->info->twittersilo__access_token = $token['oauth_token']; |
|---|
| 259 | $user->info->twittersilo__access_token_secret = $token['oauth_token_secret']; |
|---|
| 260 | $user->info->twittersilo__user_id = $token['user_id']; |
|---|
| 261 | $user->info->commit(); |
|---|
| 262 | echo '<form><p>'._t( 'Habari TwitterSilo plugin successfully authorized.' ).'</p></form>'; |
|---|
| 263 | Session::notice( _t( 'Habari TwitterSilo plugin successfully authorized.', 'twittersilo' ) ); |
|---|
| 264 | //Utils::redirect( $config_url ); |
|---|
| 265 | } |
|---|
| 266 | else{ |
|---|
| 267 | // TODO: We need to fudge something to report the error in the event something fails. Sadly, the Twitter OAuth class we use doesn't seem to cater for errors very well and returns the Twitter XML response as an array key. |
|---|
| 268 | // TODO: Also need to gracefully cater for when users click "Deny" |
|---|
| 269 | echo '<form><p>'._t( 'There was a problem with your authorization.' ).'</p></form>'; |
|---|
| 270 | } |
|---|
| 271 | unset( $_SESSION['TwitterSiloReqToken'] ); |
|---|
| 272 | } |
|---|
| 273 | break; |
|---|
| 274 | case 'deauthorize': |
|---|
| 275 | $user->info->twittersilo__user_id = ''; |
|---|
| 276 | $user->info->twittersilo__access_token = ''; |
|---|
| 277 | $user->info->twittersilo__access_token_secret = ''; |
|---|
| 278 | $user->info->commit(); |
|---|
| 279 | $reauth_url = URL::get( 'admin', array( 'page' => 'plugins', 'configure' => $this->plugin_id(), 'configaction' => 'authorize' ) ) . '#plugin_options'; |
|---|
| 280 | $ui->append( 'static', 'nocontent', '<p>'._t( 'The Twitter Plugin authorization has been deleted. Please ensure you ' ) . '<a href="http://twitter.com/settings/connections" target="_blank">' . _t( 'revoke access ' ).'</a>'._t( 'from your Twitter account too.' ).'<p><p>'._t( 'Do you want to ' ).'<b><a href="'.$reauth_url.'">'._t( 're-authorize this plugin' ).'</a></b>?<p>' ); |
|---|
| 281 | Session::notice( _t( 'Habari TwitterSilo plugin authorization revoked. <br>Don\'t forget to revoke access on Twitter itself.', 'twitter' ) ); |
|---|
| 282 | //Utils::redirect( $reauth_url ); |
|---|
| 283 | $ui->out(); |
|---|
| 284 | break; |
|---|
| 285 | } |
|---|
| 286 | } |
|---|
| 287 | |
|---|
| 288 | protected static function twitter_fetch ( $url ) |
|---|
| 289 | { |
|---|
| 290 | $user = User::identify(); |
|---|
| 291 | require_once dirname( __FILE__ ) . '/lib/twitteroauth/twitteroauth.php'; |
|---|
| 292 | |
|---|
| 293 | $connection = new TwitterOAuth( TwitterSilo::CONSUMER_KEY, TwitterSilo::CONSUMER_SECRET, $user->info->twittersilo__access_token, $user->info->twittersilo__access_token_secret ); |
|---|
| 294 | $connection->useragent = 'Habari Twitter Silo - 1.1'; |
|---|
| 295 | |
|---|
| 296 | if ( $result = $connection->get( $url ) ) { |
|---|
| 297 | return $result; |
|---|
| 298 | } |
|---|
| 299 | else { |
|---|
| 300 | return false; |
|---|
| 301 | } |
|---|
| 302 | } |
|---|
| 303 | |
|---|
| 304 | protected static function twitter_status( $id ) |
|---|
| 305 | { |
|---|
| 306 | return self::twitter_fetch( 'statuses/show/' . $id ); |
|---|
| 307 | } |
|---|
| 308 | |
|---|
| 309 | protected static function twitter_mine( ) |
|---|
| 310 | { |
|---|
| 311 | return self::twitter_fetch( 'statuses/user_timeline' ); |
|---|
| 312 | } |
|---|
| 313 | |
|---|
| 314 | protected static function twitter_friend_tweets( $id ) |
|---|
| 315 | { |
|---|
| 316 | return self::twitter_fetch( 'statuses/user_timeline/'. urlencode( $id ) ); |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | protected static function twitter_friends( ) |
|---|
| 320 | { |
|---|
| 321 | return self::twitter_fetch( 'statuses/friends' ); |
|---|
| 322 | } |
|---|
| 323 | |
|---|
| 324 | } |
|---|
| 325 | |
|---|
| 326 | ?> |
|---|