Failed Conditions
Branch release-2.1 (4e22cf)
by Rick
06:39
created

RepairBoards.php ➔ findForumErrors()   F

Complexity

Conditions 48
Paths 336

Size

Total Lines 216
Code Lines 105

Duplication

Lines 4
Ratio 1.85 %

Importance

Changes 0
Metric Value
cc 48
eloc 105
nc 336
nop 1
dl 4
loc 216
rs 3.3333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This is here for the "repair any errors" feature in the admin center.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2017 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 4
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
/**
20
 * Finds or repairs errors in the database to fix possible problems.
21
 * Requires the admin_forum permission.
22
 * Calls createSalvageArea() to create a new board, if necessary.
23
 * Accessed by ?action=admin;area=repairboards.
24
 *
25
 * @uses repair_boards sub-template.
26
 */
27
function RepairBoards()
28
{
29
	global $txt, $context, $sourcedir, $salvageBoardID;
30
31
	isAllowedTo('admin_forum');
32
33
	// Try secure more memory.
34
	setMemoryLimit('128M');
35
36
	// Print out the top of the webpage.
37
	$context['page_title'] = $txt['admin_repair'];
38
	$context['sub_template'] = 'repair_boards';
39
	$context[$context['admin_menu_name']]['current_subsection'] = 'general';
40
41
	// Load the language file.
42
	loadLanguage('ManageMaintenance');
43
44
	// Make sure the tabs stay nice.
45
	$context[$context['admin_menu_name']]['tab_data'] = array(
46
		'title' => $txt['maintain_title'],
47
		'help' => '',
48
		'description' => $txt['maintain_info'],
49
		'tabs' => array(),
50
	);
51
52
	// Start displaying errors without fixing them.
53
	if (isset($_GET['fixErrors']))
54
		checkSession('get');
55
56
	// Will want this.
57
	loadForumTests();
58
59
	// Giant if/else. The first displays the forum errors if a variable is not set and asks
60
	// if you would like to continue, the other fixes the errors.
61
	if (!isset($_GET['fixErrors']))
62
	{
63
		$context['error_search'] = true;
64
		$context['repair_errors'] = array();
65
		$context['to_fix'] = findForumErrors();
66
67
		if (!empty($context['to_fix']))
68
		{
69
			$_SESSION['repairboards_to_fix'] = $context['to_fix'];
70
			$_SESSION['repairboards_to_fix2'] = null;
71
72
			if (empty($context['repair_errors']))
73
				$context['repair_errors'][] = '???';
74
		}
75
	}
76
	else
77
	{
78
		$context['error_search'] = false;
79
		$context['to_fix'] = isset($_SESSION['repairboards_to_fix']) ? $_SESSION['repairboards_to_fix'] : array();
80
81
		require_once($sourcedir . '/Subs-Boards.php');
82
83
		// Actually do the fix.
84
		findForumErrors(true);
85
86
		// Note that we've changed everything possible ;)
87
		updateSettings(array(
88
			'settings_updated' => time(),
89
		));
90
		updateStats('message');
91
		updateStats('topic');
92
		updateSettings(array(
93
			'calendar_updated' => time(),
94
		));
95
96
		if (!empty($salvageBoardID))
97
		{
98
			$context['redirect_to_recount'] = true;
99
		}
100
101
		$_SESSION['repairboards_to_fix'] = null;
102
		$_SESSION['repairboards_to_fix2'] = null;
103
	}
104
}
105
106
/**
107
 * Show the not_done template to avoid CGI timeouts and similar.
108
 * Called when 3 or more seconds have passed while searching for errors.
109
 * If max_substep is set, $_GET['substep'] / $max_substep is the percent
110
 * done this step is.
111
 *
112
 * @param array $to_fix An array of information about what to fix
113
 * @param string $current_step_description The description of the current step
114
 * @param int $max_substep The maximum substep to reach before pausing
115
 * @param bool $force Whether to force pausing even if we don't really need to
116
 */
117
function pauseRepairProcess($to_fix, $current_step_description, $max_substep = 0, $force = false)
118
{
119
	global $context, $txt, $time_start, $db_temp_cache, $db_cache;
120
121
	// More time, I need more time!
122
	@set_time_limit(600);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
123
	if (function_exists('apache_reset_timeout'))
124
		@apache_reset_timeout();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
125
126
	// Errr, wait.  How much time has this taken already?
127
	if (!$force && time() - array_sum(explode(' ', $time_start)) < 3)
128
		return;
129
130
	// Restore the query cache if interested.
131
	if (!empty($db_temp_cache))
132
		$db_cache = $db_temp_cache;
133
134
	$context['continue_get_data'] = '?action=admin;area=repairboards' . (isset($_GET['fixErrors']) ? ';fixErrors' : '') . ';step=' . $_GET['step'] . ';substep=' . $_GET['substep'] . ';' . $context['session_var'] . '=' . $context['session_id'];
135
	$context['page_title'] = $txt['not_done_title'];
136
	$context['continue_post_data'] = '';
137
	$context['continue_countdown'] = '2';
138
	$context['sub_template'] = 'not_done';
139
140
	// Change these two if more steps are added!
141
	if (empty($max_substep))
142
		$context['continue_percent'] = round(($_GET['step'] * 100) / $context['total_steps']);
143 View Code Duplication
	else
144
		$context['continue_percent'] = round((($_GET['step'] + ($_GET['substep'] / $max_substep)) * 100) / $context['total_steps']);
145
146
	// Never more than 100%!
147
	$context['continue_percent'] = min($context['continue_percent'], 100);
148
149
	// What about substeps?
150
	$context['substep_enabled'] = $max_substep != 0;
151
	$context['substep_title'] = sprintf($txt['repair_currently_' . (isset($_GET['fixErrors']) ? 'fixing' : 'checking')], (isset($txt['repair_operation_' . $current_step_description]) ? $txt['repair_operation_' . $current_step_description] : $current_step_description));
152
	$context['substep_continue_percent'] = $max_substep == 0 ? 0 : round(($_GET['substep'] * 100) / $max_substep, 1);
153
154
	$_SESSION['repairboards_to_fix'] = $to_fix;
155
	$_SESSION['repairboards_to_fix2'] = $context['repair_errors'];
156
157
	obExit();
158
}
159
160
/**
161
 * Load up all the tests we might want to do ;)
162
 */
