Rotating Tweets (Twitter widget and shortcode) - Version 1.3.12

Version Description

Includes an important upgrade needed for Rotating Tweets to keep working after March 2013. Supports version 1.1 of the Twitter API. Fixed problem with hashtags.

=

Download this release

Release Info

Developer mpntod
Plugin Icon wp plugin Rotating Tweets (Twitter widget and shortcode)
Version 1.3.12
Comparing to
See all releases

Code changes from version 1.3.11 to 1.3.12

js/rotating_tweet.js CHANGED
@@ -36,6 +36,7 @@ jQuery(document).ready(function() {
36
  pause: 1,
37
  height: rt_height_px,
38
  timeout: rotate_timeout,
 
39
  width: rt_target_width,
40
  fx: rotate_fx,
41
  fit: rt_fit
@@ -62,6 +63,7 @@ jQuery(document).ready(function() {
62
  height: rt_height_px,
63
  timeout: rotate_timeout,
64
  width: rt_target_width,
 
65
  fit: rt_fit,
66
  fx: rotate_fx
67
  });
36
  pause: 1,
37
  height: rt_height_px,
38
  timeout: rotate_timeout,
39
+ cleartypeNoBg: true,
40
  width: rt_target_width,
41
  fx: rotate_fx,
42
  fit: rt_fit
63
  height: rt_height_px,
64
  timeout: rotate_timeout,
65
  width: rt_target_width,
66
+ cleartypeNoBg: true,
67
  fit: rt_fit,
68
  fx: rotate_fx
69
  });
lib/{OAuth.php → WP_OAuth.php} RENAMED
@@ -3,11 +3,11 @@
3
 
4
  /* Generic exception class
5
  */
6
- class OAuthException extends Exception {
7
  // pass
8
  }
9
 
10
- class OAuthConsumer {
11
  public $key;
12
  public $secret;
13
 
@@ -18,11 +18,11 @@ class OAuthConsumer {
18
  }
19
 
20
  function __toString() {
21
- return "OAuthConsumer[key=$this->key,secret=$this->secret]";
22
  }
23
  }
24
 
