Skip to content

Commit df65d76

Browse files
committed
new plugin which embeds the contribution of SNS
Supported Facebook, Google+, Instagram, Twitter and Vine. #snsref(SNS Post URL[,width:(Digit)][,media:(1|0)][,thread:(1|0)][,caption:(1|0)][,audio:(0|1)][,related:(1:0)][,simple]) :width | Width(px) for Facebook, Instagram, Twitter and Vine. Google+ is not effective. :media | for Twitter :thread | for Twitter :caption | for Instagram :audio | for Vine :related | for Vine :simple | for Vine
1 parent 04d2caf commit df65d76

File tree

1 file changed

+207
-0
lines changed

1 file changed

+207
-0
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
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 &#38;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.'&amp;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

Comments
 (0)