|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* This file has functions in it to handle merging of two or more topics |
|
5
|
|
|
* |
|
6
|
|
|
* @name ElkArte Forum |
|
7
|
|
|
* @copyright ElkArte Forum contributors |
|
8
|
|
|
* @license BSD http://opensource.org/licenses/BSD-3-Clause |
|
9
|
|
|
* |
|
10
|
|
|
* This file contains code covered by: |
|
11
|
|
|
* copyright: 2011 Simple Machines (http://www.simplemachines.org) |
|
12
|
|
|
* license: BSD, See included LICENSE.TXT for terms and conditions. |
|
13
|
|
|
* |
|
14
|
|
|
* @version 1.1 |
|
15
|
|
|
* |
|
16
|
|
|
*/ |
|
17
|
|
|
|
|
18
|
|
|
/** |
|
19
|
|
|
* This class has functions to handle merging of two or more topics |
|
20
|
|
|
* in to a single new or existing topic. |
|
21
|
|
|
* |
|
22
|
|
|
* Class TopicsMerge |
|
23
|
|
|
*/ |
|
24
|
|
|
class TopicsMerge |
|
25
|
|
|
{ |
|
26
|
|
|
/** |
|
27
|
|
|
* For each topic a set of information (id, board, subject, poll, etc.) |
|
28
|
|
|
* |
|
29
|
|
|
* @var mixed[] |
|
30
|
|
|
*/ |
|
31
|
|
|
public $topic_data = array(); |
|
32
|
|
|
|
|
33
|
|
|
/** |
|
34
|
|
|
* All the boards the topics are in |
|
35
|
|
|
* |
|
36
|
|
|
* @var int[] |
|
37
|
|
|
*/ |
|
38
|
|
|
public $boards = array(); |
|
39
|
|
|
|
|
40
|
|
|
/** |
|
41
|
|
|
* The id_topic with the lowest id_first_msg |
|
42
|
|
|
* |
|
43
|
|
|
* @var int |
|
44
|
|
|
*/ |
|
45
|
|
|
public $firstTopic = 0; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* The id_board of the topic TopicsMerge::$firstTopic |
|
49
|
|
|
* |
|
50
|
|
|
* @var int |
|
51
|
|
|
*/ |
|
52
|
|
|
public $firstBoard = 0; |
|
53
|
|
|
|
|
54
|
|
|
/** |
|
55
|
|
|
* Just the array of topics to merge. |
|
56
|
|
|
* |
|
57
|
|
|
* @var int[] |
|
58
|
|
|
*/ |
|
59
|
|
|
private $_topics = array(); |
|
60
|
|
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* Sum of the number of views of each topic. |
|
63
|
|
|
* |
|
64
|
|
|
* @var int |
|
65
|
|
|
*/ |
|
66
|
|
|
private $_num_views = 0; |
|
67
|
|
|
|
|
68
|
|
|
/** |
|
69
|
|
|
* If at least one of the topics is sticky |
|
70
|
|
|
* |
|
71
|
|
|
* @var int |
|
72
|
|
|
*/ |
|
73
|
|
|
private $_is_sticky = 0; |
|
74
|
|
|
|
|
75
|
|
|
/** |
|
76
|
|
|
* An array of "totals" (number of topics/messages, unapproved, etc.) for |
|
77
|
|
|
* each board involved |
|
78
|
|
|
* |
|
79
|
|
|
* @var mixed[] |
|
80
|
|
|
*/ |
|
81
|
|
|
private $_boardTotals = array(); |
|
82
|
|
|
|
|
83
|
|
|
/** |
|
84
|
|
|
* If any topic has a poll, the array of poll id |
|
85
|
|
|
* |
|
86
|
|
|
* @var int[] |
|
87
|
|
|
*/ |
|
88
|
|
|
private $_polls = array(); |
|
89
|
|
|
|
|
90
|
|
|
/** |
|
91
|
|
|
* List of errors occurred |
|
92
|
|
|
* |
|
93
|
|
|
* @var string[] |
|
94
|
|
|
*/ |
|
95
|
|
|
private $_errors = array(); |
|
96
|
|
|
|
|
97
|
|
|
/** |
|
98
|
|
|
* The database object |
|
99
|
|
|
* |
|
100
|
|
|
* @var object |
|
101
|
|
|
*/ |
|
102
|
|
|
private $_db = null; |
|
103
|
|
|
|
|
104
|
|
|
/** |
|
105
|
|
|
* Initialize the class with a list of topics to merge |
|
106
|
|
|
* |
|
107
|
|
|
* @param int[] $topics array of topics to merge into one |
|
108
|
|
|
*/ |
|
109
|
|
|
public function __construct($topics) |
|
110
|
|
|
{ |
|
111
|
|
|
// Prepare the vars |
|
112
|
|
|
$this->_db = database(); |
|
113
|
|
|
|
|
114
|
|
|
// Ensure all the id's are integers |
|
115
|
|
|
$topics = array_map('intval', $topics); |
|
116
|
|
|
$this->_topics = array_filter($topics); |
|
117
|
|
|
|
|
118
|
|
|
// Find out some preliminary information |
|
119
|
|
|
$this->_loadTopicDetails(); |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* If errors occurred while working |
|
124
|
|
|
* |
|
125
|
|
|
* @return bool |
|
126
|
|
|
*/ |
|
127
|
|
|
public function hasErrors() |
|
128
|
|
|
{ |
|
129
|
|
|
return !empty($this->_errors); |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
/** |
|
133
|
|
|
* The first error occurred |
|
134
|
|
|
* |
|
135
|
|
|
* @return array|string |
|
136
|
|
|
*/ |
|
137
|
|
|
public function firstError() |
|
138
|
|
|
{ |
|
139
|
|
|
if (!empty($this->_errors)) |
|
140
|
|
|
{ |
|
141
|
|
|
$errors = array_values($this->_errors); |
|
142
|
|
|
|
|
143
|
|
|
return array_shift($errors); |
|
144
|
|
|
} |
|
145
|
|
|
else |
|
146
|
|
|
{ |
|
147
|
|
|
return ''; |
|
148
|
|
|
} |
|
149
|
|
|
} |
|
150
|
|
|
|
|
151
|
|
|
/** |
|
152
|
|
|
* Returns the polls information if any of the topics has a poll. |
|
153
|
|
|
* |
|
154
|
|
|
* @return mixed[] |
|
155
|
|
|
*/ |
|
156
|
|
|
public function getPolls() |
|
157
|
|
|
{ |
|
158
|
|
|
$polls = array(); |
|
159
|
|
|
|
|
160
|
|
|
if (count($this->_polls) > 1) |
|
161
|
|
|
{ |
|
162
|
|
|
$request = $this->_db->query('', ' |
|
163
|
|
|
SELECT |
|
164
|
|
|
t.id_topic, t.id_poll, m.subject, p.question |
|
165
|
|
|
FROM {db_prefix}polls AS p |
|
166
|
|
|
INNER JOIN {db_prefix}topics AS t ON (t.id_poll = p.id_poll) |
|
167
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) |
|
168
|
|
|
WHERE p.id_poll IN ({array_int:polls}) |
|
169
|
|
|
LIMIT {int:limit}', |
|
170
|
|
|
array( |
|
171
|
|
|
'polls' => $this->_polls, |
|
172
|
|
|
'limit' => count($this->_polls), |
|
173
|
|
|
) |
|
174
|
|
|
); |
|
175
|
|
|
while ($row = $this->_db->fetch_assoc($request)) |
|
176
|
|
|
{ |
|
177
|
|
|
$polls[] = array( |
|
178
|
|
|
'id' => $row['id_poll'], |
|
179
|
|
|
'topic' => array( |
|
180
|
|
|
'id' => $row['id_topic'], |
|
181
|
|
|
'subject' => $row['subject'] |
|
182
|
|
|
), |
|
183
|
|
|
'question' => $row['question'], |
|
184
|
|
|
'selected' => $row['id_topic'] == $this->firstTopic |
|
185
|
|
|
); |
|
186
|
|
|
} |
|
187
|
|
|
$this->_db->free_result($request); |
|
188
|
|
|
} |
|
189
|
|
|
|
|
190
|
|
|
return $polls; |
|
191
|
|
|
} |
|
192
|
|
|
|
|
193
|
|
|
/** |
|
194
|
|
|
* Performs the merge operations |
|
195
|
|
|
* |
|
196
|
|
|
* @param mixed[] $details |
|
197
|
|
|
* @return bool|int[] |
|
198
|
|
|
* @throws Elk_Exception |
|
199
|
|
|
*/ |
|
200
|
|
|
public function doMerge($details = array()) |
|
201
|
|
|
{ |
|
202
|
|
|
// Just to be sure, here we should not have any error around |
|
203
|
|
|
$this->_errors = array(); |
|
204
|
|
|
|
|
205
|
|
|
// Determine target board. |
|
206
|
|
|
$target_board = count($this->boards) > 1 ? (int) $details['board'] : $this->boards[0]; |
|
207
|
|
|
if (!in_array($target_board, $details['accessible_boards'])) |
|
208
|
|
|
{ |
|
209
|
|
|
$this->_errors[] = array('no_board', true); |
|
210
|
|
|
return false; |
|
211
|
|
|
} |
|
212
|
|
|
|
|
213
|
|
|
// Determine which poll will survive and which polls won't. |
|
214
|
|
|
$target_poll = count($this->_polls) > 1 ? (int) $details['poll'] : (count($this->_polls) == 1 ? $this->_polls[0] : 0); |
|
215
|
|
|
if ($target_poll > 0 && !in_array($target_poll, $this->_polls)) |
|
216
|
|
|
{ |
|
217
|
|
|
$this->_errors[] = array('no_access', false); |
|
218
|
|
|
return false; |
|
219
|
|
|
} |
|
220
|
|
|
|
|
221
|
|
|
$deleted_polls = empty($target_poll) ? $this->_polls : array_diff($this->_polls, array($target_poll)); |
|
222
|
|
|
|
|
223
|
|
|
// Determine the subject of the newly merged topic - was a custom subject specified? |
|
224
|
|
|
if (empty($details['subject']) && $details['custom_subject'] != '') |
|
225
|
|
|
{ |
|
226
|
|
|
$target_subject = strtr(Util::htmltrim(Util::htmlspecialchars($details['custom_subject'])), array("\r" => '', "\n" => '', "\t" => '')); |
|
227
|
|
|
|
|
228
|
|
|
// Keep checking the length. |
|
229
|
|
|
if (Util::strlen($target_subject) > 100) |
|
230
|
|
|
$target_subject = Util::substr($target_subject, 0, 100); |
|
231
|
|
|
|
|
232
|
|
|
// Nothing left - odd but pick the first topics subject. |
|
233
|
|
|
if ($target_subject == '') |
|
234
|
|
|
$target_subject = $this->topic_data[$this->firstTopic]['subject']; |
|
235
|
|
|
} |
|
236
|
|
|
// A subject was selected from the list. |
|
237
|
|
|
elseif (!empty($this->topic_data[(int) $details['subject']]['subject'])) |
|
238
|
|
|
$target_subject = $this->topic_data[(int) $details['subject']]['subject']; |
|
239
|
|
|
// Nothing worked? Just take the subject of the first message. |
|
240
|
|
|
else |
|
241
|
|
|
$target_subject = $this->topic_data[$this->firstTopic]['subject']; |
|
242
|
|
|
|
|
243
|
|
|
// Get the first and last message and the number of messages.... |
|
244
|
|
|
$request = $this->_db->query('', ' |
|
245
|
|
|
SELECT |
|
246
|
|
|
approved, MIN(id_msg) AS first_msg, MAX(id_msg) AS last_msg, COUNT(*) AS message_count |
|
247
|
|
|
FROM {db_prefix}messages |
|
248
|
|
|
WHERE id_topic IN ({array_int:topics}) |
|
249
|
|
|
GROUP BY approved |
|
250
|
|
|
ORDER BY approved DESC', |
|
251
|
|
|
array( |
|
252
|
|
|
'topics' => $this->_topics, |
|
253
|
|
|
) |
|
254
|
|
|
); |
|
255
|
|
|
$topic_approved = 1; |
|
256
|
|
|
$first_msg = 0; |
|
257
|
|
|
$num_replies = 0; |
|
258
|
|
|
while ($row = $this->_db->fetch_assoc($request)) |
|
259
|
|
|
{ |
|
260
|
|
|
// If this is approved, or is fully unapproved. |
|
261
|
|
|
if ($row['approved'] || !isset($first_msg)) |
|
262
|
|
|
{ |
|
263
|
|
|
$first_msg = $row['first_msg']; |
|
264
|
|
|
$last_msg = $row['last_msg']; |
|
265
|
|
|
if ($row['approved']) |
|
266
|
|
|
{ |
|
267
|
|
|
$num_replies = $row['message_count'] - 1; |
|
268
|
|
|
$num_unapproved = 0; |
|
269
|
|
|
} |
|
270
|
|
|
else |
|
271
|
|
|
{ |
|
272
|
|
|
$topic_approved = 0; |
|
273
|
|
|
$num_replies = 0; |
|
274
|
|
|
$num_unapproved = $row['message_count']; |
|
275
|
|
|
} |
|
276
|
|
|
} |
|
277
|
|
|
else |
|
278
|
|
|
{ |
|
279
|
|
|
// If this has a lower first_msg then the first post is not approved and hence the number of replies was wrong! |
|
280
|
|
|
if ($first_msg > $row['first_msg']) |
|
281
|
|
|
{ |
|
282
|
|
|
$first_msg = $row['first_msg']; |
|
283
|
|
|
$num_replies++; |
|
284
|
|
|
$topic_approved = 0; |
|
285
|
|
|
} |
|
286
|
|
|
$num_unapproved = $row['message_count']; |
|
287
|
|
|
} |
|
288
|
|
|
} |
|
289
|
|
|
$this->_db->free_result($request); |
|
290
|
|
|
|
|
291
|
|
|
// Ensure we have a board stat for the target board. |
|
292
|
|
View Code Duplication |
if (!isset($this->_boardTotals[$target_board])) |
|
293
|
|
|
{ |
|
294
|
|
|
$this->_boardTotals[$target_board] = array( |
|
295
|
|
|
'num_posts' => 0, |
|
296
|
|
|
'num_topics' => 0, |
|
297
|
|
|
'unapproved_posts' => 0, |
|
298
|
|
|
'unapproved_topics' => 0 |
|
299
|
|
|
); |
|
300
|
|
|
} |
|
301
|
|
|
|
|
302
|
|
|
// Fix the topic count stuff depending on what the new one counts as. |
|
303
|
|
|
if ($topic_approved) |
|
304
|
|
|
$this->_boardTotals[$target_board]['num_topics']--; |
|
305
|
|
|
else |
|
306
|
|
|
$this->_boardTotals[$target_board]['unapproved_topics']--; |
|
307
|
|
|
|
|
308
|
|
|
$this->_boardTotals[$target_board]['unapproved_posts'] -= $num_unapproved; |
|
|
|
|
|
|
309
|
|
|
$this->_boardTotals[$target_board]['num_posts'] -= $topic_approved ? $num_replies + 1 : $num_replies; |
|
310
|
|
|
|
|
311
|
|
|
// Get the member ID of the first and last message. |
|
312
|
|
|
$request = $this->_db->query('', ' |
|
313
|
|
|
SELECT |
|
314
|
|
|
id_member |
|
315
|
|
|
FROM {db_prefix}messages |
|
316
|
|
|
WHERE id_msg IN ({int:first_msg}, {int:last_msg}) |
|
317
|
|
|
ORDER BY id_msg |
|
318
|
|
|
LIMIT 2', |
|
319
|
|
|
array( |
|
320
|
|
|
'first_msg' => $first_msg, |
|
321
|
|
|
'last_msg' => $last_msg, |
|
|
|
|
|
|
322
|
|
|
) |
|
323
|
|
|
); |
|
324
|
|
|
list ($member_started) = $this->_db->fetch_row($request); |
|
325
|
|
|
list ($member_updated) = $this->_db->fetch_row($request); |
|
326
|
|
|
|
|
327
|
|
|
// First and last message are the same, so only row was returned. |
|
328
|
|
|
if ($member_updated === null) |
|
329
|
|
|
$member_updated = $member_started; |
|
330
|
|
|
|
|
331
|
|
|
$this->_db->free_result($request); |
|
332
|
|
|
|
|
333
|
|
|
// Obtain all the message ids we are going to affect. |
|
334
|
|
|
$affected_msgs = messagesInTopics($this->_topics); |
|
335
|
|
|
|
|
336
|
|
|
// Assign the first topic ID to be the merged topic. |
|
337
|
|
|
$id_topic = min($this->_topics); |
|
338
|
|
|
|
|
339
|
|
|
$enforce_subject = Util::htmlspecialchars(trim($details['enforce_subject'])); |
|
340
|
|
|
|
|
341
|
|
|
// Merge topic notifications. |
|
342
|
|
|
$notifications = is_array($details['notifications']) ? array_intersect($this->_topics, $details['notifications']) : array(); |
|
343
|
|
|
fixMergedTopics($first_msg, $this->_topics, $id_topic, $target_board, $target_subject, $enforce_subject, $notifications); |
|
344
|
|
|
|
|
345
|
|
|
// Assign the properties of the newly merged topic. |
|
346
|
|
|
setTopicAttribute($id_topic, array( |
|
347
|
|
|
'id_board' => $target_board, |
|
348
|
|
|
'is_sticky' => $this->_is_sticky, |
|
349
|
|
|
'approved' => $topic_approved, |
|
350
|
|
|
'id_member_started' => $member_started, |
|
351
|
|
|
'id_member_updated' => $member_updated, |
|
352
|
|
|
'id_first_msg' => $first_msg, |
|
353
|
|
|
'id_last_msg' => $last_msg, |
|
354
|
|
|
'id_poll' => $target_poll, |
|
355
|
|
|
'num_replies' => $num_replies, |
|
356
|
|
|
'unapproved_posts' => $num_unapproved, |
|
357
|
|
|
'num_views' => $this->_num_views, |
|
358
|
|
|
)); |
|
359
|
|
|
|
|
360
|
|
|
// Get rid of the redundant polls. |
|
361
|
|
|
if (!empty($deleted_polls)) |
|
362
|
|
|
{ |
|
363
|
|
|
require_once(SUBSDIR . '/Poll.subs.php'); |
|
364
|
|
|
removePoll($deleted_polls); |
|
365
|
|
|
} |
|
366
|
|
|
|
|
367
|
|
|
$this->_updateStats($affected_msgs, $id_topic, $target_subject, $enforce_subject); |
|
|
|
|
|
|
368
|
|
|
|
|
369
|
|
|
return array($id_topic, $target_board); |
|
370
|
|
|
} |
|
371
|
|
|
|
|
372
|
|
|
/** |
|
373
|
|
|
* Takes care of updating all the relevant statistics |
|
374
|
|
|
* |
|
375
|
|
|
* @param int[] $affected_msgs |
|
376
|
|
|
* @param int $id_topic |
|
377
|
|
|
* @param string $target_subject |
|
378
|
|
|
* @param bool $enforce_subject |
|
379
|
|
|
* @throws Elk_Exception |
|
380
|
|
|
*/ |
|
381
|
|
|
protected function _updateStats($affected_msgs, $id_topic, $target_subject, $enforce_subject) |
|
382
|
|
|
{ |
|
383
|
|
|
// Cycle through each board... |
|
384
|
|
|
foreach ($this->_boardTotals as $id_board => $stats) |
|
385
|
|
|
decrementBoard($id_board, $stats); |
|
386
|
|
|
|
|
387
|
|
|
// Determine the board the final topic resides in |
|
388
|
|
|
$topic_info = getTopicInfo($id_topic); |
|
389
|
|
|
$id_board = $topic_info['id_board']; |
|
390
|
|
|
|
|
391
|
|
|
// Update all the statistics. |
|
392
|
|
|
require_once(SUBSDIR . '/Topic.subs.php'); |
|
393
|
|
|
updateTopicStats(); |
|
394
|
|
|
|
|
395
|
|
|
require_once(SUBSDIR . '/Messages.subs.php'); |
|
396
|
|
|
updateSubjectStats($id_topic, $target_subject); |
|
397
|
|
|
updateLastMessages($this->boards); |
|
398
|
|
|
|
|
399
|
|
|
logAction('merge', array('topic' => $id_topic, 'board' => $id_board)); |
|
400
|
|
|
|
|
401
|
|
|
// Notify people that these topics have been merged? |
|
402
|
|
|
require_once(SUBSDIR . '/Notification.subs.php'); |
|
403
|
|
|
sendNotifications($id_topic, 'merge'); |
|
404
|
|
|
|
|
405
|
|
|
// Grab the response prefix (like 'Re: ') in the default forum language. |
|
406
|
|
|
$response_prefix = response_prefix(); |
|
407
|
|
|
|
|
408
|
|
|
// If there's a search index that needs updating, update it... |
|
409
|
|
|
$search = new \ElkArte\Search\Search; |
|
410
|
|
|
$searchAPI = $search->findSearchAPI(); |
|
411
|
|
|
if (is_callable(array($searchAPI, 'topicMerge'))) |
|
412
|
|
|
$searchAPI->topicMerge($id_topic, $this->_topics, $affected_msgs, empty($enforce_subject) ? null : array($response_prefix, $target_subject)); |
|
413
|
|
|
} |
|
414
|
|
|
|
|
415
|
|
|
/** |
|
416
|
|
|
* Grabs all the details of the topics involved in the merge process and loads |
|
417
|
|
|
* then in $this->topic_data |
|
418
|
|
|
*/ |
|
419
|
|
|
protected function _loadTopicDetails() |
|
420
|
|
|
{ |
|
421
|
|
|
global $scripturl, $modSettings, $user_info; |
|
422
|
|
|
|
|
423
|
|
|
// Joy of all joys, make sure they're not pi**ing about with unapproved topics they can't see :P |
|
424
|
|
|
if ($modSettings['postmod_active']) |
|
425
|
|
|
$can_approve_boards = !empty($user_info['mod_cache']['ap']) ? $user_info['mod_cache']['ap'] : boardsAllowedTo('approve_posts'); |
|
426
|
|
|
|
|
427
|
|
|
// Get info about the topics and polls that will be merged. |
|
428
|
|
|
$request = $this->_db->query('', ' |
|
429
|
|
|
SELECT |
|
430
|
|
|
t.id_topic, t.id_board, b.id_cat, t.id_poll, t.num_views, t.is_sticky, t.approved, t.num_replies, t.unapproved_posts, |
|
431
|
|
|
m1.subject, m1.poster_time AS time_started, COALESCE(mem1.id_member, 0) AS id_member_started, COALESCE(mem1.real_name, m1.poster_name) AS name_started, |
|
432
|
|
|
m2.poster_time AS time_updated, COALESCE(mem2.id_member, 0) AS id_member_updated, COALESCE(mem2.real_name, m2.poster_name) AS name_updated |
|
433
|
|
|
FROM {db_prefix}topics AS t |
|
434
|
|
|
INNER JOIN {db_prefix}messages AS m1 ON (m1.id_msg = t.id_first_msg) |
|
435
|
|
|
INNER JOIN {db_prefix}messages AS m2 ON (m2.id_msg = t.id_last_msg) |
|
436
|
|
|
LEFT JOIN {db_prefix}members AS mem1 ON (mem1.id_member = m1.id_member) |
|
437
|
|
|
LEFT JOIN {db_prefix}members AS mem2 ON (mem2.id_member = m2.id_member) |
|
438
|
|
|
LEFT JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) |
|
439
|
|
|
WHERE t.id_topic IN ({array_int:topic_list}) |
|
440
|
|
|
ORDER BY t.id_first_msg |
|
441
|
|
|
LIMIT {int:limit}', |
|
442
|
|
|
array( |
|
443
|
|
|
'topic_list' => $this->_topics, |
|
444
|
|
|
'limit' => count($this->_topics), |
|
445
|
|
|
) |
|
446
|
|
|
); |
|
447
|
|
|
if ($this->_db->num_rows($request) < 2) |
|
448
|
|
|
{ |
|
449
|
|
|
$this->_db->free_result($request); |
|
450
|
|
|
|
|
451
|
|
|
$this->_errors[] = array('no_topic_id', true); |
|
452
|
|
|
|
|
453
|
|
|
return false; |
|
454
|
|
|
} |
|
455
|
|
|
while ($row = $this->_db->fetch_assoc($request)) |
|
456
|
|
|
{ |
|
457
|
|
|
// Make a note for the board counts... |
|
458
|
|
View Code Duplication |
if (!isset($this->_boardTotals[$row['id_board']])) |
|
459
|
|
|
{ |
|
460
|
|
|
$this->_boardTotals[$row['id_board']] = array( |
|
461
|
|
|
'num_posts' => 0, |
|
462
|
|
|
'num_topics' => 0, |
|
463
|
|
|
'unapproved_posts' => 0, |
|
464
|
|
|
'unapproved_topics' => 0 |
|
465
|
|
|
); |
|
466
|
|
|
} |
|
467
|
|
|
|
|
468
|
|
|
// We can't see unapproved topics here? |
|
469
|
|
|
if ($modSettings['postmod_active'] && !$row['approved'] && $can_approve_boards != array(0) && in_array($row['id_board'], $can_approve_boards)) |
|
|
|
|
|
|
470
|
|
|
continue; |
|
471
|
|
|
elseif (!$row['approved']) |
|
472
|
|
|
$this->_boardTotals[$row['id_board']]['unapproved_topics']++; |
|
473
|
|
|
else |
|
474
|
|
|
$this->_boardTotals[$row['id_board']]['num_topics']++; |
|
475
|
|
|
|
|
476
|
|
|
$this->_boardTotals[$row['id_board']]['unapproved_posts'] += $row['unapproved_posts']; |
|
477
|
|
|
$this->_boardTotals[$row['id_board']]['num_posts'] += $row['num_replies'] + ($row['approved'] ? 1 : 0); |
|
478
|
|
|
|
|
479
|
|
|
$this->topic_data[$row['id_topic']] = array( |
|
480
|
|
|
'id' => $row['id_topic'], |
|
481
|
|
|
'board' => $row['id_board'], |
|
482
|
|
|
'poll' => $row['id_poll'], |
|
483
|
|
|
'num_views' => $row['num_views'], |
|
484
|
|
|
'subject' => $row['subject'], |
|
485
|
|
|
'started' => array( |
|
486
|
|
|
'time' => standardTime($row['time_started']), |
|
487
|
|
|
'html_time' => htmlTime($row['time_started']), |
|
488
|
|
|
'timestamp' => forum_time(true, $row['time_started']), |
|
489
|
|
|
'href' => empty($row['id_member_started']) ? '' : $scripturl . '?action=profile;u=' . $row['id_member_started'], |
|
490
|
|
|
'link' => empty($row['id_member_started']) ? $row['name_started'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member_started'] . '">' . $row['name_started'] . '</a>' |
|
491
|
|
|
), |
|
492
|
|
|
'updated' => array( |
|
493
|
|
|
'time' => standardTime($row['time_updated']), |
|
494
|
|
|
'html_time' => htmlTime($row['time_updated']), |
|
495
|
|
|
'timestamp' => forum_time(true, $row['time_updated']), |
|
496
|
|
|
'href' => empty($row['id_member_updated']) ? '' : $scripturl . '?action=profile;u=' . $row['id_member_updated'], |
|
497
|
|
|
'link' => empty($row['id_member_updated']) ? $row['name_updated'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member_updated'] . '">' . $row['name_updated'] . '</a>' |
|
498
|
|
|
) |
|
499
|
|
|
); |
|
500
|
|
|
$this->_num_views += $row['num_views']; |
|
501
|
|
|
$this->boards[] = $row['id_board']; |
|
502
|
|
|
|
|
503
|
|
|
// If there's no poll, id_poll == 0... |
|
504
|
|
|
if ($row['id_poll'] > 0) |
|
505
|
|
|
$this->_polls[] = $row['id_poll']; |
|
506
|
|
|
|
|
507
|
|
|
// Store the id_topic with the lowest id_first_msg. |
|
508
|
|
|
if (empty($this->firstTopic)) |
|
509
|
|
|
{ |
|
510
|
|
|
$this->firstTopic = $row['id_topic']; |
|
511
|
|
|
$this->firstBoard = $row['id_board']; |
|
512
|
|
|
} |
|
513
|
|
|
|
|
514
|
|
|
$this->_is_sticky = max($this->_is_sticky, $row['is_sticky']); |
|
515
|
|
|
} |
|
516
|
|
|
$this->_db->free_result($request); |
|
517
|
|
|
|
|
518
|
|
|
$this->boards = array_map('intval', array_values(array_unique($this->boards))); |
|
519
|
|
|
|
|
520
|
|
|
// If we didn't get any topics then they've been messing with unapproved stuff. |
|
521
|
|
|
if (empty($this->topic_data)) |
|
522
|
|
|
{ |
|
523
|
|
|
$this->_errors[] = array('no_topic_id', true); |
|
524
|
|
|
} |
|
525
|
|
|
|
|
526
|
|
|
return true; |
|
527
|
|
|
} |
|
528
|
|
|
} |
|
529
|
|
|
|
If you define a variable conditionally, it can happen that it is not defined for all execution paths.
Let’s take a look at an example:
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.
Available Fixes
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: