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: