Completed
Pull Request — master (#695)
by
unknown
15:38
created

fetch_posts::get_global_id()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 8
nc 5
nop 0
dl 0
loc 18
ccs 13
cts 13
cp 1
crap 6
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
*
4
* @package Board3 Portal v2.1
5
* @copyright (c) 2014 Board3 Group ( www.board3.de )
6
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
7
*
8
*/
9
10
namespace board3\portal\portal;
11
12
class fetch_posts
13
{
14
	/**
15
	* phpBB auth
16
	* @var \phpbb\auth\auth
17
	*/
18
	protected $auth;
19
20
	/**
21
	* phpBB cache
22
	* @var \phpbb\cache\driver\driver_interface
23
	*/
24
	protected $cache;
25
26
	/**
27
	* phpBB config
28
	* @var \phpbb\config\config
29
	*/
30
	protected $config;
31
32
	/**
33
	* phpBB db driver
34
	* @var \phpbb\db\driver\driver_interface
35
	*/
36
	protected $db;
37
38
	/**
39
	* Modules helper
40
	* @var \board3\portal\includes\modules_helper
41
	*/
42
	protected $modules_helper;
43
44
	/**
45
	* phpBB user
46
	* @var \phpbb\user
47
	*/
48
	protected $user;
49
50
	/**
51
	* SQL Query where constraint
52
	* @var string
53
	*/
54
	protected $where_string = '';
55
56
	/**
57
	* SQL topic type constraint
58
	* @var string
59
	*/
60
	protected $topic_type = '';
61
62
	/**
63
	* SQL user link constraint
64
	* @var string
65
	*/
66
	protected $user_link = '';
67
68
	/**
69
	* SQL post link constraint
70
	* @var string
71
	*/
72
	protected $post_link = '';
73
74
	/**
75
	* SQL topic order constraint
76
	* @var string
77
	*/
78
	protected $topic_order = '';
79
80
	/**
81
	* Module ID
82
	* @var int
83
	*/
84
	protected $module_id;
85
86
	/**
87
	* Forum ID to use for global topics
88
	* @var int
89
	*/
90
	protected $global_id;
91
92
	/**
93
	* Type of posts to fetch
94
	* @var string
95
	*/
96
	protected $type;
97
98
	/**
99
	* Constructor
100
	* NOTE: The parameters of this method must match in order and type with
101
	* the dependencies defined in the services.yml file for this service.
102
	* @param \phpbb\auth\auth			$auth	phpBB auth object
103
	* @param \phpbb\cache\driver			$cache	phpBB cache driver
104
	* @param \phpbb\config\config			$config	phpBB config
105
	* @param \phpbb\db\driver_interface		$db	phpBB database driver
106
	* @param \board3\portal\includes\modules_helper	$modules_helper Board3 modules helper
107
	* @param \phpbb\user				$user	phpBB user object
108
	*/
109 30 View Code Duplication
	public function __construct($auth, $cache, $config, $db, $modules_helper, $user)
110
	{
111 30
		$this->auth = $auth;
112 30
		$this->cache = $cache;
113 30
		$this->config = $config;
114 30
		$this->db = $db;
115 30
		$this->modules_helper = $modules_helper;
116 30
		$this->user = $user;
117 30
	}
118
119
	/**
120
	* Get posts defined by type and other settings
121
	*
122
	* @param string $forum_from Forums from which the posts should be retrieved
123
	* @param bool $permissions Whether permissions should be taken into account
124
	* 					during retrieval
125
	* @param int $number_of_posts Number of posts to get
126
	* @param int $text_length Length the text should be shortened to
127
	* @param int $time The amount of days ago the posts could have been posted
128
	* @param string $type Type of posts to get
129
	* @param int $start At which position the query should start
130
	* @param bool $invert Whether the permissions should be inverted
131
	*
132
	* @return array An array containing the posts that were retrieved from the database
133
	*/
134 30
	public function get_posts($forum_from, $permissions, $number_of_posts, $text_length, $time, $type, $start = 0, $invert = false)
135
	{
136 30
		$posts = array();
137 30
		$post_time = $this->get_setting_based_data($time == 0, '', 'AND t.topic_time > ' . (time() - (int) $time * 86400));
138 30
		$forum_from = $this->get_setting_based_data(strpos($forum_from, ',') !== false, explode(',', $forum_from), $this->get_setting_based_data($forum_from != '', array($forum_from), array()));
139 30
		$topic_icons = array(0);
140 30
		$have_icons = 0;
141 30
		$this->global_id = 0;
142 30
		$this->type = $type;
143 30
		$this->reset_constraints();
144
145
		// Get disallowed forums
146 30
		$disallow_access = $this->modules_helper->get_disallowed_forums($permissions);
147
148
		// Set forums that should be excluded or included
149 30
		if (!$this->set_forum_constraints($forum_from, $disallow_access, $invert))
150 30
		{
151 2
			return array();
152
		}
153
154
		// Get SQL constraints
155 28
		$this->get_type_constraints();
156
157
		// Get global forum ID for announcements
158 26
		if (!$this->get_global_id())
159 26
		{
160 4
			return array();
161
		}
162
163 22
		$result = $this->run_sql_query($post_time, $number_of_posts, $start);
164
165 22
		$i = 0;
166
167
		// Fill posts array
168 22
		while ($row = $this->db->sql_fetchrow($result))
169
		{
170 12
			$this->fill_posts_array($row, $text_length, $i, $have_icons, $posts, $topic_icons);
171 12
			++$i;
172 12
		}
173 22
		$this->db->sql_freeresult($result);
174
175 22
		$posts['topic_icons'] = $this->get_setting_based_data(max($topic_icons) > 0 && $have_icons, true, false);
176 22
		$posts['topic_count'] = $i;
177
178 22
		if ($this->global_id < 1)
179 22
		{
180 2
			return array();
181
		}
182
		else
183
		{
184 20
			return $posts;
185
		}
186
	}
187
188
	/**
189
	* Run SQL query for fetching posts from database
190
	*
191
	* @param int	$post_time		Post time
192
	* @param int	$number_of_posts	Number of posts to fetch
193
	* @param int	$start			Start of query
194
	*
195
	* @return int Result pointer
196
	*/
197 22
	protected function run_sql_query($post_time, $number_of_posts, $start)
198
	{
199
		$sql_array = array(
200
			'SELECT' => 't.forum_id,
201
				t.topic_id,
202
				t.topic_last_post_id,
203
				t.topic_last_post_time,
204
				t.topic_time,
205
				t.topic_title,
206
				t.topic_attachment,
207
				t.topic_views,
208
				t.poll_start,
209
				t.topic_posts_approved,
210
				t.topic_posts_unapproved,
211
				t.topic_posts_softdeleted,
212
				t.topic_poster,
213
				t.topic_type,
214
				t.topic_status,
215
				t.topic_last_poster_name,
216
				t.topic_last_poster_id,
217
				t.topic_last_poster_colour,
218
				t.icon_id,
219
				u.username,
220
				u.user_id,
221
				u.user_type,
222
				u.user_colour,
223
				p.post_id,
224
				p.poster_id,
225
				p.post_time,
226
				p.post_text,
227
				p.post_attachment,
228
				p.post_username,
229
				p.enable_smilies,
230
				p.enable_bbcode,
231
				p.enable_magic_url,
232
				p.bbcode_bitfield,
233
				p.bbcode_uid,
234
				f.forum_name,
235 22
				f.enable_icons',
236
			'FROM' => array(
237 22
				TOPICS_TABLE => 't',
238 22
			),
239
			'LEFT_JOIN' => array(
240
				array(
241 22
					'FROM' => array(USERS_TABLE => 'u'),
242 22
					'ON' => $this->user_link,
243 22
				),
244
				array(
245 22
					'FROM' => array(FORUMS_TABLE => 'f'),
246 22
					'ON' => 't.forum_id=f.forum_id',
247 22
				),
248
				array(
249 22
					'FROM' => array(POSTS_TABLE => 'p'),
250 22
					'ON' => $this->post_link,
251 22
				),
252 22
			),
253 22
			'WHERE' => $this->topic_type . '
254 22
					' . $post_time . '
255 22
					AND t.topic_status <> ' . ITEM_MOVED . '
256
					AND t.topic_visibility = 1
257
					AND t.topic_moved_id = 0
258 22
					' . $this->where_string,
259 22
			'ORDER_BY' => $this->topic_order,
260 22
		);
261
262 22
		$sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_POSTED_TABLE => 'tp'), 'ON' => 'tp.topic_id = t.topic_id AND tp.user_id = ' . $this->user->data['user_id']);
263 22
		$sql_array['SELECT'] .= ', tp.topic_posted';
264 22
		$sql = $this->db->sql_build_query('SELECT', $sql_array);
265
266
		// Cache queries for 30 seconds
267 22
		if ($number_of_posts != 0)
268 22
		{
269 20
			$result = $this->db->sql_query_limit($sql, $number_of_posts, $start, 30);
270 20
		}
271
		else
272
		{
273 2
			$result = $this->db->sql_query($sql, 30);
274
		}
275
276 22
		return $result;
277
	}
