Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like link often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use link, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | class link extends helper |
||
14 | { |
||
15 | /** @var \phpbb\db\driver\driver_interface */ |
||
16 | protected $db; |
||
17 | |||
18 | /** @var \phpbb\config\config */ |
||
19 | protected $config; |
||
20 | |||
21 | /** @var \phpbb\language\language */ |
||
22 | protected $language; |
||
23 | |||
24 | /** @var \phpbb\template\template */ |
||
25 | protected $template; |
||
26 | |||
27 | /** @var \phpbb\user */ |
||
28 | protected $user; |
||
29 | |||
30 | /** @var \phpbb\controller\helper */ |
||
31 | protected $helper; |
||
32 | |||
33 | /** @var \phpbb\request\request */ |
||
34 | protected $request; |
||
35 | |||
36 | /** @var \phpbb\auth\auth */ |
||
37 | protected $auth; |
||
38 | |||
39 | /** @var \phpbb\notification\manager */ |
||
40 | protected $notification; |
||
41 | |||
42 | /** @var \phpbb\filesystem\filesystem_interface */ |
||
43 | protected $filesystem; |
||
44 | |||
45 | /** @var \FastImageSize\FastImageSize */ |
||
46 | protected $imagesize; |
||
47 | |||
48 | /** @var \phpbb\files\upload */ |
||
49 | protected $files_upload; |
||
50 | |||
51 | /** @var string phpBB root path */ |
||
52 | protected $root_path; |
||
53 | |||
54 | /** @var string phpEx */ |
||
55 | protected $php_ext; |
||
56 | |||
57 | /** |
||
58 | * Constructor |
||
59 | * |
||
60 | * @param \phpbb\db\driver\driver_interface $db Database object |
||
61 | * @param \phpbb\config\config $config Config object |
||
62 | * @param \phpbb\language\language $language Language object |
||
63 | * @param \phpbb\template\template $template Template object |
||
64 | * @param \phpbb\user $user User object |
||
65 | * @param \phpbb\controller\helper $helper Controller helper object |
||
66 | * @param \phpbb\request\request $request Request object |
||
67 | * @param \phpbb\auth\auth $auth Auth object |
||
68 | * @param \phpbb\notification\manager $notification Notification object |
||
69 | * @param \phpbb\filesystem\filesystem_interface $filesystem phpBB filesystem helper |
||
70 | * @param \FastImageSize\FastImageSize $imagesize FastImageSize class |
||
71 | * @param \phpbb\files\upload $files_upload Upload object |
||
72 | * @param string $root_path phpBB root path |
||
73 | * @param string $php_ext phpEx |
||
74 | */ |
||
75 | View Code Duplication | public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\language\language $language, \phpbb\template\template $template, \phpbb\user $user, \phpbb\controller\helper $helper, \phpbb\request\request $request, \phpbb\auth\auth $auth, \phpbb\notification\manager $notification, \phpbb\filesystem\filesystem_interface $filesystem, \FastImageSize\FastImageSize $imagesize, \phpbb\files\upload $files_upload, $root_path, $php_ext) |
|
76 | { |
||
77 | $this->db = $db; |
||
78 | $this->config = $config; |
||
79 | $this->language = $language; |
||
80 | $this->template = $template; |
||
81 | $this->user = $user; |
||
82 | $this->helper = $helper; |
||
83 | $this->request = $request; |
||
84 | $this->auth = $auth; |
||
85 | $this->notification = $notification; |
||
86 | $this->filesystem = $filesystem; |
||
87 | $this->imagesize = $imagesize; |
||
88 | $this->files_upload = $files_upload; |
||
89 | $this->root_path = $root_path; |
||
90 | $this->php_ext = $php_ext; |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * Add a link into db |
||
95 | * |
||
96 | * @param array $data Contains all data to insert in db |
||
97 | * @param bool $need_approval Links needs to be approved? |
||
98 | * @return null |
||
99 | */ |
||
100 | public function add($data, $need_approval) |
||
101 | { |
||
102 | $notification_data = array(); |
||
103 | |||
104 | $this->db->sql_transaction('begin'); |
||
105 | |||
106 | $sql = 'INSERT INTO ' . $this->links_table . ' ' . $this->db->sql_build_array('INSERT', $data); |
||
107 | $this->db->sql_query($sql); |
||
108 | $notification_data['link_id'] = $this->db->sql_nextid(); |
||
109 | |||
110 | if (!$need_approval || $this->auth->acl_get('a_') || $this->auth->acl_get('m_')) |
||
111 | { |
||
112 | $sql = 'UPDATE ' . $this->categories_table . ' |
||
113 | SET cat_links = cat_links + 1 |
||
114 | WHERE cat_id = ' . (int) $data['link_cat']; |
||
115 | $this->db->sql_query($sql); |
||
116 | |||
117 | $notification_type = 'ernadoo.phpbbdirectory.notification.type.directory_website'; |
||
118 | } |
||
119 | else if ($this->config['dir_mail']) |
||
120 | { |
||
121 | $notification_type = 'ernadoo.phpbbdirectory.notification.type.directory_website_in_queue'; |
||
122 | } |
||
123 | |||
124 | $this->db->sql_transaction('commit'); |
||
125 | |||
126 | if (isset($notification_type)) |
||
127 | { |
||
128 | $notification_data = array_merge($notification_data, |
||
129 | array( |
||
130 | 'user_from' => (int) $data['link_user_id'], |
||
131 | 'link_name' => $data['link_name'], |
||
132 | 'link_url' => $data['link_url'], |
||
133 | 'link_description' => $data['link_description'], |
||
134 | 'cat_id' => (int) $data['link_cat'], |
||
135 | 'cat_name' => \ernadoo\phpbbdirectory\core\categorie::getname((int) $data['link_cat']), |
||
136 | ) |
||
137 | ); |
||
138 | |||
139 | $this->notification->add_notifications($notification_type, $notification_data); |
||
140 | } |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * Edit a link of the db |
||
145 | * |
||
146 | * @param array $data Contains all data to edit in db |
||
147 | * @param int $link_id is link's id, for WHERE clause |
||
148 | * @param bool $need_approval Links needs to be approved? |
||
149 | * @return null |
||
150 | */ |
||
151 | public function edit($data, $link_id, $need_approval) |
||
152 | { |
||
153 | $notification_data = array( |
||
154 | 'link_id' => (int) $link_id, |
||
155 | 'user_from' => (int) $data['link_user_id'], |
||
156 | 'link_name' => $data['link_name'], |
||
157 | 'link_description' => $data['link_description'], |
||
158 | 'cat_id' => (int) $data['link_cat'], |
||
159 | 'cat_name' => \ernadoo\phpbbdirectory\core\categorie::getname((int) $data['link_cat']), |
||
160 | ); |
||
161 | |||
162 | $old_cat = array_pop($data); |
||
163 | |||
164 | if ($old_cat != $data['link_cat'] || $need_approval) |
||
165 | { |
||
166 | $this->notification->delete_notifications('ernadoo.phpbbdirectory.notification.type.directory_website', (int) $link_id); |
||
167 | |||
168 | $this->db->sql_transaction('begin'); |
||
169 | |||
170 | $sql = 'UPDATE ' . $this->categories_table . ' |
||
171 | SET cat_links = cat_links - 1 |
||
172 | WHERE cat_id = ' . (int) $old_cat; |
||
173 | $this->db->sql_query($sql); |
||
174 | |||
175 | if (!$need_approval) |
||
176 | { |
||
177 | $sql = 'UPDATE ' . $this->categories_table . ' |
||
178 | SET cat_links = cat_links + 1 |
||
179 | WHERE cat_id = ' . (int) $data['link_cat']; |
||
180 | $this->db->sql_query($sql); |
||
181 | |||
182 | $notification_type = 'ernadoo.phpbbdirectory.notification.type.directory_website'; |
||
183 | } |
||
184 | else |
||
185 | { |
||
186 | $data['link_active'] = false; |
||
187 | $notification_type = 'ernadoo.phpbbdirectory.notification.type.directory_website_in_queue'; |
||
188 | } |
||
189 | |||
190 | $this->db->sql_transaction('commit'); |
||
191 | |||
192 | $this->notification->add_notifications($notification_type, $notification_data); |
||
193 | } |
||
194 | |||
195 | $sql = 'UPDATE ' . $this->links_table . ' |
||
196 | SET ' . $this->db->sql_build_array('UPDATE', $data) . ' |
||
197 | WHERE link_id = ' . (int) $link_id; |
||
198 | $this->db->sql_query($sql); |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * Delete a link of the db |
||
203 | * |
||
204 | * @param int $cat_id The category ID |
||
205 | * @param mixed $link_id Link's id, for WHERE clause |
||
206 | * @return null |
||
207 | */ |
||
208 | public function del($cat_id, $link_id) |
||
209 | { |
||
210 | $this->db->sql_transaction('begin'); |
||
211 | |||
212 | $url_array = is_array($link_id) ? $link_id : array($link_id); |
||
213 | |||
214 | // Delete links datas |
||
215 | $link_datas_ary = array( |
||
216 | $this->links_table => 'link_id', |
||
217 | $this->comments_table => 'comment_link_id', |
||
218 | $this->votes_table => 'vote_link_id', |
||
219 | ); |
||
220 | |||
221 | $sql = 'SELECT link_banner |
||
222 | FROM ' . $this->links_table . ' |
||
223 | WHERE '. $this->db->sql_in_set('link_id', $url_array); |
||
224 | $result = $this->db->sql_query($sql); |
||
225 | |||
226 | while ($row = $this->db->sql_fetchrow($result)) |
||
227 | { |
||
228 | View Code Duplication | if ($row['link_banner'] && !preg_match('/^(http:\/\/|https:\/\/|ftp:\/\/|ftps:\/\/|www\.).+/si', $row['link_banner'])) |
|
229 | { |
||
230 | $banner_img = $this->root_path . $this->get_banner_path(basename($row['link_banner'])); |
||
231 | |||
232 | if (file_exists($banner_img)) |
||
233 | { |
||
234 | @unlink($banner_img); |
||
235 | } |
||
236 | } |
||
237 | } |
||
238 | |||
239 | foreach ($link_datas_ary as $table => $field) |
||
240 | { |
||
241 | $this->db->sql_query("DELETE FROM $table WHERE ".$this->db->sql_in_set($field, $url_array)); |
||
242 | } |
||
243 | |||
244 | $sql = 'UPDATE ' . $this->categories_table . ' |
||
245 | SET cat_links = cat_links - '.sizeof($url_array).' |
||
246 | WHERE cat_id = ' . (int) $cat_id; |
||
247 | $this->db->sql_query($sql); |
||
248 | |||
249 | $this->db->sql_transaction('commit'); |
||
250 | |||
251 | foreach ($url_array as $link_id) |
||
252 | { |
||
253 | $this->notification->delete_notifications(array( |
||
254 | 'ernadoo.phpbbdirectory.notification.type.directory_website', |
||
255 | 'ernadoo.phpbbdirectory.notification.type.directory_website_in_queue' |
||
256 | ), $link_id); |
||
257 | } |
||
258 | |||
259 | View Code Duplication | if ($this->request->is_ajax()) |
|
260 | { |
||
261 | $sql = 'SELECT cat_links |
||
262 | FROM ' . $this->categories_table . ' |
||
263 | WHERE cat_id = ' . (int) $cat_id; |
||
264 | $result = $this->db->sql_query($sql); |
||
265 | $data = $this->db->sql_fetchrow($result); |
||
266 | |||
267 | $json_response = new \phpbb\json_response; |
||
268 | $json_response->send(array( |
||
269 | 'success' => true, |
||
270 | |||
271 | 'MESSAGE_TITLE' => $this->language->lang('INFORMATION'), |
||
272 | 'MESSAGE_TEXT' => $this->language->lang('DIR_DELETE_OK'), |
||
273 | 'LINK_ID' => $link_id, |
||
274 | 'TOTAL_LINKS' => $this->language->lang('DIR_NB_LINKS', (int) $data['cat_links']), |
||
275 | )); |
||
276 | } |
||
277 | } |
||
278 | |||
279 | /** |
||
280 | * Increments link view counter |
||
281 | * |
||
282 | * @param int $link_id Link's id, for WHERE clause |
||
283 | * @return null |
||
284 | * @throws \phpbb\exception\http_exception |
||
285 | */ |
||
286 | public function view($link_id) |
||
287 | { |
||
288 | $sql = 'SELECT link_id, link_url |
||
289 | FROM ' . $this->links_table . ' |
||
290 | WHERE link_id = ' . (int) $link_id; |
||
291 | $result = $this->db->sql_query($sql); |
||
292 | $data = $this->db->sql_fetchrow($result); |
||
293 | |||
294 | if (empty($data['link_id'])) |
||
295 | { |
||
296 | throw new \phpbb\exception\http_exception(404, 'DIR_ERROR_NO_LINKS'); |
||
297 | } |
||
298 | |||
299 | $sql = 'UPDATE ' . $this->links_table . ' |
||
300 | SET link_view = link_view + 1 |
||
301 | WHERE link_id = ' . (int) $link_id; |
||
302 | $this->db->sql_query($sql); |
||
303 | |||
304 | redirect($data['link_url'], false, true); |
||
305 | return; |
||
306 | } |
||
307 | |||
308 | /** |
||
309 | * Verify that an URL exist before add into db |
||
310 | * |
||
311 | * @param string $url The URL to check |
||
312 | * @return bool True if url is reachable, else false. |
||
313 | */ |
||
314 | public function checkurl($url) |
||
315 | { |
||
316 | $details = parse_url($url); |
||
317 | |||
318 | $default_port = 80; |
||
319 | $hostname = $details['host']; |
||
320 | |||
321 | if ($details['scheme'] == 'https') |
||
322 | { |
||
323 | $default_port = 443; |
||
324 | $hostname = 'ssl://' . $details['host']; |
||
325 | } |
||
326 | |||
327 | if (!isset($details['path'])) |
||
328 | { |
||
329 | $details['path'] = '/'; |
||
330 | } |
||
331 | |||
332 | $port = (isset($details['port']) && !empty($details['port'])) ? (int) $details['port'] : $default_port; |
||
333 | |||
334 | if ($sock = @fsockopen($hostname, $port, $errno, $errstr, 1)) |
||
335 | { |
||
336 | $requete = 'GET '.$details['path']." HTTP/1.1\r\n"; |
||
337 | $requete .= 'Host: '.$details['host']."\r\n\r\n"; |
||
338 | |||
339 | // Send a HTTP GET header |
||
340 | fputs($sock, $requete); |
||
341 | // answer from server |
||
342 | $str = fgets($sock, 1024); |
||
343 | preg_match("'HTTP/1\.. (.*) (.*)'U", $str, $parts); |
||
344 | fclose($sock); |
||
345 | |||
346 | return !($parts[1] == '404'); |
||
347 | } |
||
348 | return false; |
||
349 | } |
||
350 | |||
351 | /** |
||
352 | * Delete the final '/', if no path |
||
353 | * |
||
354 | * @param string $url URL to clean |
||
355 | * @return string $url The correct string. |
||
356 | */ |
||
357 | public function clean_url($url) |
||
358 | { |
||
359 | $details = parse_url($url); |
||
360 | |||
361 | if (isset($details['path']) && $details['path'] == '/' && !isset($details['query'])) |
||
362 | { |
||
363 | return substr($url, 0, -1); |
||
364 | } |
||
365 | return $url; |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Display a flag |
||
370 | * |
||
371 | * @param array $data Link's data from db |
||
372 | * @return string Flag path. |
||
373 | */ |
||
374 | public function display_flag($data) |
||
375 | { |
||
376 | global $phpbb_extension_manager; |
||
377 | |||
378 | $ext_path = $phpbb_extension_manager->get_extension_path('ernadoo/phpbbdirectory', true); |
||
379 | $flag_path = $ext_path.'images/flags/'; |
||
380 | $img_flag = 'no_flag.png'; |
||
381 | |||
382 | if ($this->config['dir_activ_flag'] && !empty($data['link_flag']) && file_exists($flag_path . $data['link_flag'])) |
||
383 | { |
||
384 | $img_flag = $data['link_flag']; |
||
385 | } |
||
386 | |||
387 | return $this->get_img_path('flags', $img_flag); |
||
388 | } |
||
389 | |||
390 | /** |
||
391 | * Calculate the link's note |
||
392 | * |
||
393 | * @param int $total_note Sum of all link's notes |
||
394 | * @param int $nb_vote Number of votes |
||
395 | * @param bool $votes_status Votes are enable in this category? |
||
396 | * @return string $note The calculated note. |
||
397 | */ |
||
398 | public function display_note($total_note, $nb_vote, $votes_status) |
||
399 | { |
||
400 | if (!$votes_status) |
||
401 | { |
||
402 | return; |
||
403 | } |
||
404 | |||
405 | $note = ($nb_vote < 1) ? '' : $total_note / $nb_vote; |
||
406 | $note = (strlen($note) > 2) ? number_format($note, 1) : $note; |
||
407 | |||
408 | return ($nb_vote) ? $this->language->lang('DIR_FROM_TEN', $note) : $this->language->lang('DIR_NO_NOTE'); |
||
409 | } |
||
410 | |||
411 | /** |
||
412 | * Display the vote form for auth users |
||
413 | * |
||
414 | * @param array $data Link's data from db |
||
415 | * @return null|string Html combo list or nothing if votes are not available. |
||
416 | */ |
||
417 | public function display_vote($data) |
||
418 | { |
||
419 | if ($this->user->data['is_registered'] && $this->auth->acl_get('u_vote_dir') && empty($data['vote_user_id'])) |
||
420 | { |
||
421 | $list = '<select name="vote">'; |
||
422 | for ($i = 0; $i <= 10; $i++) |
||
423 | { |
||
424 | $list .= '<option value="' . $i . '"' . (($i == 5) ? ' selected="selected"' : '') . '>' . $i . '</option>'; |
||
425 | } |
||
426 | $list .= '</select>'; |
||
427 | |||
428 | return $list; |
||
429 | } |
||
430 | } |
||
431 | |||
432 | /** |
||
433 | * Display the RSS icon |
||
434 | * |
||
435 | * @param array $data Link's data from db |
||
436 | * @return null|string RSS feed URL or nothing. |
||
437 | */ |
||
438 | public function display_rss($data) |
||
439 | { |
||
440 | if ($this->config['dir_activ_rss'] && !empty($data['link_rss'])) |
||
441 | { |
||
442 | return $data['link_rss']; |
||
443 | } |
||
444 | } |
||
445 | |||
446 | /** |
||
447 | * Display link's thumb if thumb service enabled. |
||
448 | * if thumb don't exists in db or if a new service was choosen in acp |
||
449 | * thumb is research |
||
450 | * |
||
451 | * @param array $data Link's data from db |
||
452 | * @return string|null Thumb or null. |
||
453 | */ |
||
454 | public function display_thumb($data) |
||
455 | { |
||
456 | if ($this->config['dir_activ_thumb']) |
||
457 | { |
||
458 | if (!$data['link_thumb'] || ($this->config['dir_thumb_service_reverse'] && (!strstr($data['link_thumb'], 'ascreen.jpg') && (!strstr($data['link_thumb'], $this->config['dir_thumb_service']))))) |
||
459 | { |
||
460 | $thumb = $this->thumb_process($data['link_url']); |
||
461 | |||
462 | $sql = 'UPDATE ' . $this->links_table . " |
||
463 | SET link_thumb = '" . $this->db->sql_escape($thumb) . "' |
||
464 | WHERE link_id = " . (int) $data['link_id']; |
||
465 | $this->db->sql_query($sql); |
||
466 | |||
467 | return $thumb; |
||
468 | } |
||
469 | return $data['link_thumb']; |
||
470 | } |
||
471 | } |
||
472 | |||
473 | /** |
||
474 | * Display and resize a banner |
||
475 | * |
||
476 | * @param array $data link's data from db |
||
477 | * @return string $s_banner html code. |
||
478 | */ |
||
479 | public function display_bann($data) |
||
480 | { |
||
481 | if (!empty($data['link_banner'])) |
||
482 | { |
||
483 | if (!preg_match('/^(http:\/\/|https:\/\/|ftp:\/\/|ftps:\/\/|www\.).+/si', $data['link_banner'])) |
||
484 | { |
||
485 | $img_src = $this->helper->route('ernadoo_phpbbdirectory_banner_controller', array('banner_img' => $data['link_banner'])); |
||
486 | $physical_path = $this->get_banner_path($data['link_banner']); |
||
487 | } |
||
488 | else |
||
489 | { |
||
490 | $img_src = $physical_path = $data['link_banner']; |
||
491 | } |
||
492 | |||
493 | if (($image_data = $this->imagesize->getImageSize($physical_path)) === false) |
||
494 | { |
||
495 | return ''; |
||
496 | } |
||
497 | |||
498 | $width = $image_data['width']; |
||
499 | $height = $image_data['height']; |
||
500 | |||
501 | if (($width > $this->config['dir_banner_width'] || $height > $this->config['dir_banner_height']) && $this->config['dir_banner_width'] > 0 && $this->config['dir_banner_height'] > 0) |
||
502 | { |
||
503 | $coef_w = $width / $this->config['dir_banner_width']; |
||
504 | $coef_h = $height / $this->config['dir_banner_height']; |
||
505 | $coef_max = max($coef_w, $coef_h); |
||
506 | $width /= $coef_max; |
||
507 | $height /= $coef_max; |
||
508 | } |
||
509 | |||
510 | return '<img src="' . $img_src . '" width="' . $width . '" height="' . $height . '" alt="'.$data['link_name'].'" title="'.$data['link_name'].'" />'; |
||
511 | } |
||
512 | return ''; |
||
513 | } |
||
514 | |||
515 | /** |
||
516 | * Add a vote in db, for a specifi link |
||
517 | * |
||
518 | * @param int $link_id Link_id from db |
||
519 | * @param int $note Note submeted |
||
520 | * @return null |
||
521 | */ |
||
522 | public function add_vote($link_id, $note) |
||
523 | { |
||
524 | $data = array( |
||
525 | 'vote_link_id' => (int) $link_id, |
||
526 | 'vote_user_id' => $this->user->data['user_id'], |
||
527 | 'vote_note' => (int) $note, |
||
528 | ); |
||
529 | |||
530 | $this->db->sql_transaction('begin'); |
||
531 | |||
532 | $sql = 'INSERT INTO ' . $this->votes_table . ' ' . $this->db->sql_build_array('INSERT', $data); |
||
533 | $this->db->sql_query($sql); |
||
534 | |||
535 | $sql = 'UPDATE ' . $this->links_table . ' |
||
536 | SET link_vote = link_vote + 1, |
||
537 | link_note = link_note + ' . (int) $data['vote_note'] . ' |
||
538 | WHERE link_id = ' . (int) $link_id; |
||
539 | $this->db->sql_query($sql); |
||
540 | |||
541 | $this->db->sql_transaction('commit'); |
||
542 | |||
543 | if ($this->request->is_ajax()) |
||
544 | { |
||
545 | $sql= 'SELECT link_vote, link_note FROM ' . $this->links_table . ' WHERE link_id = ' . (int) $link_id; |
||
546 | $result = $this->db->sql_query($sql); |
||
547 | $data = $this->db->sql_fetchrow($result); |
||
548 | |||
549 | $note = $this->display_note($data['link_note'], $data['link_vote'], true); |
||
550 | |||
551 | $json_response = new \phpbb\json_response; |
||
552 | $json_response->send(array( |
||
553 | 'success' => true, |
||
554 | |||
555 | 'MESSAGE_TITLE' => $this->language->lang('INFORMATION'), |
||
556 | 'MESSAGE_TEXT' => $this->language->lang('DIR_VOTE_OK'), |
||
557 | 'NOTE' => $note, |
||
558 | 'NB_VOTE' => $this->language->lang('DIR_NB_VOTES', (int) $data['link_vote']), |
||
559 | 'LINK_ID' => $link_id |
||
560 | )); |
||
561 | } |
||
562 | } |
||
563 | |||
564 | /** |
||
565 | * Search an appropriate thumb for url |
||
566 | * |
||
567 | * @param string $url Link's url |
||
568 | * @return string The thumb url |
||
569 | */ |
||
570 | public function thumb_process($url) |
||
571 | { |
||
572 | if (!$this->config['dir_activ_thumb']) |
||
573 | { |
||
574 | return $this->root_path.'images/directory/nothumb.gif'; |
||
575 | } |
||
576 | |||
577 | $details = parse_url($url); |
||
578 | |||
579 | $root_url = $details['scheme'].'://'.$details['host']; |
||
580 | $absolute_url = isset($details['path']) ? $root_url.$details['path'] : $root_url; |
||
581 | |||
582 | if ($this->config['dir_activ_thumb_remote'] && $this->_ascreen_exist($details['scheme'], $details['host'])) |
||
583 | { |
||
584 | return $root_url.'/ascreen.jpg'; |
||
585 | } |
||
586 | return $this->config['dir_thumb_service'].$absolute_url; |
||
587 | } |
||
588 | |||
589 | /** |
||
590 | * Check if ascreen thumb exists |
||
591 | * |
||
592 | * @param string $protocol The protocol |
||
593 | * @param string $host The hostname |
||
594 | * @return bool True if ascreen file exixts, else false |
||
595 | */ |
||
596 | private function _ascreen_exist($protocol, $host) |
||
597 | { |
||
598 | if (($thumb_info = $this->imagesize->getImageSize($protocol.'://'.$host.'/ascreen.jpg')) !== false) |
||
599 | { |
||
600 | // Obviously this is an image, we did some additional tests |
||
601 | if ($thumb_info['width'] == '120' && $thumb_info['height'] == '90' && $thumb_info['type'] == 2) |
||
602 | { |
||
603 | return true; |
||
604 | } |
||
605 | } |
||
606 | return false; |
||
607 | } |
||
608 | |||
609 | /** |
||
610 | * Primary work on banner, can edit, copy or check a banner |
||
611 | * |
||
612 | * @param string $banner The banner's remote url |
||
613 | * @param array $error The array error, passed by reference |
||
614 | * @return null |
||
615 | */ |
||
616 | public function banner_process(&$banner, &$error) |
||
617 | { |
||
618 | $old_banner = $this->request->variable('old_banner', ''); |
||
619 | |||
620 | $destination = $this->root_path . $this->get_banner_path(); |
||
621 | |||
622 | // Can we upload? |
||
623 | $can_upload = ($this->config['dir_storage_banner'] && $this->filesystem->exists($destination) && $this->filesystem->is_writable($destination) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false; |
||
624 | |||
625 | if ($banner && $can_upload) |
||
626 | { |
||
627 | $file = $this->_banner_upload($banner, $error); |
||
628 | } |
||
629 | else if ($banner) |
||
630 | { |
||
631 | $file = $this->_banner_remote($banner, $error); |
||
632 | } |
||
633 | else if ($this->request->is_set_post('delete_banner') && $old_banner) |
||
634 | { |
||
635 | $this->_banner_delete($old_banner); |
||
636 | return; |
||
637 | } |
||
638 | |||
639 | if (!sizeof($error)) |
||
640 | { |
||
641 | if ($banner && $old_banner && !preg_match('/^(http:\/\/|https:\/\/|ftp:\/\/|ftps:\/\/|www\.).+/si', $old_banner)) |
||
642 | { |
||
643 | $this->_banner_delete($old_banner); |
||
644 | } |
||
645 | |||
646 | $banner = !empty($file) ? $file : ''; |
||
647 | } |
||
648 | } |
||
649 | |||
650 | /** |
||
651 | * Copy a remonte banner to server. |
||
652 | * called by banner_process() |
||
653 | * |
||
654 | * @param string $banner The banner's remote url |
||
655 | * @param array $error The array error, passed by reference |
||
656 | * @return false|string String if no errors, else false |
||
657 | */ |
||
658 | private function _banner_upload($banner, &$error) |
||
659 | { |
||
660 | /** @var \phpbb\files\upload $upload */ |
||
661 | $upload = $this->files_upload |
||
662 | ->set_error_prefix('DIR_BANNER_') |
||
663 | ->set_allowed_extensions(array('jpg', 'jpeg', 'gif', 'png')) |
||
664 | ->set_max_filesize($this->config['dir_banner_filesize']) |
||
665 | ->set_disallowed_content((isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false)); |
||
666 | |||
667 | $file = $upload->handle_upload('files.types.remote', $banner); |
||
668 | |||
669 | $prefix = unique_id() . '_'; |
||
670 | $file->clean_filename('real', $prefix); |
||
671 | |||
672 | if (sizeof($file->error)) |
||
673 | { |
||
674 | $file->remove(); |
||
675 | $error = array_merge($error, $file->error); |
||
676 | $error = array_map(array($this->language, 'lang'), $error); |
||
677 | return false; |
||
678 | } |
||
679 | |||
680 | $destination = $this->get_banner_path(); |
||
681 | |||
682 | // Move file and overwrite any existing image |
||
683 | $file->move_file($destination, true); |
||
684 | |||
685 | return strtolower($file->get('realname')); |
||
686 | } |
||
687 | |||
688 | /** |
||
689 | * Check than remote banner exists |
||
690 | * called by banner_process() |
||
691 | * |
||
692 | * @param string $banner The banner's remote url |
||
693 | * @param array $error The array error, passed by reference |
||
694 | * @return false|string String if no errors, else false |
||
695 | */ |
||
696 | private function _banner_remote($banner, &$error) |
||
697 | { |
||
698 | if (!preg_match('#^(http|https|ftp)://#i', $banner)) |
||
699 | { |
||
700 | $banner = 'http://' . $banner; |
||
701 | } |
||
702 | if (!preg_match('#^(http|https|ftp)://(?:(.*?\.)*?[a-z0-9\-]+?\.[a-z]{2,4}|(?:\d{1,3}\.){3,5}\d{1,3}):?([0-9]*?).*?\.(gif|jpg|jpeg|png)$#i', $banner)) |
||
703 | { |
||
704 | $error[] = $this->language->lang('DIR_BANNER_URL_INVALID'); |
||
705 | return false; |
||
706 | } |
||
707 | |||
708 | // Get image dimensions |
||
709 | if (($image_data = $this->imagesize->getImageSize($banner)) === false) |
||
710 | { |
||
711 | $error[] = $this->language->lang('DIR_BANNER_UNABLE_GET_IMAGE_SIZE'); |
||
712 | return false; |
||
713 | } |
||
714 | |||
715 | if (!empty($image_data) && ($image_data['width'] < 2 || $image_data['height'] < 2)) |
||
716 | { |
||
717 | $error[] = $this->language->lang('DIR_BANNER_UNABLE_GET_IMAGE_SIZE'); |
||
718 | return false; |
||
719 | } |
||
720 | |||
721 | $width = $image_data['width']; |
||
722 | $height = $image_data['height']; |
||
723 | |||
724 | if ($width <= 0 || $height <= 0) |
||
725 | { |
||
726 | $error[] = $this->language->lang('DIR_BANNER_UNABLE_GET_IMAGE_SIZE'); |
||
727 | return false; |
||
728 | } |
||
729 | |||
730 | // Check image type |
||
731 | $types = \phpbb\files\upload::image_types(); |
||
732 | $extension = strtolower(\phpbb\files\filespec::get_extension($banner)); |
||
733 | |||
734 | // Check if this is actually an image |
||
735 | if ($file_stream = @fopen($banner, 'r')) |
||
736 | { |
||
737 | // Timeout after 1 second |
||
738 | stream_set_timeout($file_stream, 1); |
||
739 | // read some data to ensure headers are present |
||
740 | fread($file_stream, 1024); |
||
741 | $meta = stream_get_meta_data($file_stream); |
||
742 | if (isset($meta['wrapper_data']['headers']) && is_array($meta['wrapper_data']['headers'])) |
||
743 | { |
||
744 | $headers = $meta['wrapper_data']['headers']; |
||
745 | } |
||
746 | else if (isset($meta['wrapper_data']) && is_array($meta['wrapper_data'])) |
||
747 | { |
||
748 | $headers = $meta['wrapper_data']; |
||
749 | } |
||
750 | else |
||
751 | { |
||
752 | $headers = array(); |
||
753 | } |
||
754 | |||
755 | foreach ($headers as $header) |
||
756 | { |
||
757 | $header = preg_split('/ /', $header, 2); |
||
758 | if (strtr(strtolower(trim($header[0], ':')), '_', '-') === 'content-type') |
||
759 | { |
||
760 | if (strpos($header[1], 'image/') !== 0) |
||
761 | { |
||
762 | $error[] = 'DIR_BANNER_URL_INVALID'; |
||
763 | fclose($file_stream); |
||
764 | return false; |
||
765 | } |
||
766 | else |
||
767 | { |
||
768 | fclose($file_stream); |
||
769 | break; |
||
770 | } |
||
771 | } |
||
772 | } |
||
773 | } |
||
774 | else |
||
775 | { |
||
776 | $error[] = 'DIR_BANNER_URL_INVALID'; |
||
777 | return false; |
||
778 | } |
||
779 | |||
780 | if (!empty($image_data) && (!isset($types[$image_data['type']]) || !in_array($extension, $types[$image_data['type']]))) |
||
781 | { |
||
782 | if (!isset($types[$image_data['type']])) |
||
783 | { |
||
784 | $error[] = $this->language->lang('UNABLE_GET_IMAGE_SIZE'); |
||
785 | } |
||
786 | else |
||
787 | { |
||
788 | $error[] = $this->language->lang('DIR_BANNER_IMAGE_FILETYPE_MISMATCH', $types[$image_data['type']][0], $extension); |
||
789 | } |
||
790 | return false; |
||
791 | } |
||
792 | |||
793 | if (($this->config['dir_banner_width'] || $this->config['dir_banner_height']) && ($width > $this->config['dir_banner_width'] || $height > $this->config['dir_banner_height'])) |
||
794 | { |
||
795 | $error[] = $this->language->lang('DIR_BANNER_WRONG_SIZE', $this->config['dir_banner_width'], $this->config['dir_banner_height'], $width, $height); |
||
796 | return false; |
||
797 | } |
||
798 | |||
799 | return $banner; |
||
800 | } |
||
801 | |||
802 | /** |
||
803 | * Delete a banner from server |
||
804 | * |
||
805 | * @param string $file The file's name |
||
806 | * @return bool True if delete success, else false |
||
807 | */ |
||
808 | private function _banner_delete($file) |
||
809 | { |
||
810 | $old_banner = $this->root_path . $this->get_banner_path($file); |
||
811 | |||
812 | if (file_exists($old_banner)) |
||
813 | { |
||
814 | @unlink($old_banner); |
||
815 | return true; |
||
816 | } |
||
817 | |||
818 | return false; |
||
819 | } |
||
820 | |||
821 | /** |
||
822 | * List flags |
||
823 | * |
||
824 | * @param string $flag_path The flag directory path |
||
825 | * @param string $value Selected flag |
||
826 | * @return string $list Html code |
||
827 | */ |
||
828 | public function get_dir_flag_list($flag_path, $value) |
||
829 | { |
||
830 | $list = ''; |
||
831 | |||
832 | $this->language->add_lang('directory_flags', 'ernadoo/phpbbdirectory'); |
||
833 | |||
834 | $flags = $this->preg_grep_keys('/^DIR_FLAG_CODE_/i', $this->language->get_lang_array()); |
||
835 | |||
836 | if (extension_loaded('intl')) |
||
837 | { |
||
838 | $locale = $this->language->lang('USER_LANG'); |
||
839 | |||
840 | $col = new \Collator($locale); |
||
841 | $col->asort($flags); |
||
842 | } |
||
843 | else |
||
844 | { |
||
845 | asort($flags); |
||
846 | } |
||
847 | |||
848 | foreach ($flags as $file => $name) |
||
849 | { |
||
850 | $img_file = strtolower(substr(strrchr($file, '_'), 1)).'.png'; |
||
851 | |||
852 | if (file_exists($flag_path.$img_file)) |
||
853 | { |
||
854 | $list .= '<option value="' . $img_file . '" ' . (($img_file == $value) ? 'selected="selected"' : '') . '>' . $name . '</option>'; |
||
855 | } |
||
856 | } |
||
857 | |||
858 | return $list; |
||
859 | } |
||
860 | |||
861 | /** |
||
862 | * Display recents links added |
||
863 | * |
||
864 | * @return null |
||
865 | */ |
||
866 | public function recents() |
||
867 | { |
||
868 | if ($this->config['dir_recent_block']) |
||
869 | { |
||
870 | $limit_sql = $this->config['dir_recent_rows'] * $this->config['dir_recent_columns']; |
||
871 | $exclude_array = array_filter(explode(',', str_replace(' ', '', $this->config['dir_recent_exclude']))); |
||
872 | |||
873 | $sql_array = array( |
||
874 | 'SELECT' => 'l.link_id, l.link_cat, l.link_url, l.link_user_id, l.link_comment, l. link_description, l.link_vote, l.link_note, l.link_view, l.link_time, l.link_name, l.link_thumb, u.user_id, u.username, u.user_colour, c.cat_name', |
||
875 | 'FROM' => array( |
||
876 | $this->links_table => 'l'), |
||
877 | 'LEFT_JOIN' => array( |
||
878 | array( |
||
879 | 'FROM' => array(USERS_TABLE => 'u'), |
||
880 | 'ON' => 'l.link_user_id = u.user_id' |
||
881 | ), |
||
882 | array( |
||
883 | 'FROM' => array($this->categories_table => 'c'), |
||
884 | 'ON' => 'l.link_cat = c.cat_id' |
||
885 | ) |
||
886 | ), |
||
887 | 'WHERE' => 'l.link_active = 1' . (sizeof($exclude_array) ? ' AND ' . $this->db->sql_in_set('l.link_cat', $exclude_array, true) : ''), |
||
888 | 'ORDER_BY' => 'l.link_time DESC, l.link_id DESC'); |
||
889 | |||
890 | $sql = $this->db->sql_build_query('SELECT', $sql_array); |
||
891 | $result = $this->db->sql_query_limit($sql, $limit_sql, 0); |
||
892 | $num = 0; |
||
893 | $rowset = array(); |
||
894 | |||
895 | while ($site = $this->db->sql_fetchrow($result)) |
||
896 | { |
||
897 | $rowset[$site['link_id']] = $site; |
||
898 | } |
||
899 | $this->db->sql_freeresult($result); |
||
900 | |||
901 | if (sizeof($rowset)) |
||
902 | { |
||
903 | $this->template->assign_block_vars('block', array( |
||
904 | 'S_COL_WIDTH' => (100 / $this->config['dir_recent_columns']) . '%', |
||
905 | )); |
||
906 | |||
907 | foreach ($rowset as $row) |
||
908 | { |
||
909 | if (($num % $this->config['dir_recent_columns']) == 0) |
||
910 | { |
||
911 | $this->template->assign_block_vars('block.row', array()); |
||
912 | } |
||
913 | |||
914 | $this->template->assign_block_vars('block.row.col', array( |
||
915 | 'NAME' => $row['link_name'], |
||
916 | 'USER' => get_username_string('full', $row['link_user_id'], $row['username'], $row['user_colour']), |
||
917 | 'TIME' => ($row['link_time']) ? $this->user->format_date($row['link_time']) : '', |
||
918 | 'CAT' => $row['cat_name'], |
||
919 | 'COUNT' => $row['link_view'], |
||
920 | 'COMMENT' => $row['link_comment'], |
||
921 | |||
922 | 'U_CAT' => $this->helper->route('ernadoo_phpbbdirectory_dynamic_route_' . $row['link_cat']), |
||
923 | 'U_COMMENT' => $this->helper->route('ernadoo_phpbbdirectory_comment_view_controller', array('link_id' => (int) $row['link_id'])), |
||
924 | 'U_LINK' => $row['link_url'], |
||
925 | 'U_THUMB' => $this->display_thumb($row), |
||
926 | 'U_VIEW' => $this->helper->route('ernadoo_phpbbdirectory_view_controller', array('link_id' => (int) $row['link_id'])), |
||
927 | |||
928 | 'L_DIR_SEARCH_NB_CLICKS' => $this->language->lang('DIR_SEARCH_NB_CLICKS', (int) $row['link_view']), |
||
929 | 'L_DIR_SEARCH_NB_COMMS' => $this->language->lang('DIR_SEARCH_NB_COMMS', (int) $row['link_comment']), |
||
930 | )); |
||
931 | $num++; |
||
932 | } |
||
933 | |||
934 | while (($num % $this->config['dir_recent_columns']) != 0) |
||
935 | { |
||
936 | $this->template->assign_block_vars('block.row.col2', array()); |
||
937 | $num++; |
||
938 | } |
||
939 | } |
||
940 | } |
||
941 | } |
||
942 | |||
943 | /** |
||
944 | * Validate back link |
||
945 | * |
||
946 | * @param string $remote_url Page URL contains the backlink |
||
947 | * @param bool $optional Link back is optional in this category? |
||
948 | * @param bool $cron This methos is called by con process? |
||
949 | * @return false|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) |
||
950 | */ |
||
951 | public function validate_link_back($remote_url, $optional, $cron = false) |
||
988 | } |
||
989 |