Completed
Push — 3.2.x ( 186427...2e2541 )
by Erwan
03:01
created

link::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
c 6
b 0
f 0
dl 0
loc 18
rs 9.4285
cc 1
eloc 16
nc 1
nop 15

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
*
4
* phpBB Directory extension for the phpBB Forum Software package.
5
*
6
* @copyright (c) 2014 ErnadoO <http://www.phpbb-services.com>
7
* @license GNU General Public License, version 2 (GPL-2.0)
8
*
9
*/
10
11
namespace ernadoo\phpbbdirectory\core;
12
13
class link
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\factory */
49
	protected $files_factory;
50
51
	/** @var \ernadoo\phpbbdirectory\core\helper */
52
	protected $dir_helper;
53
54
	/** @var string phpBB root path */
55
	protected $root_path;
56
57
	/** @var string phpEx */
58
	protected $php_ext;
59
60
	/**
61
	* Constructor
62
	*
63
	* @param \phpbb\db\driver\driver_interface 					$db					Database object
64
	* @param \phpbb\config\config 								$config				Config object
65
	* @param \phpbb\language\language							$language			Language object
66
	* @param \phpbb\template\template 							$template			Template object
67
	* @param \phpbb\user 										$user				User object
68
	* @param \phpbb\controller\helper 							$helper				Controller helper object
69
	* @param \phpbb\request\request 							$request			Request object
70
	* @param \phpbb\auth\auth 									$auth				Auth object
71
	* @param \phpbb\notification\manager						$notification		Notification object
72
	* @param \phpbb\filesystem\filesystem_interface				$filesystem			phpBB filesystem helper
73
	* @param \FastImageSize\FastImageSize						$imagesize 			FastImageSize class
74
	* @param \phpbb\files\factory								$files_factory		File classes factory
75
	* @param \ernadoo\phpbbdirectory\core\helper				$dir_helper			PhpBB Directory extension helper object
76
	* @param string         									$root_path			phpBB root path
77
	* @param string         									$php_ext			phpEx
78
	*/
79
	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\factory $files_factory, \ernadoo\phpbbdirectory\core\helper $dir_helper, $root_path, $php_ext)
80
	{
81
		$this->db				= $db;
82
		$this->config			= $config;
83
		$this->language			= $language;
84
		$this->template			= $template;
85
		$this->user				= $user;
86
		$this->helper			= $helper;
87
		$this->request			= $request;
88
		$this->auth				= $auth;
89
		$this->notification		= $notification;
90
		$this->filesystem		= $filesystem;
91
		$this->imagesize		= $imagesize;
92
		$this->files_factory 	= $files_factory;
93
		$this->dir_helper		= $dir_helper;
94
		$this->root_path		= $root_path;
95
		$this->php_ext			= $php_ext;
96
	}
97
98
	/**
99
	* Add a link into db
100
	*
101
	* @param	array	$data			Contains all data to insert in db
102
	* @param	bool	$need_approval	Links needs to be approved?
103
	* @return	null
104
	*/
105
	public function add($data, $need_approval)
106
	{
107
		$notification_data = array();
108
109
		$this->db->sql_transaction('begin');
110
111
		$sql = 'INSERT INTO ' . DIR_LINK_TABLE . ' ' . $this->db->sql_build_array('INSERT', $data);
112
		$this->db->sql_query($sql);
113
		$notification_data['link_id'] = $this->db->sql_nextid();
114
115
		if (!$need_approval || $this->auth->acl_get('a_') || $this->auth->acl_get('m_'))
116
		{
117
			$sql = 'UPDATE ' . DIR_CAT_TABLE . '
118
				SET cat_links = cat_links + 1
119
				WHERE cat_id = ' . (int) $data['link_cat'];
120
			$this->db->sql_query($sql);
121
122
			$notification_type = 'ernadoo.phpbbdirectory.notification.type.directory_website';
123
		}
124
		else if ($this->config['dir_mail'])
125
		{
126
			$notification_type = 'ernadoo.phpbbdirectory.notification.type.directory_website_in_queue';
127
		}
128
129
		$this->db->sql_transaction('commit');
130
131
		if (isset($notification_type))
132
		{
133
			$notification_data = array_merge($notification_data,
134
				array(
135
					'user_from'			=> (int) $data['link_user_id'],
136
					'link_name'			=> $data['link_name'],
137
					'link_url'			=> $data['link_url'],
138
					'link_description'	=> $data['link_description'],
139
					'cat_id'			=> (int) $data['link_cat'],
140
					'cat_name'			=> \ernadoo\phpbbdirectory\core\categorie::getname((int) $data['link_cat']),
141
				)
142
			);
143
144
			$this->notification->add_notifications($notification_type, $notification_data);
145
		}
146
	}
147
148
	/**
149
	* Edit a link of the db
150
	*
151
	* @param	array	$data			Contains all data to edit in db
152
	* @param	int		$link_id		is link's id, for WHERE clause
153
	* @param	bool	$need_approval	Links needs to be approved?
154
	* @return	null
155
	*/
156
	public function edit($data, $link_id, $need_approval)
