WordPress.org

Plugin Directory

Changeset 611071


Ignore:
Timestamp:
10/11/12 19:27:59 (19 months ago)
Author:
alexkingorg
Message:

version 3.0

Location:
twitter-tools/trunk
Files:
21 added
5 deleted
2 edited

Legend:

Unmodified
Added
Removed
  • twitter-tools/trunk/README.txt

    r276373 r611071  
    11=== Twitter Tools === 
    2 Tags: twitter, tweet, integration, post, digest, notify, integrate, archive, widget 
    32Contributors: alexkingorg, crowdfavorite 
    4 Requires at least: 2.9 
    5 Tested up to: 3.0.1 
    6 Stable tag: 2.4 
     3Tags: twitter, tweet, integration, post, notify, integrate, archive, widget, shortcode, social 
     4Requires at least: 3.4 
     5Tested up to: 3.4.2 
     6Stable tag: 3.0 
     7License: GPLv2 
     8License URI: http://www.gnu.org/licenses/gpl-2.0.html 
    79 
    810Twitter Tools is a plugin that creates a complete integration between your WordPress blog and your Twitter account. 
    911 
    10 == Details == 
     12== Description == 
    1113 
    1214Twitter Tools integrates with Twitter by giving you the following functionality: 
    1315 
    14 * Archive your Twitter tweets (downloaded every 10 minutes) 
     16* Connect multiple Twitter accounts (via Social) 
     17* Archive the tweets from your Twitter accounts (downloaded every 10 minutes) 
    1518* Create a blog post from each of your tweets 
    16 * Create a daily or weekly digest post of your tweets 
    17 * Create a tweet on Twitter whenever you post in your blog, with a link to the blog post 
    18 * Post a tweet from your sidebar 
    19 * Post a tweet from the WP Admin screens 
    20 * Pass your tweets along to another service (via API hook) 
     19* Create a tweet on Twitter whenever you post in your blog, with a link to the blog post (via Social) 
     20* Browse your tweets locally by @mention, #hashtag or user account (optionally display these publicly) 
     21 
     22Twitter Tools leverages Social's connection to Twitter so that you don't have to create an app and copy keys around. It supports multiple accounts (must be authorized as "global" accounts in Social) with settings on a per-account basis. 
    2123 
    2224 
    2325== Installation == 
     26 
     27_Twitter Tools relies on the <a href="http://wordpress.org/extend/plugins/social/">Social</a> plugin to connect to Twitter. If you aren't already using this plugin please install it before installing Twitter Tools._ 
    2428 
    25291. Download the plugin archive and expand it (you've likely already done this). 
     
    2933 
    3034 
    31 == Configuration == 
    32  
    33 There are a number of configuration options for Twitter Tools. You can find these in Options > Twitter Tools. 
    34  
    35 == Showing Your Tweets == 
    36  
    37 = Widget Friendly = 
    38  
    39 If you are using widgets, you can drag Twitter Tools to your sidebar to display your latest tweets. 
    40  
     35== Upgrading == 
     36 
     37If you have upgraded from an older version of Twitter Tools, your data will need to be converted to the new Twitter Tools format. On the Twitter Tools Options page you will see a prompt to upgrade if appropriate. Follow the steps to convert your data. 
     38 
     39Twitter Tools now stores complete Twitter data along with your basic tweet content. Over time, Twitter Tools will request this data for upgraded tweets. This process make take a few days, as only 10 tweets are requested per hour (to avoid egatively impacting your rate limit). 
     40 
     41 
     42== Connecting Accounts == 
     43 
     44Any Twitter accounts connected on the Social settings page are available for Twitter Tools. You can enable them on a per-account account basis, as well as specifying per-account preferences for creating blog posts, etc. (on the Twitter Tools options screen). 
     45 
     46 
     47== Managing your Tweets == 
     48 
     49You can view, edit and delete (or unpublish) the local copy of your Tweets right in your WordPress admin. Navigate the tweets from the "Tweets" menu item and manage them just as you would any other post type. Twitter Tools does not know if you've deleted a tweet on Twitter, so you'll need to also delete the copy of the tweet from the admin to remove it from your WordPress site. 
     50 
     51 
     52== Displaying your Tweets == 
     53 
     54Twitter Tools include options to create URLs for your local tweets using the following scheme: 
     55 
     56- single tweet: http://alexking.org/tweets/253580615113400321 
     57- account archive: http://alexking.org/tweet-accounts/alexkingorg 
     58- @mention archive: http://alexking.org/tweet-mentions/sogrady 
     59- #hashtag archive: http://alexking.org/tweet-hashtags/monktoberfest 
     60 
     61You can enable public URLs for your tweets in your Twitter Tools settings. If you choose not to enable public URLs for your tweets, you can still vuew and manage them from within the admin screens. 
    4162 
    4263= Shortcode = 
    4364 
    44 Use: 
    45  
    46 `[aktt_tweets]` 
    47  
    48 to show your latest tweets. This will show the number of tweets set in your Settings. If you want to control how many tweets are shown explicitly, you can do so by adding a 'count' parameter like this: 
    49  
    50 `[aktt_tweets count=5]` 
    51  
    52  
    53 = Template Tags = 
    54  
    55 If you are not using widgest, you can use a template tag to add your latest tweets to your sidebar. 
    56  
    57 `<?php aktt_sidebar_tweets(); ?>` 
    58  
    59  
    60 If you just want your latest tweet, use this template tag. 
    61  
    62 `<?php aktt_latest_tweet(); ?>` 
    63  
    64  
    65 == Plugins == 
    66  
    67 Twitter Tools supports plugins, several are included. You can find more here: 
    68  
    69 http://delicious.com/alexkingorg/twitter-tools+plugin 
    70  
    71  
    72 == Hooks/API == 
    73  
    74 Twitter Tools contains a hook that can be used to pass along your tweet data to another service (for example, some folks have wanted to be able to update their Facebook status). To use this hook, create a plugin and add an action to: 
    75  
    76 `aktt_add_tweet` (action) 
    77  
    78 Your plugin function will receive an `aktt_tweet` object as the first parameter. 
    79  
    80 Example psuedo-code: 
    81  
    82 `function my_status_update($tweet) { // do something here }` 
    83 `add_action('aktt_add_tweet', 'my_status_update')` 
    84  
    85 --- 
    86  
    87 Twitter Tools also provides a filter on the URL sent to Twitter so that you can run it through an URL-shortening service if you like. 
    88  
    89 `tweet_blog_post_url` (filter) 
    90  
    91 Your plugin function will receive the URL as the first parameter. 
    92  
    93 Example psuedo-code: 
    94  
    95 `function my_short_url($long_url) { 
    96     // do something here - return the shortened URL  
    97     $short_url = my_short_url_func($long_url); 
    98     return $short_url; 
    99 }` 
    100 `add_filter('tweet_blog_post_url', 'my_short_url')` 
    101  
    102 --- 
    103  
    104 `aktt_do_tweet` (filter) 
    105  
    106 Returning false in this hook will prevent a tweet from being sent. One parameter is sent, the Tweet object to be sent to Twitter. 
    107  
    108 Example psuedo-code: 
    109  
    110 `function dont_tweet($tweet) { 
    111     if (some condition) { 
    112         // will not tweet 
    113         return false; 
    114     } 
    115     else { 
    116         // must return the $tweet to send it 
    117         return $tweet; 
    118     } 
    119 }` 
    120 `add_filter('aktt_do_tweet', 'dont_tweet')` 
    121  
    122 --- 
    123  
    124 `aktt_do_blog_post_tweet` (filter) 
    125  
    126 Returning false in this hook will prevent a blog post Tweet from being sent. Two parameters are passed, the Tweet object to be sent to Twitter and the Post generating the Tweet. 
    127  
    128 Example psuedo-code: 
    129  
    130 `function dont_post_tweet($tweet, $post) { 
    131     if (some condition) { 
    132         // will not tweet 
    133         return false; 
    134     } 
    135     else { 
    136         // must return the $tweet to send it 
    137         return $tweet; 
    138     } 
    139 }` 
    140 `add_filter('aktt_do_blog_post_tweet', 'dont_post_tweet', 10, 2)` 
    141  
    142 --- 
    143  
    144 `aktt_do_tweet_post` (filter) 
    145  
    146 Returning false in this hook will prevent a blog post from being created from a Tweet. Two parameters are passed, the data to be used in the post and the Tweet object. 
    147  
    148 Example psuedo-code: 
    149  
    150 `function dont_tweet_post($post, $data) { 
    151     if (some condition) { 
    152         // will not post 
    153         return false; 
    154     } 
    155     else { 
    156         // must return the $data for a post to be created 
    157         return $data; 
    158     } 
    159 }` 
    160 `add_filter('aktt_do_tweet_post', 'dont_tweet_post', 10, 2)` 
    161  
    162 --- 
    163  
    164 `aktt_tweets_to_digest_post` (filter) 
    165  
    166 Allows you to make changes the tweets that will be included in a digest post. 
    167  
    168 --- 
    169  
    170 `aktt_options_form` (action) 
    171  
    172 Allows you to add to the Twitter Tools settings page. 
    173  
    174 --- 
    175  
    176 `aktt_post_options` (action) 
    177  
    178 Allows you to add to the Twitter Tools box on the New Post page (requires the option to tweet on blog posts to be enabled). 
    179  
    180 == Known Issues == 
    181  
    182 * If you change your blog post notification tweet prefix, the previous blog post notification might not be correctly recognized as a blog post tweet. This is only under very rare conditions due to timing issues. 
    183 * Only one Twitter account is supported (not one account per author). 
    184 * Tweets are not deleted from the tweet table in your WordPress database when they are deleted from Twitter. To delete from your WordPress database, use a database admin tool like phpMyAdmin. 
    185  
    186  
    187 == Frequently Asked Questions == 
    188  
    189 = Who is allowed to post a Tweet from within WordPress? = 
    190  
    191 Anyone who has a 'publish_post' permission. Basically, if you can post to the blog, you can also post to Twitter (using the account info in the Twitter Tools configuration). 
    192  
    193 = What happens if I have both my tweets posting to my blog as posts and my posts sent to Twitter? Will it cause the world to end in a spinning fireball of death? =  
    194  
    195 Actually, Twitter Tools has taken this into account and you can safely enable both creating posts from your tweets and tweets from your posts without duplicating them in either place. 
    196  
    197 = Does Twitter Tools use a URL shortening service by default? = 
    198  
    199 No, Twitter Tools sends your long URL to Twitter and Twitter chooses to shorten it or not. 
    200  
    201 As of version 2.0 a plugin to do this with the Bit.ly service is included as an option. 
    202  
    203 = Can Twitter Tools use a URL shortening service? = 
    204  
    205 Yes, Twitter Tools includes a filter: 
    206  
    207 `tweet_blog_post_url` 
    208  
    209 as of version 1.6. Plugins for this filter may already exist, or you can create your own. The plugin needs to attach to this filter using the standard WordPress `add_filter()` function and return a URL that will then be passed with your blog post tweet. 
    210  
    211 As of version 2.0 a plugin to do this with the Bit.ly service is included as an option. 
    212  
    213 = Is there any way to change the 'New Blog Post:' prefix when my new posts get tweeted? = 
    214  
    215 Yes, as of version 2.0 you can change this on the Options page. 
    216  
    217 = Can I remove the 'New Blog Post:' prefix entirely? = 
    218  
    219 No, this is not a good idea. Twitter Tools needs to be able to look at the beginning of the tweet and identify if it's a notification from your blog or not. Otherwise, Twitter Tools and Twitter could keep passing the blog posts and resulting tweets back and forth resulting in the 'spinning fireball of death' mentioned above. 
    220  
     65You can use a shortcode to display a list of tweets. 
     66 
     67    [aktt_tweets account="alexkingorg"]  
     68 
     69If you want, you can specify some additional parameters to control how many tweets are displayed: 
     70 
     71    [aktt_tweets account="alexkingorg" count="5" offset="0"] 
     72 
     73You can also choose to explicitly include or exclude replies and retweets: 
     74 
     75    [aktt_tweets account="alexkingorg" include_rts="0" include_replies="1"] 
     76 
     77If you want to limit the tweets to specific @mentions or #hashtags, you can to that as well: 
     78 
     79    [aktt_tweets account="alexkingorg" mentions="crowdfavorite,twittertools" hashtags="wordpress,plugin,twittertools"] 
     80 
     81= Widget = 
     82 
     83The options for the shortcode are also available for the Twitter Tools widget via a few settings. 
     84 
     85= Create Blog Posts = 
     86 
     87Twitter Tools can create a blog post from each of your Tweets. This feature can be enabled on a per-account basis. If there is an image included in the media data of the tweet Twitter Tools will try to save that image as the featured image for the post and append it to the blog post content. 
     88 
     89Please note that this will take effect for all future tweets, it does not retroactively create posts for older tweets (though you could pretty easily script it to do so if you desired). 
     90 
     91 
     92== Customization == 
     93 
     94Twitter Tools is designed to be customizable via the standard hook/filter API. If you find you need additional hooks (or to suggest other bug fixes and enhancements) please create a pull request on GitHub. 
     95 
     96https://github.com/crowdfavorite/wp-twitter-tools 
     97 
     98Get creative! Here are some examples of ways to use more of the full Twitter data to create links back into Twitter where appropriate: 
     99 
     100- linking to the original tweet on Twitter 
     101- linking to "in reply to" tweets 
     102 
     103 
     104== FAQ == 
     105 
     106= What if I don't want to use Social's comment display? = 
     107 
     108All of Social's features (broadcasting, comment display, looking for responses on Twitter and Facebook and the ability to log in with Twitter or Facebook) can be disabled on Social's settings screen. 
     109 
     110= Will Twitter Tools pull in my entire tweet archive from Twitter? = 
     111 
     112Twitter Tools starts archiving from the time you enable it. It does not try to download your entire tweet history. However, there is code in Twitter Tools that can be scripted to download and import tweets. You can put together the pieces with your own code to create the combination of features you desire. Here's an Gist to get you started: 
     113 
     114https://gist.github.com/3470627 
     115 
     116== Screenshots == 
     117 
     1181. Show your tweets on your site (optional). 
     1192. Tweets can be viewed by account, @mention or #hashtag. 
     1203. Manage your tweets in the standard WordPress admin interface. 
     1214. View tweets by @mention, #hashtag, etc. 
     1225. Easy interface to for per-account settings. 
     123 
     124 
     125== Upgrade Notice == 
     126 
     127Version 3.0 is a complete rewrite that utilizes <a href="http://wordpress.org/extend/plugins/social/">Social</a> to make connecting your Twitter account easy. It is compatibile with the latest Twitter API changes as of October 11, 2012. 
    221128 
    222129== Changelog == 
     130 
     131= 3.0 = 
     132 
     133* Complete rewrite! 
     134* Integrates with Social (required) to provide a vastly improved set-up experience 
     135* Broadcasting features are now handled via the Social plugin 
     136* Tweets are stored as a custom post type, providing easy admin access to edit or delete tweets as needed 
     137* Tweets are cross-linked and browsable via custom taxonomies for accounts, @mentions and #hashtags 
     138* Full Twitter is now stored with each tweet 
     139* Comprehensive upgrade routine to migrate existing data and backfill upgraded tweets with full Twitter data 
     140* Additional control over which tweets are displayed via shortcode and widget 
     141* Daily and weekly digest functionality has been removed 
     142 
    223143 
    224144= 2.4 = 
  • twitter-tools/trunk/twitter-tools.php

    r309358 r611071  
    33Plugin Name: Twitter Tools 
    44Plugin URI: http://crowdfavorite.com/wordpress/plugins/twitter-tools/ 
    5 Description: A complete integration between your WordPress blog and <a href="http://twitter.com">Twitter</a>. Bring your tweets into your blog and pass your blog posts to Twitter. Show your tweets in your sidebar, and post tweets from your WordPress admin. 
    6 Version: 2.4 
     5Description: An integration between your WordPress site and Twitter. Create posts from your tweets. Show your tweets in your sidebar. Relies on <a href="http://wordpress.org/extend/plugins/social/">Social</a>. 
     6Version: 3.0 
    77Author: Crowd Favorite 
    88Author URI: http://crowdfavorite.com 
    99*/ 
    1010 
    11 // Copyright (c) 2007-2010 Crowd Favorite, Ltd., Alex King. All rights reserved. 
     11// Copyright (c) 2007-2012 Crowd Favorite, Ltd. All rights reserved. 
    1212// 
    1313// Released under the GPL license 
     
    1717// http://wordpress.org/ 
    1818// 
    19 // Thanks to John Ford ( http://www.aldenta.com ) for his contributions. 
    20 // Thanks to Dougal Campbell ( http://dougal.gunters.org ) for his contributions. 
    21 // Thanks to Silas Sewell ( http://silas.sewell.ch ) for his contributions. 
    22 // Thanks to Greg Grubbs for his contributions. 
    23 // 
    2419// ********************************************************************** 
    2520// This program is distributed in the hope that it will be useful, but 
     
    2823// ********************************************************************** 
    2924 
    30 /* TODO 
     25$aktt_file = __FILE__; 
     26if (isset($plugin)) { 
     27    $aktt_file = $plugin; 
     28} 
     29else if (isset($mu_plugin)) { 
     30    $aktt_file = $mu_plugin; 
     31} 
     32else if (isset($network_plugin)) { 
     33    $aktt_file = $network_plugin; 
     34} 
     35@define('AKTT_FILE', $aktt_file); 
     36@define('AKTT_PATH', WP_PLUGIN_DIR.'/'.basename(dirname($aktt_file)).'/'); 
    3137 
    32 - update widget to new WP widget class 
    33 - what should retweet support look like? 
    34 - refactor digests to use WP-CRON 
    35 - truncate super-long post titles so that full tweet content is < 140 chars 
     38require_once(AKTT_PATH.'/classes/aktt.php'); 
     39require_once(AKTT_PATH.'/classes/aktt_account.php'); 
     40require_once(AKTT_PATH.'/classes/aktt_tweet.php'); 
     41require_once(AKTT_PATH.'/widget.php'); 
    3642 
    37 */ 
     43add_action('after_setup_theme', array('AKTT', 'after_setup_theme'), 9999); 
     44add_action('init', array('AKTT', 'init'), 0); 
    3845 
    39 define('AKTT_VERSION', '2.4'); 
    40  
    41 load_plugin_textdomain('twitter-tools', false, dirname(plugin_basename(__FILE__)) . '/language'); 
    42  
    43 if (!defined('PLUGINDIR')) { 
    44     define('PLUGINDIR','wp-content/plugins'); 
     46/* Shortcode syntax 
     47 *  [aktt_tweets  
     48 *      account="alexkingorg" 
     49 *      count="5"  
     50 *      offset="0" 
     51 *      include_rts="0" 
     52 *      include_replies="0" 
     53 *      mentions="crowdfavorite,twittertools" 
     54 *      hashtags="wordpress,plugin,twittertools" 
     55 *  ] 
     56 */ 
     57function aktt_shortcode_tweets($args) { 
     58    if (!AKTT::$enabled) { 
     59        return ''; 
     60    } 
     61    if ($account = AKTT::default_account()) { 
     62        $username = $account->social_acct->name(); 
     63    } 
     64    else { // no accounts, get out 
     65        return ''; 
     66    } 
     67    $args = shortcode_atts(array( 
     68        'account' => $username, 
     69        'include_rts' => 0, 
     70        'include_replies' => 0, 
     71        'count' => 5, 
     72        'mentions' => '', 
     73        'hashtags' => '', 
     74    ), $args); 
     75    $tweets = AKTT::get_tweets($args); 
     76    ob_start(); 
     77    include(AKTT_PATH.'/views/tweet-list.php'); 
     78    return ob_get_clean(); 
    4579} 
    4680 
    47 if (is_file(trailingslashit(ABSPATH.PLUGINDIR).'twitter-tools.php')) { 
    48     define('AKTT_FILE', trailingslashit(ABSPATH.PLUGINDIR).'twitter-tools.php'); 
    49 } 
    50 else if (is_file(trailingslashit(ABSPATH.PLUGINDIR).'twitter-tools/twitter-tools.php')) { 
    51     define('AKTT_FILE', trailingslashit(ABSPATH.PLUGINDIR).'twitter-tools/twitter-tools.php'); 
     81/* Shortcode syntax 
     82 *  [aktt_tweet account="alexkingorg"] 
     83 *  [aktt_tweet id="138741523272577028"] 
     84 */ 
     85function aktt_shortcode_tweet($args) { 
     86    if (!AKTT::$enabled) { 
     87        return ''; 
     88    } 
     89    if ($account = AKTT::default_account()) { 
     90        $username = $account->social_acct->name(); 
     91    } 
     92    else { // no accounts, get out 
     93        return ''; 
     94    } 
     95    $args = shortcode_atts(array( 
     96        'account' => $username, 
     97        'id' => null 
     98    ), $args); 
     99// if we have an ID, only search by that 
     100    if (!empty($args['id'])) { 
     101        unset($args['account']); 
     102    } 
     103    $args['count'] = 1; 
     104    $tweets = AKTT::get_tweets($args); 
     105    if (count($tweets) != 1) { 
     106        return ''; 
     107    } 
     108    $tweet = $tweets[0]; 
     109    ob_start(); 
     110    include(AKTT_PATH.'/views/tweet.php'); 
     111    return ob_get_clean(); 
    52112} 
    53113 
    54 define('AKTT_API_POST_STATUS', 'http://twitter.com/statuses/update.json'); 
    55 define('AKTT_API_USER_TIMELINE', 'http://twitter.com/statuses/user_timeline.json'); 
    56 define('AKTT_API_STATUS_SHOW', 'http://twitter.com/statuses/show/###ID###.json'); 
    57 define('AKTT_PROFILE_URL', 'http://twitter.com/###USERNAME###'); 
    58 define('AKTT_STATUS_URL', 'http://twitter.com/###USERNAME###/statuses/###STATUS###'); 
    59 define('AKTT_HASHTAG_URL', 'http://search.twitter.com/search?q=###HASHTAG###'); 
     114// included for compatibility only 
     115function aktt_sidebar_tweets($count = 5, $form = null) { 
     116    _deprecated_function(__FUNCTION__, '3.0', 'aktt_shortcode_tweets()'); 
     117    echo do_shortcode('[aktt_tweets count="'.intval($count).'"]'); 
     118} 
    60119 
    61 function aktt_install() { 
    62     global $wpdb; 
    63      
    64     $aktt_install = new twitter_tools; 
    65     $wpdb->aktt = $wpdb->prefix.'ak_twitter'; 
    66     $tables = $wpdb->get_col(" 
    67         SHOW TABLES LIKE '$wpdb->aktt' 
    68     "); 
    69     if (!in_array($wpdb->aktt, $tables)) { 
    70         $charset_collate = ''; 
    71         if ( version_compare(mysql_get_server_info(), '4.1.0', '>=') ) { 
    72             if (!empty($wpdb->charset)) { 
    73                 $charset_collate .= " DEFAULT CHARACTER SET $wpdb->charset"; 
    74             } 
    75             if (!empty($wpdb->collate)) { 
    76                 $charset_collate .= " COLLATE $wpdb->collate"; 
    77             } 
    78         } 
    79         $result = $wpdb->query(" 
    80             CREATE TABLE `$wpdb->aktt` ( 
    81             `id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY , 
    82             `tw_id` VARCHAR( 255 ) NOT NULL , 
    83             `tw_text` VARCHAR( 255 ) NOT NULL , 
    84             `tw_reply_username` VARCHAR( 255 ) DEFAULT NULL , 
    85             `tw_reply_tweet` VARCHAR( 255 ) DEFAULT NULL , 
    86             `tw_created_at` DATETIME NOT NULL , 
    87             `modified` DATETIME NOT NULL , 
    88             UNIQUE KEY `tw_id_unique` ( `tw_id` ) 
    89             ) $charset_collate 
    90         "); 
     120function aktt_sideload_image($file, $post_id, $desc = null) { 
     121    if (!function_exists('wp_sideload_image') && !function_exists('download_url')) { 
     122        include(ABSPATH.'wp-admin/includes/file.php'); 
    91123    } 
    92     foreach ($aktt_install->options as $option) { 
    93         add_option('aktt_'.$option, $aktt_install->$option); 
     124    // Can be replaced with `wp_sideload_image` once WP 3.5 is released 
     125    if (function_exists('wp_sideload_image')) { 
     126        return wp_sideload_image($file, $post_id, $desc); 
    94127    } 
    95     add_option('aktt_update_hash', ''); 
    96 } 
    97 register_activation_hook(AKTT_FILE, 'aktt_install'); 
    98  
    99 class twitter_tools { 
    100     function twitter_tools() { 
    101         $this->options = array( 
    102             'twitter_username' 
    103             , 'create_blog_posts' 
    104             , 'create_digest' 
    105             , 'create_digest_weekly' 
    106             , 'digest_daily_time' 
    107             , 'digest_weekly_time' 
    108             , 'digest_weekly_day' 
    109             , 'digest_title' 
    110             , 'digest_title_weekly' 
    111             , 'blog_post_author' 
    112             , 'blog_post_category' 
    113             , 'blog_post_tags' 
    114             , 'notify_twitter' 
    115             , 'sidebar_tweet_count' 
    116             , 'tweet_from_sidebar' 
    117             , 'give_tt_credit' 
    118             , 'exclude_reply_tweets' 
    119             , 'tweet_prefix' 
    120             , 'last_tweet_download' 
    121             , 'doing_tweet_download' 
    122             , 'doing_digest_post' 
    123             , 'install_date' 
    124             , 'js_lib' 
    125             , 'digest_tweet_order' 
    126             , 'notify_twitter_default' 
    127             , 'app_consumer_key' 
    128             , 'app_consumer_secret' 
    129             , 'oauth_token' 
    130             , 'oauth_token_secret' 
    131         ); 
    132         $this->twitter_username = ''; 
    133         $this->create_blog_posts = '0'; 
    134         $this->create_digest = '0'; 
    135         $this->create_digest_weekly = '0'; 
    136         $this->digest_daily_time = null; 
    137         $this->digest_weekly_time = null; 
    138         $this->digest_weekly_day = null; 
    139         $this->digest_title = __("Twitter Updates for %s", 'twitter-tools'); 
    140         $this->digest_title_weekly = __("Twitter Weekly Updates for %s", 'twitter-tools'); 
    141         $this->blog_post_author = '1'; 
    142         $this->blog_post_category = '1'; 
    143         $this->blog_post_tags = ''; 
    144         $this->notify_twitter = '0'; 
    145         $this->notify_twitter_default = '0'; 
    146         $this->sidebar_tweet_count = '3'; 
    147         $this->tweet_from_sidebar = '1'; 
    148         $this->give_tt_credit = '1'; 
    149         $this->exclude_reply_tweets = '0'; 
    150         $this->install_date = ''; 
    151         $this->js_lib = 'jquery'; 
    152         $this->digest_tweet_order = 'ASC'; 
    153         $this->tweet_prefix = 'New blog post'; 
    154         $this->app_consumer_key = ''; 
    155         $this->app_consumer_secret = ''; 
    156         $this->oauth_token = ''; 
    157         $this->oauth_token_secret =''; 
    158         // not included in options 
    159         $this->update_hash = ''; 
    160         $this->tweet_format = $this->tweet_prefix.': %s %s'; 
    161         $this->last_digest_post = ''; 
    162         $this->last_tweet_download = ''; 
    163         $this->doing_tweet_download = '0'; 
    164         $this->doing_digest_post = '0'; 
    165         $this->oauth_hash = ''; 
    166         $this->version = AKTT_VERSION; 
    167     } 
    168      
    169     function upgrade() { 
    170         global $wpdb; 
    171         $wpdb->aktt = $wpdb->prefix.'ak_twitter'; 
    172  
    173         $col_data = $wpdb->get_results(" 
    174             SHOW COLUMNS FROM $wpdb->aktt 
    175         "); 
    176         $cols = array(); 
    177         foreach ($col_data as $col) { 
    178             $cols[] = $col->Field; 
    179         } 
    180         // 1.2 schema upgrade 
    181         if (!in_array('tw_reply_username', $cols)) { 
    182             $wpdb->query(" 
    183                 ALTER TABLE `$wpdb->aktt` 
    184                 ADD `tw_reply_username` VARCHAR( 255 ) DEFAULT NULL 
    185                 AFTER `tw_text` 
    186             "); 
    187         } 
    188         if (!in_array('tw_reply_tweet', $cols)) { 
    189             $wpdb->query(" 
    190                 ALTER TABLE `$wpdb->aktt` 
    191                 ADD `tw_reply_tweet` VARCHAR( 255 ) DEFAULT NULL 
    192                 AFTER `tw_reply_username` 
    193             "); 
    194         } 
    195         $this->upgrade_default_tweet_prefix(); 
    196         // upgrade indexes 2.1 
    197         $index_data = $wpdb->get_results(" 
    198             SHOW INDEX FROM $wpdb->aktt 
    199         "); 
    200         $indexes = array(); 
    201         foreach ($index_data as $index) { 
    202             $indexes[] = $index->Key_name; 
    203         } 
    204         if (in_array('tw_id', $indexes)) { 
    205             $wpdb->query(" 
    206                 ALTER TABLE `$wpdb->aktt` 
    207                 DROP INDEX `tw_id` 
    208             "); 
    209         } 
    210         if (!in_array('tw_id_unique', $indexes)) { 
    211             $wpdb->query(" 
    212                 ALTER IGNORE TABLE `$wpdb->aktt` 
    213                 ADD UNIQUE KEY `tw_id_unique` ( `tw_id` ) 
    214             "); 
    215             $wpdb->query(" 
    216                 OPTIMIZE TABLE `$wpdb->aktt` 
    217             "); 
    218         } 
    219     } 
    220      
    221     function upgrade_default_tweet_prefix() { 
    222         $prefix = get_option('aktt_tweet_prefix'); 
    223         if (empty($prefix)) { 
    224             $aktt_defaults = new twitter_tools; 
    225             update_option('aktt_tweet_prefix', $aktt_defaults->tweet_prefix); 
    226         } 
     128    if ( empty( $file ) ) { 
     129        return new WP_Error( '', 'File URL cannot be empty.' ); 
    227130    } 
    228131 
    229     function get_settings() { 
    230         foreach ($this->options as $option) { 
    231             $value = get_option('aktt_'.$option); 
    232             if ($option != 'tweet_prefix' || !empty($value)) { 
    233                 $this->$option = $value; 
    234             } 
    235         } 
    236         $this->tweet_format = $this->tweet_prefix.': %s %s'; 
    237     } 
    238      
    239     // puts post fields into object propps 
    240     function populate_settings() { 
    241         foreach ($this->options as $option) { 
    242             $value = stripslashes($_POST['aktt_'.$option]); 
    243             if (isset($_POST['aktt_'.$option]) && ($option != 'tweet_prefix' || !empty($value))) { 
    244                 $this->$option = $value; 
    245             } 
    246         } 
    247     } 
    248      
    249     // puts object props into wp option storage 
    250     function update_settings() { 
    251         if (current_user_can('manage_options')) { 
    252             $this->sidebar_tweet_count = intval($this->sidebar_tweet_count); 
    253             if ($this->sidebar_tweet_count == 0) { 
    254                 $this->sidebar_tweet_count = '3'; 
    255             } 
    256             foreach ($this->options as $option) { 
    257                 update_option('aktt_'.$option, $this->$option); 
    258             } 
    259             if (empty($this->install_date)) { 
    260                 update_option('aktt_install_date', current_time('mysql')); 
    261             } 
    262             $this->initiate_digests(); 
    263             $this->upgrade(); 
    264             $this->upgrade_default_tweet_prefix(); 
    265             update_option('aktt_installed_version', AKTT_VERSION); 
    266             delete_option('aktt_twitter_password'); 
    267         } 
    268     } 
    269      
    270     // figure out when the next weekly and daily digests will be 
    271     function initiate_digests() { 
    272         $next = ($this->create_digest) ? $this->calculate_next_daily_digest() : null; 
    273         $this->next_daily_digest = $next; 
    274         update_option('aktt_next_daily_digest', $next); 
    275          
    276         $next = ($this->create_digest_weekly) ? $this->calculate_next_weekly_digest() : null; 
    277         $this->next_weekly_digest = $next; 
    278         update_option('aktt_next_weekly_digest', $next); 
    279     } 
    280      
    281     function calculate_next_daily_digest() { 
    282         $optionDate = strtotime($this->digest_daily_time); 
    283         $hour_offset = date("G", $optionDate); 
    284         $minute_offset = date("i", $optionDate); 
    285         $next = mktime($hour_offset, $minute_offset, 0); 
    286          
    287         // may have to move to next day 
    288         $now = time(); 
    289         while($next < $now) { 
    290             $next += 60 * 60 * 24; 
    291         } 
    292         return $next; 
    293     } 
    294      
    295     function calculate_next_weekly_digest() { 
    296         $optionDate = strtotime($this->digest_weekly_time); 
    297         $hour_offset = date("G", $optionDate); 
    298         $minute_offset = date("i", $optionDate); 
    299          
    300         $current_day_of_month = date("j"); 
    301         $current_day_of_week = date("w"); 
    302         $current_month = date("n"); 
    303          
    304         // if this week's day is less than today, go for next week 
    305         $nextDay = $current_day_of_month - $current_day_of_week + $this->digest_weekly_day; 
    306         $next = mktime($hour_offset, $minute_offset, 0, $current_month, $nextDay); 
    307         if ($this->digest_weekly_day <= $current_day_of_week) { 
    308             $next = strtotime('+1 week', $next); 
    309         } 
    310         return $next; 
    311     } 
    312      
    313     function ping_digests() { 
    314         // still busy 
    315         if (get_option('aktt_doing_digest_post') == '1') { 
    316             return; 
    317         } 
    318         // check all the digest schedules 
    319         if ($this->create_digest == 1) { 
    320             $this->ping_digest('aktt_next_daily_digest', 'aktt_last_digest_post', $this->digest_title, 60 * 60 * 24 * 1); 
    321         } 
    322         if ($this->create_digest_weekly == 1) { 
    323             $this->ping_digest('aktt_next_weekly_digest', 'aktt_last_digest_post_weekly', $this->digest_title_weekly, 60 * 60 * 24 * 7); 
    324         } 
    325         return; 
    326     } 
    327      
    328     function ping_digest($nextDateField, $lastDateField, $title, $defaultDuration) { 
     132    // Download file to temp location 
     133    $tmp = download_url( $file ); 
    329134 
    330         $next = get_option($nextDateField); 
    331          
    332         if ($next) {         
    333             $next = $this->validateDate($next); 
    334             $rightNow = time(); 
    335             if ($rightNow >= $next) { 
    336                 $start = get_option($lastDateField); 
    337                 $start = $this->validateDate($start, $rightNow - $defaultDuration); 
    338                 if ($this->do_digest_post($start, $next, $title)) { 
    339                     update_option($lastDateField, $rightNow); 
    340                     update_option($nextDateField, $next + $defaultDuration); 
    341                 } else { 
    342                     update_option($lastDateField, null); 
    343                 } 
    344             } 
    345         } 
    346     } 
    347      
    348     function validateDate($in, $default = 0) { 
    349         if (!is_numeric($in)) { 
    350             // try to convert what they gave us into a date 
    351             $out = strtotime($in); 
    352             // if that doesn't work, return the default 
    353             if (!is_numeric($out)) { 
    354                 return $default; 
    355             } 
    356             return $out;     
    357         } 
    358         return $in; 
     135    // Set variables for storage 
     136    // fix file filename for query strings 
     137    preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches ); 
     138    $file_array['name'] = basename($matches[0]); 
     139    $file_array['tmp_name'] = $tmp; 
     140 
     141    // If error storing temporarily, unlink 
     142    if ( is_wp_error( $tmp ) ) { 
     143        @unlink($file_array['tmp_name']); 
     144        $file_array['tmp_name'] = ''; 
    359145    } 
    360146 
    361     function do_digest_post($start, $end, $title) { 
    362          
    363         if (!$start || !$end) return false; 
    364  
    365         // flag us as busy 
    366         update_option('aktt_doing_digest_post', '1'); 
    367         remove_action('publish_post', 'aktt_notify_twitter', 99); 
    368         remove_action('publish_post', 'aktt_store_post_options', 1, 2); 
    369         remove_action('save_post', 'aktt_store_post_options', 1, 2); 
    370         // see if there's any tweets in the time range 
    371         global $wpdb; 
    372          
    373         $startGMT = gmdate("Y-m-d H:i:s", $start); 
    374         $endGMT = gmdate("Y-m-d H:i:s", $end); 
    375          
    376         // build sql 
    377         $conditions = array(); 
    378         $conditions[] = "tw_created_at >= '{$startGMT}'"; 
    379         $conditions[] = "tw_created_at <= '{$endGMT}'"; 
    380         $conditions[] = "tw_text NOT LIKE '".$wpdb->escape($this->tweet_prefix)."%'"; 
    381         if ($this->exclude_reply_tweets) { 
    382             $conditions[] = "tw_text NOT LIKE '@%'"; 
    383         } 
    384         $where = implode(' AND ', $conditions); 
    385          
    386         $sql = " 
    387             SELECT * FROM {$wpdb->aktt} 
    388             WHERE {$where} 
    389             ORDER BY tw_created_at {$this->digest_tweet_order} 
    390         "; 
    391  
    392         $tweets = $wpdb->get_results($sql); 
    393  
    394         if (count($tweets) > 0) { 
    395          
    396             $tweets_to_post = array(); 
    397             foreach ($tweets as $data) { 
    398                 $tweet = new aktt_tweet; 
    399                 $tweet->tw_text = $data->tw_text; 
    400                 $tweet->tw_reply_tweet = $data->tw_reply_tweet; 
    401                 if (!$tweet->tweet_is_post_notification() || ($tweet->tweet_is_reply() && $this->exclude_reply_tweets)) { 
    402                     $tweets_to_post[] = $data; 
    403                 } 
    404             } 
    405              
    406             $tweets_to_post = apply_filters('aktt_tweets_to_digest_post', $tweets_to_post); // here's your chance to alter the tweet list that will be posted as the digest 
    407  
    408             if (count($tweets_to_post) > 0) { 
    409                 $content = '<ul class="aktt_tweet_digest">'."\n"; 
    410                 foreach ($tweets_to_post as $tweet) { 
    411                     $content .= '   <li>'.aktt_tweet_display($tweet, 'absolute').'</li>'."\n"; 
    412                 } 
    413                 $content .= '</ul>'."\n"; 
    414                 if ($this->give_tt_credit == '1') { 
    415                     $content .= '<p class="aktt_credit">'.__('Powered by <a href="http://alexking.org/projects/wordpress">Twitter Tools</a>', 'twitter-tools').'</p>'; 
    416                 } 
    417                 $post_data = array( 
    418                     'post_content' => $wpdb->escape($content), 
    419                     'post_title' => $wpdb->escape(sprintf($title, date('Y-m-d'))), 
    420                     'post_date' => date('Y-m-d H:i:s', $end), 
    421                     'post_category' => array($this->blog_post_category), 
    422                     'post_status' => 'publish', 
    423                     'post_author' => $wpdb->escape($this->blog_post_author) 
    424                 ); 
    425                 $post_data = apply_filters('aktt_digest_post_data', $post_data); // last chance to alter the digest content 
    426  
    427                 $post_id = wp_insert_post($post_data); 
    428  
    429                 add_post_meta($post_id, 'aktt_tweeted', '1', true); 
    430                 wp_set_post_tags($post_id, $this->blog_post_tags); 
    431             } 
    432  
    433         } 
    434         add_action('publish_post', 'aktt_notify_twitter', 99); 
    435         add_action('publish_post', 'aktt_store_post_options', 1, 2); 
    436         add_action('save_post', 'aktt_store_post_options', 1, 2); 
    437         update_option('aktt_doing_digest_post', '0'); 
    438         return true; 
     147    if (!function_exists('media_handle_sideload')) { 
     148        include(ABSPATH.'wp-admin/includes/media.php'); 
    439149    } 
    440      
    441     function tweet_download_interval() { 
    442         return 600; 
     150    if (!function_exists('wp_read_image_metadata')) { 
     151        include(ABSPATH.'wp-admin/includes/image.php'); 
    443152    } 
    444      
    445     function do_tweet($tweet = '') {         
    446         if (empty($tweet) || empty($tweet->tw_text)) { 
    447             return; 
    448         } 
    449         $tweet = apply_filters('aktt_do_tweet', $tweet); // return false here to not tweet 
    450         if (!$tweet) { 
    451             return; 
    452         } 
    453  
    454         if (aktt_oauth_test() && ($connection = aktt_oauth_connection())) { 
    455             $connection->post( 
    456                 AKTT_API_POST_STATUS 
    457                 , array( 
    458                     'status' => $tweet->tw_text 
    459                     , 'source' => 'twittertools' 
    460                 ) 
    461             ); 
    462             if (strcmp($connection->http_code, '200') == 0) { 
    463                 update_option('aktt_last_tweet_download', strtotime('-28 minutes')); 
    464                 return true; 
    465             } 
    466         } 
    467         return false; 
    468     } 
    469      
    470     function do_blog_post_tweet($post_id = 0) { 
    471 // this is only called on the publish_post hook 
    472         if ($this->notify_twitter == '0' 
    473             || $post_id == 0 
    474             || get_post_meta($post_id, 'aktt_tweeted', true) == '1' 
    475             || get_post_meta($post_id, 'aktt_notify_twitter', true) == 'no' 
    476         ) { 
    477             return; 
    478         } 
    479         $post = get_post($post_id); 
    480         // check for an edited post before TT was installed 
    481         if ($post->post_date <= $this->install_date) { 
    482             return; 
    483         } 
    484         // check for private posts 
    485         if ($post->post_status == 'private') { 
    486             return; 
    487         } 
    488         $tweet = new aktt_tweet; 
    489         $url = apply_filters('tweet_blog_post_url', get_permalink($post_id)); 
    490         $tweet->tw_text = sprintf(__($this->tweet_format, 'twitter-tools'), @html_entity_decode($post->post_title, ENT_COMPAT, 'UTF-8'), $url); 
    491         $tweet = apply_filters('aktt_do_blog_post_tweet', $tweet, $post); // return false here to not tweet 
    492         if (!$tweet) { 
    493             return; 
    494         } 
    495         $this->do_tweet($tweet); 
    496         add_post_meta($post_id, 'aktt_tweeted', '1', true); 
    497     } 
    498      
    499     function do_tweet_post($tweet) { 
    500         global $wpdb; 
    501         remove_action('publish_post', 'aktt_notify_twitter', 99); 
    502         $data = array( 
    503             'post_content' => $wpdb->escape(aktt_make_clickable($tweet->tw_text)) 
    504             , 'post_title' => $wpdb->escape(trim_add_elipsis($tweet->tw_text, 30)) 
    505             , 'post_date' => get_date_from_gmt(date('Y-m-d H:i:s', $tweet->tw_created_at)) 
    506             , 'post_category' => array($this->blog_post_category) 
    507             , 'post_status' => 'publish' 
    508             , 'post_author' => $wpdb->escape($this->blog_post_author) 
    509         ); 
    510         $data = apply_filters('aktt_do_tweet_post', $data, $tweet); // return false here to not make a blog post 
    511         if (!$data) { 
    512             return; 
    513         } 
    514         $post_id = wp_insert_post($data); 
    515         add_post_meta($post_id, 'aktt_twitter_id', $tweet->tw_id, true); 
    516         wp_set_post_tags($post_id, $this->blog_post_tags); 
    517         add_action('publish_post', 'aktt_notify_twitter', 99); 
    518     } 
     153    return media_handle_sideload( $file_array, $post_id, $desc ); 
    519154} 
    520  
    521 class aktt_tweet { 
    522     function aktt_tweet( 
    523         $tw_id = '' 
    524         , $tw_text = '' 
    525         , $tw_created_at = '' 
    526         , $tw_reply_username = null 
    527         , $tw_reply_tweet = null 
    528     ) { 
    529         $this->id = ''; 
    530         $this->modified = ''; 
    531         $this->tw_created_at = $tw_created_at; 
    532         $this->tw_text = $tw_text; 
    533         $this->tw_reply_username = $tw_reply_username; 
    534         $this->tw_reply_tweet = $tw_reply_tweet; 
    535         $this->tw_id = $tw_id; 
    536     } 
    537      
    538     function twdate_to_time($date) { 
    539         $parts = explode(' ', $date); 
    540         $date = strtotime($parts[1].' '.$parts[2].', '.$parts[5].' '.$parts[3]); 
    541         return $date; 
    542     } 
    543      
    544     function tweet_post_exists() { 
    545         global $wpdb; 
    546         $test = $wpdb->get_results(" 
    547             SELECT * 
    548             FROM $wpdb->postmeta 
    549             WHERE meta_key = 'aktt_twitter_id' 
    550             AND meta_value = '".$wpdb->escape($this->tw_id)."' 
    551         "); 
    552         if (count($test) > 0) { 
    553             return true; 
    554         } 
    555         return false; 
    556     } 
    557      
    558     function tweet_is_post_notification() { 
    559         global $aktt; 
    560         if (substr($this->tw_text, 0, strlen($aktt->tweet_prefix)) == $aktt->tweet_prefix) { 
    561             return true; 
    562         } 
    563         return false; 
    564     } 
    565      
    566     function tweet_is_reply() { 
    567 // Twitter data changed - users still expect anything starting with @ is a reply 
    568 //      return !empty($this->tw_reply_tweet); 
    569         return (substr($this->tw_text, 0, 1) == '@'); 
    570     } 
    571      
    572     function add() { 
    573         global $wpdb, $aktt; 
    574         $wpdb->query(" 
    575             INSERT 
    576             INTO $wpdb->aktt 
    577             ( tw_id 
    578             , tw_text 
    579             , tw_reply_username 
    580             , tw_reply_tweet 
    581             , tw_created_at 
    582             , modified 
    583             ) 
    584             VALUES 
    585             ( '".$wpdb->escape($this->tw_id)."' 
    586             , '".$wpdb->escape($this->tw_text)."' 
    587             , '".$wpdb->escape($this->tw_reply_username)."' 
    588             , '".$wpdb->escape($this->tw_reply_tweet)."' 
    589             , '".date('Y-m-d H:i:s', $this->tw_created_at)."' 
    590             , NOW() 
    591             ) 
    592         "); 
    593         do_action('aktt_add_tweet', $this); 
    594         if ($aktt->create_blog_posts == '1' && !$this->tweet_post_exists() && !$this->tweet_is_post_notification() && (!$aktt->exclude_reply_tweets || !$this->tweet_is_reply())) { 
    595             $aktt->do_tweet_post($this); 
    596         } 
    597     } 
    598 } 
    599  
    600 function aktt_api_status_show_url($id) { 
    601     return str_replace('###ID###', $id, AKTT_API_STATUS_SHOW); 
    602 } 
    603  
    604 function aktt_profile_url($username) { 
    605     return str_replace('###USERNAME###', $username, AKTT_PROFILE_URL); 
    606 } 
    607  
    608 function aktt_profile_link($username, $prefix = '', $suffix = '') { 
    609     return $prefix.'<a href="'.aktt_profile_url($username).'" class="aktt_username">'.$username.'</a>'.$suffix; 
    610 } 
    611  
    612 function aktt_hashtag_url($hashtag) { 
    613     $hashtag = urlencode('#'.$hashtag); 
    614     return str_replace('###HASHTAG###', $hashtag, AKTT_HASHTAG_URL); 
    615 } 
    616  
    617 function aktt_hashtag_link($hashtag, $prefix = '', $suffix = '') { 
    618     return $prefix.'<a href="'.aktt_hashtag_url($hashtag).'" class="aktt_hashtag">'.htmlspecialchars($hashtag).'</a> '.$suffix; 
    619 } 
    620  
    621 function aktt_status_url($username, $status) { 
    622     return str_replace( 
    623         array( 
    624             '###USERNAME###' 
    625             , '###STATUS###' 
    626         ) 
    627         , array( 
    628             $username 
    629             , $status 
    630         ) 
    631         , AKTT_STATUS_URL 
    632     ); 
    633 } 
    634 function aktt_oauth_test() { 
    635     global $aktt; 
    636     return ( aktt_oauth_credentials_to_hash() == get_option('aktt_oauth_hash') ); 
    637 } 
    638  
    639 function aktt_ping_digests() { 
    640     global $aktt; 
    641     $aktt->ping_digests(); 
    642 } 
    643  
    644 function aktt_update_tweets() { 
    645     global $aktt; 
    646      
    647     // let the last update run for 10 minutes 
    648     if (time() - intval(get_option('aktt_doing_tweet_download')) < $aktt->tweet_download_interval()) { 
    649         return; 
    650     } 
    651     // wait 10 min between downloads 
    652     if (time() - intval(get_option('aktt_last_tweet_download')) < $aktt->tweet_download_interval()) { 
    653         return; 
    654     } 
    655     update_option('aktt_doing_tweet_download', time()); 
    656     global $wpdb, $aktt; 
    657     if (empty($aktt->twitter_username)) { 
    658         update_option('aktt_doing_tweet_download', '0'); 
    659         return; 
    660     } 
    661  
    662     if ( aktt_oauth_test() && ($connection = aktt_oauth_connection()) ) { 
    663         $data = $connection->get(AKTT_API_USER_TIMELINE); 
    664         if ($connection->http_code != '200') { 
    665             update_option('aktt_doing_tweet_download', '0'); 
    666             return; 
    667         } 
    668     } 
    669     else { 
    670         return; 
    671     } 
    672     // hash results to see if they're any different than the last update, if so, return 
    673  
    674     $hash = md5($data); 
    675     if ($hash == get_option('aktt_update_hash')) { 
    676         update_option('aktt_last_tweet_download', time()); 
    677         update_option('aktt_doing_tweet_download', '0'); 
    678         do_action('aktt_update_tweets'); 
    679         return; 
    680     } 
    681     $data = preg_replace('/"id":(\d+)/', '"id":"$1"', $data); // hack for json_decode on 32-bit PHP 
    682     $tweets = json_decode($data); 
    683  
    684     if (is_array($tweets) && count($tweets)) { 
    685         $tweet_ids = array(); 
    686         foreach ($tweets as $tweet) { 
    687             $tweet_ids[] = $wpdb->escape($tweet->id); 
    688         } 
    689         $existing_ids = $wpdb->get_col(" 
    690             SELECT tw_id 
    691             FROM $wpdb->aktt 
    692             WHERE tw_id 
    693             IN ('".implode("', '", $tweet_ids)."') 
    694         "); 
    695         foreach ($tweets as $tw_data) { 
    696             if (!$existing_ids || !in_array($tw_data->id, $existing_ids)) { 
    697                 $tweet = new aktt_tweet( 
    698                     $tw_data->id 
    699                     , $tw_data->text 
    700                 ); 
    701                 $tweet->tw_created_at = $tweet->twdate_to_time($tw_data->created_at); 
    702                 if (!empty($tw_data->in_reply_to_status_id)) { 
    703                     $tweet->tw_reply_tweet = $tw_data->in_reply_to_status_id; 
    704                     $url = aktt_api_status_show_url($tw_data->in_reply_to_status_id); 
    705                     $data = $connection->get($url); 
    706                     if (strcmp($connection->http_code, '200') == 0) { 
    707                         $status = json_decode($data); 
    708                         $tweet->tw_reply_username = $status->user->screen_name; 
    709                     } 
    710                 } 
    711                 // make sure we haven't downloaded someone else's tweets - happens sometimes due to Twitter hiccups 
    712                 if (strtolower($tw_data->user->screen_name) == strtolower($aktt->twitter_username)) { 
    713                     $tweet->add(); 
    714                 } 
    715             } 
    716         } 
    717     } 
    718     aktt_reset_tweet_checking($hash, time()); 
    719     do_action('aktt_update_tweets'); 
    720 } 
    721  
    722 function aktt_reset_tweet_checking($hash = '', $time = 0) { 
    723     if (!current_user_can('manage_options')) { 
    724         return; 
    725     } 
    726     update_option('aktt_update_hash', $hash); 
    727     update_option('aktt_last_tweet_download', $time); 
    728     update_option('aktt_doing_tweet_download', '0'); 
    729 } 
    730  
    731 function aktt_reset_digests() { 
    732     if (!current_user_can('manage_options')) { 
    733         return; 
    734     } 
    735     update_option('aktt_doing_digest_post', '0'); 
    736 } 
    737  
    738 function aktt_notify_twitter($post_id) { 
    739     global $aktt; 
    740     $aktt->do_blog_post_tweet($post_id); 
    741 } 
    742 add_action('publish_post', 'aktt_notify_twitter', 99); 
    743  
    744 function aktt_sidebar_tweets($limit = null, $form = null) { 
    745     global $wpdb, $aktt; 
    746     if (!$limit) { 
    747         $limit = $aktt->sidebar_tweet_count; 
    748     } 
    749     if ($aktt->exclude_reply_tweets) { 
    750         $where = "AND tw_text NOT LIKE '@%' "; 
    751     } 
    752     else { 
    753         $where = ''; 
    754     } 
    755     $tweets = $wpdb->get_results(" 
    756         SELECT * 
    757         FROM $wpdb->aktt 
    758         WHERE tw_text NOT LIKE '".$wpdb->escape($aktt->tweet_prefix.'%')."' 
    759         $where 
    760         ORDER BY tw_created_at DESC 
    761         LIMIT $limit 
    762     "); 
    763     $output = '<div class="aktt_tweets">'."\n" 
    764         .'  <ul>'."\n"; 
    765     if (count($tweets) > 0) { 
    766         foreach ($tweets as $tweet) { 
    767             $output .= '        <li>'.aktt_tweet_display($tweet).'</li>'."\n"; 
    768         } 
    769     } 
    770     else { 
    771         $output .= '        <li>'.__('No tweets available at the moment.', 'twitter-tools').'</li>'."\n"; 
    772     } 
    773     if (!empty($aktt->twitter_username)) { 
    774         $output .= '        <li class="aktt_more_updates"><a href="'.aktt_profile_url($aktt->twitter_username).'">'.__('More updates...', 'twitter-tools').'</a></li>'."\n"; 
    775     } 
    776     $output .= '</ul>'; 
    777     if ($form !== false && $aktt->tweet_from_sidebar == '1' && aktt_oauth_test()) { 
    778         $output .= aktt_tweet_form('input', 'onsubmit="akttPostTweet(); return false;"'); 
    779           $output .= '  <p id="aktt_tweet_posted_msg">'.__('Posting tweet...', 'twitter-tools').'</p>'; 
    780     } 
    781     if ($aktt->give_tt_credit == '1') { 
    782         $output .= '<p class="aktt_credit">'.__('Powered by <a href="http://alexking.org/projects/wordpress">Twitter Tools</a>', 'twitter-tools').'</p>'; 
    783     } 
    784     $output .= '</div>'; 
    785     print($output); 
    786 } 
    787  
    788 function aktt_shortcode_tweets($args) { 
    789     extract(shortcode_atts(array( 
    790         'count' => null 
    791     ), $args)); 
    792     ob_start(); 
    793     aktt_sidebar_tweets($count, false); 
    794     $output = ob_get_contents(); 
    795     ob_end_clean(); 
    796     return $output; 
    797 } 
    798 add_shortcode('aktt_tweets', 'aktt_shortcode_tweets'); 
    799  
    800 function aktt_latest_tweet() { 
    801     global $wpdb, $aktt; 
    802     if ($aktt->exclude_reply_tweets) { 
    803         $where = "AND tw_text NOT LIKE '@%' "; 
    804     } 
    805     else { 
    806         $where = ''; 
    807     } 
    808     $tweets = $wpdb->get_results(" 
    809         SELECT * 
    810         FROM $wpdb->aktt 
    811         WHERE tw_text NOT LIKE '".$wpdb->escape($aktt->tweet_prefix)."%' 
    812         $where 
    813         ORDER BY tw_created_at DESC 
    814         LIMIT 1 
    815     "); 
    816     if (count($tweets) == 1) { 
    817         foreach ($tweets as $tweet) { 
    818             $output = aktt_tweet_display($tweet); 
    819         } 
    820     } 
    821     else { 
    822         $output = __('No tweets available at the moment.', 'twitter-tools'); 
    823     } 
    824     print($output); 
    825 } 
    826  
    827 function aktt_tweet_display($tweet, $time = 'relative') { 
    828     global $aktt; 
    829     $output = aktt_make_clickable(wp_specialchars($tweet->tw_text)); 
    830     if (!empty($tweet->tw_reply_username)) { 
    831         $output .=  ' <a href="'.aktt_status_url($tweet->tw_reply_username, $tweet->tw_reply_tweet).'" class="aktt_tweet_reply">'.sprintf(__('in reply to %s', 'twitter-tools'), $tweet->tw_reply_username).'</a>'; 
    832     } 
    833     switch ($time) { 
    834         case 'relative': 
    835             $time_display = aktt_relativeTime($tweet->tw_created_at, 3); 
    836             break; 
    837         case 'absolute': 
    838             $time_display = '#'; 
    839             break; 
    840     } 
    841     $output .= ' <a href="'.aktt_status_url($aktt->twitter_username, $tweet->tw_id).'" class="aktt_tweet_time">'.$time_display.'</a>'; 
    842     $output = apply_filters('aktt_tweet_display', $output, $tweet); // allows you to alter the tweet display output 
    843     return $output; 
    844 } 
    845  
    846 function aktt_make_clickable($tweet) { 
    847     $tweet .= ' '; 
    848     $tweet = preg_replace_callback( 
    849             '/(^|\s)@([a-zA-Z0-9_]{1,})(\W)/' 
    850             , create_function( 
    851                 '$matches' 
    852                 , 'return aktt_profile_link($matches[2], \' @\', $matches[3]);' 
    853             ) 
    854             , $tweet 
    855     ); 
    856     $tweet = preg_replace_callback( 
    857         '/(^|\s)#([a-zA-Z0-9_]{1,})(\W)/' 
    858         , create_function( 
    859             '$matches' 
    860             , 'return aktt_hashtag_link($matches[2], \' #\', \'\');' 
    861         ) 
    862         , $tweet 
    863     ); 
    864      
    865     if (function_exists('make_chunky')) { 
    866         return make_chunky($tweet); 
    867     } 
    868     else { 
    869         return make_clickable($tweet); 
    870     } 
    871 } 
    872  
    873 function aktt_tweet_form($type = 'input', $extra = '') { 
    874     $output = ''; 
    875     if (current_user_can('publish_posts') && aktt_oauth_test()) { 
    876         $output .= ' 
    877 <form action="'.site_url('index.php').'" method="post" id="aktt_tweet_form" '.$extra.'> 
    878     <fieldset> 
    879         '; 
    880         switch ($type) { 
    881             case 'input': 
    882                 $output .= ' 
    883         <p><input type="text" size="20" maxlength="140" id="aktt_tweet_text" name="aktt_tweet_text" onkeyup="akttCharCount();" /></p> 
    884         <input type="hidden" name="ak_action" value="aktt_post_tweet_sidebar" /> 
    885         <script type="text/javascript"> 
    886         //<![CDATA[ 
    887         function akttCharCount() { 
    888             var count = document.getElementById("aktt_tweet_text").value.length; 
    889             if (count > 0) { 
    890                 document.getElementById("aktt_char_count").innerHTML = 140 - count; 
    891             } 
    892             else { 
    893                 document.getElementById("aktt_char_count").innerHTML = ""; 
    894             } 
    895         } 
    896         setTimeout("akttCharCount();", 500); 
    897         document.getElementById("aktt_tweet_form").setAttribute("autocomplete", "off"); 
    898         //]]> 
    899         </script> 
    900                 '; 
    901                 break; 
    902             case 'textarea': 
    903                 $output .= ' 
    904         <p><textarea type="text" cols="60" rows="5" maxlength="140" id="aktt_tweet_text" name="aktt_tweet_text" onkeyup="akttCharCount();"></textarea></p> 
    905         <input type="hidden" name="ak_action" value="aktt_post_tweet_admin" /> 
    906         <script type="text/javascript"> 
    907         //<![CDATA[ 
    908         function akttCharCount() { 
    909             var count = document.getElementById("aktt_tweet_text").value.length; 
    910             if (count > 0) { 
    911                 document.getElementById("aktt_char_count").innerHTML = (140 - count) + "'.__(' characters remaining', 'twitter-tools').'"; 
    912             } 
    913             else { 
    914                 document.getElementById("aktt_char_count").innerHTML = ""; 
    915             } 
    916         } 
    917         setTimeout("akttCharCount();", 500); 
    918         document.getElementById("aktt_tweet_form").setAttribute("autocomplete", "off"); 
    919         //]]> 
    920         </script> 
    921                 '; 
    922                 break; 
    923         } 
    924         $output .= ' 
    925         <p> 
    926             <input type="submit" id="aktt_tweet_submit" name="aktt_tweet_submit" value="'.__('Post Tweet!', 'twitter-tools').'" class="button-primary" /> 
    927             <span id="aktt_char_count"></span> 
    928         </p> 
    929         <div class="clear"></div> 
    930     </fieldset> 
    931     '.wp_nonce_field('aktt_new_tweet', '_wpnonce', true, false).wp_referer_field(false).' 
    932 </form> 
    933         '; 
    934     } 
    935     return $output; 
    936 } 
    937  
    938 function aktt_widget_init() { 
    939     if (!function_exists('register_sidebar_widget')) { 
    940         return; 
    941     } 
    942     function aktt_widget($args) { 
    943         extract($args); 
    944         $options = get_option('aktt_widget'); 
    945         $title = $options['title']; 
    946         if (empty($title)) { 
    947         } 
    948         echo $before_widget . $before_title . $title . $after_title; 
    949         aktt_sidebar_tweets(); 
    950         echo $after_widget; 
    951     } 
    952     register_sidebar_widget(array(__('Twitter Tools', 'twitter-tools'), 'widgets'), 'aktt_widget'); 
    953      
    954     function aktt_widget_control() { 
    955         $options = get_option('aktt_widget'); 
    956         if (!is_array($options)) { 
    957             $options = array( 
    958                 'title' => __("What I'm Doing...", 'twitter-tools') 
    959             ); 
    960         } 
    961         if (isset($_POST['ak_action']) && $_POST['ak_action'] == 'aktt_update_widget_options') { 
    962             $options['title'] = strip_tags(stripslashes($_POST['aktt_widget_title'])); 
    963             update_option('aktt_widget', $options); 
    964             // reset checking so that sidebar isn't blank if this is the first time activating 
    965             aktt_reset_tweet_checking(); 
    966             aktt_update_tweets(); 
    967         } 
    968  
    969         // Be sure you format your options to be valid HTML attributes. 
    970         $title = htmlspecialchars($options['title'], ENT_QUOTES); 
    971          
    972         // Here is our little form segment. Notice that we don't need a 
    973         // complete form. This will be embedded into the existing form. 
    974         print(' 
    975             <p style="text-align:right;"><label for="aktt_widget_title">' . __('Title:') . ' <input style="width: 200px;" id="aktt_widget_title" name="aktt_widget_title" type="text" value="'.$title.'" /></label></p> 
    976             <p>'.__('Find additional Twitter Tools options on the <a href="options-general.php?page=twitter-tools.php">Twitter Tools Options page</a>.', 'twitter-tools').' 
    977             <input type="hidden" id="ak_action" name="ak_action" value="aktt_update_widget_options" /> 
    978         '); 
    979     } 
    980     register_widget_control(array(__('Twitter Tools', 'twitter-tools'), 'widgets'), 'aktt_widget_control', 300, 100); 
    981  
    982 } 
    983 add_action('widgets_init', 'aktt_widget_init'); 
    984  
    985 function aktt_init() { 
    986     global $wpdb, $aktt; 
    987     $wpdb->aktt = $wpdb->prefix.'ak_twitter'; 
    988     $aktt = new twitter_tools; 
    989     $aktt->get_settings(); 
    990     if (($aktt->last_tweet_download + $aktt->tweet_download_interval()) < time()) { 
    991         add_action('shutdown', 'aktt_update_tweets'); 
    992         add_action('shutdown', 'aktt_ping_digests'); 
    993     } 
    994     if (!is_admin() && $aktt->tweet_from_sidebar && current_user_can('publish_posts')) { 
    995         switch ($aktt->js_lib) { 
    996             case 'jquery': 
    997                 wp_enqueue_script('jquery'); 
    998                 break; 
    999             case 'prototype': 
    1000                 wp_enqueue_script('prototype'); 
    1001                 break; 
    1002         } 
    1003     } 
    1004     if (is_admin()) { 
    1005         global $wp_version; 
    1006         $update = false; 
    1007         if (isset($wp_version) && version_compare($wp_version, '2.5', '>=') && empty ($aktt->install_date)) { 
    1008             $update = true; 
    1009         } 
    1010         if (!get_option('aktt_tweet_prefix')) { 
    1011             update_option('aktt_tweet_prefix', $aktt->tweet_prefix); 
    1012             $update = true; 
    1013         } 
    1014         $installed_version = get_option('aktt_installed_version'); 
    1015         if ($installed_version != AKTT_VERSION) { 
    1016             $update = true; 
    1017         } 
    1018         if (!empty($installed_version) && version_compare($installed_version, '2.4', '<') && !aktt_oauth_test()) { 
    1019             add_action('admin_notices', create_function( '', "echo '<div class=\"error\"><p>".sprintf(__('Twitter recently changed how it authenticates its users, you will need you to update your <a href="%s">Twitter Tools settings</a>. We apologize for any inconvenience these new authentication steps may cause.', 'twitter-tools'), admin_url('options-general.php?page=twitter-tools.php'))."</p></div>';" ) ); 
    1020         } 
    1021         else if ($update) { 
    1022             add_action('admin_notices', create_function( '', "echo '<div class=\"error\"><p>".sprintf(__('Please update your <a href="%s">Twitter Tools settings</a>', 'twitter-tools'), admin_url('options-general.php?page=twitter-tools.php'))."</p></div>';" ) ); 
    1023         } 
    1024     } 
    1025 } 
    1026 add_action('init', 'aktt_init', 1); 
    1027  
    1028 function aktt_head() { 
    1029     global $aktt; 
    1030     if ($aktt->tweet_from_sidebar) { 
    1031         print(' 
    1032             <link rel="stylesheet" type="text/css" href="'.site_url('/index.php?ak_action=aktt_css&amp;v='.AKTT_VERSION).'" /> 
    1033             <script type="text/javascript" src="'.site_url('/index.php?ak_action=aktt_js&amp;v='.AKTT_VERSION).'"></script> 
    1034         '); 
    1035     } 
    1036 } 
    1037 add_action('wp_head', 'aktt_head'); 
    1038  
    1039 function aktt_head_admin() { 
    1040     print(' 
    1041         <link rel="stylesheet" type="text/css" href="'.admin_url('index.php?ak_action=aktt_css_admin&amp;v='.AKTT_VERSION).'" /> 
    1042         <script type="text/javascript" src="'.admin_url('index.php?ak_action=aktt_js_admin&amp;v='.AKTT_VERSION).'"></script> 
    1043     '); 
    1044 } 
    1045 if (isset($_GET['page']) && $_GET['page'] == 'twitter-tools.php') { 
    1046     add_action('admin_head', 'aktt_head_admin'); 
    1047 } 
    1048  
    1049 function aktt_resources() { 
    1050     global $aktt; 
    1051     if (!empty($_GET['ak_action'])) { 
    1052         switch($_GET['ak_action']) { 
    1053             case 'aktt_js': 
    1054                 header("Content-type: text/javascript"); 
    1055                 switch ($aktt->js_lib) { 
    1056                     case 'jquery': 
    1057 ?> 
    1058 function akttPostTweet() { 
    1059     var tweet_field = jQuery('#aktt_tweet_text'); 
    1060     var tweet_form = tweet_field.parents('form'); 
    1061     var tweet_text = tweet_field.val(); 
    1062     if (tweet_text == '') { 
    1063         return; 
    1064     } 
    1065     var tweet_msg = jQuery("#aktt_tweet_posted_msg"); 
    1066     var nonce = jQuery(tweet_form).find('input[name=_wpnonce]').val(); 
    1067     var refer = jQuery(tweet_form).find('input[name=_wp_http_referer]').val(); 
    1068     jQuery.post( 
    1069         "<?php echo site_url('index.php'); ?>", 
    1070         { 
    1071             ak_action: "aktt_post_tweet_sidebar",  
    1072             aktt_tweet_text: tweet_text, 
    1073             _wpnonce: nonce, 
    1074             _wp_http_referer: refer 
    1075         }, 
    1076         function(data) { 
    1077             tweet_msg.html(data); 
    1078             akttSetReset(); 
    1079         } 
    1080     ); 
    1081     tweet_field.val('').focus(); 
    1082     jQuery('#aktt_char_count').html(''); 
    1083     jQuery("#aktt_tweet_posted_msg").show(); 
    1084 } 
    1085 function akttSetReset() { 
    1086     setTimeout('akttReset();', 2000); 
    1087 } 
    1088 function akttReset() { 
    1089     jQuery('#aktt_tweet_posted_msg').hide(); 
    1090 } 
    1091 <?php 
    1092                         break; 
    1093                     case 'prototype': 
    1094 ?> 
    1095 function akttPostTweet() { 
    1096     var tweet_field = $('aktt_tweet_text'); 
    1097     var tweet_text = tweet_field.value; 
    1098     if (tweet_text == '') { 
    1099         return; 
    1100     } 
    1101     var tweet_msg = $("aktt_tweet_posted_msg"); 
    1102     var nonce = $('_wpnonce').value; 
    1103     var refer = $('_wpnonce').next('input').value; 
    1104     var akttAjax = new Ajax.Updater( 
    1105         tweet_msg, 
    1106         "<?php echo site_url('index.php'); ?>", 
    1107         { 
    1108             method: "post", 
    1109             parameters: "ak_action=aktt_post_tweet_sidebar&aktt_tweet_text=" + tweet_text + '&_wpnonce=' + nonce + '&_wp_http_referer=' + refer, 
    1110             onComplete: akttSetReset 
    1111         } 
    1112     ); 
    1113     tweet_field.value = ''; 
    1114     tweet_field.focus(); 
    1115     $('aktt_char_count').innerHTML = ''; 
    1116     tweet_msg.style.display = 'block'; 
    1117 } 
    1118 function akttSetReset() { 
    1119     setTimeout('akttReset();', 2000); 
    1120 } 
    1121 function akttReset() { 
    1122     $('aktt_tweet_posted_msg').style.display = 'none'; 
    1123 } 
    1124 <?php 
    1125                         break; 
    1126                 } 
    1127                 die(); 
    1128                 break; 
    1129             case 'aktt_css': 
    1130                 header("Content-Type: text/css"); 
    1131 ?> 
    1132 #aktt_tweet_form { 
    1133     margin: 0; 
    1134     padding: 5px 0; 
    1135 } 
    1136 #aktt_tweet_form fieldset { 
    1137     border: 0; 
    1138 } 
    1139 #aktt_tweet_form fieldset #aktt_tweet_submit { 
    1140     float: right; 
    1141     margin-right: 10px; 
    1142 } 
    1143 #aktt_tweet_form fieldset #aktt_char_count { 
    1144     color: #666; 
    1145 } 
    1146 #aktt_tweet_posted_msg { 
    1147     background: #ffc; 
    1148     display: none; 
    1149     margin: 0 0 5px 0; 
    1150     padding: 5px; 
    1151 } 
    1152 #aktt_tweet_form div.clear { 
    1153     clear: both; 
    1154     float: none; 
    1155 } 
    1156 <?php 
    1157                 die(); 
    1158                 break; 
    1159             case 'aktt_js_admin': 
    1160                 header("Content-Type: text/javascript"); 
    1161 ?> 
    1162  
    1163 jQuery(function($) { 
    1164     $("#aktt_authentication_showhide").click(function(){ 
    1165         $("#aktt_authentication_display").slideToggle(); 
    1166     }); 
    1167 }); 
    1168  
    1169 (function($){ 
    1170  
    1171     jQuery.fn.timepicker = function(){ 
    1172      
    1173         var hrs = new Array(); 
    1174         for(var h = 1; h <= 12; hrs.push(h++)); 
    1175  
    1176         var mins = new Array(); 
    1177         for(var m = 0; m < 60; mins.push(m++)); 
    1178  
    1179         var ap = new Array('am', 'pm'); 
    1180  
    1181         function pad(n) { 
    1182             n = n.toString(); 
    1183             return n.length == 1 ? '0' + n : n; 
    1184         } 
    1185      
    1186         this.each(function() { 
    1187  
    1188             var v = $(this).val(); 
    1189             if (!v) v = new Date(); 
    1190  
    1191             var d = new Date(v); 
    1192             var h = d.getHours(); 
    1193             var m = d.getMinutes(); 
    1194             var p = (h >= 12) ? "pm" : "am"; 
    1195             h = (h > 12) ? h - 12 : h; 
    1196  
    1197             var output = ''; 
    1198  
    1199             output += '<select id="h_' + this.id + '" class="timepicker">';              
    1200             for (var hr in hrs){ 
    1201                 output += '<option value="' + pad(hrs[hr]) + '"'; 
    1202                 if(parseInt(hrs[hr], 10) == h || (parseInt(hrs[hr], 10) == 12 && h == 0)) output += ' selected'; 
    1203                 output += '>' + pad(hrs[hr]) + '</option>'; 
    1204             } 
    1205             output += '</select>'; 
    1206      
    1207             output += '<select id="m_' + this.id + '" class="timepicker">';              
    1208             for (var mn in mins){ 
    1209                 output += '<option value="' + pad(mins[mn]) + '"'; 
    1210                 if(parseInt(mins[mn], 10) == m) output += ' selected'; 
    1211                 output += '>' + pad(mins[mn]) + '</option>'; 
    1212             } 
    1213             output += '</select>';               
    1214      
    1215             output += '<select id="p_' + this.id + '" class="timepicker">';              
    1216             for(var pp in ap){ 
    1217                 output += '<option value="' + ap[pp] + '"'; 
    1218                 if(ap[pp] == p) output += ' selected'; 
    1219                 output += '>' + ap[pp] + '</option>'; 
    1220             } 
    1221             output += '</select>'; 
    1222              
    1223             $(this).after(output); 
    1224              
    1225             var field = this; 
    1226             $(this).siblings('select.timepicker').change(function() { 
    1227                 var h = parseInt($('#h_' + field.id).val(), 10); 
    1228                 var m = parseInt($('#m_' + field.id).val(), 10); 
    1229                 var p = $('#p_' + field.id).val(); 
    1230      
    1231                 if (p == "am") { 
    1232                     if (h == 12) { 
    1233                         h = 0; 
    1234                     } 
    1235                 } else if (p == "pm") { 
    1236                     if (h < 12) { 
    1237                         h += 12; 
    1238                     } 
    1239                 } 
    1240                  
    1241                 var d = new Date(); 
    1242                 d.setHours(h); 
    1243                 d.setMinutes(m); 
    1244                  
    1245                 $(field).val(d.toUTCString()); 
    1246             }).change(); 
    1247  
    1248         }); 
    1249  
    1250         return this; 
    1251     }; 
    1252      
    1253     jQuery.fn.daypicker = function() { 
    1254          
    1255         var days = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); 
    1256          
    1257         this.each(function() { 
    1258              
    1259             var v = $(this).val(); 
    1260             if (!v) v = 0; 
    1261             v = parseInt(v, 10); 
    1262              
    1263             var output = ""; 
    1264             output += '<select id="d_' + this.id + '" class="daypicker">';               
    1265             for (var i = 0; i < days.length; i++) { 
    1266                 output += '<option value="' + i + '"'; 
    1267                 if (v == i) output += ' selected'; 
    1268                 output += '>' + days[i] + '</option>'; 
    1269             } 
    1270             output += '</select>'; 
    1271              
    1272             $(this).after(output); 
    1273              
    1274             var field = this; 
    1275             $(this).siblings('select.daypicker').change(function() { 
    1276                 $(field).val( $(this).val() ); 
    1277             }).change(); 
    1278          
    1279         }); 
    1280          
    1281     }; 
    1282      
    1283     jQuery.fn.forceToggleClass = function(classNames, bOn) { 
    1284         return this.each(function() { 
    1285             jQuery(this)[ bOn ? "addClass" : "removeClass" ](classNames); 
    1286         }); 
    1287     }; 
    1288      
    1289 })(jQuery); 
    1290  
    1291 jQuery(function() { 
    1292  
    1293     // add in the time and day selects 
    1294     jQuery('form#ak_twittertools input.time').timepicker(); 
    1295     jQuery('form#ak_twittertools input.day').daypicker(); 
    1296      
    1297     // togglers 
    1298     jQuery('.time_toggle .toggler').change(function() { 
    1299         var theSelect = jQuery(this); 
    1300         theSelect.parent('.time_toggle').forceToggleClass('active', theSelect.val() === "1"); 
    1301     }).change(); 
    1302      
    1303 }); 
    1304 <?php 
    1305                 die(); 
    1306                 break; 
    1307             case 'aktt_css_admin': 
    1308                 header("Content-Type: text/css"); 
    1309 ?> 
    1310 #aktt_tweet_form { 
    1311     margin: 0; 
    1312     padding: 5px 0; 
    1313 } 
    1314 #aktt_tweet_form fieldset { 
    1315     border: 0; 
    1316 } 
    1317 #aktt_tweet_form fieldset textarea { 
    1318     width: 95%; 
    1319 } 
    1320 #aktt_tweet_form fieldset #aktt_tweet_submit { 
    1321     float: right; 
    1322     margin-right: 50px; 
    1323 } 
    1324 #aktt_tweet_form fieldset #aktt_char_count { 
    1325     color: #666; 
    1326 } 
    1327 #ak_readme { 
    1328     height: 300px; 
    1329     width: 95%; 
    1330 } 
    1331  
    1332 form.aktt .options, 
    1333 #ak_twittertools .options, 
    1334 #ak_twittertools_disconnect .options { 
    1335     overflow: hidden; 
    1336     border: none; 
    1337 } 
    1338 form.aktt .option, 
    1339 #ak_twittertools .option, 
    1340 #ak_twittertools_disconnect .option { 
    1341     overflow: hidden; 
    1342     padding-bottom: 9px; 
    1343     padding-top: 9px; 
    1344 } 
    1345 form.aktt .option label, 
    1346 #ak_twittertools .option label, 
    1347 #ak_twittertools_disconnect .option label { 
    1348     display: block; 
    1349     float: left; 
    1350     width: 200px; 
    1351     margin-right: 24px; 
    1352     text-align: right; 
    1353 } 
    1354 form.aktt .option span, 
    1355 #ak_twittertools .option span { 
    1356     color: #666; 
    1357     display: block; 
    1358     float: left; 
    1359     margin-left: 230px; 
    1360     margin-top: 6px; 
    1361     clear: left; 
    1362 } 
    1363 form.aktt select, 
    1364 form.aktt input, 
    1365 #ak_twittertools select, 
    1366 #ak_twittertools input, 
    1367 #ak_twittertools_disconnect input { 
    1368     float: left; 
    1369     display: block; 
    1370     margin-right: 6px; 
    1371 } 
    1372 form.aktt p.submit, 
    1373 #ak_twittertools p.submit, 
    1374 #ak_twittertools_disconnect p.submit { 
    1375     overflow: hidden; 
    1376 } 
    1377  
    1378 #ak_twittertools fieldset.options .option span.aktt_login_result_wait { 
    1379     background: #ffc; 
    1380 } 
    1381 #ak_twittertools fieldset.options .option span.aktt_login_result { 
    1382     background: #CFEBF7; 
    1383     color: #000; 
    1384 } 
    1385 #ak_twittertools .timepicker, 
    1386 #ak_twittertools .daypicker { 
    1387     display: none; 
    1388 } 
    1389 #ak_twittertools .active .timepicker, 
    1390 #ak_twittertools .active .daypicker { 
    1391     display: block 
    1392 } 
    1393 #ak_twittertools_disconnect .auth_information_link{ 
    1394     margin-left: 6px; 
    1395 } 
    1396 .aktt_experimental { 
    1397     background: #eee; 
    1398     border: 2px solid #ccc; 
    1399 } 
    1400 .aktt_experimental h4 { 
    1401     color: #666; 
    1402     margin: 0; 
    1403     padding: 10px; 
    1404     text-align: center; 
    1405 } 
    1406 #aktt_sub_instructions ul { 
    1407     list-style-type: circle; 
    1408     padding-top:0px; 
    1409 } 
    1410 #aktt_sub_instructions ul li{ 
    1411     margin-left: 20px; 
    1412 } 
    1413 #aktt_authentication_display { 
    1414     display: none; 
    1415 } 
    1416 #ak_twittertools_disconnect .auth_label { 
    1417     display: block; 
    1418     float: left; 
    1419     width: 200px; 
    1420     margin-right: 24px; 
    1421     text-align: right; 
    1422 } 
    1423 #ak_twittertools_disconnect .auth_code { 
    1424      
    1425 } 
    1426  
    1427 .help { 
    1428     color: #777; 
    1429     font-size: 11px; 
    1430 } 
    1431 .txt-center { 
    1432     text-align: center; 
    1433 } 
    1434 #cf { 
    1435     width: 90%; 
    1436 } 
    1437  
    1438 /* Developed by and Support by callouts */ 
    1439 #cf-callouts { 
    1440     background: url(http://cloud.wphelpcenter.com/resources/wp-admin-0001/border-fade-sprite.gif) 0 0 repeat-x; 
    1441     float: left; 
    1442     margin: 18px 0; 
    1443 } 
    1444 .cf-callout { 
    1445     float: left; 
    1446     margin-top: 18px; 
    1447     max-width: 500px; 
    1448     width: 50%; 
    1449 } 
    1450 #cf-callout-credit { 
    1451     margin-right: 9px; 
    1452 } 
    1453 #cf-callout-credit .cf-box-title { 
    1454     background: #193542 url(http://cloud.wphelpcenter.com/resources/wp-admin-0001/box-sprite.png) 0 0 repeat-x; 
    1455     border-bottom: 1px solid #0C1A21; 
    1456 } 
    1457 #cf-callout-support { 
    1458     margin-left: 9px; 
    1459 } 
    1460 #cf-callout-support .cf-box-title { 
    1461     background: #8D2929 url(http://cloud.wphelpcenter.com/resources/wp-admin-0001/box-sprite.png) 0 -200px repeat-x; 
    1462     border-bottom: 1px solid #461414; 
    1463 } 
    1464  
    1465 /* General cf-box styles */ 
    1466 .cf-box {  
    1467     background: #EFEFEF url(http://cloud.wphelpcenter.com/resources/wp-admin-0001/box-sprite.png) 0 -400px repeat-x; 
    1468     border: 1px solid #E3E3E3; 
    1469     border-radius: 5px; 
    1470     -moz-border-radius: 5px; 
    1471     -webkit-border-radius: 5px; 
    1472     -khtml-border-radius: 5px; 
    1473 } 
    1474 .cf-box .cf-box-title { 
    1475     color: #fff; 
    1476     font-size: 14px; 
    1477     font-weight: normal; 
    1478     padding: 6px 15px; 
    1479     margin: 0 0 12px 0; 
    1480     -moz-border-radius-topleft: 5px; 
    1481     -webkit-border-top-left-radius: 5px; 
    1482     -khtml-border-top-left-radius: 5px; 
    1483     border-top-left-radius: 5px; 
    1484     -moz-border-radius-topright: 5px; 
    1485     -webkit-border-top-right-radius: 5px; 
    1486     -khtml-border-top-right-radius: 5px; 
    1487     border-top-right-radius: 5px; 
    1488     text-align: center; 
    1489     text-shadow: #333 0 1px 1px; 
    1490 } 
    1491 .cf-box .cf-box-title a { 
    1492     display: block; 
    1493     color: #fff; 
    1494 } 
    1495 .cf-box .cf-box-title a:hover { 
    1496     color: #E1E1E1; 
    1497 } 
    1498 .cf-box .cf-box-content { 
    1499     margin: 0 15px 15px 15px; 
    1500 } 
    1501 .cf-box .cf-box-content p { 
    1502     font-size: 11px; 
    1503 } 
    1504  
    1505  
    1506 <?php 
    1507                 die(); 
    1508                 break; 
    1509         } 
    1510     } 
    1511 } 
    1512 add_action('init', 'aktt_resources', 2); 
    1513  
    1514 function aktt_oauth_connection() { 
    1515     global $aktt; 
    1516     if ( !empty($aktt->app_consumer_key) && !empty($aktt->app_consumer_secret) && !empty($aktt->oauth_token) && !empty($aktt->oauth_token_secret) ) {    
    1517         require_once(dirname(__FILE__).'/twitteroauth.php'); 
    1518         $connection = new TwitterOAuth( 
    1519             $aktt->app_consumer_key,  
    1520             $aktt->app_consumer_secret,  
    1521             $aktt->oauth_token,  
    1522             $aktt->oauth_token_secret 
    1523         ); 
    1524         $connection->useragent = 'Twitter Tools http://alexking.org/projects/wordpress'; 
    1525         return $connection; 
    1526     } 
    1527     else { 
    1528         return false; 
    1529     } 
    1530 } 
    1531  
    1532 function aktt_oauth_credentials_to_hash() { 
    1533     global $aktt; 
    1534     $hash = md5($aktt->app_consumer_key.$aktt->app_consumer_secret.$aktt->oauth_token.$aktt->oauth_token_secret); 
    1535     return $hash;        
    1536 } 
    1537  
    1538 function aktt_request_handler() { 
    1539     global $wpdb, $aktt; 
    1540     if (!empty($_GET['ak_action'])) { 
    1541         switch($_GET['ak_action']) { 
    1542             case 'aktt_update_tweets': 
    1543                 if (!wp_verify_nonce($_GET['_wpnonce'], 'aktt_update_tweets')) { 
    1544                     wp_die('Oops, please try again.'); 
    1545                 } 
    1546                 aktt_update_tweets(); 
    1547                 wp_redirect(admin_url('options-general.php?page=twitter-tools.php&tweets-updated=true')); 
    1548                 die(); 
    1549                 break; 
    1550             case 'aktt_reset_tweet_checking': 
    1551                 if (!wp_verify_nonce($_GET['_wpnonce'], 'aktt_update_tweets')) { 
    1552                     wp_die('Oops, please try again.'); 
    1553                 } 
    1554                 aktt_reset_tweet_checking(); 
    1555                 wp_redirect(admin_url('options-general.php?page=twitter-tools.php&tweet-checking-reset=true')); 
    1556                 die(); 
    1557                 break; 
    1558             case 'aktt_reset_digests': 
    1559                 if (!wp_verify_nonce($_GET['_wpnonce'], 'aktt_update_tweets')) { 
    1560                     wp_die('Oops, please try again.'); 
    1561                 } 
    1562                 aktt_reset_digests(); 
    1563                 wp_redirect(admin_url('options-general.php?page=twitter-tools.php&digest-reset=true')); 
    1564                 die(); 
    1565                 break; 
    1566         } 
    1567     } 
    1568     if (!empty($_POST['ak_action'])) { 
    1569         switch($_POST['ak_action']) { 
    1570             case 'aktt_update_settings': 
    1571                 if (!wp_verify_nonce($_POST['_wpnonce'], 'aktt_settings')) { 
    1572                     wp_die('Oops, please try again.'); 
    1573                 } 
    1574                 $aktt->populate_settings(); 
    1575                 $aktt->update_settings(); 
    1576                 wp_redirect(admin_url('options-general.php?page=twitter-tools.php&updated=true')); 
    1577                 die(); 
    1578                 break; 
    1579             case 'aktt_post_tweet_sidebar': 
    1580                 if (!empty($_POST['aktt_tweet_text']) && current_user_can('publish_posts')) { 
    1581                     if (!wp_verify_nonce($_POST['_wpnonce'], 'aktt_new_tweet')) { 
    1582                         wp_die('Oops, please try again.'); 
    1583                     } 
    1584                     $tweet = new aktt_tweet(); 
    1585                     $tweet->tw_text = stripslashes($_POST['aktt_tweet_text']); 
    1586                     if ($aktt->do_tweet($tweet)) { 
    1587                         die(__('Tweet posted.', 'twitter-tools')); 
    1588                     } 
    1589                     else { 
    1590                         die(__('Tweet post failed.', 'twitter-tools')); 
    1591                     } 
    1592                 } 
    1593                 break; 
    1594             case 'aktt_post_tweet_admin': 
    1595                 if (!empty($_POST['aktt_tweet_text']) && current_user_can('publish_posts')) { 
    1596                     if (!wp_verify_nonce($_POST['_wpnonce'], 'aktt_new_tweet')) { 
    1597                         wp_die('Oops, please try again.'); 
    1598                     } 
    1599                     $tweet = new aktt_tweet(); 
    1600                     $tweet->tw_text = stripslashes($_POST['aktt_tweet_text']); 
    1601                     if ($aktt->do_tweet($tweet)) { 
    1602                         wp_redirect(admin_url('post-new.php?page=twitter-tools.php&tweet-posted=true')); 
    1603                     } 
    1604                     else { 
    1605                         wp_die(__('Oops, your tweet was not posted. Please check your blog is connected to Twitter and Twitter is up and running happily.', 'twitter-tools')); 
    1606                     } 
    1607                     die(); 
    1608                 } 
    1609                 break; 
    1610             case 'aktt_oauth_test': 
    1611                 if (!wp_verify_nonce($_POST['_wpnonce'], 'aktt_oauth_test')) { 
    1612                     wp_die('Oops, please try again.'); 
    1613                 } 
    1614                 $auth_test = false; 
    1615                 if ( !empty($_POST['aktt_app_consumer_key']) 
    1616                     && !empty($_POST['aktt_app_consumer_secret']) 
    1617                     && !empty($_POST['aktt_oauth_token']) 
    1618                     && !empty($_POST['aktt_oauth_token_secret']) 
    1619                 ) { 
    1620                     $aktt->populate_settings(); 
    1621                     $aktt->update_settings(); 
    1622                     $message = 'fail'; 
    1623                     if ($connection = aktt_oauth_connection()) { 
    1624                         $data = $connection->get('account/verify_credentials'); 
    1625                         if ($connection->http_code == '200') { 
    1626                             $data = json_decode($data); 
    1627                             update_option('aktt_twitter_username', stripslashes($data->screen_name)); 
    1628                             $oauth_hash = aktt_oauth_credentials_to_hash(); 
    1629                             update_option('aktt_oauth_hash', $oauth_hash); 
    1630                             $message = 'success'; 
    1631                         } 
    1632                     } 
    1633                 } 
    1634                 wp_redirect(admin_url('options-general.php?page=twitter-tools.php&oauth='.$message)); 
    1635             break; 
    1636             case 'aktt_twitter_disconnect': 
    1637                 if (!wp_verify_nonce($_POST['_wpnonce'], 'aktt_twitter_disconnect')) { 
    1638                     wp_die('Oops, please try again.'); 
    1639                 } 
    1640                  
    1641                 update_option('aktt_app_consumer_key', ''); 
    1642                 update_option('aktt_app_consumer_secret', ''); 
    1643                 update_option('aktt_oauth_token', ''); 
    1644                 update_option('aktt_oauth_token_secret', ''); 
    1645                 wp_redirect(admin_url('options-general.php?page=twitter-tools.php&updated=true')); 
    1646             break; 
    1647         } 
    1648     } 
    1649 } 
    1650 add_action('init', 'aktt_request_handler', 10); 
    1651  
    1652 function aktt_admin_tweet_form() { 
    1653     global $aktt; 
    1654     if ( $_GET['tweet-posted'] ) { 
    1655         print(' 
    1656             <div id="message" class="updated fade"> 
    1657                 <p>'.__('Tweet posted.', 'twitter-tools').'</p> 
    1658             </div> 
    1659         '); 
    1660     } 
    1661     if ( aktt_oauth_test() ) { 
    1662         print(' 
    1663             <div class="wrap" id="aktt_write_tweet"> 
    1664             <h2>'.__('Write Tweet', 'twitter-tools').'</h2> 
    1665             <p>'.__('This will create a new \'tweet\' in <a href="http://twitter.com">Twitter</a> using the account information in your <a href="options-general.php?page=twitter-tools.php">Twitter Tools Options</a>.', 'twitter-tools').'</p> 
    1666             '.aktt_tweet_form('textarea').' 
    1667             </div> 
    1668         '); 
    1669     }  
    1670 } 
    1671  
    1672 function aktt_options_form() { 
    1673     global $wpdb, $aktt, $wp_version; 
    1674  
    1675     $categories = get_categories('hide_empty=0'); 
    1676     $cat_options = ''; 
    1677     foreach ($categories as $category) { 
    1678 // WP < 2.3 compatibility 
    1679         !empty($category->term_id) ? $cat_id = $category->term_id : $cat_id = $category->cat_ID; 
    1680         !empty($category->name) ? $cat_name = $category->name : $cat_name = $category->cat_name; 
    1681         if ($cat_id == $aktt->blog_post_category) { 
    1682             $selected = 'selected="selected"'; 
    1683         } 
    1684         else { 
    1685             $selected = ''; 
    1686         } 
    1687         $cat_options .= "\n\t<option value='$cat_id' $selected>$cat_name</option>"; 
    1688     } 
    1689  
    1690     global $current_user; 
    1691     $authors = get_editable_user_ids($current_user->ID); 
    1692     $author_options = ''; 
    1693     if (count($authors)) { 
    1694         foreach ($authors as $user_id) { 
    1695             $usero = new WP_User($user_id); 
    1696             $author = $usero->data; 
    1697             // Only list users who are allowed to publish 
    1698             if (! $usero->has_cap('publish_posts')) { 
    1699                 continue; 
    1700             } 
    1701             if ($author->ID == $aktt->blog_post_author) { 
    1702                 $selected = 'selected="selected"'; 
    1703             } 
    1704             else { 
    1705                 $selected = ''; 
    1706             } 
    1707             $author_options .= "\n\t<option value='$author->ID' $selected>$author->user_nicename</option>"; 
    1708         } 
    1709     } 
    1710      
    1711     $js_libs = array( 
    1712         'jquery' => 'jQuery' 
    1713         , 'prototype' => 'Prototype' 
    1714     ); 
    1715     $js_lib_options = ''; 
    1716     foreach ($js_libs as $js_lib => $js_lib_display) { 
    1717         if ($js_lib == $aktt->js_lib) { 
    1718             $selected = 'selected="selected"'; 
    1719         } 
    1720         else { 
    1721             $selected = ''; 
    1722         } 
    1723         $js_lib_options .= "\n\t<option value='$js_lib' $selected>$js_lib_display</option>"; 
    1724     } 
    1725     $digest_tweet_orders = array( 
    1726         'ASC' => __('Oldest first (Chronological order)', 'twitter-tools'), 
    1727         'DESC' => __('Newest first (Reverse-chronological order)', 'twitter-tools') 
    1728     ); 
    1729     $digest_tweet_order_options = ''; 
    1730     foreach ($digest_tweet_orders as $digest_tweet_order => $digest_tweet_order_display) { 
    1731         if ($digest_tweet_order == $aktt->digest_tweet_order) { 
    1732             $selected = 'selected="selected"'; 
    1733         } 
    1734         else { 
    1735             $selected = ''; 
    1736         } 
    1737         $digest_tweet_order_options .= "\n\t<option value='$digest_tweet_order' $selected>$digest_tweet_order_display</option>"; 
    1738     }    
    1739     $yes_no = array( 
    1740         'create_blog_posts' 
    1741         , 'create_digest' 
    1742         , 'create_digest_weekly' 
    1743         , 'notify_twitter' 
    1744         , 'notify_twitter_default' 
    1745         , 'tweet_from_sidebar' 
    1746         , 'give_tt_credit' 
    1747         , 'exclude_reply_tweets' 
    1748     ); 
    1749     foreach ($yes_no as $key) { 
    1750         $var = $key.'_options'; 
    1751         if ($aktt->$key == '0') { 
    1752             $$var = ' 
    1753                 <option value="0" selected="selected">'.__('No', 'twitter-tools').'</option> 
    1754                 <option value="1">'.__('Yes', 'twitter-tools').'</option> 
    1755             '; 
    1756         } 
    1757         else { 
    1758             $$var = ' 
    1759                 <option value="0">'.__('No', 'twitter-tools').'</option> 
    1760                 <option value="1" selected="selected">'.__('Yes', 'twitter-tools').'</option> 
    1761             '; 
    1762         } 
    1763     } 
    1764     if ( $_GET['tweets-updated'] ) { 
    1765         print(' 
    1766             <div id="message" class="updated fade"> 
    1767                 <p>'.__('Tweets updated.', 'twitter-tools').'</p> 
    1768             </div> 
    1769         '); 
    1770     } 
    1771     if ( $_GET['tweet-checking-reset'] ) { 
    1772         print(' 
    1773             <div id="message" class="updated fade"> 
    1774                 <p>'.__('Tweet checking has been reset.', 'twitter-tools').'</p> 
    1775             </div> 
    1776         '); 
    1777     } 
    1778      
    1779     if ( strcmp($_GET['oauth'], "success" ) == 0 ) { 
    1780         print(' 
    1781             <div id="message" class="updated fade"> 
    1782                 <p>'.__('Yay! We connected with Twitter.', 'twitter-tools').'</p> 
    1783             </div> 
    1784  
    1785         '); 
    1786     } 
    1787     else if (strcmp($_GET['oauth'], "fail" ) == 0 ) { 
    1788         print(' 
    1789             <div id="message" class="updated fade"> 
    1790                 <p>'.__('Authentication Failed. Please check your credentials and make sure <a href="http://www.twitter.com/" title="Twitter" target="_blank">Twitter</a> is up and running.', 'twitter-tools').'</p> 
    1791             </div> 
    1792  
    1793         '); 
    1794     } 
    1795      
    1796     print('  
    1797             <div class="wrap" id="aktt_options_page"> 
    1798             <h2>'.__('Twitter Tools Options', 'twitter-tools').' &nbsp; <script type="text/javascript">var WPHC_AFF_ID = "14303"; var WPHC_POSITION = "c1"; var WPHC_PRODUCT = "Twitter Tools ('.AKTT_VERSION.')"; var WPHC_WP_VERSION = "'.$wp_version.'";</script><script type="text/javascript" src="http://cloud.wphelpcenter.com/support-form/0001/deliver-a.js"></script></h2>' 
    1799     ); 
    1800     if ( !aktt_oauth_test() ) { 
    1801         print('  
    1802             <h3>'.__('Connect to Twitter','twitter-tools').'</h3> 
    1803             <p style="width: 700px;">'.__('In order to get started, we need to follow some steps to get this site registered with Twitter. This process is awkward and more complicated than it should be. We hope to have a better solution for this in a future release, but for now this system is what Twitter supports. If you have any trouble, please use the Support button above to contact <a href="http://wphelpcenter.com" target="_blank">WordPress HelpCenter</a> and provide code 14303.', 'twitter-tools').'</p>  
    1804             <form id="ak_twittertools" name="ak_twittertools" action="'.admin_url('options-general.php').'" method="post"> 
    1805                 <fieldset class="options"> 
    1806                     <h4>'.__('1. Register this site as an application on ', 'twitter-tools') . '<a href="http://dev.twitter.com/apps/new" title="'.__('Twitter App Registration','twitter-tools').'" target="_blank">'.__('Twitter\'s app registration page','twitter-tools').'</a></h4> 
    1807                     <div id="aktt_sub_instructions"> 
    1808                         <ul> 
    1809                         <li>'.__('If you\'re not logged in, you can use your Twitter username and password' , 'twitter-tools').'</li> 
    1810                         <li>'.__('Your Application\'s Name will be what shows up after "via" in your twitter stream' , 'twitter-tools').'</li> 
    1811                         <li>'.__('Application Type should be set on ' , 'twitter-tools').'<strong>'.__('Browser' , 'twitter-tools').'</strong></li> 
    1812                         <li>'.__('The Callback URL should be ' , 'twitter-tools').'<strong>'.  get_bloginfo( 'url' ) .'</strong></li> 
    1813                         <li>'.__('Default Access type should be set to ' , 'twitter-tools').'<strong>'.__('Read &amp; Write' , 'twitter-tools').'</strong> '.__('(this is NOT the default)' , 'twitter-tools').'</li> 
    1814                         </ul> 
    1815                     <p>'.__('Once you have registered your site as an application, you will be provided with a consumer key and a comsumer secret.' , 'twitter-tools').'</p> 
    1816                     </div> 
    1817                     <h4>'.__('2. Copy and paste your consumer key and consumer secret into the fields below' , 'twitter-tools').'</h4> 
    1818                  
    1819                     <div class="option"> 
    1820                         <label for="aktt_app_consumer_key">'.__('Twitter Consumer Key', 'twitter-tools').'</label> 
    1821                         <input type="text" size="25" name="aktt_app_consumer_key" id="aktt_app_consumer_key" value="'.esc_attr($aktt->app_consumer_key).'" autocomplete="off"> 
    1822                     </div> 
    1823                     <div class="option"> 
    1824                         <label for="aktt_app_consumer_secret">'.__('Twitter Consumer Secret', 'twitter-tools').'</label> 
    1825                         <input type="text" size="25" name="aktt_app_consumer_secret" id="aktt_app_consumer_secret" value="'.esc_attr($aktt->app_consumer_secret).'" autocomplete="off"> 
    1826                     </div> 
    1827                     <h4>3. Copy and paste your Access Token and Access Token Secret into the fields below</h4> 
    1828                     <p>On the right hand side of your application page, click on \'My Access Token\'.</p> 
    1829                     <div class="option"> 
    1830                         <label for="aktt_oauth_token">'.__('Access Token', 'twitter-tools').'</label> 
    1831                         <input type="text" size="25" name="aktt_oauth_token" id="aktt_oauth_token" value="'.esc_attr($aktt->oauth_token).'" autocomplete="off"> 
    1832                     </div> 
    1833                     <div class="option"> 
    1834                         <label for="aktt_oauth_token_secret">'.__('Access Token Secret', 'twitter-tools').'</label> 
    1835                         <input type="text" size="25" name="aktt_oauth_token_secret" id="aktt_oauth_token_secret" value="'.esc_attr($aktt->oauth_token_secret).'" autocomplete="off"> 
    1836                     </div> 
    1837                 </fieldset> 
    1838                 <p class="submit"> 
    1839                     <input type="submit" name="submit" class="button-primary" value="'.__('Connect to Twitter', 'twitter-tools').'" /> 
    1840                 </p> 
    1841                 <input type="hidden" name="ak_action" value="aktt_oauth_test" class="hidden" style="display: none;" /> 
    1842                 '.wp_nonce_field('aktt_oauth_test', '_wpnonce', true, false).wp_referer_field(false).' 
    1843             </form> 
    1844                  
    1845                 '); 
    1846     } 
    1847     else if ( aktt_oauth_test() ) { 
    1848         print('  
    1849             <form id="ak_twittertools_disconnect" name="ak_twittertools_disconnect" action="'.admin_url('options-general.php').'" method="post"> 
    1850                 <p><a href="#" id="aktt_authentication_showhide" class="auth_information_link">Account Information</a></p> 
    1851                 <div id="aktt_authentication_display"> 
    1852                     <fieldset class="options"> 
    1853                         <div class="option"><span class="auth_label">'.__('Twitter Username ', 'twitter-tools').'</span><span class="auth_code">'.$aktt->twitter_username.'</span></div> 
    1854                         <div class="option"><span class="auth_label">'.__('Consumer Key ', 'twitter-tools').'</span><span class="auth_code">'.$aktt->app_consumer_key.'</span></div> 
    1855                         <div class="option"><span class="auth_label">'.__('Consumer Secret ', 'twitter-tools').'</span><span class="auth_code">'.$aktt->app_consumer_secret.'</span></div> 
    1856                         <div class="option"><span class="auth_label">'.__('Access Token ', 'twitter-tools').'</span><span class="auth_code">'.$aktt->oauth_token.'</span></div> 
    1857                         <div class="option"><span class="auth_label">'.__('Access Token Secret ', 'twitter-tools').'</span><span class="auth_code">'.$aktt->oauth_token_secret.'</span></div> 
    1858                     </fieldset> 
    1859                     <p class="submit"> 
    1860                     <input type="submit" name="submit" class="button-primary" value="'.__('Disconnect Your WordPress and Twitter Account', 'twitter-tools').'" /> 
    1861                     </p> 
    1862                     <input type="hidden" name="ak_action" value="aktt_twitter_disconnect" class="hidden" style="display: none;" /> 
    1863                     '.wp_nonce_field('aktt_twitter_disconnect', '_wpnonce', true, false).wp_referer_field(false).'  
    1864                 </div>       
    1865             </form> 
    1866                      
    1867             <form id="ak_twittertools" name="ak_twittertools" action="'.admin_url('options-general.php').'" method="post"> 
    1868                 <fieldset class="options">           
    1869                     <div class="option"> 
    1870                         <label for="aktt_notify_twitter">'.__('Enable option to create a tweet when you post in your blog?', 'twitter-tools').'</label> 
    1871                         <select name="aktt_notify_twitter" id="aktt_notify_twitter">'.$notify_twitter_options.'</select> 
    1872                     </div> 
    1873                     <div class="option"> 
    1874                         <label for="aktt_tweet_prefix">'.__('Tweet prefix for new blog posts:', 'twitter-tools').'</label> 
    1875                         <input type="text" size="30" name="aktt_tweet_prefix" id="aktt_tweet_prefix" value="'.esc_attr($aktt->tweet_prefix).'" /><span>'.__('Cannot be left blank. Will result in <b>{Your prefix}: Title URL</b>', 'twitter-tools').'</span> 
    1876                     </div> 
    1877                     <div class="option"> 
    1878                         <label for="aktt_notify_twitter_default">'.__('Set this on by default?', 'twitter-tools').'</label> 
    1879                         <select name="aktt_notify_twitter_default" id="aktt_notify_twitter_default">'.$notify_twitter_default_options.'</select><span>'                         .__('Also determines tweeting for posting via XML-RPC', 'twitter-tools').'</span> 
    1880                     </div> 
    1881                     <div class="option"> 
    1882                         <label for="aktt_create_blog_posts">'.__('Create a blog post from each of your tweets?', 'twitter-tools').'</label> 
    1883                         <select name="aktt_create_blog_posts" id="aktt_create_blog_posts">'.$create_blog_posts_options.'</select> 
    1884                     </div> 
    1885                     <div class="option"> 
    1886                         <label for="aktt_blog_post_category">'.__('Category for tweet posts:', 'twitter-tools').'</label> 
    1887                         <select name="aktt_blog_post_category" id="aktt_blog_post_category">'.$cat_options.'</select> 
    1888                     </div> 
    1889                     <div class="option"> 
    1890                         <label for="aktt_blog_post_tags">'.__('Tag(s) for your tweet posts:', 'twitter-tools').'</label> 
    1891                         <input name="aktt_blog_post_tags" id="aktt_blog_post_tags" value="'.esc_attr($aktt->blog_post_tags).'"> 
    1892                         <span>'.__('Separate multiple tags with commas. Example: tweets, twitter', 'twitter-tools').'</span> 
    1893                     </div> 
    1894                     <div class="option"> 
    1895                         <label for="aktt_blog_post_author">'.__('Author for tweet posts:', 'twitter-tools').'</label> 
    1896                         <select name="aktt_blog_post_author" id="aktt_blog_post_author">'.$author_options.'</select> 
    1897                     </div> 
    1898                     <div class="option"> 
    1899                         <label for="aktt_exclude_reply_tweets">'.__('Exclude @reply tweets in your sidebar, digests and created blog posts?', 'twitter-tools').'</label> 
    1900                         <select name="aktt_exclude_reply_tweets" id="aktt_exclude_reply_tweets">'.$exclude_reply_tweets_options.'</select> 
    1901                     </div> 
    1902                     <div class="option"> 
    1903                         <label for="aktt_sidebar_tweet_count">'.__('Tweets to show in sidebar:', 'twitter-tools').'</label> 
    1904                         <input type="text" size="3" name="aktt_sidebar_tweet_count" id="aktt_sidebar_tweet_count" value="'.esc_attr($aktt->sidebar_tweet_count).'" /> 
    1905                         <span>'.__('Numbers only please.', 'twitter-tools').'</span> 
    1906                     </div> 
    1907                     <div class="option"> 
    1908                         <label for="aktt_tweet_from_sidebar">'.__('Create tweets from your sidebar?', 'twitter-tools').'</label> 
    1909                         <select name="aktt_tweet_from_sidebar" id="aktt_tweet_from_sidebar">'.$tweet_from_sidebar_options.'</select> 
    1910                     </div> 
    1911                     <div class="option"> 
    1912                         <label for="aktt_js_lib">'.__('JS Library to use?', 'twitter-tools').'</label> 
    1913                         <select name="aktt_js_lib" id="aktt_js_lib">'.$js_lib_options.'</select> 
    1914                     </div> 
    1915                     <div class="option"> 
    1916                         <label for="aktt_give_tt_credit">'.__('Give Twitter Tools credit?', 'twitter-tools').'</label> 
    1917                         <select name="aktt_give_tt_credit" id="aktt_give_tt_credit">'.$give_tt_credit_options.'</select> 
    1918                     </div> 
    1919                  
    1920                     <div class="aktt_experimental"> 
    1921                         <h4>'.__('- Experimental -', 'twitter-tools').'</h4> 
    1922                  
    1923                     <div class="option time_toggle"> 
    1924                         <label>'.__('Create a daily digest blog post from your tweets?', 'twitter-tools').'</label> 
    1925                         <select name="aktt_create_digest" class="toggler">'.$create_digest_options.'</select> 
    1926                         <input type="hidden" class="time" id="aktt_digest_daily_time" name="aktt_digest_daily_time" value="'.esc_attr($aktt->digest_daily_time).'" /> 
    1927                     </div> 
    1928                     <div class="option"> 
    1929                         <label for="aktt_digest_title">'.__('Title for daily digest posts:', 'twitter-tools').'</label> 
    1930                         <input type="text" size="30" name="aktt_digest_title" id="aktt_digest_title" value="'.$aktt->digest_title.'" /> 
    1931                         <span>'.__('Include %s where you want the date. Example: Tweets on %s', 'twitter-tools').'</span> 
    1932                     </div> 
    1933                     <div class="option time_toggle"> 
    1934                         <label>'.__('Create a weekly digest blog post from your tweets?', 'twitter-tools').'</label> 
    1935                         <select name="aktt_create_digest_weekly" class="toggler">'.$create_digest_weekly_options.'</select> 
    1936                         <input type="hidden" class="time" name="aktt_digest_weekly_time" id="aktt_digest_weekly_time" value="'.esc_attr($aktt->digest_weekly_time).'" /> 
    1937                         <input type="hidden" class="day" name="aktt_digest_weekly_day" value="'.$aktt->digest_weekly_day.'" /> 
    1938                     </div> 
    1939                     <div class="option"> 
    1940                         <label for="aktt_digest_title_weekly">'.__('Title for weekly digest posts:', 'twitter-tools').'</label> 
    1941                         <input type="text" size="30" name="aktt_digest_title_weekly" id="aktt_digest_title_weekly" value="'.esc_attr($aktt->digest_title_weekly).'" /> 
    1942                         <span>'.__('Include %s where you want the date. Example: Tweets on %s', 'twitter-tools').'</span> 
    1943                     </div> 
    1944                     <div class="option"> 
    1945                         <label for="aktt_digest_tweet_order">'.__('Order of tweets in digest?', 'twitter-tools').'</label> 
    1946                         <select name="aktt_digest_tweet_order" id="aktt_digest_tweet_order">'.$digest_tweet_order_options.'</select> 
    1947                     </div> 
    1948                  
    1949                     </div> 
    1950                  
    1951                 </fieldset> 
    1952                 <p class="submit"> 
    1953                     <input type="submit" name="submit" class="button-primary" value="'.__('Update Twitter Tools Options', 'twitter-tools').'" /> 
    1954                 </p> 
    1955                 <input type="hidden" name="ak_action" value="aktt_update_settings" class="hidden" style="display: none;" /> 
    1956                 '.wp_nonce_field('aktt_settings', '_wpnonce', true, false).wp_referer_field(false).' 
    1957             </form> 
    1958             <h2>'.__('Update Tweets / Reset Checking and Digests', 'twitter-tools').'</h2> 
    1959             <form name="ak_twittertools_updatetweets" action="'.admin_url('options-general.php').'" method="get"> 
    1960                 <p>'.__('Use these buttons to manually update your tweets or reset the checking settings.', 'twitter-tools').'</p> 
    1961                 <p class="submit"> 
    1962                     <input type="submit" name="submit-button" value="'.__('Update Tweets', 'twitter-tools').'" /> 
    1963                     <input type="submit" name="reset-button-1" value="'.__('Reset Tweet Checking', 'twitter-tools').'" onclick="document.getElementById(\'ak_action_2\').value = \'aktt_reset_tweet_checking\';" /> 
    1964                     <input type="submit" name="reset-button-2" value="'.__('Reset Digests', 'twitter-tools').'" onclick="document.getElementById(\'ak_action_2\').value = \'aktt_reset_digests\';" /> 
    1965                     <input type="hidden" name="ak_action" id="ak_action_2" value="aktt_update_tweets" /> 
    1966                 </p> 
    1967                 '.wp_nonce_field('aktt_update_tweets', '_wpnonce', true, false).wp_referer_field(false).' 
    1968             </form> 
    1969     '); 
    1970     } //end elsif statement 
    1971     do_action('aktt_options_form'); 
    1972 ?> 
    1973     <div id="cf"> 
    1974         <div id="cf-callouts"> 
    1975             <div class="cf-callout"> 
    1976                 <div id="cf-callout-credit" class="cf-box"> 
    1977                     <h3 class="cf-box-title">Plugin Developed By</h3> 
    1978                     <div class="cf-box-content"> 
    1979                         <p class="txt-center"><a href="http://crowdfavorite.com/" title="Crowd Favorite : Elegant WordPress and Web Application Development"><img src="http://cloud.wphelpcenter.com/resources/wp-admin-0001/cf-logo.png" alt="Crowd Favorite"></a></p> 
    1980                         <p>An independent development firm specializing in WordPress development and integrations, sophisticated web applications, Open Source implementations and user experience consulting. If you need it to work, trust Crowd Favorite to build it.</p> 
    1981                     </div><!-- .cf-box-content --> 
    1982                 </div><!-- #cf-callout-credit -->                        
    1983             </div> 
    1984             <div class="cf-callout"> 
    1985                 <div id="cf-callout-support" class="cf-box"> 
    1986                     <h3 class="cf-box-title">Professional Support From</h3> 
    1987                     <div class="cf-box-content"> 
    1988                         <p class="txt-center"><a href="http://wphelpcenter.com/" title="WordPress HelpCenter"><img src="http://cloud.wphelpcenter.com/resources/wp-admin-0001/wphc-logo.png" alt="WordPress HelpCenter"></a></p> 
    1989                         <p>Need help with WordPress right now? That's what we're here for. We can help with anything from how-to questions to server troubleshooting, theme customization to upgrades and installs. Give us a call - 303-395-1346.</p> 
    1990                     </div><!-- .cf-box-content --> 
    1991                 </div><!-- #cf-callout-support -->                       
    1992             </div> 
    1993         </div><!-- #cf-callouts --> 
    1994     </div><!-- #cf --> 
    1995 <?php 
    1996     print(' 
    1997                  
    1998             </div> 
    1999     '); 
    2000 } 
    2001  
    2002 function aktt_meta_box() { 
    2003     global $aktt, $post; 
    2004     if ($aktt->notify_twitter) { 
    2005         $notify = get_post_meta($post->ID, 'aktt_notify_twitter', true); 
    2006         if ($notify == '') { 
    2007             switch ($aktt->notify_twitter_default) { 
    2008                 case '1': 
    2009                     $notify = 'yes'; 
    2010                     break; 
    2011                 case '0': 
    2012                     $notify = 'no'; 
    2013                     break; 
    2014             } 
    2015         } 
    2016         echo ' 
    2017             <p>'.__('Send post to Twitter?', 'twitter-tools').' 
    2018         &nbsp; 
    2019         <input type="radio" name="aktt_notify_twitter" id="aktt_notify_twitter_yes" value="yes" '.checked('yes', $notify, false).' /> <label for="aktt_notify_twitter_yes">'.__('Yes', 'twitter-tools').'</label> &nbsp;&nbsp; 
    2020         <input type="radio" name="aktt_notify_twitter" id="aktt_notify_twitter_no" value="no" '.checked('no', $notify, false).' /> <label for="aktt_notify_twitter_no">'.__('No', 'twitter-tools').'</label> 
    2021         '; 
    2022         echo ' 
    2023             </p> 
    2024         '; 
    2025         do_action('aktt_post_options'); 
    2026     } 
    2027 } 
    2028 function aktt_add_meta_box() { 
    2029     global $aktt; 
    2030     if ($aktt->notify_twitter) { 
    2031         add_meta_box('aktt_post_form', __('Twitter Tools', 'twitter-tools'), 'aktt_meta_box', 'post', 'side'); 
    2032     } 
    2033 } 
    2034 add_action('admin_init', 'aktt_add_meta_box'); 
    2035  
    2036 function aktt_store_post_options($post_id, $post = false) { 
    2037     global $aktt; 
    2038     $post = get_post($post_id); 
    2039     if (!$post || $post->post_type == 'revision') { 
    2040         return; 
    2041     } 
    2042  
    2043     $notify_meta = get_post_meta($post_id, 'aktt_notify_twitter', true); 
    2044     $posted_meta = $_POST['aktt_notify_twitter']; 
    2045  
    2046     $save = false; 
    2047     if (!empty($posted_meta)) { 
    2048         $posted_meta == 'yes' ? $meta = 'yes' : $meta = 'no'; 
    2049         $save = true; 
    2050     } 
    2051     else if (empty($notify_meta)) { 
    2052         $aktt->notify_twitter_default ? $meta = 'yes' : $meta = 'no'; 
    2053         $save = true; 
    2054     } 
    2055      
    2056     if ($save) { 
    2057         update_post_meta($post_id, 'aktt_notify_twitter', $meta); 
    2058     } 
    2059 } 
    2060 add_action('draft_post', 'aktt_store_post_options', 1, 2); 
    2061 add_action('publish_post', 'aktt_store_post_options', 1, 2); 
    2062 add_action('save_post', 'aktt_store_post_options', 1, 2); 
    2063  
    2064 function aktt_menu_items() { 
    2065     if (current_user_can('manage_options')) { 
    2066         add_options_page( 
    2067             __('Twitter Tools Options', 'twitter-tools') 
    2068             , __('Twitter Tools', 'twitter-tools') 
    2069             , 10 
    2070             , basename(__FILE__) 
    2071             , 'aktt_options_form' 
    2072         ); 
    2073     } 
    2074     if (current_user_can('publish_posts')) { 
    2075         add_submenu_page( 
    2076             'post-new.php' 
    2077             , __('New Tweet', 'twitter-tools') 
    2078             , __('Tweet', 'twitter-tools') 
    2079             , 2 
    2080             , basename(__FILE__) 
    2081             , 'aktt_admin_tweet_form' 
    2082         ); 
    2083     } 
    2084 } 
    2085 add_action('admin_menu', 'aktt_menu_items'); 
    2086  
    2087 function aktt_plugin_action_links($links, $file) { 
    2088     $plugin_file = basename(__FILE__); 
    2089     if (basename($file) == $plugin_file) { 
    2090         $settings_link = '<a href="options-general.php?page='.$plugin_file.'">'.__('Settings', 'twitter-tools').'</a>'; 
    2091         array_unshift($links, $settings_link); 
    2092     } 
    2093     return $links; 
    2094 } 
    2095 add_filter('plugin_action_links', 'aktt_plugin_action_links', 10, 2); 
    2096  
    2097 if (!function_exists('trim_add_elipsis')) { 
    2098     function trim_add_elipsis($string, $limit = 100) { 
    2099         if (strlen($string) > $limit) { 
    2100             $string = substr($string, 0, $limit)."..."; 
    2101         } 
    2102         return $string; 
    2103     } 
    2104 } 
    2105  
    2106 if (!function_exists('ak_gmmktime')) { 
    2107     function ak_gmmktime() { 
    2108         return gmmktime() - get_option('gmt_offset') * 3600; 
    2109     } 
    2110 } 
    2111  
    2112 /** 
    2113  
    2114 based on: http://www.gyford.com/phil/writing/2006/12/02/quick_twitter.php 
    2115  
    2116      * Returns a relative date, eg "4 hrs ago". 
    2117      * 
    2118      * Assumes the passed-in can be parsed by strtotime. 
    2119      * Precision could be one of: 
    2120      *  1   5 hours, 3 minutes, 2 seconds ago (not yet implemented). 
    2121      *  2   5 hours, 3 minutes 
    2122      *  3   5 hours 
    2123      * 
    2124      * This is all a little overkill, but copied from other places I've used it. 
    2125      * Also superfluous, now I've noticed that the Twitter API includes something 
    2126      * similar, but this version is more accurate and less verbose. 
    2127      * 
    2128      * @access private. 
    2129      * @param string date In a format parseable by strtotime(). 
    2130      * @param integer precision 
    2131      * @return string 
    2132      */ 
    2133 function aktt_relativeTime ($date, $precision=2) 
    2134 { 
    2135  
    2136     $now = time(); 
    2137  
    2138     $time = gmmktime( 
    2139         substr($date, 11, 2) 
    2140         , substr($date, 14, 2) 
    2141         , substr($date, 17, 2) 
    2142         , substr($date, 5, 2) 
    2143         , substr($date, 8, 2) 
    2144         , substr($date, 0, 4) 
    2145     ); 
    2146  
    2147     $time = strtotime(date('Y-m-d H:i:s', $time)); 
    2148  
    2149     $diff   =  $now - $time; 
    2150  
    2151     $months =  floor($diff/2419200); 
    2152     $diff   -= $months * 2419200; 
    2153     $weeks  =  floor($diff/604800); 
    2154     $diff   -= $weeks*604800; 
    2155     $days   =  floor($diff/86400); 
    2156     $diff   -= $days * 86400; 
    2157     $hours  =  floor($diff/3600); 
    2158     $diff   -= $hours * 3600; 
    2159     $minutes = floor($diff/60); 
    2160     $diff   -= $minutes * 60; 
    2161     $seconds = $diff; 
    2162  
    2163     if ($months > 0) { 
    2164         return date_i18n( __('Y-m-d', 'twitter-tools'), $time); 
    2165     } else { 
    2166         $relative_date = ''; 
    2167         if ($weeks > 0) { 
    2168             // Weeks and days 
    2169             $relative_date .= ($relative_date?', ':'').$weeks.' '.__ngettext('week', 'weeks', $weeks, 'twitter-tools'); 
    2170             if ($precision <= 2) { 
    2171                 $relative_date .= $days>0? ($relative_date?', ':'').$days.' '.__ngettext('day', 'days', $days, 'twitter-tools'):''; 
    2172                 if ($precision == 1) { 
    2173                     $relative_date .= $hours>0?($relative_date?', ':'').$hours.' '.__ngettext('hr', 'hrs', $hours, 'twitter-tools'):''; 
    2174                 } 
    2175             } 
    2176         } elseif ($days > 0) { 
    2177             // days and hours 
    2178             $relative_date .= ($relative_date?', ':'').$days.' '.__ngettext('day', 'days', $days, 'twitter-tools'); 
    2179             if ($precision <= 2) { 
    2180                 $relative_date .= $hours>0?($relative_date?', ':'').$hours.' '.__ngettext('hr', 'hrs', $hours, 'twitter-tools'):''; 
    2181                 if ($precision == 1) { 
    2182                     $relative_date .= $minutes>0?($relative_date?', ':'').$minutes.' '.__ngettext('min', 'mins', $minutes, 'twitter-tools'):''; 
    2183                 } 
    2184             } 
    2185         } elseif ($hours > 0) { 
    2186             // hours and minutes 
    2187             $relative_date .= ($relative_date?', ':'').$hours.' '.__ngettext('hr', 'hrs', $hours, 'twitter-tools'); 
    2188             if ($precision <= 2) { 
    2189                 $relative_date .= $minutes>0?($relative_date?', ':'').$minutes.' '.__ngettext('min', 'mins', $minutes, 'twitter-tools'):''; 
    2190                 if ($precision == 1) { 
    2191                     $relative_date .= $seconds>0?($relative_date?', ':'').$seconds.' '.__ngettext('sec', 'secs', $seconds, 'twitter-tools'):''; 
    2192                 } 
    2193             } 
    2194         } elseif ($minutes > 0) { 
    2195             // minutes only 
    2196             $relative_date .= ($relative_date?', ':'').$minutes.' '.__ngettext('min', 'mins', $minutes, 'twitter-tools'); 
    2197             if ($precision == 1) { 
    2198                 $relative_date .= $seconds>0?($relative_date?', ':'').$seconds.' '.__ngettext('sec', 'secs', $seconds, 'twitter-tools'):''; 
    2199             } 
    2200         } else { 
    2201             // seconds only 
    2202             $relative_date .= ($relative_date?', ':'').$seconds.' '.__ngettext('sec', 'secs', $seconds, 'twitter-tools'); 
    2203         } 
    2204     } 
    2205  
    2206     // Return relative date and add proper verbiage 
    2207     return sprintf(__('%s ago', 'twitter-tools'), $relative_date); 
    2208 } 
    2209  
    2210 ?> 
Note: See TracChangeset for help on using the changeset viewer.