Version Description
- Completely rewitten to use the new widget class introduced in WordPress 2.8
- Now uses the json class that will be included in WordPress 2.9 for anyone on PHP < 5.2
- The "Show Link to Twitter Widget Pro" is now off by default to comply with the latest decisions regarding the plugin repository
Download this release
Release Info
Developer | aaroncampbell |
Plugin | Twitter Widget Pro |
Version | 2.0.0 |
Comparing to | |
See all releases |
Code changes from version 1.5.1 to 2.0.0
- class-json.php +860 -0
- json_decode.php +0 -392
- languages/twitter-widget-pro.pot +106 -86
- readme.txt +8 -3
- upgrade.html +4 -1
- wp-twitter-widget.php +416 -494
class-json.php
ADDED
@@ -0,0 +1,860 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
3 |
+
/**
|
4 |
+
* Converts to and from JSON format.
|
5 |
+
*
|
6 |
+
* JSON (JavaScript Object Notation) is a lightweight data-interchange
|
7 |
+
* format. It is easy for humans to read and write. It is easy for machines
|
8 |
+
* to parse and generate. It is based on a subset of the JavaScript
|
9 |
+
* Programming Language, Standard ECMA-262 3rd Edition - December 1999.
|
10 |
+
* This feature can also be found in Python. JSON is a text format that is
|
11 |
+
* completely language independent but uses conventions that are familiar
|
12 |
+
* to programmers of the C-family of languages, including C, C++, C#, Java,
|
13 |
+
* JavaScript, Perl, TCL, and many others. These properties make JSON an
|
14 |
+
* ideal data-interchange language.
|
15 |
+
*
|
16 |
+
* This package provides a simple encoder and decoder for JSON notation. It
|
17 |
+
* is intended for use with client-side Javascript applications that make
|
18 |
+
* use of HTTPRequest to perform server communication functions - data can
|
19 |
+
* be encoded into JSON notation for use in a client-side javascript, or
|
20 |
+
* decoded from incoming Javascript requests. JSON format is native to
|
21 |
+
* Javascript, and can be directly eval()'ed with no further parsing
|
22 |
+
* overhead
|
23 |
+
*
|
24 |
+
* All strings should be in ASCII or UTF-8 format!
|
25 |
+
*
|
26 |
+
* LICENSE: Redistribution and use in source and binary forms, with or
|
27 |
+
* without modification, are permitted provided that the following
|
28 |
+
* conditions are met: Redistributions of source code must retain the
|
29 |
+
* above copyright notice, this list of conditions and the following
|
30 |
+
* disclaimer. Redistributions in binary form must reproduce the above
|
31 |
+
* copyright notice, this list of conditions and the following disclaimer
|
32 |
+
* in the documentation and/or other materials provided with the
|
33 |
+
* distribution.
|
34 |
+
*
|
35 |
+
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
36 |
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
37 |
+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
38 |
+
* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
39 |
+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
40 |
+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
41 |
+
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
42 |
+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
43 |
+
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
44 |
+
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
45 |
+
* DAMAGE.
|
46 |
+
*
|
47 |
+
* @category
|
48 |
+
* @package Services_JSON
|
49 |
+
* @author Michal Migurski <mike-json@teczno.com>
|
50 |
+
* @author Matt Knapp <mdknapp[at]gmail[dot]com>
|
51 |
+
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
|
52 |
+
* @copyright 2005 Michal Migurski
|
53 |
+
* @version CVS: $Id: JSON.php,v 1.3 2009/05/22 23:51:00 alan_k Exp $
|
54 |
+
* @license http://www.opensource.org/licenses/bsd-license.php
|
55 |
+
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
|
56 |
+
*/
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Marker constant for Services_JSON::decode(), used to flag stack state
|
60 |
+
*/
|
61 |
+
define('SERVICES_JSON_SLICE', 1);
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Marker constant for Services_JSON::decode(), used to flag stack state
|
65 |
+
*/
|
66 |
+
define('SERVICES_JSON_IN_STR', 2);
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Marker constant for Services_JSON::decode(), used to flag stack state
|
70 |
+
*/
|
71 |
+
define('SERVICES_JSON_IN_ARR', 3);
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Marker constant for Services_JSON::decode(), used to flag stack state
|
75 |
+
*/
|
76 |
+
define('SERVICES_JSON_IN_OBJ', 4);
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Marker constant for Services_JSON::decode(), used to flag stack state
|
80 |
+
*/
|
81 |
+
define('SERVICES_JSON_IN_CMT', 5);
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Behavior switch for Services_JSON::decode()
|
85 |
+
*/
|
86 |
+
define('SERVICES_JSON_LOOSE_TYPE', 16);
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Behavior switch for Services_JSON::decode()
|
90 |
+
*/
|
91 |
+
define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Converts to and from JSON format.
|
95 |
+
*
|
96 |
+
* Brief example of use:
|
97 |
+
*
|
98 |
+
* <code>
|
99 |
+
* // create a new instance of Services_JSON
|
100 |
+
* $json = new Services_JSON();
|
101 |
+
*
|
102 |
+
* // convert a complexe value to JSON notation, and send it to the browser
|
103 |
+
* $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
|
104 |
+
* $output = $json->encode($value);
|
105 |
+
*
|
106 |
+
* print($output);
|
107 |
+
* // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
|
108 |
+
*
|
109 |
+
* // accept incoming POST data, assumed to be in JSON notation
|
110 |
+
* $input = file_get_contents('php://input', 1000000);
|
111 |
+
* $value = $json->decode($input);
|
112 |
+
* </code>
|
113 |
+
*/
|
114 |
+
class Services_JSON
|
115 |
+
{
|
116 |
+
/**
|
117 |
+
* constructs a new JSON instance
|
118 |
+
*
|
119 |
+
* @param int $use object behavior flags; combine with boolean-OR
|
120 |
+
*
|
121 |
+
* possible values:
|
122 |
+
* - SERVICES_JSON_LOOSE_TYPE: loose typing.
|
123 |
+
* "{...}" syntax creates associative arrays
|
124 |
+
* instead of objects in decode().
|
125 |
+
* - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
|
126 |
+
* Values which can't be encoded (e.g. resources)
|
127 |
+
* appear as NULL instead of throwing errors.
|
128 |
+
* By default, a deeply-nested resource will
|
129 |
+
* bubble up with an error, so all return values
|
130 |
+
* from encode() should be checked with isError()
|
131 |
+
*/
|
132 |
+
function Services_JSON($use = 0)
|
133 |
+
{
|
134 |
+
$this->use = $use;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* convert a string from one UTF-16 char to one UTF-8 char
|
139 |
+
*
|
140 |
+
* Normally should be handled by mb_convert_encoding, but
|
141 |
+
* provides a slower PHP-only method for installations
|
142 |
+
* that lack the multibye string extension.
|
143 |
+
*
|
144 |
+
* @param string $utf16 UTF-16 character
|
145 |
+
* @return string UTF-8 character
|
146 |
+
* @access private
|
147 |
+
*/
|
148 |
+
function utf162utf8($utf16)
|
149 |
+
{
|
150 |
+
// oh please oh please oh please oh please oh please
|
151 |
+
if(function_exists('mb_convert_encoding')) {
|
152 |
+
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
|
153 |
+
}
|
154 |
+
|
155 |
+
$bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
|
156 |
+
|
157 |
+
switch(true) {
|
158 |
+
case ((0x7F & $bytes) == $bytes):
|
159 |
+
// this case should never be reached, because we are in ASCII range
|
160 |
+
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
161 |
+
return chr(0x7F & $bytes);
|
162 |
+
|
163 |
+
case (0x07FF & $bytes) == $bytes:
|
164 |
+
// return a 2-byte UTF-8 character
|
165 |
+
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
166 |
+
return chr(0xC0 | (($bytes >> 6) & 0x1F))
|
167 |
+
. chr(0x80 | ($bytes & 0x3F));
|
168 |
+
|
169 |
+
case (0xFFFF & $bytes) == $bytes:
|
170 |
+
// return a 3-byte UTF-8 character
|
171 |
+
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
172 |
+
return chr(0xE0 | (($bytes >> 12) & 0x0F))
|
173 |
+
. chr(0x80 | (($bytes >> 6) & 0x3F))
|
174 |
+
. chr(0x80 | ($bytes & 0x3F));
|
175 |
+
}
|
176 |
+
|
177 |
+
// ignoring UTF-32 for now, sorry
|
178 |
+
return '';
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* convert a string from one UTF-8 char to one UTF-16 char
|
183 |
+
*
|
184 |
+
* Normally should be handled by mb_convert_encoding, but
|
185 |
+
* provides a slower PHP-only method for installations
|
186 |
+
* that lack the multibye string extension.
|
187 |
+
*
|
188 |
+
* @param string $utf8 UTF-8 character
|
189 |
+
* @return string UTF-16 character
|
190 |
+
* @access private
|
191 |
+
*/
|
192 |
+
function utf82utf16($utf8)
|
193 |
+
{
|
194 |
+
// oh please oh please oh please oh please oh please
|
195 |
+
if(function_exists('mb_convert_encoding')) {
|
196 |
+
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
|
197 |
+
}
|
198 |
+
|
199 |
+
switch(strlen($utf8)) {
|
200 |
+
case 1:
|
201 |
+
// this case should never be reached, because we are in ASCII range
|
202 |
+
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
203 |
+
return $utf8;
|
204 |
+
|
205 |
+
case 2:
|
206 |
+
// return a UTF-16 character from a 2-byte UTF-8 char
|
207 |
+
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
208 |
+
return chr(0x07 & (ord($utf8{0}) >> 2))
|
209 |
+
. chr((0xC0 & (ord($utf8{0}) << 6))
|
210 |
+
| (0x3F & ord($utf8{1})));
|
211 |
+
|
212 |
+
case 3:
|
213 |
+
// return a UTF-16 character from a 3-byte UTF-8 char
|
214 |
+
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
215 |
+
return chr((0xF0 & (ord($utf8{0}) << 4))
|
216 |
+
| (0x0F & (ord($utf8{1}) >> 2)))
|
217 |
+
. chr((0xC0 & (ord($utf8{1}) << 6))
|
218 |
+
| (0x7F & ord($utf8{2})));
|
219 |
+
}
|
220 |
+
|
221 |
+
// ignoring UTF-32 for now, sorry
|
222 |
+
return '';
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* encodes an arbitrary variable into JSON format (and sends JSON Header)
|
227 |
+
*
|
228 |
+
* @param mixed $var any number, boolean, string, array, or object to be encoded.
|
229 |
+
* see argument 1 to Services_JSON() above for array-parsing behavior.
|
230 |
+
* if var is a strng, note that encode() always expects it
|
231 |
+
* to be in ASCII or UTF-8 format!
|
232 |
+
*
|
233 |
+
* @return mixed JSON string representation of input var or an error if a problem occurs
|
234 |
+
* @access public
|
235 |
+
*/
|
236 |
+
function encode($var)
|
237 |
+
{
|
238 |
+
header('Content-type: application/x-javascript');
|
239 |
+
return $this->_encode($var);
|
240 |
+
}
|
241 |
+
/**
|
242 |
+
* encodes an arbitrary variable into JSON format without JSON Header - warning - may allow CSS!!!!)
|
243 |
+
*
|
244 |
+
* @param mixed $var any number, boolean, string, array, or object to be encoded.
|
245 |
+
* see argument 1 to Services_JSON() above for array-parsing behavior.
|
246 |
+
* if var is a strng, note that encode() always expects it
|
247 |
+
* to be in ASCII or UTF-8 format!
|
248 |
+
*
|
249 |
+
* @return mixed JSON string representation of input var or an error if a problem occurs
|
250 |
+
* @access public
|
251 |
+
*/
|
252 |
+
function encodeUnsafe($var)
|
253 |
+
{
|
254 |
+
return $this->_encode($var);
|
255 |
+
}
|
256 |
+
/**
|
257 |
+
* PRIVATE CODE that does the work of encodes an arbitrary variable into JSON format
|
258 |
+
*
|
259 |
+
* @param mixed $var any number, boolean, string, array, or object to be encoded.
|
260 |
+
* see argument 1 to Services_JSON() above for array-parsing behavior.
|
261 |
+
* if var is a strng, note that encode() always expects it
|
262 |
+
* to be in ASCII or UTF-8 format!
|
263 |
+
*
|
264 |
+
* @return mixed JSON string representation of input var or an error if a problem occurs
|
265 |
+
* @access public
|
266 |
+
*/
|
267 |
+
function _encode($var)
|
268 |
+
{
|
269 |
+
|
270 |
+
switch (gettype($var)) {
|
271 |
+
case 'boolean':
|
272 |
+
return $var ? 'true' : 'false';
|
273 |
+
|
274 |
+
case 'NULL':
|
275 |
+
return 'null';
|
276 |
+
|
277 |
+
case 'integer':
|
278 |
+
return (int) $var;
|
279 |
+
|
280 |
+
case 'double':
|
281 |
+
case 'float':
|
282 |
+
return (float) $var;
|
283 |
+
|
284 |
+
case 'string':
|
285 |
+
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
|
286 |
+
$ascii = '';
|
287 |
+
$strlen_var = strlen($var);
|
288 |
+
|
289 |
+
/*
|
290 |
+
* Iterate over every character in the string,
|
291 |
+
* escaping with a slash or encoding to UTF-8 where necessary
|
292 |
+
*/
|
293 |
+
for ($c = 0; $c < $strlen_var; ++$c) {
|
294 |
+
|
295 |
+
$ord_var_c = ord($var{$c});
|
296 |
+
|
297 |
+
switch (true) {
|
298 |
+
case $ord_var_c == 0x08:
|
299 |
+
$ascii .= '\b';
|
300 |
+
break;
|
301 |
+
case $ord_var_c == 0x09:
|
302 |
+
$ascii .= '\t';
|
303 |
+
break;
|
304 |
+
case $ord_var_c == 0x0A:
|
305 |
+
$ascii .= '\n';
|
306 |
+
break;
|
307 |
+
case $ord_var_c == 0x0C:
|
308 |
+
$ascii .= '\f';
|
309 |
+
break;
|
310 |
+
case $ord_var_c == 0x0D:
|
311 |
+
$ascii .= '\r';
|
312 |
+
break;
|
313 |
+
|
314 |
+
case $ord_var_c == 0x22:
|
315 |
+
case $ord_var_c == 0x2F:
|
316 |
+
case $ord_var_c == 0x5C:
|
317 |
+
// double quote, slash, slosh
|
318 |
+
$ascii .= '\\'.$var{$c};
|
319 |
+
break;
|
320 |
+
|
321 |
+
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
|
322 |
+
// characters U-00000000 - U-0000007F (same as ASCII)
|
323 |
+
$ascii .= $var{$c};
|
324 |
+
break;
|
325 |
+
|
326 |
+
case (($ord_var_c & 0xE0) == 0xC0):
|
327 |
+
// characters U-00000080 - U-000007FF, mask 110XXXXX
|
328 |
+
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
329 |
+
if ($c+1 >= $strlen_var) {
|
330 |
+
$c += 1;
|
331 |
+
$ascii .= '?';
|
332 |
+
break;
|
333 |
+
}
|
334 |
+
|
335 |
+
$char = pack('C*', $ord_var_c, ord($var{$c + 1}));
|
336 |
+
$c += 1;
|
337 |
+
$utf16 = $this->utf82utf16($char);
|
338 |
+
$ascii .= sprintf('\u%04s', bin2hex($utf16));
|
339 |
+
break;
|
340 |
+
|
341 |
+
case (($ord_var_c & 0xF0) == 0xE0):
|
342 |
+
if ($c+2 >= $strlen_var) {
|
343 |
+
$c += 2;
|
344 |
+
$ascii .= '?';
|
345 |
+
break;
|
346 |
+
}
|
347 |
+
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
|
348 |
+
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
349 |
+
$char = pack('C*', $ord_var_c,
|
350 |
+
@ord($var{$c + 1}),
|
351 |
+
@ord($var{$c + 2}));
|
352 |
+
$c += 2;
|
353 |
+
$utf16 = $this->utf82utf16($char);
|
354 |
+
$ascii .= sprintf('\u%04s', bin2hex($utf16));
|
355 |
+
break;
|
356 |
+
|
357 |
+
case (($ord_var_c & 0xF8) == 0xF0):
|
358 |
+
if ($c+3 >= $strlen_var) {
|
359 |
+
$c += 3;
|
360 |
+
$ascii .= '?';
|
361 |
+
break;
|
362 |
+
}
|
363 |
+
// characters U-00010000 - U-001FFFFF, mask 11110XXX
|
364 |
+
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
365 |
+
$char = pack('C*', $ord_var_c,
|
366 |
+
ord($var{$c + 1}),
|
367 |
+
ord($var{$c + 2}),
|
368 |
+
ord($var{$c + 3}));
|
369 |
+
$c += 3;
|
370 |
+
$utf16 = $this->utf82utf16($char);
|
371 |
+
$ascii .= sprintf('\u%04s', bin2hex($utf16));
|
372 |
+
break;
|
373 |
+
|
374 |
+
case (($ord_var_c & 0xFC) == 0xF8):
|
375 |
+
// characters U-00200000 - U-03FFFFFF, mask 111110XX
|
376 |
+
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
377 |
+
if ($c+4 >= $strlen_var) {
|
378 |
+
$c += 4;
|
379 |
+
$ascii .= '?';
|
380 |
+
break;
|
381 |
+
}
|
382 |
+
$char = pack('C*', $ord_var_c,
|
383 |
+
ord($var{$c + 1}),
|
384 |
+
ord($var{$c + 2}),
|
385 |
+
ord($var{$c + 3}),
|
386 |
+
ord($var{$c + 4}));
|
387 |
+
$c += 4;
|
388 |
+
$utf16 = $this->utf82utf16($char);
|
389 |
+
$ascii .= sprintf('\u%04s', bin2hex($utf16));
|
390 |
+
break;
|
391 |
+
|
392 |
+
case (($ord_var_c & 0xFE) == 0xFC):
|
393 |
+
if ($c+5 >= $strlen_var) {
|
394 |
+
$c += 5;
|
395 |
+
$ascii .= '?';
|
396 |
+
break;
|
397 |
+
}
|
398 |
+
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
|
399 |
+
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
400 |
+
$char = pack('C*', $ord_var_c,
|
401 |
+
ord($var{$c + 1}),
|
402 |
+
ord($var{$c + 2}),
|
403 |
+
ord($var{$c + 3}),
|
404 |
+
ord($var{$c + 4}),
|
405 |
+
ord($var{$c + 5}));
|
406 |
+
$c += 5;
|
407 |
+
$utf16 = $this->utf82utf16($char);
|
408 |
+
$ascii .= sprintf('\u%04s', bin2hex($utf16));
|
409 |
+
break;
|
410 |
+
}
|
411 |
+
}
|
412 |
+
return '"'.$ascii.'"';
|
413 |
+
|
414 |
+
case 'array':
|
415 |
+
/*
|
416 |
+
* As per JSON spec if any array key is not an integer
|
417 |
+
* we must treat the the whole array as an object. We
|
418 |
+
* also try to catch a sparsely populated associative
|
419 |
+
* array with numeric keys here because some JS engines
|
420 |
+
* will create an array with empty indexes up to
|
421 |
+
* max_index which can cause memory issues and because
|
422 |
+
* the keys, which may be relevant, will be remapped
|
423 |
+
* otherwise.
|
424 |
+
*
|
425 |
+
* As per the ECMA and JSON specification an object may
|
426 |
+
* have any string as a property. Unfortunately due to
|
427 |
+
* a hole in the ECMA specification if the key is a
|
428 |
+
* ECMA reserved word or starts with a digit the
|
429 |
+
* parameter is only accessible using ECMAScript's
|
430 |
+
* bracket notation.
|
431 |
+
*/
|
432 |
+
|
433 |
+
// treat as a JSON object
|
434 |
+
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
|
435 |
+
$properties = array_map(array($this, 'name_value'),
|
436 |
+
array_keys($var),
|
437 |
+
array_values($var));
|
438 |
+
|
439 |
+
foreach($properties as $property) {
|
440 |
+
if(Services_JSON::isError($property)) {
|
441 |
+
return $property;
|
442 |
+
}
|
443 |
+
}
|
444 |
+
|
445 |
+
return '{' . join(',', $properties) . '}';
|
446 |
+
}
|
447 |
+
|
448 |
+
// treat it like a regular array
|
449 |
+
$elements = array_map(array($this, '_encode'), $var);
|
450 |
+
|
451 |
+
foreach($elements as $element) {
|
452 |
+
if(Services_JSON::isError($element)) {
|
453 |
+
return $element;
|
454 |
+
}
|
455 |
+
}
|
456 |
+
|
457 |
+
return '[' . join(',', $elements) . ']';
|
458 |
+
|
459 |
+
case 'object':
|
460 |
+
$vars = get_object_vars($var);
|
461 |
+
|
462 |
+
$properties = array_map(array($this, 'name_value'),
|
463 |
+
array_keys($vars),
|
464 |
+
array_values($vars));
|
465 |
+
|
466 |
+
foreach($properties as $property) {
|
467 |
+
if(Services_JSON::isError($property)) {
|
468 |
+
return $property;
|
469 |
+
}
|
470 |
+
}
|
471 |
+
|
472 |
+
return '{' . join(',', $properties) . '}';
|
473 |
+
|
474 |
+
default:
|
475 |
+
return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
|
476 |
+
? 'null'
|
477 |
+
: new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
|
478 |
+
}
|
479 |
+
}
|
480 |
+
|
481 |
+
/**
|
482 |
+
* array-walking function for use in generating JSON-formatted name-value pairs
|
483 |
+
*
|
484 |
+
* @param string $name name of key to use
|
485 |
+
* @param mixed $value reference to an array element to be encoded
|
486 |
+
*
|
487 |
+
* @return string JSON-formatted name-value pair, like '"name":value'
|
488 |
+
* @access private
|
489 |
+
*/
|
490 |
+
function name_value($name, $value)
|
491 |
+
{
|
492 |
+
$encoded_value = $this->_encode($value);
|
493 |
+
|
494 |
+
if(Services_JSON::isError($encoded_value)) {
|
495 |
+
return $encoded_value;
|
496 |
+
}
|
497 |
+
|
498 |
+
return $this->_encode(strval($name)) . ':' . $encoded_value;
|
499 |
+
}
|
500 |
+
|
501 |
+
/**
|
502 |
+
* reduce a string by removing leading and trailing comments and whitespace
|
503 |
+
*
|
504 |
+
* @param $str string string value to strip of comments and whitespace
|
505 |
+
*
|
506 |
+
* @return string string value stripped of comments and whitespace
|
507 |
+
* @access private
|
508 |
+
*/
|
509 |
+
function reduce_string($str)
|
510 |
+
{
|
511 |
+
$str = preg_replace(array(
|
512 |
+
|
513 |
+
// eliminate single line comments in '// ...' form
|
514 |
+
'#^\s*//(.+)$#m',
|
515 |
+
|
516 |
+
// eliminate multi-line comments in '/* ... */' form, at start of string
|
517 |
+
'#^\s*/\*(.+)\*/#Us',
|
518 |
+
|
519 |
+
// eliminate multi-line comments in '/* ... */' form, at end of string
|
520 |
+
'#/\*(.+)\*/\s*$#Us'
|
521 |
+
|
522 |
+
), '', $str);
|
523 |
+
|
524 |
+
// eliminate extraneous space
|
525 |
+
return trim($str);
|
526 |
+
}
|
527 |
+
|
528 |
+
/**
|
529 |
+
* decodes a JSON string into appropriate variable
|
530 |
+
*
|
531 |
+
* @param string $str JSON-formatted string
|
532 |
+
*
|
533 |
+
* @return mixed number, boolean, string, array, or object
|
534 |
+
* corresponding to given JSON input string.
|
535 |
+
* See argument 1 to Services_JSON() above for object-output behavior.
|
536 |
+
* Note that decode() always returns strings
|
537 |
+
* in ASCII or UTF-8 format!
|
538 |
+
* @access public
|
539 |
+
*/
|
540 |
+
function decode($str)
|
541 |
+
{
|
542 |
+
$str = $this->reduce_string($str);
|
543 |
+
|
544 |
+
switch (strtolower($str)) {
|
545 |
+
case 'true':
|
546 |
+
return true;
|
547 |
+
|
548 |
+
case 'false':
|
549 |
+
return false;
|
550 |
+
|
551 |
+
case 'null':
|
552 |
+
return null;
|
553 |
+
|
554 |
+
default:
|
555 |
+
$m = array();
|
556 |
+
|
557 |
+
if (is_numeric($str)) {
|
558 |
+
// Lookie-loo, it's a number
|
559 |
+
|
560 |
+
// This would work on its own, but I'm trying to be
|
561 |
+
// good about returning integers where appropriate:
|
562 |
+
// return (float)$str;
|
563 |
+
|
564 |
+
// Return float or int, as appropriate
|
565 |
+
return ((float)$str == (integer)$str)
|
566 |
+
? (integer)$str
|
567 |
+
: (float)$str;
|
568 |
+
|
569 |
+
} elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
|
570 |
+
// STRINGS RETURNED IN UTF-8 FORMAT
|
571 |
+
$delim = substr($str, 0, 1);
|
572 |
+
$chrs = substr($str, 1, -1);
|
573 |
+
$utf8 = '';
|
574 |
+
$strlen_chrs = strlen($chrs);
|
575 |
+
|
576 |
+
for ($c = 0; $c < $strlen_chrs; ++$c) {
|
577 |
+
|
578 |
+
$substr_chrs_c_2 = substr($chrs, $c, 2);
|
579 |
+
$ord_chrs_c = ord($chrs{$c});
|
580 |
+
|
581 |
+
switch (true) {
|
582 |
+
case $substr_chrs_c_2 == '\b':
|
583 |
+
$utf8 .= chr(0x08);
|
584 |
+
++$c;
|
585 |
+
break;
|
586 |
+
case $substr_chrs_c_2 == '\t':
|
587 |
+
$utf8 .= chr(0x09);
|
588 |
+
++$c;
|
589 |
+
break;
|
590 |
+
case $substr_chrs_c_2 == '\n':
|
591 |
+
$utf8 .= chr(0x0A);
|
592 |
+
++$c;
|
593 |
+
break;
|
594 |
+
case $substr_chrs_c_2 == '\f':
|
595 |
+
$utf8 .= chr(0x0C);
|
596 |
+
++$c;
|
597 |
+
break;
|
598 |
+
case $substr_chrs_c_2 == '\r':
|
599 |
+
$utf8 .= chr(0x0D);
|
600 |
+
++$c;
|
601 |
+
break;
|
602 |
+
|
603 |
+
case $substr_chrs_c_2 == '\\"':
|
604 |
+
case $substr_chrs_c_2 == '\\\'':
|
605 |
+
case $substr_chrs_c_2 == '\\\\':
|
606 |
+
case $substr_chrs_c_2 == '\\/':
|
607 |
+
if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
|
608 |
+
($delim == "'" && $substr_chrs_c_2 != '\\"')) {
|
609 |
+
$utf8 .= $chrs{++$c};
|
610 |
+
}
|
611 |
+
break;
|
612 |
+
|
613 |
+
case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
|
614 |
+
// single, escaped unicode character
|
615 |
+
$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
|
616 |
+
. chr(hexdec(substr($chrs, ($c + 4), 2)));
|
617 |
+
$utf8 .= $this->utf162utf8($utf16);
|
618 |
+
$c += 5;
|
619 |
+
break;
|
620 |
+
|
621 |
+
case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
|
622 |
+
$utf8 .= $chrs{$c};
|
623 |
+
break;
|
624 |
+
|
625 |
+
case ($ord_chrs_c & 0xE0) == 0xC0:
|
626 |
+
// characters U-00000080 - U-000007FF, mask 110XXXXX
|
627 |
+
//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
628 |
+
$utf8 .= substr($chrs, $c, 2);
|
629 |
+
++$c;
|
630 |
+
break;
|
631 |
+
|
632 |
+
case ($ord_chrs_c & 0xF0) == 0xE0:
|
633 |
+
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
|
634 |
+
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
635 |
+
$utf8 .= substr($chrs, $c, 3);
|
636 |
+
$c += 2;
|
637 |
+
break;
|
638 |
+
|
639 |
+
case ($ord_chrs_c & 0xF8) == 0xF0:
|
640 |
+
// characters U-00010000 - U-001FFFFF, mask 11110XXX
|
641 |
+
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
642 |
+
$utf8 .= substr($chrs, $c, 4);
|
643 |
+
$c += 3;
|
644 |
+
break;
|
645 |
+
|
646 |
+
case ($ord_chrs_c & 0xFC) == 0xF8:
|
647 |
+
// characters U-00200000 - U-03FFFFFF, mask 111110XX
|
648 |
+
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
649 |
+
$utf8 .= substr($chrs, $c, 5);
|
650 |
+
$c += 4;
|
651 |
+
break;
|
652 |
+
|
653 |
+
case ($ord_chrs_c & 0xFE) == 0xFC:
|
654 |
+
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
|
655 |
+
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
656 |
+
$utf8 .= substr($chrs, $c, 6);
|
657 |
+
$c += 5;
|
658 |
+
break;
|
659 |
+
|
660 |
+
}
|
661 |
+
|
662 |
+
}
|
663 |
+
|
664 |
+
return $utf8;
|
665 |
+
|
666 |
+
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
|
667 |
+
// array, or object notation
|
668 |
+
|
669 |
+
if ($str{0} == '[') {
|
670 |
+
$stk = array(SERVICES_JSON_IN_ARR);
|
671 |
+
$arr = array();
|
672 |
+
} else {
|
673 |
+
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
|
674 |
+
$stk = array(SERVICES_JSON_IN_OBJ);
|
675 |
+
$obj = array();
|
676 |
+
} else {
|
677 |
+
$stk = array(SERVICES_JSON_IN_OBJ);
|
678 |
+
$obj = new stdClass();
|
679 |
+
}
|
680 |
+
}
|
681 |
+
|
682 |
+
array_push($stk, array('what' => SERVICES_JSON_SLICE,
|
683 |
+
'where' => 0,
|
684 |
+
'delim' => false));
|
685 |
+
|
686 |
+
$chrs = substr($str, 1, -1);
|
687 |
+
$chrs = $this->reduce_string($chrs);
|
688 |
+
|
689 |
+
if ($chrs == '') {
|
690 |
+
if (reset($stk) == SERVICES_JSON_IN_ARR) {
|
691 |
+
return $arr;
|
692 |
+
|
693 |
+
} else {
|
694 |
+
return $obj;
|
695 |
+
|
696 |
+
}
|
697 |
+
}
|
698 |
+
|
699 |
+
//print("\nparsing {$chrs}\n");
|
700 |
+
|
701 |
+
$strlen_chrs = strlen($chrs);
|
702 |
+
|
703 |
+
for ($c = 0; $c <= $strlen_chrs; ++$c) {
|
704 |
+
|
705 |
+
$top = end($stk);
|
706 |
+
$substr_chrs_c_2 = substr($chrs, $c, 2);
|
707 |
+
|
708 |
+
if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
|
709 |
+
// found a comma that is not inside a string, array, etc.,
|
710 |
+
// OR we've reached the end of the character list
|
711 |
+
$slice = substr($chrs, $top['where'], ($c - $top['where']));
|
712 |
+
array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
|
713 |
+
//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
|
714 |
+
|
715 |
+
if (reset($stk) == SERVICES_JSON_IN_ARR) {
|
716 |
+
// we are in an array, so just push an element onto the stack
|
717 |
+
array_push($arr, $this->decode($slice));
|
718 |
+
|
719 |
+
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
|
720 |
+
// we are in an object, so figure
|
721 |
+
// out the property name and set an
|
722 |
+
// element in an associative array,
|
723 |
+
// for now
|
724 |
+
$parts = array();
|
725 |
+
|
726 |
+
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
|
727 |
+
// "name":value pair
|
728 |
+
$key = $this->decode($parts[1]);
|
729 |
+
$val = $this->decode($parts[2]);
|
730 |
+
|
731 |
+
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
|
732 |
+
$obj[$key] = $val;
|
733 |
+
} else {
|
734 |
+
$obj->$key = $val;
|
735 |
+
}
|
736 |
+
} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
|
737 |
+
// name:value pair, where name is unquoted
|
738 |
+
$key = $parts[1];
|
739 |
+
$val = $this->decode($parts[2]);
|
740 |
+
|
741 |
+
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
|
742 |
+
$obj[$key] = $val;
|
743 |
+
} else {
|
744 |
+
$obj->$key = $val;
|
745 |
+
}
|
746 |
+
}
|
747 |
+
|
748 |
+
}
|
749 |
+
|
750 |
+
} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
|
751 |
+
// found a quote, and we are not inside a string
|
752 |
+
array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
|
753 |
+
//print("Found start of string at {$c}\n");
|
754 |
+
|
755 |
+
} elseif (($chrs{$c} == $top['delim']) &&
|
756 |
+
($top['what'] == SERVICES_JSON_IN_STR) &&
|
757 |
+
((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
|
758 |
+
// found a quote, we're in a string, and it's not escaped
|
759 |
+
// we know that it's not escaped becase there is _not_ an
|
760 |
+
// odd number of backslashes at the end of the string so far
|
761 |
+
array_pop($stk);
|
762 |
+
//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
|
763 |
+
|
764 |
+
} elseif (($chrs{$c} == '[') &&
|
765 |
+
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
|
766 |
+
// found a left-bracket, and we are in an array, object, or slice
|
767 |
+
array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
|
768 |
+
//print("Found start of array at {$c}\n");
|
769 |
+
|
770 |
+
} elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
|
771 |
+
// found a right-bracket, and we're in an array
|
772 |
+
array_pop($stk);
|
773 |
+
//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
|
774 |
+
|
775 |
+
} elseif (($chrs{$c} == '{') &&
|
776 |
+
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
|
777 |
+
// found a left-brace, and we are in an array, object, or slice
|
778 |
+
array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
|
779 |
+
//print("Found start of object at {$c}\n");
|
780 |
+
|
781 |
+
} elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
|
782 |
+
// found a right-brace, and we're in an object
|
783 |
+
array_pop($stk);
|
784 |
+
//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
|
785 |
+
|
786 |
+
} elseif (($substr_chrs_c_2 == '/*') &&
|
787 |
+
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
|
788 |
+
// found a comment start, and we are in an array, object, or slice
|
789 |
+
array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
|
790 |
+
$c++;
|
791 |
+
//print("Found start of comment at {$c}\n");
|
792 |
+
|
793 |
+
} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
|
794 |
+
// found a comment end, and we're in one now
|
795 |
+
array_pop($stk);
|
796 |
+
$c++;
|
797 |
+
|
798 |
+
for ($i = $top['where']; $i <= $c; ++$i)
|
799 |
+
$chrs = substr_replace($chrs, ' ', $i, 1);
|
800 |
+
|
801 |
+
//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
|
802 |
+
|
803 |
+
}
|
804 |
+
|
805 |
+
}
|
806 |
+
|
807 |
+
if (reset($stk) == SERVICES_JSON_IN_ARR) {
|
808 |
+
return $arr;
|
809 |
+
|
810 |
+
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
|
811 |
+
return $obj;
|
812 |
+
|
813 |
+
}
|
814 |
+
|
815 |
+
}
|
816 |
+
}
|
817 |
+
}
|
818 |
+
|
819 |
+
/**
|
820 |
+
* @todo Ultimately, this should just call PEAR::isError()
|
821 |
+
*/
|
822 |
+
function isError($data, $code = null)
|
823 |
+
{
|
824 |
+
if (class_exists('pear')) {
|
825 |
+
return PEAR::isError($data, $code);
|
826 |
+
} elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
|
827 |
+
is_subclass_of($data, 'services_json_error'))) {
|
828 |
+
return true;
|
829 |
+
}
|
830 |
+
|
831 |
+
return false;
|
832 |
+
}
|
833 |
+
}
|
834 |
+
|
835 |
+
if (class_exists('PEAR_Error')) {
|
836 |
+
|
837 |
+
class Services_JSON_Error extends PEAR_Error
|
838 |
+
{
|
839 |
+
function Services_JSON_Error($message = 'unknown error', $code = null,
|
840 |
+
$mode = null, $options = null, $userinfo = null)
|
841 |
+
{
|
842 |
+
parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
|
843 |
+
}
|
844 |
+
}
|
845 |
+
|
846 |
+
} else {
|
847 |
+
|
848 |
+
/**
|
849 |
+
* @todo Ultimately, this class shall be descended from PEAR_Error
|
850 |
+
*/
|
851 |
+
class Services_JSON_Error
|
852 |
+
{
|
853 |
+
function Services_JSON_Error($message = 'unknown error', $code = null,
|
854 |
+
$mode = null, $options = null, $userinfo = null)
|
855 |
+
{
|
856 |
+
|
857 |
+
}
|
858 |
+
}
|
859 |
+
|
860 |
+
}
|
json_decode.php
DELETED
@@ -1,392 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
class Zend_Json_Decoder
|
3 |
-
{
|
4 |
-
/**
|
5 |
-
* Parse tokens used to decode the JSON object. These are not
|
6 |
-
* for public consumption, they are just used internally to the
|
7 |
-
* class.
|
8 |
-
*/
|
9 |
-
const EOF = 0;
|
10 |
-
const DATUM = 1;
|
11 |
-
const LBRACE = 2;
|
12 |
-
const LBRACKET = 3;
|
13 |
-
const RBRACE = 4;
|
14 |
-
const RBRACKET = 5;
|
15 |
-
const COMMA = 6;
|
16 |
-
const COLON = 7;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Use to maintain a "pointer" to the source being decoded
|
20 |
-
*
|
21 |
-
* @var string
|
22 |
-
*/
|
23 |
-
protected $_source;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Caches the source length
|
27 |
-
*
|
28 |
-
* @var int
|
29 |
-
*/
|
30 |
-
protected $_sourceLength;
|
31 |
-
|
32 |
-
/**
|
33 |
-
* The offset within the souce being decoded
|
34 |
-
*
|
35 |
-
* @var int
|
36 |
-
*
|
37 |
-
*/
|
38 |
-
protected $_offset;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* The current token being considered in the parser cycle
|
42 |
-
*
|
43 |
-
* @var int
|
44 |
-
*/
|
45 |
-
protected $_token;
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Constructor
|
49 |
-
*
|
50 |
-
* @param string $source String source to decode
|
51 |
-
* @param int $decodeType How objects should be decoded -- see
|
52 |
-
* {@link Zend_Json::TYPE_ARRAY} and {@link Zend_Json::TYPE_OBJECT} for
|
53 |
-
* valid values
|
54 |
-
* @return void
|
55 |
-
*/
|
56 |
-
protected function __construct($source)
|
57 |
-
{
|
58 |
-
// Set defaults
|
59 |
-
$this->_source = $source;
|
60 |
-
$this->_sourceLength = strlen($source);
|
61 |
-
$this->_token = self::EOF;
|
62 |
-
$this->_offset = 0;
|
63 |
-
|
64 |
-
// Set pointer at first token
|
65 |
-
$this->_getNextToken();
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Decode a JSON source string
|
70 |
-
*
|
71 |
-
* Decodes a JSON encoded string. The value returned will be one of the
|
72 |
-
* following:
|
73 |
-
* - integer
|
74 |
-
* - float
|
75 |
-
* - boolean
|
76 |
-
* - null
|
77 |
-
* - StdClass
|
78 |
-
* - array
|
79 |
-
* - array of one or more of the above types
|
80 |
-
*
|
81 |
-
* By default, decoded objects will be returned as associative arrays; to
|
82 |
-
* return a StdClass object instead, pass {@link Zend_Json::TYPE_OBJECT} to
|
83 |
-
* the $objectDecodeType parameter.
|
84 |
-
*
|
85 |
-
* @static
|
86 |
-
* @access public
|
87 |
-
* @param string $source String to be decoded
|
88 |
-
* @param int $objectDecodeType How objects should be decoded; should be
|
89 |
-
* either or {@link Zend_Json::TYPE_ARRAY} or
|
90 |
-
* {@link Zend_Json::TYPE_OBJECT}; defaults to TYPE_ARRAY
|
91 |
-
* @return mixed
|
92 |
-
* @throws Zend_Json_Exception
|
93 |
-
*/
|
94 |
-
public static function decode($source = null)
|
95 |
-
{
|
96 |
-
if (null === $source || !is_string($source)) {
|
97 |
-
return false;
|
98 |
-
}
|
99 |
-
|
100 |
-
$decoder = new self($source);
|
101 |
-
|
102 |
-
return $decoder->_decodeValue();
|
103 |
-
}
|
104 |
-
|
105 |
-
|
106 |
-
/**
|
107 |
-
* Recursive driving rountine for supported toplevel tops
|
108 |
-
*
|
109 |
-
* @return mixed
|
110 |
-
*/
|
111 |
-
protected function _decodeValue()
|
112 |
-
{
|
113 |
-
switch ($this->_token) {
|
114 |
-
case self::DATUM:
|
115 |
-
$result = $this->_tokenValue;
|
116 |
-
$this->_getNextToken();
|
117 |
-
return($result);
|
118 |
-
break;
|
119 |
-
case self::LBRACE:
|
120 |
-
return($this->_decodeObject());
|
121 |
-
break;
|
122 |
-
case self::LBRACKET:
|
123 |
-
return($this->_decodeArray());
|
124 |
-
break;
|
125 |
-
default:
|
126 |
-
return null;
|
127 |
-
break;
|
128 |
-
}
|
129 |
-
}
|
130 |
-
|
131 |
-
/**
|
132 |
-
* Decodes an object of the form:
|
133 |
-
* { "attribute: value, "attribute2" : value,...}
|
134 |
-
*
|
135 |
-
* If ZJsonEnoder or ZJAjax was used to encode the original object
|
136 |
-
* then a special attribute called __className which specifies a class
|
137 |
-
* name that should wrap the data contained within the encoded source.
|
138 |
-
*
|
139 |
-
* Decodes to either an array or StdClass object, based on the value of
|
140 |
-
* {@link $_decodeType}. If invalid $_decodeType present, returns as an
|
141 |
-
* array.
|
142 |
-
*
|
143 |
-
* @return array|StdClass
|
144 |
-
*/
|
145 |
-
protected function _decodeObject()
|
146 |
-
{
|
147 |
-
$result = new StdClass();
|
148 |
-
$members = array();
|
149 |
-
$tok = $this->_getNextToken();
|
150 |
-
|
151 |
-
while ($tok && $tok != self::RBRACE) {
|
152 |
-
if ($tok != self::DATUM || ! is_string($this->_tokenValue)) {
|
153 |
-
return $result;
|
154 |
-
}
|
155 |
-
|
156 |
-
$key = $this->_tokenValue;
|
157 |
-
$tok = $this->_getNextToken();
|
158 |
-
|
159 |
-
if ($tok != self::COLON) {
|
160 |
-
return $result;
|
161 |
-
}
|
162 |
-
|
163 |
-
$tok = $this->_getNextToken();
|
164 |
-
$members[$key] = $this->_decodeValue();
|
165 |
-
$tok = $this->_token;
|
166 |
-
|
167 |
-
if ($tok == self::RBRACE) {
|
168 |
-
break;
|
169 |
-
}
|
170 |
-
|
171 |
-
if ($tok != self::COMMA) {
|
172 |
-
return $result;
|
173 |
-
}
|
174 |
-
|
175 |
-
$tok = $this->_getNextToken();
|
176 |
-
}
|
177 |
-
|
178 |
-
// Create new StdClass and populate with $members
|
179 |
-
foreach ($members as $key => $value) {
|
180 |
-
$result->$key = $value;
|
181 |
-
}
|
182 |
-
|
183 |
-
$this->_getNextToken();
|
184 |
-
return $result;
|
185 |
-
}
|
186 |
-
|
187 |
-
/**
|
188 |
-
* Decodes a JSON array format:
|
189 |
-
* [element, element2,...,elementN]
|
190 |
-
*
|
191 |
-
* @return array
|
192 |
-
*/
|
193 |
-
protected function _decodeArray()
|
194 |
-
{
|
195 |
-
$result = array();
|
196 |
-
$starttok = $tok = $this->_getNextToken(); // Move past the '['
|
197 |
-
$index = 0;
|
198 |
-
|
199 |
-
while ($tok && $tok != self::RBRACKET) {
|
200 |
-
$result[$index++] = $this->_decodeValue();
|
201 |
-
|
202 |
-
$tok = $this->_token;
|
203 |
-
|
204 |
-
if ($tok == self::RBRACKET || !$tok) {
|
205 |
-
break;
|
206 |
-
}
|
207 |
-
|
208 |
-
if ($tok != self::COMMA) {
|
209 |
-
return $result;
|
210 |
-
}
|
211 |
-
|
212 |
-
$tok = $this->_getNextToken();
|
213 |
-
}
|
214 |
-
|
215 |
-
$this->_getNextToken();
|
216 |
-
return($result);
|
217 |
-
}
|
218 |
-
|
219 |
-
|
220 |
-
/**
|
221 |
-
* Removes whitepsace characters from the source input
|
222 |
-
*/
|
223 |
-
protected function _eatWhitespace()
|
224 |
-
{
|
225 |
-
if (preg_match(
|
226 |
-
'/([\t\b\f\n\r ])*/s',
|
227 |
-
$this->_source,
|
228 |
-
$matches,
|
229 |
-
PREG_OFFSET_CAPTURE,
|
230 |
-
$this->_offset)
|
231 |
-
&& $matches[0][1] == $this->_offset)
|
232 |
-
{
|
233 |
-
$this->_offset += strlen($matches[0][0]);
|
234 |
-
}
|
235 |
-
}
|
236 |
-
|
237 |
-
|
238 |
-
/**
|
239 |
-
* Retrieves the next token from the source stream
|
240 |
-
*
|
241 |
-
* @return int Token constant value specified in class definition
|
242 |
-
*/
|
243 |
-
protected function _getNextToken()
|
244 |
-
{
|
245 |
-
$this->_token = self::EOF;
|
246 |
-
$this->_tokenValue = null;
|
247 |
-
$this->_eatWhitespace();
|
248 |
-
|
249 |
-
if ($this->_offset >= $this->_sourceLength) {
|
250 |
-
return(self::EOF);
|
251 |
-
}
|
252 |
-
|
253 |
-
$str = $this->_source;
|
254 |
-
$str_length = $this->_sourceLength;
|
255 |
-
$i = $this->_offset;
|
256 |
-
$start = $i;
|
257 |
-
|
258 |
-
switch ($str{$i}) {
|
259 |
-
case '{':
|
260 |
-
$this->_token = self::LBRACE;
|
261 |
-
break;
|
262 |
-
case '}':
|
263 |
-
$this->_token = self::RBRACE;
|
264 |
-
break;
|
265 |
-
case '[':
|
266 |
-
$this->_token = self::LBRACKET;
|
267 |
-
break;
|
268 |
-
case ']':
|
269 |
-
$this->_token = self::RBRACKET;
|
270 |
-
break;
|
271 |
-
case ',':
|
272 |
-
$this->_token = self::COMMA;
|
273 |
-
break;
|
274 |
-
case ':':
|
275 |
-
$this->_token = self::COLON;
|
276 |
-
break;
|
277 |
-
case '"':
|
278 |
-
$result = '';
|
279 |
-
do {
|
280 |
-
$i++;
|
281 |
-
if ($i >= $str_length) {
|
282 |
-
break;
|
283 |
-
}
|
284 |
-
|
285 |
-
$chr = $str{$i};
|
286 |
-
if ($chr == '\\') {
|
287 |
-
$i++;
|
288 |
-
if ($i >= $str_length) {
|
289 |
-
break;
|
290 |
-
}
|
291 |
-
$chr = $str{$i};
|
292 |
-
switch ($chr) {
|
293 |
-
case '"' :
|
294 |
-
$result .= '"';
|
295 |
-
break;
|
296 |
-
case '\\':
|
297 |
-
$result .= '\\';
|
298 |
-
break;
|
299 |
-
case '/' :
|
300 |
-
$result .= '/';
|
301 |
-
break;
|
302 |
-
case 'b' :
|
303 |
-
$result .= chr(8);
|
304 |
-
break;
|
305 |
-
case 'f' :
|
306 |
-
$result .= chr(12);
|
307 |
-
break;
|
308 |
-
case 'n' :
|
309 |
-
$result .= chr(10);
|
310 |
-
break;
|
311 |
-
case 'r' :
|
312 |
-
$result .= chr(13);
|
313 |
-
break;
|
314 |
-
case 't' :
|
315 |
-
$result .= chr(9);
|
316 |
-
break;
|
317 |
-
case '\'' :
|
318 |
-
$result .= '\'';
|
319 |
-
break;
|
320 |
-
default:
|
321 |
-
throw new Exception("Illegal escape "
|
322 |
-
. "sequence '" . $chr . "'");
|
323 |
-
}
|
324 |
-
} elseif ($chr == '"') {
|
325 |
-
break;
|
326 |
-
} else {
|
327 |
-
$result .= $chr;
|
328 |
-
}
|
329 |
-
} while ($i < $str_length);
|
330 |
-
|
331 |
-
$this->_token = self::DATUM;
|
332 |
-
//$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
|
333 |
-
$this->_tokenValue = $result;
|
334 |
-
break;
|
335 |
-
case 't':
|
336 |
-
if (($i+ 3) < $str_length && substr($str, $start, 4) == "true") {
|
337 |
-
$this->_token = self::DATUM;
|
338 |
-
}
|
339 |
-
$this->_tokenValue = true;
|
340 |
-
$i += 3;
|
341 |
-
break;
|
342 |
-
case 'f':
|
343 |
-
if (($i+ 4) < $str_length && substr($str, $start, 5) == "false") {
|
344 |
-
$this->_token = self::DATUM;
|
345 |
-
}
|
346 |
-
$this->_tokenValue = false;
|
347 |
-
$i += 4;
|
348 |
-
break;
|
349 |
-
case 'n':
|
350 |
-
if (($i+ 3) < $str_length && substr($str, $start, 4) == "null") {
|
351 |
-
$this->_token = self::DATUM;
|
352 |
-
}
|
353 |
-
$this->_tokenValue = NULL;
|
354 |
-
$i += 3;
|
355 |
-
break;
|
356 |
-
}
|
357 |
-
|
358 |
-
if ($this->_token != self::EOF) {
|
359 |
-
$this->_offset = $i + 1; // Consume the last token character
|
360 |
-
return($this->_token);
|
361 |
-
}
|
362 |
-
|
363 |
-
$chr = $str{$i};
|
364 |
-
if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) {
|
365 |
-
if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s',
|
366 |
-
$str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) {
|
367 |
-
|
368 |
-
$datum = $matches[0][0];
|
369 |
-
|
370 |
-
if (is_numeric($datum)) {
|
371 |
-
if (preg_match('/^0\d+$/', $datum)) {
|
372 |
-
return;
|
373 |
-
} else {
|
374 |
-
$val = intval($datum);
|
375 |
-
$fVal = floatval($datum);
|
376 |
-
$this->_tokenValue = ($val == $fVal ? $val : $fVal);
|
377 |
-
}
|
378 |
-
} else {
|
379 |
-
return;
|
380 |
-
}
|
381 |
-
|
382 |
-
$this->_token = self::DATUM;
|
383 |
-
$this->_offset = $start + strlen($datum);
|
384 |
-
}
|
385 |
-
} else {
|
386 |
-
return;
|
387 |
-
}
|
388 |
-
|
389 |
-
return($this->_token);
|
390 |
-
}
|
391 |
-
}
|
392 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
languages/twitter-widget-pro.pot
CHANGED
@@ -7,7 +7,7 @@ msgid ""
|
|
7 |
msgstr ""
|
8 |
"Project-Id-Version: PACKAGE VERSION\n"
|
9 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/twitter-widget-pro\n"
|
10 |
-
"POT-Creation-Date: 2009-
|
11 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
12 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
@@ -16,192 +16,212 @@ msgstr ""
|
|
16 |
"Content-Transfer-Encoding: 8bit\n"
|
17 |
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
18 |
|
19 |
-
#: wp-twitter-widget.php:
|
20 |
-
msgid "Twitter
|
21 |
-
msgstr ""
|
22 |
-
|
23 |
-
#: wp-twitter-widget.php:90
|
24 |
-
msgid "Twitter Widget Pro Options"
|
25 |
-
msgstr ""
|
26 |
-
|
27 |
-
#: wp-twitter-widget.php:96
|
28 |
-
msgid "Click for Help!"
|
29 |
msgstr ""
|
30 |
|
31 |
-
#: wp-twitter-widget.php:
|
32 |
-
msgid "
|
33 |
msgstr ""
|
34 |
|
35 |
-
#: wp-twitter-widget.php:
|
36 |
-
msgid "
|
37 |
msgstr ""
|
38 |
|
39 |
-
#: wp-twitter-widget.php:
|
40 |
-
msgid ""
|
41 |
-
"You can help by sending anonymous system information that will help Xavisys "
|
42 |
-
"make better decisions about new features."
|
43 |
msgstr ""
|
44 |
|
45 |
-
#: wp-twitter-widget.php:
|
46 |
-
msgid ""
|
47 |
-
"The information will be sent anonymously, but a unique identifier will be "
|
48 |
-
"sent to prevent duplicate entries from the same installation."
|
49 |
msgstr ""
|
50 |
|
51 |
-
#: wp-twitter-widget.php:
|
52 |
-
msgid "
|
53 |
msgstr ""
|
54 |
|
55 |
-
#: wp-twitter-widget.php:
|
56 |
-
msgid "
|
57 |
msgstr ""
|
58 |
|
59 |
-
#: wp-twitter-widget.php:
|
60 |
-
msgid "
|
61 |
msgstr ""
|
62 |
|
63 |
-
#: wp-twitter-widget.php:
|
64 |
-
msgid "
|
65 |
msgstr ""
|
66 |
|
67 |
-
#: wp-twitter-widget.php:
|
68 |
-
|
69 |
-
msgid "from %s"
|
70 |
msgstr ""
|
71 |
|
72 |
-
#: wp-twitter-widget.php:
|
73 |
-
|
74 |
-
msgid "in reply to %s"
|
75 |
msgstr ""
|
76 |
|
77 |
-
#: wp-twitter-widget.php:
|
78 |
-
|
79 |
-
msgid ""
|
80 |
-
"Powered by <a href=\"%s\" title=\"Get Twitter Widget for your WordPress site"
|
81 |
-
"\">WordPress Twitter Widget Pro</a>"
|
82 |
msgstr ""
|
83 |
|
84 |
-
#: wp-twitter-widget.php:
|
85 |
-
msgid "
|
86 |
msgstr ""
|
87 |
|
88 |
-
#: wp-twitter-widget.php:
|
89 |
-
msgid "
|
90 |
msgstr ""
|
91 |
|
92 |
-
#: wp-twitter-widget.php:
|
93 |
-
msgid "
|
94 |
msgstr ""
|
95 |
|
96 |
-
#: wp-twitter-widget.php:
|
97 |
-
msgid "
|
98 |
msgstr ""
|
99 |
|
100 |
-
#: wp-twitter-widget.php:
|
101 |
-
msgid "
|
102 |
msgstr ""
|
103 |
|
104 |
-
#: wp-twitter-widget.php:
|
105 |
-
msgid "
|
106 |
msgstr ""
|
107 |
|
108 |
-
#: wp-twitter-widget.php:
|
109 |
-
msgid "
|
110 |
msgstr ""
|
111 |
|
112 |
-
#: wp-twitter-widget.php:
|
113 |
-
msgid "
|
114 |
msgstr ""
|
115 |
|
116 |
-
#: wp-twitter-widget.php:
|
117 |
-
msgid "
|
118 |
msgstr ""
|
119 |
|
120 |
-
#: wp-twitter-widget.php:
|
121 |
-
msgid "
|
122 |
msgstr ""
|
123 |
|
124 |
-
#: wp-twitter-widget.php:
|
125 |
-
msgid "
|
126 |
msgstr ""
|
127 |
|
128 |
-
#: wp-twitter-widget.php:
|
129 |
-
msgid "
|
130 |
msgstr ""
|
131 |
|
132 |
-
#: wp-twitter-widget.php:
|
133 |
-
msgid "
|
134 |
msgstr ""
|
135 |
|
136 |
-
#: wp-twitter-widget.php:
|
137 |
-
|
|
|
138 |
msgstr ""
|
139 |
|
140 |
-
#: wp-twitter-widget.php:
|
141 |
-
|
|
|
142 |
msgstr ""
|
143 |
|
144 |
-
#: wp-twitter-widget.php:
|
145 |
-
|
|
|
|
|
|
|
146 |
msgstr ""
|
147 |
|
148 |
-
#: wp-twitter-widget.php:
|
149 |
-
msgid "
|
150 |
msgstr ""
|
151 |
|
152 |
-
#: wp-twitter-widget.php:
|
153 |
-
msgid "
|
154 |
msgstr ""
|
155 |
|
156 |
-
#: wp-twitter-widget.php:
|
157 |
#, php-format
|
158 |
msgid "about %s year ago"
|
159 |
msgid_plural "about %s years ago"
|
160 |
msgstr[0] ""
|
161 |
msgstr[1] ""
|
162 |
|
163 |
-
#: wp-twitter-widget.php:
|
164 |
#, php-format
|
165 |
msgid "about %s month ago"
|
166 |
msgid_plural "about %s months ago"
|
167 |
msgstr[0] ""
|
168 |
msgstr[1] ""
|
169 |
|
170 |
-
#: wp-twitter-widget.php:
|
171 |
#, php-format
|
172 |
msgid "about %s week ago"
|
173 |
msgid_plural "about %s weeks ago"
|
174 |
msgstr[0] ""
|
175 |
msgstr[1] ""
|
176 |
|
177 |
-
#: wp-twitter-widget.php:
|
178 |
#, php-format
|
179 |
msgid "about %s day ago"
|
180 |
msgid_plural "about %s days ago"
|
181 |
msgstr[0] ""
|
182 |
msgstr[1] ""
|
183 |
|
184 |
-
#: wp-twitter-widget.php:
|
185 |
#, php-format
|
186 |
msgid "about %s hour ago"
|
187 |
msgid_plural "about %s hours ago"
|
188 |
msgstr[0] ""
|
189 |
msgstr[1] ""
|
190 |
|
191 |
-
#: wp-twitter-widget.php:
|
192 |
#, php-format
|
193 |
msgid "about %s minute ago"
|
194 |
msgid_plural "about %s minutes ago"
|
195 |
msgstr[0] ""
|
196 |
msgstr[1] ""
|
197 |
|
198 |
-
#: wp-twitter-widget.php:
|
199 |
#, php-format
|
200 |
msgid "about %s second ago"
|
201 |
msgid_plural "about %s seconds ago"
|
202 |
msgstr[0] ""
|
203 |
msgstr[1] ""
|
204 |
|
205 |
-
#: wp-twitter-widget.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
msgid "Settings"
|
207 |
msgstr ""
|
7 |
msgstr ""
|
8 |
"Project-Id-Version: PACKAGE VERSION\n"
|
9 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/twitter-widget-pro\n"
|
10 |
+
"POT-Creation-Date: 2009-09-27 22:49+0000\n"
|
11 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
12 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
16 |
"Content-Transfer-Encoding: 8bit\n"
|
17 |
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
18 |
|
19 |
+
#: wp-twitter-widget.php:39
|
20 |
+
msgid "Follow a Twitter Feed"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
msgstr ""
|
22 |
|
23 |
+
#: wp-twitter-widget.php:46 wp-twitter-widget.php:449
|
24 |
+
msgid "Twitter Widget Pro"
|
25 |
msgstr ""
|
26 |
|
27 |
+
#: wp-twitter-widget.php:71
|
28 |
+
msgid "Twitter username:"
|
29 |
msgstr ""
|
30 |
|
31 |
+
#: wp-twitter-widget.php:72
|
32 |
+
msgid "username"
|
|
|
|
|
33 |
msgstr ""
|
34 |
|
35 |
+
#: wp-twitter-widget.php:75
|
36 |
+
msgid "Give the feed a title (optional):"
|
|
|
|
|
37 |
msgstr ""
|
38 |
|
39 |
+
#: wp-twitter-widget.php:76
|
40 |
+
msgid "title"
|
41 |
msgstr ""
|
42 |
|
43 |
+
#: wp-twitter-widget.php:79
|
44 |
+
msgid "How many items would you like to display?"
|
45 |
msgstr ""
|
46 |
|
47 |
+
#: wp-twitter-widget.php:90
|
48 |
+
msgid "Hide @replies"
|
49 |
msgstr ""
|
50 |
|
51 |
+
#: wp-twitter-widget.php:93
|
52 |
+
msgid "What to display when Twitter is down (optional):"
|
53 |
msgstr ""
|
54 |
|
55 |
+
#: wp-twitter-widget.php:94
|
56 |
+
msgid "errmsg"
|
|
|
57 |
msgstr ""
|
58 |
|
59 |
+
#: wp-twitter-widget.php:97
|
60 |
+
msgid "Number of seconds to wait for a response from Twitter (default 2):"
|
|
|
61 |
msgstr ""
|
62 |
|
63 |
+
#: wp-twitter-widget.php:98
|
64 |
+
msgid "fetchTimeOut"
|
|
|
|
|
|
|
65 |
msgstr ""
|
66 |
|
67 |
+
#: wp-twitter-widget.php:101
|
68 |
+
msgid "Show date/time of Tweet (rather than 2 ____ ago):"
|
69 |
msgstr ""
|
70 |
|
71 |
+
#: wp-twitter-widget.php:103
|
72 |
+
msgid "Always"
|
73 |
msgstr ""
|
74 |
|
75 |
+
#: wp-twitter-widget.php:104
|
76 |
+
msgid "If over an hour old"
|
77 |
msgstr ""
|
78 |
|
79 |
+
#: wp-twitter-widget.php:105
|
80 |
+
msgid "If over a day old"
|
81 |
msgstr ""
|
82 |
|
83 |
+
#: wp-twitter-widget.php:106
|
84 |
+
msgid "If over a week old"
|
85 |
msgstr ""
|
86 |
|
87 |
+
#: wp-twitter-widget.php:107
|
88 |
+
msgid "If over a month old"
|
89 |
msgstr ""
|
90 |
|
91 |
+
#: wp-twitter-widget.php:108
|
92 |
+
msgid "If over a year old"
|
93 |
msgstr ""
|
94 |
|
95 |
+
#: wp-twitter-widget.php:109
|
96 |
+
msgid "Never"
|
97 |
msgstr ""
|
98 |
|
99 |
+
#: wp-twitter-widget.php:114
|
100 |
+
msgid "Hide RSS Icon and Link"
|
101 |
msgstr ""
|
102 |
|
103 |
+
#: wp-twitter-widget.php:118
|
104 |
+
msgid "Show Profile Image"
|
105 |
msgstr ""
|
106 |
|
107 |
+
#: wp-twitter-widget.php:122
|
108 |
+
msgid "Show Link to Twitter Widget Pro"
|
109 |
msgstr ""
|
110 |
|
111 |
+
#: wp-twitter-widget.php:176
|
112 |
+
msgid "Syndicate this content"
|
113 |
msgstr ""
|
114 |
|
115 |
+
#: wp-twitter-widget.php:194
|
116 |
+
msgid "No Tweets Available"
|
117 |
msgstr ""
|
118 |
|
119 |
+
#: wp-twitter-widget.php:211
|
120 |
+
#, php-format
|
121 |
+
msgid "from %s"
|
122 |
msgstr ""
|
123 |
|
124 |
+
#: wp-twitter-widget.php:215
|
125 |
+
#, php-format
|
126 |
+
msgid "in reply to %s"
|
127 |
msgstr ""
|
128 |
|
129 |
+
#: wp-twitter-widget.php:239
|
130 |
+
#, php-format
|
131 |
+
msgid ""
|
132 |
+
"Powered by <a href=\"%s\" title=\"Get Twitter Widget for your WordPress site"
|
133 |
+
"\">WordPress Twitter Widget Pro</a>"
|
134 |
msgstr ""
|
135 |
|
136 |
+
#: wp-twitter-widget.php:295
|
137 |
+
msgid "Invalid Twitter Response."
|
138 |
msgstr ""
|
139 |
|
140 |
+
#: wp-twitter-widget.php:309
|
141 |
+
msgid "Could not connect to Twitter"
|
142 |
msgstr ""
|
143 |
|
144 |
+
#: wp-twitter-widget.php:372
|
145 |
#, php-format
|
146 |
msgid "about %s year ago"
|
147 |
msgid_plural "about %s years ago"
|
148 |
msgstr[0] ""
|
149 |
msgstr[1] ""
|
150 |
|
151 |
+
#: wp-twitter-widget.php:373
|
152 |
#, php-format
|
153 |
msgid "about %s month ago"
|
154 |
msgid_plural "about %s months ago"
|
155 |
msgstr[0] ""
|
156 |
msgstr[1] ""
|
157 |
|
158 |
+
#: wp-twitter-widget.php:374
|
159 |
#, php-format
|
160 |
msgid "about %s week ago"
|
161 |
msgid_plural "about %s weeks ago"
|
162 |
msgstr[0] ""
|
163 |
msgstr[1] ""
|
164 |
|
165 |
+
#: wp-twitter-widget.php:375
|
166 |
#, php-format
|
167 |
msgid "about %s day ago"
|
168 |
msgid_plural "about %s days ago"
|
169 |
msgstr[0] ""
|
170 |
msgstr[1] ""
|
171 |
|
172 |
+
#: wp-twitter-widget.php:376
|
173 |
#, php-format
|
174 |
msgid "about %s hour ago"
|
175 |
msgid_plural "about %s hours ago"
|
176 |
msgstr[0] ""
|
177 |
msgstr[1] ""
|
178 |
|
179 |
+
#: wp-twitter-widget.php:377
|
180 |
#, php-format
|
181 |
msgid "about %s minute ago"
|
182 |
msgid_plural "about %s minutes ago"
|
183 |
msgstr[0] ""
|
184 |
msgstr[1] ""
|
185 |
|
186 |
+
#: wp-twitter-widget.php:378
|
187 |
#, php-format
|
188 |
msgid "about %s second ago"
|
189 |
msgid_plural "about %s seconds ago"
|
190 |
msgstr[0] ""
|
191 |
msgstr[1] ""
|
192 |
|
193 |
+
#: wp-twitter-widget.php:465
|
194 |
+
msgid "Twitter Widget Pro Options"
|
195 |
+
msgstr ""
|
196 |
+
|
197 |
+
#: wp-twitter-widget.php:471
|
198 |
+
msgid "Click for Help!"
|
199 |
+
msgstr ""
|
200 |
+
|
201 |
+
#: wp-twitter-widget.php:472
|
202 |
+
msgid "System Information:"
|
203 |
+
msgstr ""
|
204 |
+
|
205 |
+
#: wp-twitter-widget.php:477
|
206 |
+
msgid "I agree to send anonymous system information"
|
207 |
+
msgstr ""
|
208 |
+
|
209 |
+
#: wp-twitter-widget.php:479
|
210 |
+
msgid ""
|
211 |
+
"You can help by sending anonymous system information that will help Xavisys "
|
212 |
+
"make better decisions about new features."
|
213 |
+
msgstr ""
|
214 |
+
|
215 |
+
#: wp-twitter-widget.php:480
|
216 |
+
msgid ""
|
217 |
+
"The information will be sent anonymously, but a unique identifier will be "
|
218 |
+
"sent to prevent duplicate entries from the same installation."
|
219 |
+
msgstr ""
|
220 |
+
|
221 |
+
#: wp-twitter-widget.php:486
|
222 |
+
msgid "Update Options »"
|
223 |
+
msgstr ""
|
224 |
+
|
225 |
+
#: wp-twitter-widget.php:579
|
226 |
msgid "Settings"
|
227 |
msgstr ""
|
readme.txt
CHANGED
@@ -2,9 +2,9 @@
|
|
2 |
Contributors: aaroncampbell
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=paypal%40xavisys%2ecom&item_name=Twitter%20Widget%20Pro&no_shipping=0&no_note=1&tax=0¤cy_code=USD&lc=US&bn=PP%2dDonationsBF&charset=UTF%2d8
|
4 |
Tags: twitter, widget, feed
|
5 |
-
Requires at least: 2.
|
6 |
-
Tested up to: 2.8.
|
7 |
-
Stable tag:
|
8 |
|
9 |
A widget that properly handles twitter feeds, including parsing @username, #hashtags, and URLs into links. Requires PHP5.
|
10 |
|
@@ -46,6 +46,11 @@ Aparently the database queries required to display the friends feed was causing
|
|
46 |
|
47 |
== Changelog ==
|
48 |
|
|
|
|
|
|
|
|
|
|
|
49 |
= 1.5.1 =
|
50 |
* Re-enables the caching that got inadvertantly disabled in 1.5.0.
|
51 |
|
2 |
Contributors: aaroncampbell
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=paypal%40xavisys%2ecom&item_name=Twitter%20Widget%20Pro&no_shipping=0&no_note=1&tax=0¤cy_code=USD&lc=US&bn=PP%2dDonationsBF&charset=UTF%2d8
|
4 |
Tags: twitter, widget, feed
|
5 |
+
Requires at least: 2.8
|
6 |
+
Tested up to: 2.8.4
|
7 |
+
Stable tag: 2.0.0
|
8 |
|
9 |
A widget that properly handles twitter feeds, including parsing @username, #hashtags, and URLs into links. Requires PHP5.
|
10 |
|
46 |
|
47 |
== Changelog ==
|
48 |
|
49 |
+
= 2.0.0 =
|
50 |
+
* Completely rewitten to use the new widget class introduced in WordPress 2.8
|
51 |
+
* Now uses the json class that will be included in WordPress 2.9 for anyone on PHP < 5.2
|
52 |
+
* The "Show Link to Twitter Widget Pro" is now off by default to comply with the latest decisions regarding the plugin repository
|
53 |
+
|
54 |
= 1.5.1 =
|
55 |
* Re-enables the caching that got inadvertantly disabled in 1.5.0.
|
56 |
|
upgrade.html
CHANGED
@@ -1,4 +1,7 @@
|
|
1 |
<p><a href="http://wordpress.org/extend/plugins/twitter-widget-pro/changelog/">Change Log</a></p>
|
2 |
<ul style="list-style: disc inside; padding: 5px 0 0 15px; font-weight: normal;">
|
3 |
-
<li>
|
|
|
|
|
|
|
4 |
</ul>
|
1 |
<p><a href="http://wordpress.org/extend/plugins/twitter-widget-pro/changelog/">Change Log</a></p>
|
2 |
<ul style="list-style: disc inside; padding: 5px 0 0 15px; font-weight: normal;">
|
3 |
+
<li style="color:red; font-weight:bold;">Now requires WordPress 2.8 and still required PHP 5+</li>
|
4 |
+
<li>Completely rewitten to use the new widget class introduced in WordPress 2.8</li>
|
5 |
+
<li>Now uses the json class that will be included in WordPress 2.9 for anyone on PHP < 5.2</li>
|
6 |
+
<li>The "Show Link to Twitter Widget Pro" is now off by default to comply with the latest decisions regarding the plugin repository</li>
|
7 |
</ul>
|
wp-twitter-widget.php
CHANGED
@@ -3,334 +3,186 @@
|
|
3 |
* Plugin Name: Twitter Widget Pro
|
4 |
* Plugin URI: http://xavisys.com/wordpress-twitter-widget/
|
5 |
* Description: A widget that properly handles twitter feeds, including @username, #hashtag, and link parsing. It can even display profile images for the users. Requires PHP5.
|
6 |
-
* Version:
|
7 |
* Author: Aaron D. Campbell
|
8 |
* Author URI: http://xavisys.com/
|
9 |
* Text Domain: twitter-widget-pro
|
10 |
*/
|
11 |
|
12 |
-
/*
|
|
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
*/
|
28 |
-
/**
|
29 |
-
* wpTwitterWidget is the class that handles ALL of the plugin functionality.
|
30 |
-
* It helps us avoid name collisions
|
31 |
-
* http://codex.wordpress.org/Writing_a_Plugin#Avoiding_Function_Name_Collisions
|
32 |
-
*/
|
33 |
|
34 |
class wpTwitterWidgetException extends Exception {}
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
* Repository base url
|
52 |
-
*
|
53 |
-
* @since 1.4.4
|
54 |
-
* @var string
|
55 |
-
*/
|
56 |
-
private $_reposUrl = 'http://plugins.svn.wordpress.org/';
|
57 |
-
|
58 |
-
public function __construct() {
|
59 |
-
/**
|
60 |
-
* Add update messages that can be attached to the CURRENT release (not
|
61 |
-
* this one), but only for 2.8+
|
62 |
-
*/
|
63 |
-
global $wp_version;
|
64 |
-
if ( version_compare('2.8', $wp_version, '<=') ) {
|
65 |
-
add_action ( 'in_plugin_update_message-'.plugin_basename ( __FILE__ ) , array ( $this , '_changelog' ), null, 2 );
|
66 |
-
}
|
67 |
-
}
|
68 |
|
69 |
-
|
70 |
-
register_setting( 'twitter_widget_pro_options', 'twitter_widget_pro' );
|
71 |
}
|
72 |
|
73 |
-
|
74 |
-
|
75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
|
77 |
-
|
78 |
-
$lang_dir = basename(dirname(__FILE__)) . '/languages';
|
79 |
-
load_plugin_textdomain('twitter-widget-pro', 'wp-content/plugins/' . $lang_dir, $lang_dir);
|
80 |
}
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
*/
|
85 |
-
public function options() {
|
86 |
-
//Get our options
|
87 |
-
$this->_getSettings();
|
88 |
?>
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
<?php
|
|
|
116 |
}
|
117 |
|
118 |
-
public function
|
119 |
-
$
|
120 |
-
$response = wp_remote_get ( $url );
|
121 |
-
$code = (int) wp_remote_retrieve_response_code ( $response );
|
122 |
-
if ( $code == 200 ) {
|
123 |
-
echo wp_remote_retrieve_body ( $response );
|
124 |
-
}
|
125 |
-
}
|
126 |
-
|
127 |
-
/**
|
128 |
-
* Pulls the JSON feed from Twitter and returns an array of objects
|
129 |
-
*
|
130 |
-
* @param array $widgetOptions - settings needed to get feed url, etc
|
131 |
-
* @return array
|
132 |
-
*/
|
133 |
-
private function _parseFeed($widgetOptions) {
|
134 |
-
$feedUrl = $this->_getFeedUrl($widgetOptions);
|
135 |
-
$resp = wp_remote_request($feedUrl, array('timeout' => $widgetOptions['fetchTimeOut']));
|
136 |
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
} else {
|
141 |
-
require_once('json_decode.php');
|
142 |
-
$decodedResponse = Zend_Json_Decoder::decode($resp['body']);
|
143 |
-
}
|
144 |
-
if ( empty($decodedResponse) ) {
|
145 |
-
if (empty($widgetOptions['errmsg'])) {
|
146 |
-
$widgetOptions['errmsg'] = __('Invalid Twitter Response.', 'twitter-widget-pro');
|
147 |
-
}
|
148 |
-
throw new wpTwitterWidgetException($widgetOptions['errmsg']);
|
149 |
-
} elseif( !empty($decodedResponse->error) ) {
|
150 |
-
if (empty($widgetOptions['errmsg'])) {
|
151 |
-
$widgetOptions['errmsg'] = $decodedResponse->error;
|
152 |
-
}
|
153 |
-
throw new wpTwitterWidgetException($widgetOptions['errmsg']);
|
154 |
-
} else {
|
155 |
-
return $decodedResponse;
|
156 |
-
}
|
157 |
-
} else {
|
158 |
-
// Failed to fetch url;
|
159 |
-
if (empty($widgetOptions['errmsg'])) {
|
160 |
-
$widgetOptions['errmsg'] = __('Could not connect to Twitter', 'twitter-widget-pro');
|
161 |
-
}
|
162 |
-
throw new wpTwitterWidgetException($widgetOptions['errmsg']);
|
163 |
-
}
|
164 |
-
}
|
165 |
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
* @param string[optional] $type - 'rss' or 'json'
|
171 |
-
* @param bool[optional] $count - If true, it adds the count parameter to the URL
|
172 |
-
* @return string - Twitter feed URL
|
173 |
-
*/
|
174 |
-
private function _getFeedUrl($widgetOptions, $type = 'json', $count = true) {
|
175 |
-
if (!in_array($type, array('rss', 'json'))) {
|
176 |
-
$type = 'json';
|
177 |
-
}
|
178 |
-
if ( $count ) {
|
179 |
-
$num = ($widgetOptions['hidereplies'])? 100:$widgetOptions['items'];
|
180 |
-
$count = sprintf('?count=%u', $num);
|
181 |
-
} else {
|
182 |
-
$count = '';
|
183 |
}
|
184 |
-
return sprintf('http://twitter.com/statuses/user_timeline/%1$s.%2$s%3$s', $widgetOptions['username'], $type, $count);
|
185 |
-
}
|
186 |
|
187 |
-
|
188 |
-
* Replace @username with a link to that twitter user
|
189 |
-
*
|
190 |
-
* @param string $text - Tweet text
|
191 |
-
* @return string - Tweet text with @replies linked
|
192 |
-
*/
|
193 |
-
public function linkTwitterUsers($text) {
|
194 |
-
$text = preg_replace('/(^|\s)@(\w*)/i', '$1<a href="http://twitter.com/$2" class="twitter-user">@$2</a>', $text);
|
195 |
-
return $text;
|
196 |
}
|
197 |
|
198 |
-
|
199 |
-
|
200 |
-
*
|
201 |
-
* @param string $text - Tweet text
|
202 |
-
* @return string - Tweet text with #hashtags linked
|
203 |
-
*/
|
204 |
-
public function linkHashtags($text) {
|
205 |
-
$text = preg_replace_callback('/(^|\s)(#\w*)/i', array($this, '_hashtagLink'), $text);
|
206 |
-
return $text;
|
207 |
}
|
208 |
|
209 |
-
|
210 |
-
|
211 |
-
*
|
212 |
-
* @param array $matches - Tweet text
|
213 |
-
* @return string - Tweet text with #hashtags linked
|
214 |
-
*/
|
215 |
-
private function _hashtagLink($matches) {
|
216 |
-
return "{$matches[1]}<a href='http://search.twitter.com/search?q="
|
217 |
-
. urlencode($matches[2])
|
218 |
-
. "' class='twitter-hashtag'>{$matches[2]}</a>";
|
219 |
-
}
|
220 |
-
|
221 |
-
/**
|
222 |
-
* Turn URLs into links
|
223 |
-
*
|
224 |
-
* @param string $text - Tweet text
|
225 |
-
* @return string - Tweet text with URLs repalced with links
|
226 |
-
*/
|
227 |
-
public function linkUrls($text) {
|
228 |
-
/**
|
229 |
-
* match protocol://address/path/file.extension?some=variable&another=asf%
|
230 |
-
* $1 is a possible space, this keeps us from linking href="[link]" etc
|
231 |
-
* $2 is the whole URL
|
232 |
-
* $3 is protocol://
|
233 |
-
* $4 is the URL without the protocol://
|
234 |
-
* $5 is the URL parameters
|
235 |
-
*/
|
236 |
-
$text = preg_replace("/(^|\s)(([a-zA-Z]+:\/\/)([a-z][a-z0-9_\..-]*[a-z]{2,6})([a-zA-Z0-9~\/*-?&%]*))/i", "$1<a href=\"$2\">$2</a>", $text);
|
237 |
-
|
238 |
-
/**
|
239 |
-
* match www.something.domain/path/file.extension?some=variable&another=asf%
|
240 |
-
* $1 is a possible space, this keeps us from linking href="[link]" etc
|
241 |
-
* $2 is the whole URL that was matched. The protocol is missing, so we assume http://
|
242 |
-
* $3 is www.
|
243 |
-
* $4 is the URL matched without the www.
|
244 |
-
* $5 is the URL parameters
|
245 |
-
*/
|
246 |
-
$text = preg_replace("/(^|\s)(www\.([a-z][a-z0-9_\..-]*[a-z]{2,6})([a-zA-Z0-9~\/*-?&%]*))/i", "$1<a href=\"http://$2\">$2</a>", $text);
|
247 |
-
|
248 |
-
return $text;
|
249 |
-
}
|
250 |
-
|
251 |
-
/**
|
252 |
-
* Gets tweets, from cache if possible
|
253 |
-
*
|
254 |
-
* @param array $widgetOptions - options needed to get feeds
|
255 |
-
* @return array - Array of objects
|
256 |
-
*/
|
257 |
-
private function _getTweets($widgetOptions) {
|
258 |
-
$feedHash = sha1($this->_getFeedUrl($widgetOptions));
|
259 |
-
$tweets = get_option("wptw-{$feedHash}");
|
260 |
-
$cacheAge = get_option("wptw-{$feedHash}-time");
|
261 |
-
//If we don't have cache or it's more than 5 minutes old
|
262 |
-
if ( empty($tweets) || (time() - $cacheAge) > 300 ) {
|
263 |
-
try {
|
264 |
-
$tweets = $this->_parseFeed($widgetOptions);
|
265 |
-
update_option("wptw-{$feedHash}", $tweets);
|
266 |
-
update_option("wptw-{$feedHash}-time", time());
|
267 |
-
} catch (wpTwitterWidgetException $e) {
|
268 |
-
throw $e;
|
269 |
-
}
|
270 |
-
}
|
271 |
-
return $tweets;
|
272 |
-
}
|
273 |
-
|
274 |
-
/**
|
275 |
-
* Displays the Twitter widget, with all tweets in an unordered list.
|
276 |
-
* Things are classed but not styled to allow easy styling.
|
277 |
-
*
|
278 |
-
* @param array $args - Widget Settings
|
279 |
-
* @param array|int $widget_args - Widget Number
|
280 |
-
*/
|
281 |
-
public function display($args, $widget_args = 1) {
|
282 |
-
extract( $args, EXTR_SKIP );
|
283 |
-
if ( is_numeric($widget_args) )
|
284 |
-
$widget_args = array( 'number' => $widget_args );
|
285 |
-
$widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
|
286 |
-
extract( $widget_args, EXTR_SKIP );
|
287 |
-
|
288 |
-
$options = get_option('widget_twitter');
|
289 |
-
if ( !isset($options[$number]) ) {
|
290 |
-
return;
|
291 |
-
}
|
292 |
|
293 |
// Validate our options
|
294 |
-
$
|
295 |
-
if ( $
|
296 |
-
$
|
297 |
}
|
298 |
-
if (!isset($
|
299 |
-
$
|
300 |
}
|
301 |
|
302 |
-
$options[$number]['hiderss'] = (isset($options[$number]['hiderss']) && $options[$number]['hiderss']);
|
303 |
-
$options[$number]['hidereplies'] = (isset($options[$number]['hidereplies']) && $options[$number]['hidereplies']);
|
304 |
-
$options[$number]['avatar'] = (isset($options[$number]['avatar']) && $options[$number]['avatar']);
|
305 |
-
$options[$number]['showXavisysLink'] = (!isset($options[$number]['showXavisysLink']) || $options[$number]['showXavisysLink'] != 'false');
|
306 |
-
|
307 |
-
|
308 |
try {
|
309 |
-
$tweets = $this->_getTweets($
|
310 |
} catch (wpTwitterWidgetException $e) {
|
311 |
$tweets = $e;
|
312 |
}
|
313 |
|
314 |
-
echo $before_widget . '<div>';
|
315 |
|
316 |
// If "hide rss" hasn't been checked, show the linked icon
|
317 |
-
if (
|
318 |
if ( file_exists(dirname(__FILE__) . '/rss.png') ) {
|
319 |
$icon = str_replace(ABSPATH, get_option('siteurl').'/', dirname(__FILE__)) . '/rss.png';
|
320 |
} else {
|
321 |
$icon = get_option('siteurl').'/wp-includes/images/rss.png';
|
322 |
}
|
323 |
-
$feedUrl = $this->_getFeedUrl($
|
324 |
-
$before_title .= "<a class='twitterwidget' href='{$feedUrl}' title='" . attribute_escape(__('Syndicate this content', 'twitter-widget-pro')) ."'><img style='background:orange;color:white;border:none;' width='14' height='14' src='{$icon}' alt='RSS' /></a> ";
|
325 |
}
|
326 |
-
$twitterLink = 'http://twitter.com/' . $
|
327 |
-
$before_title .= "<a class='twitterwidget' href='{$twitterLink}' title='" . attribute_escape("Twitter: {$
|
328 |
-
$after_title = '</a>' . $after_title;
|
329 |
-
if (empty($
|
330 |
-
$
|
331 |
}
|
332 |
-
echo $before_title . $
|
333 |
-
if (!is_a($tweets, 'wpTwitterWidgetException') && !empty($tweets[0]) && $
|
334 |
echo '<div class="twitter-avatar">';
|
335 |
echo $this->_getProfileImage($tweets[0]->user);
|
336 |
echo '</div>';
|
@@ -343,9 +195,9 @@ class wpTwitterWidget
|
|
343 |
} else {
|
344 |
$count = 0;
|
345 |
foreach ($tweets as $tweet) {
|
346 |
-
if (
|
347 |
// Set our "ago" string which converts the date to "# ___(s) ago"
|
348 |
-
$tweet->ago = $this->_timeSince(strtotime($tweet->created_at), $
|
349 |
?>
|
350 |
<li>
|
351 |
<span class="entry-content"><?php echo apply_filters( 'widget_twitter_content', $tweet->text ); ?></span>
|
@@ -373,14 +225,14 @@ replyTo;
|
|
373 |
</span>
|
374 |
</li>
|
375 |
<?php
|
376 |
-
if (++$count >= $
|
377 |
break;
|
378 |
}
|
379 |
}
|
380 |
}
|
381 |
}
|
382 |
|
383 |
-
if ($
|
384 |
?>
|
385 |
<li class="xavisys-link">
|
386 |
<span class="xavisys-link-text">
|
@@ -389,212 +241,96 @@ replyTo;
|
|
389 |
</li>
|
390 |
<?php
|
391 |
}
|
392 |
-
echo '</ul></div>' . $after_widget;
|
393 |
}
|
394 |
|
395 |
/**
|
396 |
-
*
|
397 |
*
|
398 |
-
* @param
|
399 |
-
* @return
|
400 |
*/
|
401 |
-
private function
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
407 |
}
|
408 |
|
409 |
/**
|
410 |
-
*
|
411 |
*
|
412 |
-
* @param
|
413 |
-
* @return
|
414 |
*/
|
415 |
-
private function
|
416 |
-
|
417 |
-
|
418 |
-
<a title="{$user->name}" href="http://twitter.com/{$user->screen_name}">{$user->screen_name}</a>
|
419 |
-
</strong>
|
420 |
-
profileImage;
|
421 |
-
}
|
422 |
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
public function control($widget_args) {
|
429 |
-
global $wp_registered_widgets;
|
430 |
-
static $updated = false;
|
431 |
-
|
432 |
-
if ( is_numeric($widget_args) )
|
433 |
-
$widget_args = array( 'number' => $widget_args );
|
434 |
-
$widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
|
435 |
-
extract( $widget_args, EXTR_SKIP );
|
436 |
-
|
437 |
-
$options = get_option('widget_twitter');
|
438 |
-
|
439 |
-
if ( !is_array($options) )
|
440 |
-
$options = array();
|
441 |
-
|
442 |
-
if ( !$updated && !empty($_POST['sidebar']) ) {
|
443 |
-
$sidebar = (string) $_POST['sidebar'];
|
444 |
-
|
445 |
-
$sidebars_widgets = wp_get_sidebars_widgets();
|
446 |
-
if ( isset($sidebars_widgets[$sidebar]) )
|
447 |
-
$this_sidebar =& $sidebars_widgets[$sidebar];
|
448 |
-
else
|
449 |
-
$this_sidebar = array();
|
450 |
-
|
451 |
-
foreach ( $this_sidebar as $_widget_id ) {
|
452 |
-
if ( array($this,'display') == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) {
|
453 |
-
$widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number'];
|
454 |
-
if ( !in_array( "twitter-$widget_number", $_POST['widget-id'] ) ) // the widget has been removed.
|
455 |
-
unset($options[$widget_number]);
|
456 |
-
}
|
457 |
-
}
|
458 |
|
459 |
-
|
460 |
-
|
461 |
-
|
|
|
462 |
|
463 |
-
$
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
$
|
468 |
}
|
469 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
470 |
}
|
471 |
-
|
472 |
-
update_option('widget_twitter', $options);
|
473 |
-
$updated = true;
|
474 |
-
}
|
475 |
-
|
476 |
-
if ( -1 != $number ) {
|
477 |
-
$options[$number]['number'] = $number;
|
478 |
-
$options[$number]['title'] = attribute_escape($options[$number]['title']);
|
479 |
-
$options[$number]['errmsg'] = attribute_escape($options[$number]['errmsg']);
|
480 |
-
$options[$number]['fetchTimeOut'] = attribute_escape($options[$number]['fetchTimeOut']);
|
481 |
-
$options[$number]['username'] = attribute_escape($options[$number]['username']);
|
482 |
-
$options[$number]['hiderss'] = (bool) $options[$number]['hiderss'];
|
483 |
-
$options[$number]['hidereplies'] = (bool) $options[$number]['hidereplies'];
|
484 |
-
$options[$number]['avatar'] = (bool) $options[$number]['avatar'];
|
485 |
-
$options[$number]['showXavisysLink'] = (!isset($options[$number]['showXavisysLink']) || $options[$number]['showXavisysLink'] != 'false');
|
486 |
-
}
|
487 |
-
// Fix Undefined offset Notice
|
488 |
-
if ( empty($options[$number]) ) {
|
489 |
-
$options[$number] = array();
|
490 |
}
|
491 |
-
$this->_showForm($options[$number]);
|
492 |
}
|
493 |
|
494 |
/**
|
495 |
-
*
|
496 |
*
|
497 |
-
* @
|
|
|
|
|
|
|
498 |
*/
|
499 |
-
|
500 |
-
if (
|
501 |
-
$
|
502 |
-
$widget_ops = array('classname' => 'widget_twitter', 'description' => __('Follow a Twitter Feed', 'twitter-widget-pro'));
|
503 |
-
$control_ops = array('width' => 400, 'height' => 350, 'id_base' => 'twitter');
|
504 |
-
$name = __('Twitter Widget Pro', 'twitter-widget-pro');
|
505 |
-
|
506 |
-
$id = false;
|
507 |
-
foreach ( array_keys($options) as $o ) {
|
508 |
-
// Old widgets can have null values for some reason
|
509 |
-
if ( !isset($options[$o]['title']) || !isset($options[$o]['username']) )
|
510 |
-
continue;
|
511 |
-
$id = "twitter-$o"; // Never never never translate an id
|
512 |
-
wp_register_sidebar_widget($id, $name, array($this,'display'), $widget_ops, array( 'number' => $o ));
|
513 |
-
wp_register_widget_control($id, $name, array($this,'control'), $control_ops, array( 'number' => $o ));
|
514 |
}
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
}
|
521 |
-
|
522 |
-
|
523 |
-
/**
|
524 |
-
* Displays the actualy for that populates the widget options box in the
|
525 |
-
* admin section
|
526 |
-
*
|
527 |
-
* @param array $args - Current widget settings and widget number, gets combind with defaults
|
528 |
-
*/
|
529 |
-
private function _showForm($args) {
|
530 |
-
|
531 |
-
$defaultArgs = array( 'title' => '',
|
532 |
-
'errmsg' => '',
|
533 |
-
'fetchTimeOut' => '2',
|
534 |
-
'username' => '',
|
535 |
-
'hiderss' => false,
|
536 |
-
'hidereplies' => false,
|
537 |
-
'avatar' => false,
|
538 |
-
'showXavisysLink' => true,
|
539 |
-
'items' => 10,
|
540 |
-
'showts' => 60 * 60 * 24,
|
541 |
-
'number' => '%i%' );
|
542 |
-
|
543 |
-
$args = wp_parse_args( $args, $defaultArgs );
|
544 |
-
extract( $args );
|
545 |
-
?>
|
546 |
-
<p>
|
547 |
-
<label for="twitter-username-<?php echo $number; ?>"><?php _e('Twitter username:', 'twitter-widget-pro'); ?></label>
|
548 |
-
<input class="widefat" id="twitter-username-<?php echo $number; ?>" name="widget-twitter[<?php echo $number; ?>][username]" type="text" value="<?php echo $username; ?>" />
|
549 |
-
</p>
|
550 |
-
<p>
|
551 |
-
<label for="twitter-title-<?php echo $number; ?>"><?php _e('Give the feed a title (optional):', 'twitter-widget-pro'); ?></label>
|
552 |
-
<input class="widefat" id="twitter-title-<?php echo $number; ?>" name="widget-twitter[<?php echo $number; ?>][title]" type="text" value="<?php echo $title; ?>" />
|
553 |
-
</p>
|
554 |
-
<p>
|
555 |
-
<label for="twitter-items-<?php echo $number; ?>"><?php _e('How many items would you like to display?', 'twitter-widget-pro'); ?></label>
|
556 |
-
<select id="twitter-items-<?php echo $number; ?>" name="widget-twitter[<?php echo $number; ?>][items]">
|
557 |
-
<?php
|
558 |
-
for ( $i = 1; $i <= 20; ++$i ) {
|
559 |
-
echo "<option value='$i' ", selected($items, $i), ">$i</option>";
|
560 |
-
}
|
561 |
-
?>
|
562 |
-
</select>
|
563 |
-
</p>
|
564 |
-
<p>
|
565 |
-
<label for="twitter-hidereplies-<?php echo $number; ?>"><input class="checkbox" type="checkbox" id="twitter-hidereplies-<?php echo $number; ?>" name="widget-twitter[<?php echo $number; ?>][hidereplies]"<?php checked($hidereplies, true); ?> /> <?php _e('Hide @replies', 'twitter-widget-pro'); ?></label>
|
566 |
-
</p>
|
567 |
-
<p>
|
568 |
-
<label for="twitter-errmsg-<?php echo $number; ?>"><?php _e('What to display when Twitter is down (optional):', 'twitter-widget-pro'); ?></label>
|
569 |
-
<input class="widefat" id="twitter-errmsg-<?php echo $number; ?>" name="widget-twitter[<?php echo $number; ?>][errmsg]" type="text" value="<?php echo $errmsg; ?>" />
|
570 |
-
</p>
|
571 |
-
<p>
|
572 |
-
<label for="twitter-fetchTimeOut-<?php echo $number; ?>"><?php _e('Number of seconds to wait for a response from Twitter (default 2):', 'twitter-widget-pro'); ?></label>
|
573 |
-
<input class="widefat" id="twitter-fetchTimeOut-<?php echo $number; ?>" name="widget-twitter[<?php echo $number; ?>][fetchTimeOut]" type="text" value="<?php echo $fetchTimeOut; ?>" />
|
574 |
-
</p>
|
575 |
-
<p>
|
576 |
-
<label for="twitter-showts-<?php echo $number; ?>"><?php _e('Show date/time of Tweet (rather than 2 ____ ago):', 'twitter-widget-pro'); ?></label>
|
577 |
-
<select id="twitter-showts-<?php echo $number; ?>" name="widget-twitter[<?php echo $number; ?>][showts]">
|
578 |
-
<option value="0" <?php echo selected($showts, '0'); ?>><?php _e('Always', 'twitter-widget-pro');?></a>
|
579 |
-
<option value="3600" <?php echo selected($showts, '3600'); ?>><?php _e('If over an hour old', 'twitter-widget-pro');?></a>
|
580 |
-
<option value="86400" <?php echo selected($showts, '86400'); ?>><?php _e('If over a day old', 'twitter-widget-pro');?></a>
|
581 |
-
<option value="604800" <?php echo selected($showts, '604800'); ?>><?php _e('If over a week old', 'twitter-widget-pro');?></a>
|
582 |
-
<option value="2592000" <?php echo selected($showts, '2592000'); ?>><?php _e('If over a month old', 'twitter-widget-pro');?></a>
|
583 |
-
<option value="31536000" <?php echo selected($showts, '31536000'); ?>><?php _e('If over a year old', 'twitter-widget-pro');?></a>
|
584 |
-
<option value="-1" <?php echo selected($showts, '-1'); ?>><?php _e('Never', 'twitter-widget-pro');?></a>
|
585 |
-
</select>
|
586 |
-
</p>
|
587 |
-
<p>
|
588 |
-
<label for="twitter-hiderss-<?php echo $number; ?>"><input class="checkbox" type="checkbox" id="twitter-hiderss-<?php echo $number; ?>" name="widget-twitter[<?php echo $number; ?>][hiderss]"<?php checked($hiderss, true); ?> /> <?php _e('Hide RSS Icon and Link', 'twitter-widget-pro'); ?></label>
|
589 |
-
</p>
|
590 |
-
<p>
|
591 |
-
<label for="twitter-avatar-<?php echo $number; ?>"><input class="checkbox" type="checkbox" id="twitter-avatar-<?php echo $number; ?>" name="widget-twitter[<?php echo $number; ?>][avatar]"<?php checked($avatar, true); ?> /> <?php _e('Show Profile Image', 'twitter-widget-pro'); ?></label>
|
592 |
-
</p>
|
593 |
-
<p>
|
594 |
-
<input type="hidden" name="widget-twitter[<?php echo $number; ?>][showXavisysLink]" value="false" />
|
595 |
-
<label for="twitter-showXavisysLink-<?php echo $number; ?>"><input class="checkbox" type="checkbox" value="true" id="twitter-showXavisysLink-<?php echo $number; ?>" name="widget-twitter[<?php echo $number; ?>][showXavisysLink]"<?php checked($showXavisysLink, true); ?> /> <?php _e('Show Link to Twitter Widget Pro', 'twitter-widget-pro'); ?></label>
|
596 |
-
</p>
|
597 |
-
<?php
|
598 |
}
|
599 |
|
600 |
/**
|
@@ -608,8 +344,8 @@ profileImage;
|
|
608 |
* @return string
|
609 |
*/
|
610 |
private function _timeSince($startTimestamp, $max) {
|
611 |
-
|
612 |
-
|
613 |
'year' => 60 * 60 * 24 * 365, // 31,536,000 seconds
|
614 |
'month' => 60 * 60 * 24 * 30, // 2,592,000 seconds
|
615 |
'week' => 60 * 60 * 24 * 7, // 604,800 seconds
|
@@ -617,22 +353,22 @@ profileImage;
|
|
617 |
'hour' => 60 * 60, // 3600 seconds
|
618 |
'minute' => 60, // 60 seconds
|
619 |
'second' => 1 // 1 second
|
620 |
-
|
621 |
|
622 |
-
|
623 |
|
624 |
-
|
625 |
return date_i18n('h:i:s A F d, Y', $startTimestamp);
|
626 |
-
|
627 |
|
628 |
foreach ( $chunks as $key => $seconds ) {
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
}
|
634 |
|
635 |
-
|
636 |
'year' => _n('about %s year ago', 'about %s years ago', $count, 'twitter-widget-pro'),
|
637 |
'month' => _n('about %s month ago', 'about %s months ago', $count, 'twitter-widget-pro'),
|
638 |
'week' => _n('about %s week ago', 'about %s weeks ago', $count, 'twitter-widget-pro'),
|
@@ -640,9 +376,141 @@ profileImage;
|
|
640 |
'hour' => _n('about %s hour ago', 'about %s hours ago', $count, 'twitter-widget-pro'),
|
641 |
'minute' => _n('about %s minute ago', 'about %s minutes ago', $count, 'twitter-widget-pro'),
|
642 |
'second' => _n('about %s second ago', 'about %s seconds ago', $count, 'twitter-widget-pro'),
|
643 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
644 |
|
645 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
646 |
}
|
647 |
|
648 |
/**
|
@@ -653,7 +521,7 @@ profileImage;
|
|
653 |
$this->_getSettings();
|
654 |
if ($this->_settings['user_agreed_to_send_system_information'] == 'true') {
|
655 |
$lastSent = get_option('twp-sysinfo');
|
656 |
-
|
657 |
if (serialize($lastSent) != serialize($sysinfo)) {
|
658 |
$params = array(
|
659 |
'method' => 'POST',
|
@@ -713,20 +581,74 @@ profileImage;
|
|
713 |
}
|
714 |
return $links;
|
715 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
716 |
}
|
717 |
// Instantiate our class
|
718 |
$wpTwitterWidget = new wpTwitterWidget();
|
719 |
-
|
720 |
-
/**
|
721 |
-
* Add filters and actions
|
722 |
-
*/
|
723 |
-
add_action( 'admin_menu', array($wpTwitterWidget,'admin_menu') );
|
724 |
-
add_filter( 'init', array( $wpTwitterWidget, 'init_locale') );
|
725 |
-
add_filter( 'admin_init', array( $wpTwitterWidget, 'registerSettings') );
|
726 |
-
add_filter( 'admin_init', array( $wpTwitterWidget, 'sendSysInfo') );
|
727 |
-
add_action( 'widgets_init', array($wpTwitterWidget, 'register') );
|
728 |
-
add_filter( 'widget_twitter_content', array($wpTwitterWidget, 'linkTwitterUsers') );
|
729 |
-
add_filter( 'widget_twitter_content', array($wpTwitterWidget, 'linkUrls') );
|
730 |
-
add_filter( 'widget_twitter_content', array($wpTwitterWidget, 'linkHashtags') );
|
731 |
-
add_filter( 'widget_twitter_content', 'convert_chars' );
|
732 |
-
add_filter( 'plugin_action_links', array($wpTwitterWidget, 'addSettingLink'), 10, 2 );
|
3 |
* Plugin Name: Twitter Widget Pro
|
4 |
* Plugin URI: http://xavisys.com/wordpress-twitter-widget/
|
5 |
* Description: A widget that properly handles twitter feeds, including @username, #hashtag, and link parsing. It can even display profile images for the users. Requires PHP5.
|
6 |
+
* Version: 2.0.0
|
7 |
* Author: Aaron D. Campbell
|
8 |
* Author URI: http://xavisys.com/
|
9 |
* Text Domain: twitter-widget-pro
|
10 |
*/
|
11 |
|
12 |
+
/*
|
13 |
+
Copyright 2006-current Aaron D. Campbell (email : wp_plugins@xavisys.com)
|
14 |
|
15 |
+
This program is free software; you can redistribute it and/or modify
|
16 |
+
it under the terms of the GNU General Public License as published by
|
17 |
+
the Free Software Foundation; either version 2 of the License, or
|
18 |
+
(at your option) any later version.
|
19 |
|
20 |
+
This program is distributed in the hope that it will be useful,
|
21 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
22 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
23 |
+
GNU General Public License for more details.
|
24 |
|
25 |
+
You should have received a copy of the GNU General Public License
|
26 |
+
along with this program; if not, write to the Free Software
|
27 |
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
28 |
*/
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
class wpTwitterWidgetException extends Exception {}
|
31 |
|
32 |
+
/**
|
33 |
+
* WP_Widget_Twitter_Pro is the class that handles the main widget.
|
34 |
+
*/
|
35 |
+
class WP_Widget_Twitter_Pro extends WP_Widget {
|
36 |
+
public function WP_Widget_Twitter_Pro () {
|
37 |
+
$widget_ops = array(
|
38 |
+
'classname' => 'widget_twitter',
|
39 |
+
'description' => __( 'Follow a Twitter Feed', 'twitter-widget-pro' )
|
40 |
+
);
|
41 |
+
$control_ops = array(
|
42 |
+
'width' => 400,
|
43 |
+
'height' => 350,
|
44 |
+
'id_base' => 'twitter'
|
45 |
+
);
|
46 |
+
$name = __( 'Twitter Widget Pro', 'twitter-widget-pro' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
+
$this->WP_Widget('twitter', $name, $widget_ops, $control_ops);
|
|
|
49 |
}
|
50 |
|
51 |
+
private function _getInstanceSettings ( $instance ) {
|
52 |
+
$defaultArgs = array( 'title' => '',
|
53 |
+
'errmsg' => '',
|
54 |
+
'fetchTimeOut' => '2',
|
55 |
+
'username' => '',
|
56 |
+
'hiderss' => false,
|
57 |
+
'hidereplies' => false,
|
58 |
+
'avatar' => false,
|
59 |
+
'showXavisysLink' => false,
|
60 |
+
'items' => 10,
|
61 |
+
'showts' => 60 * 60 * 24,
|
62 |
+
);
|
63 |
|
64 |
+
return wp_parse_args( $instance, $defaultArgs );
|
|
|
|
|
65 |
}
|
66 |
|
67 |
+
public function form( $instance ) {
|
68 |
+
$instance = $this->_getInstanceSettings( $instance );
|
|
|
|
|
|
|
|
|
69 |
?>
|
70 |
+
<p>
|
71 |
+
<label for="<?php echo $this->get_field_id('username'); ?>"><?php _e('Twitter username:', 'twitter-widget-pro'); ?></label>
|
72 |
+
<input class="widefat" id="<?php echo $this->get_field_id('username'); ?>" name="<?php echo $this->get_field_name('username'); ?>" type="text" value="<?php esc_attr_e($instance['username']); ?>" />
|
73 |
+
</p>
|
74 |
+
<p>
|
75 |
+
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Give the feed a title (optional):', 'twitter-widget-pro'); ?></label>
|
76 |
+
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php esc_attr_e($instance['title']); ?>" />
|
77 |
+
</p>
|
78 |
+
<p>
|
79 |
+
<label for="<?php echo $this->get_field_id('items'); ?>"><?php _e('How many items would you like to display?', 'twitter-widget-pro'); ?></label>
|
80 |
+
<select id="<?php echo $this->get_field_id('items'); ?>" name="<?php echo $this->get_field_name('items'); ?>">
|
81 |
+
<?php
|
82 |
+
for ( $i = 1; $i <= 20; ++$i ) {
|
83 |
+
echo "<option value='$i' ". selected($instance['items'], $i, false). ">$i</option>";
|
84 |
+
}
|
85 |
+
?>
|
86 |
+
</select>
|
87 |
+
</p>
|
88 |
+
<p>
|
89 |
+
<input class="checkbox" type="checkbox" value="true" id="<?php echo $this->get_field_id('hidereplies'); ?>" name="<?php echo $this->get_field_name('hidereplies'); ?>"<?php checked($instance['hidereplies'], 'true'); ?> />
|
90 |
+
<label for="<?php echo $this->get_field_id('hidereplies'); ?>"><?php _e('Hide @replies', 'twitter-widget-pro'); ?></label>
|
91 |
+
</p>
|
92 |
+
<p>
|
93 |
+
<label for="<?php echo $this->get_field_id('errmsg'); ?>"><?php _e('What to display when Twitter is down (optional):', 'twitter-widget-pro'); ?></label>
|
94 |
+
<input class="widefat" id="<?php echo $this->get_field_id('errmsg'); ?>" name="<?php echo $this->get_field_name('errmsg'); ?>" type="text" value="<?php esc_attr_e($instance['errmsg']); ?>" />
|
95 |
+
</p>
|
96 |
+
<p>
|
97 |
+
<label for="<?php echo $this->get_field_id('fetchTimeOut'); ?>"><?php _e('Number of seconds to wait for a response from Twitter (default 2):', 'twitter-widget-pro'); ?></label>
|
98 |
+
<input class="widefat" id="<?php echo $this->get_field_id('fetchTimeOut'); ?>" name="<?php echo $this->get_field_name('fetchTimeOut'); ?>" type="text" value="<?php esc_attr_e($instance['fetchTimeOut']); ?>" />
|
99 |
+
</p>
|
100 |
+
<p>
|
101 |
+
<label for="<?php echo $this->get_field_id('showts'); ?>"><?php _e('Show date/time of Tweet (rather than 2 ____ ago):', 'twitter-widget-pro'); ?></label>
|
102 |
+
<select id="<?php echo $this->get_field_id('showts'); ?>" name="<?php echo $this->get_field_name('showts'); ?>">
|
103 |
+
<option value="0" <?php selected($instance['showts'], '0'); ?>><?php _e('Always', 'twitter-widget-pro');?></option>
|
104 |
+
<option value="3600" <?php selected($instance['showts'], '3600'); ?>><?php _e('If over an hour old', 'twitter-widget-pro');?></option>
|
105 |
+
<option value="86400" <?php selected($instance['showts'], '86400'); ?>><?php _e('If over a day old', 'twitter-widget-pro');?></option>
|
106 |
+
<option value="604800" <?php selected($instance['showts'], '604800'); ?>><?php _e('If over a week old', 'twitter-widget-pro');?></option>
|
107 |
+
<option value="2592000" <?php selected($instance['showts'], '2592000'); ?>><?php _e('If over a month old', 'twitter-widget-pro');?></option>
|
108 |
+
<option value="31536000" <?php selected($instance['showts'], '31536000'); ?>><?php _e('If over a year old', 'twitter-widget-pro');?></option>
|
109 |
+
<option value="-1" <?php selected($instance['showts'], '-1'); ?>><?php _e('Never', 'twitter-widget-pro');?></option>
|
110 |
+
</select>
|
111 |
+
</p>
|
112 |
+
<p>
|
113 |
+
<input class="checkbox" type="checkbox" value="true" id="<?php echo $this->get_field_id('hiderss'); ?>" name="<?php echo $this->get_field_name('hiderss'); ?>"<?php checked($instance['hiderss'], 'true'); ?> />
|
114 |
+
<label for="<?php echo $this->get_field_id('hiderss'); ?>"><?php _e('Hide RSS Icon and Link', 'twitter-widget-pro'); ?></label>
|
115 |
+
</p>
|
116 |
+
<p>
|
117 |
+
<input class="checkbox" type="checkbox" value="true" id="<?php echo $this->get_field_id('avatar'); ?>" name="<?php echo $this->get_field_name('avatar'); ?>"<?php checked($instance['avatar'], 'true'); ?> />
|
118 |
+
<label for="<?php echo $this->get_field_id('avatar'); ?>"><?php _e('Show Profile Image', 'twitter-widget-pro'); ?></label>
|
119 |
+
</p>
|
120 |
+
<p>
|
121 |
+
<input class="checkbox" type="checkbox" value="true" id="<?php echo $this->get_field_id('showXavisysLink'); ?>" name="<?php echo $this->get_field_name('showXavisysLink'); ?>"<?php checked($instance['showXavisysLink'], 'true'); ?> />
|
122 |
+
<label for="<?php echo $this->get_field_id('showXavisysLink'); ?>"><?php _e('Show Link to Twitter Widget Pro', 'twitter-widget-pro'); ?></label>
|
123 |
+
</p>
|
124 |
<?php
|
125 |
+
return;
|
126 |
}
|
127 |
|
128 |
+
public function update( $new_instance, $old_instance ) {
|
129 |
+
$instance = $this->_getInstanceSettings( $new_instance );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
|
131 |
+
// Clean up the free-form areas
|
132 |
+
$instance['title'] = stripslashes($new_instance['title']);
|
133 |
+
$instance['errmsg'] = stripslashes($new_instance['errmsg']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
|
135 |
+
// If the current user isn't allowed to use unfiltered HTML, filter it
|
136 |
+
if ( !current_user_can('unfiltered_html') ) {
|
137 |
+
$instance['title'] = strip_tags($new_instance['title']);
|
138 |
+
$instance['errmsg'] = strip_tags($new_instance['errmsg']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
}
|
|
|
|
|
140 |
|
141 |
+
return $instance;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
}
|
143 |
|
144 |
+
public function flush_widget_cache() {
|
145 |
+
wp_cache_delete('widget_twitter_widget_pro', 'widget');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
}
|
147 |
|
148 |
+
public function widget( $args, $instance ) {
|
149 |
+
$instance = $this->_getInstanceSettings( $instance );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
|
151 |
// Validate our options
|
152 |
+
$instance['items'] = (int) $instance['items'];
|
153 |
+
if ( $instance['items'] < 1 || 20 < $instance['items'] ) {
|
154 |
+
$instance['items'] = 10;
|
155 |
}
|
156 |
+
if (!isset($instance['showts'])) {
|
157 |
+
$instance['showts'] = 86400;
|
158 |
}
|
159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
try {
|
161 |
+
$tweets = $this->_getTweets($instance);
|
162 |
} catch (wpTwitterWidgetException $e) {
|
163 |
$tweets = $e;
|
164 |
}
|
165 |
|
166 |
+
echo $args['before_widget'] . '<div>';
|
167 |
|
168 |
// If "hide rss" hasn't been checked, show the linked icon
|
169 |
+
if ( $instance['hiderss'] != 'true' ) {
|
170 |
if ( file_exists(dirname(__FILE__) . '/rss.png') ) {
|
171 |
$icon = str_replace(ABSPATH, get_option('siteurl').'/', dirname(__FILE__)) . '/rss.png';
|
172 |
} else {
|
173 |
$icon = get_option('siteurl').'/wp-includes/images/rss.png';
|
174 |
}
|
175 |
+
$feedUrl = $this->_getFeedUrl($instance, 'rss', false);
|
176 |
+
$args['before_title'] .= "<a class='twitterwidget' href='{$feedUrl}' title='" . attribute_escape(__('Syndicate this content', 'twitter-widget-pro')) ."'><img style='background:orange;color:white;border:none;' width='14' height='14' src='{$icon}' alt='RSS' /></a> ";
|
177 |
}
|
178 |
+
$twitterLink = 'http://twitter.com/' . $instance['username'];
|
179 |
+
$args['before_title'] .= "<a class='twitterwidget' href='{$twitterLink}' title='" . attribute_escape("Twitter: {$instance['username']}") . "'>";
|
180 |
+
$args['after_title'] = '</a>' . $args['after_title'];
|
181 |
+
if (empty($instance['title'])) {
|
182 |
+
$instance['title'] = "Twitter: {$instance['username']}";
|
183 |
}
|
184 |
+
echo $args['before_title'] . $instance['title'] . $args['after_title'];
|
185 |
+
if (!is_a($tweets, 'wpTwitterWidgetException') && !empty($tweets[0]) && $instance['avatar'] == 'true') {
|
186 |
echo '<div class="twitter-avatar">';
|
187 |
echo $this->_getProfileImage($tweets[0]->user);
|
188 |
echo '</div>';
|
195 |
} else {
|
196 |
$count = 0;
|
197 |
foreach ($tweets as $tweet) {
|
198 |
+
if ( $instance['hidereplies'] != 'true' || empty($tweet->in_reply_to_user_id)) {
|
199 |
// Set our "ago" string which converts the date to "# ___(s) ago"
|
200 |
+
$tweet->ago = $this->_timeSince(strtotime($tweet->created_at), $instance['showts']);
|
201 |
?>
|
202 |
<li>
|
203 |
<span class="entry-content"><?php echo apply_filters( 'widget_twitter_content', $tweet->text ); ?></span>
|
225 |
</span>
|
226 |
</li>
|
227 |
<?php
|
228 |
+
if (++$count >= $instance['items']) {
|
229 |
break;
|
230 |
}
|
231 |
}
|
232 |
}
|
233 |
}
|
234 |
|
235 |
+
if ( $instance['showXavisysLink'] == 'true' ) {
|
236 |
?>
|
237 |
<li class="xavisys-link">
|
238 |
<span class="xavisys-link-text">
|
241 |
</li>
|
242 |
<?php
|
243 |
}
|
244 |
+
echo '</ul></div>' . $args['after_widget'];
|
245 |
}
|
246 |
|
247 |
/**
|
248 |
+
* Gets tweets, from cache if possible
|
249 |
*
|
250 |
+
* @param array $widgetOptions - options needed to get feeds
|
251 |
+
* @return array - Array of objects
|
252 |
*/
|
253 |
+
private function _getTweets($widgetOptions) {
|
254 |
+
$feedHash = sha1($this->_getFeedUrl($widgetOptions));
|
255 |
+
$tweets = get_option("wptw-{$feedHash}");
|
256 |
+
$cacheAge = get_option("wptw-{$feedHash}-time");
|
257 |
+
//If we don't have cache or it's more than 5 minutes old
|
258 |
+
if ( empty($tweets) || (time() - $cacheAge) > 300 ) {
|
259 |
+
try {
|
260 |
+
$tweets = $this->_parseFeed($widgetOptions);
|
261 |
+
update_option("wptw-{$feedHash}", $tweets);
|
262 |
+
update_option("wptw-{$feedHash}-time", time());
|
263 |
+
} catch (wpTwitterWidgetException $e) {
|
264 |
+
throw $e;
|
265 |
+
}
|
266 |
+
}
|
267 |
+
return $tweets;
|
268 |
}
|
269 |
|
270 |
/**
|
271 |
+
* Pulls the JSON feed from Twitter and returns an array of objects
|
272 |
*
|
273 |
+
* @param array $widgetOptions - settings needed to get feed url, etc
|
274 |
+
* @return array
|
275 |
*/
|
276 |
+
private function _parseFeed($widgetOptions) {
|
277 |
+
$feedUrl = $this->_getFeedUrl($widgetOptions);
|
278 |
+
$resp = wp_remote_request($feedUrl, array('timeout' => $widgetOptions['fetchTimeOut']));
|
|
|
|
|
|
|
|
|
279 |
|
280 |
+
if ( !is_wp_error($resp) && $resp['response']['code'] >= 200 && $resp['response']['code'] < 300 ) {
|
281 |
+
if (function_exists('json_decode')) {
|
282 |
+
$decodedResponse = json_decode( $resp['body'] );
|
283 |
+
} else {
|
284 |
+
global $wp_json;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
285 |
|
286 |
+
if ( !is_a($wp_json, 'Services_JSON') ) {
|
287 |
+
require_once( 'class-json.php' );
|
288 |
+
$wp_json = new Services_JSON();
|
289 |
+
}
|
290 |
|
291 |
+
$decodedResponse = $wp_json->decode( $resp['body'] );
|
292 |
+
}
|
293 |
+
if ( empty($decodedResponse) ) {
|
294 |
+
if (empty($widgetOptions['errmsg'])) {
|
295 |
+
$widgetOptions['errmsg'] = __('Invalid Twitter Response.', 'twitter-widget-pro');
|
296 |
}
|
297 |
+
throw new wpTwitterWidgetException($widgetOptions['errmsg']);
|
298 |
+
} elseif( !empty($decodedResponse->error) ) {
|
299 |
+
if (empty($widgetOptions['errmsg'])) {
|
300 |
+
$widgetOptions['errmsg'] = $decodedResponse->error;
|
301 |
+
}
|
302 |
+
throw new wpTwitterWidgetException($widgetOptions['errmsg']);
|
303 |
+
} else {
|
304 |
+
return $decodedResponse;
|
305 |
+
}
|
306 |
+
} else {
|
307 |
+
// Failed to fetch url;
|
308 |
+
if (empty($widgetOptions['errmsg'])) {
|
309 |
+
$widgetOptions['errmsg'] = __('Could not connect to Twitter', 'twitter-widget-pro');
|
310 |
}
|
311 |
+
throw new wpTwitterWidgetException($widgetOptions['errmsg']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
312 |
}
|
|
|
313 |
}
|
314 |
|
315 |
/**
|
316 |
+
* Gets the URL for the desired feed.
|
317 |
*
|
318 |
+
* @param array $widgetOptions - settings needed such as username, feet type, etc
|
319 |
+
* @param string[optional] $type - 'rss' or 'json'
|
320 |
+
* @param bool[optional] $count - If true, it adds the count parameter to the URL
|
321 |
+
* @return string - Twitter feed URL
|
322 |
*/
|
323 |
+
private function _getFeedUrl($widgetOptions, $type = 'json', $count = true) {
|
324 |
+
if (!in_array($type, array('rss', 'json'))) {
|
325 |
+
$type = 'json';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
}
|
327 |
+
if ( $count ) {
|
328 |
+
$num = ($widgetOptions['hidereplies'])? 100:$widgetOptions['items'];
|
329 |
+
$count = sprintf('?count=%u', $num);
|
330 |
+
} else {
|
331 |
+
$count = '';
|
332 |
}
|
333 |
+
return sprintf('http://twitter.com/statuses/user_timeline/%1$s.%2$s%3$s', $widgetOptions['username'], $type, $count);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
334 |
}
|
335 |
|
336 |
/**
|
344 |
* @return string
|
345 |
*/
|
346 |
private function _timeSince($startTimestamp, $max) {
|
347 |
+
// array of time period chunks
|
348 |
+
$chunks = array(
|
349 |
'year' => 60 * 60 * 24 * 365, // 31,536,000 seconds
|
350 |
'month' => 60 * 60 * 24 * 30, // 2,592,000 seconds
|
351 |
'week' => 60 * 60 * 24 * 7, // 604,800 seconds
|
353 |
'hour' => 60 * 60, // 3600 seconds
|
354 |
'minute' => 60, // 60 seconds
|
355 |
'second' => 1 // 1 second
|
356 |
+
);
|
357 |
|
358 |
+
$since = time() - $startTimestamp;
|
359 |
|
360 |
+
if ($max != '-1' && $since >= $max) {
|
361 |
return date_i18n('h:i:s A F d, Y', $startTimestamp);
|
362 |
+
}
|
363 |
|
364 |
foreach ( $chunks as $key => $seconds ) {
|
365 |
+
// finding the biggest chunk (if the chunk fits, break)
|
366 |
+
if (($count = floor($since / $seconds)) != 0) {
|
367 |
+
break;
|
368 |
+
}
|
369 |
}
|
370 |
|
371 |
+
$messages = array(
|
372 |
'year' => _n('about %s year ago', 'about %s years ago', $count, 'twitter-widget-pro'),
|
373 |
'month' => _n('about %s month ago', 'about %s months ago', $count, 'twitter-widget-pro'),
|
374 |
'week' => _n('about %s week ago', 'about %s weeks ago', $count, 'twitter-widget-pro'),
|
376 |
'hour' => _n('about %s hour ago', 'about %s hours ago', $count, 'twitter-widget-pro'),
|
377 |
'minute' => _n('about %s minute ago', 'about %s minutes ago', $count, 'twitter-widget-pro'),
|
378 |
'second' => _n('about %s second ago', 'about %s seconds ago', $count, 'twitter-widget-pro'),
|
379 |
+
);
|
380 |
+
|
381 |
+
return sprintf($messages[$key], $count);
|
382 |
+
}
|
383 |
+
}
|
384 |
+
|
385 |
+
|
386 |
+
/**
|
387 |
+
* wpTwitterWidget is the class that handles everything outside the widget. This
|
388 |
+
* includes filters that modify tweet content for things like linked usernames.
|
389 |
+
* It also helps us avoid name collisions.
|
390 |
+
*/
|
391 |
+
class wpTwitterWidget
|
392 |
+
{
|
393 |
+
/**
|
394 |
+
* @var array Plugin settings
|
395 |
+
*/
|
396 |
+
private $_settings;
|
397 |
+
|
398 |
+
/**
|
399 |
+
* Plugin file to test against on plugins page
|
400 |
+
*
|
401 |
+
* @var string
|
402 |
+
*/
|
403 |
+
private $_pluginBasename;
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Repository base url
|
407 |
+
*
|
408 |
+
* @since 1.4.4
|
409 |
+
* @var string
|
410 |
+
*/
|
411 |
+
private $_reposUrl = 'http://plugins.svn.wordpress.org/';
|
412 |
+
|
413 |
+
public function __construct() {
|
414 |
+
/**
|
415 |
+
* Add filters and actions
|
416 |
+
*/
|
417 |
+
add_action( 'admin_menu', array($wpTwitterWidget,'admin_menu') );
|
418 |
+
add_filter( 'init', array( $wpTwitterWidget, 'init_locale') );
|
419 |
+
add_filter( 'admin_init', array( $wpTwitterWidget, 'registerSettings') );
|
420 |
+
add_filter( 'admin_init', array( $wpTwitterWidget, 'sendSysInfo') );
|
421 |
+
add_action( 'widgets_init', array($wpTwitterWidget, 'register') );
|
422 |
+
add_filter( 'widget_twitter_content', array($wpTwitterWidget, 'linkTwitterUsers') );
|
423 |
+
add_filter( 'widget_twitter_content', array($wpTwitterWidget, 'linkUrls') );
|
424 |
+
add_filter( 'widget_twitter_content', array($wpTwitterWidget, 'linkHashtags') );
|
425 |
+
add_filter( 'widget_twitter_content', 'convert_chars' );
|
426 |
+
add_filter( 'plugin_action_links', array($wpTwitterWidget, 'addSettingLink'), 10, 2 );
|
427 |
+
add_action ( 'in_plugin_update_message-'.plugin_basename ( __FILE__ ) , array ( $this , '_changelog' ), null, 2 );
|
428 |
+
}
|
429 |
+
|
430 |
+
public function registerSettings() {
|
431 |
+
register_setting( 'twitter_widget_pro_options', 'twitter_widget_pro' );
|
432 |
+
}
|
433 |
+
|
434 |
+
public function admin_menu() {
|
435 |
+
add_options_page(__('Twitter Widget Pro', 'twitter-widget-pro'), __('Twitter Widget Pro', 'twitter-widget-pro'), 'manage_options', 'TwitterWidgetPro', array($this, 'options'));
|
436 |
+
}
|
437 |
+
|
438 |
+
public function init_locale() {
|
439 |
+
$lang_dir = basename(dirname(__FILE__)) . '/languages';
|
440 |
+
load_plugin_textdomain('twitter-widget-pro', 'wp-content/plugins/' . $lang_dir, $lang_dir);
|
441 |
+
}
|
442 |
+
|
443 |
+
/**
|
444 |
+
* This is used to display the options page for this plugin
|
445 |
+
*/
|
446 |
+
public function options() {
|
447 |
+
//Get our options
|
448 |
+
$this->_getSettings();
|
449 |
+
?>
|
450 |
+
<div class="wrap">
|
451 |
+
<h2><?php _e('Twitter Widget Pro Options', 'twitter-widget-pro') ?></h2>
|
452 |
+
<form action="options.php" method="post" id="wp_twitter_widget_pro">
|
453 |
+
<?php settings_fields( 'twitter_widget_pro_options' ); ?>
|
454 |
+
<table class="form-table">
|
455 |
+
<tr valign="top">
|
456 |
+
<th scope="row">
|
457 |
+
<a title="<?php _e('Click for Help!', 'twitter-widget-pro'); ?>" href="#" onclick="jQuery('#twp_user_agreed_to_send_system_information_help').toggle(); return false;">
|
458 |
+
<?php _e('System Information:', 'twitter-widget-pro') ?>
|
459 |
+
</a>
|
460 |
+
</th>
|
461 |
+
<td>
|
462 |
+
<input type="hidden" name="twitter_widget_pro[user_agreed_to_send_system_information]" value="false" />
|
463 |
+
<label for="twp_user_agreed_to_send_system_information"><input type="checkbox" name="twitter_widget_pro[user_agreed_to_send_system_information]" value="true" id="twp_user_agreed_to_send_system_information"<?php checked('true', $this->_settings['user_agreed_to_send_system_information']); ?> /> <?php _e('I agree to send anonymous system information', 'twitter-widget-pro'); ?></label><br />
|
464 |
+
<small id="twp_user_agreed_to_send_system_information_help" style="display:none;">
|
465 |
+
<?php _e('You can help by sending anonymous system information that will help Xavisys make better decisions about new features.', 'twitter-widget-pro'); ?><br />
|
466 |
+
<?php _e('The information will be sent anonymously, but a unique identifier will be sent to prevent duplicate entries from the same installation.', 'twitter-widget-pro'); ?>
|
467 |
+
</small>
|
468 |
+
</td>
|
469 |
+
</tr>
|
470 |
+
</table>
|
471 |
+
<p class="submit">
|
472 |
+
<input type="submit" name="Submit" value="<?php _e('Update Options »', 'twitter-widget-pro'); ?>" />
|
473 |
+
</p>
|
474 |
+
</form>
|
475 |
+
</div>
|
476 |
+
<?php
|
477 |
+
}
|
478 |
+
|
479 |
+
public function _changelog ($pluginData, $newPluginData) {
|
480 |
+
$url = "{$this->_reposUrl}/{$newPluginData->slug}/tags/{$newPluginData->new_version}/upgrade.html";
|
481 |
+
$response = wp_remote_get ( $url );
|
482 |
+
$code = (int) wp_remote_retrieve_response_code ( $response );
|
483 |
+
if ( $code == 200 ) {
|
484 |
+
echo wp_remote_retrieve_body ( $response );
|
485 |
+
}
|
486 |
+
}
|
487 |
+
|
488 |
+
/**
|
489 |
+
* Returns the Twitter user's profile image, linked to that user's profile
|
490 |
+
*
|
491 |
+
* @param object $user - Twitter User
|
492 |
+
* @return string - Linked image (XHTML)
|
493 |
+
*/
|
494 |
+
private function _getProfileImage($user) {
|
495 |
+
return <<<profileImage
|
496 |
+
<a title="{$user->name}" href="http://twitter.com/{$user->screen_name}">
|
497 |
+
<img alt="{$user->name}" src="{$user->profile_image_url}" />
|
498 |
+
</a>
|
499 |
+
profileImage;
|
500 |
+
}
|
501 |
|
502 |
+
/**
|
503 |
+
* Returns the user's screen name as a link inside strong tags.
|
504 |
+
*
|
505 |
+
* @param object $user - Twitter user
|
506 |
+
* @return string - Username as link (XHTML)
|
507 |
+
*/
|
508 |
+
private function _getUserName($user) {
|
509 |
+
return <<<profileImage
|
510 |
+
<strong>
|
511 |
+
<a title="{$user->name}" href="http://twitter.com/{$user->screen_name}">{$user->screen_name}</a>
|
512 |
+
</strong>
|
513 |
+
profileImage;
|
514 |
}
|
515 |
|
516 |
/**
|
521 |
$this->_getSettings();
|
522 |
if ($this->_settings['user_agreed_to_send_system_information'] == 'true') {
|
523 |
$lastSent = get_option('twp-sysinfo');
|
524 |
+
$sysinfo = $this->_get_sysinfo();
|
525 |
if (serialize($lastSent) != serialize($sysinfo)) {
|
526 |
$params = array(
|
527 |
'method' => 'POST',
|
581 |
}
|
582 |
return $links;
|
583 |
}
|
584 |
+
|
585 |
+
/**
|
586 |
+
* Replace @username with a link to that twitter user
|
587 |
+
*
|
588 |
+
* @param string $text - Tweet text
|
589 |
+
* @return string - Tweet text with @replies linked
|
590 |
+
*/
|
591 |
+
public function linkTwitterUsers($text) {
|
592 |
+
$text = preg_replace('/(^|\s)@(\w*)/i', '$1<a href="http://twitter.com/$2" class="twitter-user">@$2</a>', $text);
|
593 |
+
return $text;
|
594 |
+
}
|
595 |
+
|
596 |
+
/**
|
597 |
+
* Replace #hashtag with a link to search.twitter.com for that hashtag
|
598 |
+
*
|
599 |
+
* @param string $text - Tweet text
|
600 |
+
* @return string - Tweet text with #hashtags linked
|
601 |
+
*/
|
602 |
+
public function linkHashtags($text) {
|
603 |
+
$text = preg_replace_callback('/(^|\s)(#\w*)/i', array($this, '_hashtagLink'), $text);
|
604 |
+
return $text;
|
605 |
+
}
|
606 |
+
|
607 |
+
/**
|
608 |
+
* Replace #hashtag with a link to search.twitter.com for that hashtag
|
609 |
+
*
|
610 |
+
* @param array $matches - Tweet text
|
611 |
+
* @return string - Tweet text with #hashtags linked
|
612 |
+
*/
|
613 |
+
private function _hashtagLink($matches) {
|
614 |
+
return "{$matches[1]}<a href='http://search.twitter.com/search?q="
|
615 |
+
. urlencode($matches[2])
|
616 |
+
. "' class='twitter-hashtag'>{$matches[2]}</a>";
|
617 |
+
}
|
618 |
+
|
619 |
+
/**
|
620 |
+
* Turn URLs into links
|
621 |
+
*
|
622 |
+
* @param string $text - Tweet text
|
623 |
+
* @return string - Tweet text with URLs repalced with links
|
624 |
+
*/
|
625 |
+
public function linkUrls($text) {
|
626 |
+
/**
|
627 |
+
* match protocol://address/path/file.extension?some=variable&another=asf%
|
628 |
+
* $1 is a possible space, this keeps us from linking href="[link]" etc
|
629 |
+
* $2 is the whole URL
|
630 |
+
* $3 is protocol://
|
631 |
+
* $4 is the URL without the protocol://
|
632 |
+
* $5 is the URL parameters
|
633 |
+
*/
|
634 |
+
$text = preg_replace("/(^|\s)(([a-zA-Z]+:\/\/)([a-z][a-z0-9_\..-]*[a-z]{2,6})([a-zA-Z0-9~\/*-?&%]*))/i", "$1<a href=\"$2\">$2</a>", $text);
|
635 |
+
|
636 |
+
/**
|
637 |
+
* match www.something.domain/path/file.extension?some=variable&another=asf%
|
638 |
+
* $1 is a possible space, this keeps us from linking href="[link]" etc
|
639 |
+
* $2 is the whole URL that was matched. The protocol is missing, so we assume http://
|
640 |
+
* $3 is www.
|
641 |
+
* $4 is the URL matched without the www.
|
642 |
+
* $5 is the URL parameters
|
643 |
+
*/
|
644 |
+
$text = preg_replace("/(^|\s)(www\.([a-z][a-z0-9_\..-]*[a-z]{2,6})([a-zA-Z0-9~\/*-?&%]*))/i", "$1<a href=\"http://$2\">$2</a>", $text);
|
645 |
+
|
646 |
+
return $text;
|
647 |
+
}
|
648 |
+
|
649 |
+
function register() {
|
650 |
+
register_widget('WP_Widget_Twitter_Pro');
|
651 |
+
}
|
652 |
}
|
653 |
// Instantiate our class
|
654 |
$wpTwitterWidget = new wpTwitterWidget();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|