157
	{
158
		$notification_data = array(
159
			'link_id'			=> (int) $link_id,
160
			'user_from'			=> (int) $data['link_user_id'],
161
			'link_name'			=> $data['link_name'],
162
			'link_description'	=> $data['link_description'],
163
			'cat_id'			=> (int) $data['link_cat'],
164
			'cat_name'			=> \ernadoo\phpbbdirectory\core\categorie::getname((int) $data['link_cat']),
165
		);
166
167
		$old_cat = array_pop($data);
168
169
		if ($old_cat != $data['link_cat'] || $need_approval)
170
		{
171
			$this->notification->delete_notifications('ernadoo.phpbbdirectory.notification.type.directory_website', (int) $link_id);
172
173
			$this->db->sql_transaction('begin');
174
175
			$sql = 'UPDATE ' . DIR_CAT_TABLE . '
176
				SET cat_links = cat_links - 1
177
				WHERE cat_id = ' . (int) $old_cat;
178
			$this->db->sql_query($sql);
179
180
			if (!$need_approval)
181
			{
182
				$sql = 'UPDATE ' . DIR_CAT_TABLE . '
183
					SET cat_links = cat_links + 1
184
					WHERE cat_id = ' . (int) $data['link_cat'];
185
				$this->db->sql_query($sql);
186
187
				$notification_type = 'ernadoo.phpbbdirectory.notification.type.directory_website';
188
			}
189
			else
190
			{
191
				$data['link_active'] = false;
192
				$notification_type = 'ernadoo.phpbbdirectory.notification.type.directory_website_in_queue';
193
			}
194
195
			$this->db->sql_transaction('commit');
196
197
			$this->notification->add_notifications($notification_type, $notification_data);
198
		}
199
200
		$sql = 'UPDATE ' . DIR_LINK_TABLE . '
201
			SET ' . $this->db->sql_build_array('UPDATE', $data) . '
202
			WHERE link_id = ' . (int) $link_id;
203
		$this->db->sql_query($sql);
204
	}
205
206
	/**
207
	* Delete a link of the db
208
	*
209
	* @param	int 	$cat_id		The category ID
210
	* @param	mixed 	$link_id	Link's id, for WHERE clause
211
	* @return	null
212
	*/
213
	public function del($cat_id, $link_id)
214
	{
215
		$this->db->sql_transaction('begin');
216
217
		$url_array = is_array($link_id) ? $link_id : array($link_id);
218
219
		// Delete links datas
220
		$link_datas_ary = array(
221
			DIR_LINK_TABLE		=> 'link_id',
222
			DIR_COMMENT_TABLE	=> 'comment_link_id',
223
			DIR_VOTE_TABLE		=> 'vote_link_id',
224
		);
225
226
		$sql = 'SELECT link_banner
227
			FROM ' . DIR_LINK_TABLE . '
228
			WHERE '. $this->db->sql_in_set('link_id', $url_array);
229
		$result = $this->db->sql_query($sql);
230
231
		while ($row = $this->db->sql_fetchrow($result))
232
		{
233 View Code Duplication
			if ($row['link_banner'] && !preg_match('/^(http:\/\/|https:\/\/|ftp:\/\/|ftps:\/\/|www\.).+/si', $row['link_banner']))
234
			{
235
				$banner_img = $this->dir_helper->get_banner_path(basename($row['link_banner']));
236
237
				if (file_exists($banner_img))
238
				{
239
					@unlink($banner_img);
240
				}
241
			}
242
		}
243
244
		foreach ($link_datas_ary as $table => $field)
245
		{
246
			$this->db->sql_query("DELETE FROM $table WHERE ".$this->db->sql_in_set($field, $url_array));
247
		}
248
249
		$sql = 'UPDATE ' . DIR_CAT_TABLE . '
250
			SET cat_links = cat_links - '.sizeof($url_array).'
251
			WHERE cat_id = ' . (int) $cat_id;
252
		$this->db->sql_query($sql);
253
254
		$this->db->sql_transaction('commit');
255
256
		foreach ($url_array as $link_id)
257
		{
258
			$this->notification->delete_notifications(array(
259
				'ernadoo.phpbbdirectory.notification.type.directory_website',
260
				'ernadoo.phpbbdirectory.notification.type.directory_website_in_queue'
261
			), $link_id);
262
		}
263
264 View Code Duplication
		if ($this->request->is_ajax())
265
		{
266
			$sql = 'SELECT cat_links
267
				FROM ' . DIR_CAT_TABLE . '
268
				WHERE cat_id = ' . (int) $cat_id;
269
			$result = $this->db->sql_query($sql);
270
			$data = $this->db->sql_fetchrow($result);
271
272
			$json_response = new \phpbb\json_response;
273
			$json_response->send(array(
274
				'success' => true,
275
276
				'MESSAGE_TITLE'	=> $this->language->lang('INFORMATION'),
277
				'MESSAGE_TEXT'	=> $this->language->lang('DIR_DELETE_OK'),
278
				'LINK_ID'		=> $link_id,
279
				'TOTAL_LINKS'	=> $this->language->lang('DIR_NB_LINKS', (int) $data['cat_links']),
280
			));
281
		}
282
	}
283
284
	/**
285
	* Increments link view counter
286
	*
287
	* @param	int		$link_id	Link's id, for WHERE clause
288
	* @return	null
289
	* @throws	\phpbb\exception\http_exception
290
	*/
291
	public function view($link_id)
292
	{
293
		$sql = 'SELECT link_id, link_url
294
			FROM ' . DIR_LINK_TABLE . '
295
			WHERE link_id = ' . (int) $link_id;
296
		$result = $this->db->sql_query($sql);
297
		$data = $this->db->sql_fetchrow($result);
298
299
		if (empty($data['link_id']))
300
		{
301
			throw new \phpbb\exception\http_exception(404, 'DIR_ERROR_NO_LINKS');
302
		}
303
304
		$sql = 'UPDATE ' . DIR_LINK_TABLE . '
305
			SET link_view = link_view + 1
306
			WHERE link_id = ' . (int) $link_id;
307
		$this->db->sql_query($sql);
308
309
		redirect($data['link_url'], false, true);
310
		return;
311
	}
312
313
	/**
314
	* Verify that an URL exist before add into db
315
	*
316
	* @param	string	$url	The URL to check
317
	* @return	bool			True if url is reachable, else false.
318
	*/
