Completed
Push — master ( db7709...24ebcc )
by Daniel
10:24
created

data::get_topic_tracking_info()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4.0741
Metric Value
dl 0
loc 11
ccs 5
cts 6
cp 0.8333
rs 9.2
cc 4
eloc 5
nc 5
nop 1
crap 4.0741
1
<?php
2
/**
3
 *
4
 * @package sitemaker
5
 * @copyright (c) 2013 Daniel A. (blitze)
6
 * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
7
 *
8
 */
9
10
namespace blitze\sitemaker\services\forum;
11
12
use phpbb\auth\auth;
13
use phpbb\config\config;
14
use phpbb\content_visibility;
15
use phpbb\db\driver\driver_interface;
16
use phpbb\user;
17
18
class data
19
{
20
	/** @var auth */
21
	protected $auth;
22
23
	/** @var config */
24
	protected $config;
25
26
	/** @var content_visibility */
27
	protected $content_visibility;
28
29
	/** @var driver_interface */
30
	protected $db;
31
32
	/** @var user */
33
	protected $user;
34
35
	/** @var string */
36
	protected $phpbb_root_path;
37
38
	/** @var string */
39
	protected $php_ext;
40
41
	/** @var array */
42
	protected $store;
43
44
	/** @var array */
45
	protected $ex_fid_ary;
46
47
	/** @var integer */
48
	protected $cache_time;
49
50
	/**
51
	 * Constructor
52
	 *
53
	 * @param auth					$auth					Auth object
54
	 * @param config				$config					Config object
55
	 * @param content_visibility	$content_visibility		Content visibility
56
	 * @param driver_interface		$db     				Database connection
57
	 * @param user					$user					User object
58
	 * @param string				$phpbb_root_path		Path to the phpbb includes directory.
59
	 * @param string				$php_ext				php file extension
60
	 * @param integer				$cache_time				Cache results for 3 hours by default
61
	 */
62 15
	public function __construct(auth $auth, config $config, content_visibility $content_visibility, driver_interface $db, user $user, $phpbb_root_path, $php_ext, $cache_time = 10800)
63
	{
64 15
		$this->auth = $auth;
65 15
		$this->config = $config;
66 15
		$this->content_visibility = $content_visibility;
67 15
		$this->db = $db;
68 15
		$this->user = $user;
69 15
		$this->phpbb_root_path = $phpbb_root_path;
70 15
		$this->php_ext = $php_ext;
71 15
		$this->cache_time = $cache_time;
72
73 15
		$this->ex_fid_ary = array_unique(array_keys($this->auth->acl_getf('!f_read', true)));
74 15
	}
75
76
	/**
77
	 * Begin query
78
	 *
79
	 * @return $this
80
	 */
81 9
	public function query()
82
	{
83 9
		$this->_reset();
84
85 9
		$this->store['sql_array'] = array(
86 9
			'SELECT'	=> array('t.*, f.*'),
87
88 9
			'FROM'		=> array(FORUMS_TABLE => 'f'),
89
90 9
			'LEFT_JOIN'	=> array(),
91
92 9
			'WHERE'		=> array(),
93
		);
94
95
		// Topics table need to be the last in the chain
96 9
		$this->store['sql_array']['FROM'][TOPICS_TABLE] = 't';
97
98 9
		return $this;
99
	}
100
101
	/**
102
	 * Fetch Forum by id(s)
103
	 *
104
	 * @param $forum_id
105
	 * @return $this
106
	 */
107 6
	public function fetch_forum($forum_id)
108
	{
109 6
		$this->_fetch($forum_id, 'f.forum_id');
110
111 6
		return $this;
112
	}
113
114
	/**
115
	 * Fetch Topic by id(s)
116
	 *
117
	 * @param mixed $topic_id	Limit by topic id: single id or array of topic ids
118
	 * @return $this
119
	 */
120
	public function fetch_topic($topic_id)
121
	{
122
		$this->_fetch($topic_id, 't.topic_id');
123
124
		return $this;
125
	}
126
127
	/**
128
	 * Fetch Topic by Poster id(s)
129
	 *
130
	 * @param mixed $user_id	User id of topic poster: single id or array of user ids
131
	 * @return $this
132
	 */
133
	public function fetch_topic_poster($user_id)
134
	{
135
		$this->_fetch($user_id, 't.topic_poster');
136
137
		return $this;
138
	}
139
140
	/**
141
	 * Fetch Post by id(s)
142
	 *
143
	 * @param mixed $post_id	Limit by post id: single id or array of post ids
144
	 * @return $this
145
	 */
146
	public function fetch_post($post_id)
147
	{
148
		$this->store['sql_array']['SELECT'][] = 'p.post_visibility, p.post_time, p.post_id';
149
		$this->store['sql_array']['FROM'][POSTS_TABLE] = 'p';
150
		$this->store['sql_array']['WHERE'][] = ((is_array($post_id)) ? $this->db->sql_in_set('p.post_id', $post_id) : 'p.post_id = ' . (int) $post_id) . ' AND t.topic_id = p.topic_id';
151
152
		return $this;
153
	}
154
155
	/**
156
	 * Fetch by Topic Type
157
	 *
158
	 * @param array $topic_type
159
	 * @return $this
160
	 */
161 6
	public function fetch_topic_type(array $topic_type)
162
	{
163 6
		if (sizeof($topic_type))
164 6
		{
165 3
			$this->store['sql_array']['WHERE'][] = $this->db->sql_in_set('t.topic_type', $topic_type);
166 3
		}
167
168 6
		if (in_array($topic_type, array(POST_STICKY, POST_ANNOUNCE)))
169 6
		{
170
			$this->store['sql_array']['WHERE'][] = '(t.topic_time_limit > 0 AND (t.topic_time + t.topic_time_limit) < ' . time() . ')';
171
		}
172
173 6
		return $this;
174
	}
175
176
	/**
177
	 * Fetch Topic Watch info
178
	 *
179
	 * @return $this
180
	 */
181
	public function fetch_watch_status()
182
	{
183
		if ($this->user->data['is_registered'])
184
		{
185
			$this->store['sql_array']['SELECT'][] = 'tw.notify_status';
186
			$this->store['sql_array']['LEFT_JOIN'][] = array(
187
				'FROM'	=> array(TOPICS_WATCH_TABLE => 'tw'),
188
				'ON'	=> 'tw.user_id = ' . $this->user->data['user_id'] . ' AND t.topic_id = tw.topic_id'
189
			);
190
191
			$this->store['sql_array']['SELECT'][] = 'fw.notify_status';
192
			$this->store['sql_array']['LEFT JOIN'][] = array(
193
				'FROM'	=> array(FORUMS_WATCH_TABLE => 'fw'),
194
				'ON'	=> '(fw.forum_id = f.forum_id AND fw.user_id = ' . $this->user->data['user_id'] . ')',
195
			);
196
		}
197
198
		return $this;
199
	}
200
201
	/**
202
	 * Fetch Topic Bookmark Info
203
	 *
204
	 * @return $this
205
	 */
206
	public function fetch_bookmark_status()
207
	{
208
		if ($this->user->data['is_registered'] && $this->config['allow_bookmarks'])
209
		{
210
			$this->store['sql_array']['SELECT'][] = 'bm.topic_id as bookmarked';
211
			$this->store['sql_array']['LEFT_JOIN'][] = array(
212
				'FROM'	=> array(BOOKMARKS_TABLE => 'bm'),
213
				'ON'	=> 'bm.user_id = ' . $this->user->data['user_id'] . ' AND t.topic_id = bm.topic_id'
214
			);
215
		}
216
217
		return $this;
218
	}
219
220
	/**
221
	 * Fetch Topic Tracking Info
222
	 *
223
	 * @param bool $track
224
	 * @return $this
225
	 */
226 4
	public function fetch_tracking_info($track = true)
227
	{
228 4
		if ($track && $this->user->data['is_registered'] && $this->config['load_db_lastread'])
229 4
		{
230 3
			$this->cache_time = 0;
231
232 3
			$this->store['sql_array']['SELECT'][] = 'tt.mark_time, ft.mark_time as forum_mark_time';
233 3
			$this->store['sql_array']['LEFT_JOIN'][] = array(
234 3
				'FROM'	=> array(TOPICS_TRACK_TABLE => 'tt'),
235 3
				'ON'	=> 'tt.user_id = ' . $this->user->data['user_id'] . ' AND t.topic_id = tt.topic_id'
236 3
			);
237
238 3
			$this->store['sql_array']['LEFT_JOIN'][] = array(
239 3
				'FROM'	=> array(FORUMS_TRACK_TABLE => 'ft'),
240 3
				'ON'	=> 'ft.user_id = ' . $this->user->data['user_id'] . ' AND t.forum_id = ft.forum_id'
241 3
			);
242 3
		}
243
244 4
		return $this;
245
	}
246
247
	/**
248
	 * Fetch by Date Range
249
	 *
250
	 * @param int $start	Unix start time
251
	 * @param int $stop		Unix stop time
252
	 * @param string $mode
253
	 * @return $this
254
	 */
255 4
	public function fetch_date_range($start, $stop, $mode = 'topic')
256
	{
257 4
		if ($start && $stop)
258 4
		{
259 1
			$this->store['sql_array']['WHERE'][] = (($mode == 'topic') ? 't.topic_time' : 'p.post_time') . " BETWEEN $start AND $stop";
260 1
		}
261
262 4
		return $this;
263
	}
264
265
	/**
266
	 * Fetch by Custom Query
267
	 *
268
	 * @param array	$sql_array		Array of elements to merge into query
269
	 * 										array(
270
	 * 											'SELECT'	=> array('p.*'),
271
	 * 											'WHERE'		=> array('p.post_id = 2'),
272
	 * 										)
273
	 * @return $this
274
	 */
275 5
	public function fetch_custom(array $sql_array)
276
	{
277 5
		$this->store['sql_array'] = array_merge_recursive($this->store['sql_array'], $sql_array);
278
279 5
		return $this;
280
	}
281
282
	/**
283
	 * Set Sorting Order
284
	 *
285
	 * @param string $sort_key		The sorting key e.g. t.topic_time
286
	 * @param string $sort_dir		Sort direction: ASC/DESC
287
	 * @return $this
288
	 */
289 9
	public function set_sorting($sort_key, $sort_dir = 'DESC')
290
	{
291 9
		$this->store['sql_array']['ORDER_BY'] = $sort_key . ' ' . $sort_dir;
292
293 9
		return $this;
294
	}
295
296
	/**
297
	 * Build the query
298
	 *
299
	 * @param bool|true $check_visibility	Should we only return data from forums the user is allowed to see?
300
	 * @param bool|true $enable_caching		Should the query be cached where possible?
301
	 * @return $this
302
	 */
303 9
	public function build($check_visibility = true, $enable_caching = true)
304
	{
305 9
		$this->_set_cache_time($enable_caching);
306 9
		$this->_set_topic_visibility($check_visibility);
307
308 9
		$this->store['sql_array']['WHERE'][] = 'f.forum_id = t.forum_id';
309 9
		$this->store['sql_array']['WHERE'][] = 't.topic_moved_id = 0';
310
311 9
		$this->store['sql_array']['SELECT'] = join(', ', array_filter($this->store['sql_array']['SELECT']));
312 9
		$this->store['sql_array']['WHERE'] = join(' AND ', array_filter($this->store['sql_array']['WHERE']));
313
314 9
		return $this;
315
	}
316
317
	/**
318
	 * Get the query array
319
	 *
320
	 * @return array	The sql array that can be used with sql_build_query
321
	 */
322
	public function get_sql_array()
323
	{
324
		return $this->store['sql_array'];
325
	}
326
327
	/**
328
	 * Get topic data
329
	 *
330
	 * @param mixed|false $limit
331
	 * @param int $start
332
	 * @return array
333
	 */
334 9
	public function get_topic_data($limit = false, $start = 0)
335
	{
336 9
		$sql = $this->db->sql_build_query('SELECT', $this->store['sql_array']);
337 9
		$result = $this->db->sql_query_limit($sql, $limit, $start, $this->cache_time);
338
339 9
		while ($row = $this->db->sql_fetchrow($result))
340
		{
341 8
			$this->store['topic'][$row['topic_id']] = $row;
342
343 8
			$this->store['tracking'][$row['forum_id']]['topic_list'][] = $row['topic_id'];
344 8
			$this->store['tracking'][$row['forum_id']]['mark_time'] =& $row['forum_mark_time'];
345 8
			$this->store['post_ids']['first'][] = $row['topic_first_post_id'];
346 8
			$this->store['post_ids']['last'][] = $row['topic_last_post_id'];
347 8
		}
348 9
		$this->db->sql_freeresult($result);
349
350 9
		return $this->store['topic'];
351
	}
352
353
	/**
354
	 * Get post data
355
	 *
356
	 * @param string $topic_first_or_last_post
357
	 * @param array $post_ids
358
	 * @param bool|false $limit
359
	 * @param int $start
360
	 * @param array $sql_array
361
	 * @return array
362
	 */
363 3
	public function get_post_data($topic_first_or_last_post = '', $post_ids = array(), $limit = false, $start = 0, $sql_array = array())
364
	{
365 3
		$sql_array = array_merge_recursive(
366
			array(
367 3
				'SELECT'	=> array('p.*'),
368 3
				'FROM'		=> array(POSTS_TABLE => 'p'),
369 3
				'WHERE'		=> $this->_get_post_data_where($post_ids, $topic_first_or_last_post),
370 3
				'ORDER_BY'	=> 'p.topic_id, p.post_time ASC',
371 3
			),
372
			$sql_array
373 3
		);
374
375 3
		$sql_array['SELECT'] = join(', ', array_filter($sql_array['SELECT']));
376 3
		$sql_array['WHERE'] = join(' AND ', array_filter($sql_array['WHERE']));
377
378 3
		$sql = $this->db->sql_build_query('SELECT', $sql_array);
379 3
		$result = $this->db->sql_query_limit($sql, $limit, $start, $this->cache_time);
380
381 3
		$post_data = array();
382 3
		while ($row = $this->db->sql_fetchrow($result))
383
		{
384 3
			$parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES;
385 3
			$row['post_text'] = generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, true);
386
387 3
			$post_data[$row['topic_id']][$row['post_id']] = $row;
388 3
			$this->store['poster_ids'][] = $row['poster_id'];
389 3
			$this->store['poster_ids'][] = $row['post_edit_user'];
390 3
			$this->store['poster_ids'][] = $row['post_delete_user'];
391 3
			$this->store['attachments'][$row['post_id']] = $row['post_attachment'];
392 3
		}
393 3
		$this->db->sql_freeresult($result);
394
395 3
		return $post_data;
396
	}