25
- class OAuthToken {
26
  // access tokens and request tokens
27
  public $key;
28
  public $secret;
@@ -42,9 +42,9 @@ class OAuthToken {
42
  */
43
  function to_string() {
44
  return "oauth_token=" .
45
- OAuthUtil::urlencode_rfc3986($this->key) .
46
  "&oauth_token_secret=" .
47
- OAuthUtil::urlencode_rfc3986($this->secret);
48
  }
49
 
50
  function __toString() {
@@ -56,7 +56,7 @@ class OAuthToken {
56
  * A class for implementing a Signature Method
57
  * See section 9 ("Signing Requests") in the spec
58
  */
59
- abstract class OAuthSignatureMethod {
60
  /**
61
  * Needs to return the name of the Signature Method (ie HMAC-SHA1)
62
  * @return string
@@ -66,20 +66,20 @@ abstract class OAuthSignatureMethod {
66
  /**
67
  * Build up the signature
68
  * NOTE: The output of this function MUST NOT be urlencoded.
69
- * the encoding is handled in OAuthRequest when the final
70
  * request is serialized
71
- * @param OAuthRequest $request
72
- * @param OAuthConsumer $consumer
73
- * @param OAuthToken $token
74
  * @return string
75
  */
76
  abstract public function build_signature($request, $consumer, $token);
77
 
78
  /**
79
  * Verifies that a given signature is correct
80
- * @param OAuthRequest $request
81
- * @param OAuthConsumer $consumer
82
- * @param OAuthToken $token
83
  * @param string $signature
84
  * @return bool
85
  */
@@ -96,7 +96,7 @@ abstract class OAuthSignatureMethod {
96
  * character (ASCII code 38) even if empty.
97
  * - Chapter 9.2 ("HMAC-SHA1")
98
  */
99
- class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {
100
  function get_name() {
101
  return "HMAC-SHA1";
102
  }
@@ -110,7 +110,7 @@ class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {
110
  ($token) ? $token->secret : ""
111
  );
112
 
113
- $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
114
  $key = implode('&', $key_parts);
115
 
116
  return base64_encode(hash_hmac('sha1', $base_string, $key, true));
@@ -122,7 +122,7 @@ class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {
122
  * over a secure channel such as HTTPS. It does not use the Signature Base String.
123
  * - Chapter 9.4 ("PLAINTEXT")
124
  */
125
- class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod {
126
  public function get_name() {
127
  return "PLAINTEXT";
128
  }
@@ -134,7 +134,7 @@ class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod {
134
  * - Chapter 9.4.1 ("Generating Signatures")
135
  *
136
  * Please note that the second encoding MUST NOT happen in the SignatureMethod, as
137
- * OAuthRequest handles this!
138
  */
139
  public function build_signature($request, $consumer, $token) {
140
  $key_parts = array(
@@ -142,7 +142,7 @@ class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod {
142
  ($token) ? $token->secret : ""
143
  );
144
 
145
- $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
146
  $key = implode('&', $key_parts);
147
  $request->base_string = $key;
148
 
@@ -158,7 +158,7 @@ class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod {
158
  * specification.
159
  * - Chapter 9.3 ("RSA-SHA1")
160
  */
161
- abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {
162
  public function get_name() {
163
  return "RSA-SHA1";
164
  }
@@ -217,7 +217,7 @@ abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {
217
  }
218
  }
219
 
220
- class OAuthRequest {
221
  private $parameters;
222
  private $http_method;
223
  private $http_url;
@@ -228,7 +228,7 @@ class OAuthRequest {
228
 
229
  function __construct($http_method, $http_url, $parameters=NULL) {
230
  @$parameters or $parameters = array();
231
- $parameters = array_merge( OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters);
232
  $this->parameters = $parameters;
233
  $this->http_method = $http_method;
234
  $this->http_url = $http_url;
@@ -255,10 +255,10 @@ class OAuthRequest {
255
  // parsed parameter-list
256
  if (!$parameters) {
257
  // Find request headers
258
- $request_headers = OAuthUtil::get_headers();
259
 
260
  // Parse the query-string to find GET parameters
261
- $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']);
262
 
263
  // It's a POST request of the proper content-type, so parse POST
264
  // parameters and add those overriding any duplicates from GET
@@ -266,16 +266,16 @@ class OAuthRequest {
266
  && @strstr($request_headers["Content-Type"],
267
  "application/x-www-form-urlencoded")
268
  ) {
269
- $post_data = OAuthUtil::parse_parameters(
270
  file_get_contents(self::$POST_INPUT)
271
  );
272
  $parameters = array_merge($parameters, $post_data);
273
  }
274
 
275
- // We have a Authorization-header with OAuth data. Parse the header
276
  // and add those overriding any duplicates from GET or POST
277
  if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") {
278
- $header_parameters = OAuthUtil::split_header(
279
  $request_headers['Authorization']
280
  );
281
  $parameters = array_merge($parameters, $header_parameters);
@@ -283,7 +283,7 @@ class OAuthRequest {
283
 
284
  }
285
 
286
- return new OAuthRequest($http_method, $http_url, $parameters);
287
  }
288
 
289
  /**
@@ -291,16 +291,16 @@ class OAuthRequest {
291
  */
292
  public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {
293
  @$parameters or $parameters = array();
294
- $defaults = array("oauth_version" => OAuthRequest::$version,
295
- "oauth_nonce" => OAuthRequest::generate_nonce(),
296
- "oauth_timestamp" => OAuthRequest::generate_timestamp(),
297
  "oauth_consumer_key" => $consumer->key);
298
  if ($token)
299
  $defaults['oauth_token'] = $token->key;
300
 
301
  $parameters = array_merge($defaults, $parameters);
302
 
303
- return new OAuthRequest($http_method, $http_url, $parameters);
304
  }
305
 
306
  public function set_parameter($name, $value, $allow_duplicates = true) {
@@ -344,7 +344,7 @@ class OAuthRequest {
344
  unset($params['oauth_signature']);
345
  }
346
 
347
- return OAuthUtil::build_http_query($params);
348
  }
349
 
350
  /**
@@ -361,7 +361,7 @@ class OAuthRequest {
361
  $this->get_signable_parameters()
362
  );
363
 
364
- $parts = OAuthUtil::urlencode_rfc3986($parts);
365
 
366
  return implode('&', $parts);
367
  }
@@ -410,7 +410,7 @@ class OAuthRequest {
410
  * builds the data one would send in a POST request
411
  */
412
  public function to_postdata() {
413
- return OAuthUtil::build_http_query($this->parameters);
414
  }
415
 
416
  /**
@@ -419,7 +419,7 @@ class OAuthRequest {
419
  public function to_header($realm=null) {
420
  $first = true;
421
  if($realm) {
422
- $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"';
423
  $first = false;
424
  } else
425
  $out = 'Authorization: OAuth';
@@ -428,12 +428,12 @@ class OAuthRequest {
428
  foreach ($this->parameters as $k => $v) {
429
  if (substr($k, 0, 5) != "oauth") continue;
430
  if (is_array($v)) {
431
- throw new OAuthException('Arrays not supported in headers');
432
  }
433
  $out .= ($first) ? ' ' : ',';
434
- $out .= OAuthUtil::urlencode_rfc3986($k) .
435
  '="' .
436
- OAuthUtil::urlencode_rfc3986($v) .
437
  '"';
438
  $first = false;
439
  }
@@ -478,7 +478,7 @@ class OAuthRequest {
478
  }
479
  }
480
 
481
- class OAuthServer {
482
  protected $timestamp_threshold = 300; // in seconds, five minutes
483
  protected $version = '1.0'; // hi blaine
484
  protected $signature_methods = array();
@@ -561,7 +561,7 @@ class OAuthServer {
561
  $version = '1.0';
562
  }
563
  if ($version !== $this->version) {
564
- throw new OAuthException("OAuth version '$version' not supported");
565
  }
566
  return $version;
567
  }
@@ -576,12 +576,12 @@ class OAuthServer {
576
  if (!$signature_method) {
577
  // According to chapter 7 ("Accessing Protected Ressources") the signature-method
578
  // parameter is required, and we can't just fallback to PLAINTEXT
579
- throw new OAuthException('No signature method parameter. This parameter is required');
580
  }
581
 
582
  if (!in_array($signature_method,
583
  array_keys($this->signature_methods))) {
584
- throw new OAuthException(
585
  "Signature method '$signature_method' not supported " .
586
  "try one of the following: " .
587
  implode(", ", array_keys($this->signature_methods))
@@ -596,12 +596,12 @@ class OAuthServer {
596
  private function get_consumer(&$request) {
597
  $consumer_key = @$request->get_parameter("oauth_consumer_key");
598
  if (!$consumer_key) {
599
- throw new OAuthException("Invalid consumer key");
600
  }
601
 
602
  $consumer = $this->data_store->lookup_consumer($consumer_key);
603
  if (!$consumer) {
604
- throw new OAuthException("Invalid consumer");
605
  }
606
 
607
  return $consumer;
@@ -616,7 +616,7 @@ class OAuthServer {
616
  $consumer, $token_type, $token_field
617
  );
618
  if (!$token) {
619
- throw new OAuthException("Invalid $token_type token: $token_field");
620
  }
621
  return $token;
622
  }
@@ -644,7 +644,7 @@ class OAuthServer {
644
  );
645
 
646
  if (!$valid_sig) {
647
- throw new OAuthException("Invalid signature");
648
  }
649
  }
650
 
@@ -653,14 +653,14 @@ class OAuthServer {
653
  */
654
  private function check_timestamp($timestamp) {
655
  if( ! $timestamp )
656
- throw new OAuthException(
657
  'Missing timestamp parameter. The parameter is required'
658
  );
659
 
660
  // verify that timestamp is recentish
661
  $now = time();
662
  if (abs($now - $timestamp) > $this->timestamp_threshold) {
663
- throw new OAuthException(
664
  "Expired timestamp, yours $timestamp, ours $now"
665
  );
666
  }
@@ -671,7 +671,7 @@ class OAuthServer {
671
  */
672
  private function check_nonce($consumer, $token, $nonce, $timestamp) {
673
  if( ! $nonce )
674
- throw new OAuthException(
675
  'Missing nonce parameter. The parameter is required'
676
  );
677
 
@@ -683,13 +683,13 @@ class OAuthServer {
683
  $timestamp
684
  );
685
  if ($found) {
686
- throw new OAuthException("Nonce already used: $nonce");
687
  }
688
  }
689
 
690
  }
691
 
692
- class OAuthDataStore {
693
  function lookup_consumer($consumer_key) {
694
  // implement me
695
  }
@@ -715,10 +715,10 @@ class OAuthDataStore {
715
 
716
  }
717
 
718
- class OAuthUtil {
719
  public static function urlencode_rfc3986($input) {
720
  if (is_array($input)) {
721
- return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input);
722
  } else if (is_scalar($input)) {
723
  return str_replace(
724
  '+',
@@ -750,7 +750,7 @@ class OAuthUtil {
750
  $header_name = $matches[2][0];
751
  $header_content = (isset($matches[5])) ? $matches[5][0] : $matches[4][0];
752
  if (preg_match('/^oauth_/', $header_name) || !$only_allow_oauth_parameters) {
753
- $params[$header_name] = OAuthUtil::urldecode_rfc3986($header_content);
754
  }
755
  $offset = $match[1] + strlen($match[0]);
756
  }
@@ -819,8 +819,8 @@ class OAuthUtil {
819
  $parsed_parameters = array();
820
  foreach ($pairs as $pair) {
821
  $split = explode('=', $pair, 2);
822
- $parameter = OAuthUtil::urldecode_rfc3986($split[0]);
823
- $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : '';
824
 
825
  if (isset($parsed_parameters[$parameter])) {
826
  // We have already recieved parameter(s) with this name, so add to the list
@@ -844,8 +844,8 @@ class OAuthUtil {
844
  if (!$params) return '';
845
 
846
  // Urlencode both keys and values
847
- $keys = OAuthUtil::urlencode_rfc3986(array_keys($params));
848
- $values = OAuthUtil::urlencode_rfc3986(array_values($params));
849
  $params = array_combine($keys, $values);
850
 
851
  // Parameters are sorted by name, using lexicographical byte value ordering.
3
 
4
  /* Generic exception class
5
  */
6
+ class WP_OAuthException extends Exception {
7
  // pass
8
  }
9
 
10
+ class WP_OAuthConsumer {
11
  public $key;
12
  public $secret;
13
 
18
  }
19
 
20
  function __toString() {
21
+ return "WP_OAuthConsumer[key=$this->key,secret=$this->secret]";
22
  }
23
  }
24
 
25
+ class WP_OAuthToken {
26
  // access tokens and request tokens
27
  public $key;
28
  public $secret;
42
  */
43
  function to_string() {
44
  return "oauth_token=" .
45
+ WP_OAuthUtil::urlencode_rfc3986($this->key) .
46
  "&oauth_token_secret=" .
47
+ WP_OAuthUtil::urlencode_rfc3986($this->secret);
48
  }
49
 
50
  function __toString() {
56
  * A class for implementing a Signature Method
57
  * See section 9 ("Signing Requests") in the spec
58
  */
59
+ abstract class WP_OAuthSignatureMethod {
60
  /**
61
  * Needs to return the name of the Signature Method (ie HMAC-SHA1)
62
  * @return string
66
  /**
67
  * Build up the signature
68
  * NOTE: The output of this function MUST NOT be urlencoded.
69
+ * the encoding is handled in WP_OAuthRequest when the final
70
  * request is serialized
71
+ * @param WP_OAuthRequest $request
72
+ * @param WP_OAuthConsumer $consumer
73
+ * @param WP_OAuthToken $token
74
  * @return string
75
  */
76
  abstract public function build_signature($request, $consumer, $token);
77
 
78
  /**
79
  * Verifies that a given signature is correct
80
+ * @param WP_OAuthRequest $request
81
+ * @param WP_OAuthConsumer $consumer
82
+ * @param WP_OAuthToken $token
83
  * @param string $signature
84
  * @return bool
85
  */
96
  * character (ASCII code 38) even if empty.
97
  * - Chapter 9.2 ("HMAC-SHA1")
98
  */
99
+ class WP_OAuthSignatureMethod_HMAC_SHA1 extends WP_OAuthSignatureMethod {
100
  function get_name() {
101
  return "HMAC-SHA1";
102
  }
110
  ($token) ? $token->secret : ""
111
  );
112
 
113
+ $key_parts = WP_OAuthUtil::urlencode_rfc3986($key_parts);
114
  $key = implode('&', $key_parts);
115
 
116
  return base64_encode(hash_hmac('sha1', $base_string, $key, true));
122
  * over a secure channel such as HTTPS. It does not use the Signature Base String.
123
  * - Chapter 9.4 ("PLAINTEXT")
124
  */
125
+ class WP_OAuthSignatureMethod_PLAINTEXT extends WP_OAuthSignatureMethod {
126
  public function get_name() {
127
  return "PLAINTEXT";
128
  }
134
  * - Chapter 9.4.1 ("Generating Signatures")
135
  *
136
  * Please note that the second encoding MUST NOT happen in the SignatureMethod, as
137
+ * WP_OAuthRequest handles this!
138
  */
139
  public function build_signature($request, $consumer, $token) {
140
  $key_parts = array(
142
  ($token) ? $token->secret : ""
143
  );
144
 
145
+ $key_parts = WP_OAuthUtil::urlencode_rfc3986($key_parts);
146
  $key = implode('&', $key_parts);
147
  $request->base_string = $key;
148
 
158
  * specification.
159
  * - Chapter 9.3 ("RSA-SHA1")
160
  */
161
+ abstract class WP_OAuthSignatureMethod_RSA_SHA1 extends WP_OAuthSignatureMethod {
162
  public function get_name() {
163
  return "RSA-SHA1";
164
  }
217
  }
218
  }
219
 
220
+ class WP_OAuthRequest {
221
  private $parameters;
222
  private $http_method;
223
  private $http_url;
228
 
229
  function __construct($http_method, $http_url, $parameters=NULL) {
230
  @$parameters or $parameters = array();
231
+ $parameters = array_merge( WP_OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters);
232
  $this->parameters = $parameters;
233
  $this->http_method = $http_method;
234
  $this->http_url = $http_url;
255
  // parsed parameter-list
256
  if (!$parameters) {
257
  // Find request headers
258
+ $request_headers = WP_OAuthUtil::get_headers();
259
 
260
  // Parse the query-string to find GET parameters
261
+ $parameters = WP_OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']);
262
 
263
  // It's a POST request of the proper content-type, so parse POST
264
  // parameters and add those overriding any duplicates from GET
266
  && @strstr($request_headers["Content-Type"],
267
  "application/x-www-form-urlencoded")
268
  ) {
269
+ $post_data = WP_OAuthUtil::parse_parameters(
270
  file_get_contents(self::$POST_INPUT)
271
  );
272
  $parameters = array_merge($parameters, $post_data);
273
  }
274
 
275
+ // We have a Authorization-header with WP_OAuth data. Parse the header
276
  // and add those overriding any duplicates from GET or POST
277
  if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") {
278
+ $header_parameters = WP_OAuthUtil::split_header(
279
  $request_headers['Authorization']
280
  );
281
  $parameters = array_merge($parameters, $header_parameters);
283
 
284
  }
285
 
286
+ return new WP_OAuthRequest($http_method, $http_url, $parameters);
287
  }
288
 
289
  /**
291
  */
292
  public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {
293
  @$parameters or $parameters = array();
294
+ $defaults = array("oauth_version" => WP_OAuthRequest::$version,
295
+ "oauth_nonce" => WP_OAuthRequest::generate_nonce(),
296
+ "oauth_timestamp" => WP_OAuthRequest::generate_timestamp(),
297
  "oauth_consumer_key" => $consumer->key);
298
  if ($token)
299
  $defaults['oauth_token'] = $token->key;
300
 
301
  $parameters = array_merge($defaults, $parameters);
302
 
303
+ return new WP_OAuthRequest($http_method, $http_url, $parameters);
304
  }
305
 
306
  public function set_parameter($name, $value, $allow_duplicates = true) {
344
  unset($params['oauth_signature']);
345
  }
346
 
347
+ return WP_OAuthUtil::build_http_query($params);
348
  }
349
 
350
  /**
361
  $this->get_signable_parameters()
362
  );
363
 
364
+ $parts = WP_OAuthUtil::urlencode_rfc3986($parts);
365
 
366
  return implode('&', $parts);
367
  }
410
  * builds the data one would send in a POST request
411
  */
412
  public function to_postdata() {
413
+ return WP_OAuthUtil::build_http_query($this->parameters);
414
  }
415
 
416
  /**
419
  public function to_header($realm=null) {
420
  $first = true;
421
  if($realm) {
422
+ $out = 'Authorization: OAuth realm="' . WP_OAuthUtil::urlencode_rfc3986($realm) . '"';
423
  $first = false;
424
  } else
425
  $out = 'Authorization: OAuth';
428
  foreach ($this->parameters as $k => $v) {
429
  if (substr($k, 0, 5) != "oauth") continue;
430
  if (is_array($v)) {
431
+ throw new WP_OAuthException('Arrays not supported in headers');
432
  }
433
  $out .= ($first) ? ' ' : ',';
434
+ $out .= WP_OAuthUtil::urlencode_rfc3986($k) .
435
  '="' .
436
+ WP_OAuthUtil::urlencode_rfc3986($v) .
437
  '"';
438
  $first = false;
439
  }
478
  }
479
  }
480
 
481
+ class WP_OAuthServer {
482
  protected $timestamp_threshold = 300; // in seconds, five minutes
483
  protected $version = '1.0'; // hi blaine
484
  protected $signature_methods = array();
561
  $version = '1.0';
562
  }
563
  if ($version !== $this->version) {
564
+ throw new WP_OAuthException("OAuth version '$version' not supported");
565
  }
566
  return $version;
567
  }
576
  if (!$signature_method) {
577
  // According to chapter 7 ("Accessing Protected Ressources") the signature-method
578
  // parameter is required, and we can't just fallback to PLAINTEXT
579
+ throw new WP_OAuthException('No signature method parameter. This parameter is required');
580
  }
581
 
582
  if (!in_array($signature_method,
583
  array_keys($this->signature_methods))) {
584
+ throw new WP_OAuthException(
585
  "Signature method '$signature_method' not supported " .
586
  "try one of the following: " .
587
  implode(", ", array_keys($this->signature_methods))
596
  private function get_consumer(&$request) {
597
  $consumer_key = @$request->get_parameter("oauth_consumer_key");
598
  if (!$consumer_key) {
599
+ throw new WP_OAuthException("Invalid consumer key");
600
  }
601
 
602
  $consumer = $this->data_store->lookup_consumer($consumer_key);
603
  if (!$consumer) {
604
+ throw new WP_OAuthException("Invalid consumer");
605
  }
606
 
607
  return $consumer;
616
  $consumer, $token_type, $token_field
617
  );
618
  if (!$token) {
619
+ throw new WP_OAuthException("Invalid $token_type token: $token_field");
620
  }
621
  return $token;
622
  }
644
  );
645
 
646
  if (!$valid_sig) {
647
+ throw new WP_OAuthException("Invalid signature");
648
  }
649
  }
650
 
653
  */
654
  private function check_timestamp($timestamp) {
655
  if( ! $timestamp )
656
+ throw new WP_OAuthException(
657
  'Missing timestamp parameter. The parameter is required'
658
  );
659
 
660
  // verify that timestamp is recentish
661
  $now = time();
662
  if (abs($now - $timestamp) > $this->timestamp_threshold) {
663
+ throw new WP_OAuthException(
664
  "Expired timestamp, yours $timestamp, ours $now"
665
  );
666
  }
671
  */
672
  private function check_nonce($consumer, $token, $nonce, $timestamp) {
673
  if( ! $nonce )
674
+ throw new WP_OAuthException(
675
  'Missing nonce parameter. The parameter is required'
676
  );
677
 
683
  $timestamp
684
  );
685
  if ($found) {
686
+ throw new WP_OAuthException("Nonce already used: $nonce");
687
  }
688
  }
689
 
690
  }
691
 
692
+ class WP_OAuthDataStore {
693
  function lookup_consumer($consumer_key) {
694
  // implement me
695
  }
715
 
716
  }
717
 
718
+ class WP_OAuthUtil {
719
  public static function urlencode_rfc3986($input) {
720
  if (is_array($input)) {
721
+ return array_map(array('WP_OAuthUtil', 'urlencode_rfc3986'), $input);
722
  } else if (is_scalar($input)) {
723
  return str_replace(
724
  '+',
750
  $header_name = $matches[2][0];
751
  $header_content = (isset($matches[5])) ? $matches[5][0] : $matches[4][0];
752
  if (preg_match('/^oauth_/', $header_name) || !$only_allow_oauth_parameters) {
753
+ $params[$header_name] = WP_OAuthUtil::urldecode_rfc3986($header_content);
754
  }
755
  $offset = $match[1] + strlen($match[0]);
756
  }
819
  $parsed_parameters = array();
820
  foreach ($pairs as $pair) {
821
  $split = explode('=', $pair, 2);
822
+ $parameter = WP_OAuthUtil::urldecode_rfc3986($split[0]);
823
+ $value = isset($split[1]) ? WP_OAuthUtil::urldecode_rfc3986($split[1]) : '';
824
 
825
  if (isset($parsed_parameters[$parameter])) {
826
  // We have already recieved parameter(s) with this name, so add to the list
844
  if (!$params) return '';
845
 
846
  // Urlencode both keys and values
847
+ $keys = WP_OAuthUtil::urlencode_rfc3986(array_keys($params));
848
+ $values = WP_OAuthUtil::urlencode_rfc3986(array_values($params));
849
  $params = array_combine($keys, $values);
850
 
851
  // Parameters are sorted by name, using lexicographical byte value ordering.
lib/wp_twitteroauth.php CHANGED
@@ -3,19 +3,19 @@
3
  /*
4
  * Abraham Williams (abraham@abrah.am) http://abrah.am
5
  *
6
- * The first PHP Library to support OAuth for Twitter's REST API.
7
  *
8
  * Updated to reflect v 1.1 of the Twitter API by Liam Gladdy at Storm Consultancy (hello@stormconsultancy) http://www.stormconsultancy.co.uk
9
  *
10
- * Further tweaked for Wordpress to cope with (likely) multiple installations of OAuth and use the wp_remote_request() function by Martin Tod (martin@martintod.org.uk) http://www.martintod.org.uk
11
  *
12
  */
13
 
14
- /* Load OAuth lib. You can find it at http://oauth.net */
15
- if(!class_exists('OAuthException')) require_once('OAuth.php');
16
 
17
  /**
18
- * Twitter OAuth class
19
  */
20
  class wp_TwitterOAuth {
21
  /* Contains the last HTTP status code returned. */
@@ -62,10 +62,10 @@ class wp_TwitterOAuth {
62
  * construct TwitterOAuth object
63
  */
64
  function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) {
65
- $this->sha1_method = new OAuthSignatureMethod_HMAC_SHA1();
66
- $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret);
67
  if (!empty($oauth_token) && !empty($oauth_token_secret)) {
68
- $this->token = new OAuthConsumer($oauth_token, $oauth_token_secret);
69
  } else {
70
  $this->token = NULL;
71
  }
@@ -83,8 +83,8 @@ class wp_TwitterOAuth {
83
  $parameters['oauth_callback'] = $oauth_callback;
84
  }
85
  $request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters);
86
- $token = OAuthUtil::parse_parameters($request);
87
- $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
88
  return $token;
89
  }
90
 
@@ -119,8 +119,8 @@ class wp_TwitterOAuth {
119
  $parameters['oauth_verifier'] = $oauth_verifier;
120
  }
121
  $request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters);
122
- $token = OAuthUtil::parse_parameters($request);
123
- $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
124
  return $token;
125
  }
126
 
@@ -139,8 +139,8 @@ class wp_TwitterOAuth {
139
  $parameters['x_auth_password'] = $password;
140
  $parameters['x_auth_mode'] = 'client_auth';
141
  $request = $this->oAuthRequest($this->accessTokenURL(), 'POST', $parameters);
142
- $token = OAuthUtil::parse_parameters($request);
143
- $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
144
  return $token;
145
  }
146
 
@@ -178,13 +178,13 @@ class wp_TwitterOAuth {
178
  }
179
 
180
  /**
181
- * Format and sign an OAuth / API request
182
  */
183
  function oAuthRequest($url, $method, $parameters) {
184
  if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) {
185
  $url = "{$this->host}{$url}.{$this->format}";
186
  }
187
- $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters);
188
  $request->sign_request($this->sha1_method, $this->consumer, $this->token);
189
  switch ($method) {
190
  case 'GET':
3
  /*
4
  * Abraham Williams (abraham@abrah.am) http://abrah.am
5
  *
6
+ * The first PHP Library to support WP_OAuth for Twitter's REST API.
7
  *
8
  * Updated to reflect v 1.1 of the Twitter API by Liam Gladdy at Storm Consultancy (hello@stormconsultancy) http://www.stormconsultancy.co.uk
9
  *
10
+ * Further tweaked for Wordpress to cope with (likely) multiple installations of WP_OAuth and use the wp_remote_request() function by Martin Tod (martin@martintod.org.uk) http://www.martintod.org.uk
11
  *
12
  */
13
 
14
+ /* Load WP_OAuth lib. You can find it at http://oauth.net */
15
+ if(!class_exists('WP_OAuthException')) require_once('WP_OAuth.php');
16
 
17
  /**
18
+ * Twitter WP_OAuth class
19
  */
20
  class wp_TwitterOAuth {
21
  /* Contains the last HTTP status code returned. */
62
  * construct TwitterOAuth object
63
  */
64
  function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) {
65
+ $this->sha1_method = new WP_OAuthSignatureMethod_HMAC_SHA1();
66
+ $this->consumer = new WP_OAuthConsumer($consumer_key, $consumer_secret);
67
  if (!empty($oauth_token) && !empty($oauth_token_secret)) {
68
+ $this->token = new WP_OAuthConsumer($oauth_token, $oauth_token_secret);
69
  } else {
70
  $this->token = NULL;
71
  }
83
  $parameters['oauth_callback'] = $oauth_callback;
84
  }
85
  $request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters);
86
+ $token = WP_OAuthUtil::parse_parameters($request);
87
+ $this->token = new WP_OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
88
  return $token;
89
  }
90
 
119
  $parameters['oauth_verifier'] = $oauth_verifier;
120
  }
121
  $request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters);
122
+ $token = WP_OAuthUtil::parse_parameters($request);
123
+ $this->token = new WP_OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
124
  return $token;
125
  }
126
 
139
  $parameters['x_auth_password'] = $password;
140
  $parameters['x_auth_mode'] = 'client_auth';
141
  $request = $this->oAuthRequest($this->accessTokenURL(), 'POST', $parameters);
142
+ $token = WP_OAuthUtil::parse_parameters($request);
143
+ $this->token = new WP_OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
144
  return $token;
145
  }
146
 
178
  }
179
 
180
  /**
181
+ * Format and sign an WP_OAuth / API request
182
  */
183
  function oAuthRequest($url, $method, $parameters) {
184
  if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) {
185
  $url = "{$this->host}{$url}.{$this->format}";
186
  }
187
+ $request = WP_OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters);
188
  $request->sign_request($this->sha1_method, $this->consumer, $this->token);
189
  switch ($method) {
190
  case 'GET':
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: shortcode,widget,twitter,rotating,rotate,rotator,tweet,tweets,animation,jquery,jquery cycle,cycle,multilingual
5
  Requires at least: 2.6
6
  Tested up to: 3.5
7
- Stable tag: 1.3.11
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -12,7 +12,7 @@ Twitter widget and shortcode to show your latest tweets one at a time an animate
12
 
13
  == Description ==
14
  * **Replaces a [shortcode](http://codex.wordpress.org/Shortcode) such as `[rotatingtweets screen_name='your_twitter']`, or a [widget](http://codex.wordpress.org/WordPress_Widgets), with a rotating display of your most recent tweets**
15
- * **Supports v 1.1 of the API** - yes! it will keep working after March 2013
16
  * **Space efficient** - instead of showing all your tweets at once, shows one at a time and then smoothly replaces it with the next one. After showing all your tweets, loops back to the beginning again.
17
  * **Reliable** - keeps showing your latest Tweets even if the Twitter website is down.
18
  * **Customisable** - you decide whose tweets to show, how many to show, whether to include retweets and replies, and whether to show a follow button. You can also decide how quickly the tweets rotate and what type of animation to use.
@@ -23,14 +23,15 @@ Twitter widget and shortcode to show your latest tweets one at a time an animate
23
  * **Multi-lingual** - now set up to be multi-lingual. The Twitter 'follow' button is automatically translated to match your site's language setting [if Twitter has made the appropriate language available](https://dev.twitter.com/docs/api/1.1/get/help/languages). Also uses [Wordpress's multi-lingual capability](http://codex.wordpress.org/I18n_for_WordPress_Developers) to enable translation of all the other text used by the plug-in via language packs.
24
 
25
  Currently the following languages are available:
 
26
  * US English *(complete)*
27
  * British English *(complete - mainly changing 'favorite' to 'favourite'!)*
28
  * German *(basic tweet display only)*
29
- * Spanish *(tweet display only)*
30
- * Italian *(tweet display only)*
31
- * Dutch *(tweet display only)*
32
 
33
- If you have made the plug-in work in your language, please send the [gettext PO and MO files](http://codex.wordpress.org/I18n_for_WordPress_Developers) to [me](http://www.martintod.org.uk/contact-martin/) and I will then share them with everyone else. You can download [the latest POT file](http://plugins.svn.wordpress.org/rotatingtweets/trunk/languages/rotatingtweets.pot), and [PO files in each language](http://plugins.svn.wordpress.org/rotatingtweets/trunk/languages/) from this site. You may find [Poedit](http://www.poedit.net/) rather useful for translation and creation of PO and MO files.
34
 
35
  If you'd like to see what the plug-in looks like in action, you can [see the plug-in working here](http://www.martintod.org.uk/2012/05/29/new-twitter-plugin-to-show-tweets-in-rotation/).
36
 
@@ -69,7 +70,9 @@ Possible variables for the shortcode include:
69
  * `show_meta_reply_retweet_favorite` = `'0'` or `'1'` - show 'reply', 'retweet' and 'favorite' buttons - optional - default is `'0'`
70
  * `links_in_new_window` = `'0'` or `'1'` - show links in a new tab or window - default is `'0'`
71
  * `rotation_type` = any of the options listed on the [jQuery.cycle website](http://jquery.malsup.com/cycle/browser.html) - default is `'scrollUp'`
 
72
  * `url_length` = sets the length that the URL should be trimmed to...
 
73
 
74
  although the only one you *have* to have is `screen_name`.
75
 
@@ -90,7 +93,7 @@ In most cases, each use (or "instance") of this plug-in gets data from Twitter e
90
  You can do this by going to the `rotatingtweets/css` directory and renaming `yourstyle-sample.css` to `yourstyle.css`. This displays a Twitter bird to the left of your tweets. Any CSS you put into `yourstyle.css` won't be overwritten when the plug-in is upgraded to the latest version.
91
 
92
  = The Rotating Tweets are not rotating. What can I do? =
93
- This normally happens if there is more than one copy of jQuery installed on a page - or more than one copy of jQuery.cycle.
94
 
95
  To see if this is the case, you can search the HTML on your website to see if either script is called more than once. The quickest way is to search the page for `jquery` and look out for lines that contain `jquery.min.js` or `jquery.cycle.all.min.js`.
96
 
@@ -98,11 +101,15 @@ The problem is that the second (or third) copy of the script overwrites all prev
98
 
99
  If this is the case, the first thing to check is that you have upgraded your template or your plug-in to the latest version.
100
 
 
101
  == Upgrade notice ==
102
- = 1.3.11 =
103
  Includes an important upgrade needed for Rotating Tweets to keep working after March 2013. Supports version 1.1 of the Twitter API. Fixed problem with hashtags.
104
 
105
  == Changelog ==
 
 
 
106
  = 1.3.11 =
107
  Supports cyrillic hashtags!
108
 
4
  Tags: shortcode,widget,twitter,rotating,rotate,rotator,tweet,tweets,animation,jquery,jquery cycle,cycle,multilingual
5
  Requires at least: 2.6
6
  Tested up to: 3.5
7
+ Stable tag: 1.3.12
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
12
 
13
  == Description ==
14
  * **Replaces a [shortcode](http://codex.wordpress.org/Shortcode) such as `[rotatingtweets screen_name='your_twitter']`, or a [widget](http://codex.wordpress.org/WordPress_Widgets), with a rotating display of your most recent tweets**
15
+ * **Supports v 1.1 of the Twitter API** - yes! it will keep working after March 2013
16
  * **Space efficient** - instead of showing all your tweets at once, shows one at a time and then smoothly replaces it with the next one. After showing all your tweets, loops back to the beginning again.
17
  * **Reliable** - keeps showing your latest Tweets even if the Twitter website is down.
18
  * **Customisable** - you decide whose tweets to show, how many to show, whether to include retweets and replies, and whether to show a follow button. You can also decide how quickly the tweets rotate and what type of animation to use.
23
  * **Multi-lingual** - now set up to be multi-lingual. The Twitter 'follow' button is automatically translated to match your site's language setting [if Twitter has made the appropriate language available](https://dev.twitter.com/docs/api/1.1/get/help/languages). Also uses [Wordpress's multi-lingual capability](http://codex.wordpress.org/I18n_for_WordPress_Developers) to enable translation of all the other text used by the plug-in via language packs.
24
 
25
  Currently the following languages are available:
26
+
27
  * US English *(complete)*
28
  * British English *(complete - mainly changing 'favorite' to 'favourite'!)*
29
  * German *(basic tweet display only)*
30
+ * Spanish *(basic tweet display only)*
31
+ * Italian *(basic tweet display only)*
32
+ * Dutch *(basic tweet display only)*
33
 
34
+ If you have made the plug-in work in your language, please send the translations you'd like to see or, even better, the relevant [gettext PO and MO files](http://codex.wordpress.org/I18n_for_WordPress_Developers) to [me](http://www.martintod.org.uk/contact-martin/) and I will then share them with everyone else. You can download [the latest POT file](http://plugins.svn.wordpress.org/rotatingtweets/trunk/languages/rotatingtweets.pot), and [PO files in each language](http://plugins.svn.wordpress.org/rotatingtweets/trunk/languages/) from this site. You may find [Poedit](http://www.poedit.net/) rather useful for translation and creation of PO and MO files.
35
 
36
  If you'd like to see what the plug-in looks like in action, you can [see the plug-in working here](http://www.martintod.org.uk/2012/05/29/new-twitter-plugin-to-show-tweets-in-rotation/).
37
 
70
  * `show_meta_reply_retweet_favorite` = `'0'` or `'1'` - show 'reply', 'retweet' and 'favorite' buttons - optional - default is `'0'`
71
  * `links_in_new_window` = `'0'` or `'1'` - show links in a new tab or window - default is `'0'`
72
  * `rotation_type` = any of the options listed on the [jQuery.cycle website](http://jquery.malsup.com/cycle/browser.html) - default is `'scrollUp'`
73
+ * `get_favorites` = `'0'` or `'1'` - show someone's favorites rather than their timeline - default is `'0'`
74
  * `url_length` = sets the length that the URL should be trimmed to...
75
+ * `url` = Twitter user URL. If `screen_name` is empty and this link is valid, `screen_name` will be set to the user name included in `url`
76
 
77
  although the only one you *have* to have is `screen_name`.
78
 
93
  You can do this by going to the `rotatingtweets/css` directory and renaming `yourstyle-sample.css` to `yourstyle.css`. This displays a Twitter bird to the left of your tweets. Any CSS you put into `yourstyle.css` won't be overwritten when the plug-in is upgraded to the latest version.
94
 
95
  = The Rotating Tweets are not rotating. What can I do? =
96
+ This normally happens if there is more than one copy of `jQuery` installed on a page - or more than one copy of `jQuery.cycle`.
97
 
98
  To see if this is the case, you can search the HTML on your website to see if either script is called more than once. The quickest way is to search the page for `jquery` and look out for lines that contain `jquery.min.js` or `jquery.cycle.all.min.js`.
99
 
101
 
102
  If this is the case, the first thing to check is that you have upgraded your template or your plug-in to the latest version.
103
 
104
+ If this still doesn't work, please let me know which plug-in or template is causing the problem and I'll see if I can build a fix into the next version of Rotating Tweets.
105
  == Upgrade notice ==
106
+ = 1.3.12 =
107
  Includes an important upgrade needed for Rotating Tweets to keep working after March 2013. Supports version 1.1 of the Twitter API. Fixed problem with hashtags.
108
 
109
  == Changelog ==
110
+ = 1.3.12 =
111
+ Removes accents from screen names (and otherwise cleans them up). Add test option (currently for shortcodes only) to access favorites. Solves clash between PECL OAuth library and the Rotating Tweets OAuth library.
112
+
113
  = 1.3.11 =
114
  Supports cyrillic hashtags!
115
 
rotatingtweets.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Rotating Tweets (Twitter widget & shortcode)
4
  Description: Replaces a shortcode such as [rotatingtweets screen_name='your_twitter_name'], or a widget, with a rotating tweets display
5
- Version: 1.3.11
6
  Text Domain: rotatingtweets
7
  Author: Martin Tod
8
  Author URI: http://www.martintod.org.uk
@@ -375,6 +375,7 @@ function rotatingtweets_display_shortcode( $atts, $content=null, $code="", $prin
375
  'official_format' => FALSE,
376
  'links_in_new_window' => FALSE,
377
  'url_length' => 29,
 
378
  'ratelimit' => FALSE
379
  ), $atts ) ;
380
  extract($args);
@@ -388,7 +389,7 @@ function rotatingtweets_display_shortcode( $atts, $content=null, $code="", $prin
388
  if(empty($screen_name)) $screen_name = 'twitter';
389
  # Makes sure the scripts are listed
390
  rotatingtweets_enqueue_scripts();
391
- $tweets = rotatingtweets_get_tweets($screen_name,$include_rts,$exclude_replies);
392
  $returnstring = rotating_tweets_display($tweets,$args,$print);
393
  return $returnstring;
394
  }
@@ -566,13 +567,19 @@ function rotatingtweets_call_twitter_API($command,$options = NULL,$api = NULL )
566
  }
567
 
568
  # Get the latest data from Twitter (or from a cache if it's been less than 2 minutes since the last load)
569
- function rotatingtweets_get_tweets($tw_screen_name,$tw_include_rts,$tw_exclude_replies) {
570
  # Clear up variables
 
571
  $cache_delay = 120;
572
  if($tw_include_rts != 1) $tw_include_rts = 0;
573
  if($tw_exclude_replies != 1) $tw_exclude_replies = 0;
 
574
  # Get the option strong
575
- $stringname = $tw_screen_name.$tw_include_rts.$tw_exclude_replies;
 
 
 
 
576
  $optionname = "rotatingtweets-cache";
577
  $option = get_option($optionname);
578
  # Attempt to deal with 'Cannot use string offset as an array' error
@@ -602,7 +609,11 @@ function rotatingtweets_get_tweets($tw_screen_name,$tw_include_rts,$tw_exclude_r
602
  # Checks if it is time to call Twitter directly yet or if it should use the cache
603
  if($timegap > $cache_delay):
604
  $apioptions = array('screen_name'=>$tw_screen_name,'include_entities'=>1,'count'=>70,'include_rts'=>$tw_include_rts,'exclude_replies'=>$tw_exclude_replies);
605
- $twitterdata = rotatingtweets_call_twitter_API('statuses/user_timeline',$apioptions);
 
 
 
 
606
  if(!is_wp_error($twitterdata)):
607
  $twitterjson = json_decode($twitterdata['body'],TRUE);
608
  if(WP_DEBUG):
@@ -765,7 +776,6 @@ function rotating_tweets_display($json,$args,$print=TRUE) {
765
  $id = uniqid('rotatingtweets_'.$timeout.'_'.$rotation_type.'_');
766
  if(WP_DEBUG):
767
  $result = "\n<div class='rotatingtweets wp_debug' id='$id'>";
768
-
769
  else:
770
  $result = "\n<div class='rotatingtweets' id='$id'>";
771
  endif;
@@ -984,12 +994,12 @@ function rotating_tweets_display($json,$args,$print=TRUE) {
984
  $result .= "</div>";
985
  endif;
986
  */
987
- if($args['show_follow'] && !empty($user['screen_name'])):
988
  $shortenvariables = '';
989
  if($args['no_show_count']) $shortenvariables = ' data-show-count="false"';
990
  if($args['no_show_screen_name']) $shortenvariables .= ' data-show-screen-name="false"';
991
- $followUserText = sprintf(__('Follow @%s','rotatingtweets'),$user['screen_name']);
992
- $result .= "\n<div class='rtw_follow follow-button'><a href='http://twitter.com/".$user['screen_name']."' class='twitter-follow-button'{$shortenvariables} title='".$followUserText."' data-lang='{$twitterlocale}'>".$followUserText."</a></div>";
993
  endif;
994
  rotatingtweets_enqueue_scripts();
995
  if($print) echo $result;
2
  /*
3
  Plugin Name: Rotating Tweets (Twitter widget & shortcode)
4
  Description: Replaces a shortcode such as [rotatingtweets screen_name='your_twitter_name'], or a widget, with a rotating tweets display
5
+ Version: 1.3.12
6
  Text Domain: rotatingtweets
7
  Author: Martin Tod
8
  Author URI: http://www.martintod.org.uk
375
  'official_format' => FALSE,
376
  'links_in_new_window' => FALSE,
377
  'url_length' => 29,
378
+ 'get_favorites' => FALSE,
379
  'ratelimit' => FALSE
380
  ), $atts ) ;
381
  extract($args);
389
  if(empty($screen_name)) $screen_name = 'twitter';
390
  # Makes sure the scripts are listed
391
  rotatingtweets_enqueue_scripts();
392
+ $tweets = rotatingtweets_get_tweets($screen_name,$include_rts,$exclude_replies,$get_favorites);
393
  $returnstring = rotating_tweets_display($tweets,$args,$print);
394
  return $returnstring;
395
  }
567
  }
568
 
569
  # Get the latest data from Twitter (or from a cache if it's been less than 2 minutes since the last load)
570
+ function rotatingtweets_get_tweets($tw_screen_name,$tw_include_rts,$tw_exclude_replies,$tw_get_favorites = FALSE) {
571
  # Clear up variables
572
+ $tw_screen_name = urlencode(trim(remove_accents($tw_screen_name)));
573
  $cache_delay = 120;
574
  if($tw_include_rts != 1) $tw_include_rts = 0;
575
  if($tw_exclude_replies != 1) $tw_exclude_replies = 0;
576
+
577
  # Get the option strong
578
+ if($tw_get_favorites) {
579
+ $stringname = $tw_screen_name.$tw_include_rts.$tw_exclude_replies.'favorites';
580
+ } else {
581
+ $stringname = $tw_screen_name.$tw_include_rts.$tw_exclude_replies;
582
+ }
583
  $optionname = "rotatingtweets-cache";
584
  $option = get_option($optionname);
585
  # Attempt to deal with 'Cannot use string offset as an array' error
609
  # Checks if it is time to call Twitter directly yet or if it should use the cache
610
  if($timegap > $cache_delay):
611
  $apioptions = array('screen_name'=>$tw_screen_name,'include_entities'=>1,'count'=>70,'include_rts'=>$tw_include_rts,'exclude_replies'=>$tw_exclude_replies);
612
+ if($tw_get_favorites) {
613
+ $twitterdata = rotatingtweets_call_twitter_API('favorites/list',$apioptions);
614
+ } else {
615
+ $twitterdata = rotatingtweets_call_twitter_API('statuses/user_timeline',$apioptions);
616
+ }
617
  if(!is_wp_error($twitterdata)):
618
  $twitterjson = json_decode($twitterdata['body'],TRUE);
619
  if(WP_DEBUG):
776
  $id = uniqid('rotatingtweets_'.$timeout.'_'.$rotation_type.'_');
777
  if(WP_DEBUG):
778
  $result = "\n<div class='rotatingtweets wp_debug' id='$id'>";
 
779
  else:
780
  $result = "\n<div class='rotatingtweets' id='$id'>";
781
  endif;
994
  $result .= "</div>";
995
  endif;
996
  */
997
+ if($args['show_follow'] && !empty($args['screen_name'])):
998
  $shortenvariables = '';
999
  if($args['no_show_count']) $shortenvariables = ' data-show-count="false"';
1000
  if($args['no_show_screen_name']) $shortenvariables .= ' data-show-screen-name="false"';
1001
+ $followUserText = sprintf(__('Follow @%s','rotatingtweets'),$args['screen_name']);
1002
+ $result .= "\n<div class='rtw_follow follow-button'><a href='http://twitter.com/".$args['screen_name']."' class='twitter-follow-button'{$shortenvariables} title='".$followUserText."' data-lang='{$twitterlocale}'>".$followUserText."</a></div>";
1003
  endif;
1004
  rotatingtweets_enqueue_scripts();
1005
  if($print) echo $result;