fetch_posts::format_message()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 2
nop 3
dl 0
loc 15
ccs 9
cts 9
cp 1
crap 3
rs 9.4285
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() - $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_title,
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'] = $this->get_setting_based_data($row['enable_bbcode'], OPTION_FLAG_BBCODE, 0) + $this->get_setting_based_data($row['enable_smilies'], OPTION_FLAG_SMILIES, 0) + $this->get_setting_based_data($row['enable_magic_url'], OPTION_FLAG_LINKS, 0);
302 12
		$message = generate_text_for_display($message, $row['bbcode_uid'], $row['bbcode_bitfield'], $row['bbcode_options']);
303
304 12
		if (!empty($attachments))
305 12
		{
306 12
			parse_attachments($row['forum_id'], $message, $attachments, $update_count);
307 12
		}
308
309
		// Get proper global ID
310 12
		$this->global_id = $this->get_setting_based_data($this->global_id, $this->global_id, $row['forum_id']);
311
312 12
		$topic_icons[] = $row['enable_icons'];
313 12
		$have_icons = $this->get_setting_based_data($row['icon_id'], 1, $have_icons);
314
315 12
		$posts[$i] = array_merge($posts[$i], array(
316 12
			'post_text'				=> ap_validate($message),
317 12
			'topic_id'				=> $row['topic_id'],
318 12
			'topic_last_post_id'	=> $row['topic_last_post_id'],
319 12
			'topic_type'			=> $row['topic_type'],
320 12
			'topic_posted'			=> $this->get_setting_based_data(isset($row['topic_posted']) && $row['topic_posted'], true, false),
321 12
			'icon_id'				=> $row['icon_id'],
322 12
			'topic_status'			=> $row['topic_status'],
323 12
			'forum_id'				=> $row['forum_id'],
324 12
			'topic_replies'			=> $row['topic_posts_approved'] + $row['topic_posts_unapproved'] + $row['topic_posts_softdeleted'] - 1,
325 12
			'topic_replies_real'	=> $row['topic_posts_approved'] - 1,
326 12
			'topic_time'			=> $this->user->format_date($row['post_time']),
327 12
			'topic_last_post_time'	=> $row['topic_last_post_time'],
328 12
			'topic_title'			=> $row['topic_title'],
329 12
			'username'				=> $row['username'],
330 12
			'username_full'			=> get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $row['post_username']),
331 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']),
332 12
			'user_id'				=> $row['user_id'],
333 12
			'user_type'				=> $row['user_type'],
334 12
			'user_colour'			=> $row['user_colour'],
335 12
			'poll'					=> $this->get_setting_based_data($row['poll_title'], true, false),
336 12
			'attachment'			=> $this->get_setting_based_data($row['topic_attachment'], true, false),
337 12
			'topic_views'			=> $row['topic_views'],
338 12
			'forum_name'			=> $row['forum_name'],
339 12
			'attachments'			=> $this->get_setting_based_data($attachments, $attachments, array()),
340 12
		));
341 12
		$posts['global_id'] = $this->global_id;
342 12
	}
343
344
	/**
345
	* Get type constraints for database query
346
	*
347
	* @return null
348
	* @throws \InvalidArgumentexception If unknown type is used
349
	*/
350 28
	protected function get_type_constraints()
351
	{
352 28
		switch ($this->type)
353
		{
354 28
			case "announcements":
355 12
				$this->get_announcements_constraints();
356 12
			break;
357 16
			case "news":
358 12
				$this->get_news_constraints();
359 12
			break;
360 4
			case "news_all":
361 2
				$this->get_news_all_constraints();
362 2
			break;
363
364 2
			default:
365
				// Method was called with unsupported type
366 2
				throw new \InvalidArgumentexception($this->user->lang('B3P_WRONG_METHOD_CALL', __FUNCTION__));
367 28
		}
368 26
	}
369
370
	/**
371
	* Get type constraints for announcements
372
	*
373
	* @return null
374
	*/
375 12
	protected function get_announcements_constraints()
376
	{
377 12
		$this->topic_type = '((t.topic_type = ' . POST_ANNOUNCE . ') OR (t.topic_type = ' . POST_GLOBAL . '))';
378 12
		$this->where_string = (strlen($this->where_string) > 0) ? 'AND (t.forum_id = 0 OR (' . trim(substr($this->where_string, 0, -4)) . '))' : '';
379 12
		$this->user_link = 't.topic_poster = u.user_id';
380 12
		$this->post_link = 't.topic_first_post_id = p.post_id';
381 12
		$this->topic_order = 't.topic_time DESC';
382 12
	}
383
384
	/**
385
	* Get type constraints for news
386
	*
387
	* @return null
388
	*/