278
279
	/**
280
	 * Fill posts array with data
281
	 *
282
	 * @param array $row Database row
283
	 * @param int $text_length Text length
284
	 * @param int $i Array pointer
285
	 * @param int $have_icons Whether any post has icons
286
	 * @param array $posts The posts array
287
	 * @param array $topic_icons List of topic icons
288
	 */
289 12
	public function fill_posts_array($row, $text_length, $i, &$have_icons, &$posts, &$topic_icons)
290
	{
291 12
		$update_count = array();
292
293
		// Get attachments
294 12
		$attachments = $this->get_post_attachments($row);
295
296 12
		$posts[$i]['bbcode_uid'] = $row['bbcode_uid'];
297
298
		// Format message
299 12
		$message = $this->format_message($row, $text_length, $posts[$i]['striped']);
300
301 12
		$row['bbcode_options'] = (int) $this->get_setting_based_data($row['enable_bbcode'], OPTION_FLAG_BBCODE, 0)
302 12
			+  (int) $this->get_setting_based_data($row['enable_smilies'], OPTION_FLAG_SMILIES, 0)
303 12
			+ (int) $this->get_setting_based_data($row['enable_magic_url'], OPTION_FLAG_LINKS, 0);
304 12
		$message = generate_text_for_display($message, $row['bbcode_uid'], $row['bbcode_bitfield'], $row['bbcode_options']);
305
306 12
		if (!empty($attachments))
307 12
		{
308 12
			parse_attachments($row['forum_id'], $message, $attachments, $update_count);
309 12
		}
310
311
		// Get proper global ID
312 12
		$this->global_id = $this->get_setting_based_data($this->global_id, $this->global_id, $row['forum_id']);
313
314 12
		$topic_icons[] = $row['enable_icons'];
315 12
		$have_icons = $this->get_setting_based_data($row['icon_id'], 1, $have_icons);
316
317 12
		$posts[$i] = array_merge($posts[$i], array(
318 12
			'post_text'				=> ap_validate($message),
319 12
			'topic_id'				=> $row['topic_id'],
320 12
			'topic_last_post_id'	=> $row['topic_last_post_id'],
321 12
			'topic_type'			=> $row['topic_type'],
322 12
			'topic_posted'			=> $this->get_setting_based_data(isset($row['topic_posted']) && $row['topic_posted'], true, false),
323 12
			'icon_id'				=> $row['icon_id'],
324 12
			'topic_status'			=> $row['topic_status'],
325 12
			'forum_id'				=> $row['forum_id'],
326 12
			'topic_replies'			=> $row['topic_posts_approved'] + $row['topic_posts_unapproved'] + $row['topic_posts_softdeleted'] - 1,
327 12
			'topic_replies_real'	=> $row['topic_posts_approved'] - 1,
328 12
			'topic_time'			=> $this->user->format_date($row['post_time']),
329 12
			'topic_last_post_time'	=> $row['topic_last_post_time'],
330 12
			'topic_title'			=> $row['topic_title'],
331 12
			'username'				=> $row['username'],
332 12
			'username_full'			=> get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $row['post_username']),
333 12
			'username_full_last'	=> get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour'], $row['topic_last_poster_name']),
334 12
			'user_id'				=> $row['user_id'],
335 12
			'user_type'				=> $row['user_type'],
336 12
			'user_colour'			=> $row['user_colour'],
337 12
			'poll'					=> $this->get_setting_based_data($row['poll_start'], true, false),
338 12
			'attachment'			=> $this->get_setting_based_data($row['topic_attachment'], true, false),
339 12
			'topic_views'			=> $row['topic_views'],
340 12
			'forum_name'			=> $row['forum_name'],
341 12
			'attachments'			=> $this->get_setting_based_data($attachments, $attachments, array()),
342 12
		));