163
function loadForumTests()
164
{
165
	global $errorTests, $smcFunc, $txt, $context;
166
167
	/* Here this array is defined like so:
168
		string check_query:	Query to be executed when testing if errors exist.
169
		string check_type:	Defines how it knows if a problem was found. If set to count looks for the first variable from check_query
170
					being > 0. Anything else it looks for some results. If not set assumes you want results.
171
		string fix_it_query:	When doing fixes if an error was detected this query is executed to "fix" it.
172
		string fix_query:	The query to execute to get data when doing a fix. If not set check_query is used again.
173
		array fix_collect:	This array is used if the fix is basically gathering all broken ids and then doing something with it.
174
			- string index:		The value returned from the main query and passed to the processing function.
175
			- process:		A function passed an array of ids to execute the fix on.
176
		function fix_processing:
177
					Function called for each row returned from fix_query to execute whatever fixes are required.
178
		function fix_full_processing:
179
					As above but does the while loop and everything itself - except the freeing.
180
		array force_fix:	If this is set then the error types included within this array will also be assumed broken.
181
					Note: At the moment only processes these if they occur after the primary error in the array.
182
	*/
183
184
	// This great array contains all of our error checks, fixes, etc etc etc.
185
	$errorTests = array(
186
		// Make a last-ditch-effort check to get rid of topics with zeros..
187
		'zero_topics' => array(
188
			'check_query' => '
189
				SELECT COUNT(*)
190
				FROM {db_prefix}topics
191
				WHERE id_topic = 0',
192
			'check_type' => 'count',
193
			'fix_it_query' => '
194
				UPDATE {db_prefix}topics
195
				SET id_topic = NULL
196
				WHERE id_topic = 0',
197
			'message' => 'repair_zero_ids',
198
		),
199
		// ... and same with messages.
200
		'zero_messages' => array(
201
			'check_query' => '
202
				SELECT COUNT(*)
203
				FROM {db_prefix}messages
204
				WHERE id_msg = 0',
205
			'check_type' => 'count',
206
			'fix_it_query' => '
207
				UPDATE {db_prefix}messages
208
				SET id_msg = NULL
209
				WHERE id_msg = 0',
210
			'message' => 'repair_zero_ids',
211
		),
212
		// Find messages that don't have existing topics.
213
		'missing_topics' => array(
214
			'substeps' => array(
215
				'step_size' => 1000,
216
				'step_max' => '
217
					SELECT MAX(id_topic)
218
					FROM {db_prefix}messages'
219
			),
220
			'check_query' => '
221
				SELECT m.id_topic, m.id_msg
222
				FROM {db_prefix}messages AS m
223
					LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
224
				WHERE m.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH}
225
					AND t.id_topic IS NULL
226
				ORDER BY m.id_topic, m.id_msg',
227
			'fix_query' => '
228
				SELECT
229
					m.id_board, m.id_topic, MIN(m.id_msg) AS myid_first_msg, MAX(m.id_msg) AS myid_last_msg,
230
					COUNT(*) - 1 AS my_num_replies
231
				FROM {db_prefix}messages AS m
232
					LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
233
				WHERE t.id_topic IS NULL
234
				GROUP BY m.id_topic, m.id_board',
235
			'fix_processing' => function ($row) use ($smcFunc)
236
			{
237
				global $salvageBoardID;
238
239
				// Only if we don't have a reasonable idea of where to put it.
240
				if ($row['id_board'] == 0)
241
				{
242
					createSalvageArea();
243
					$row['id_board'] = (int) $salvageBoardID;
244
				}
245
246
				// Make sure that no topics claim the first/last message as theirs.
247
				$smcFunc['db_query']('', '
248
					UPDATE {db_prefix}topics
249
					SET id_first_msg = 0
250
					WHERE id_first_msg = {int:id_first_msg}',
251
					array(
252
						'id_first_msg' => $row['myid_first_msg'],
253
					)
254
				);
255
				$smcFunc['db_query']('', '
256
					UPDATE {db_prefix}topics
257
					SET id_last_msg = 0
258
					WHERE id_last_msg = {int:id_last_msg}',
259
					array(
260
						'id_last_msg' => $row['myid_last_msg'],
261
					)
262
				);
263
264
				$memberStartedID = (int) getMsgMemberID($row['myid_first_msg']);
265
				$memberUpdatedID = (int) getMsgMemberID($row['myid_last_msg']);
266
267
				$newTopicID = $smcFunc['db_insert']('',
268
					'{db_prefix}topics',
269
					array(
270
						'id_board' => 'int',
271
						'id_member_started' => 'int',
272
						'id_member_updated' => 'int',
273
						'id_first_msg' => 'int',
274
						'id_last_msg' => 'int',
275
						'num_replies' => 'int'
276
					),
277
					array(
278
						$row['id_board'],
279
						$memberStartedID,
280
						$memberUpdatedID,
281
						$row['myid_first_msg'],
282
						$row['myid_last_msg'],
283
						$row['my_num_replies']
284
					),
285
					array('id_topic'),
286
					1
287
				);
288
289
				$smcFunc['db_query']('', '
290
					UPDATE {db_prefix}messages
291
					SET id_topic = {int:newTopicID}, id_board = {int:board_id}
292
					WHERE id_topic = {int:topic_id}',
293
					array(
294
						'board_id' => $row['id_board'],
295
						'topic_id' => $row['id_topic'],
296
						'newTopicID' => $newTopicID,
297
					)
298
				);
299
			},
300
			'force_fix' => array('stats_topics'),
301
			'messages' => array('repair_missing_topics', 'id_msg', 'id_topic'),
302
		),
303
		// Find topics with no messages.
304
		'missing_messages' => array(
305
			'substeps' => array(
306
				'step_size' => 1000,
307
				'step_max' => '
308
					SELECT MAX(id_topic)
309
					FROM {db_prefix}topics'
310
			),
311
			'check_query' => '
312
				SELECT t.id_topic, COUNT(m.id_msg) AS num_msg
313
				FROM {db_prefix}topics AS t
314
					LEFT JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic)
315
				WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH}
316
				GROUP BY t.id_topic
317
				HAVING COUNT(m.id_msg) = 0',
318
			// Remove all topics that have zero messages in the messages table.
319
			'fix_collect' => array(
320
				'index' => 'id_topic',
321
				'process' => function ($topics) use ($smcFunc)
322
				{
323
					$smcFunc['db_query']('', '
324
						DELETE FROM {db_prefix}topics
325
						WHERE id_topic IN ({array_int:topics})',
326
						array(
327
							'topics' => $topics,
328
						)
329
					);
330
					$smcFunc['db_query']('', '
331
						DELETE FROM {db_prefix}log_topics
332
						WHERE id_topic IN ({array_int:topics})',
333
						array(
334
							'topics' => $topics,
335
						)
336
					);
337
338
				},
339
			),
340
			'messages' => array('repair_missing_messages', 'id_topic'),
341
		),
342
		'poll_options_missing_poll' => array(
343
			'substeps' => array(
344
				'step_size' => 500,
345
				'step_max' => '
346
					SELECT MAX(id_poll)
347
					FROM {db_prefix}poll_choices'
348
			),
349
			'check_query' => '
350
				SELECT o.id_poll, count(*) as amount, t.id_topic, t.id_board, t.id_member_started AS id_poster, m.member_name AS poster_name
351
				FROM {db_prefix}poll_choices AS o
352
				  LEFT JOIN {db_prefix}polls AS p ON (p.id_poll = o.id_poll)
353
				  LEFT JOIN {db_prefix}topics AS t ON (t.id_poll = o.id_poll)
354
				  LEFT JOIN {db_prefix}members AS m ON (m.id_member = t.id_member_started)
355
				WHERE o.id_poll BETWEEN {STEP_LOW} AND {STEP_HIGH}
356
				  AND p.id_poll IS NULL
357
				GROUP BY o.id_poll
358
				  ',
359
			'fix_processing' => function ($row) use ($smcFunc, $txt)
360
			{
361
				global $salvageBoardID;
362
363
				$row['poster_name'] = !empty($row['poster_name']) ? $row['poster_name'] : $txt['guest'];
364
				$row['id_poster'] = !empty($row['id_poster']) ? $row['id_poster'] : 0;
365
366
				if(empty($row['id_board']))
367
				{
368
					// Only if we don't have a reasonable idea of where to put it.
369
					createSalvageArea();
370
					$row['id_board'] = (int)$salvageBoardID;
371
				}
372
373
				if(empty($row['id_topic'])) {
374
					$newMessageID = $smcFunc['db_insert']('',
375
						'{db_prefix}messages',
376
						array(
377
							'id_board' => 'int',
378
							'id_topic' => 'int',
379
							'poster_time' => 'int',
380
							'id_member' => 'int',
381
							'subject' => 'string-255',
382
							'poster_name' => 'string-255',
383
							'poster_email' => 'string-255',
384
							'poster_ip' => 'inet',
385
							'smileys_enabled' => 'int',
386
							'body' => 'string-65534',
387
							'icon' => 'string-16',
388
							'approved' => 'int',
389
						),
390
						array(
391
							$row['id_board'],
392
							0,
393
							time(),
394
							$row['id_poster'],
395
							$txt['salvaged_poll_topic_name'],
396
							$row['poster_name'],
397
							$txt['salvaged_poll_topic_name'],
398
							'127.0.0.1',
399
							1,
400
							$txt['salvaged_poll_message_body'],
401
							'xx',
402
							1,
403
						),
404
						array('id_msg'),
405
						1
406
					);
407
408
					$row['id_topic'] = $smcFunc['db_insert']('',
409
						'{db_prefix}topics',
410
						array(
411
							'id_board' => 'int',
412
							'id_poll' => 'int',
413
							'id_member_started' => 'int',
414
							'id_member_updated' => 'int',
415
							'id_first_msg' => 'int',
416
							'id_last_msg' => 'int',
417
							'num_replies' => 'int',
418
						),
419
						array(
420
							$row['id_board'],
421
							$row['id_poll'],
422
							$row['id_poster'],
423
							$row['id_poster'],
424
							$newMessageID,
425
							$newMessageID,
426
							0,
427
						),
428
						array('id_topic'),
429
						1
430
					);
431
432
					$smcFunc['db_query']('', '
433
						UPDATE {db_prefix}messages
434
					SET id_topic = {int:newTopicID}, id_board = {int:id_board}
435
						WHERE id_msg = {int:newMessageID}',
436
						array(
437
							'id_board' => $row['id_board'],
438
							'newTopicID' => $row['id_topic'],
439
							'newMessageID' => $newMessageID,
440
						)
441
					);
442
443
					updateStats('subject', $row['id_topic'], $txt['salvaged_poll_topic_name']);
444
				}
445
446
				$smcFunc['db_insert']('',
447
					'{db_prefix}polls',
448
					array(
449
						'id_poll' => 'int',
450
						'question' => 'string-255',
451
						'voting_locked' => 'int',
452
						'max_votes' => 'int',
453
						'expire_time' => 'int',
454
						'hide_results' => 'int',
455
						'change_vote' => 'int',
456
						'guest_vote' => 'int',
457
						'num_guest_voters' => 'int',
458
						'reset_poll' => 'int',
459
						'id_member' => 'int',
460
						'poster_name' => 'string-255',
461
					),
462
					array(
463
						$row['id_poll'],
464
						$txt['salvaged_poll_question'],
465
						1,
466
						0,
467
						0,
468
						0,
469
						0,
470
						0,
471
						0,
472
						0,
473
						$row['id_poster'],
474
						$row['poster_name'],
475
					),
476
					array()
477
				);
478
			},
479
			'force_fix' => array('stats_topics'),
480
			'messages' => array('repair_poll_options_missing_poll', 'id_poll', 'amount'),
481
		),