319
	public function checkurl($url)
320
	{
321
		$details = parse_url($url);
322
323
		$default_port = 80;
324
		$hostname = $details['host'];
325
326
		if ($details['scheme'] == 'https')
327
		{
328
			$default_port = 443;
329
			$hostname = 'tls://' . $details['host'];
330
		}
331
332
		if (!isset($details['path']))
333
		{
334
			$details['path'] = '/';
335
		}
336
337
		$port = (isset($details['port']) && !empty($details['port'])) ? (int) $details['port'] : $default_port;
338
339
		if ($sock = @fsockopen($hostname, $port, $errno, $errstr, 1))
340
		{
341
			$requete = 'GET '.$details['path']." HTTP/1.1\r\n";
342
			$requete .= 'Host: '.$details['host']."\r\n\r\n";
343
344
			// Send a HTTP GET header
345
			fputs($sock, $requete);
346
			// answer from server
347
			$str = fgets($sock, 1024);
348
			preg_match("'HTTP/1\.. (.*) (.*)'U", $str, $parts);
349
			fclose($sock);
350
351
			if ($parts[1] == '404')
352
			{
353
				return false;
354
			}
355
356
			return true;
357
		}
358
		return false;
359
	}
360
361
	/**
362
	* Delete the final '/', if no path
363
	*
364
	* @param	string	$url	URL to clean
365
	* @return	string	$url	The correct string.
366
	*/
367
	public function clean_url($url)
368
	{
369
		$details = parse_url($url);
370
371
		if (isset($details['path']) && $details['path'] == '/' && !isset($details['query']))
372
		{
373
			return substr($url, 0, -1);
374
		}
375
		return $url;
376
	}
377
378
	/**
379
	* Display a flag
380
	*
381
	* @param	array	$data	Link's data from db
382
	* @return	string			Flag path.
383
	*/
384
	public function display_flag($data)
385
	{
386
		global $phpbb_extension_manager;
387
388
		$ext_path = $phpbb_extension_manager->get_extension_path('ernadoo/phpbbdirectory', false);
389
		$flag_path = $ext_path.'images/flags/';
390
		$img_flag = 'no_flag.png';
391
392
		if ($this->config['dir_activ_flag'] && !empty($data['link_flag']) && file_exists($flag_path . $data['link_flag']))
393
		{
394
			$img_flag = $data['link_flag'];
395
		}
396
397
		return $this->dir_helper->get_img_path('flags', $img_flag);
398
	}
399
400
	/**
401
	* Calculate the link's note
402
	*
403
	* @param	int		$total_note		Sum of all link's notes
404
	* @param	int		$nb_vote		Number of votes
405
	* @param	bool	$votes_status	Votes are enable in this category?
406
	* @return	string	$note			The calculated note.
407
	*/
408
	public function display_note($total_note, $nb_vote, $votes_status)
409
	{
410
		if (!$votes_status)
411
		{
412
			return;
413
		}
414
415
		$note = ($nb_vote < 1) ? '' : $total_note / $nb_vote;
416
		$note = (strlen($note) > 2) ? number_format($note, 1) : $note;
417
418
		return ($nb_vote) ? $this->language->lang('DIR_FROM_TEN', $note) : $this->language->lang('DIR_NO_NOTE');
419
	}
420
421
	/**
422
	* Display the vote form for auth users
423
	*
424
	* @param	array	$data	Link's data from db
425
	* @return	null|string		Html combo list or nothing if votes are not available.
426
	*/
427
	public function display_vote($data)
428
	{
429
		if ($this->user->data['is_registered'] && $this->auth->acl_get('u_vote_dir') && empty($data['vote_user_id']))
430
		{
431
			$list = '<select name="vote">';
432
			for ($i = 0; $i <= 10; $i++)
433
			{
434
				$list .= '<option value="' . $i . '"' . (($i == 5) ? ' selected="selected"' : '') . '>' . $i . '</option>';
435
			}
436
			$list .= '</select>';
437
438
			return $list;
439
		}
440
	}
441
442
	/**
443
	* Display the RSS icon
444
	*
445
	* @param	array	$data	Link's data from db
446
	* @return	null|string		RSS feed URL or nothing.
447
	*/
448
	public function display_rss($data)
449
	{
450
		if ($this->config['dir_activ_rss'] && !empty($data['link_rss']))
451
		{
452
				return $data['link_rss'];
453
		}
454
	}
455
456
	/**
457
	* Display link's thumb if thumb service enabled.
458
	* if thumb don't exists in db or if a new service was choosen in acp
459
	* thumb is research
460
	*
461
	* @param	array		$data	Link's data from db
462
	* @return	string|null			Thumb or null.
463
	*/
464
	public function display_thumb($data)
465
	{
466
		if ($this->config['dir_activ_thumb'])
467
		{
468
			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'])))))
469
			{
470
				$thumb = $this->thumb_process($data['link_url']);
471
472
				$sql = 'UPDATE ' . DIR_LINK_TABLE . '
473
					SET link_thumb = "' . $this->db->sql_escape($thumb) . '"
474
					WHERE link_id = ' . (int) $data['link_id'];
475
				$this->db->sql_query($sql);
476
477
				return $thumb;
478
			}
479
			return $data['link_thumb'];
480
		}
481
	}
482
483
	/**
484
	* Display and calculate PageRank if needed
485
	*
486
	* @param	array	$data	Link's data from db
487
	* @return	string			Pagerank, 'n/a' or false
488
	*/
489
	public function display_pagerank($data)