343 12
		$posts['global_id'] = $this->global_id;
344 12
	}
345
346
	/**
347
	* Get type constraints for database query
348
	*
349
	* @return null
350
	* @throws \InvalidArgumentexception If unknown type is used
351
	*/
352 28
	protected function get_type_constraints()
353
	{
354 28
		switch ($this->type)
355
		{
356 28
			case "announcements":
357 12
				$this->get_announcements_constraints();
358 12
			break;
359 16
			case "news":
360 12
				$this->get_news_constraints();
361 12
			break;
362 4
			case "news_all":
363 2
				$this->get_news_all_constraints();
364 2
			break;
365
366 2
			default:
367
				// Method was called with unsupported type
368 2
				throw new \InvalidArgumentexception($this->user->lang('B3P_WRONG_METHOD_CALL', __FUNCTION__));
369 28
		}
370 26
	}
371
372
	/**
373
	* Get type constraints for announcements
374
	*
375
	* @return null
376
	*/
377 12
	protected function get_announcements_constraints()
378
	{
379 12
		$this->topic_type = '((t.topic_type = ' . POST_ANNOUNCE . ') OR (t.topic_type = ' . POST_GLOBAL . '))';
380 12
		$this->where_string = (strlen($this->where_string) > 0) ? 'AND (t.forum_id = 0 OR (' . trim(substr($this->where_string, 0, -4)) . '))' : '';
381 12
		$this->user_link = 't.topic_poster = u.user_id';
382 12
		$this->post_link = 't.topic_first_post_id = p.post_id';
383 12
		$this->topic_order = 't.topic_time DESC';
384 12
	}
385
386
	/**
387
	* Get type constraints for news
388
	*
389
	* @return null
390
	*/
391 14
	protected function get_news_constraints()
392
	{
393 14
		$this->topic_type = 't.topic_type = ' . POST_NORMAL;
394 14
		$this->where_string = (strlen($this->where_string) > 0) ? 'AND (' . trim(substr($this->where_string, 0, -4)) . ')' : '';
395 14
		$this->user_link = $this->get_setting_based_data($this->config['board3_news_style_' . $this->module_id], 't.topic_poster = u.user_id', $this->get_setting_based_data($this->config['board3_news_show_last_' . $this->module_id], 't.topic_last_poster_id = u.user_id', 't.topic_poster = u.user_id')) ;
396 14
		$this->post_link = $this->get_setting_based_data($this->config['board3_news_style_' . $this->module_id], 't.topic_first_post_id = p.post_id', $this->get_setting_based_data($this->config['board3_news_show_last_' . $this->module_id], 't.topic_last_post_id = p.post_id', 't.topic_first_post_id = p.post_id'));
397 14
		$this->topic_order = $this->get_setting_based_data($this->config['board3_news_show_last_' . $this->module_id], 't.topic_last_post_time DESC', 't.topic_time DESC');
398 14
	}
399
400
	/**
401
	* Get additional type constraints for all news
402
	* Overwrites topic type of get_news_constraints().
403
	*
404
	* @return null
405
	*/
406 2
	protected function get_news_all_constraints()
407
	{
408 2
		$this->get_news_constraints();
409 2
		$this->topic_type = '(t.topic_type <> ' . POST_ANNOUNCE . ') AND (t.topic_type <> ' . POST_GLOBAL . ')';
410 2
	}
411
412
	/**
413
	* Set module id
414
	*
415
	* @param	int	$module_id	Module ID
416
	* @return null
417
	*/
