query_builder   A
last analyzed

Complexity

Total Complexity 41

Size/Duplication

Total Lines 382
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 41
eloc 103
c 1
b 0
f 0
dl 0
loc 382
ccs 142
cts 142
cp 1
rs 9.1199

20 Methods

Rating   Name   Duplication   Size   Complexity  
A fetch_tracking_info() 0 19 3
A fetch_topic_type() 0 8 2
A __construct() 0 10 1
A set_sorting() 0 5 1
A get_sql_array() 0 3 1
A _fetch() 0 5 3
A fetch_db_track() 0 9 3
A fetch_bookmark_status() 0 12 3
A _reset() 0 9 1
A _set_cache_time() 0 5 2
A fetch_topic_poster() 0 5 1
A fetch_topic() 0 5 1
A _set_topic_visibility() 0 5 2
A fetch_date_range() 0 8 4
A _set_forum_table() 0 11 3
A fetch_watch_status() 0 23 2
A query() 0 20 3
A fetch_forum() 0 5 2
A build() 0 14 1
A fetch_custom() 0 10 2

How to fix   Complexity   

Complex Class

Complex classes like query_builder often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use query_builder, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 *
5
 * @package sitemaker
6
 * @copyright (c) 2013 Daniel A. (blitze)
7
 * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
8
 *
9
 */
10
11
namespace blitze\sitemaker\services\forum;
12
13
class query_builder
14
{
15
	/** @var \phpbb\auth\auth */
16
	protected $auth;
17
18
	/** @var \phpbb\config\config */
19
	protected $config;
20
21
	/** @var \phpbb\content_visibility */
22
	protected $content_visibility;
23
24
	/** @var \phpbb\db\driver\driver_interface */
25
	protected $db;
26
27
	/** @var \phpbb\user */
28
	protected $user;
29
30
	/** @var array */
31
	protected $store;
32
33
	/** @var array */
34
	protected $ex_fid_ary;
35
36
	/** @var integer */
37
	protected $cache_time;
38
39
	/**
40
	 * Constructor
41
	 *
42
	 * @param \phpbb\auth\auth					$auth					Auth object
43
	 * @param \phpbb\config\config				$config					Config object
44
	 * @param \phpbb\content_visibility			$content_visibility		Content visibility
45
	 * @param \phpbb\db\driver\driver_interface	$db     				Database connection
46
	 * @param \phpbb\user						$user					User object
47
	 * @param integer							$cache_time				Cache results for 3 hours by default
48 45
	 */
49
	public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\content_visibility $content_visibility, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $cache_time)
50 45
	{
51 45
		$this->auth = $auth;
52 45
		$this->config = $config;
53 45
		$this->content_visibility = $content_visibility;
54 45
		$this->db = $db;
55 45
		$this->user = $user;
56
		$this->cache_time = $cache_time;
57 45
58 45
		$this->ex_fid_ary = array_unique(array_keys($this->auth->acl_getf('!f_read', true)));
59
	}
60
61
	/**
62
	 * Begin query
63
	 *
64
	 * @param bool $track_topics
65
	 * @param bool $get_forum_data
66
	 * @return $this
67 35
	 */
68
	public function query($track_topics = true, $get_forum_data = true)
69 35
	{
70
		$this->_reset();
71 35
72
		$this->store['sql_array'] = array_fill_keys(array('SELECT', 'FROM', 'LEFT_JOIN', 'WHERE'), array());
73
74 35
		if ($get_forum_data)
75 23
		{
76 23
			$this->store['sql_array']['SELECT'][] = 'f.*';
77 23
			$this->store['sql_array']['FROM'][FORUMS_TABLE] = 'f';
78
		}
79 35
80
		$this->store['sql_array']['SELECT'][] = 't.*';
81
82 35
		if ($track_topics)
83 9
		{
84 9
			$this->fetch_tracking_info();
85
		}
86 35
87
		return $this;
88
	}
89
90
	/**
91
	 * Fetch Forum by id(s)
92
	 *
93
	 * @param int|array $forum_id
94
	 * @return $this
95 21
	 */
96
	public function fetch_forum($forum_id)
97 21
	{
98
		$this->_fetch($forum_id, (isset($this->store['sql_array']['FROM'][FORUMS_TABLE])) ? 'f.forum_id' : 't.forum_Id');
99 21
100
		return $this;
101
	}
102
103
	/**
104
	 * Fetch Topic by id(s)
105
	 *
106
	 * @param mixed $topic_id	Limit by topic id: single id or array of topic ids
107
	 * @return $this
108 15
	 */
109
	public function fetch_topic($topic_id)
110 15
	{
111
		$this->_fetch($topic_id, 't.topic_id');
112 15
113
		return $this;
114
	}
115
116
	/**
117
	 * Fetch Topic by Poster id(s)
118
	 *
119
	 * @param mixed $user_id	User id of topic poster: single id or array of user ids
120
	 * @return $this
121 7
	 */
122
	public function fetch_topic_poster($user_id)
123 7
	{
124
		$this->_fetch($user_id, 't.topic_poster');
125 7
126
		return $this;
127
	}
