55/**
66 * Twitter Text Formatter : format twitter timeline text in html.
77 *
8- * @author Netgloo <info@netgloo.com>
9- * @version 1.0
8+ * @author Netgloo <info@netgloo.com>
109 */
1110class TwitterTextFormatter {
1211
@@ -15,20 +14,102 @@ class TwitterTextFormatter {
1514 /**
1615 * Return the tweet text formatted with the tweet's entities.
1716 *
17+ * Default configs:
18+ *
19+ * $configs = [
20+ * 'show_retweeted_by' => true,
21+ *
22+ * 'retweeted_by_template' =>
23+ * '<em> Retweeted by {{user_name}}</em>',
24+ *
25+ * 'hashtag_link_template' =>
26+ * '<a href="{{hashtag_link}}" rel="nofollow" target="_blank">' .
27+ * '#{{hashtag_text}}</a>',
28+ *
29+ * 'url_link_template' =>
30+ * '<a href="{{url_link}}" rel="nofollow" target="_blank" ' .
31+ * 'title="{{url_title}}">{{url_text}}</a>',
32+ *
33+ * 'user_mention_link_template' =>
34+ * '<a href="{{user_mention_link}}" rel="nofollow" target="_blank" ' .
35+ * title="{{user_mention_title}}">@{{user_mention_text}}</a>',
36+ *
37+ * 'media_link_template' =>
38+ * '<a href="{{media_link}}" rel="nofollow" target="_blank" ' .
39+ * 'title="{{media_title}}">{{media_text}}</a>'
40+ * ];
41+ *
1842 * @param $tweet (Object)
43+ * @param $configs (Array)
1944 * @return (String)
2045 */
21- public static function format_text ($ tweet , $ show_retweeted_by = true ) {
46+ public static function format_text ($ tweet , $ configs = []) {
47+
48+ // Set up configs
49+
50+ self ::set_default (
51+ $ configs ,
52+ 'show_retweeted_by ' ,
53+ true
54+ );
2255
23- // Retweeted
56+ self ::set_default (
57+ $ configs ,
58+ 'retweeted_by_template ' ,
59+ '<em> Retweeted by {{user_name}}</em> '
60+ );
61+
62+ self ::set_default (
63+ $ configs ,
64+ 'hashtag_link_template ' ,
65+ '<a href="{{hashtag_link}}" rel="nofollow" target="_blank"> ' .
66+ '#{{hashtag_text}}</a> '
67+ );
68+
69+ self ::set_default (
70+ $ configs ,
71+ 'url_link_template ' ,
72+ '<a href="{{url_link}}" rel="nofollow" target="_blank" ' .
73+ 'title="{{url_title}}">{{url_text}}</a> '
74+ );
75+
76+ self ::set_default (
77+ $ configs ,
78+ 'user_mention_link_template ' ,
79+ '<a href="{{user_mention_link}}" rel="nofollow" target="_blank" ' .
80+ 'title="{{user_mention_title}}">@{{user_mention_text}}</a> '
81+ );
82+
83+ self ::set_default (
84+ $ configs ,
85+ 'media_link_template ' ,
86+ '<a href="{{media_link}}" rel="nofollow" target="_blank" ' .
87+ 'title="{{media_title}}">{{media_text}}</a> '
88+ );
89+
90+ // Is retweeted?
2491 if (isset ($ tweet ->retweeted_status )) {
92+
2593 $ user_name = $ tweet ->user ->name ;
26- $ retweeted_by = $ show_retweeted_by ?
27- "<em> Retweeted by {$ user_name }</em> " : '' ;
28- return self ::parse_tweet_text ($ tweet ->retweeted_status ) . $ retweeted_by ;
94+ $ retweeted_by = '' ;
95+
96+ // If show retweeted by, then prepare the "retweeted by" text
97+ if ($ configs ['show_retweeted_by ' ]) {
98+ $ retweeted_by = $ configs ['retweeted_by_template ' ];
99+ $ retweeted_by = str_replace (
100+ '{{user_name}} ' ,
101+ $ user_name ,
102+ $ retweeted_by
103+ );
104+ }
105+
106+ // Return the parsed re-tweet
107+ $ res = self ::parse_tweet_text ($ tweet ->retweeted_status , $ configs );
108+ return $ res . $ retweeted_by ;
29109 }
30110
31- return self ::parse_tweet_text ($ tweet );
111+ // Return the parsed tweet
112+ return self ::parse_tweet_text ($ tweet , $ configs );
32113 }
33114
34115 // --------------------------------------------------------------------------
@@ -44,62 +125,136 @@ public static function format_text($tweet, $show_retweeted_by = true) {
44125 * Credits: this function is a modified version of the one from Jacob
45126 * Emerick's Blog (http://goo.gl/lhu8Ix)
46127 */
47- private static function parse_tweet_text ($ tweet ) {
48-
49- // Define patterns for each entity
50- $ hashtag_link_pattern =
51- '<a href="http://twitter.com/search?q=%23{{1}}&src=hash" ' .
52- 'rel="nofollow" target="_blank">#{{2}}</a> ' ;
53- $ url_link_pattern =
54- '<a href="{{1}}" rel="nofollow" target="_blank" title="{{2}}">{{3}}</a> ' ;
55- $ user_mention_link_pattern =
56- '<a href="http://twitter.com/{{1}}" rel="nofollow" target="_blank" ' .
57- 'title="{{2}}">@{{3}}</a> ' ;
58- $ media_link_pattern =
59- '<a href="{{1}}" rel="nofollow" target="_blank" title="{{2}}">{{3}}</a> ' ;
128+ private static function parse_tweet_text ($ tweet , $ configs ) {
60129
61130 // Collects the set of entities
62131 $ entity_holder = array ();
63132
133+ // Hashtags
64134 if (isset ($ tweet ->entities ->hashtags )) {
135+
136+ $ template = $ configs ['hashtag_link_template ' ];
137+
65138 foreach ($ tweet ->entities ->hashtags as $ hashtag ) {
66- $ replace = $ hashtag_link_pattern ;
67- $ replace = str_replace ('{{1}} ' , strtolower ($ hashtag ->text ), $ replace );
68- $ replace = str_replace ('{{2}} ' , $ hashtag ->text , $ replace );
139+
140+ // Link: https://twitter.com/hashtag/{{1}}?src=hash
141+ $ hashtag_link = str_replace (
142+ '{{1}} ' ,
143+ strtolower ($ hashtag ->text ),
144+ 'https://twitter.com/hashtag/{{1}}?src=hash '
145+ );
146+
147+ $ replace = str_replace (
148+ '{{hashtag_link}} ' ,
149+ $ hashtag_link ,
150+ $ template
151+ );
152+
153+ $ replace = str_replace (
154+ '{{hashtag_text}} ' ,
155+ $ hashtag ->text ,
156+ $ replace
157+ );
158+
69159 self ::add_entity ($ entity_holder , $ hashtag , $ replace );
70- }
71- }
72160
161+ } // foreach
162+
163+ } // if
164+
165+ // Urls
73166 if (isset ($ tweet ->entities ->urls )) {
167+
168+ $ template = $ configs ['url_link_template ' ];
169+
74170 foreach ($ tweet ->entities ->urls as $ url ) {
75- $ replace = $ url_link_pattern ;
76- $ replace = str_replace ('{{1}} ' , $ url ->url , $ replace );
77- $ replace = str_replace ('{{2}} ' , $ url ->expanded_url , $ replace );
78- $ replace = str_replace ('{{3}} ' , $ url ->display_url , $ replace );
171+
172+ $ replace = str_replace (
173+ '{{url_link}} ' ,
174+ $ url ->url ,
175+ $ template
176+ );
177+ $ replace = str_replace (
178+ '{{url_title}} ' ,
179+ $ url ->expanded_url ,
180+ $ replace
181+ );
182+ $ replace = str_replace (
183+ '{{url_text}} ' ,
184+ $ url ->display_url ,
185+ $ replace
186+ );
187+
79188 self ::add_entity ($ entity_holder , $ url , $ replace );
80- }
81- }
82189
190+ } // foreach
191+
192+ } // if
193+
194+ // User mentions
83195 if (isset ($ tweet ->entities ->user_mentions )) {
196+
197+ $ template = $ configs ['user_mention_link_template ' ];
198+
84199 foreach ($ tweet ->entities ->user_mentions as $ user_mention ) {
85- $ replace = $ user_mention_link_pattern ;
200+
201+ // Link: https://twitter.com/{{1}}
202+ $ user_mention_link = str_replace (
203+ '{{1}} ' ,
204+ strtolower ($ user_mention ->screen_name ),
205+ 'https://twitter.com/{{1}} '
206+ );
207+
208+ $ replace = str_replace (
209+ '{{user_mention_link}} ' ,
210+ $ user_mention_link ,
211+ $ template
212+ );
86213 $ replace = str_replace (
87- '{{1}} ' , strtolower ($ user_mention ->screen_name ), $ replace );
88- $ replace = str_replace ('{{2}} ' , $ user_mention ->name , $ replace );
89- $ replace = str_replace ('{{3}} ' , $ user_mention ->screen_name , $ replace );
214+ '{{user_mention_title}} ' ,
215+ $ user_mention ->name ,
216+ $ replace
217+ );
218+ $ replace = str_replace (
219+ '{{user_mention_text}} ' ,
220+ $ user_mention ->screen_name ,
221+ $ replace
222+ );
223+
90224 self ::add_entity ($ entity_holder , $ user_mention , $ replace );
91- }
92- }
93225
226+ } // foreach
227+
228+ } // if
229+
230+ // Media
94231 if (isset ($ tweet ->entities ->media )) {
232+
233+ $ template = $ configs ['media_link_template ' ];
234+
95235 foreach ($ tweet ->entities ->media as $ media ) {
96- $ replace = $ media_link_pattern ;
97- $ replace = str_replace ('{{1}} ' , $ media ->url , $ replace );
98- $ replace = str_replace ('{{2}} ' , $ media ->expanded_url , $ replace );
99- $ replace = str_replace ('{{3}} ' , $ media ->display_url , $ replace );
236+
237+ $ replace = str_replace (
238+ '{{media_link}} ' ,
239+ $ media ->url ,
240+ $ template
241+ );
242+ $ replace = str_replace (
243+ '{{media_title}} ' ,
244+ $ media ->expanded_url ,
245+ $ replace
246+ );
247+ $ replace = str_replace (
248+ '{{media_text}} ' ,
249+ $ media ->display_url ,
250+ $ replace
251+ );
252+
100253 self ::add_entity ($ entity_holder , $ media , $ replace );
101- }
102- }
254+
255+ } // foreach
256+
257+ } // if
103258
104259 // Sort the entities in reverse order by their starting index
105260 krsort ($ entity_holder );
@@ -124,7 +279,11 @@ private static function parse_tweet_text($tweet) {
124279 /**
125280 * Add an entity to the entity_holder.
126281 */
127- private static function add_entity (&$ entity_holder , $ tweet_entity , $ replace ) {
282+ private static function add_entity (
283+ &$ entity_holder ,
284+ $ tweet_entity ,
285+ $ replace
286+ ) {
128287
129288 $ entity = new \stdClass ();
130289 $ entity ->start = $ tweet_entity ->indices [0 ];
@@ -142,7 +301,12 @@ private static function add_entity(&$entity_holder, $tweet_entity, $replace) {
142301 * String replacement supporting UTF-8 encoding.
143302 */
144303 private static function mb_substr_replace (
145- $ string , $ replacement , $ start , $ length = null , $ encoding = null ) {
304+ $ string ,
305+ $ replacement ,
306+ $ start ,
307+ $ length = null ,
308+ $ encoding = null
309+ ) {
146310
147311 $ strlen = mb_strlen ($ string , $ encoding );
148312 $ first_piece = mb_substr ($ string , 0 , $ start , $ encoding ) . $ replacement ;
@@ -157,4 +321,16 @@ private static function mb_substr_replace(
157321
158322 // --------------------------------------------------------------------------
159323
160- } // class TwitterTextFormatter
324+ /**
325+ * Set a default value for the given key.
326+ */
327+ private static function set_default (&$ array , $ key , $ default ) {
328+ if (!isset ($ array [$ key ])) {
329+ $ array [$ key ] = $ default ;
330+ }
331+ return ;
332+ }
333+
334+ // --------------------------------------------------------------------------
335+
336+ } // class
0 commit comments