490
	{
491
		if ($this->config['dir_activ_pagerank'])
492
		{
493
			if ($data['link_pagerank'] == '')
494
			{
495
				$pagerank = $this->pagerank_process($data['link_url']);
496
497
				$sql = 'UPDATE ' . DIR_LINK_TABLE . '
498
					SET link_pagerank = ' . (int) $pagerank . '
499
					WHERE link_id = ' . (int) $data['link_id'];
500
				$this->db->sql_query($sql);
501
			}
502
			else
503
			{
504
				$pagerank = (int) $data['link_pagerank'];
505
			}
506
507
			$prpos=40*$pagerank/10;
508
			$prneg=40-$prpos;
509
			$html='<img src="http://www.google.com/images/pos.gif" width="'.$prpos.'" height="4" alt="'.$pagerank.'" /><img src="http://www.google.com/images/neg.gif" width="'.$prneg.'" height="4" alt="'.$pagerank.'" /> ';
510
511
			$pagerank = $pagerank == '-1' ? $this->language->lang('DIR_PAGERANK_NOT_AVAILABLE') : $this->language->lang('DIR_FROM_TEN', $pagerank);
512
			return $html.$pagerank;
513
		}
514
		return false;
515
	}
516
517
	/**
518
	* Display and resize a banner
519
	*
520
	* @param	array	$data		link's data from db
521
	* @return	string	$s_banner	html code.
522
	*/
523
	public function display_bann($data)
524
	{
525
		if (!empty($data['link_banner']))
526
		{
527
			if (!preg_match('/^(http:\/\/|https:\/\/|ftp:\/\/|ftps:\/\/|www\.).+/si', $data['link_banner']))
528
			{
529
				$img_src = $this->helper->route('ernadoo_phpbbdirectory_banner_controller', array('banner_img' => $data['link_banner']));
530
				$physical_path = $this->dir_helper->get_banner_path($data['link_banner']);
531
			}
532
			else
533
			{
534
				$img_src = $physical_path = $data['link_banner'];
535
			}
536
537
			if (($image_data = $this->imagesize->getImageSize($physical_path)) === false)
538
			{
539
				return '';
540
			}
541
542
			$width = $image_data['width'];
543
			$height = $image_data['height'];
544
545
			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)
546
			{
547
				$coef_w = $width / $this->config['dir_banner_width'];
548
				$coef_h = $height / $this->config['dir_banner_height'];
549
				$coef_max = max($coef_w, $coef_h);
550
				$width /= $coef_max;
551
				$height /= $coef_max;
552
			}
553
554
			return '<img src="' . $img_src . '" width="' . $width . '" height="' . $height . '" alt="'.$data['link_name'].'" title="'.$data['link_name'].'" />';
555
		}
556
		return '';
557
	}
558
559
	/**
560
	* Add a vote in db, for a specifi link
561
	*
562
	* @param	int		$link_id	Link_id from db
563
	* @return	null
564
	*/
565
	public function add_vote($link_id)
566
	{
567
		$data = array(
568
			'vote_link_id' 		=> (int) $link_id,
569
			'vote_user_id' 		=> $this->user->data['user_id'],
570
			'vote_note'			=> $this->request->variable('vote', 0),
571
		);
572
573
		$this->db->sql_transaction('begin');
574
575
		$sql = 'INSERT INTO ' . DIR_VOTE_TABLE . ' ' . $this->db->sql_build_array('INSERT', $data);
576
		$this->db->sql_query($sql);
577
578
		$sql = 'UPDATE ' . DIR_LINK_TABLE . '
579
			SET link_vote = link_vote + 1,
580
			link_note = link_note + ' . (int) $data['vote_note'] . '
581
		WHERE link_id = ' . (int) $link_id;
582
		$this->db->sql_query($sql);
583
584
		$this->db->sql_transaction('commit');
585
586
		if ($this->request->is_ajax())
587
		{
588
			$sql= 'SELECT link_vote, link_note FROM ' . DIR_LINK_TABLE . ' WHERE link_id = ' . (int) $link_id;
589
			$result = $this->db->sql_query($sql);
590
			$data = $this->db->sql_fetchrow($result);
591
592
			$note = $this->display_note($data['link_note'], $data['link_vote'], true);
593
594
			$json_response = new \phpbb\json_response;
595
			$json_response->send(array(
596
				'success' => true,
597
598
				'MESSAGE_TITLE'	=> $this->language->lang('INFORMATION'),
599
				'MESSAGE_TEXT'	=> $this->language->lang('DIR_VOTE_OK'),
600
				'NOTE'			=> $note,
601
				'NB_VOTE'		=> $this->language->lang('DIR_NB_VOTES', (int) $data['link_vote']),
602
				'LINK_ID'		=> $link_id
603
			));
604
		}
605
	}
606
607
	/**
608
	* Search an appropriate thumb for url
609
	*
610
	* @param	string	$url	Link's url
611
	* @return	string			The thumb url
612
	*/
613
	public function thumb_process($url)
614
	{
615
		if (!$this->config['dir_activ_thumb'])
616
		{
617
			return $this->root_path.'images/directory/nothumb.gif';
618
		}
619
620
		$details = parse_url($url);
621
622
		$root_url		= $details['scheme'].'://'.$details['host'];
623
		$absolute_url	= isset($details['path']) ? $root_url.$details['path'] : $root_url;
624
625
		if ($this->config['dir_activ_thumb_remote'] && $this->_ascreen_exist($details['scheme'], $details['host']))
626
		{
627
			return $root_url.'/ascreen.jpg';
628
		}
629
		return $this->config['dir_thumb_service'].$absolute_url;
630
	}
631
632
	/**
633
	* Check if ascreen thumb exists
634
	*
635
	* @param	string	$protocol	The protocol
636
	* @param	string	$host		The hostname
637
	* @return	bool				True if ascreen file exixts, else false
638
	*/