482
		'polls_missing_topics' => array(
483
			'substeps' => array(
484
				'step_size' => 500,
485
				'step_max' => '
486
					SELECT MAX(id_poll)
487
					FROM {db_prefix}polls'
488
			),
489
			'check_query' => '
490
				SELECT p.id_poll, p.id_member, p.poster_name, t.id_board
491
				FROM {db_prefix}polls AS p
492
					LEFT JOIN {db_prefix}topics AS t ON (t.id_poll = p.id_poll)
493
				WHERE p.id_poll BETWEEN {STEP_LOW} AND {STEP_HIGH}
494
					AND t.id_poll IS NULL',
495
			'fix_processing' => function ($row) use ($smcFunc, $txt)
496
			{
497
				global $salvageBoardID;
498
499
				// Only if we don't have a reasonable idea of where to put it.
500
				if ($row['id_board'] == 0)
501
				{
502
					createSalvageArea();
503
					$row['id_board'] = (int) $salvageBoardID;
504
				}
505
506
				$row['poster_name'] = !empty($row['poster_name']) ? $row['poster_name'] : $txt['guest'];
507
508
				$newMessageID = $smcFunc['db_insert']('',
509
					'{db_prefix}messages',
510
					array(
511
						'id_board' => 'int',
512
						'id_topic' => 'int',
513
						'poster_time' => 'int',
514
						'id_member' => 'int',
515
						'subject' => 'string-255',
516
						'poster_name' => 'string-255',
517
						'poster_email' => 'string-255',
518
						'poster_ip' => 'inet',
519
						'smileys_enabled' => 'int',
520
						'body' => 'string-65534',
521
						'icon' => 'string-16',
522
						'approved' => 'int',
523
					),
524
					array(
525
						$row['id_board'],
526
						0,
527
						time(),
528
						$row['id_member'],
529
						$txt['salvaged_poll_topic_name'],
530
						$row['poster_name'],
531
						'',
532
						'127.0.0.1',
533
						1,
534
						$txt['salvaged_poll_message_body'],
535
						'xx',
536
						1,
537
					),
538
					array('id_msg'),
539
					1
540
				);
541
542
				$newTopicID = $smcFunc['db_insert']('',
543
					'{db_prefix}topics',
544
					array(
545
						'id_board' => 'int',
546
						'id_poll' => 'int',
547
						'id_member_started' => 'int',
548
						'id_member_updated' => 'int',
549
						'id_first_msg' => 'int',
550
						'id_last_msg' => 'int',
551
						'num_replies' => 'int',
552
					),
553
					array(
554
						$row['id_board'],
555
						$row['id_poll'],
556
						$row['id_member'],
557
						$row['id_member'],
558
						$newMessageID,
559
						$newMessageID,
560
						0,
561
					),
562
					array('id_topic'),
563
					1
564
				);
565
566
				$smcFunc['db_query']('', '
567
					UPDATE {db_prefix}messages
568
				SET id_topic = {int:newTopicID}, id_board = {int:id_board}
569
					WHERE id_msg = {int:newMessageID}',
570
					array(
571
						'id_board' => $row['id_board'],
572
						'newTopicID' => $newTopicID,
573
						'newMessageID' => $newMessageID,
574
					)
575
				);
576
577
				updateStats('subject', $newTopicID, $txt['salvaged_poll_topic_name']);
578
579
580
		},
581
			'force_fix' => array('stats_topics'),
582
			'messages' => array('repair_polls_missing_topics', 'id_poll', 'id_topic'),
583
		),
584
		'stats_topics' => array(
585
			'substeps' => array(
586
				'step_size' => 200,
587
				'step_max' => '
588
					SELECT MAX(id_topic)
589
					FROM {db_prefix}topics'
590
			),
591
			'check_query' => '
592
				SELECT
593
					t.id_topic, t.id_first_msg, t.id_last_msg,
594
					CASE WHEN MIN(ma.id_msg) > 0 THEN
595
						CASE WHEN MIN(mu.id_msg) > 0 THEN
596
							CASE WHEN MIN(mu.id_msg) < MIN(ma.id_msg) THEN MIN(mu.id_msg) ELSE MIN(ma.id_msg) END ELSE
597
						MIN(ma.id_msg) END ELSE
598
					MIN(mu.id_msg) END AS myid_first_msg,
599
					CASE WHEN MAX(ma.id_msg) > 0 THEN MAX(ma.id_msg) ELSE MIN(mu.id_msg) END AS myid_last_msg,
600
					t.approved, mf.approved, mf.approved AS firstmsg_approved
601
				FROM {db_prefix}topics AS t
602
					LEFT JOIN {db_prefix}messages AS ma ON (ma.id_topic = t.id_topic AND ma.approved = 1)
603
					LEFT JOIN {db_prefix}messages AS mu ON (mu.id_topic = t.id_topic AND mu.approved = 0)
604
					LEFT JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg)
605
				WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH}
606
				GROUP BY t.id_topic, t.id_first_msg, t.id_last_msg, t.approved, mf.approved
607
				ORDER BY t.id_topic',
608
			'fix_processing' => function ($row) use ($smcFunc)
609
			{
610
				$row['firstmsg_approved'] = (int) $row['firstmsg_approved'];
611
				$row['myid_first_msg'] = (int) $row['myid_first_msg'];
612
				$row['myid_last_msg'] = (int) $row['myid_last_msg'];
613
614
				// Not really a problem?
615 View Code Duplication
				if ($row['myid_first_msg'] == $row['myid_first_msg'] && $row['myid_first_msg'] == $row['myid_first_msg'] && $row['approved'] == $row['firstmsg_approved'])
616
					return false;
617
618
				$memberStartedID = (int) getMsgMemberID($row['myid_first_msg']);
619
				$memberUpdatedID = (int) getMsgMemberID($row['myid_last_msg']);
620
621
				$smcFunc['db_query']('', '
622
					UPDATE {db_prefix}topics
623
					SET id_first_msg = {int:myid_first_msg},
624
						id_member_started = {int:memberStartedID}, id_last_msg = {int:myid_last_msg},
625
						id_member_updated = {int:memberUpdatedID}, approved = {int:firstmsg_approved}
626
					WHERE id_topic = {int:topic_id}',
627
					array(
628
						'myid_first_msg' => $row['myid_first_msg'],
629
						'memberStartedID' => $memberStartedID,
630
						'myid_last_msg' => $row['myid_last_msg'],
631
						'memberUpdatedID' => $memberUpdatedID,
632
						'firstmsg_approved' => $row['firstmsg_approved'],
633
						'topic_id' => $row['id_topic'],
634
					)
635
				);
636
			},
637
			'message_function' => function ($row) use ($txt, &$context)
638
			{
639
				// A pretend error?
640 View Code Duplication
				if ($row['myid_first_msg'] == $row['myid_first_msg'] && $row['myid_first_msg'] == $row['myid_first_msg'] && $row['approved'] == $row['firstmsg_approved'])
641
					return false;
642
643
				if ($row['id_first_msg'] != $row['myid_first_msg'])
644
					$context['repair_errors'][] = sprintf($txt['repair_stats_topics_1'], $row['id_topic'], $row['id_first_msg']);
645
				if ($row['id_last_msg'] != $row['myid_last_msg'])
646
					$context['repair_errors'][] = sprintf($txt['repair_stats_topics_2'], $row['id_topic'], $row['id_last_msg']);
647
				if ($row['approved'] != $row['firstmsg_approved'])
648
					$context['repair_errors'][] = sprintf($txt['repair_stats_topics_5'], $row['id_topic']);
649
650
				return true;
651
			},
652
		),
653
		// Find topics with incorrect num_replies.
654
		'stats_topics2' => array(
655
			'substeps' => array(
656
				'step_size' => 300,
657
				'step_max' => '
658
					SELECT MAX(id_topic)
659
					FROM {db_prefix}topics'
660
			),
661
			'check_query' => '
662
				SELECT
663
					t.id_topic, t.num_replies, mf.approved,
664
					CASE WHEN COUNT(ma.id_msg) > 0 THEN CASE WHEN mf.approved > 0 THEN COUNT(ma.id_msg) - 1 ELSE COUNT(ma.id_msg) END ELSE 0 END AS my_num_replies
665
				FROM {db_prefix}topics AS t
666
					LEFT JOIN {db_prefix}messages AS ma ON (ma.id_topic = t.id_topic AND ma.approved = 1)
667
					LEFT JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg)
668
				WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH}