128
129
	/**
130
	 * Fetch by Topic Type
131
	 *
132
	 * @param array $topic_type
133
	 * @return $this
134 17
	 */
135
	public function fetch_topic_type(array $topic_type)
136 17
	{
137 17
		if (sizeof($topic_type))
138 5
		{
139 5
			$this->store['sql_array']['WHERE'][] = $this->db->sql_in_set('t.topic_type', $topic_type);
140
		}
141 17
142
		return $this;
143
	}
144
145
	/**
146
	 * Fetch Topic Watch info
147
	 *
148
	 * @param $type
149
	 * @return $this
150 2
	 */
151
	public function fetch_watch_status($type = 'topic')
152 2
	{
153 2
		if ($this->user->data['is_registered'])
154
		{
155
			$keys = array(
156 1
				'forum'	=> array(
157 1
					'table'	=> FORUMS_WATCH_TABLE,
158 1
					'cond'	=> 'ws.forum_id = f.forum_id',
159
				),
160 1
				'topic'	=> array(
161 1
					'table'	=> TOPICS_WATCH_TABLE,
162 1
					'cond'	=> 'ws.topic_id = t.topic_id',
163 1
				),
164
			);
165 1
166 1
			$this->store['sql_array']['SELECT'][] = 'ws.notify_status';
167 1
			$this->store['sql_array']['LEFT_JOIN'][] = array(
168 1
				'FROM'	=> array($keys[$type]['table'] => 'ws'),
169
				'ON'	=> $keys[$type]['cond'] . ' AND ws.user_id = ' . (int) $this->user->data['user_id'],
170 1
			);
171
		}
172 2
173
		return $this;
174
	}
175
176
	/**
177
	 * Fetch Topic Bookmark Info
178
	 *
179
	 * @return $this
180 2
	 */
181
	public function fetch_bookmark_status()
182 2
	{
183 2
		if ($this->user->data['is_registered'] && $this->config['allow_bookmarks'])
184 1
		{
185 1
			$this->store['sql_array']['SELECT'][] = 'bm.topic_id as bookmarked';
186 1
			$this->store['sql_array']['LEFT_JOIN'][] = array(
187 1
				'FROM'	=> array(BOOKMARKS_TABLE => 'bm'),
188 1
				'ON'	=> 'bm.user_id = ' . (int) $this->user->data['user_id'] . ' AND t.topic_id = bm.topic_id'
189 1
			);
190
		}
191 2
192
		return $this;
193
	}
194
195
	/**
196
	 * Fetch Topic Tracking Info
197
	 *
198
	 * @return $this
199 9
	 */
200
	public function fetch_tracking_info()
201 9
	{
202 9
		if ($this->user->data['is_registered'] && $this->config['load_db_lastread'])
203 8
		{
204
			$this->cache_time = 0;
205 8
206 8
			$this->store['sql_array']['SELECT'][] = 'tt.mark_time, ft.mark_time as forum_mark_time';
207 8
			$this->store['sql_array']['LEFT_JOIN'][] = array(
208 8
				'FROM'	=> array(TOPICS_TRACK_TABLE => 'tt'),
209 8
				'ON'	=> 'tt.user_id = ' . (int) $this->user->data['user_id'] . ' AND t.topic_id = tt.topic_id'
210
			);
211 8
212 8
			$this->store['sql_array']['LEFT_JOIN'][] = array(
213 8
				'FROM'	=> array(FORUMS_TRACK_TABLE => 'ft'),
214 8
				'ON'	=> 'ft.user_id = ' . (int) $this->user->data['user_id'] . ' AND t.forum_id = ft.forum_id'
215 8
			);
216
		}
217 9
218
		return $this;
219
	}
220
221
	/**
222
	 * Fetch Topics posted Info
223
	 *
224
	 * @return $this
225
	 */
226
	public function fetch_db_track()
227
	{
228 14
		if ($this->user->data['is_registered'] && $this->config['load_db_track'])
229
		{
230 14
			$this->store['sql_array']['SELECT'][] = 'tp.topic_posted';
231 14
			$this->store['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']);
232 2
		}
233 2
234
		return $this;
235 14
	}
236
237
	/**
238
	 * Fetch by Date Range
239
	 *
240
	 * @param int $unix_start_time
241
	 * @param int $unix_stop_time
242
	 * @param string $mode topic|post
243
	 * @return $this
244
	 */
245
	public function fetch_date_range($unix_start_time, $unix_stop_time, $mode = 'topic')
246
	{
247
		if ($unix_start_time && $unix_stop_time)
248
		{
249
			$this->store['sql_array']['WHERE'][] = (($mode == 'topic') ? 't.topic_time' : 'p.post_time') . " BETWEEN $unix_start_time AND $unix_stop_time";
250 13
		}
251
252 13
		return $this;
253
	}
