1+ <?php
2+
3+ class xpwiki_plugin_snsref extends xpwiki_plugin {
4+
5+ private $ usage , $ sns , $ options , $ width , $ fetcherr ;
6+
7+ public function plugin_snsref_init () {
8+ $ this ->usage = 'Usage: #snsref(SNS post URL) or &snsref(SNS post URL); ' ;
9+
10+ $ this ->sns = array (
11+ 'twitter ' => '#^https?://twitter\.com/[a-z0-9_-]+/status/([0-9]+)#i ' ,
12+ 'google ' => '#^(https?://plus\.google\.com/(?:[^/]+/)*?([0-9]+)/posts/([a-z0-9]+))#i ' ,
13+ 'facebook ' => '#^(https?://www\.facebook\.com/(?:([a-z0-9._-]+)/posts/|photo.php\?fbid=)([0-9]+))#i ' ,
14+ 'instagram ' => '#^https?://instagram\.com/p/([a-z0-9]+)#i ' ,
15+ 'vine ' => '#^https?://vine\.co/v/([a-z0-9]+)#i ' ,
16+ );
17+
18+ $ this ->options = array (
19+ 'media ' => 1 , // for twitter
20+ 'thread ' => 1 , // for twitter
21+ 'lang ' => 'ja ' , // for twitter
22+ 'width ' => 466 , // for Facebook, Instagram, Twitter and Vine. Google+ is not effective.
23+ 'caption ' => 1 , // for instagram
24+ 'audio ' => 0 , // for vine
25+ 'related ' => 1 , // for vine
26+ 'simple ' => false , // for vine
27+ );
28+
29+ $ this ->minwidth = 300 ;
30+
31+ $ this ->maxwidth = 1024 ;
32+ }
33+
34+ public function plugin_snsref_convert () {
35+ $ args = func_get_args ();
36+ if ($ args ) {
37+ $ this ->width = 0 ;
38+ $ html = $ this ->getHtml ($ args );
39+ $ width = ($ this ->width )? 'width: ' .$ this ->width .'px ' : '' ;
40+ return '<div style=" ' .$ width .'" class="plugin_snsref"> ' . "\n" . $ html . "\n" . '</div> ' ;
41+ } else {
42+ return $ this ->usage ;
43+ }
44+ }
45+
46+ public function plugin_snsref_inline () {
47+ $ args = func_get_args ();
48+ $ body = array_pop ($ args );
49+ if ($ args ) {
50+ $ this ->width = 0 ;
51+ $ html = $ this ->getHtml ($ args );
52+ $ width = ($ this ->width )? 'width: ' .$ this ->width .'px ' : '' ;
53+ return '<div style="display:inline-block; ' .$ width .'"> ' . $ html . '</div> ' ;
54+ } else {
55+ return $ this ->usage ;
56+ }
57+ }
58+
59+ /////////////////////
60+ // Pprivate functions
61+
62+ private function getHtml ($ args ) {
63+ $ options = $ this ->options ;
64+ $ this ->fetch_options ($ options , $ args , array ('url ' ));
65+ $ options ['width ' ] = max (min (intval ($ options ['width ' ]), $ this ->maxwidth ), $ this ->minwidth );
66+
67+ $ url = $ options ['url ' ];
68+ foreach ($ this ->sns as $ host => $ regex ) {
69+ if (preg_match ($ regex , $ url , $ m )) {
70+ return '<!--NA--> ' .$ this ->fetch ($ host , $ options , $ m ).'<!--/NA--> ' ;
71+ }
72+ }
73+
74+ return 'Bad URL: ' .$ this ->func ->htmlspecialchars ($ url );
75+ }
76+
77+ private function fetch ($ host , $ options , $ m ) {
78+ switch ($ host ) {
79+ case 'twitter ' :
80+ return $ this ->fetch_twitter ($ options , $ m );
81+ case 'google ' :
82+ return $ this ->fetch_google ($ options , $ m );
83+ case 'facebook ' :
84+ return $ this ->fetch_facebook ($ options , $ m );
85+ case 'instagram ' :
86+ $ this ->width = $ options ['width ' ];
87+ return $ this ->fetch_instagram ($ options , $ m );
88+ case 'vine ' :
89+ return $ this ->fetch_vine ($ options , $ m );
90+ default :
91+ $ method = 'fetch_ ' . $ host ;
92+ if (method_exists ($ this , $ method )) {
93+ return $ this ->$ method ($ options , $ m );
94+ } else {
95+ return 'Bad URL: ' .$ this ->func ->htmlspecialchars ($ url );
96+ }
97+ }
98+ }
99+
100+ private function apiRequest ($ apiurl , $ target = 'html ' ) {
101+ $ html = null ;
102+ $ this ->fetcherr = false ;
103+ $ res = $ this ->func ->http_request ($ apiurl );
104+ if ($ res ['rc ' ] === 200 ) {
105+ if ($ res ['data ' ] && $ decd = json_decode ($ res ['data ' ], true )) {
106+ if (is_array ($ decd ) && isset ($ decd [$ target ])) {
107+ $ html = mb_convert_encoding ($ decd [$ target ], $ this ->cont ['SOURCE_ENCODING ' ], 'UTF-8 ' );
108+ $ ttl = 2592000 ; // 30days
109+ }
110+ }
111+ }
112+ if (is_null ($ html )) {
113+ $ this ->fetcherr = true ;
114+ if ($ res ['rc ' ] === 404 ) {
115+ // Not found
116+ $ html = 'Target post was not found: ' ;
117+ $ ttl = 3600 ;
118+ } else {
119+ // Network error
120+ $ html = 'Network error, Try after 10 minute: ' ;
121+ $ ttl = 60 ;
122+ $ this ->root ->rtf ['disable_render_cache ' ] = true ;
123+ }
124+ }
125+ return array ($ html , $ ttl );
126+ }
127+
128+ private function fetch_instagram ($ options , $ m ) {
129+
130+ $ url = $ options ['url ' ];
131+ $ hidecaption = ($ options ['caption ' ] && $ options ['caption ' ] !== 'none ' )? '0 ' : '1 ' ;
132+
133+ $ id = $ m [1 ];
134+ $ ckey = 'i: ' . $ id . ': ' . $ hidecaption ;
135+ $ html = '' ;
136+
137+ if ($ html = $ this ->func ->cache_get_db ($ ckey , 'snsref ' )) {
138+ return $ html ;
139+ }
140+
141+ $ html = $ url ;
142+ $ ttl = 60 ;
143+ $ apiurl = 'https://api.instagram.com/oembed/?beta=1&url=http://instagram.com/p/ ' .$ id .'/&hidecaption= ' .$ hidecaption ;
144+
145+ list ($ html , $ ttl ) = $ this ->apiRequest ($ apiurl );
146+ if ($ this ->fetcherr ) {
147+ $ html .= $ this ->func ->htmlspecialchars ($ url );
148+ }
149+
150+ $ this ->func ->cache_save_db ($ html , 'snsref ' , $ ttl , $ ckey );
151+ return $ html ;
152+ }
153+
154+ private function fetch_twitter ($ options , $ m ) {
155+
156+ $ url = $ options ['url ' ];
157+ $ media = ($ options ['media ' ] && $ options ['media ' ] !== 'none ' )? '1 ' : '0 ' ;
158+ $ thread = ($ options ['thread ' ] && $ options ['thread ' ] !== 'none ' )? '1 ' : '0 ' ;
159+ $ lang = preg_replace ('/[^a-zA-Z0-9._-]/ ' , '' , $ options ['lang ' ]);
160+
161+ $ id = $ m [1 ];
162+ $ ckey = 't: ' . $ id . ': ' . $ media . $ thread . $ lang ;
163+ $ html = '' ;
164+
165+ if ($ html = $ this ->func ->cache_get_db ($ ckey , 'snsref ' )) {
166+ $ this ->twitterSetWidth ($ html , $ options );
167+ return $ html ;
168+ }
169+
170+ $ html = $ url ;
171+ $ ttl = 60 ;
172+ $ media = $ media ? 'false ' : 'true ' ;
173+ $ thread = $ thread ? 'false ' : 'true ' ;
174+ $ apiurl = 'https://api.twitter.com/1/statuses/oembed.json?hide_media= ' .$ media .'&hide_thread= ' .$ thread .'&lang= ' .$ lang .'&id= ' .$ id ;
175+
176+ list ($ html , $ ttl ) = $ this ->apiRequest ($ apiurl );
177+ if ($ this ->fetcherr ) {
178+ $ html .= $ this ->func ->htmlspecialchars ($ url );
179+ }
180+
181+ $ this ->func ->cache_save_db ($ html , 'snsref ' , $ ttl , $ ckey );
182+
183+ $ this ->twitterSetWidth ($ html , $ options );
184+ return $ html ;
185+ }
186+
187+ private function twitterSetWidth (&$ html , $ options ) {
188+ $ html = str_replace ('<blockquote ' , '<blockquote width=" ' .$ options ['width ' ].'" ' , $ html );
189+ }
190+
191+ private function fetch_google ($ options , $ m ) {
192+ $ this ->func ->add_js_head ('//apis.google.com/js/plusone.js ' );
193+ return '<div class="g-post" data-href="https://plus.google.com/ ' .$ this ->func ->htmlspecialchars ($ m [2 ]).'/posts/ ' .$ this ->func ->htmlspecialchars ($ m [3 ]).'">Google+:<a href=" ' .$ this ->func ->htmlspecialchars ($ m [1 ]).'"> ' .$ this ->func ->htmlspecialchars ($ m [2 ].'- ' .$ m [3 ]).'</a></div> ' ;
194+ }
195+
196+ private function fetch_facebook ($ options , $ m ) {
197+ return '<div id="fb-root"></div> <script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1"; fjs.parentNode.insertBefore(js, fjs); }(document, \'script \', \'facebook-jssdk \'));</script>
198+ <div class="fb-post" data-href=" ' .$ this ->func ->htmlspecialchars ($ m [1 ]).'" data-width=" ' .$ options ['width ' ].'"><div class="fb-xfbml-parse-ignore">Facebook: <a href=" ' .$ this ->func ->htmlspecialchars ($ m [1 ]).'"> ' .$ this ->func ->htmlspecialchars ($ m [2 ].'- ' .$ m [3 ]).'</a></div></div> ' ;
199+ }
200+
201+ private function fetch_vine ($ options , $ m ) {
202+ $ audio = ($ options ['audio ' ] && $ options ['audio ' ] !== 'none ' )? '1 ' : '0 ' ;
203+ $ related = ($ options ['related ' ] && $ options ['related ' ] !== 'none ' )? '1 ' : '0 ' ;
204+ $ type = ($ options ['simple ' ])? 'simple ' : 'postcard ' ;
205+ return '<iframe class="vine-embed" src="https://vine.co/v/ ' .$ m [1 ].'/embed/ ' .$ type .'?audio= ' .$ audio .'&related= ' .$ related .'" width=" ' .$ options ['width ' ].'" height=" ' .$ options ['width ' ].'" frameborder="0"></iframe><script async src="//platform.vine.co/static/scripts/embed.js" charset="utf-8"></script> ' ;
206+ }
207+ }
0 commit comments