├── README.md ├── composer.json ├── publishiza.php ├── publishiza ├── assets │ ├── css │ │ └── publishiza.css │ └── js │ │ └── publishiza.js ├── includes │ ├── admin.php │ ├── capabilities.php │ ├── hooks.php │ ├── keyring.php │ ├── service.php │ └── twitter.php └── keyring │ ├── admin-ui.php │ ├── includes │ ├── oauth-php │ │ ├── CHANGELOG.txt │ │ ├── LICENSE.txt │ │ ├── OAuth.php │ │ ├── OAuthTests.xml │ │ ├── OAuth_TestServer.php │ │ ├── doc │ │ │ └── design.txt │ │ └── tests │ │ │ ├── Mock_OAuthBaseStringRequest.php │ │ │ ├── Mock_OAuthDataStore.php │ │ │ ├── Mock_OAuthSignatureMethod_RSA_SHA1.php │ │ │ ├── OAuthConsumerTest.php │ │ │ ├── OAuthRequestTest.php │ │ │ ├── OAuthServerTest.php │ │ │ ├── OAuthSignatureMethodHmacSha1Test.php │ │ │ ├── OAuthSignatureMethodPlaintextTest.php │ │ │ ├── OAuthSignatureMethodRsaSha1Test.php │ │ │ ├── OAuthTokenTest.php │ │ │ ├── OAuthUtilTest.php │ │ │ └── common.php │ ├── services │ │ ├── core │ │ │ ├── http-basic.php │ │ │ ├── oauth1.php │ │ │ └── oauth2.php │ │ └── extended │ │ │ ├── 500px.php │ │ │ ├── delicious.php │ │ │ ├── eventbrite.php │ │ │ ├── facebook.php │ │ │ ├── fitbit.php │ │ │ ├── flickr.php │ │ │ ├── foursquare.php │ │ │ ├── google-contacts.php │ │ │ ├── instagram.php │ │ │ ├── instapaper.php │ │ │ ├── linkedin.php │ │ │ ├── moves.php │ │ │ ├── nest.php │ │ │ ├── pinterest.php │ │ │ ├── runkeeper.php │ │ │ ├── tripit.php │ │ │ ├── tumblr.php │ │ │ ├── twitter.php │ │ │ └── yahoo.php │ └── stores │ │ └── singlestore.php │ ├── keyring.php │ ├── languages │ └── keyring.po │ ├── readme.txt │ ├── service.php │ ├── store.php │ └── token.php └── readme.txt /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Publishiza 3 | 4 | Compose and publish a Tweetstorm, all from inside your WordPress. 5 | 6 | * Seamlessly integrates into your WordPress dashboard interface 7 | * Safe, secure, & efficient 8 | 9 | Publishiza includes Keyring, a great foundation by my pal Beau Lebens. 10 | 11 | # Installation 12 | 13 | * Download and install using the built in WordPress plugin installer. 14 | * Activate in the "Plugins" area of your admin by clicking the "Activate" link. 15 | * Visit: Tools > Keyring 16 | * Add a New Service 17 | * Authorize Publishiza 18 | 19 | # FAQ 20 | 21 | ### Does this create new database tables? 22 | 23 | No. It uses WordPress's custom post-type, custom taxonomy, and metadata APIs. 24 | 25 | ### Does this modify existing database tables? 26 | 27 | No. All of WordPress's core database tables remain untouched. 28 | 29 | ### Where can I get support? 30 | 31 | * Here on GitHub: https://github.com/JJJ/publishiza/ 32 | 33 | ### Can I contribute? 34 | 35 | Yes, please! 36 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jjj/publishiza", 3 | "description": "Compose and publish a Tweetstorm, all from inside your WordPress.", 4 | "homepage": "https://github.com/jjj/publishiza", 5 | "type": "wordpress-plugin", 6 | "require": { 7 | "php": ">=5.2", 8 | "composer/installers": "^1.0" 9 | }, 10 | "license": "GPLv2 or later", 11 | "authors": [ 12 | { 13 | "name": "John James Jacoby", 14 | "email": "johnjamesjacoby@me.com" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /publishiza.php: -------------------------------------------------------------------------------- 1 | 'keyring', 'action' => 'services' ), admin_url( 'tools.php' ) ); 114 | wp_safe_redirect( $redirect_to ); 115 | exit; 116 | } 117 | add_action( 'activated_plugin', 'publishiza_activation_redirect' ); 118 | -------------------------------------------------------------------------------- /publishiza/assets/css/publishiza.css: -------------------------------------------------------------------------------- 1 | #publishiza-action { 2 | margin: 10px; 3 | } 4 | 5 | #publishiza-select { 6 | line-height: 2.5em; 7 | margin-top: 3px; 8 | display: none; 9 | } 10 | #publishiza-select select#pts_post_type { 11 | margin-right: 2px; 12 | } 13 | #publishiza-select a#save-publishiza { 14 | vertical-align: middle; 15 | margin-right: 2px; 16 | } 17 | #publishiza-display { 18 | font-weight: bold; 19 | } 20 | #post-body .publishiza::before { 21 | content: '\f301'; 22 | font: 400 20px/1 dashicons; 23 | speak: none; 24 | display: inline-block; 25 | padding: 0 2px 0 0; 26 | top: 0; 27 | left: -1px; 28 | position: relative; 29 | vertical-align: top; 30 | -webkit-font-smoothing: antialiased; 31 | -moz-osx-font-smoothing: grayscale; 32 | text-decoration: none !important; 33 | color: #888; 34 | } 35 | -------------------------------------------------------------------------------- /publishiza/assets/js/publishiza.js: -------------------------------------------------------------------------------- 1 | jQuery( function( $ ) { 2 | var $publish_btn = $( '#publish' ), 3 | $edit = $( '#edit-publishiza' ), 4 | $save = $( '#save-publishiza' ), 5 | $cancel = $( '#cancel-publishiza' ), 6 | $select = $( '#publishiza-select' ), 7 | $display = $( '#publishiza-display' ), 8 | $publish_text = $publish_btn.val(); 9 | 10 | $( '.misc-pub-section.curtime.misc-pub-section-last' ).removeClass( 'misc-pub-section-last' ); 11 | 12 | $edit.on( 'click', function( e ) { 13 | $( this ).hide(); 14 | $select.slideDown(); 15 | e.preventDefault(); 16 | } ); 17 | 18 | $save.on( 'click', function( e ) { 19 | var $select_text = $( '#publishiza :selected' ).text(); 20 | 21 | $select.slideUp(); 22 | $edit.show(); 23 | $display.text( $select_text ); 24 | 25 | if ( 'on' === $select_text ) { 26 | $publish_btn.val( '\u{1F4A9}\u{1F329}' ); 27 | } else { 28 | $publish_btn.val( $publish_text ); 29 | } 30 | 31 | e.preventDefault(); 32 | } ); 33 | 34 | $cancel.on( 'click', function( e ) { 35 | $select.slideUp(); 36 | $edit.show(); 37 | e.preventDefault(); 38 | } ); 39 | } ); 40 | -------------------------------------------------------------------------------- /publishiza/includes/admin.php: -------------------------------------------------------------------------------- 1 | get_tokens( array( 29 | 'service' => 'publishiza', 30 | 'user_id' => $post->post_author 31 | ) ); 32 | 33 | // Not authed 34 | if ( ! empty( $tokens ) ) { 35 | $setup = true; 36 | } ?> 37 | 38 |
' . __( '← Back', 'publishiza' ) . '
'; 72 | echo '' . __( 'Credentials saved.', 'publishiza' ) . '
' . __( 'In a separate browser tab, login to Twitter with the account you would like to connect to Publishiza, then click "Connect"', 'publishiza' ) . '
'; 130 | } 131 | } 132 | 133 | // 134 | remove_action( 'keyring_load_services', array( 'Keyring_Service_Twitter', 'init' ) ); 135 | add_action( 'keyring_load_services', array( 'Keyring_Service_Publishiza', 'init' ) ); 136 | -------------------------------------------------------------------------------- /publishiza/includes/twitter.php: -------------------------------------------------------------------------------- 1 | 'array', 14 | 'description' => esc_html__( 'Publishiza response information from Twitter', 'publishiza' ), 15 | 'single' => true, 16 | 'sanitize_callback' => 'publishiza_sanitize_post_meta', 17 | 'auth_callback' => 'publishiza_auth_post_meta', 18 | 'show_in_rest' => true 19 | ) ); 20 | } 21 | 22 | /** 23 | * Publishiza to Twitter 24 | * 25 | * @since 1.0.0 26 | * 27 | * @param int $post_id 28 | * @param WP_Post $post 29 | */ 30 | function publishiza_publish_post( $post_id = 0, $post = null ) { 31 | 32 | // Bail if not Publishiza'ing 33 | if ( empty( $_POST['publishiza'] ) ) { 34 | return; 35 | } 36 | 37 | // Bail if already Publishizaed 38 | if ( get_post_meta( $post_id, 'publishiza', true ) ) { 39 | return; 40 | } 41 | 42 | // Bail if nonce fails 43 | if ( ! wp_verify_nonce( 'publishiza-nonce', 'publishiza-select' ) ) { 44 | //return; 45 | } 46 | 47 | // Publishiza & get response 48 | $response = publishiza_maybe_post_to_twitter( $post ); 49 | 50 | // Save response to prevent 51 | add_post_meta( $post_id, 'publishiza', array( 52 | 'time' => time(), 53 | 'start' => $response 54 | ) ); 55 | } 56 | 57 | /** 58 | * Maybe Publishiza a WordPress post to Twitter 59 | * 60 | * Check for valid service/tokens/tweets – bail if there is a problem 61 | * 62 | * @since 1.0.0 63 | * 64 | * @param WP_Post $post 65 | */ 66 | function publishiza_maybe_post_to_twitter( $post = null ) { 67 | 68 | // Look for Publishiza connection 69 | $service = Keyring::get_service_by_name( 'publishiza' ); 70 | 71 | // Bail if no connection to Twitter 72 | if ( ! $service->is_connected() ) { 73 | return; 74 | } 75 | 76 | // Look for auth tokens 77 | $tokens = Keyring::get_token_store()->get_tokens( array( 78 | 'service' => 'publishiza', 79 | 'user_id' => $post->post_author 80 | ) ); 81 | 82 | // Bail if not authed 83 | if ( empty( $tokens ) ) { 84 | return false; 85 | } 86 | 87 | // Process post content into Tweets 88 | $tweets = publishiza_get_tweets_from_text( $post->post_content, $post ); 89 | 90 | // Bail if no tweets 91 | if ( empty( $tweets ) ) { 92 | return false; 93 | } 94 | 95 | // Try to post tweets to Twitter 96 | return publishiza_post_tweets_to_twitter( array( 97 | 'tweets' => $tweets, 98 | 'service' => $service, 99 | 'tokens' => $tokens 100 | ) ); 101 | } 102 | 103 | /** 104 | * Return array of strings for more predictable fitment into Twitter's current 105 | * 140 character restriction. 106 | * 107 | * @since 1.1.0 108 | * 109 | * @param string $text 110 | * @return array 111 | */ 112 | function publishiza_get_tweets_from_text( $text = '', $text_object = null ) { 113 | 114 | /** 115 | * Filter length of individual tweets 116 | * 117 | * @since 1.0.0 118 | * 119 | * @param int 119 Maximum length of each tweet 120 | * @return int 121 | */ 122 | $length = (int) apply_filters( 'publishiza_storm_length', 119 ); 123 | 124 | // Format text blob for word wrapping 125 | $decoded = html_entity_decode( $text, ENT_QUOTES, 'UTF-8' ); 126 | $stripped = wp_strip_all_tags( $decoded, true ); 127 | 128 | /** 129 | * Filter the plain-text, so it can be stormed 130 | * 131 | * @since 1.1.0 132 | * 133 | * @param string $stripped Stripped text 134 | * @param string $text Original text 135 | * @return string 136 | */ 137 | $filtered = (string) apply_filters( 'publishiza_storm_text', $stripped, $text, $text_object ); 138 | 139 | // Wrap text blob into a managable array 140 | $split = wordwrap( $filtered, $length, "\n", false ); 141 | $trimmed = array_map( 'trim', explode( "\n", $split ) ); 142 | $tweets = array_filter( $trimmed ); 143 | 144 | /** 145 | * Filter array of tweets, processed from $text 146 | * 147 | * @since 1.1.0 148 | * 149 | * @param array $tweets Array of all tweets 150 | * @param string $text The original text 151 | * @param int $length The maximum length of each tweet 152 | * @return array 153 | */ 154 | return (array) apply_filters( 'publishiza_format_post_content_for_twitter', $tweets, $text, $length ); 155 | } 156 | 157 | /** 158 | * Sends multiple POST requests to the Twitter API, one for each tweet in the 159 | * array of tweets passed 160 | * 161 | * @since 1.1.0 162 | * 163 | * @param array $tweets 164 | * @param Keyring_Service $service 165 | * 166 | * @return boolean 167 | */ 168 | function publishiza_post_tweets_to_twitter( $args = array() ) { 169 | 170 | // Parse args 171 | $r = wp_parse_args( $args, array( 172 | 'tweets' => array(), 173 | 'service' => null, 174 | 'tokens' => null 175 | ) ); 176 | 177 | // Bail if nothing to do 178 | if ( empty( $r['tweets'] ) || empty( $r['tokens'] ) || empty( $r['service'] ) ) { 179 | return false; 180 | } 181 | 182 | // Storm settings 183 | $sleep = apply_filters( 'publishiza_storm_sleep', 2 ); 184 | $control = apply_filters( 'publishiza_storm_control', html_entity_decode( '💩🌩 ', 0, 'UTF-8' ) ); 185 | $ndash = apply_filters( 'publishiza_storm_divider', html_entity_decode( '–', 0, 'UTF-8' ) ); 186 | $ellip = apply_filters( 'publishiza_storm_ellipsis', html_entity_decode( '…', 0, 'UTF-8' ) ); 187 | $count = count( $r['tweets'] ); 188 | $responses = array(); 189 | $first = false; 190 | 191 | // Loop through connections (multiple accounts can storm simultaneously) 192 | foreach ( $r['tokens'] as $token ) { 193 | 194 | // Set the token 195 | $r['service']->token = $token; 196 | $previous_status_id = false; 197 | 198 | // Storm 199 | foreach ( $r['tweets'] as $index => $tweet ) { 200 | 201 | // Build the prefix 202 | $position = (int) $index + 1; 203 | $prefix = apply_filters( 'publishiza_storm_prefix', "{$control}{$position}/{$count} {$ndash} " ); 204 | $text = "{$prefix}{$tweet}"; 205 | 206 | // Maybe append an ellipsis 207 | if ( ! empty( $ellip ) && ( $position !== $count ) ) { 208 | $text = "{$text}{$ellip}"; 209 | } 210 | 211 | // Get request body 212 | $body = array( 213 | 'status' => $text, 214 | 'trim_user' => 1 215 | ); 216 | 217 | // Maybe in response to the first ID 218 | if ( ( $position > 1 ) && ! empty( $previous_status_id ) ) { 219 | $body['in_reply_to_status_id'] = (int) $previous_status_id; 220 | } 221 | 222 | // Send update to Twitter 223 | $response = $r['service']->request( $r['service']->update_url, array( 224 | 'method' => $r['service']->update_method, 225 | 'body' => $body 226 | ) ); 227 | 228 | // Error! 229 | if ( is_a( $response, 'Keyring_Error' ) ) { 230 | return false; 231 | } 232 | 233 | // Setup storm 234 | if ( isset( $response->id ) ) { 235 | $previous_status_id = $response->id; 236 | 237 | // Set first response ID 238 | if ( empty( $first ) && ( 1 === $position ) ) { 239 | $first = $response->id; 240 | } 241 | } 242 | 243 | // Add response to responses array (@todo: save for debug?) 244 | $responses[] = $response; 245 | 246 | // Wait to avoid being throttled 247 | sleep( $sleep ); 248 | } 249 | } 250 | 251 | // Return ID of first tweet 252 | return $first; 253 | } 254 | 255 | /** 256 | * Maybe append the short-link to the end of the blog post content 257 | * 258 | * @since 1.1.0 259 | * 260 | * @param string $text 261 | * @param string $original 262 | * @param WP_Post $object 263 | * 264 | * @return string 265 | */ 266 | function publishiza_append_short_link( $text = '', $original = '', $object = null ) { 267 | 268 | // Bail if no text or not a post object 269 | if ( empty( $text ) || ! is_a( $object, 'WP_Post' ) ) { 270 | return $text; 271 | } 272 | 273 | // Bail if turned off 274 | if ( ! apply_filters( 'publishiza_append_short_link', false, $object ) ) { 275 | return $text; 276 | } 277 | 278 | // Get the short link 279 | $shorty = wp_get_shortlink( $post->ID, 'post', false ); 280 | 281 | // Return text, maybe with appended short-link 282 | return ! empty( $shorty ) 283 | ? "{$text} - {$shorty}" 284 | : $text; 285 | } 286 | -------------------------------------------------------------------------------- /publishiza/keyring/admin-ui.php: -------------------------------------------------------------------------------- 1 | Keyring) which includes: 5 | * - managing Service credentials 6 | * - creating connections 7 | * - deleting connections 8 | * - (coming soon) managing active/inactive Services 9 | * 10 | * Run Keyring with KEYRING__HEADLESS_MODE defined as true to disable all UI. 11 | * 12 | * @package Keyring 13 | */ 14 | class Keyring_Admin_UI { 15 | var $keyring = false; 16 | 17 | function __construct() { 18 | add_action( 'admin_menu', array( $this, 'admin_menu' ) ); 19 | } 20 | 21 | static function &init() { 22 | static $instance = false; 23 | 24 | if ( !$instance ) { 25 | $instance = new Keyring_Admin_UI; 26 | } 27 | 28 | return $instance; 29 | } 30 | 31 | function inline_css() { 32 | ?>keyring = Keyring::init(); 47 | add_action( 'admin_head', array( $this, 'inline_css' ) ); 48 | } 49 | 50 | function admin_page_header( $screen = false ) { 51 | // Output the actual heading + icon for the page 52 | echo '' . __( '← Back', 'keyring' ) . '
'; 61 | break; 62 | case 'error' : 63 | echo '' . __( 'Click a service to create a new connection:', 'keyring' ) . '
'; 179 | echo '' . __( 'There are no fully-configured services available to connect to.', 'keyring' ) . '
'; 196 | } 197 | 198 | if ( current_user_can( 'manage_options' ) && count( $not_configured ) ) { 199 | echo '' . __( 'The following services need to be configured correctly before you can connect to them.', 'keyring' ) . '
'; 200 | echo '' . sprintf( __( 'You haven\'t added any connections yet. Add a New Connection.', 'keyring' ), esc_url( Keyring_Util::admin_url( false, array( 'action' => 'services' ) ) ) ) . '
'; 238 | } 239 | 240 | function get_columns() { 241 | return array( 242 | 'service' => __( 'Service', 'keyring' ), 243 | 'avatar' => __( 'Avatar', 'keyring' ), 244 | 'id' => __( 'External ID', 'keyring' ), 245 | 'name' => __( 'Name', 'keyring' ), 246 | 'meta' => __( 'Meta', 'keyring' ), 247 | 'actions' => ' ' 248 | ); 249 | } 250 | 251 | function column_service( $row ) { 252 | echo $row->get_service()->get_label(); 253 | } 254 | 255 | function column_avatar( $row ) { 256 | $picture = set_url_scheme( $row->get_meta( 'picture' ) ); 257 | if ( $picture ) { 258 | echo '' . sprintf( __( 'Enter your username and password for accessing %s:', 'keyring' ), $this->get_label() ) . '
'; 71 | echo ''; 88 | echo '' . sprintf( __( 'To connect to 500px, you\'ll need to create an application at 500px.com.', 'keyring' ), 'https://500px.com/settings/applications' ) . '
'; 42 | echo '' . __( "Once you've created your app, enter the Consumer Key and Consumer Secret below.", 'keyring' ) . '
'; 43 | } 44 | 45 | function parse_response( $response ) { 46 | return json_decode( $response ); 47 | } 48 | 49 | function build_token_meta( $token ) { 50 | // Set the token so that we can make requests using it 51 | $this->set_token( 52 | new Keyring_Access_Token( 53 | $this->get_name(), 54 | new OAuthToken( 55 | $token['oauth_token'], 56 | $token['oauth_token_secret'] 57 | ) 58 | ) 59 | ); 60 | 61 | $response = $this->request( "https://api.500px.com/v1/users", array( 'method' => 'GET' ) ); 62 | 63 | if ( Keyring_Util::is_error( $response ) ) { 64 | $meta = array(); 65 | } else { 66 | $meta = array( 67 | 'user_id' => $response->user->id, 68 | 'username' => $response->user->username, 69 | 'name' => $response->user->fullname, 70 | 'picture' => $response->user->userpic_https_url, 71 | ); 72 | } 73 | 74 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 75 | } 76 | 77 | function get_display( Keyring_Access_Token $token ) { 78 | return $token->get_meta( 'username' ); 79 | } 80 | 81 | function test_connection() { 82 | $response = $this->request( $this->users_url, array( 'method' => $this->users_method ) ); 83 | if ( ! Keyring_Util::is_error( $response ) ) { 84 | return true; 85 | } 86 | 87 | return $response; 88 | } 89 | } 90 | 91 | add_action( 'keyring_load_services', array( 'Keyring_Service_500px', 'init' ) ); 92 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/delicious.php: -------------------------------------------------------------------------------- 1 | set_endpoint( 'verify', 'https://api.del.icio.us/v1/posts/update', 'GET' ); 10 | $this->requires_token( true ); 11 | } 12 | 13 | function _get_credentials() { 14 | return false; 15 | } 16 | 17 | function parse_response( $data ) { 18 | return simplexml_load_string( $data ); 19 | } 20 | 21 | function get_display( Keyring_Access_Token $token ) { 22 | return $token->get_meta( 'username' ); 23 | } 24 | 25 | function test_connection() { 26 | $response = $this->request( 'https://api.del.icio.us/v1/posts/all?results=1' ); 27 | if ( ! Keyring_Util::is_error( $response ) ) { 28 | return true; 29 | } 30 | 31 | return $response; 32 | } 33 | } 34 | 35 | add_action( 'keyring_load_services', array( 'Keyring_Service_Delicious', 'init' ) ); 36 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/eventbrite.php: -------------------------------------------------------------------------------- 1 | get_name() . '_request_token_params', array( $this, 'add_connection_referrer' ) ); 18 | 19 | $this->set_endpoint( 'authorize', self::OAUTH_BASE . 'authorize', 'GET' ); 20 | $this->set_endpoint( 'access_token', self::OAUTH_BASE . 'token', 'POST' ); 21 | $this->set_endpoint( 'self', self::API_BASE . 'users/me/', 'GET' ); 22 | 23 | // Enable "basic" UI for entering key/secret 24 | if ( ! KEYRING__HEADLESS_MODE ) { 25 | add_action( 'keyring_eventbrite_manage_ui', array( $this, 'basic_ui' ) ); 26 | add_filter( 'keyring_eventbrite_basic_ui_intro', array( $this, 'basic_ui_intro' ) ); 27 | } 28 | 29 | $creds = $this->get_credentials(); 30 | $this->app_id = $creds['app_id']; 31 | $this->key = $creds['key']; 32 | $this->secret = $creds['secret']; 33 | 34 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 35 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 36 | 37 | $this->authorization_header = 'Bearer'; 38 | $this->authorization_parameter = false; 39 | } 40 | 41 | /** 42 | * Append a referrer to the oAuth request made to Eventbrite, at their request 43 | * 44 | * See http://themedevp2.wordpress.com/2013/12/05/can-we-add-refwpoauth-to/ 45 | * 46 | * @param array $params 47 | * @filter keyring_eventbrite_request_token_params 48 | * @return array 49 | */ 50 | public function add_connection_referrer( $params ) { 51 | if ( ! isset( $params['ref'] ) ) { 52 | $params['ref'] = 'wpoauth'; 53 | } 54 | 55 | return $params; 56 | } 57 | 58 | function basic_ui_intro() { 59 | echo '' . sprintf( __( "To get started, register an OAuth client on Eventbrite. The most important setting is the OAuth redirect_uri, which should be set to %s
. You can set the other values to whatever you like.", 'keyring' ), esc_url( Keyring_Util::admin_url( 'eventbrite', array( 'action' => 'verify' ) ) ) ) . '
' . __( "Once you've saved those changes, copy the APPLICATION KEY value into the API Key field, then click the 'Show' link next to the OAuth client secret, copy the value into the API Secret field and click save (you don't need an App ID value for Eventbrite).", 'keyring' ) . '
'; 61 | } 62 | 63 | function build_token_meta( $token ) { 64 | $this->set_token( 65 | new Keyring_Access_Token( 66 | $this->get_name(), 67 | $token['access_token'], 68 | array() 69 | ) 70 | ); 71 | $response = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 72 | $meta = array(); 73 | if ( !Keyring_Util::is_error( $response ) ) { 74 | if ( isset( $response->emails->email ) ) { 75 | $meta['username'] = $response->emails->email; 76 | } 77 | 78 | if ( isset( $response->id ) ) { 79 | $meta['user_id'] = $response->id; 80 | } 81 | 82 | if ( isset( $response->name ) ) { 83 | $meta['name'] = $response->name; 84 | } 85 | } 86 | 87 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, null, $this ); 88 | } 89 | 90 | function get_display( Keyring_Access_Token $token ) { 91 | return $token->get_meta( 'name' ); 92 | } 93 | 94 | function parse_response( $response ) { 95 | return json_decode( $response ); 96 | } 97 | 98 | function test_connection() { 99 | $res = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 100 | if ( !Keyring_Util::is_error( $res ) ) { 101 | return true; 102 | } 103 | 104 | return $res; 105 | } 106 | } 107 | 108 | add_action( 'keyring_load_services', array( 'Keyring_Service_Eventbrite', 'init' ) ); 109 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/facebook.php: -------------------------------------------------------------------------------- 1 | set_endpoint( 'authorize', 'https://www.facebook.com/v2.2/dialog/oauth', 'GET' ); 21 | $this->set_endpoint( 'access_token', 'https://graph.facebook.com/v2.2/oauth/access_token', 'GET' ); 22 | $this->set_endpoint( 'self', 'https://graph.facebook.com/v2.2/me', 'GET' ); 23 | $this->set_endpoint( 'profile_pic', 'https://graph.facebook.com/v2.2/me/picture/?redirect=false&width=150&height=150', 'GET' ); 24 | 25 | $creds = $this->get_credentials(); 26 | $this->app_id = $creds['app_id']; 27 | $this->key = $creds['key']; 28 | $this->secret = $creds['secret']; 29 | 30 | $kr_nonce = wp_create_nonce( 'keyring-verify' ); 31 | $nonce = wp_create_nonce( 'keyring-verify-facebook' ); 32 | $this->redirect_uri = Keyring_Util::admin_url( self::NAME, array( 'action' => 'verify', 'kr_nonce' => $kr_nonce, 'nonce' => $nonce, ) ); 33 | 34 | $this->requires_token( true ); 35 | 36 | add_filter( 'keyring_facebook_request_token_params', array( $this, 'filter_request_token' ) ); 37 | } 38 | 39 | function basic_ui_intro() { 40 | echo '' . __( "If you haven't already, you'll need to set up an app on Facebook:", 'keyring' ) . '
'; 41 | echo '%s
", 'keyring' ), $_SERVER['HTTP_HOST'] ) . '%s
", 'keyring' ), get_bloginfo( 'url' ) ) . '' . __( "Once you're done configuring your app, copy and paste your App ID and App Secret (in the top section of your app's Basic details) into the appropriate fields below. Leave the App Key field blank.", 'keyring' ) . '
'; 50 | } 51 | 52 | function _get_credentials() { 53 | if ( 54 | defined( 'KEYRING__FACEBOOK_ID' ) 55 | && 56 | defined( 'KEYRING__FACEBOOK_SECRET' ) 57 | ) { 58 | return array( 59 | 'app_id' => constant( 'KEYRING__FACEBOOK_ID' ), 60 | 'key' => constant( 'KEYRING__FACEBOOK_ID' ), 61 | 'secret' => constant( 'KEYRING__FACEBOOK_SECRET' ), 62 | ); 63 | } else { 64 | $all = apply_filters( 'keyring_credentials', get_option( 'keyring_credentials' ) ); 65 | if ( !empty( $all['facebook'] ) ) { 66 | $creds = $all['facebook']; 67 | $creds['key'] = $creds['app_id']; 68 | return $creds; 69 | } 70 | 71 | // Return null to allow fall-thru to checking generic constants + DB 72 | return null; 73 | } 74 | } 75 | 76 | function is_configured() { 77 | $credentials = $this->get_credentials(); 78 | return !empty( $credentials['app_id'] ) && !empty( $credentials['secret'] ); 79 | } 80 | 81 | /** 82 | * Add scope to the outbound URL, and allow developers to modify it 83 | * @param array $params Core request parameters 84 | * @return Array containing originals, plus the scope parameter 85 | */ 86 | function filter_request_token( $params ) { 87 | if ( $scope = implode( ',', apply_filters( 'keyring_facebook_scope', array() ) ) ) 88 | $params['scope'] = $scope; 89 | return $params; 90 | } 91 | 92 | /** 93 | * Facebook decided to make things interesting and mix OAuth1 and 2. They return 94 | * their access tokens using query string encoding, so we handle that here. 95 | */ 96 | function parse_access_token( $token ) { 97 | parse_str( $token, $token ); 98 | return $token; 99 | } 100 | 101 | function build_token_meta( $token ) { 102 | $this->set_token( 103 | new Keyring_Access_Token( 104 | $this->get_name(), 105 | $token['access_token'], 106 | array() 107 | ) 108 | ); 109 | $response = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 110 | if ( Keyring_Util::is_error( $response ) ) { 111 | $meta = array(); 112 | } else { 113 | $meta = array( 114 | 'user_id' => $response->id, 115 | 'name' => $response->name, 116 | 'picture' => "https://graph.facebook.com/v2.2/{$response->id}/picture?type=large", 117 | ); 118 | } 119 | 120 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 121 | } 122 | 123 | function get_display( Keyring_Access_Token $token ) { 124 | return $token->get_meta( 'name' ); 125 | } 126 | 127 | function test_connection() { 128 | $res = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 129 | if ( ! Keyring_Util::is_error( $res ) ) 130 | return true; 131 | 132 | return $res; 133 | } 134 | 135 | /** 136 | * Get a list of FB Pages that this user has permissions to manage 137 | * @param Keyring_Token $connection A connection to FB. 138 | * @return Array containing the raw results for each page, or empty if none. 139 | */ 140 | function get_fb_pages( $connection = false ) { 141 | if ( $connection ) 142 | $this->set_token( $connection ); 143 | 144 | $additional_external_users = array(); 145 | $fb_accounts = $this->request( 'https://graph.facebook.com/v2.2/me/accounts/' ); 146 | if ( ! empty( $fb_accounts ) && ! is_wp_error( $fb_accounts ) ) { 147 | foreach ( $fb_accounts->data as $fb_account ) { 148 | $fb_page = $this->request( 'https://graph.facebook.com/v2.2/' . urlencode( $fb_account->id ) ); 149 | 150 | // only continue with this account as a viable option if we can post content to it 151 | if ( ! $fb_page->is_published || ! $fb_page->can_post ) { 152 | continue; 153 | } 154 | 155 | $this_fb_page = array( 156 | 'id' => $fb_page->id, 157 | 'name' => $fb_page->name, 158 | 'access_token' => $fb_account->access_token, 159 | 'category' => $fb_page->category, 160 | 'picture' => null, 161 | ); 162 | 163 | $picture = $this->request( 'https://graph.facebook.com/v2.2/' . urlencode( $fb_account->id ) . '/picture?redirect=false' ); 164 | if ( !empty( $picture->data ) ) { 165 | $this_fb_page['picture'] = esc_url_raw( $picture->data->url ); 166 | } 167 | 168 | $additional_external_users[] = (object) $this_fb_page; 169 | } 170 | } 171 | 172 | 173 | return $additional_external_users; 174 | } 175 | 176 | function fetch_additional_external_users() { 177 | return $this->get_fb_pages(); 178 | } 179 | } 180 | 181 | add_action( 'keyring_load_services', array( 'Keyring_Service_Facebook', 'init' ) ); 182 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/fitbit.php: -------------------------------------------------------------------------------- 1 | set_endpoint( 'authorize', 'https://www.fitbit.com/oauth2/authorize', 'GET' ); 23 | $this->set_endpoint( 'access_token', 'https://api.fitbit.com/oauth2/token', 'POST' ); 24 | $this->set_endpoint( 'refresh', 'https://api.fitbit.com/oauth2/token', 'POST' ); 25 | $this->set_endpoint( 'profile', 'https://api.fitbit.com/1/user/-/profile.json', 'GET' ); 26 | 27 | $creds = $this->get_credentials(); 28 | $this->app_id = $creds['app_id']; 29 | $this->key = $creds['key']; 30 | $this->secret = $creds['secret']; 31 | 32 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 33 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 34 | 35 | // Fitbit requires an exact match on Redirect URI, which means we can't send any nonces 36 | $this->callback_url = remove_query_arg( array( 'nonce', 'kr_nonce' ), $this->callback_url ); 37 | add_action( 'pre_keyring_fitbit_verify', array( $this, 'redirect_incoming_verify' ) ); 38 | 39 | // Send authorization via header 40 | $this->authorization_header = 'Bearer'; 41 | 42 | add_filter( 'keyring_fitbit_request_token_params', array( $this, 'request_token_params' ) ); 43 | add_filter( 'keyring_fitbit_verify_token_params', array( $this, 'verify_token_params' ) ); 44 | add_filter( 'keyring_fitbit_verify_token_post_params', array( $this, 'verify_token_post_params' ) ); 45 | 46 | add_filter( 'keyring_access_token', array( $this, 'fix_access_token_meta' ), 10, 2 ); 47 | } 48 | 49 | function basic_ui_intro() { 50 | echo '' . sprintf( __( 'Go to Fitbit and create a new application, which allows Keyring to talk to Fitbit.', 'keyring' ), 'https://dev.fitbit.com/apps/new' ) . '
'; 51 | echo '' . sprintf( __( "You can use anything for the name/description details etc. Make sure you set the OAuth 2.0 Application Type to Personal (grants you some extra access) and set your Callback URL to %s
. You only need Read-Only access if you are syncing data, but Read & Write will let you update details as well.", 'keyring' ), Keyring_Util::admin_url( self::NAME, array( 'action' => 'verify' ) ) ) . '
' . sprintf( __( 'To connect to Flickr, you\'ll need to create an application at Flickr.com. If this is a personal website then you can use a non-commercial key (which will be approved automatically).', 'keyring' ), 'http://www.flickr.com/services/apps/create/apply/?' ) . '
'; 37 | echo '' . __( "Once you've created your app, enter the API Key and Secret below (App ID is not required for Flickr apps).", 'keyring' ) . '
'; 38 | } 39 | 40 | function build_token_meta( $token ) { 41 | // Need to make a request to get full information 42 | $this->set_token( 43 | new Keyring_Access_Token( 44 | $this->get_name(), 45 | new OAuthToken( 46 | $token['oauth_token'], 47 | $token['oauth_token_secret'] 48 | ) 49 | ) 50 | ); 51 | $url = "https://api.flickr.com/services/rest/?"; 52 | $params = array( 53 | 'method' => 'flickr.people.getInfo', 54 | 'api_key' => $this->key, 55 | 'user_id' => $token['user_nsid'], 56 | ); 57 | $url = $url . http_build_query( $params ); 58 | 59 | $response = $this->request( $url, array( 'method' => 'GET' ) ); 60 | if ( Keyring_Util::is_error( $response ) ) { 61 | $meta = array(); 62 | } else { 63 | $meta = array( 64 | 'user_id' => $token['user_nsid'], 65 | 'username' => $token['username'], 66 | 'name' => $token['fullname'], 67 | 'picture' => "http://farm{$response->person->iconfarm}.staticflickr.com/{$response->person->iconserver}/buddyicons/{$token['user_nsid']}.jpg", 68 | ); 69 | } 70 | 71 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 72 | } 73 | 74 | function get_display( Keyring_Access_Token $token ) { 75 | $return = ''; 76 | $meta = $token->get_meta(); 77 | if ( !empty( $meta['name'] ) ) 78 | return $meta['name']; 79 | else if ( !empty( $meta['username'] ) ) 80 | return $meta['username']; 81 | } 82 | 83 | /** 84 | * Custom request method so that we can force JSON for Flickr, which otherwise 85 | * uses XML. 86 | * @param string $url The URL to request 87 | * @param array $params Any additional parameters requried for this reqeust 88 | * @return Mixed with either a Keyring_Error, or a decoded JSON response object 89 | */ 90 | function request( $url, array $params = array() ) { 91 | // http://www.flickr.com/services/api/response.json.html 92 | $url = add_query_arg( 93 | array( 94 | 'format' => 'json', // Always return JSON 95 | 'nojsoncallback' => 1, // Don't wrap it in a callback 96 | ), 97 | $url ); 98 | return parent::request( $url, $params ); 99 | } 100 | 101 | /** 102 | * Since we're forcing all requests to be for JSON data, we can decode 103 | * all responses as JSON as well. 104 | * @param string $response Full content of the response 105 | * @return JSON object representation of the response 106 | */ 107 | function parse_response( $response ) { 108 | return json_decode( $response ); 109 | } 110 | 111 | function test_connection() { 112 | $url = "https://api.flickr.com/services/rest/?"; 113 | $params = array( 114 | 'method' => 'flickr.test.login', 115 | 'api_key' => $this->key, 116 | ); 117 | $url = $url . http_build_query( $params ); 118 | 119 | $response = $this->request( $url ); 120 | if ( ! Keyring_Util::is_error( $response ) ) { 121 | return true; 122 | } 123 | 124 | return $response; 125 | } 126 | } 127 | 128 | add_action( 'keyring_load_services', array( 'Keyring_Service_Flickr', 'init' ) ); 129 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/foursquare.php: -------------------------------------------------------------------------------- 1 | set_endpoint( 'authorize', 'https://foursquare.com/oauth2/authenticate', 'GET' ); 25 | $this->set_endpoint( 'access_token', 'https://foursquare.com/oauth2/access_token', 'GET' ); 26 | $this->set_endpoint( 'self', 'https://api.foursquare.com/v2/users/self', 'GET' ); 27 | 28 | $creds = $this->get_credentials(); 29 | $this->app_id = $creds['app_id']; 30 | $this->key = $creds['key']; 31 | $this->secret = $creds['secret']; 32 | 33 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 34 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 35 | } 36 | 37 | function basic_ui_intro() { 38 | echo '' . sprintf( __( 'If you haven\'t already, you\'ll need to create a new app at Foursquare. You should only need to worry about these settings:', 'keyring' ), 'https://foursquare.com/developers/register' ) . '
'; 39 | echo '%s
", 'keyring' ), get_bloginfo( 'url' ) ) . '%s
", 'keyring' ), Keyring_Util::admin_url( 'foursquare', array( 'action' => 'verify' ) ) ) . '' . __( "Once you've saved those changes, copy the Client id value into the API Key field, and the Client secret value into the API Secret field and click save (you don't need an App ID value for Foursquare).", 'keyring' ) . '
'; 46 | } 47 | 48 | function build_token_meta( $token ) { 49 | $token = new Keyring_Access_Token( $this->get_name(), $token['access_token'], array() ); 50 | $this->set_token( $token ); 51 | $res = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 52 | if ( Keyring_Util::is_error( $res ) ) { 53 | $meta = array(); 54 | } else { 55 | $meta = array( 56 | 'user_id' => $res->response->user->id, 57 | 'first_name' => $res->response->user->firstName, 58 | 'last_name' => $res->response->user->lastName, 59 | 'picture' => $res->response->user->photo->prefix . '300x300' . $res->response->user->photo->suffix, 60 | ); 61 | } 62 | 63 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $res, $this ); 64 | } 65 | 66 | function get_display( Keyring_Access_Token $token ) { 67 | $meta = $token->get_meta(); 68 | return trim( $meta['first_name'] . ' ' . $meta['last_name'] ); 69 | } 70 | 71 | function request( $url, array $params = array() ) { 72 | $url = add_query_arg( array( 'v' => self::API_VERSION ), $url ); 73 | return parent::request( $url, $params ); 74 | } 75 | 76 | function test_connection() { 77 | $response = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 78 | if ( ! Keyring_Util::is_error( $response ) ) { 79 | return true; 80 | } 81 | 82 | return $response; 83 | } 84 | } 85 | 86 | add_action( 'keyring_load_services', array( 'Keyring_Service_Foursquare', 'init' ) ); 87 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/google-contacts.php: -------------------------------------------------------------------------------- 1 | set_endpoint( 'authorize', 'https://accounts.google.com/o/oauth2/auth', 'GET' ); 35 | $this->set_endpoint( 'access_token', 'https://accounts.google.com/o/oauth2/token', 'POST' ); 36 | $this->set_endpoint( 'self', 'https://www.googleapis.com/oauth2/v1/userinfo', 'GET' ); 37 | 38 | $creds = $this->get_credentials(); 39 | $this->redirect_uri = $creds['redirect_uri']; 40 | $this->key = $creds['key']; 41 | $this->secret = $creds['secret']; 42 | 43 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 44 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 45 | 46 | $this->authorization_header = 'Bearer'; // Oh, you 47 | $this->authorization_parameter = false; 48 | 49 | // Need to reset the callback because Google is very strict about where it sends people 50 | if ( !empty( $creds['redirect_uri'] ) ) 51 | $this->callback_url = $creds['redirect_uri']; // Allow user to manually enter a redirect URI 52 | else 53 | $this->callback_url = remove_query_arg( array( 'nonce', 'kr_nonce' ), $this->callback_url ); // At least strip nonces, since you can't save them in your app config 54 | } 55 | 56 | function basic_ui_intro() { 57 | echo '' . sprintf( __( "Google controls access to all of their APIs through their API Console. Go to the console and click the project dropdown just under the logo in the upper left of the screen. Click Create… to create a new project. Enter a name and then click Create project. You don't technically need access to any of the additional APIs, but if you want to, then feel free to enable them", 'keyring' ), 'https://code.google.com/apis/console' ) . '
'; 58 | echo '' . __( "Now you need to set up an OAuth Client ID.", 'keyring' ) . '
'; 59 | echo '%s
", 'keyring' ), Keyring_Util::admin_url( $this->get_name(), array( 'action' => 'verify' ) ) ) . 'http://%s
", 'keyring' ), $_SERVER['HTTP_HOST'] ) . '' . __( "Once you've saved your details, copy the Client ID into the Client ID field below, and the Client secret value into Client Secret. The Redirect URI box should fill itself out for you.", 'keyring' ) . '
'; 70 | } 71 | 72 | function _get_credentials() { 73 | if ( 74 | defined( 'KEYRING__GOOGLECONTACTS_KEY' ) 75 | && 76 | defined( 'KEYRING__GOOGLECONTACTS_SECRET' ) 77 | ) { 78 | return array( 79 | 'redirect_uri' => defined( 'KEYRING__GOOGLECONTACTS_URI' ) ? constant( 'KEYRING__GOOGLECONTACTS_URI' ) : '', // optional 80 | 'key' => constant( 'KEYRING__GOOGLECONTACTS_KEY' ), 81 | 'secret' => constant( 'KEYRING__GOOGLECONTACTS_SECRET' ), 82 | ); 83 | } else { 84 | return null; 85 | } 86 | } 87 | 88 | function request_token_params( $params ) { 89 | $params['scope'] = self::SCOPE; 90 | return $params; 91 | } 92 | 93 | function redirect_incoming_verify( $request ) { 94 | if ( !isset( $request['kr_nonce'] ) ) { 95 | // First request, from Google. Nonce it and move on. 96 | $kr_nonce = wp_create_nonce( 'keyring-verify' ); 97 | $nonce = wp_create_nonce( 'keyring-verify-' . $this->get_name() ); 98 | wp_safe_redirect( 99 | Keyring_Util::admin_url( 100 | $this->get_name(), 101 | array( 102 | 'action' => 'verify', 103 | 'kr_nonce' => $kr_nonce, 104 | 'nonce' => $nonce, 105 | 'state' => $request['state'], 106 | 'code' => $request['code'], // Auth code from successful response (maybe) 107 | ) 108 | ) 109 | ); 110 | exit; 111 | } 112 | } 113 | 114 | function build_token_meta( $token ) { 115 | $meta = array(); 116 | if ( !$token ) 117 | return $meta; 118 | 119 | $token = new Keyring_Access_Token( $this->get_name(), new OAuthToken( $token['access_token'], '' ), array() ); 120 | $this->set_token( $token ); 121 | $response = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 122 | if ( !Keyring_Util::is_error( $response ) ) { 123 | $meta = array( 124 | 'user_id' => $response->id, 125 | 'name' => $response->name, 126 | 'profile' => $response->link, 127 | 'picture' => $response->picture, 128 | ); 129 | } 130 | 131 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 132 | } 133 | 134 | function get_display( Keyring_Access_Token $token ) { 135 | return $token->get_meta( 'name' ); 136 | } 137 | 138 | function request( $url, array $params = array() ) { 139 | // add header (version), required for all requests 140 | $params['headers']['GData-Version'] = self::API_VERSION; 141 | 142 | return parent::request( $url, $params ); 143 | } 144 | 145 | // Minor modifications from Keyring_Service::basic_ui 146 | function basic_ui() { 147 | if ( !isset( $_REQUEST['nonce'] ) || !wp_verify_nonce( $_REQUEST['nonce'], 'keyring-manage-' . $this->get_name() ) ) { 148 | Keyring::error( __( 'Invalid/missing management nonce.', 'keyring' ) ); 149 | exit; 150 | } 151 | 152 | // Common Header 153 | echo '' . __( '← Back', 'keyring' ) . '
'; 157 | echo '' . __( 'Credentials saved.', 'keyring' ) . '
' . sprintf( __( 'To get started, register an OAuth client on Instagram. The most important setting is the OAuth redirect_uri, which should be set to %2$s
. You can set the other values to whatever you like.', 'keyring' ), 'http://instagram.com/developer/clients/register/', Keyring_Util::admin_url( 'instagram', array( 'action' => 'verify' ) ) ) . '
' . __( "Once you've saved those changes, copy the CLIENT ID value into the API Key field, and the CLIENT SECRET value into the API Secret field and click save (you don't need an App ID value for Instagram).", 'keyring' ) . '
'; 40 | } 41 | 42 | function build_token_meta( $token ) { 43 | if ( empty( $token['user'] ) ) { 44 | $meta = array(); 45 | } else { 46 | $meta = array( 47 | 'user_id' => $token['user']->id, 48 | 'username' => $token['user']->username, 49 | 'name' => $token['user']->full_name, 50 | 'picture' => $token['user']->profile_picture, 51 | ); 52 | } 53 | 54 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, null, $this ); 55 | } 56 | 57 | function get_display( Keyring_Access_Token $token ) { 58 | return $token->get_meta( 'name' ); 59 | } 60 | 61 | function test_connection() { 62 | $response = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 63 | if ( ! Keyring_Util::is_error( $response ) ) { 64 | return true; 65 | } 66 | 67 | return $response; 68 | } 69 | } 70 | 71 | add_action( 'keyring_load_services', array( 'Keyring_Service_Instagram', 'init' ) ); 72 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/instapaper.php: -------------------------------------------------------------------------------- 1 | authorization_header = true; 22 | 23 | $this->set_endpoint( 'access_token', 'https://www.instapaper.com/api/1/oauth/access_token', 'POST' ); 24 | $this->set_endpoint( 'verify', 'https://www.instapaper.com/api/1/account/verify_credentials', 'POST' ); 25 | 26 | $creds = $this->get_credentials(); 27 | $this->app_id = $creds['app_id']; 28 | $this->key = $creds['key']; 29 | $this->secret = $creds['secret']; 30 | 31 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 32 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 33 | 34 | $this->requires_token( true ); 35 | } 36 | 37 | function basic_ui_intro() { 38 | echo '' . sprintf( __( 'To use the Instapaper API, you need to get manually approved. Apply here, then wait for a reply email.', 'keyring' ), 'http://www.instapaper.com/main/request_oauth_consumer_token' ) . '
'; 39 | echo '' . __( "Once you get approved, you'll get an email back with your details. Copy the OAuth consumer key value into the API Key field, and the OAuth consumer secret value into the API Secret field and click save (you don't need an App ID value for Instapaper).", 'keyring' ) . '
'; 40 | } 41 | 42 | /** 43 | * Mostly duplicated from HTTP Basic 44 | */ 45 | function request_ui() { 46 | // Common Header 47 | echo '' . sprintf( __( 'Enter your username (or email address) and password for accessing %s:', 'keyring' ), $this->get_label() ) . '
'; 87 | echo ''; 104 | echo '' . sprintf( __( "To connect to LinkedIn, you'll first need to create an app. A lot of the details are required, but they're not actually important to the operation of your app, since Keyring will override any important settings.", 'keyring' ), 'https://www.linkedin.com/secure/developer?newapp=' ) . '
'; 40 | echo '' . __( "Once you've created your app, go down to the OAuth Keys section and copy the API Key value into the API Key field below, and the Secret Key value into the API Secret field and click save (you don't need an App ID value for LinkedIn).", 'keyring' ) . '
'; 41 | } 42 | 43 | function parse_response( $response ) { 44 | if ( 'set_token( 58 | new Keyring_Access_Token( 59 | $this->get_name(), 60 | new OAuthToken( 61 | $token['oauth_token'], 62 | $token['oauth_token_secret'] 63 | ) 64 | ) 65 | ); 66 | 67 | // Get user profile information 68 | $response = $this->request( "https://api.linkedin.com/v1/people/~:(id,formatted-name,picture-url)?format=json" ); 69 | if ( Keyring_Util::is_error( $response ) ) { 70 | $meta = array(); 71 | } else { 72 | $this->person = $response; 73 | $meta = array( 74 | 'user_id' => $this->person->id, 75 | 'name' => $this->person->formattedName, 76 | 'picture' => $this->person->pictureUrl, 77 | ); 78 | } 79 | 80 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 81 | } 82 | 83 | function get_display( Keyring_Access_Token $token ) { 84 | return $token->get_meta( 'name' ); 85 | } 86 | 87 | function test_connection() { 88 | $res = $this->request( "https://api.linkedin.com/v1/people/~:(id,formatted-name)?format=json" ); 89 | if ( !Keyring_Util::is_error( $res ) ) 90 | return true; 91 | 92 | return $res; 93 | } 94 | } 95 | 96 | add_action( 'keyring_load_services', array( 'Keyring_Service_LinkedIn', 'init' ) ); 97 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/moves.php: -------------------------------------------------------------------------------- 1 | place_types = array( 17 | 'unknown' => __( 'Unknown', 'keyring' ), 18 | 'home' => __( 'Home', 'keyring' ), 19 | 'work' => __( 'Work', 'keyring' ), 20 | 'school' => __( 'School', 'keyring' ), 21 | 'user' => __( 'Manually Named', 'keyring' ), 22 | 'foursquare' => __( 'Selected from foursquare', 'keyring' ), 23 | ); 24 | 25 | $this->activity_types = array( 26 | 'wlk' => __( 'Walking', 'keyring' ), 27 | 'cyc' => __( 'Cycling', 'keyring' ), 28 | 'run' => __( 'Running', 'keyring' ), 29 | 'trp' => __( 'Transport', 'keyring' ), 30 | ); 31 | 32 | // Enable "basic" UI for entering key/secret 33 | if ( ! KEYRING__HEADLESS_MODE ) { 34 | add_action( 'keyring_moves_manage_ui', array( $this, 'basic_ui' ) ); 35 | add_filter( 'keyring_moves_basic_ui_intro', array( $this, 'basic_ui_intro' ) ); 36 | } 37 | 38 | $this->set_endpoint( 'authorize', 'https://api.moves-app.com/oauth/v1/authorize', 'GET' ); 39 | $this->set_endpoint( 'access_token', 'https://api.moves-app.com/oauth/v1/access_token', 'POST' ); 40 | $this->set_endpoint( 'verify_token', 'https://api.moves-app.com/oauth/v1/tokeninfo', 'GET' ); 41 | $this->set_endpoint( 'profile', 'https://api.moves-app.com/api/1.1/user/profile', 'GET' ); 42 | 43 | $creds = $this->get_credentials(); 44 | $this->app_id = $creds['app_id']; 45 | $this->key = $creds['key']; 46 | $this->secret = $creds['secret']; 47 | 48 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 49 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 50 | 51 | // Moves requires an exact match on Redirect URI, which means we can't send any nonces 52 | $this->callback_url = remove_query_arg( array( 'nonce', 'kr_nonce' ), $this->callback_url ); 53 | add_action( 'pre_keyring_moves_verify', array( $this, 'redirect_incoming_verify' ) ); 54 | 55 | $this->authorization_header = 'Bearer'; 56 | $this->authorization_parameter = false; 57 | 58 | add_filter( 'keyring_moves_request_token_params', array( $this, 'request_token_params' ) ); 59 | } 60 | 61 | function basic_ui_intro() { 62 | echo '' . sprintf( __( 'Head over and create a new application on Moves-app which you\'ll use to connect.', 'keyring' ), 'https://dev.moves-app.com/apps/new' ) . '
'; 63 | echo '' . sprintf( __( "Once it's created, click the Development tab. Your App ID and API Key are both shown on that page as Client ID. Enter your Client secret in the API Secret box. On that tab there is also a Redirect URI box, which you should set to %s
.", 'keyring' ), Keyring_Util::admin_url( self::NAME, array( 'action' => 'verify' ) ) ) . '
' . sprintf( __( 'You will need to create a Developer account, and set up a Nest Product (that is what they call apps). The most important setting is the Redirect URI, which should be set to %2$s
. Make sure you select appropriate permissions as well.', 'keyring' ), 'https://developers.nest.com/products/new', Keyring_Util::admin_url( $this->get_name(), array( 'action' => 'verify' ) ) ) . '
' . __( "Once you've set that up, copy your Product ID value into the API Key field, and the Product Secret value into the API Secret field and click save (you don't need an App ID value for Nest).", 'keyring' ) . '
'; 63 | } 64 | 65 | function build_token_meta( $token ) { 66 | $this->set_token( 67 | new Keyring_Access_Token( 68 | $this->get_name(), 69 | $token['access_token'], 70 | array() 71 | ) 72 | ); 73 | $response = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 74 | if ( Keyring_Util::is_error( $response ) ) { 75 | $meta = array(); 76 | } else { 77 | if ( ! empty( $response->structures ) ) { 78 | $label = array(); 79 | foreach ( $response->structures as $id => $structure ) { 80 | $label[] = $structure->name; 81 | } 82 | $meta = array( 83 | 'name' => implode( ' / ', $label ), 84 | ); 85 | } 86 | } 87 | 88 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 89 | } 90 | 91 | function get_display( Keyring_Access_Token $token ) { 92 | return $token->get_meta( 'name' ); 93 | } 94 | 95 | function test_connection() { 96 | $response = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 97 | if ( ! Keyring_Util::is_error( $response ) ) { 98 | return true; 99 | } 100 | 101 | return $response; 102 | } 103 | } 104 | 105 | add_action( 'keyring_load_services', array( 'Keyring_Service_Nest', 'init' ) ); 106 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/pinterest.php: -------------------------------------------------------------------------------- 1 | set_endpoint( 'authorize', 'https://api.pinterest.com/oauth/', 'GET' ); 23 | $this->set_endpoint( 'access_token', 'https://api.pinterest.com/v1/oauth/token', 'POST' ); 24 | $this->set_endpoint( 'self', 'https://api.pinterest.com/v1/me/?fields=first_name,last_name,username,image', 'GET' ); // undocumented, but required to get the `image` in a single request 25 | 26 | $creds = $this->get_credentials(); 27 | $this->app_id = $creds['app_id']; 28 | $this->key = $creds['key']; 29 | $this->secret = $creds['secret']; 30 | 31 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 32 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 33 | 34 | // Send auth token in query string 35 | $this->authorization_header = false; 36 | $this->authorization_parameter = 'access_token'; 37 | 38 | add_filter( 'keyring_pinterest_request_token_params', array( $this, 'request_token_params' ) ); 39 | 40 | // Handle Pinterest's annoying limitation of not allowing us to redirect to a dynamic URL 41 | add_action( 'pre_keyring_pinterest_verify', array( $this, 'redirect_incoming_verify' ) ); 42 | 43 | // Strip nonces, since you can't save them in your app config, and Pinterest is strict about redirect_uris 44 | // Can also only return you to an HTTPS address 45 | $this->callback_url = remove_query_arg( array( 'nonce', 'kr_nonce' ), $this->callback_url ); 46 | } 47 | 48 | function request_token_params( $params ) { 49 | $params['scope'] = apply_filters( 'keyring_pinterest_scope', self::SCOPE ); 50 | return $params; 51 | } 52 | 53 | function redirect_incoming_verify( $request ) { 54 | if ( !isset( $request['kr_nonce'] ) ) { 55 | // First request, from Pinterest. Nonce it and move on. 56 | $kr_nonce = wp_create_nonce( 'keyring-verify' ); 57 | $nonce = wp_create_nonce( 'keyring-verify-' . $this->get_name() ); 58 | wp_safe_redirect( 59 | Keyring_Util::admin_url( 60 | $this->get_name(), 61 | array( 62 | 'action' => 'verify', 63 | 'kr_nonce' => $kr_nonce, 64 | 'nonce' => $nonce, 65 | 'state' => $request['state'], 66 | 'code' => $request['code'], // Auth code from successful response (maybe) 67 | ) 68 | ) 69 | ); 70 | exit; 71 | } 72 | } 73 | 74 | function basic_ui_intro() { 75 | echo '' . sprintf( __( 'To get started, register an API client on Pinterest. The most important setting is the OAuth redirect_uri, which should be set to %2$s
. You can set the other values to whatever you like.', 'keyring' ), 'https://developers.pinterest.com/apps/', Keyring_Util::admin_url( 'pinterest', array( 'action' => 'verify' ) ) ) . '
' . __( "Once you're approved, copy your CLIENT ID value into the API Key field, and the CLIENT SECRET value into the API Secret field and click save (you don't need an App ID value for Pinterest).", 'keyring' ) . '
'; 77 | } 78 | 79 | function build_token_meta( $token ) { 80 | $this->set_token( 81 | new Keyring_Access_Token( 82 | $this->get_name(), 83 | $token['access_token'], 84 | array() 85 | ) 86 | ); 87 | $response = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 88 | if ( Keyring_Util::is_error( $response ) ) { 89 | $meta = array(); 90 | } else { 91 | $meta = array( 92 | 'user_id' => $response->data->id, 93 | 'username' => $response->data->username, 94 | 'name' => $response->data->first_name . ' ' . $response->data->last_name, 95 | 'picture' => $response->data->image->{'60x60'}->url // Pinterest violate their own docs that this should be 'small' 96 | ); 97 | } 98 | 99 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 100 | } 101 | 102 | function get_display( Keyring_Access_Token $token ) { 103 | return $token->get_meta( 'name' ); 104 | } 105 | 106 | function test_connection() { 107 | $response = $this->request( $this->self_url, array( 'method' => $this->self_method ) ); 108 | if ( ! Keyring_Util::is_error( $response ) ) { 109 | return true; 110 | } 111 | 112 | return $response; 113 | } 114 | } 115 | 116 | add_action( 'keyring_load_services', array( 'Keyring_Service_Pinterest', 'init' ) ); 117 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/runkeeper.php: -------------------------------------------------------------------------------- 1 | set_endpoint( 'authorize', 'https://runkeeper.com/apps/authorize', 'GET' ); 22 | $this->set_endpoint( 'access_token', 'https://runkeeper.com/apps/token', 'POST' ); 23 | $this->set_endpoint( 'deauthorize', 'https://runkeeper.com/apps/de-authorize', 'POST' ); 24 | $this->set_endpoint( 'user', 'https://api.runkeeper.com/user', 'GET' ); 25 | $this->set_endpoint( 'profile', 'https://api.runkeeper.com/profile', 'GET' ); 26 | 27 | $creds = $this->get_credentials(); 28 | $this->app_id = $creds['app_id']; 29 | $this->key = $creds['key']; 30 | $this->secret = $creds['secret']; 31 | 32 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 33 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 34 | 35 | $this->authorization_header = 'Bearer'; 36 | $this->authorization_parameter = false; 37 | } 38 | 39 | function basic_ui_intro() { 40 | echo '' . sprintf( __( 'You\'ll need to register a new application on RunKeeper so that you can connect. Be sure to check the Read Health Information option under Permissions Requests (and explain why you want to read that data). You will also be required to set an Estimated Date of Publication.', 'keyring' ), 'http://runkeeper.com/partner/applications/register' ) . '
'; 41 | echo '' . __( "Once you've registered your application, click the Application Keys and URLs next to it, and copy the Client ID into the API Key field below, and the Client Secret value into API Secret.", 'keyring' ) . '
'; 42 | } 43 | 44 | function build_token_meta( $token ) { 45 | $this->set_token( 46 | new Keyring_Access_Token( 47 | $this->get_name(), 48 | $token['access_token'], 49 | array() 50 | ) 51 | ); 52 | $response = $this->request( $this->user_url, array( 'method' => $this->user_method ) ); 53 | if ( Keyring_Util::is_error( $response ) ) { 54 | $meta = array(); 55 | } else { 56 | // Only useful thing in that request is userID 57 | $meta = array( 'user_id' => (int) $response->userID ); 58 | 59 | // Now get the rest of their profile 60 | $profile = $this->request( $this->profile_url, array( 'method' => $this->profile_method ) ); 61 | if ( !Keyring_Util::is_error( $profile ) ) { 62 | $meta['username'] = substr( $profile->profile, strrpos( $profile->profile, '/' ) + 1 ); 63 | $meta['name'] = $profile->name; 64 | $meta['picture'] = $profile->large_picture; 65 | } 66 | 67 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $profile, $this ); 68 | } 69 | return array(); 70 | } 71 | 72 | function get_display( Keyring_Access_Token $token ) { 73 | return $token->get_meta( 'name' );; 74 | } 75 | 76 | function test_connection() { 77 | $response = $this->request( $this->user_url, array( 'method' => $this->user_method ) ); 78 | if ( ! Keyring_Util::is_error( $response ) ) { 79 | return true; 80 | } 81 | 82 | return $response; 83 | } 84 | } 85 | 86 | add_action( 'keyring_load_services', array( 'Keyring_Service_RunKeeper', 'init' ) ); 87 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/tripit.php: -------------------------------------------------------------------------------- 1 | authorization_header = true; 21 | $this->authorization_realm = false; 22 | 23 | $this->set_endpoint( 'request_token', 'https://api.tripit.com/oauth/request_token', 'POST' ); 24 | $this->set_endpoint( 'authorize', 'https://www.tripit.com/oauth/authorize', 'GET' ); 25 | $this->set_endpoint( 'access_token', 'https://api.tripit.com/oauth/access_token', 'POST' ); 26 | $this->set_endpoint( 'verify', 'https://api.tripit.com/v1/get/profile/id/me', 'GET' ); 27 | 28 | $creds = $this->get_credentials(); 29 | $this->app_id = $creds['app_id']; 30 | $this->key = $creds['key']; 31 | $this->secret = $creds['secret']; 32 | 33 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 34 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 35 | 36 | $this->requires_token( true ); 37 | } 38 | 39 | function basic_ui_intro() { 40 | echo '' . sprintf( __( 'If you haven\'t created an app on TripIt yet, create one now. Make sure you select \'Full API Application\' and \'Web application or widget\'; other than that the settings are all up to you.', 'keyring' ), 'https://www.tripit.com/developer/create' ) . '
'; 41 | echo '' . __( "Once you've created your app, you will see a yellow box at the top of the page, where you can get your API Key and API Secret, to enter below (you don't need an App ID value for TripIt).", 'keyring' ) . '
'; 42 | } 43 | 44 | function parse_response( $response ) { 45 | return json_decode( $response ); 46 | } 47 | 48 | function build_token_meta( $token ) { 49 | // Set the token so that we can make requests using it 50 | $this->set_token( 51 | new Keyring_Access_Token( 52 | $this->get_name(), 53 | new OAuthToken( 54 | $token['oauth_token'], 55 | $token['oauth_token_secret'] 56 | ) 57 | ) 58 | ); 59 | 60 | $response = $this->request( $this->verify_url, array( 'method' => $this->verify_method ) ); 61 | if ( Keyring_Util::is_error( $response ) ) { 62 | $meta = array(); 63 | } else { 64 | $meta = array( 65 | 'user_id' => $response->Profile->{'@attributes'}->ref, 66 | 'username' => $response->Profile->screen_name, 67 | 'name' => $response->Profile->public_display_name, 68 | 'picture' => $response->Profile->photo_url, 69 | '_classname' => get_called_class(), 70 | ); 71 | } 72 | 73 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 74 | } 75 | 76 | function get_display( Keyring_Access_Token $token ) { 77 | return $token->get_meta( 'name' ); 78 | } 79 | 80 | function request( $url, array $params = array() ) { 81 | $url = add_query_arg( array( 'format' => 'json' ), $url ); 82 | return parent::request( $url, $params ); 83 | } 84 | 85 | function test_connection() { 86 | $response = $this->request( $this->verify_url, array( 'method' => $this->verify_method ) ); 87 | if ( !Keyring_Util::is_error( $response ) ) 88 | return true; 89 | 90 | return $response; 91 | } 92 | } 93 | 94 | add_action( 'keyring_load_services', array( 'Keyring_Service_TripIt', 'init' ) ); 95 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/tumblr.php: -------------------------------------------------------------------------------- 1 | set_endpoint( 'request_token', 'http://www.tumblr.com/oauth/request_token', 'POST' ); 21 | $this->set_endpoint( 'authorize', 'http://www.tumblr.com/oauth/authorize', 'GET' ); 22 | $this->set_endpoint( 'access_token', 'http://www.tumblr.com/oauth/access_token', 'POST' ); 23 | 24 | $creds = $this->get_credentials(); 25 | $this->app_id = $creds['app_id']; 26 | $this->key = $creds['key']; 27 | $this->secret = $creds['secret']; 28 | 29 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 30 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 31 | 32 | $this->authorization_header = true; // Send OAuth token in the header, not querystring 33 | $this->authorization_realm = 'tumblr.com'; 34 | } 35 | 36 | function basic_ui_intro() { 37 | echo '' . sprintf( __( 'To get started, register an application with Tumblr. The Default callback URL should be set to %2$s
, and you can enter whatever you like in the other fields.', 'keyring' ), 'http://www.tumblr.com/oauth/register', Keyring_Util::admin_url( 'tumblr', array( 'action' => 'verify' ) ) ) . '
' . __( "Once you've created your app, copy the OAuth Consumer Key into the API Key field below. Click the Show secret key link, and then copy the Secret Key value into the API Secret field below. You don't need an App ID value for Tumblr.", 'keyring' ) . '
'; 39 | } 40 | 41 | function parse_response( $response ) { 42 | return json_decode( $response ); 43 | } 44 | 45 | function build_token_meta( $token ) { 46 | // Set the token so that we can make requests using it 47 | $this->set_token( 48 | new Keyring_Access_Token( 49 | 'tumblr', 50 | new OAuthToken( 51 | $token['oauth_token'], 52 | $token['oauth_token_secret'] 53 | ) 54 | ) 55 | ); 56 | 57 | $response = $this->request( 'http://api.tumblr.com/v2/user/info', array( 'method' => 'POST' ) ); 58 | 59 | if ( Keyring_Util::is_error( $response ) ) { 60 | $meta = array(); 61 | } else { 62 | $this->person = $response->response->user; 63 | $meta = array( 64 | 'name' => $this->person->name, 65 | ); 66 | } 67 | 68 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 69 | } 70 | 71 | function get_display( Keyring_Access_Token $token ) { 72 | return $token->get_meta( 'name' ); 73 | } 74 | 75 | function test_connection() { 76 | $res = $this->request( 'http://api.tumblr.com/v2/user/info', array( 'method' => 'POST' ) ); 77 | if ( !Keyring_Util::is_error( $res ) ) 78 | return true; 79 | 80 | return $res; 81 | } 82 | } 83 | 84 | add_action( 'keyring_load_services', array( 'Keyring_Service_Tumblr', 'init' ) ); 85 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/twitter.php: -------------------------------------------------------------------------------- 1 | authorization_header = true; 21 | $this->authorization_realm = "twitter.com"; 22 | 23 | $this->set_endpoint( 'request_token', 'https://twitter.com/oauth/request_token', 'POST' ); 24 | $this->set_endpoint( 'authorize', 'https://twitter.com/oauth/authorize', 'GET' ); 25 | $this->set_endpoint( 'access_token', 'https://twitter.com/oauth/access_token', 'POST' ); 26 | $this->set_endpoint( 'verify', 'https://api.twitter.com/1.1/account/verify_credentials.json', 'GET' ); 27 | 28 | $creds = $this->get_credentials(); 29 | $this->app_id = $creds['app_id']; 30 | $this->key = $creds['key']; 31 | $this->secret = $creds['secret']; 32 | 33 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 34 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 35 | 36 | $this->requires_token( true ); 37 | } 38 | 39 | function basic_ui_intro() { 40 | echo '' . sprintf( __( 'If you haven\'t already, you\'ll need to create an app on Twitter (log in using your normal Twitter account). Make sure you enter something for the Callback URL, even though Keyring will override it with the correct value. Just enter your homepage, e.g. %2$s
.', 'keyring' ), 'https://apps.twitter.com/app/new', get_bloginfo( 'url' ) ) . '
' . __( "Once you've created an app, copy and paste your Consumer key and Consumer secret (from under the OAuth settings section of your app's details) into the boxes below. You don't need an App ID for Twitter.", 'keyring' ) . '
'; 42 | } 43 | 44 | function parse_response( $response ) { 45 | return json_decode( $response ); 46 | } 47 | 48 | function build_token_meta( $token ) { 49 | // Set the token so that we can make requests using it 50 | $this->set_token( 51 | new Keyring_Access_Token( 52 | $this->get_name(), 53 | new OAuthToken( 54 | $token['oauth_token'], 55 | $token['oauth_token_secret'] 56 | ) 57 | ) 58 | ); 59 | 60 | $response = $this->request( $this->verify_url, array( 'method' => $this->verify_method ) ); 61 | if ( Keyring_Util::is_error( $response ) ) { 62 | $meta = array(); 63 | } else { 64 | $meta = array( 65 | 'user_id' => $token['user_id'], 66 | 'username' => $token['screen_name'], 67 | 'name' => $response->name, 68 | 'picture' => str_replace( '_normal.', '.', $response->profile_image_url ), 69 | '_classname' => get_called_class(), 70 | ); 71 | } 72 | 73 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 74 | } 75 | 76 | function get_display( Keyring_Access_Token $token ) { 77 | return '@' . $token->get_meta( 'username' ); 78 | } 79 | 80 | function test_connection() { 81 | $res = $this->request( 'https://api.twitter.com/1.1/account/verify_credentials.json' ); 82 | if ( !Keyring_Util::is_error( $res ) ) 83 | return true; 84 | 85 | // Twitter may return a rate limiting error if the user accesses the sharing settings or post 86 | // page frequently. If so, ignore that error, things are likely aaaa-okay... 87 | $keyring_error_message = $res->get_error_message(); 88 | if ( is_array( $keyring_error_message ) && isset( $keyring_error_message['response']['code'] ) ) { 89 | if ( 429 == absint( $keyring_error_message['response']['code'] ) ) { 90 | return true; 91 | } 92 | } 93 | 94 | return $res; 95 | } 96 | } 97 | 98 | add_action( 'keyring_load_services', array( 'Keyring_Service_Twitter', 'init' ) ); 99 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/services/extended/yahoo.php: -------------------------------------------------------------------------------- 1 | set_endpoint( 'request_token', 'https://api.login.yahoo.com/oauth/v2/get_request_token', 'GET' ); 21 | $this->set_endpoint( 'authorize', 'https://api.login.yahoo.com/oauth/v2/request_auth', 'GET' ); 22 | $this->set_endpoint( 'access_token', 'https://api.login.yahoo.com/oauth/v2/get_token', 'POST' ); 23 | 24 | $creds = $this->get_credentials(); 25 | $this->app_id = $creds['app_id']; 26 | $this->key = $creds['key']; 27 | $this->secret = $creds['secret']; 28 | 29 | $this->consumer = new OAuthConsumer( $this->key, $this->secret, $this->callback_url ); 30 | $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1; 31 | } 32 | 33 | function basic_ui_intro() { 34 | echo '' . sprintf( __( 'To connect to Yahoo!, you need to Create a new project. Make sure you set the Access Scope to This app requires access to private user data. When you select that, you will be asked for an Application Domain, which should probably be set to http://%2$s
. Which APIs you request access for will depend on how Keyring will be used on this site. Common ones will be Contacts, Social Directory, Status, and Updates.', 'keyring' ), 'https://developer.apps.yahoo.com/dashboard/createKey.html', $_SERVER['HTTP_HOST'] ) . '
' . __( "Once you've created your project, copy and paste your Consumer key and Consumer secret (from under the Authentication Information: OAuth section of your app's details) into the boxes below. You don't need an App ID for Yahoo!.", 'keyring' ) . '
'; 36 | } 37 | 38 | function parse_response( $response ) { 39 | return json_decode( $response ); 40 | } 41 | 42 | function build_token_meta( $token ) { 43 | $expires = isset( $token['oauth_expires_in'] ) ? gmdate( 'Y-m-d H:i:s', time() + $token['oauth_expires_in'] ) : 0; 44 | 45 | $this->set_token( 46 | new Keyring_Access_Token( 47 | 'yahoo', 48 | new OAuthToken( 49 | $token['oauth_token'], 50 | $token['oauth_token_secret'] 51 | ) 52 | ) 53 | ); 54 | 55 | // Get user profile information 56 | $response = $this->request( "http://social.yahooapis.com/v1/user/{$token['xoauth_yahoo_guid']}/profile?format=json" ); 57 | 58 | if ( Keyring_Util::is_error( $response ) ) { 59 | $meta = array(); 60 | } else { 61 | $this->person = $response->profile; 62 | $meta = array( 63 | 'user_id' => $token['xoauth_yahoo_guid'], 64 | 'name' => $this->person->nickname, 65 | 'picture' => $this->person->image->imageUrl, 66 | ); 67 | } 68 | 69 | return apply_filters( 'keyring_access_token_meta', $meta, $this->get_name(), $token, $response, $this ); 70 | } 71 | 72 | function get_display( Keyring_Access_Token$token ) { 73 | return $token->get_meta( 'name' ); 74 | } 75 | 76 | function test_connection() { 77 | $this->maybe_refresh_token(); 78 | 79 | $guid = $this->token->get_meta( 'external_id' ); 80 | 81 | $res = $this->request( 'http://social.yahooapis.com/v1/user/' . $guid . '/profile?format=json' ); 82 | if ( !Keyring_Util::is_error( $res ) ) 83 | return true; 84 | 85 | return $res; 86 | } 87 | 88 | function maybe_refresh_token() { 89 | global $wpdb; 90 | 91 | if ( empty( $this->token->token ) || empty( $this->token->token->tokenExpires ) ) 92 | return; 93 | 94 | if ( $this->token->token->tokenExpires && $this->token->token->tokenExpires < time() ) { 95 | $api_url = 'https://api.login.yahoo.com/oauth/v2/get_token'; 96 | $api_url .= '?oauth_session_handle=' . $this->token->token->sessionHandle; 97 | 98 | $refresh = $this->request( $api_url, array( 99 | 'method' => 'GET', 100 | 'raw_response' => true, 101 | ) ); 102 | 103 | if ( !Keyring_Util::is_error( $refresh ) ) { 104 | $token = $this->parse_access_token( $refresh ); 105 | 106 | // Fake request token 107 | global $keyring_request_token; 108 | $keyring_request_token = new Keyring_Request_Token( 109 | $this->get_name(), 110 | array() 111 | ); 112 | 113 | // Build (real) access token 114 | $access_token = new Keyring_Access_Token( 115 | $this->get_name(), 116 | new OAuthToken( 117 | $token['oauth_token'], 118 | $token['oauth_token_secret'] 119 | ), 120 | $this->build_token_meta( $token ), 121 | $this->token->unique_id 122 | ); 123 | 124 | // Store the updated access token 125 | $access_token = apply_filters( 'keyring_access_token', $access_token, $token ); 126 | $id = $this->store->update( $access_token ); 127 | 128 | // And switch to using it 129 | $this->set_token( $access_token ); 130 | } 131 | } 132 | } 133 | } 134 | 135 | add_action( 'keyring_load_services', array( 'Keyring_Service_Yahoo', 'init' ) ); 136 | -------------------------------------------------------------------------------- /publishiza/keyring/includes/stores/singlestore.php: -------------------------------------------------------------------------------- 1 | __( 'Keyring Request Token', 'keyring' ), 19 | 'description' => __( 'Token or authentication details stored by Keyring. Request tokens are used during the authorization flow.', 'keyring' ), 20 | 'public' => false, 21 | ) ); 22 | 23 | register_post_type( 'kr_access_token', array( 24 | 'label' => __( 'Keyring Access Token', 'keyring' ), 25 | 'description' => __( 'Token or authentication details stored by Keyring. Access tokens are used to make secure requests.', 'keyring' ), 26 | 'public' => false, 27 | ) ); 28 | 29 | $instance = new Keyring_SingleStore; 30 | } 31 | 32 | return $instance; 33 | } 34 | 35 | function insert( $token ) { 36 | // Avoid duplicates by checking to see if this exists already 37 | $found = get_posts( array( 38 | 'posts_per_page' => 1, 39 | 'post_type' => 'kr_' . $token->type() . '_token', 40 | 'meta_key' => 'service', 41 | 'meta_value' => $token->get_name(), 42 | 'author' => get_current_user_id(), 43 | 's' => serialize( $token->token ), // Search the post content for this token 44 | 'exact' => true, // Require exact content match 45 | 'sentence' => true, // Require to search by phrase, otherwise string is split by regex 46 | ) ); 47 | 48 | if ( $found ) { 49 | $token->unique_id = $found[0]->ID; 50 | return $this->update( $token ); 51 | } 52 | 53 | $post = array( 54 | 'post_type' => 'kr_' . $token->type() . '_token', 55 | 'post_status' => 'publish', 56 | 'post_content' => serialize( $token->token ), 57 | ); 58 | $id = wp_insert_post( add_magic_quotes( $post ) ); 59 | if ( $id ) { 60 | // Always record what service this token is for 61 | update_post_meta( $id, 'service', $token->get_name() ); 62 | 63 | // Optionally include any meta related to this token 64 | foreach ( (array) $token->get_meta( false, true ) as $key => $val ) { 65 | update_post_meta( $id, $key, $val ); 66 | } 67 | return $id; 68 | } 69 | return false; 70 | } 71 | 72 | function update( $token ) { 73 | if ( !$token->unique_id ) 74 | return false; 75 | 76 | $id = $token->unique_id; 77 | $post = get_post( $id ); 78 | if ( !$post ) 79 | return false; 80 | 81 | $post->post_content = serialize( $token->token ); 82 | wp_update_post( $post ); 83 | 84 | foreach ( $token->get_meta( false, true ) as $key => $val ) { 85 | update_post_meta( $id, $key, $val ); 86 | } 87 | 88 | return $id; 89 | } 90 | 91 | function delete( $args = array() ) { 92 | if ( !$args['id'] ) 93 | return false; 94 | return wp_delete_post( $args['id'] ); 95 | } 96 | 97 | function get_tokens( $args = array() ) { 98 | $defaults = array( 99 | 'type' => 'access', 100 | 'service' => false, 101 | 'user_id' => get_current_user_id(), 102 | 'blog_id' => get_current_blog_id(), 103 | ); 104 | $args = wp_parse_args( $args, $defaults ); 105 | 106 | $query = array( 107 | 'numberposts' => -1, // all 108 | 'post_type' => 'kr_' . $args['type'] . '_token', 109 | 'author' => $args['user_id'], 110 | ); 111 | 112 | // Get tokens for a specific service 113 | if ( $args['service'] ) { 114 | $query['meta_key'] = 'service'; 115 | $query['meta_value'] = $args['service']; 116 | } 117 | 118 | $token_type = 'request' == $args['type'] ? 'Keyring_Request_Token' : 'Keyring_Access_Token'; 119 | $tokens = array(); 120 | $posts = get_posts( $query ); 121 | if ( count( $posts ) ) { 122 | foreach ( $posts as $post ) { 123 | $meta = get_post_meta( $post->ID ); 124 | foreach ( $meta as $mid => $met ) { 125 | $meta[$mid] = $met[0]; 126 | } 127 | 128 | $tokens[] = new $token_type( 129 | get_post_meta( 130 | $post->ID, 131 | 'service', 132 | true 133 | ), 134 | unserialize( $post->post_content ), 135 | $meta, 136 | $post->ID 137 | ); 138 | } 139 | } 140 | 141 | return $tokens; 142 | } 143 | 144 | function get_token( $args = array() ) { 145 | $defaults = array( 146 | 'id' => false, 147 | 'type' => 'access', 148 | 'service' => false, 149 | 'user_id' => get_current_user_id(), 150 | 'blog_id' => get_current_blog_id(), 151 | ); 152 | $args = wp_parse_args( $args, $defaults ); 153 | 154 | if ( !$args['id'] && !$args['service'] ) 155 | return false; 156 | 157 | $post = get_post( $args['id'] ); 158 | if ( $post ) { 159 | $meta = get_post_meta( $post->ID ); 160 | foreach ( $meta as $mid => $met ) { 161 | $meta[$mid] = $met[0]; 162 | } 163 | 164 | $token_type = 'kr_request_token' == $post->post_type ? 'Keyring_Request_Token' : 'Keyring_Access_Token'; 165 | return new $token_type( 166 | get_post_meta( 167 | $post->ID, 168 | 'service', 169 | true 170 | ), 171 | unserialize( $post->post_content ), 172 | $meta, 173 | $post->ID 174 | ); 175 | } 176 | return false; 177 | } 178 | 179 | function count( $args = array() ) { 180 | return count( $this->get_tokens( $args ) ); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /publishiza/keyring/keyring.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | 12 | // Define this in your wp-config (and set to true) to enable debugging 13 | defined( 'KEYRING__DEBUG_MODE' ) or define( 'KEYRING__DEBUG_MODE', false ); 14 | 15 | // The name of a class which extends Keyring_Store to handle storage/manipulation of tokens. 16 | // Optionally define this in your wp-config.php or some other global config file. 17 | defined( 'KEYRING__TOKEN_STORE' ) or define( 'KEYRING__TOKEN_STORE', 'Keyring_SingleStore' ); 18 | 19 | // Keyring can be run in "headless" mode, which just avoids creating any UI, and leaves 20 | // that up to you. Defaults to off (provides its own basic UI). 21 | defined( 'KEYRING__HEADLESS_MODE' ) or define( 'KEYRING__HEADLESS_MODE', false ); 22 | 23 | // Debug/messaging levels. Don't mess with these 24 | define( 'KEYRING__DEBUG_NOTICE', 1 ); 25 | define( 'KEYRING__DEBUG_WARN', 2 ); 26 | define( 'KEYRING__DEBUG_ERROR', 3 ); 27 | 28 | // Indicates Keyring is installed/active so that other plugins can detect it 29 | define( 'KEYRING__VERSION', '1.7.1' ); 30 | 31 | /** 32 | * Core Keyring class that handles UI and the general flow of requesting access tokens etc 33 | * to manage access to remote services. 34 | * 35 | * @package Keyring 36 | */ 37 | class Keyring { 38 | protected $registered_services = array(); 39 | protected $store = false; 40 | protected $errors = array(); 41 | protected $messages = array(); 42 | protected $token_store = ''; 43 | var $admin_page = 'keyring'; 44 | 45 | function __construct() { 46 | if ( ! KEYRING__HEADLESS_MODE ) { 47 | require_once dirname( __FILE__ ) . '/admin-ui.php'; 48 | Keyring_Admin_UI::init(); 49 | 50 | add_filter( 'keyring_admin_url', function( $url, $params ) { 51 | $url = admin_url( 'tools.php?page=' . Keyring::init()->admin_page ); 52 | return add_query_arg( $params, $url ); 53 | }, 10, 2 ); 54 | } 55 | 56 | // This is used internally to create URLs, and also to know when to 57 | // attach handers. @see admin_url() and request_handlers() 58 | $this->admin_page = apply_filters( 'keyring_admin_page', 'keyring' ); 59 | } 60 | 61 | static function &init( $force_load = false ) { 62 | static $instance = false; 63 | 64 | if ( !$instance ) { 65 | if ( ! KEYRING__HEADLESS_MODE ) 66 | load_plugin_textdomain( 'keyring', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); 67 | $instance = new Keyring; 68 | 69 | // Keyring is being loaded 'late', so we need to do some extra set-up 70 | if ( did_action( 'init' ) || $force_load ) { 71 | $instance->plugins_loaded(); 72 | do_action( 'keyring_load_services' ); 73 | } 74 | } else { 75 | if ( $force_load ) { 76 | $instance->plugins_loaded(); 77 | do_action( 'keyring_load_services' ); 78 | } 79 | } 80 | 81 | return $instance; 82 | } 83 | 84 | static function plugins_loaded() { 85 | // Load stores early so we can confirm they're loaded correctly 86 | require_once dirname( __FILE__ ) . '/store.php'; 87 | do_action( 'keyring_load_token_stores' ); 88 | $keyring = Keyring::init(); 89 | $keyring->token_store = apply_filters( 'keyring_token_store', defined( 'KEYRING__TOKEN_STORE' ) ? KEYRING__TOKEN_STORE : false ); 90 | if ( !class_exists( $keyring->token_store ) || !in_array( 'Keyring_Store', class_parents( $keyring->token_store ) ) ) 91 | wp_die( sprintf( __( 'InvalidKEYRING__TOKEN_STORE
specified. Please make sure KEYRING__TOKEN_STORE
is set to a valid classname for handling token storage in %s
(or wp-config.php
)', 'keyring' ), __FILE__ ) );
92 |
93 | // Load base token and service definitions + core services
94 | require_once dirname( __FILE__ ) . '/token.php';
95 | require_once dirname( __FILE__ ) . '/service.php'; // Triggers a load of all core + extended service definitions
96 |
97 | // Initiate Keyring
98 | add_action( 'init', array( 'Keyring', 'init' ), 1 );
99 |
100 | // Load external Services (plugins etc should hook to this to define new ones/extensions)
101 | add_action( 'init', function() {
102 | do_action( 'keyring_load_services' );
103 | }, 2 );
104 |
105 | /**
106 | * And trigger request handlers, which plugins and extended Services use to handle UI,
107 | * redirects, errors etc.
108 | * @see ::request_handlers()
109 | */
110 | add_action( 'admin_init', array( 'Keyring', 'request_handlers' ), 100 );
111 | }
112 |
113 | /**
114 | * Core request handler which is the crux of everything. An action is called
115 | * here for almost everything Keyring does, so you can use it to intercept
116 | * almost everything. Based entirely on $_REQUEST[page|action|service]
117 | */
118 | static function request_handlers() {
119 | global $current_user;
120 |
121 | if ( defined( 'KEYRING__FORCE_USER' ) && KEYRING__FORCE_USER && in_array( $_REQUEST['action'], array( 'request', 'verify' ) ) ) {
122 | global $current_user;
123 | $real_user = $current_user->ID;
124 | wp_set_current_user( KEYRING__FORCE_USER );
125 | }
126 |
127 | if (
128 | !empty( $_REQUEST['action'] )
129 | &&
130 | in_array( $_REQUEST['action'], apply_filters( 'keyring_core_actions', array( 'request', 'verify', 'created', 'delete', 'manage' ) ) )
131 | &&
132 | !empty( $_REQUEST['service'] )
133 | &&
134 | in_array( $_REQUEST['service'], array_keys( Keyring::get_registered_services() ) )
135 | ) {
136 | // We have an action here to allow us to do things pre-authorization, just in case
137 | do_action( "pre_keyring_{$_REQUEST['service']}_{$_REQUEST['action']}", $_REQUEST );
138 |
139 | // Core nonce check required for everything. "keyring-ACTION" is the kr_nonce format
140 | if ( !isset( $_REQUEST['kr_nonce'] ) || !wp_verify_nonce( $_REQUEST['kr_nonce'], 'keyring-' . $_REQUEST['action'] ) ) {
141 | Keyring::error( __( 'Invalid/missing Keyring core nonce. All core actions require a valid nonce.', 'keyring' ) );
142 | exit;
143 | }
144 |
145 | Keyring_Util::debug( "keyring_{$_REQUEST['service']}_{$_REQUEST['action']}" );
146 | Keyring_Util::debug( $_GET );
147 | do_action( "keyring_{$_REQUEST['service']}_{$_REQUEST['action']}", $_REQUEST );
148 |
149 | if ( 'delete' == $_REQUEST['action'] )
150 | do_action( "keyring_connection_deleted", $_REQUEST['service'], $_REQUEST );
151 | }
152 |
153 | if ( defined( 'KEYRING__FORCE_USER' ) && KEYRING__FORCE_USER && in_array( $_REQUEST['action'], array( 'request', 'verify' ) ) )
154 | wp_set_current_user( $real_user );
155 | }
156 |
157 | static function register_service( Keyring_Service $service ) {
158 | if ( Keyring_Util::is_service( $service ) ) {
159 | Keyring::init()->registered_services[ $service->get_name() ] = $service;
160 | return true;
161 | }
162 | return false;
163 | }
164 |
165 | static function get_registered_services() {
166 | return Keyring::init()->registered_services;
167 | }
168 |
169 | static function get_service_by_name( $name ) {
170 | $keyring = Keyring::init();
171 | if ( !isset( $keyring->registered_services[ $name ] ) )
172 | return null;
173 |
174 | return $keyring->registered_services[ $name ];
175 | }
176 |
177 | static function get_token_store() {
178 | $keyring = Keyring::init();
179 |
180 | if ( !$keyring->store )
181 | $keyring->store = call_user_func( array( $keyring->token_store, 'init' ) );
182 |
183 | return $keyring->store;
184 | }
185 |
186 | static function message( $str ) {
187 | $keyring = Keyring::init();
188 | $keyring->messages[] = $str;
189 | }
190 |
191 | /**
192 | * Generic error handler/trigger.
193 | * @param String $str Informational message (user-readable)
194 | * @param array $info Additional information relating to the error.
195 | * @param boolean $die If we should immediately die (default) or continue
196 | */
197 | static function error( $str, $info = array(), $die = true ) {
198 | $keyring = Keyring::init();
199 | $keyring->errors[] = $str;
200 | do_action( 'keyring_error', $str, $info, isset( $this ) ? $this : null );
201 | if ( $die ) {
202 | wp_die( $str, __( 'Keyring Error', 'keyring' ) );
203 | exit;
204 | }
205 | }
206 |
207 | function has_errors() {
208 | return count( $this->errors );
209 | }
210 |
211 | function has_messages() {
212 | return count( $this->messages );
213 | }
214 |
215 | function get_messages() {
216 | return $this->messages;
217 | }
218 |
219 | function get_errors() {
220 | return $this->errors;
221 | }
222 | }
223 |
224 | class Keyring_Util {
225 | static function debug( $str, $level = KEYRING__DEBUG_NOTICE ) {
226 | if ( !KEYRING__DEBUG_MODE )
227 | return;
228 |
229 | if ( is_object( $str ) || is_array( $str ) )
230 | $str = print_r( $str, true );
231 |
232 | switch ( $level ) {
233 | case KEYRING__DEBUG_WARN :
234 | echo "' . $str . '
' ); 238 | exit; 239 | } 240 | 241 | error_log( "Keyring: $str" ); 242 | } 243 | 244 | static function is_service( $service ) { 245 | if ( is_object( $service ) && is_subclass_of( $service, 'Keyring_Service' ) ) 246 | return true; 247 | 248 | return false; 249 | } 250 | 251 | static function has_custom_ui( $service, $action ) { 252 | return has_action( "keyring_{$service}_{$action}_ui" ); 253 | } 254 | 255 | /** 256 | * Get a URL to the Keyring admin UI, works kinda like WP's admin_url() 257 | * 258 | * @param string $service Shortname of a specific service. 259 | * @return URL to Keyring admin UI (main listing, or specific service verify process) 260 | */ 261 | static function admin_url( $service = false, $params = array() ) { 262 | $url = admin_url(); 263 | 264 | if ( $service ) 265 | $params['service'] = $service; 266 | 267 | if ( count( $params ) ) 268 | $url = add_query_arg( $params, $url ); 269 | 270 | return apply_filters( 'keyring_admin_url', $url, $params ); 271 | } 272 | 273 | static function connect_to( $service, $for ) { 274 | Keyring_Util::debug( 'Connect to: ' . $service ); 275 | // Redirect into Keyring's auth handler if a valid service is provided 276 | $kr_nonce = wp_create_nonce( 'keyring-request' ); 277 | $request_nonce = wp_create_nonce( 'keyring-request-' . $service ); 278 | wp_safe_redirect( 279 | Keyring_Util::admin_url( 280 | $service, 281 | array( 282 | 'action' => 'request', 283 | 'kr_nonce' => $kr_nonce, 284 | 'nonce' => $request_nonce, 285 | 'for' => $for 286 | ) 287 | ) 288 | ); 289 | exit; 290 | } 291 | 292 | static function token_select_box( $tokens, $name, $create = false ) { 293 | ?>name = strtolower( $service ); // Name of the service this token is for 29 | $this->token = $token; 30 | $this->unique_id = $uniq; 31 | $this->meta = $meta; 32 | $this->get_service(); 33 | } 34 | 35 | function __toString() { 36 | return (string) $this->token; 37 | } 38 | 39 | function get_uniq_id() { 40 | if ( isset( $this->unique_id ) ) 41 | return $this->unique_id; 42 | return null; 43 | } 44 | 45 | function get_display() { 46 | if ( $service = $this->get_service() ) 47 | return $service->get_display( $this ); 48 | return $this->name; 49 | } 50 | 51 | function get_service() { 52 | if ( !$this->service ) { 53 | $class = $this->get_meta( '_classname', true ); 54 | if ( $class && class_exists( $class ) ) { 55 | $this->service = call_user_func( array( $class, 'init' ) ); 56 | } else { 57 | $this->service = Keyring::get_service_by_name( $this->get_name() ); 58 | } 59 | } 60 | return $this->service; 61 | } 62 | 63 | function get_name() { 64 | return $this->name; 65 | } 66 | 67 | /** 68 | * Get a specific piece of meta data for this token, or all meta as an array. 69 | * 70 | * @param mixed $name The key name for a specific meta item, or false for all. 71 | * @param bool $allow_hidden Allow access to "hidden" meta (prefixed with "_") 72 | * @return Mixed meta value, array of meta values, or null 73 | */ 74 | function get_meta( $name = false, $allow_hidden = false ) { 75 | $return = null; 76 | if ( $name ) { 77 | if ( '_' != substr( $name, 0, 1 ) || $allow_hidden ) { 78 | if ( isset( $this->meta[ $name ] ) ) { 79 | $return = $this->meta[ $name ]; 80 | } 81 | } 82 | } else { 83 | foreach ( (array) $this->meta as $key => $val ) { 84 | if ( '_' != substr( $key, 0, 1 ) || $allow_hidden ) { 85 | $return[ $key ] = $val; 86 | } 87 | } 88 | } 89 | 90 | return $return; 91 | } 92 | 93 | /** 94 | * Check if a token has expired, or will expire in the next $window seconds 95 | **/ 96 | function is_expired( $window = 0 ) { 97 | if ( !$expires = $this->get_meta( 'expires' ) ) 98 | return false; // No expires value, assume it's a permanent token 99 | 100 | if ( '0000-00-00 00:00:00' == $expires ) 101 | return false; // Doesn't expire 102 | 103 | if ( ( time() + $window ) > strtotime( $expires ) ) 104 | return true; // Token's expiry time has passed, or will pass before $window 105 | 106 | // Not expired 107 | return false; 108 | } 109 | } 110 | 111 | /** 112 | * During the first phase of the auth flow, we normally want to (or are required to) 113 | * store some details before sending the user off to a remote service to grant access. 114 | * Use a request token to store those details locally, then we can retrieve them when 115 | * we get back to finish the auth flow. 116 | */ 117 | class Keyring_Request_Token extends Keyring_Token { 118 | function __construct( $service, $token, $meta = array(), $uniq = false ) { 119 | $meta['type'] = 'request'; 120 | return parent::__construct( $service, $token, $meta, $uniq ); 121 | } 122 | 123 | function type() { 124 | return 'request'; 125 | } 126 | } 127 | 128 | /** 129 | * Access tokens are what are 'permanently' stored, containing the information required 130 | * to make secure connections/requests on behalf of the user of a remote service. 131 | */ 132 | class Keyring_Access_Token extends Keyring_Token { 133 | function __construct( $service, $token, $meta = array(), $uniq = false ) { 134 | $meta['type'] = 'access'; 135 | return parent::__construct( $service, $token, $meta, $uniq ); 136 | } 137 | 138 | function type() { 139 | return 'access'; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === Publishiza === 2 | Contributors: johnjamesjacoby 3 | Tags: post, twitter, tweet, storm 4 | Requires at least: 4.7 5 | Tested up to: 4.8 6 | Stable tag: 1.0.0 7 | License: GPLv2 or later 8 | License URI: https://www.gnu.org/licenses/gpl-2.0.html 9 | Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9Q4F4EL5YJ62J 10 | 11 | Compose and publish a Tweetstorm, all from inside your WordPress. 12 | 13 | == Description == 14 | 15 | Seamlessly integrates into your WordPress dashboard interface. Safe, secure, & efficient. 16 | 17 | Publishiza includes Keyring, a great foundation by my pal by Beau Lebens. 18 | 19 | == Installation == 20 | 21 | * Download and install using the built in WordPress plugin installer. 22 | * Activate in the "Plugins" area of your admin by clicking the "Activate" link. 23 | * Visit: Tools > Keyring 24 | * Add a New Service 25 | * Authorize Publishiza 26 | 27 | == Frequently Asked Questions == 28 | 29 | = Why would I need this? = 30 | 31 | You really like tweetstorming, but you also want to archive your content in your blog. 32 | 33 | == Screenshots == 34 | 1. Publish box 35 | 2. Keyring 36 | 37 | == Changelog == 38 | 39 | = 1.0.0 = 40 | * Initial release 41 | --------------------------------------------------------------------------------