639
	private function _ascreen_exist($protocol, $host)
640
	{
641
		if (($thumb_info = $this->imagesize->getImageSize($protocol.'://'.$host.'/ascreen.jpg')) !== false)
642
		{
643
			// Obviously this is an image, we did some additional tests
644
			if ($thumb_info['width'] == '120' && $thumb_info['height'] == '90' && $thumb_info['type'] == 2)
645
			{
646
				return true;
647
			}
648
		}
649
		return false;
650
	}
651
652
	/**
653
	* Primary work on banner, can edit, copy or check a banner
654
	*
655
	* @param	string	$banner	The banner's remote url
656
	* @param	array	$error	The array error, passed by reference
657
	* @return	null
658
	*/
659
	public function banner_process(&$banner, &$error)
660
	{
661
		$old_banner = $this->request->variable('old_banner', '');
662
663
		$destination = $this->dir_helper->get_banner_path();
664
665
		// Can we upload?
666
		$can_upload = ($this->config['dir_storage_banner'] && $this->filesystem->exists($this->root_path . $destination) && $this->filesystem->is_writable($this->root_path . $destination) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false;
667
668
		if ($banner && $can_upload)
669
		{
670
			$file = $this->_banner_upload($banner, $error);
671
		}
672
		else if ($banner)
673
		{
674
			$file = $this->_banner_remote($banner, $error);
675
		}
676
		else if ($this->request->is_set_post('delete_banner') && $old_banner)
677
		{
678
			$this->_banner_delete($old_banner);
679
			return;
680
		}
681
682
		if (!sizeof($error))
683
		{
684
			if ($banner && $old_banner && !preg_match('/^(http:\/\/|https:\/\/|ftp:\/\/|ftps:\/\/|www\.).+/si', $old_banner))
685
			{
686
				$this->_banner_delete($old_banner);
687
			}
688
689
			$banner = !empty($file) ? $file : '';
690
		}
691
	}
692
693
	/**
694
	* Copy a remonte banner to server.
695
	* called by banner_process()
696
	*
697
	* @param	string	$banner The banner's remote url
698
	* @param	array	$error	The array error, passed by reference
699
	* @return	false|string	String if no errors, else false
700
	*/
701
	private function _banner_upload($banner, &$error)
702
	{
703
		/** @var \phpbb\files\upload $upload */
704
		$upload = $this->files_factory->get('upload')
705
			->set_error_prefix('DIR_BANNER_')
706
			->set_allowed_extensions(array('jpg', 'jpeg', 'gif', 'png'))
707
			->set_max_filesize($this->config['dir_banner_filesize'])
708
			->set_disallowed_content((isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false));
709
710
		$file = $upload->handle_upload('files.types.remote', $banner);
711
712
		$prefix = unique_id() . '_';
713
		$file->clean_filename('real', $prefix);
714
715
		if (sizeof($file->error))
716
		{
717
			$file->remove();
718
			$error = array_merge($error, $file->error);
719
			return false;
720
		}
721
722
		$destination = $this->dir_helper->get_banner_path();
723
724
		// Move file and overwrite any existing image
725
		$file->move_file($destination, true);
726
727
		return strtolower($file->get('realname'));
728
	}
729
730
	/**
731
	* Check than remote banner exists
732
	* called by banner_process()
733
	*
734
	* @param	string	$banner	The banner's remote url
735
	* @param	array	$error	The array error, passed by reference
736
	* @return	false|string	String if no errors, else false
737
	*/
738
	private function _banner_remote($banner, &$error)
739
	{
740
		if (!preg_match('#^(http|https|ftp)://#i', $banner))
741
		{
742
			$banner = 'http://' . $banner;
743
		}
744
		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))
745
		{
746
			$error[] = $this->language->lang('DIR_BANNER_URL_INVALID');
747
			return false;
748
		}
749
750
		// Get image dimensions
751
		if (($image_data = $this->imagesize->getImageSize($banner)) === false)
752
		{
753
			$error[] = $this->language->lang('DIR_BANNER_UNABLE_GET_IMAGE_SIZE');
754
			return false;
755
		}
756
757
		if (!empty($image_data) && ($image_data['width'] < 2 || $image_data['height'] < 2))
758
		{
759
			$error[] = $this->language->lang('DIR_BANNER_UNABLE_GET_IMAGE_SIZE');
760
			return false;
761
		}
762
763
		$width = $image_data['width'];
764
		$height = $image_data['height'];
765
766
		if ($width <= 0 || $height <= 0)
767
		{
768
			$error[] = $this->language->lang('DIR_BANNER_UNABLE_GET_IMAGE_SIZE');
769
			return false;
770
		}
771
772
		// Check image type
773
		$types		= \phpbb\files\upload::image_types();
774
		$extension	= strtolower(\phpbb\files\filespec::get_extension($banner));
775
776
		// Check if this is actually an image
777
		if ($file_stream = @fopen($banner, 'r'))
778
		{
779
			// Timeout after 1 second
780
			stream_set_timeout($file_stream, 1);
781
			// read some data to ensure headers are present
782
			fread($file_stream, 1024);
783
			$meta = stream_get_meta_data($file_stream);
784
			if (isset($meta['wrapper_data']['headers']) && is_array($meta['wrapper_data']['headers']))
785
			{
786
				$headers = $meta['wrapper_data']['headers'];
787
			}
788
			else if (isset($meta['wrapper_data']) && is_array($meta['wrapper_data']))
789
			{
790
				$headers = $meta['wrapper_data'];
791
			}
792
			else
793
			{
794
				$headers = array();
795
			}
796
797
			foreach ($headers as $header)
798
			{
799
				$header = preg_split('/ /', $header, 2);
800
				if (strtr(strtolower(trim($header[0], ':')), '_', '-') === 'content-type')
801
				{
802
					if (strpos($header[1], 'image/') !== 0)
803
					{
804
						$error[] = 'DIR_BANNER_URL_INVALID';
805
						fclose($file_stream);
806
						return false;
807
					}
808
					else
809
					{
810
						fclose($file_stream);
811
						break;
812
					}
813
				}
814
			}
815
		}
