' . $args['after_widget'];
}
/**
* Gets tweets, from cache if possible
*
* @param array $widgetOptions - options needed to get feeds
* @return array - Array of objects
*/
private function _getTweets($widgetOptions) {
$feedHash = sha1($this->_getFeedUrl($widgetOptions));
$tweets = get_option("wptw-{$feedHash}");
$cacheAge = get_option("wptw-{$feedHash}-time");
//If we don't have cache or it's more than 5 minutes old
if ( empty($tweets) || (time() - $cacheAge) > 300 ) {
try {
$tweets = $this->_parseFeed($widgetOptions);
update_option("wptw-{$feedHash}", $tweets);
update_option("wptw-{$feedHash}-time", time());
} catch (wpTwitterWidgetException $e) {
throw $e;
}
}
return $tweets;
}
/**
* Pulls the JSON feed from Twitter and returns an array of objects
*
* @param array $widgetOptions - settings needed to get feed url, etc
* @return array
*/
private function _parseFeed($widgetOptions) {
$feedUrl = $this->_getFeedUrl($widgetOptions);
$resp = wp_remote_request($feedUrl, array('timeout' => $widgetOptions['fetchTimeOut']));
if ( !is_wp_error($resp) && $resp['response']['code'] >= 200 && $resp['response']['code'] < 300 ) {
if (function_exists('json_decode')) {
$decodedResponse = json_decode( $resp['body'] );
} else {
global $wp_json;
if ( !is_a($wp_json, 'Services_JSON') ) {
require_once( 'class-json.php' );
$wp_json = new Services_JSON();
}
$decodedResponse = $wp_json->decode( $resp['body'] );
}
if ( empty($decodedResponse) ) {
if (empty($widgetOptions['errmsg'])) {
$widgetOptions['errmsg'] = __('Invalid Twitter Response.', 'twitter-widget-pro');
}
throw new wpTwitterWidgetException($widgetOptions['errmsg']);
} elseif( !empty($decodedResponse->error) ) {
if (empty($widgetOptions['errmsg'])) {
$widgetOptions['errmsg'] = $decodedResponse->error;
}
throw new wpTwitterWidgetException($widgetOptions['errmsg']);
} else {
return $decodedResponse;
}
} else {
// Failed to fetch url;
if (empty($widgetOptions['errmsg'])) {
$widgetOptions['errmsg'] = __('Could not connect to Twitter', 'twitter-widget-pro');
}
throw new wpTwitterWidgetException($widgetOptions['errmsg']);
}
}
/**
* Gets the URL for the desired feed.
*
* @param array $widgetOptions - settings needed such as username, feet type, etc
* @param string[optional] $type - 'rss' or 'json'
* @param bool[optional] $count - If true, it adds the count parameter to the URL
* @return string - Twitter feed URL
*/
private function _getFeedUrl($widgetOptions, $type = 'json', $count = true) {
if (!in_array($type, array('rss', 'json'))) {
$type = 'json';
}
if ( $count ) {
$num = ($widgetOptions['hidereplies'])? 100:$widgetOptions['items'];
$count = sprintf('?count=%u', $num);
} else {
$count = '';
}
return sprintf('http://twitter.com/statuses/user_timeline/%1$s.%2$s%3$s', $widgetOptions['username'], $type, $count);
}
/**
* Twitter displays all tweets that are less than 24 with something like
* "about 4 hours ago" and ones older than 24 hours with a time and date.
* This function allows us to simulate that functionality, but lets us
* choose where the dividing line is.
*
* @param int $startTimestamp - The timestamp used to calculate time passed
* @param int $max - Max number of seconds to conver to "ago" messages. 0 for all, -1 for none
* @return string
*/
private function _timeSince($startTimestamp, $max) {
// array of time period chunks
$chunks = array(
'year' => 60 * 60 * 24 * 365, // 31,536,000 seconds
'month' => 60 * 60 * 24 * 30, // 2,592,000 seconds
'week' => 60 * 60 * 24 * 7, // 604,800 seconds
'day' => 60 * 60 * 24, // 86,400 seconds
'hour' => 60 * 60, // 3600 seconds
'minute' => 60, // 60 seconds
'second' => 1 // 1 second
);
$since = time() - $startTimestamp;
if ($max != '-1' && $since >= $max) {
return date_i18n('h:i:s A F d, Y', $startTimestamp);
}
foreach ( $chunks as $key => $seconds ) {
// finding the biggest chunk (if the chunk fits, break)
if (($count = floor($since / $seconds)) != 0) {
break;
}
}
$messages = array(
'year' => _n('about %s year ago', 'about %s years ago', $count, 'twitter-widget-pro'),
'month' => _n('about %s month ago', 'about %s months ago', $count, 'twitter-widget-pro'),
'week' => _n('about %s week ago', 'about %s weeks ago', $count, 'twitter-widget-pro'),
'day' => _n('about %s day ago', 'about %s days ago', $count, 'twitter-widget-pro'),
'hour' => _n('about %s hour ago', 'about %s hours ago', $count, 'twitter-widget-pro'),
'minute' => _n('about %s minute ago', 'about %s minutes ago', $count, 'twitter-widget-pro'),
'second' => _n('about %s second ago', 'about %s seconds ago', $count, 'twitter-widget-pro'),
);
return sprintf($messages[$key], $count);
}
/**
* Returns the Twitter user's profile image, linked to that user's profile
*
* @param object $user - Twitter User
* @return string - Linked image (XHTML)
*/
private function _getProfileImage($user) {
return <<
profileImage;
}
}
/**
* wpTwitterWidget is the class that handles everything outside the widget. This
* includes filters that modify tweet content for things like linked usernames.
* It also helps us avoid name collisions.
*/
class wpTwitterWidget
{
/**
* @var array Plugin settings
*/
private $_settings;
/**
* Plugin file to test against on plugins page
*
* @var string
*/
private $_pluginBasename;
/**
* Repository base url
*
* @since 1.4.4
* @var string
*/
private $_reposUrl = 'http://plugins.svn.wordpress.org/';
public function __construct() {
/**
* Add filters and actions
*/
add_action( 'admin_menu', array($this,'admin_menu') );
add_filter( 'init', array( $this, 'init_locale') );
add_filter( 'admin_init', array( $this, 'registerSettings') );
add_filter( 'admin_init', array( $this, 'sendSysInfo') );
add_action( 'widgets_init', array($this, 'register') );
add_filter( 'widget_twitter_content', array($this, 'linkTwitterUsers') );
add_filter( 'widget_twitter_content', array($this, 'linkUrls') );
add_filter( 'widget_twitter_content', array($this, 'linkHashtags') );
add_filter( 'widget_twitter_content', 'convert_chars' );
add_filter( 'plugin_action_links', array($this, 'addSettingLink'), 10, 2 );
add_action ( 'in_plugin_update_message-'.plugin_basename ( __FILE__ ) , array ( $this , '_changelog' ), null, 2 );
}
public function registerSettings() {
register_setting( 'twitter_widget_pro_options', 'twitter_widget_pro' );
}
public function admin_menu() {
add_options_page(__('Twitter Widget Pro', 'twitter-widget-pro'), __('Twitter Widget Pro', 'twitter-widget-pro'), 'manage_options', 'TwitterWidgetPro', array($this, 'options'));
}
public function init_locale() {
$lang_dir = basename(dirname(__FILE__)) . '/languages';
load_plugin_textdomain('twitter-widget-pro', 'wp-content/plugins/' . $lang_dir, $lang_dir);
}
/**
* This is used to display the options page for this plugin
*/
public function options() {
//Get our options
$this->_getSettings();
?>
_reposUrl}/{$newPluginData->slug}/tags/{$newPluginData->new_version}/upgrade.html";
$response = wp_remote_get ( $url );
$code = (int) wp_remote_retrieve_response_code ( $response );
if ( $code == 200 ) {
echo wp_remote_retrieve_body ( $response );
}
}
/**
* Returns the user's screen name as a link inside strong tags.
*
* @param object $user - Twitter user
* @return string - Username as link (XHTML)
*/
private function _getUserName($user) {
return <<{$user->screen_name}
profileImage;
}
/**
* if user agrees to send system information and the last sent info is
* outdated then send the stats
*/
public function sendSysInfo() {
$this->_getSettings();
if ($this->_settings['user_agreed_to_send_system_information'] == 'true') {
$lastSent = get_option('twp-sysinfo');
$sysinfo = $this->_get_sysinfo();
if (serialize($lastSent) != serialize($sysinfo)) {
$params = array(
'method' => 'POST',
'blocking' => false,
'body' => $sysinfo,
);
$resp = wp_remote_request( 'http://xavisys.com/plugin-info.php', $params );
update_option( 'twp-sysinfo', $sysinfo );
}
}
}
private function _get_sysinfo() {
global $wpdb;
$pluginData = get_plugin_data(__FILE__);
$s = array();
$s['plugin'] = $pluginData['Name'];
$s['id'] = $this->_get_id($pluginData['Name']);
$s['version'] = $pluginData['Version'];
$s['php_version'] = phpversion();
$s['mysql_version'] = @mysql_get_server_info($wpdb->dbh);
$s['server_software'] = $_SERVER["SERVER_SOFTWARE"];
$s['memory_limit'] = ini_get('memory_limit');
return $s;
}
private function _get_id($name) {
$this->_getSettings();
if ( empty($this->_settings['sysinfo-id']) ) {
$this->_settings['sysinfo-id'] = sha1( get_bloginfo('url') . $name );
$this->_updateSettings();
}
return $this->_settings['sysinfo-id'];
}
private function _updateSettings() {
update_option('twitter_widget_pro', $this->_settings);
}
private function _getSettings() {
$defaults = array(
);
$this->_settings = get_option('twitter_widget_pro');
$this->_settings = wp_parse_args($this->_settings, $defaults);
}
public function addSettingLink( $links, $file ){
if ( empty($this->_pluginBasename) ) {
$this->_pluginBasename = plugin_basename(__FILE__);
}
if ( $file == $this->_pluginBasename ) {
// Add settings link to our plugin
$link = '' . __('Settings', 'twitter-widget-pro') . '';
array_unshift( $links, $link );
}
return $links;
}
/**
* Replace @username with a link to that twitter user
*
* @param string $text - Tweet text
* @return string - Tweet text with @replies linked
*/
public function linkTwitterUsers($text) {
$text = preg_replace('/(^|\s)@(\w*)/i', '$1@$2', $text);
return $text;
}
/**
* Replace #hashtag with a link to search.twitter.com for that hashtag
*
* @param string $text - Tweet text
* @return string - Tweet text with #hashtags linked
*/
public function linkHashtags($text) {
$text = preg_replace_callback('/(^|\s)(#\w*)/i', array($this, '_hashtagLink'), $text);
return $text;
}
/**
* Replace #hashtag with a link to search.twitter.com for that hashtag
*
* @param array $matches - Tweet text
* @return string - Tweet text with #hashtags linked
*/
private function _hashtagLink($matches) {
return "{$matches[1]}{$matches[2]}";
}
/**
* Turn URLs into links
*
* @param string $text - Tweet text
* @return string - Tweet text with URLs repalced with links
*/
public function linkUrls($text) {
/**
* match protocol://address/path/file.extension?some=variable&another=asf%
* $1 is a possible space, this keeps us from linking href="[link]" etc
* $2 is the whole URL
* $3 is protocol://
* $4 is the URL without the protocol://
* $5 is the URL parameters
*/
$text = preg_replace("/(^|\s)(([a-zA-Z]+:\/\/)([a-z][a-z0-9_\..-]*[a-z]{2,6})([a-zA-Z0-9~\/*-?&%]*))/i", "$1$2", $text);
/**
* match www.something.domain/path/file.extension?some=variable&another=asf%
* $1 is a possible space, this keeps us from linking href="[link]" etc
* $2 is the whole URL that was matched. The protocol is missing, so we assume http://
* $3 is www.
* $4 is the URL matched without the www.
* $5 is the URL parameters
*/
$text = preg_replace("/(^|\s)(www\.([a-z][a-z0-9_\..-]*[a-z]{2,6})([a-zA-Z0-9~\/*-?&%]*))/i", "$1$2", $text);
return $text;
}
function register() {
register_widget('WP_Widget_Twitter_Pro');
}
}
// Instantiate our class
$wpTwitterWidget = new wpTwitterWidget();