669
				GROUP BY t.id_topic, t.num_replies, mf.approved
670
				ORDER BY t.id_topic',
671
			'fix_processing' => function ($row)
672
		{
673
674
				global $smcFunc;
675
				$row['my_num_replies'] = (int) $row['my_num_replies'];
676
677
				// Not really a problem?
678
				if ($row['my_num_replies'] == $row['num_replies'])
679
					return false;
680
681
				$smcFunc['db_query']('', '
682
					UPDATE {db_prefix}topics
683
					SET num_replies = {int:my_num_replies}
684
					WHERE id_topic = {int:topic_id}',
685
					array(
686
						'my_num_replies' => $row['my_num_replies'],
687
						'topic_id' => $row['id_topic'],
688
					)
689
				);
690
691
		},
692
			'message_function' => function ($row)
693
		{
694
695
				global $txt, $context;
696
697
				// Just joking?
698
				if ($row['my_num_replies'] == $row['num_replies'])
699
					return false;
700
701
				if ($row['num_replies'] != $row['my_num_replies'])
702
					$context['repair_errors'][] = sprintf($txt['repair_stats_topics_3'], $row['id_topic'], $row['num_replies']);
703
704
				return true;
705
706
		},
707
		),
708
		// Find topics with incorrect unapproved_posts.
709
		'stats_topics3' => array(
710
			'substeps' => array(
711
				'step_size' => 1000,
712
				'step_max' => '
713
					SELECT MAX(id_topic)
714
					FROM {db_prefix}topics'
715
			),
716
			'check_query' => '
717
				SELECT
718
					t.id_topic, t.unapproved_posts, COUNT(mu.id_msg) AS my_unapproved_posts
719
				FROM {db_prefix}topics AS t
720
					LEFT JOIN {db_prefix}messages AS mu ON (mu.id_topic = t.id_topic AND mu.approved = 0)
721
				WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH}
722
				GROUP BY t.id_topic, t.unapproved_posts
723
				HAVING unapproved_posts != COUNT(mu.id_msg)
724
				ORDER BY t.id_topic',
725
			'fix_processing' => function ($row)
726
		{
727
728
				global $smcFunc;
729
				$row['my_unapproved_posts'] = (int) $row['my_unapproved_posts'];
730
731
				$smcFunc['db_query']('', '
732
					UPDATE {db_prefix}topics
733
					SET unapproved_posts = {int:my_unapproved_posts}
734
					WHERE id_topic = {int:topic_id}',
735
					array(
736
						'my_unapproved_posts' => $row['my_unapproved_posts'],
737
						'topic_id' => $row['id_topic'],
738
					)
739
				);
740
741
		},
742
			'messages' => array('repair_stats_topics_4', 'id_topic', 'unapproved_posts'),
743
		),
744
		// Find topics with nonexistent boards.
745
		'missing_boards' => array(
746
			'substeps' => array(
747
				'step_size' => 1000,
748
				'step_max' => '
749
					SELECT MAX(id_topic)
750
					FROM {db_prefix}topics'
751
			),
752
			'check_query' => '
753
				SELECT t.id_topic, t.id_board
754
				FROM {db_prefix}topics AS t
755
					LEFT JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
756
				WHERE b.id_board IS NULL
757
					AND t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH}
758
				ORDER BY t.id_board, t.id_topic',
759
			'fix_query' => '
760
				SELECT t.id_board, COUNT(*) AS my_num_topics, COUNT(m.id_msg) AS my_num_posts
761
				FROM {db_prefix}topics AS t
762
					LEFT JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
763
					LEFT JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic)
764
				WHERE b.id_board IS NULL
765
					AND t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH}
766
				GROUP BY t.id_board',
767
			'fix_processing' => function ($row)
768
		{
769
770
				global $smcFunc, $salvageCatID, $txt;
771
				createSalvageArea();
772
773
				$row['my_num_topics'] = (int) $row['my_num_topics'];
774
				$row['my_num_posts'] = (int) $row['my_num_posts'];
775
776
				$newBoardID = $smcFunc['db_insert']('',
777
					'{db_prefix}boards',
778
					array('id_cat' => 'int', 'name' => 'string', 'description' => 'string', 'num_topics' => 'int', 'num_posts' => 'int', 'member_groups' => 'string'),
779
					array($salvageCatID, $txt['salvaged_board_name'], $txt['salvaged_board_description'], $row['my_num_topics'], $row['my_num_posts'], '1'),
780
					array('id_board'),
781
					1
782
				);
783
784
				$smcFunc['db_query']('', '
785
					UPDATE {db_prefix}topics
786
					SET id_board = {int:newBoardID}
787
					WHERE id_board = {int:board_id}',
788
					array(
789
						'newBoardID' => $newBoardID,
790
						'board_id' => $row['id_board'],
791
					)
792
				);
793
				$smcFunc['db_query']('', '
794
					UPDATE {db_prefix}messages
795
					SET id_board = {int:newBoardID}
796
					WHERE id_board = {int:board_id}',
797
					array(
798
						'newBoardID' => $newBoardID,
799
						'board_id' => $row['id_board'],
800
					)
801
				);
802
803
		},
804
			'messages' => array('repair_missing_boards', 'id_topic', 'id_board'),
805
		),
806
		// Find boards with nonexistent categories.
807
		'missing_categories' => array(
808
			'check_query' => '
809
				SELECT b.id_board, b.id_cat
810
				FROM {db_prefix}boards AS b
811
					LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
812
				WHERE c.id_cat IS NULL
813
				ORDER BY b.id_cat, b.id_board',
814
			'fix_collect' => array(
815
				'index' => 'id_cat',
816
				'process' => function ($cats)
817
				{
818
					global $smcFunc, $salvageCatID;
819
					createSalvageArea();
820
					$smcFunc['db_query']('', '
821
						UPDATE {db_prefix}boards
822
						SET id_cat = {int:salvageCatID}
823
						WHERE id_cat IN ({array_int:categories})',
824
						array(
825
							'salvageCatID' => $salvageCatID,
826
							'categories' => $cats,
827
						)
828
					);
829
				},
830
			),
831
			'messages' => array('repair_missing_categories', 'id_board', 'id_cat'),
832
		),
833
		// Find messages with nonexistent members.
834
		'missing_posters' => array(
835
			'substeps' => array(
836
				'step_size' => 2000,
837
				'step_max' => '
838
					SELECT MAX(id_msg)
839
					FROM {db_prefix}messages'
840
			),
841
			'check_query' => '
842
				SELECT m.id_msg, m.id_member
843
				FROM {db_prefix}messages AS m
844
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
845
				WHERE mem.id_member IS NULL
846
					AND m.id_member != 0
847
					AND m.id_msg BETWEEN {STEP_LOW} AND {STEP_HIGH}
848
				ORDER BY m.id_msg',
849
			// Last step-make sure all non-guest posters still exist.
850
			'fix_collect' => array(
851
				'index' => 'id_msg',
852
				'process' => function ($msgs)
853
		{
854
855
					global $smcFunc;
856
					$smcFunc['db_query']('', '
857
						UPDATE {db_prefix}messages
858
						SET id_member = {int:guest_id}
859
						WHERE id_msg IN ({array_int:msgs})',
860
						array(
861
							'msgs' => $msgs,
862
							'guest_id' => 0,
863
						)
864
					);
865
866
		},
867
			),
868
			'messages' => array('repair_missing_posters', 'id_msg', 'id_member'),
869
		),
870
		// Find boards with nonexistent parents.
871
		'missing_parents' => array(
872
			'check_query' => '
873
				SELECT b.id_board, b.id_parent
874
				FROM {db_prefix}boards AS b
875
					LEFT JOIN {db_prefix}boards AS p ON (p.id_board = b.id_parent)
876
				WHERE b.id_parent != 0
877
					AND (p.id_board IS NULL OR p.id_board = b.id_board)
878
				ORDER BY b.id_parent, b.id_board',
879
			'fix_collect' => array(
880
				'index' => 'id_parent',
881
				'process' => function ($parents)
882
				{
883
					global $smcFunc, $salvageBoardID, $salvageCatID;
884
					createSalvageArea();
885
					$smcFunc['db_query']('', '
886
						UPDATE {db_prefix}boards
887
						SET id_parent = {int:salvageBoardID}, id_cat = {int:salvageCatID}, child_level = 1
888
						WHERE id_parent IN ({array_int:parents})',
889
						array(
890
							'salvageBoardID' => $salvageBoardID,
891
							'salvageCatID' => $salvageCatID,
892
							'parents' => $parents,
893
						)
894
					);
895
				},
896
			),
897
			'messages' => array('repair_missing_parents', 'id_board', 'id_parent'),
898
		),