418 30
	public function set_module_id($module_id)
419
	{
420 30
		$this->module_id = $module_id;
421 30
	}
422
423
	/**
424
	* Set forums to exclude or include
425
	*
426
	* @param	array	$forum_from	Forums that should be shown or
427
	*					excluded from being shown
428
	* @param	array	$disallowed_forums	Forums that user is not
429
	*					allowed to see
430
	* @param	bool	$invert		Whether forum IDs in forum_from
431
	*					should be used for excluding or
432
	*					including forums
433
	* @return bool True if valid constraints were generated, false if not
434
	*/
435 30
	protected function set_forum_constraints($forum_from, $disallowed_forums, $invert = false)
436
	{
437 30
		if ($invert == true || empty($forum_from))
438 30
		{
439 24
			$access_list = array_merge($disallowed_forums, $forum_from);
440 24
			$sql_operator = '<>';
441 24
			$sql_append = 'AND';
442 24
		}
443
		else
444
		{
445 6
			$access_list = array_diff($forum_from, $disallowed_forums);
446 6
			$sql_operator = '=';
447 6
			$sql_append = 'OR';
448
449 6
			if (empty($access_list) && !empty($forum_from))
450 6
			{
451 2
				return false;
452
			}
453
		}
454
455
		// Generate where string
456 28
		$this->generate_where_string($access_list, $sql_operator, $sql_append);
457
458 28
		return true;
459
	}
460
461
	/**
462
	* Generate where string for database query
463
	*
464
	* @param	array	$access_list	Array containing the forum IDs
465
	*					the user has access to
466
	* @param	string	$sql_operator	The sql operator to use
467
	* @param	string	$sql_append	The sql append type to use.
468
	*					Should be either AND or OR
469
	* @return null
470
	*/
471 28
	protected function generate_where_string($access_list, $sql_operator, $sql_append)
472
	{
473 28
		foreach ($access_list as $acc_id)
474
		{
475 14
			$acc_id = (int) $acc_id;
476 14
			$this->where_string .= 't.forum_id ' . $sql_operator . " $acc_id $sql_append ";
477 14
			if ($sql_operator === '=' && $this->type == 'announcements' && $this->global_id < 1 && $acc_id > 0)
478 14
			{
479 4
				$this->global_id = $acc_id;
480 4
			}
481 28
		}
482 28
	}
483
484
	/**
485
	* Gets the a global forum ID for global announcements
486
	*
487
	* @return bool True if proper ID was selected, false if not
488
	*/
489 26
	protected function get_global_id()
490
	{
491 26
		if ($this->type == 'announcements' && $this->global_id < 1)
492 26
		{
493 8
			if (!empty($this->where_string) || ($row = $this->cache->get('_forum_id_first_forum_post')) === false)
494 8
			{
495 6
				$row = $this->get_first_forum_id();
496 6
			}
497
498 8
			if (empty($row))
499 8
			{
500 4
				return false;
501
			}
502 4
			$this->global_id = $row['forum_id'];
503 4
		}
504
505 22
		return true;
506
	}
507
508
	/**
509
	* Gets the first forum_id of FORUM_POST type forums
510
	*
511
	* @return array Database row of query
512
	*/
513 6
	protected function get_first_forum_id()
514
	{
515
		$sql = 'SELECT forum_id
516 6
			FROM ' . FORUMS_TABLE . '
517 6
			WHERE forum_type = ' . FORUM_POST . '
518 6
			' . str_replace('t.', '', $this->where_string) . '
519 6
			ORDER BY forum_id';
520 6
		$result = $this->db->sql_query_limit($sql, 1);
521 6
		$row = $this->db->sql_fetchrow($result);
522 6
		$this->db->sql_freeresult($result);
523
524 6
		if (empty($this->where_string))
525 6
		{
526
			// Cache first forum ID for one day = 86400 s
527 2
			$this->cache->put('_forum_id_first_forum_post', $row, 86400);
528 2
		}
529
530 6
		return $row;
531
	}
532
533
	/**
534
	* Resets constraints that might have been set before
535
	*
536
	* @return null
537
	*/
538 30
	protected function reset_constraints()