254 13
255
	/**
256 3
	 * Fetch by Custom Query
257 13
	 *
258
	 * @param array	$sql_array			Array of elements to merge into query
259 13
	 * 										array(
260
	 * 											'SELECT'	=> array('p.*'),
261
	 * 											'WHERE'		=> array('p.post_id = 2'),
262
	 * 										)
263
	 * @param array $overwrite_keys		Array of query keys to overwrite with yours instead of merging
264
	 *									e.g array('SELECT') will overwrite the 'SELECT' key with whatever is provided in $sql_array
265
	 * @return $this
266
	 */
267
	public function fetch_custom(array $sql_array, $overwrite_keys = array())
268
	{
269 13
		$this->store['sql_array'] = array_merge_recursive($this->store['sql_array'], $sql_array);
270
271 13
		foreach ($overwrite_keys as $key)
272
		{
273 13
			$this->store['sql_array'][$key] = $sql_array[$key];
274
		}
275
276
		return $this;
277
	}
278
279
	/**
280
	 * Set Sorting Order
281
	 *
282
	 * @param string $sort_key		The sorting key e.g. t.topic_time
283
	 * @param string $sort_dir		Sort direction: ASC/DESC
284 35
	 * @return $this
285
	 */
286 35
	public function set_sorting($sort_key, $sort_dir = 'DESC')
287 35
	{
288 35
		$this->store['sql_array']['ORDER_BY'] = $sort_key . ' ' . $sort_dir;
289
290
		return $this;
291 35
	}
292 35
293
	/**
294 35
	 * Build the query
295 35
	 *
296
	 * @param bool|true $check_visibility		Should we only return data from forums the user is allowed to see?
297 35
	 * @param bool|true $enable_caching			Should the query be cached where possible?
298
	 * @param bool|true $exclude_hidden_forums	Leave out hidden forums?
299
	 * @return $this
300
	 */
301
	public function build($check_visibility = true, $enable_caching = true, $exclude_hidden_forums = true)
302
	{
303
		$this->_set_cache_time($enable_caching);
304
		$this->_set_topic_visibility($check_visibility);
305 21
		$this->_set_forum_table($exclude_hidden_forums);
306
307 21
		// Topics table need to be the last in the chain
308
		$this->store['sql_array']['FROM'][TOPICS_TABLE] = 't';
309
		$this->store['sql_array']['WHERE'][] = 't.topic_moved_id = 0';
310
311
		$this->store['sql_array']['SELECT'] = join(', ', array_filter($this->store['sql_array']['SELECT']));
312
		$this->store['sql_array']['WHERE'] = join(' AND ', array_filter($this->store['sql_array']['WHERE']));
313 24
314
		return $this;
315 24
	}
316
317
	/**
318
	 * Get the query array
319
	 *
320
	 * @return array	The sql array that can be used with sql_build_query
321
	 */
322 35
	public function get_sql_array()
323
	{
324 35
		return $this->store['sql_array'];
325 35
	}
326 5
327 5
	/**
328 35
	 * @param bool $enable_caching
329
	 * @return void
330
	 */
331
	protected function _set_cache_time($enable_caching)
332
	{
333
		if ($enable_caching === false)
334
		{
335 21
			$this->cache_time = 0;
336
		}
337 21
	}
338 21
339 12
	/**
340 12
	 * @param int|array $column_id
341 21
	 * @param string $column
342
	 * @return void
343
	 */
344
	private function _fetch($column_id, $column)
345
	{
346
		if (!empty($column_id))
347 35
		{
348
			$this->store['sql_array']['WHERE'][] = (is_array($column_id)) ? $this->db->sql_in_set($column, $column_id) : $column . ' = ' . (int) $column_id;
349
		}
350 35
	}
351 35
352 35
	/**
353 35
	 * @param bool $check_visibility
354 35
	 * @return void
355
	 */
356
	private function _set_topic_visibility($check_visibility)
357
	{
358
		if ($check_visibility)
359
		{
360 35
			$this->store['sql_array']['WHERE'][] = $this->content_visibility->get_global_visibility_sql('topic', array_map('intval', $this->ex_fid_ary), 't.');
361
		}
362
	}
363 35
364 22
	/**
365 22
	 * @param bool $exclude_hidden_forums
366 22
	 * @return void
367
	 */
368 35
	private function _set_forum_table($exclude_hidden_forums)
369 35
	{
370 33
		if ($exclude_hidden_forums)
371 33
		{
372 35
			$this->store['sql_array']['FROM'][FORUMS_TABLE] = 'f';
373
			$this->store['sql_array']['WHERE'][] = 'f.hidden_forum = 0';
374
		}
375
376
		if (isset($this->store['sql_array']['FROM'][FORUMS_TABLE]))
377
		{
378 35
			$this->store['sql_array']['WHERE'][] = 'f.forum_id = t.forum_id';
379
		}
380 35
	}
381 35
382 35
	/**
383 35
	 * Reset data
384 35
	 * @return void
385 35
	 */
386 35
	private function _reset()
387
	{
388 35
		$this->store = array(
389
			'attachments'	=> array(),
390
			'post_ids'		=> array(),
391
			'poster_ids'	=> array(),
392
			'sql_array'		=> array(),
393
			'topic'			=> array(),
394
			'tracking'		=> array(),
395
		);
396
	}
397
}
398