899
		'missing_polls' => array(
900
			'substeps' => array(
901
				'step_size' => 500,
902
				'step_max' => '
903
					SELECT MAX(id_poll)
904
					FROM {db_prefix}topics'
905
			),
906
			'check_query' => '
907
				SELECT t.id_poll, t.id_topic
908
				FROM {db_prefix}topics AS t
909
					LEFT JOIN {db_prefix}polls AS p ON (p.id_poll = t.id_poll)
910
				WHERE t.id_poll != 0
911
					AND t.id_poll BETWEEN {STEP_LOW} AND {STEP_HIGH}
912
					AND p.id_poll IS NULL',
913
			'fix_collect' => array(
914
				'index' => 'id_poll',
915
				'process' => function ($polls)
916
		{
917
918
					global $smcFunc;
919
					$smcFunc['db_query']('', '
920
						UPDATE {db_prefix}topics
921
						SET id_poll = 0
922
						WHERE id_poll IN ({array_int:polls})',
923
						array(
924
							'polls' => $polls,
925
						)
926
					);
927
928
		},
929
			),
930
			'messages' => array('repair_missing_polls', 'id_topic', 'id_poll'),
931
		),
932
		'missing_calendar_topics' => array(
933
			'substeps' => array(
934
				'step_size' => 1000,
935
				'step_max' => '
936
					SELECT MAX(id_topic)
937
					FROM {db_prefix}calendar'
938
			),
939
			'check_query' => '
940
				SELECT cal.id_topic, cal.id_event
941
				FROM {db_prefix}calendar AS cal
942
					LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = cal.id_topic)
943
				WHERE cal.id_topic != 0
944
					AND cal.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH}
945
					AND t.id_topic IS NULL
946
				ORDER BY cal.id_topic',
947
			'fix_collect' => array(
948
				'index' => 'id_topic',
949
				'process' => function ($events)
950
		{
951
952
					global $smcFunc;
953
					$smcFunc['db_query']('', '
954
						UPDATE {db_prefix}calendar
955
						SET id_topic = 0, id_board = 0
956
						WHERE id_topic IN ({array_int:events})',
957
						array(
958
							'events' => $events,
959
						)
960
					);
961
962
		},
963
			),
964
			'messages' => array('repair_missing_calendar_topics', 'id_event', 'id_topic'),
965
		),
966
		'missing_log_topics' => array(
967
			'substeps' => array(
968
				'step_size' => 150,
969
				'step_max' => '
970
					SELECT MAX(id_member)
971
					FROM {db_prefix}log_topics'
972
			),
973
			'check_query' => '
974
				SELECT lt.id_topic
975
				FROM {db_prefix}log_topics AS lt
976
					LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = lt.id_topic)
977
				WHERE t.id_topic IS NULL
978
					AND lt.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}',
979
			'fix_collect' => array(
980
				'index' => 'id_topic',
981
				'process' => function ($topics)
982
		{
983
984
					global $smcFunc;
985
					$smcFunc['db_query']('', '
986
						DELETE FROM {db_prefix}log_topics
987
						WHERE id_topic IN ({array_int:topics})',
988
						array(
989
							'topics' => $topics,
990
						)
991
					);
992
993
		},
994
			),
995
			'messages' => array('repair_missing_log_topics', 'id_topic'),
996
		),
997
		'missing_log_topics_members' => array(
998
			'substeps' => array(
999
				'step_size' => 150,
1000
				'step_max' => '
1001
					SELECT MAX(id_member)
1002
					FROM {db_prefix}log_topics'
1003
			),
1004
			'check_query' => '
1005
				SELECT lt.id_member
1006
				FROM {db_prefix}log_topics AS lt
1007
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lt.id_member)
1008
				WHERE mem.id_member IS NULL
1009
					AND lt.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}
1010
				GROUP BY lt.id_member',
1011
			'fix_collect' => array(
1012
				'index' => 'id_member',
1013
				'process' => function ($members)
1014
		{
1015
1016
					global $smcFunc;
1017
					$smcFunc['db_query']('', '
1018
						DELETE FROM {db_prefix}log_topics
1019
						WHERE id_member IN ({array_int:members})',
1020
						array(
1021
							'members' => $members,
1022
						)
1023
					);
1024
1025
		},
1026
			),
1027
			'messages' => array('repair_missing_log_topics_members', 'id_member'),
1028
		),
1029
		'missing_log_boards' => array(
1030
			'substeps' => array(
1031
				'step_size' => 500,
1032
				'step_max' => '
1033
					SELECT MAX(id_member)
1034
					FROM {db_prefix}log_boards'
1035
			),
1036
			'check_query' => '
1037
				SELECT lb.id_board
1038
				FROM {db_prefix}log_boards AS lb
1039
					LEFT JOIN {db_prefix}boards AS b ON (b.id_board = lb.id_board)
1040
				WHERE b.id_board IS NULL
1041
					AND lb.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}
1042
				GROUP BY lb.id_board',
1043
			'fix_collect' => array(
1044
				'index' => 'id_board',
1045
				'process' => function ($boards)
1046
		{
1047
1048
					global $smcFunc;
1049
					$smcFunc['db_query']('', '
1050
						DELETE FROM {db_prefix}log_boards
1051
						WHERE id_board IN ({array_int:boards})',
1052
						array(
1053
							'boards' => $boards,
1054
						)
1055
					);
1056
1057
		},
1058
			),
1059
			'messages' => array('repair_missing_log_boards', 'id_board'),
1060
		),
1061
		'missing_log_boards_members' => array(
1062
			'substeps' => array(
1063
				'step_size' => 500,
1064
				'step_max' => '
1065
					SELECT MAX(id_member)
1066
					FROM {db_prefix}log_boards'
1067
			),
1068
			'check_query' => '
1069
				SELECT lb.id_member
1070
				FROM {db_prefix}log_boards AS lb
1071
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lb.id_member)
1072
				WHERE mem.id_member IS NULL
1073
					AND lb.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}
1074
				GROUP BY lb.id_member',
1075
			'fix_collect' => array(
1076
				'index' => 'id_member',
1077
				'process' => function ($members) use ($smcFunc)
1078
				{
1079
					$smcFunc['db_query']('', '
1080
						DELETE FROM {db_prefix}log_boards
1081
						WHERE id_member IN ({array_int:members})',
1082
						array(
1083
							'members' => $members,
1084
						)
1085
					);
1086
				},
1087
			),
1088
			'messages' => array('repair_missing_log_boards_members', 'id_member'),
1089
		),
1090
		'missing_log_mark_read' => array(
1091
			'substeps' => array(
1092
				'step_size' => 500,
1093
				'step_max' => '
1094
					SELECT MAX(id_member)
1095
					FROM {db_prefix}log_mark_read'
1096
			),
1097
			'check_query' => '
1098
				SELECT lmr.id_board
1099
				FROM {db_prefix}log_mark_read AS lmr
1100
					LEFT JOIN {db_prefix}boards AS b ON (b.id_board = lmr.id_board)
1101
				WHERE b.id_board IS NULL
1102
					AND lmr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}
1103
				GROUP BY lmr.id_board',
1104
			'fix_collect' => array(
1105
				'index' => 'id_board',
1106
				'process' => function ($boards) use ($smcFunc)
1107
				{
1108
					$smcFunc['db_query']('', '
1109
						DELETE FROM {db_prefix}log_mark_read
1110
						WHERE id_board IN ({array_int:boards})',
1111
						array(
1112
							'boards' => $boards,
1113
						)
1114
					);
1115
				},
1116
			),
1117
			'messages' => array('repair_missing_log_mark_read', 'id_board'),
1118
		),
1119
		'missing_log_mark_read_members' => array(
1120
			'substeps' => array(
1121
				'step_size' => 500,
1122
				'step_max' => '
1123
					SELECT MAX(id_member)
1124
					FROM {db_prefix}log_mark_read'
1125
			),
1126
			'check_query' => '
1127
				SELECT lmr.id_member
1128
				FROM {db_prefix}log_mark_read AS lmr
1129
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lmr.id_member)
1130
				WHERE mem.id_member IS NULL
1131
					AND lmr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}
1132
				GROUP BY lmr.id_member',
1133
			'fix_collect' => array(
1134
				'index' => 'id_member',
1135
				'process' => function ($members) use ($smcFunc)
1136
				{
1137
					$smcFunc['db_query']('', '
1138
						DELETE FROM {db_prefix}log_mark_read
1139
						WHERE id_member IN ({array_int:members})',
1140
						array(
1141
							'members' => $members,
1142
						)
1143
					);
1144
				},
1145
			),
1146
			'messages' => array('repair_missing_log_mark_read_members', 'id_member'),
1147
		),
