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