389 14
	protected function get_news_constraints()
390
	{
391 14
		$this->topic_type = 't.topic_type = ' . POST_NORMAL;
392 14
		$this->where_string = (strlen($this->where_string) > 0) ? 'AND (' . trim(substr($this->where_string, 0, -4)) . ')' : '';
393 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')) ;
394 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'));
395 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');
396 14
	}
397
398
	/**
399
	* Get additional type constraints for all news
400
	* Overwrites topic type of get_news_constraints().
401
	*
402
	* @return null
403
	*/
404 2
	protected function get_news_all_constraints()
405
	{
406 2
		$this->get_news_constraints();
407 2
		$this->topic_type = '(t.topic_type <> ' . POST_ANNOUNCE . ') AND (t.topic_type <> ' . POST_GLOBAL . ')';
408 2
	}
409
410
	/**
411
	* Set module id
412
	*
413
	* @param	int	$module_id	Module ID
414
	* @return null
415
	*/
416 30
	public function set_module_id($module_id)
417
	{
418 30
		$this->module_id = $module_id;
419 30
	}
420
421
	/**
422
	* Set forums to exclude or include
423
	*
424
	* @param	array	$forum_from	Forums that should be shown or
425
	*					excluded from being shown
426
	* @param	array	$disallowed_forums	Forums that user is not
427
	*					allowed to see
428
	* @param	bool	$invert		Whether forum IDs in forum_from
429
	*					should be used for excluding or
430
	*					including forums
431
	* @return bool True if valid constraints were generated, false if not
432
	*/
433 30
	protected function set_forum_constraints($forum_from, $disallowed_forums, $invert = false)
434
	{
435 30
		if ($invert == true || empty($forum_from))
436 30
		{
437 24
			$access_list = array_merge($disallowed_forums, $forum_from);
438 24
			$sql_operator = '<>';
439 24
			$sql_append = 'AND';
440 24
		}
441
		else
442
		{
443 6
			$access_list = array_diff($forum_from, $disallowed_forums);
444 6
			$sql_operator = '=';
445 6
			$sql_append = 'OR';
446
447 6
			if (empty($access_list) && !empty($forum_from))
448 6
			{
449 2
				return false;
450
			}
451
		}
452
453
		// Generate where string
454 28
		$this->generate_where_string($access_list, $sql_operator, $sql_append);
455
456 28
		return true;
457
	}
458
459
	/**
460
	* Generate where string for database query
461
	*
462
	* @param	array	$access_list	Array containing the forum IDs
463
	*					the user has access to
464
	* @param	string	$sql_operator	The sql operator to use
465
	* @param	string	$sql_append	The sql append type to use.
466
	*					Should be either AND or OR
467
	* @return null
468
	*/
469 28
	protected function generate_where_string($access_list, $sql_operator, $sql_append)
470
	{
471 28
		foreach ($access_list as $acc_id)
472
		{
473 14
			$acc_id = (int) $acc_id;
474 14
			$this->where_string .= 't.forum_id ' . $sql_operator . " $acc_id $sql_append ";
475 14
			if ($sql_operator === '=' && $this->type == 'announcements' && $this->global_id < 1 && $acc_id > 0)
476 14
			{
477 4
				$this->global_id = $acc_id;
478 4
			}
479 28
		}
480 28
	}
481
482
	/**
483
	* Gets the a global forum ID for global announcements
484
	*
485
	* @return bool True if proper ID was selected, false if not
486
	*/
487 26
	protected function get_global_id()
488
	{
489 26
		if ($this->type == 'announcements' && $this->global_id < 1)
490 26
		{
491 8
			if (!empty($this->where_string) || ($row = $this->cache->get('_forum_id_first_forum_post')) === false)
492 8
			{
493 6
				$row = $this->get_first_forum_id();
494 6
			}
495
496 8
			if (empty($row))
497 8
			{
498 4
				return false;
499
			}
500 4
			$this->global_id = $row['forum_id'];
501 4
		}
502
503 22
		return true;
504
	}
505
506
	/**
507
	* Gets the first forum_id of FORUM_POST type forums
508
	*
509
	* @return array Database row of query
510
	*/
511 6
	protected function get_first_forum_id()
512
	{
513
		$sql = 'SELECT forum_id
514 6
			FROM ' . FORUMS_TABLE . '
515 6
			WHERE forum_type = ' . FORUM_POST . '
516 6
			' . str_replace('t.', '', $this->where_string) . '
517 6
			ORDER BY forum_id';
518 6
		$result = $this->db->sql_query_limit($sql, 1);
519 6
		$row = $this->db->sql_fetchrow($result);
520 6
		$this->db->sql_freeresult($result);
521
522 6
		if (empty($this->where_string))
523 6
		{
524
			// Cache first forum ID for one day = 86400 s
525 2
			$this->cache->put('_forum_id_first_forum_post', $row, 86400);
526 2
		}
527
528 6
		return $row;
529
	}