1148
		'missing_pms' => array(
1149
			'substeps' => array(
1150
				'step_size' => 500,
1151
				'step_max' => '
1152
					SELECT MAX(id_pm)
1153
					FROM {db_prefix}pm_recipients'
1154
			),
1155
			'check_query' => '
1156
				SELECT pmr.id_pm
1157
				FROM {db_prefix}pm_recipients AS pmr
1158
					LEFT JOIN {db_prefix}personal_messages AS pm ON (pm.id_pm = pmr.id_pm)
1159
				WHERE pm.id_pm IS NULL
1160
					AND pmr.id_pm BETWEEN {STEP_LOW} AND {STEP_HIGH}
1161
				GROUP BY pmr.id_pm',
1162
			'fix_collect' => array(
1163
				'index' => 'id_pm',
1164
				'process' => function ($pms) use ($smcFunc)
1165
				{
1166
					$smcFunc['db_query']('', '
1167
						DELETE FROM {db_prefix}pm_recipients
1168
						WHERE id_pm IN ({array_int:pms})',
1169
						array(
1170
							'pms' => $pms,
1171
						)
1172
					);
1173
				},
1174
			),
1175
			'messages' => array('repair_missing_pms', 'id_pm'),
1176
		),
1177
		'missing_recipients' => array(
1178
			'substeps' => array(
1179
				'step_size' => 500,
1180
				'step_max' => '
1181
					SELECT MAX(id_member)
1182
					FROM {db_prefix}pm_recipients'
1183
			),
1184
			'check_query' => '
1185
				SELECT pmr.id_member
1186
				FROM {db_prefix}pm_recipients AS pmr
1187
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = pmr.id_member)
1188
				WHERE pmr.id_member != 0
1189
					AND pmr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}
1190
					AND mem.id_member IS NULL
1191
				GROUP BY pmr.id_member',
1192
			'fix_collect' => array(
1193
				'index' => 'id_member',
1194
				'process' => function ($members)
1195
		{
1196
1197
					global $smcFunc;
1198
					$smcFunc['db_query']('', '
1199
						DELETE FROM {db_prefix}pm_recipients
1200
						WHERE id_member IN ({array_int:members})',
1201
						array(
1202
							'members' => $members,
1203
						)
1204
					);
1205
1206
		},
1207
			),
1208
			'messages' => array('repair_missing_recipients', 'id_member'),
1209
		),
1210
		'missing_senders' => array(
1211
			'substeps' => array(
1212
				'step_size' => 500,
1213
				'step_max' => '
1214
					SELECT MAX(id_pm)
1215
					FROM {db_prefix}personal_messages'
1216
			),
1217
			'check_query' => '
1218
				SELECT pm.id_pm, pm.id_member_from
1219
				FROM {db_prefix}personal_messages AS pm
1220
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = pm.id_member_from)
1221
				WHERE pm.id_member_from != 0
1222
					AND pm.id_pm BETWEEN {STEP_LOW} AND {STEP_HIGH}
1223
					AND mem.id_member IS NULL',
1224
			'fix_collect' => array(
1225
				'index' => 'id_pm',
1226
				'process' => function ($guestMessages)
1227
		{
1228
1229
					global $smcFunc;
1230
					$smcFunc['db_query']('', '
1231
						UPDATE {db_prefix}personal_messages
1232
						SET id_member_from = 0
1233
						WHERE id_pm IN ({array_int:guestMessages})',
1234
						array(
1235
							'guestMessages' => $guestMessages,
1236
						));
1237
1238
		},
1239
			),
1240
			'messages' => array('repair_missing_senders', 'id_pm', 'id_member_from'),
1241
		),
1242
		'missing_notify_members' => array(
1243
			'substeps' => array(
1244
				'step_size' => 500,
1245
				'step_max' => '
1246
					SELECT MAX(id_member)
1247
					FROM {db_prefix}log_notify'
1248
			),
1249
			'check_query' => '
1250
				SELECT ln.id_member
1251
				FROM {db_prefix}log_notify AS ln
1252
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = ln.id_member)
1253
				WHERE ln.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}
1254
					AND mem.id_member IS NULL
1255
				GROUP BY ln.id_member',
1256
			'fix_collect' => array(
1257
				'index' => 'id_member',
1258
				'process' => function ($members) use ($smcFunc)
1259
				{
1260
					$smcFunc['db_query']('', '
1261
						DELETE FROM {db_prefix}log_notify
1262
						WHERE id_member IN ({array_int:members})',
1263
						array(
1264
							'members' => $members,
1265
						)
1266
					);
1267
				},
1268
			),
1269
			'messages' => array('repair_missing_notify_members', 'id_member'),
1270
		),
1271
		'missing_cached_subject' => array(
1272
			'substeps' => array(
1273
				'step_size' => 100,
1274
				'step_max' => '
1275
					SELECT MAX(id_topic)
1276
					FROM {db_prefix}topics'
1277
			),
1278
			'check_query' => '
1279
				SELECT t.id_topic, fm.subject
1280
				FROM {db_prefix}topics AS t
1281
					INNER JOIN {db_prefix}messages AS fm ON (fm.id_msg = t.id_first_msg)
1282
					LEFT JOIN {db_prefix}log_search_subjects AS lss ON (lss.id_topic = t.id_topic)
1283
				WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH}
1284
					AND lss.id_topic IS NULL',
1285
			'fix_full_processing' => function ($result)
1286
		{
1287
1288
				global $smcFunc;
1289
1290
				$inserts = array();
1291
				while ($row = $smcFunc['db_fetch_assoc']($result))
1292
				{
1293
					foreach (text2words($row['subject']) as $word)
1294
						$inserts[] = array($word, $row['id_topic']);
1295 View Code Duplication
					if (count($inserts) > 500)
1296
					{
1297
						$smcFunc['db_insert']('ignore',
1298
							'{db_prefix}log_search_subjects',
1299
							array('word' => 'string', 'id_topic' => 'int'),
1300
							$inserts,
1301
							array('word', 'id_topic')
1302
						);
1303
						$inserts = array();
1304
					}
1305
1306
				}
1307
1308 View Code Duplication
				if (!empty($inserts))
1309
					$smcFunc['db_insert']('ignore',
1310
						'{db_prefix}log_search_subjects',
1311
						array('word' => 'string', 'id_topic' => 'int'),
1312
						$inserts,
1313
						array('word', 'id_topic')
1314
					);
1315
1316
		},
1317
			'message_function' => function ($row)
1318
		{
1319
1320
				global $txt, $context;
1321
1322
				if (count(text2words($row['subject'])) != 0)
1323
				{
1324
					$context['repair_errors'][] = sprintf($txt['repair_missing_cached_subject'], $row['id_topic']);
1325
					return true;
1326
				}
1327
1328
				return false;
1329
1330
		},
1331
		),
1332
		'missing_topic_for_cache' => array(
1333
			'substeps' => array(
1334
				'step_size' => 50,
1335
				'step_max' => '
1336
					SELECT MAX(id_topic)
1337
					FROM {db_prefix}log_search_subjects'
1338
			),
1339
			'check_query' => '
1340
				SELECT lss.id_topic, lss.word
1341
				FROM {db_prefix}log_search_subjects AS lss
1342
					LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = lss.id_topic)
1343
				WHERE lss.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH}
1344
					AND t.id_topic IS NULL',
1345
			'fix_collect' => array(
1346
				'index' => 'id_topic',
1347
				'process' => function ($deleteTopics)
1348
		{
1349
1350
					global $smcFunc;
1351
					$smcFunc['db_query']('', '
1352
						DELETE FROM {db_prefix}log_search_subjects
1353
						WHERE id_topic IN ({array_int:deleteTopics})',
1354
						array(
1355
							'deleteTopics' => $deleteTopics,
1356
						)
1357
					);
1358
1359
		},
1360
			),
1361
			'messages' => array('repair_missing_topic_for_cache', 'word'),
1362
		),
1363
		'missing_member_vote' => array(
1364
			'substeps' => array(
1365
				'step_size' => 500,
1366
				'step_max' => '
1367
					SELECT MAX(id_member)
1368
					FROM {db_prefix}log_polls'
1369
			),
1370
			'check_query' => '
1371
				SELECT lp.id_poll, lp.id_member
1372
				FROM {db_prefix}log_polls AS lp
1373
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lp.id_member)
1374
				WHERE lp.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}
1375
					AND lp.id_member > 0
1376
					AND mem.id_member IS NULL',
1377
			'fix_collect' => array(
1378
				'index' => 'id_member',
1379
				'process' => function ($members)
1380
		{
1381
1382
					global $smcFunc;
1383
					$smcFunc['db_query']('', '
1384
						DELETE FROM {db_prefix}log_polls
1385
						WHERE id_member IN ({array_int:members})',
1386
						array(
1387
							'members' => $members,
1388
						)
1389
					);
1390
1391
		},
1392
			),
1393
			'messages' => array('repair_missing_log_poll_member', 'id_poll', 'id_member'),
1394
		),