397
398
	/**
399
	 * Get attachments...
400
	 *
401
	 * @param int $forum_id
402
	 * @return array
403
	 */
404
	public function get_attachments($forum_id)
405
	{
406
		$this->store['attachments'] = array_flip(array_filter($this->store['attachments']));
407
408
		$attachments = array();
409
		if ($this->_attachments_allowed($forum_id))
410
		{
411
			$sql = 'SELECT *
412
				FROM ' . ATTACHMENTS_TABLE . '
413
				WHERE ' . $this->db->sql_in_set('post_msg_id', $this->store['attachments']) . '
414
					AND in_message = 0
415
				ORDER BY filetime DESC, post_msg_id ASC';
416
			$result = $this->db->sql_query($sql);
417
418
			while ($row = $this->db->sql_fetchrow($result))
419
			{
420
				$attachments[$row['post_msg_id']][] = $row;
421
			}
422
			$this->db->sql_freeresult($result);
423
		}
424
		$this->store['attachments'] = array();
425
426
		return $attachments;
427
	}
428
429
	/**
430
	 * Get topic tracking info
431
	 *
432
	 * @param int $forum_id
433
	 * @return array
434
	 */
435 4
	public function get_topic_tracking_info($forum_id = 0)
436
	{
437 4
		if (!sizeof($this->store['tracking']))
438 4
		{
439
			return array();
440
		}
441
442 4
		$tracking_info = $this->_get_tracking_info();
443
444 4
		return ($forum_id) ? (isset($tracking_info[$forum_id]) ? $tracking_info[$forum_id] : array()) : $tracking_info;
445
	}