539
	{
540 30
		$this->where_string = '';
541 30
	}
542
543
	/**
544
	 * Get valid data based on setting
545
	 *
546
	 * @param mixed $setting Setting to check
547
	 * @param mixed $setting_true Data if setting is 'on' (not empty)
548
	 * @param mixed $setting_false Data if setting is 'off' (empty or 0)
549
	 *
550
	 * @return mixed Valid data based on setting
551
	 */
552 30
	protected function get_setting_based_data($setting, $setting_true, $setting_false)
553
	{
554 30
		return (!empty($setting)) ? $setting_true : $setting_false;
555
	}
556
557
	/**
558
	 * Assert that all supplied arguments evaluate to true
559
	 *
560
	 * @return bool True if all evaluate to true, false if not
561
	 */
562 12
	protected function assert_all_true()
563
	{
564 12
		$args = func_get_args();
565 12
		$return = true;
566
567 12
		foreach ($args as $argument)
568
		{
569 12
			$return = $return && $argument;
570 12
		}
571
572 12
		return $return;
573
	}
574
575
	/**
576
	 * Get attachments of posts
577
	 *
578
	 * @param array $row Database row of post
579
	 *
580
	 * @return array Attachment data
581
	 */
582 12
	protected function get_post_attachments($row)
583
	{
584 12
		$attachments = array();
585
586 12
		if ($this->user_can_download($row['forum_id']) && $this->assert_all_true($this->config['allow_attachments'], $row['post_id'], $row['post_attachment']))
587 12
		{
588
			// Pull attachment data
589
			$sql = 'SELECT *
590 12
					FROM ' . ATTACHMENTS_TABLE . '
591 12
					WHERE post_msg_id = '. (int) $row['post_id'] .'
592
					AND in_message = 0
593 12
					ORDER BY filetime DESC';
594 12
			$result = $this->db->sql_query($sql);
595
596 12
			while ($row = $this->db->sql_fetchrow($result))
597
			{
598 12
				$attachments[] = $row;
599 12
			}
600 12
			$this->db->sql_freeresult($result);
601 12
		}
602
603 12
		return $attachments;
604
	}
605
606
	/**
607
	 * Check if user can download a file in this forum
608
	 *
609
	 * @param int $forum_id Forum ID to check
610
	 *
611
	 * @return bool True if user can download, false if not
612
	 */
613 12
	protected function user_can_download($forum_id)
614
	{
615 12
		return $this->auth->acl_get('u_download') && ($this->auth->acl_get('f_download', $forum_id) || $forum_id == 0);
616
	}
617
618
	/**
619
	 * Format message for display
620
	 *
621
	 * @param array $row Database row
622
	 * @param int $text_length Length of text
623
	 * @param bool $posts_striped Whether post is striped
624
	 *
625
	 * @return mixed|string
626
	 */
627 12
	protected function format_message($row, $text_length, &$posts_striped)
628
	{
629 12
		if ($text_length > 0 && (strlen($row['post_text']) > $text_length))
630 12
		{
631 2
			$message = str_replace(array("\n", "\r"), array('<br />', "\n"), $row['post_text']);
632 2
			$message = $this->shorten_message($message, $row['bbcode_uid'], $text_length);
633 2
			$posts_striped = true;
634 2
		}
635
		else
636
		{
637 10
			$message = str_replace("\n", '<br/> ', $row['post_text']);
638
		}
639
640 12
		return $message;
641
	}
642
643
	/**
644
	 * Shorten message to specified length
645
	 *
646
	 * @param string $message Post text
647
	 * @param string $bbcode_uid BBCode UID
648
	 * @param int $length Length the text should have after shortening
649
	 *
650
	 * @return string Shortened messsage
651
	 */
652 2
	public function shorten_message($message, $bbcode_uid, $length)
653
	{
654 2
		if (class_exists('\Nickvergessen\TrimMessage\TrimMessage'))
655 2
		{
656
			$trim = new \Nickvergessen\TrimMessage\TrimMessage($message, $bbcode_uid, $length);
657
			$message = $trim->message();
658
			unset($trim);
659
		}
660
661 2
		return $message;
662
	}
663
}
664