1395
		'missing_log_poll_vote' => array(
1396
			'substeps' => array(
1397
				'step_size' => 500,
1398
				'step_max' => '
1399
					SELECT MAX(id_poll)
1400
					FROM {db_prefix}log_polls'
1401
			),
1402
			'check_query' => '
1403
				SELECT lp.id_poll, lp.id_member
1404
				FROM {db_prefix}log_polls AS lp
1405
					LEFT JOIN {db_prefix}polls AS p ON (p.id_poll = lp.id_poll)
1406
				WHERE lp.id_poll BETWEEN {STEP_LOW} AND {STEP_HIGH}
1407
					AND p.id_poll IS NULL',
1408
			'fix_collect' => array(
1409
				'index' => 'id_poll',
1410
				'process' => function ($polls)
1411
		{
1412
1413
					global $smcFunc;
1414
					$smcFunc['db_query']('', '
1415
						DELETE FROM {db_prefix}log_polls
1416
						WHERE id_poll IN ({array_int:polls})',
1417
						array(
1418
							'polls' => $polls,
1419
						)
1420
					);
1421
1422
		},
1423
			),
1424
			'messages' => array('repair_missing_log_poll_vote', 'id_member', 'id_poll'),
1425
		),
1426
		'report_missing_comments' => array(
1427
			'substeps' => array(
1428
				'step_size' => 500,
1429
				'step_max' => '
1430
					SELECT MAX(id_report)
1431
					FROM {db_prefix}log_reported'
1432
			),
1433
			'check_query' => '
1434
				SELECT lr.id_report, lr.subject
1435
				FROM {db_prefix}log_reported AS lr
1436
					LEFT JOIN {db_prefix}log_reported_comments AS lrc ON (lrc.id_report = lr.id_report)
1437
				WHERE lr.id_report BETWEEN {STEP_LOW} AND {STEP_HIGH}
1438
					AND lrc.id_report IS NULL',
1439
			'fix_collect' => array(
1440
				'index' => 'id_report',
1441
				'process' => function ($reports)
1442
		{
1443
1444
					global $smcFunc;
1445
					$smcFunc['db_query']('', '
1446
						DELETE FROM {db_prefix}log_reported
1447
						WHERE id_report IN ({array_int:reports})',
1448
						array(
1449
							'reports' => $reports,
1450
						)
1451
					);
1452
1453
		},
1454
			),
1455
			'messages' => array('repair_report_missing_comments', 'id_report', 'subject'),
1456
		),
1457
		'comments_missing_report' => array(
1458
			'substeps' => array(
1459
				'step_size' => 200,
1460
				'step_max' => '
1461
					SELECT MAX(id_report)
1462
					FROM {db_prefix}log_reported_comments'
1463
			),
1464
			'check_query' => '
1465
				SELECT lrc.id_report, lrc.membername
1466
				FROM {db_prefix}log_reported_comments AS lrc
1467
					LEFT JOIN {db_prefix}log_reported AS lr ON (lr.id_report = lrc.id_report)
1468
				WHERE lrc.id_report BETWEEN {STEP_LOW} AND {STEP_HIGH}
1469
					AND lr.id_report IS NULL',
1470
			'fix_collect' => array(
1471
				'index' => 'id_report',
1472
				'process' => function ($reports)
1473
				{
1474
					global $smcFunc;
1475
					$smcFunc['db_query']('', '
1476
						DELETE FROM {db_prefix}log_reported_comments
1477
						WHERE id_report IN ({array_int:reports})',
1478
						array(
1479
							'reports' => $reports,
1480
						)
1481
					);
1482
				},
1483
			),
1484
			'messages' => array('repair_comments_missing_report', 'id_report', 'membername'),
1485
		),
1486
		'group_request_missing_member' => array(
1487
			'substeps' => array(
1488
				'step_size' => 200,
1489
				'step_max' => '
1490
					SELECT MAX(id_member)
1491
					FROM {db_prefix}log_group_requests'
1492
			),
1493
			'check_query' => '
1494
				SELECT lgr.id_member
1495
				FROM {db_prefix}log_group_requests AS lgr
1496
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lgr.id_member)
1497
				WHERE lgr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}
1498
					AND mem.id_member IS NULL
1499
				GROUP BY lgr.id_member',
1500
			'fix_collect' => array(
1501
				'index' => 'id_member',
1502
				'process' => function ($members)
1503
				{
1504
					global $smcFunc;
1505
					$smcFunc['db_query']('', '
1506
						DELETE FROM {db_prefix}log_group_requests
1507
						WHERE id_member IN ({array_int:members})',
1508
						array(
1509
							'members' => $members,
1510
						)
1511
					);
1512
				},
1513
			),
1514
			'messages' => array('repair_group_request_missing_member', 'id_member'),
1515
		),
1516
		'group_request_missing_group' => array(
1517
			'substeps' => array(
1518
				'step_size' => 200,
1519
				'step_max' => '
1520
					SELECT MAX(id_group)
1521
					FROM {db_prefix}log_group_requests'
1522
			),
1523
			'check_query' => '
1524
				SELECT lgr.id_group
1525
				FROM {db_prefix}log_group_requests AS lgr
1526
					LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = lgr.id_group)
1527
				WHERE lgr.id_group BETWEEN {STEP_LOW} AND {STEP_HIGH}
1528
					AND mg.id_group IS NULL
1529
				GROUP BY lgr.id_group',
1530
			'fix_collect' => array(
1531
				'index' => 'id_group',
1532
				'process' => function ($groups)
1533
				{
1534
					global $smcFunc;
1535
					$smcFunc['db_query']('', '
1536
						DELETE FROM {db_prefix}log_group_requests
1537
						WHERE id_group IN ({array_int:groups})',
1538
						array(
1539
							'groups' => $groups,
1540
						)
1541
					);
1542
				},
1543
			),
1544
			'messages' => array('repair_group_request_missing_group', 'id_group'),
1545
		),
1546
	);
1547
}
1548
1549
/**
1550
 * Checks for errors in steps, until 5 seconds have passed.
1551
 * It keeps track of the errors it did find, so that the actual repair
1552
 * won't have to recheck everything.
1553
 *
1554
 * @param bool $do_fix Whether to actually fix the errors or just return the info
1555
 * @return array, the errors found.
0 ignored issues
show
Documentation introduced by
The doc-type array, could not be parsed: Expected "|" or "end of type", but got "," at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1556
 */