530
531
	/**
532
	* Resets constraints that might have been set before
533
	*
534
	* @return null
535
	*/
536 30
	protected function reset_constraints()
537
	{
538 30
		$this->where_string = '';
539 30
	}
540
541
	/**
542
	 * Get valid data based on setting
543
	 *
544
	 * @param mixed $setting Setting to check
545
	 * @param mixed $setting_true Data if setting is 'on' (not empty)
546
	 * @param mixed $setting_false Data if setting is 'off' (empty or 0)
547
	 *
548
	 * @return mixed Valid data based on setting
549
	 */
550 30
	protected function get_setting_based_data($setting, $setting_true, $setting_false)
551
	{
552 30
		return (!empty($setting)) ? $setting_true : $setting_false;
553
	}
554
555
	/**
556
	 * Assert that all supplied arguments evaluate to true
557
	 *
558
	 * @return bool True if all evaluate to true, false if not
559
	 */
560 12
	protected function assert_all_true()
561
	{
562 12
		$args = func_get_args();
563 12
		$return = true;
564
565 12
		foreach ($args as $argument)
566
		{
567 12
			$return = $return && $argument;
568 12
		}
569
570 12
		return $return;
571
	}
572
573
	/**
574
	 * Get attachments of posts
575
	 *
576
	 * @param array $row Database row of post
577
	 *
578
	 * @return array Attachment data
579
	 */
580 12
	protected function get_post_attachments($row)
581
	{
582 12
		$attachments = array();
583
584 12
		if ($this->user_can_download($row['forum_id']) && $this->assert_all_true($this->config['allow_attachments'], $row['post_id'], $row['post_attachment']))
585 12
		{
586
			// Pull attachment data
587
			$sql = 'SELECT *
588 12
					FROM ' . ATTACHMENTS_TABLE . '
589 12
					WHERE post_msg_id = '. (int) $row['post_id'] .'
590
					AND in_message = 0
591 12
					ORDER BY filetime DESC';
592 12
			$result = $this->db->sql_query($sql);
593
594 12
			while ($row = $this->db->sql_fetchrow($result))
595
			{
596 12
				$attachments[] = $row;
597 12
			}
598 12
			$this->db->sql_freeresult($result);
599 12
		}
600
601 12
		return $attachments;
602
	}
603
604
	/**
605
	 * Check if user can download a file in this forum
606
	 *
607
	 * @param int $forum_id Forum ID to check
608
	 *
609
	 * @return bool True if user can download, false if not
610
	 */
611 12
	protected function user_can_download($forum_id)
612
	{
613 12
		return $this->auth->acl_get('u_download') && ($this->auth->acl_get('f_download', $forum_id) || $forum_id == 0);
614
	}
615
616
	/**
617
	 * Format message for display
618
	 *
619
	 * @param array $row Database row
620
	 * @param int $text_length Length of text
621
	 * @param bool $posts_striped Whether post is striped
622
	 *
623
	 * @return mixed|string
624
	 */
625 12
	protected function format_message($row, $text_length, &$posts_striped)
626
	{
627 12
		if ($text_length > 0 && (strlen($row['post_text']) > $text_length))
628 12
		{
629 2
			$message = str_replace(array("\n", "\r"), array('<br />', "\n"), $row['post_text']);
630 2
			$message = $this->shorten_message($message, $row['bbcode_uid'], $text_length);
631 2
			$posts_striped = true;
632 2
		}
633
		else
634
		{
635 10
			$message = str_replace("\n", '<br/> ', $row['post_text']);
636
		}
637
638 12
		return $message;
639
	}
640
641
	/**
642
	 * Shorten message to specified length
643
	 *
644
	 * @param string $message Post text
645
	 * @param string $bbcode_uid BBCode UID
646
	 * @param int $length Length the text should have after shortening
647
	 *
648
	 * @return string Shortened messsage
649
	 */
650 2
	public function shorten_message($message, $bbcode_uid, $length)
651
	{
652 2
		if (class_exists('\Nickvergessen\TrimMessage\TrimMessage'))
653 2
		{
654 2
			$trim = new \Nickvergessen\TrimMessage\TrimMessage($message, $bbcode_uid, $length);
655 2
			$message = $trim->message();
656 2
			unset($trim);
657 2
		}
658
659 2
		return $message;
660
	}
661
}
662