1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* |
4
|
|
|
* @package phpBB Extension - tas2580 Social Media Buttons |
5
|
|
|
* @copyright (c) 2015 tas2580 (https://tas2580.net) |
6
|
|
|
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 |
7
|
|
|
* |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace tas2580\socialbuttons\event; |
11
|
|
|
|
12
|
|
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Event listener |
16
|
|
|
*/ |
17
|
|
|
class listener implements EventSubscriberInterface |
18
|
|
|
{ |
19
|
|
|
/** @var \phpbb\config\config */ |
20
|
|
|
protected $config; |
21
|
|
|
|
22
|
|
|
/** @var \phpbb\template\template */ |
23
|
|
|
protected $template; |
24
|
|
|
|
25
|
|
|
/** @var \phpbb\user */ |
26
|
|
|
protected $user; |
27
|
|
|
|
28
|
|
|
/** @var \phpbb\request\request */ |
29
|
|
|
protected $request; |
30
|
|
|
|
31
|
|
|
/** @var \phpbb\cache\driver\driver_interface */ |
32
|
|
|
protected $cache; |
33
|
|
|
|
34
|
|
|
/** @var string phpbb_root_path */ |
35
|
|
|
protected $phpbb_root_path; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Constructor |
39
|
|
|
* |
40
|
|
|
* @param \phpbb\config\config $config Config Object |
41
|
|
|
* @param \phpbb\template\template $template Template object |
42
|
|
|
* @param \phpbb\user $user User object |
43
|
|
|
* @param \phpbb\request\request $request Request object |
44
|
|
|
* @param \phpbb\cache\driver\driver_interface $cache Cache driver interface |
45
|
|
|
* @param string $phpbb_root_path phpbb_root_path |
46
|
|
|
* @access public |
47
|
|
|
*/ |
48
|
|
|
public function __construct(\phpbb\config\config $config, \phpbb\template\template $template, \phpbb\user $user, \phpbb\request\request $request, \phpbb\cache\driver\driver_interface $cache, $phpbb_root_path) |
49
|
|
|
{ |
50
|
|
|
$this->config = $config; |
51
|
|
|
$this->template = $template; |
52
|
|
|
$this->user = $user; |
53
|
|
|
$this->request = $request; |
54
|
|
|
$this->cache = $cache; |
55
|
|
|
$this->phpbb_root_path = $phpbb_root_path; |
56
|
|
|
$this->description = ''; |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Assign functions defined in this class to event listeners in the core |
61
|
|
|
* |
62
|
|
|
* @return array |
63
|
|
|
* @static |
64
|
|
|
* @access public |
65
|
|
|
*/ |
66
|
|
|
public static function getSubscribedEvents() |
67
|
|
|
{ |
68
|
|
|
return array( |
69
|
|
|
'core.viewtopic_post_row_after' => 'display_og_description', |
70
|
|
|
'core.viewtopic_modify_page_title' => 'display_on_viewtopic', |
71
|
|
|
'core.index_modify_page_title' => 'display_on_index' |
72
|
|
|
); |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Display the first post as Open Graph description |
77
|
|
|
* |
78
|
|
|
* @param object $event The event object |
79
|
|
|
* @return null |
80
|
|
|
* @access public |
81
|
|
|
*/ |
82
|
|
|
public function display_og_description($event) |
83
|
|
|
{ |
84
|
|
|
if (empty($this->description)) |
85
|
|
|
{ |
86
|
|
|
$desctiption = strip_tags($event['post_row']['MESSAGE']); |
87
|
|
|
//Facebook only displays the first 300 characters of a description, so we can cut the post text after 300 characters |
88
|
|
|
$this->description = (strlen($desctiption) > 300) ? preg_replace("/[^ ]*$/", '', substr($desctiption, 0, 300)) . '...' : $desctiption; |
89
|
|
|
$this->template->assign_vars(array( |
90
|
|
|
'OG_DESCRIPTION' => $this->description, |
91
|
|
|
)); |
92
|
|
|
} |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* Display Social Media Buttons at the index page |
97
|
|
|
* |
98
|
|
|
* @param object $event The event object |
99
|
|
|
* @return null |
100
|
|
|
* @access public |
101
|
|
|
*/ |
102
|
|
|
public function display_on_index($event) |
103
|
|
|
{ |
104
|
|
|
$url = generate_board_url(); |
105
|
|
|
$enable_buttons = isset($this->config['socialbuttons_display_on_index']) ? $this->config['socialbuttons_display_on_index'] : false; |
106
|
|
|
// Display the shares count |
107
|
|
View Code Duplication |
if ($enable_buttons && isset($this->config['socialbuttons_showshares']) && $this->config['socialbuttons_showshares']) |
|
|
|
|
108
|
|
|
{ |
109
|
|
|
$shares = $this->get_share_count($url, 'index'); |
110
|
|
|
$this->template->assign_vars(array( |
111
|
|
|
'S_SHOWSHARES' => true, |
112
|
|
|
'SHARES_FACEBOOK' => isset($shares['facebook']) ? (int) $shares['facebook'] : 0, |
113
|
|
|
'SHARES_TWITTER' => isset($shares['twitter']) ? (int) $shares['twitter'] : 0, |
114
|
|
|
'SHARES_GOOGLE' => isset($shares['google']) ? (int) $shares['google'] : 0, |
115
|
|
|
'SHARES_LINKEDIN' => isset($shares['linkedin']) ? (int) $shares['linkedin'] : 0, |
116
|
|
|
)); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
// Display the buttons and the OG meta tags |
120
|
|
|
$this->template->assign_vars(array( |
121
|
|
|
'SOCIAL_MEDIA_CLASS' => 'socialmediabuttons' . (isset($this->config['socialbuttons_style']) ? $this->config['socialbuttons_style'] : 1), |
122
|
|
|
'S_ENABLE_BUTTONS' => $enable_buttons, |
123
|
|
|
'U_SHARELINK' => urlencode($url), |
124
|
|
|
'S_FACEBOOK' => isset($this->config['socialbuttons_facebook']) ? $this->config['socialbuttons_facebook'] : '', |
125
|
|
|
'S_TWITTER' => isset($this->config['socialbuttons_twitter']) ? $this->config['socialbuttons_twitter'] : '', |
126
|
|
|
'S_GOOGLE' => isset($this->config['socialbuttons_google']) ? $this->config['socialbuttons_google'] : '', |
127
|
|
|
'S_LINKEDIN' => isset($this->config['socialbuttons_linkedin']) ? $this->config['socialbuttons_linkedin'] : '', |
128
|
|
|
'ENABLE_OG' => isset($this->config['socialbuttons_enable_og']) ? $this->config['socialbuttons_enable_og'] : '', |
129
|
|
|
'ENABLE_OG_TITLE' => isset($this->config['socialbuttons_enable_og_title']) ? $this->config['socialbuttons_enable_og_title'] : '', |
130
|
|
|
'OG_IMAGE' => isset($this->config['socialbuttons_og_image']) ? $this->config['socialbuttons_og_image'] : '', |
131
|
|
|
'OG_URL' => $url, |
132
|
|
|
'OG_TITLE' => $event['page_title'], |
133
|
|
|
)); |
134
|
|
|
$this->user->add_lang_ext('tas2580/socialbuttons', 'common'); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Display Social Media Buttons at topics page |
139
|
|
|
* |
140
|
|
|
* @param object $event The event object |
141
|
|
|
* @return null |
142
|
|
|
* @access public |
143
|
|
|
*/ |
144
|
|
|
public function display_on_viewtopic($event) |
145
|
|
|
{ |
146
|
|
|
$enabled_forums = isset($this->config['socialbuttons_enable_forums']) ? explode(',', $this->config['socialbuttons_enable_forums']) : array(); |
147
|
|
|
$enable_buttons = ((isset($this->config['socialbuttons_enable']) && $this->config['socialbuttons_enable']) || in_array($event['topic_data']['forum_id'], $enabled_forums)); |
148
|
|
|
|
149
|
|
|
// Generate the full URL of the topic without session ID |
150
|
|
|
$use_seo_urls = isset($this->config['socialbuttons_use_seo_urls']) ? $this->config['socialbuttons_use_seo_urls'] : false; |
151
|
|
|
if ($use_seo_urls) |
152
|
|
|
{ |
153
|
|
|
// we can not use $this->user->page['page'] because it fails on use of SEO extensions |
154
|
|
|
$page = $this->request->server('REQUEST_URI'); |
155
|
|
|
if (!$page) |
156
|
|
|
{ |
157
|
|
|
// IIS |
158
|
|
|
$page = $this->request->server('HTTP_X_REWRITE_URL'); |
159
|
|
|
} |
160
|
|
|
$host = $this->request->server('HTTP_HOST'); |
161
|
|
|
$https = $this->request->server('HTTPS'); |
162
|
|
|
$url = ($https ? 'https://' : 'http://') . $host . '/' . $page; |
163
|
|
|
} |
164
|
|
|
else |
165
|
|
|
{ |
166
|
|
|
$url = generate_board_url() . '/viewtopic.php?f=' . $event['topic_data']['forum_id'] . '&t=' . $event['topic_data']['topic_id']; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
// Display the shares count |
170
|
|
View Code Duplication |
if ($enable_buttons && isset($this->config['socialbuttons_showshares']) && $this->config['socialbuttons_showshares']) |
|
|
|
|
171
|
|
|
{ |
172
|
|
|
$shares = $this->get_share_count($url); |
173
|
|
|
$this->template->assign_vars(array( |
174
|
|
|
'S_SHOWSHARES' => true, |
175
|
|
|
'SHARES_FACEBOOK' => isset($shares['facebook']) ? (int) $shares['facebook'] : 0, |
176
|
|
|
'SHARES_TWITTER' => isset($shares['twitter']) ? (int) $shares['twitter'] : 0, |
177
|
|
|
'SHARES_GOOGLE' => isset($shares['google']) ? (int) $shares['google'] : 0, |
178
|
|
|
'SHARES_LINKEDIN' => isset($shares['linkedin']) ? (int) $shares['linkedin'] : 0, |
179
|
|
|
)); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
// Display the buttons and the OG meta tags |
183
|
|
|
$forums = isset($this->config['socialbuttons_enable_og_desc_forums']) ? explode(',', $this->config['socialbuttons_enable_og_desc_forums']) : array(); |
184
|
|
|
$position = isset($this->config['socialbuttons_position']) ? $this->config['socialbuttons_position'] : 2; |
185
|
|
|
$this->template->assign_vars(array( |
186
|
|
|
'SOCIAL_MEDIA_CLASS' => 'socialmediabuttons' . (isset($this->config['socialbuttons_style']) ? $this->config['socialbuttons_style'] : 1), |
187
|
|
|
'S_ENABLE_BUTTONS' => $enable_buttons, |
188
|
|
|
'S_FACEBOOK' => isset($this->config['socialbuttons_facebook']) ? $this->config['socialbuttons_facebook'] : '', |
189
|
|
|
'S_TWITTER' => isset($this->config['socialbuttons_twitter']) ? $this->config['socialbuttons_twitter'] : '', |
190
|
|
|
'S_GOOGLE' => isset($this->config['socialbuttons_google']) ? $this->config['socialbuttons_google'] : '', |
191
|
|
|
'S_LINKEDIN' => isset($this->config['socialbuttons_linkedin']) ? $this->config['socialbuttons_linkedin'] : '', |
192
|
|
|
'S_SHOW_AT_TOP' => ($position == 0 || $position == 1) ? true : false, |
193
|
|
|
'S_SHOW_AT_BOTTOM' => ($position == 0 || $position == 2) ? true : false, |
194
|
|
|
'U_TOPICLINK' => urlencode($url), |
195
|
|
|
'OG_URL' => $url, |
196
|
|
|
'ENABLE_OG' => isset($this->config['socialbuttons_enable_og']) ? $this->config['socialbuttons_enable_og'] : '', |
197
|
|
|
'OG_IMAGE' => isset($this->config['socialbuttons_og_image']) ? $this->config['socialbuttons_og_image'] : '', |
198
|
|
|
'ENABLE_OG_TITLE' => isset($this->config['socialbuttons_enable_og_title']) ? $this->config['socialbuttons_enable_og_title'] : '', |
199
|
|
|
'OG_TITLE' => $event['page_title'], |
200
|
|
|
'ENABLE_OG_DESC' => ((isset($this->config['socialbuttons_enable_og_desc']) && $this->config['socialbuttons_enable_og_desc']) || in_array($event['topic_data']['forum_id'], $forums)), |
201
|
|
|
)); |
202
|
|
|
$this->user->add_lang_ext('tas2580/socialbuttons', 'common'); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* Get the number of shares |
207
|
|
|
* |
208
|
|
|
* @param string $url The URL to get the shares for |
209
|
|
|
* @return array |
210
|
|
|
* @access private |
211
|
|
|
*/ |
212
|
|
|
private function get_share_count($url) |
213
|
|
|
{ |
214
|
|
|
$cache_time = isset($this->config['socialbuttons_cachetime']) ? $this->config['socialbuttons_cachetime'] : 0; |
215
|
|
|
$multiplicator = isset($this->config['socialbuttons_multiplicator']) ? $this->config['socialbuttons_multiplicator'] : 1; |
216
|
|
|
|
217
|
|
|
$cachetime = ((int) $cache_time * (int) $multiplicator); |
218
|
|
|
$cache_file = '_socialbuttons_' . $url; |
219
|
|
|
$shares = $this->cache->get($cache_file); |
220
|
|
|
|
221
|
|
|
// If cache is too old or we have no cache, query the platforms |
222
|
|
|
if ($shares === false) |
223
|
|
|
{ |
224
|
|
|
$content = $querys = array(); |
225
|
|
|
// Collect the querys |
226
|
|
|
if (isset($this->config['socialbuttons_facebook']) && ($this->config['socialbuttons_facebook'] == 1)) |
227
|
|
|
{ |
228
|
|
|
$querys['facebook'] = 'https://www.facebook.com/plugins/like.php?&layout=box_count&href=' . $url; |
229
|
|
|
} |
230
|
|
|
if (isset($this->config['socialbuttons_twitter']) && ($this->config['socialbuttons_twitter'] == 1)) |
231
|
|
|
{ |
232
|
|
|
$querys['twitter'] = 'http://opensharecount.com/count.json?url=' . $url; |
233
|
|
|
} |
234
|
|
|
if (isset($this->config['socialbuttons_google']) && ($this->config['socialbuttons_twitter'] == 1)) |
235
|
|
|
{ |
236
|
|
|
$querys['google'] = 'https://plusone.google.com/_/+1/fastbutton?url=' . $url; |
237
|
|
|
} |
238
|
|
|
if (isset($this->config['socialbuttons_linkedin']) && ($this->config['socialbuttons_twitter'] == 1)) |
239
|
|
|
{ |
240
|
|
|
$querys['linkedin'] = 'https://www.linkedin.com/countserv/count/share?format=json&url=' . $url; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
// Do we have curl? We can query all platforms paralel what is mutch faster |
244
|
|
|
if (function_exists('curl_multi_init') && function_exists('curl_multi_exec')) |
245
|
|
|
{ |
246
|
|
|
// Set curl options for each URL |
247
|
|
|
$mh = curl_multi_init(); |
248
|
|
|
$handle = array(); |
249
|
|
|
foreach ($querys as $platform => $query_url) |
250
|
|
|
{ |
251
|
|
|
$ch = curl_init(); |
252
|
|
|
curl_setopt($ch, CURLOPT_URL, $query_url); |
253
|
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); |
254
|
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,3); |
255
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 3); |
256
|
|
|
curl_setopt($ch, CURLOPT_NOBODY, false); |
257
|
|
|
curl_setopt($ch, CURLOPT_HEADER, false); |
258
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
259
|
|
|
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0'); |
260
|
|
|
curl_multi_add_handle($mh, $ch); |
261
|
|
|
$handle[$platform] = $ch; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
// Exec the query |
265
|
|
|
$running = 0; |
266
|
|
|
do |
267
|
|
|
{ |
268
|
|
|
curl_multi_exec($mh, $running); |
269
|
|
|
} |
270
|
|
|
while ($running > 0); |
271
|
|
|
|
272
|
|
|
// Get the resonse |
273
|
|
|
foreach ($handle as $platform => $ch) |
274
|
|
|
{ |
275
|
|
|
$handle = curl_multi_info_read($mh); |
276
|
|
|
$content[$platform] = curl_multi_getcontent($ch); |
277
|
|
|
curl_multi_remove_handle($mh, $handle['handle'] ); |
278
|
|
|
} |
279
|
|
|
curl_multi_close($mh); |
280
|
|
|
} |
281
|
|
|
// No curl we have to do it the old way |
282
|
|
|
else |
283
|
|
|
{ |
284
|
|
|
//Set the useragent |
285
|
|
|
$options = array('http' => array('user_agent' => 'Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0')); |
286
|
|
|
$context = stream_context_create($options); |
287
|
|
|
foreach ($querys as $platform => $query_url) |
288
|
|
|
{ |
289
|
|
|
$content[$platform] = file_get_contents($query_url, false, $context); |
290
|
|
|
} |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
// Get the number of shares from response |
294
|
|
|
$matches = array(); |
295
|
|
|
preg_match('#<div id="aggregateCount" class="Oy">([0-9]+)</div>#s', $content['google'], $matches); |
296
|
|
|
$shares['google'] = isset($matches[1]) ? $matches[1] : 0; |
297
|
|
|
|
298
|
|
|
preg_match('#<span id="u_0_1">([0-9]+)</span>#s', $content['facebook'], $matches); |
299
|
|
|
$shares['facebook'] = isset($matches[1]) ? $matches[1] : 0 ; |
300
|
|
|
|
301
|
|
|
$pageinfo = json_decode($content['twitter'], true); |
302
|
|
|
$shares['twitter'] = isset($pageinfo['count']) ? $pageinfo['count'] : 0; |
303
|
|
|
|
304
|
|
|
$pageinfo = json_decode($content['linkedin'], true); |
305
|
|
|
$shares['linkedin'] = isset($pageinfo['count']) ? $pageinfo['count'] : 0; |
306
|
|
|
|
307
|
|
|
// Write data to cache |
308
|
|
|
$this->cache->put($cache_file, $shares, $cachetime); |
309
|
|
|
return $shares; |
310
|
|
|
} |
311
|
|
|
else |
312
|
|
|
{ |
313
|
|
|
// return data from cache |
314
|
|
|
return $shares; |
315
|
|
|
} |
316
|
|
|
} |
317
|
|
|
} |
318
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.