446
447
	/**
448
	 * Returns an array of topic first post or last post ids
449
	 *
450
	 * @return array
451
	 */
452
	public function get_posters_info()
453
	{
454
		$this->store['poster_ids'] = array_filter(array_unique($this->store['poster_ids']));
455
456
		$sql = 'SELECT *
457
			FROM ' . USERS_TABLE . '
458
			WHERE ' . $this->db->sql_in_set('user_id', $this->store['poster_ids']);
459
		$result = $this->db->sql_query($sql);
460
461
		$poster = array();
462
		while ($row = $this->db->sql_fetchrow($result))
463
		{
464
			$poster[$row['user_id']] = $row;
465
		}
466
		$this->db->sql_freeresult($result);
467
468
		return $poster;
469
	}
470
471
	/**
472
	 * Returns an array of topic first post or last post ids
473
	 *
474
	 * @param string $first_or_last_post
475
	 * @return array
476
	 */
477 3
	public function get_topic_post_ids($first_or_last_post = 'first')
478
	{
479 3
		return (isset($this->store['post_ids'][$first_or_last_post])) ? $this->store['post_ids'][$first_or_last_post] : array();
480
	}
481
482
	/**
483
	 * Reset data
484
	 */
485 9
	private function _reset()
486
	{
487 9
		$this->store = array(
488 9
			'attachments'	=> array(),
489 9
			'post_ids'		=> array(),
490 9
			'poster_ids'	=> array(),
491 9
			'sql_array'		=> array(),
492 9
			'topic'			=> array(),
493 9
			'tracking'		=> array(),
494
		);
495 9
	}