816
		else
817
		{
818
			$error[] = 'DIR_BANNER_URL_INVALID';
819
			return false;
820
		}
821
822
		if (!empty($image_data) && (!isset($types[$image_data['type']]) || !in_array($extension, $types[$image_data['type']])))
823
		{
824
			if (!isset($types[$image_data['type']]))
825
			{
826
				$error[] = $this->language->lang('UNABLE_GET_IMAGE_SIZE');
827
			}
828
			else
829
			{
830
				$error[] = $this->language->lang('DIR_BANNER_IMAGE_FILETYPE_MISMATCH', $types[$image_data['type']][0], $extension);
831
			}
832
			return false;
833
		}
834
835
		if (($this->config['dir_banner_width'] || $this->config['dir_banner_height']) && ($width > $this->config['dir_banner_width'] || $height > $this->config['dir_banner_height']))
836
		{
837
			$error[] = $this->language->lang('DIR_BANNER_WRONG_SIZE', $this->config['dir_banner_width'], $this->config['dir_banner_height'], $width, $height);
838
			return false;
839
		}
840
841
		return $banner;
842
	}
843
844
	/**
845
	* Delete a banner from server
846
	*
847
	* @param	string	$file	The file's name
848
	* @return	bool			True if delete success, else false
849
	*/
850
	private function _banner_delete($file)
851
	{
852
		if (file_exists($this->dir_helper->get_banner_path($file)))
853
		{
854
			@unlink($this->dir_helper->get_banner_path($file));
855
			return true;
856
		}
857
858
		return false;
859
	}
860
861
	/**
862
	* PageRank Lookup (Based on Google Toolbar for Mozilla Firefox)
863
	*
864
	* @copyright 2012 HM2K <[email protected]>
865
	* @link http://pagerank.phurix.net/
866
	* @author James Wade <[email protected]>
867
	* @version $Revision: 2.1 $
868
	* @require PHP 4.3.0 (file_get_contents)
869
	* @updated 06/10/11
870
	*
871
	* @param	string		$q	The website URL
872
	* @return	string			The calculated pagerank, or -1
873
	*/
874
	public function pagerank_process($q)
875
	{
876
		$googleDomains	= array('.com', '.com.tr', '.de', '.fr', '.be', '.ca', '.ro', '.ch');
877
		$seed			= $this->language->lang('SEED');
878
		$result			= 0x01020345;
879
		$len			= strlen($q);
880
881
		for ($i=0; $i<$len; $i++)
882
		{
883
			$result ^= ord($seed{$i%strlen($seed)}) ^ ord($q{$i});
884
			$result = (($result >> 23) & 0x1ff) | $result << 9;
885
		}
886
887
		if (PHP_INT_MAX != 2147483647)
888
		{
889
			$result = -(~($result & 0xFFFFFFFF) + 1);
890
		}
891
892
		$ch		= sprintf('8%x', $result);
893
		$url	= 'http://%s/tbr?client=navclient-auto&ch=%s&features=Rank&q=info:%s';
894
		$host	= 'toolbarqueries.google'.$googleDomains[mt_rand(0,count($googleDomains)-1)];
895
896
		$url	= sprintf($url,$host,$ch,$q);
897
		@$pr	= trim(file_get_contents($url,false));
898
899
		if (is_numeric(substr(strrchr($pr, ':'), 1)))
900
		{
901
			return substr(strrchr($pr, ':'), 1);
902
		}
903
		return '-1';
904
	}
905
906
	/**
907
	* List flags
908
	*
909
	* @param	string	$flag_path	The flag directory path
910
	* @param	string	$value		Selected flag
911
	* @return	string	$list		Html code
912
	*/
913
	public function get_dir_flag_list($flag_path, $value)
914
	{
915
		$list = '';
916
917
		$this->language->add_lang('directory_flags', 'ernadoo/phpbbdirectory');
918
919
		$flags = $this->dir_helper->preg_grep_keys('/^DIR_FLAG_CODE_/i', $this->language->get_lang_array());
920
921
		if (extension_loaded('intl'))
922
		{
923
			$locale = $this->language->lang('USER_LANG');
924
925
			$col = new \Collator($locale);
926
			$col->asort($flags);
927
		}
928
		else
929
		{
930
			asort($flags);
931
		}
932
933
		foreach ($flags as $file => $name)
934
		{
935
			$img_file = strtolower(substr(strrchr($file, '_'), 1)).'.png';
936
937
			if (file_exists($flag_path.$img_file))
938
			{
939
				$list .= '<option value="' . $img_file . '" ' . (($img_file == $value) ? 'selected="selected"' : '') . '>' . $name . '</option>';
940
			}
941
		}
942
943
		return $list;
944
	}
945
946
	/**
947
	* Display recents links added
948
	*
949
	* @return	null
950
	*/
951
	public function recents()