1557
function findForumErrors($do_fix = false)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1558
{
1559
	global $context, $txt, $smcFunc, $errorTests, $db_cache, $db_temp_cache;
1560
1561
	// This may take some time...
1562
	@set_time_limit(600);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1563
1564
	$to_fix = !empty($_SESSION['repairboards_to_fix']) ? $_SESSION['repairboards_to_fix'] : array();
1565
	$context['repair_errors'] = isset($_SESSION['repairboards_to_fix2']) ? $_SESSION['repairboards_to_fix2'] : array();
1566
1567
	$_GET['step'] = empty($_GET['step']) ? 0 : (int) $_GET['step'];
1568
	$_GET['substep'] = empty($_GET['substep']) ? 0 : (int) $_GET['substep'];
1569
1570
	// Don't allow the cache to get too full.
1571
	$db_temp_cache = $db_cache;
1572
	$db_cache = '';
1573
1574
	$context['total_steps'] = count($errorTests);
1575
1576
	// For all the defined error types do the necessary tests.
1577
	$current_step = -1;
1578
	$total_queries = 0;
1579
	foreach ($errorTests as $error_type => $test)
1580
	{
1581
		$current_step++;
1582
1583
		// Already done this?
1584
		if ($_GET['step'] > $current_step)
1585
			continue;
1586
1587
		// If we're fixing it but it ain't broke why try?
1588
		if ($do_fix && !in_array($error_type, $to_fix))
1589
		{
1590
			$_GET['step']++;
1591
			continue;
1592
		}
1593
1594
		// Has it got substeps?
1595
		if (isset($test['substeps']))
1596
		{
1597
			$step_size = isset($test['substeps']['step_size']) ? $test['substeps']['step_size'] : 100;
1598
			$request = $smcFunc['db_query']('',
1599
				$test['substeps']['step_max'],
1600
				array(
1601
				)
1602
			);
1603
			list ($step_max) = $smcFunc['db_fetch_row']($request);
1604
1605
			$total_queries++;
1606
			$smcFunc['db_free_result']($request);
1607
		}
1608
1609
		// We in theory keep doing this... the substeps.
1610
		$done = false;
1611
		while (!$done)
1612
		{
1613
			// Make sure there's at least one ID to test.
1614
			if (isset($test['substeps']) && empty($step_max))
1615
				break;
1616
1617
			// What is the testing query (Changes if we are testing or fixing)
1618
			if (!$do_fix)
1619
				$test_query = 'check_query';
1620
			else
1621
				$test_query = isset($test['fix_query']) ? 'fix_query' : 'check_query';
1622
1623
			// Do the test...
1624
			$request = $smcFunc['db_query']('',
1625
				isset($test['substeps']) ? strtr($test[$test_query], array('{STEP_LOW}' => $_GET['substep'], '{STEP_HIGH}' => $_GET['substep'] + $step_size - 1)) : $test[$test_query],
0 ignored issues
show
Bug introduced by
The variable $step_size does not seem to be defined for all execution paths leading up to this point.

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:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

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

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1626
				array(
1627
				)
1628
			);
1629
1630
			// Does it need a fix?
1631 View Code Duplication
			if (!empty($test['check_type']) && $test['check_type'] == 'count')
1632
				list ($needs_fix) = $smcFunc['db_fetch_row']($request);
1633
			else
1634
				$needs_fix = $smcFunc['db_num_rows']($request);
1635
1636
			$total_queries++;
1637
1638
			if ($needs_fix)
1639
			{
1640
				// What about a message to the user?
1641
				if (!$do_fix)
1642
				{
1643
					// Assume need to fix.
1644
					$found_errors = true;
1645
1646
					if (isset($test['message']))
1647
						$context['repair_errors'][] = $txt[$test['message']];
1648
1649
					// One per row!
1650
					elseif (isset($test['messages']))
1651
					{
1652
						while ($row = $smcFunc['db_fetch_assoc']($request))
1653
						{
1654
							$variables = $test['messages'];
1655
							foreach ($variables as $k => $v)
1656
							{
1657
								if ($k == 0 && isset($txt[$v]))
1658
									$variables[$k] = $txt[$v];
1659
								elseif ($k > 0 && isset($row[$v]))
1660
									$variables[$k] = $row[$v];
1661
							}
1662
							$context['repair_errors'][] = call_user_func_array('sprintf', $variables);
1663
						}
1664
					}
1665
1666
					// A function to process?
1667
					elseif (isset($test['message_function']))
1668
					{
1669
						// Find out if there are actually errors.
1670
						$found_errors = false;
1671
						while ($row = $smcFunc['db_fetch_assoc']($request))
1672
							$found_errors |= $test['message_function']($row);
1673
					}
1674
1675
					// Actually have something to fix?
1676
					if ($found_errors)
1677
						$to_fix[] = $error_type;
1678
				}
1679
1680
				// We want to fix, we need to fix - so work out what exactly to do!
1681
				else
1682
				{
1683
					// Are we simply getting a collection of ids?
1684
					if (isset($test['fix_collect']))
1685
					{
1686
						$ids = array();
1687
						while ($row = $smcFunc['db_fetch_assoc']($request))
1688
							$ids[] = $row[$test['fix_collect']['index']];
1689
						if (!empty($ids))
1690
						{
1691
							// Fix it!
1692
							$test['fix_collect']['process']($ids);
1693
						}
1694
					}
1695
1696
					// Simply executing a fix it query?
1697
					elseif (isset($test['fix_it_query']))
1698
						$smcFunc['db_query']('',
1699
							$test['fix_it_query'],
1700
							array(
1701
							)
1702
						);
1703
1704
					// Do we have some processing to do?
1705
					elseif (isset($test['fix_processing']))
1706
					{
1707
						while ($row = $smcFunc['db_fetch_assoc']($request))
1708
							$test['fix_processing']($row);
1709
					}
1710
1711
					// What about the full set of processing?
1712
					elseif (isset($test['fix_full_processing']))
1713
						$test['fix_full_processing']($request);
1714
1715
					// Do we have other things we need to fix as a result?
1716
					if (!empty($test['force_fix']))
1717
					{
1718
						foreach ($test['force_fix'] as $item)
1719
							if (!in_array($item, $to_fix))
1720
								$to_fix[] = $item;
1721
					}
1722
				}
1723
			}
1724
1725
			// Free the result.
1726
			$smcFunc['db_free_result']($request);
1727
			// Keep memory down.
1728
			$db_cache = '';
1729
1730
			// Are we done yet?
1731
			if (isset($test['substeps']))
1732
			{
1733
				$_GET['substep'] += $step_size;
1734
				// Not done?
1735
				if ($_GET['substep'] <= $step_max)
1736
				{
1737
					pauseRepairProcess($to_fix, $error_type, $step_max);
0 ignored issues
show
Bug introduced by
The variable $step_max does not seem to be defined for all execution paths leading up to this point.

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:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

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

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1738
				}
1739
				else
1740
					$done = true;
1741
			}
1742
			else
1743
				$done = true;
1744
1745
			// Don't allow more than 1000 queries at a time.
1746
			if ($total_queries >= 1000)
1747
				pauseRepairProcess($to_fix, $error_type, $step_max, true);
1748
		}
1749
1750
		// Keep going.
1751
		$_GET['step']++;
1752
		$_GET['substep'] = 0;
1753
1754
		$to_fix = array_unique($to_fix);
1755
1756
		// If we're doing fixes and this needed a fix and we're all done then don't do it again.
1757
		if ($do_fix)
1758
		{
1759
			$key = array_search($error_type, $to_fix);
1760
			if ($key !== false && isset($to_fix[$key]))
1761
				unset($to_fix[$key]);
1762
		}
1763
1764
		// Are we done?
1765
		pauseRepairProcess($to_fix, $error_type);
1766
	}
1767
1768
	// Restore the cache.
1769
	$db_cache = $db_temp_cache;
1770
1771
	return $to_fix;
1772
}
1773
1774
/**
1775
 * Create a salvage area for repair purposes, if one doesn't already exist.
1776
 * Uses the forum's default language, and checks based on that name.
1777
 */
1778
function createSalvageArea()
1779
{
1780
	global $txt, $language, $salvageBoardID, $salvageCatID, $smcFunc;
1781
	static $createOnce = false;
1782
1783
	// Have we already created it?
1784
	if ($createOnce)
1785
		return;
1786
	else
1787
		$createOnce = true;
1788
1789
	// Back to the forum's default language.
1790
	loadLanguage('Admin', $language);
1791
1792
	// Check to see if a 'Salvage Category' exists, if not => insert one.
1793
	$result = $smcFunc['db_query']('', '
1794
		SELECT id_cat
1795
		FROM {db_prefix}categories
1796
		WHERE name = {string:cat_name}
1797
		LIMIT 1',
1798
		array(
1799
			'cat_name' => $txt['salvaged_category_name'],
1800
		)
1801
	);
1802 View Code Duplication
	if ($smcFunc['db_num_rows']($result) != 0)
1803
		list ($salvageCatID) = $smcFunc['db_fetch_row']($result);
1804
	$smcFunc['db_free_result']($result);
1805
1806
	if (empty($salvageCatID))
1807
	{
1808
		$salvageCatID = $smcFunc['db_insert']('',
1809
			'{db_prefix}categories',
1810
			array('name' => 'string-255', 'cat_order' => 'int'),
1811
			array($txt['salvaged_category_name'], -1),
1812
			array('id_cat'),
1813
			1
1814
		);
1815
1816
		if ($smcFunc['db_affected_rows']() <= 0)
1817
		{
1818
			loadLanguage('Admin');
1819
			fatal_lang_error('salvaged_category_error', false);
1820
		}
1821
	}
1822
1823
	// Check to see if a 'Salvage Board' exists, if not => insert one.
1824
	$result = $smcFunc['db_query']('', '
1825
		SELECT id_board
1826
		FROM {db_prefix}boards
1827
		WHERE id_cat = {int:id_cat}
1828
			AND name = {string:board_name}
1829
		LIMIT 1',
1830
		array(
1831
			'id_cat' => $salvageCatID,
1832
			'board_name' => $txt['salvaged_board_name'],
1833
		)
1834
	);
1835 View Code Duplication
	if ($smcFunc['db_num_rows']($result) != 0)
1836
		list ($salvageBoardID) = $smcFunc['db_fetch_row']($result);
1837
	$smcFunc['db_free_result']($result);
1838
1839
	if (empty($salvageBoardID))
1840
	{
1841
		$salvageBoardID = $smcFunc['db_insert']('',
1842
			'{db_prefix}boards',
1843
			array('name' => 'string-255', 'description' => 'string-255', 'id_cat' => 'int', 'member_groups' => 'string', 'board_order' => 'int', 'redirect' => 'string'),
1844
			array($txt['salvaged_board_name'], $txt['salvaged_board_description'], $salvageCatID, '1', -1, ''),
1845
			array('id_board'),
1846
			1
1847
		);
1848
1849
		if ($smcFunc['db_affected_rows']() <= 0)
1850
		{
1851
			loadLanguage('Admin');
1852
			fatal_lang_error('salvaged_board_error', false);
1853
		}
1854
1855
	}
1856
1857
	$smcFunc['db_query']('alter_table_boards', '
1858
		ALTER TABLE {db_prefix}boards
1859
		ORDER BY board_order',
1860
		array(
1861
		)
1862
	);
1863
1864
	// Restore the user's language.
1865
	loadLanguage('Admin');
1866
}
1867
1868
?>