496
497
	/**
498
	 * @param int $column_id
499
	 * @param string $column
500
	 */
501 6
	private function _fetch($column_id, $column)
502
	{
503 6
		if (!empty($column_id))
504 6
		{
505 1
			$this->store['sql_array']['WHERE'][] = (is_array($column_id)) ? $this->db->sql_in_set($column, $column_id) : $column . ' = ' . (int) $column_id;
506 1
		}
507 6
	}
508
509
	/**
510
	 * @param bool $enable_caching
511
	 */
512 9
	protected function _set_cache_time($enable_caching)
513
	{
514 9
		if ($enable_caching === false)
515 9
		{
516 3
			$this->cache_time = 0;
517 3
		}
518 9
	}
519
520
	/**
521
	 * @param bool $check_visibility
522
	 */
523 9
	private function _set_topic_visibility($check_visibility)
524
	{
525
		if ($check_visibility)
526 9
		{
527 9
			$this->store['sql_array']['WHERE'][] = 't.topic_time <= ' . time();
528 9
			$this->store['sql_array']['WHERE'][] = $this->content_visibility->get_global_visibility_sql('topic', $this->ex_fid_ary, 't.');
529 9
		}
530 9
	}
531
532
	/**
533
	 * @param array $post_ids
534
	 * @param string $topic_first_or_last_post
535
	 * @return array
536
	 */