952
	{
953
		if ($this->config['dir_recent_block'])
954
		{
955
			$limit_sql		= $this->config['dir_recent_rows'] * $this->config['dir_recent_columns'];
956
			$exclude_array	= explode(',', str_replace(' ', '', $this->config['dir_recent_exclude']));
957
958
			$sql_array = array(
959
				'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',
960
				'FROM'		=> array(
961
						DIR_LINK_TABLE	=> 'l'),
962
				'LEFT_JOIN'	=> array(
963
						array(
964
							'FROM'	=> array(USERS_TABLE	=> 'u'),
965
							'ON'	=> 'l.link_user_id = u.user_id'
966
						),
967
						array(
968
							'FROM'	=> array(DIR_CAT_TABLE => 'c'),
969
							'ON'	=> 'l.link_cat = c.cat_id'
970
						)
971
				),
972
				'WHERE'		=> $this->db->sql_in_set('l.link_cat', $exclude_array, true).' AND l.link_active = 1',
973
				'ORDER_BY'	=> 'l.link_time DESC, l.link_id DESC');
974
975
			$sql = $this->db->sql_build_query('SELECT', $sql_array);
976
			$result = $this->db->sql_query_limit($sql, $limit_sql, 0);
977
			$num = 0;
978
			$rowset = array();
979
980
			while ($site = $this->db->sql_fetchrow($result))
981
			{
982
				$rowset[$site['link_id']] = $site;
983
			}
984
			$this->db->sql_freeresult($result);
985
986
			if (sizeof($rowset))
987
			{
988
				$this->template->assign_block_vars('block', array(
989
					'S_COL_WIDTH'			=> (100 / $this->config['dir_recent_columns']) . '%',
990
				));
991
992
				foreach ($rowset as $row)
993
				{
994
					if (($num % $this->config['dir_recent_columns']) == 0)
995
					{
996
						$this->template->assign_block_vars('block.row', array());
997
					}
998
999
					$this->template->assign_block_vars('block.row.col', array(
1000
						'UC_THUMBNAIL'            => '<a href="'.$row['link_url'].'" onclick="window.open(\''.$this->helper->route('ernadoo_phpbbdirectory_view_controller', array('link_id' => (int) $row['link_id'])).'\'); return false;"><img src="'.$row['link_thumb'].'" title="'.$row['link_name'].'" alt="'.$row['link_name'].'" /></a>',
1001
						'NAME'                    => $row['link_name'],
1002
						'USER'                    => get_username_string('full', $row['link_user_id'], $row['username'], $row['user_colour']),
1003
						'TIME'                    => ($row['link_time']) ? $this->user->format_date($row['link_time']) : '',
1004
						'CAT'                     => $row['cat_name'],
1005
						'COUNT'					  => $row['link_view'],
1006
						'COMMENT'                 => $row['link_comment'],
1007
1008
						'U_CAT'                   => $this->helper->route('ernadoo_phpbbdirectory_page_controller', array('cat_id' => (int) $row['link_cat'])),
1009
						'U_COMMENT'               => $this->helper->route('ernadoo_phpbbdirectory_comment_view_controller', array('link_id' => (int) $row['link_id'])),
1010
1011
						'L_DIR_SEARCH_NB_CLICKS'	=> $this->language->lang('DIR_SEARCH_NB_CLICKS', (int) $row['link_view']),
1012
						'L_DIR_SEARCH_NB_COMMS'		=> $this->language->lang('DIR_SEARCH_NB_COMMS', (int) $row['link_comment']),
1013
					));
1014
					$num++;
1015
				}
1016
1017
				while (($num % $this->config['dir_recent_columns']) != 0)
1018
				{
1019
					$this->template->assign_block_vars('block.row.col2', array());
1020
					$num++;
1021
				}
1022
			}
1023
		}
1024
	}
1025
1026
	/**
1027
	* Validate back link
1028
	*
1029
	* @param	string		$remote_url	Page URL contains the backlink
1030
	* @param	bool		$optional	Link back is optional in this category?
1031
	* @param	bool		$cron		This methos is called by con process?
1032
	* @return	false|string			Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
1033
	*/
1034
	public function validate_link_back($remote_url, $optional, $cron = false)
1035
	{
1036
		if (!$cron)
1037
		{
1038
			if (empty($remote_url) && $optional)
1039
			{
1040
				return false;
1041
			}
1042
1043
			if (!preg_match('#^http[s]?://(.*?\.)*?[a-z0-9\-]+\.[a-z]{2,4}#i', $remote_url))
1044
			{
1045
				return 'DIR_ERROR_WRONG_DATA_BACK';
1046
			}
1047
		}
1048
1049
		if (false === ($handle = @fopen($remote_url, 'r')))
1050
		{
1051
			return 'DIR_ERROR_NOT_FOUND_BACK';
1052
		}
1053
1054
		$buff = '';
1055
1056
		// Read by packet, faster than file_get_contents()
1057
		while (!feof($handle))
1058
		{
1059
			$buff .= fgets($handle, 256);
1060
1061
			if (stristr($buff, $this->config['server_name']))
1062
			{
1063
				@fclose($handle);
1064
				return false;
1065
			}
1066
		}
1067
		@fclose($handle);
1068
1069
		return 'DIR_ERROR_NO_LINK_BACK';
1070
	}
1071
1072
	/**
1073
	* Check, for website with backlink specified, if backlink is always here.
1074
	* After $nb_check verification, website is deleted, otherwise, a notification is send to poster
1075
	*
1076
	* @param	int		$cat_id		The categoryID
1077
	* @param	int		$nb_check	Number of check before demete a website
1078
	* @param	int		$next_prune	Date of next auto check
1079
	* @return	null
1080
	*/
1081
	private function _check($cat_id, $nb_check, $next_prune)