537 3
	private function _get_post_data_where(array $post_ids, $topic_first_or_last_post)
538
	{
539 3
		$sql_where = array();
540 3
		if (sizeof($this->store['topic']))
541 3
		{
542 3
			$sql_where[] = $this->db->sql_in_set('topic_id', array_keys($this->store['topic']));
543
544
			if ($topic_first_or_last_post)
545 3
			{
546 3
				$post_ids = array_merge($post_ids, $this->get_topic_post_ids($topic_first_or_last_post));
547 3
				$sql_where[] = $this->db->sql_in_set('post_id', $post_ids);
548 3
			}
549 3
		}
550
551 3
		$sql_where[] = $this->content_visibility->get_global_visibility_sql('post', $this->ex_fid_ary, 'p.');
552
553 3
		return $sql_where;
554
	}
555
556
	/**
557
	 * @return array
558
	 */
559 4
	private function _get_tracking_info()
560
	{
561 4
		$info = array();
562 4
		if ($this->_can_track_by_lastread())
563 4
		{
564 4
			$info = $this->_build_tracking_info('get_topic_tracking');
565 4
		}
566
		else if ($this->_can_track_anonymous())
567
		{
568
			$info = $this->_build_tracking_info('get_complete_topic_tracking');
569
		}
570
571 4
		return $info;
572
	}
573
574
	/**
575
	 * @param string $function
576
	 * @return array
577
	 */
578 4
	private function _build_tracking_info($function)
579
	{
580 4
		$tracking_info = array();
581 4
		foreach ($this->store['tracking'] as $fid => $forum)
582
		{
583 4
			$tracking_info[$fid] = call_user_func_array($function, array($fid, $forum['topic_list'], &$this->store['topic'], array($fid => $forum['mark_time'])));
584 4
		}
585
586 4
		return $tracking_info;
587
	}
588
589
	/**
590
	 * @return bool
591
	 */
592 4
	private function _can_track_by_lastread()
593
	{
594 4
		return ($this->config['load_db_lastread'] && $this->user->data['is_registered']) ? true : false;
595
	}
596
597
	/**
598
	 * @return bool
599
	 */
600
	private function _can_track_anonymous()
601
	{
602
		return ($this->config['load_anon_lastread'] || $this->user->data['is_registered']) ? true : false;
603
	}
604
605
	/**
606
	 * @param int $forum_id
607
	 * @return bool
608
	 */
609
	private function _attachments_allowed($forum_id)
610
	{
611
		return (sizeof($this->store['attachments']) && $this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $forum_id)) ? true : false;
612
	}
613
}
614