1082
	{
1083
		$del_array = $update_array = array();
1084
1085
		$sql_array = array(
1086
			'SELECT'	=> 'link_id, link_cat, link_back, link_guest_email, link_nb_check, link_user_id, link_name, link_url, link_description, u.user_lang, u.user_dateformat',
1087
			'FROM'		=> array(
1088
					DIR_LINK_TABLE	=> 'l'),
1089
			'LEFT_JOIN'	=> array(
1090
					array(
1091
						'FROM'	=> array(USERS_TABLE	=> 'u'),
1092
						'ON'	=> 'l.link_user_id = u.user_id'
1093
					)
1094
			),
1095
			'WHERE'		=> 'l.link_back <> "" AND l.link_active = 1 AND l.link_cat = '  . (int) $cat_id);
1096
1097
		$sql = $this->db->sql_build_query('SELECT', $sql_array);
1098
		$result = $this->db->sql_query($sql);
1099
1100
		while ($row = $this->db->sql_fetchrow($result))
1101
		{
1102
			if ($this->validate_link_back($row['link_back'], false, true) !== false)
1103
			{
1104
				if (!$nb_check || ($row['link_nb_check']+1) >= $nb_check)
1105
				{
1106
					$del_array[] = $row['link_id'];
1107
				}
1108
				else
1109
				{
1110
					// A first table containing links ID to update
1111
					$update_array[$row['link_id']] = $row;
1112
				}
1113
			}
1114
		}
1115
		$this->db->sql_freeresult($result);
1116
1117
		if (sizeof($del_array))
1118
		{
1119
			$this->del($cat_id, $del_array);
1120
		}
1121
		if (sizeof($update_array))
1122
		{
1123
			$this->_update_check($update_array, $next_prune);
1124
		}
1125
	}
1126
1127
	/**
1128
	* Method called by cron task.
1129
	*
1130
	* @param	array	$cat_data	Information about category, from db
1131
	* @return	null
1132
	*/
1133
	public function auto_check($cat_data)
1134
	{
1135
		global $phpbb_log;
1136
1137
		$sql = 'SELECT cat_name
1138
			FROM ' . DIR_CAT_TABLE . '
1139
			WHERE cat_id = ' . (int) $cat_data['cat_id'];
1140
		$result = $this->db->sql_query($sql);
1141
		$row = $this->db->sql_fetchrow($result);
1142
		$this->db->sql_freeresult($result);
1143
1144
		if ($row)
1145
		{
1146
			$next_prune = time() + ($cat_data['cat_cron_freq'] * 86400);
1147
1148
			$this->_check($cat_data['cat_id'], $cat_data['cat_cron_nb_check'], $next_prune);
1149
1150
			$sql = 'UPDATE ' . DIR_CAT_TABLE . "
1151
				SET cat_cron_next = $next_prune
1152
				WHERE cat_id = " . (int) $cat_data['cat_id'];
1153
			$this->db->sql_query($sql);
1154
1155
			$phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_AUTO_PRUNE', time(), array($row['cat_name']));
1156
		}
1157
1158
		return;
1159
	}
1160
1161
	/**
1162
	* Update website verification number after a missing backlink, and send notificaton
1163
	*
1164
	* @param	array	$u_array	Information about website
1165
	* @param	int		$next_prune	Date of next auto check
1166
	* @return	null
1167
	*/
1168
	private function _update_check($u_array, $next_prune)
1169
	{
1170
		if (!class_exists('messenger'))
1171
		{
1172
			include($this->root_path . 'includes/functions_messenger.' . $this->php_ext);
1173
		}
1174
1175
		$messenger = new \messenger(false);
1176
1177
		// cron.php don't call $user->setup(), so $this->timezone is unset.
1178
		// We need to define it, because we use user->format_date below
1179
		$this->user->timezone = new \DateTimeZone($this->config['board_timezone']);
1180
1181
		$sql = 'UPDATE ' . DIR_LINK_TABLE . '
1182
			SET link_nb_check = link_nb_check + 1
1183
			WHERE ' . $this->db->sql_in_set('link_id', array_keys($u_array));
1184
		$this->db->sql_query($sql);
1185
1186
		foreach ($u_array as $data)
1187
		{
1188
			strip_bbcode($data['link_description']);
1189
1190
			$notification_data = array(
1191
					'cat_name'			=> \ernadoo\phpbbdirectory\core\categorie::getname((int) $data['link_cat']),
1192
					'link_id'			=> $data['link_id'],
1193
					'link_user_id'		=> $data['link_user_id'],
1194
					'link_name'			=> $data['link_name'],
1195
					'link_url'			=> $data['link_url'],
1196
					'link_description'	=> $data['link_description'],
1197
					'next_cron' 		=> $this->user->format_date($next_prune, $data['user_dateformat']),
1198
			);
1199
1200
			if ($data['link_nb_check'])
1201
			{
1202
				$this->notification->delete_notifications('ernadoo.phpbbdirectory.notification.type.directory_website_error_cron', $notification_data);
1203
			}
1204
1205
			// New notification system can't send mail to an anonymous user with an email address stored in another table than phpbb_users
1206
			if ($data['link_user_id'] == ANONYMOUS)
1207
			{
1208
				$username = $email = $data['link_guest_email'];
1209
1210
				$messenger->template('@ernadoo_phpbbdirectory/directory_website_error_cron', $data['user_lang']);
1211
				$messenger->to($email, $username);
1212
1213
				$messenger->assign_vars(array(
1214
					'USERNAME'			=> htmlspecialchars_decode($username),
1215
					'LINK_NAME'			=> $data['link_name'],
1216
					'LINK_URL'			=> $data['link_url'],
1217
					'LINK_DESCRIPTION'	=> $data['link_description'],
1218
					'NEXT_CRON' 		=> $this->user->format_date($next_prune, $data['user_dateformat']),
1219
				));
1220
1221
				$messenger->send(NOTIFY_EMAIL);
1222
			}
1223
			else
1224
			{
1225
				$this->notification->add_notifications('ernadoo.phpbbdirectory.notification.type.directory_website_error_cron', $notification_data);
1226
			}
1227
		}
1228
	}
1229
}
1230