Mercurial > hg > vamp-website
comparison forum/Sources/RepairBoards.php @ 76:e3e11437ecea website
Add forum code
author | Chris Cannam |
---|---|
date | Sun, 07 Jul 2013 11:25:48 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
75:72f59aa7e503 | 76:e3e11437ecea |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * Simple Machines Forum (SMF) | |
5 * | |
6 * @package SMF | |
7 * @author Simple Machines http://www.simplemachines.org | |
8 * @copyright 2011 Simple Machines | |
9 * @license http://www.simplemachines.org/about/smf/license.php BSD | |
10 * | |
11 * @version 2.0 | |
12 */ | |
13 | |
14 if (!defined('SMF')) | |
15 die('Hacking attempt...'); | |
16 | |
17 /* This is here for the "repair any errors" feature in the admin center. It | |
18 uses just two simple functions: | |
19 | |
20 void RepairBoards() | |
21 - finds or repairs errors in the database to fix possible problems. | |
22 - requires the admin_forum permission. | |
23 - uses the raw_data sub template. | |
24 - calls createSalvageArea() to create a new board, if necesary. | |
25 - accessed by ?action=admin;area=repairboards. | |
26 | |
27 void pauseRepairProcess(array to_fix, string current_step_desc, int max_substep = none, force = false) | |
28 - show the not_done template to avoid CGI timeouts and similar. | |
29 - called when 3 or more seconds have passed while searching for errors. | |
30 - if max_substep is set, $_GET['substep'] / $max_substep is the percent | |
31 done this step is. | |
32 | |
33 array findForumErrors() | |
34 - checks for errors in steps, until 5 seconds have passed. | |
35 - keeps track of the errors it did find, so that the actual repair | |
36 won't have to recheck everything. | |
37 - returns the array of errors found. | |
38 | |
39 void createSalvageArea() | |
40 - creates a salvage board/category if one doesn't already exist. | |
41 - uses the forum's default language, and checks based on that name. | |
42 */ | |
43 | |
44 function RepairBoards() | |
45 { | |
46 global $txt, $scripturl, $db_connection, $context, $sourcedir; | |
47 global $salvageCatID, $salvageBoardID, $smcFunc, $errorTests; | |
48 | |
49 isAllowedTo('admin_forum'); | |
50 | |
51 // Try secure more memory. | |
52 @ini_set('memory_limit', '128M'); | |
53 | |
54 // Print out the top of the webpage. | |
55 $context['page_title'] = $txt['admin_repair']; | |
56 $context['sub_template'] = 'repair_boards'; | |
57 $context[$context['admin_menu_name']]['current_subsection'] = 'general'; | |
58 | |
59 // Load the language file. | |
60 loadLanguage('ManageMaintenance'); | |
61 | |
62 // Make sure the tabs stay nice. | |
63 $context[$context['admin_menu_name']]['tab_data'] = array( | |
64 'title' => $txt['maintain_title'], | |
65 'help' => '', | |
66 'description' => $txt['maintain_info'], | |
67 'tabs' => array(), | |
68 ); | |
69 | |
70 // Start displaying errors without fixing them. | |
71 if (isset($_GET['fixErrors'])) | |
72 checkSession('get'); | |
73 | |
74 // Will want this. | |
75 loadForumTests(); | |
76 | |
77 // Giant if/else. The first displays the forum errors if a variable is not set and asks | |
78 // if you would like to continue, the other fixes the errors. | |
79 if (!isset($_GET['fixErrors'])) | |
80 { | |
81 $context['error_search'] = true; | |
82 $context['repair_errors'] = array(); | |
83 $context['to_fix'] = findForumErrors(); | |
84 | |
85 if (!empty($context['to_fix'])) | |
86 { | |
87 $_SESSION['repairboards_to_fix'] = $context['to_fix']; | |
88 $_SESSION['repairboards_to_fix2'] = null; | |
89 | |
90 if (empty($context['repair_errors'])) | |
91 $context['repair_errors'][] = '???'; | |
92 } | |
93 } | |
94 else | |
95 { | |
96 $context['error_search'] = false; | |
97 $context['to_fix'] = isset($_SESSION['repairboards_to_fix']) ? $_SESSION['repairboards_to_fix'] : array(); | |
98 | |
99 require_once($sourcedir . '/Subs-Boards.php'); | |
100 | |
101 // Get the MySQL version for future reference. | |
102 $mysql_version = $smcFunc['db_server_info']($db_connection); | |
103 | |
104 // Actually do the fix. | |
105 findForumErrors(true); | |
106 | |
107 // Note that we've changed everything possible ;) | |
108 updateSettings(array( | |
109 'settings_updated' => time(), | |
110 )); | |
111 updateStats('message'); | |
112 updateStats('topic'); | |
113 updateSettings(array( | |
114 'calendar_updated' => time(), | |
115 )); | |
116 | |
117 if (!empty($salvageBoardID)) | |
118 { | |
119 $context['redirect_to_recount'] = true; | |
120 } | |
121 | |
122 $_SESSION['repairboards_to_fix'] = null; | |
123 $_SESSION['repairboards_to_fix2'] = null; | |
124 } | |
125 } | |
126 | |
127 function pauseRepairProcess($to_fix, $current_step_description, $max_substep = 0, $force = false) | |
128 { | |
129 global $context, $txt, $time_start, $db_temp_cache, $db_cache; | |
130 | |
131 // More time, I need more time! | |
132 @set_time_limit(600); | |
133 if (function_exists('apache_reset_timeout')) | |
134 @apache_reset_timeout(); | |
135 | |
136 // Errr, wait. How much time has this taken already? | |
137 if (!$force && time() - array_sum(explode(' ', $time_start)) < 3) | |
138 return; | |
139 | |
140 // Restore the query cache if interested. | |
141 if (!empty($db_temp_cache)) | |
142 $db_cache = $db_temp_cache; | |
143 | |
144 $context['continue_get_data'] = '?action=admin;area=repairboards' . (isset($_GET['fixErrors']) ? ';fixErrors' : '') . ';step=' . $_GET['step'] . ';substep=' . $_GET['substep'] . ';' . $context['session_var'] . '=' . $context['session_id']; | |
145 $context['page_title'] = $txt['not_done_title']; | |
146 $context['continue_post_data'] = ''; | |
147 $context['continue_countdown'] = '2'; | |
148 $context['sub_template'] = 'not_done'; | |
149 | |
150 // Change these two if more steps are added! | |
151 if (empty($max_substep)) | |
152 $context['continue_percent'] = round(($_GET['step'] * 100) / $context['total_steps']); | |
153 else | |
154 $context['continue_percent'] = round((($_GET['step'] + ($_GET['substep'] / $max_substep)) * 100) / $context['total_steps']); | |
155 | |
156 // Never more than 100%! | |
157 $context['continue_percent'] = min($context['continue_percent'], 100); | |
158 | |
159 // What about substeps? | |
160 $context['substep_enabled'] = $max_substep != 0; | |
161 $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)); | |
162 $context['substep_continue_percent'] = $max_substep == 0 ? 0 : round(($_GET['substep'] * 100) / $max_substep, 1); | |
163 | |
164 $_SESSION['repairboards_to_fix'] = $to_fix; | |
165 $_SESSION['repairboards_to_fix2'] = $context['repair_errors']; | |
166 | |
167 obExit(); | |
168 } | |
169 | |
170 // Load up all the tests we might want to do ;) | |
171 function loadForumTests() | |
172 { | |
173 global $smcFunc, $errorTests; | |
174 | |
175 /* Here this array is defined like so: | |
176 string check_query: Query to be executed when testing if errors exist. | |
177 string check_type: Defines how it knows if a problem was found. If set to count looks for the first variable from check_query | |
178 being > 0. Anything else it looks for some results. If not set assumes you want results. | |
179 string fix_it_query: When doing fixes if an error was detected this query is executed to "fix" it. | |
180 string fix_query: The query to execute to get data when doing a fix. If not set check_query is used again. | |
181 array fix_collect: This array is used if the fix is basically gathering all broken ids and then doing something with it. | |
182 - string index: The value returned from the main query and passed to the processing function. | |
183 - process: A function passed an array of ids to execute the fix on. | |
184 function fix_processing: | |
185 Function called for each row returned from fix_query to execute whatever fixes are required. | |
186 function fix_full_processing: | |
187 As above but does the while loop and everything itself - except the freeing. | |
188 array force_fix: If this is set then the error types included within this array will also be assumed broken. | |
189 Note: At the moment only processes these if they occur after the primary error in the array. | |
190 */ | |
191 | |
192 // This great array contains all of our error checks, fixes, etc etc etc. | |
193 $errorTests = array( | |
194 // Make a last-ditch-effort check to get rid of topics with zeros.. | |
195 'zero_topics' => array( | |
196 'check_query' => ' | |
197 SELECT COUNT(*) | |
198 FROM {db_prefix}topics | |
199 WHERE id_topic = 0', | |
200 'check_type' => 'count', | |
201 'fix_it_query' => ' | |
202 UPDATE {db_prefix}topics | |
203 SET id_topic = NULL | |
204 WHERE id_topic = 0', | |
205 'message' => 'repair_zero_ids', | |
206 ), | |
207 // ... and same with messages. | |
208 'zero_messages' => array( | |
209 'check_query' => ' | |
210 SELECT COUNT(*) | |
211 FROM {db_prefix}messages | |
212 WHERE id_msg = 0', | |
213 'check_type' => 'count', | |
214 'fix_it_query' => ' | |
215 UPDATE {db_prefix}messages | |
216 SET id_msg = NULL | |
217 WHERE id_msg = 0', | |
218 'message' => 'repair_zero_ids', | |
219 ), | |
220 // Find messages that don't have existing topics. | |
221 'missing_topics' => array( | |
222 'substeps' => array( | |
223 'step_size' => 1000, | |
224 'step_max' => ' | |
225 SELECT MAX(id_topic) | |
226 FROM {db_prefix}messages' | |
227 ), | |
228 'check_query' => ' | |
229 SELECT m.id_topic, m.id_msg | |
230 FROM {db_prefix}messages AS m | |
231 LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) | |
232 WHERE m.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
233 AND t.id_topic IS NULL | |
234 ORDER BY m.id_topic, m.id_msg', | |
235 'fix_query' => ' | |
236 SELECT | |
237 m.id_board, m.id_topic, MIN(m.id_msg) AS myid_first_msg, MAX(m.id_msg) AS myid_last_msg, | |
238 COUNT(*) - 1 AS my_num_replies | |
239 FROM {db_prefix}messages AS m | |
240 LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) | |
241 WHERE t.id_topic IS NULL | |
242 GROUP BY m.id_topic, m.id_board', | |
243 'fix_processing' => create_function('$row', ' | |
244 global $smcFunc, $salvageBoardID; | |
245 | |
246 // Only if we don\'t have a reasonable idea of where to put it. | |
247 if ($row[\'id_board\'] == 0) | |
248 { | |
249 createSalvageArea(); | |
250 $row[\'id_board\'] = (int) $salvageBoardID; | |
251 } | |
252 | |
253 // Make sure that no topics claim the first/last message as theirs. | |
254 $smcFunc[\'db_query\'](\'\', \' | |
255 UPDATE {db_prefix}topics | |
256 SET id_first_msg = 0 | |
257 WHERE id_first_msg = {int:id_first_msg}\', | |
258 array( | |
259 \'id_first_msg\' => $row[\'myid_first_msg\'], | |
260 ) | |
261 ); | |
262 $smcFunc[\'db_query\'](\'\', \' | |
263 UPDATE {db_prefix}topics | |
264 SET id_last_msg = 0 | |
265 WHERE id_last_msg = {int:id_last_msg}\', | |
266 array( | |
267 \'id_last_msg\' => $row[\'myid_last_msg\'], | |
268 ) | |
269 ); | |
270 | |
271 $memberStartedID = (int) getMsgMemberID($row[\'myid_first_msg\']); | |
272 $memberUpdatedID = (int) getMsgMemberID($row[\'myid_last_msg\']); | |
273 | |
274 $smcFunc[\'db_insert\'](\'\', | |
275 \'{db_prefix}topics\', | |
276 array( | |
277 \'id_board\' => \'int\', | |
278 \'id_member_started\' => \'int\', | |
279 \'id_member_updated\' => \'int\', | |
280 \'id_first_msg\' => \'int\', | |
281 \'id_last_msg\' => \'int\', | |
282 \'num_replies\' => \'int\' | |
283 ), | |
284 array( | |
285 $row[\'id_board\'], | |
286 $memberStartedID, | |
287 $memberUpdatedID, | |
288 $row[\'myid_first_msg\'], | |
289 $row[\'myid_last_msg\'], | |
290 $row[\'my_num_replies\'] | |
291 ), | |
292 array(\'id_topic\') | |
293 ); | |
294 | |
295 $newTopicID = $smcFunc[\'db_insert_id\']("{db_prefix}topics", \'id_topic\'); | |
296 | |
297 $smcFunc[\'db_query\'](\'\', " | |
298 UPDATE {db_prefix}messages | |
299 SET id_topic = $newTopicID, id_board = $row[id_board] | |
300 WHERE id_topic = $row[id_topic]", | |
301 array( | |
302 ) | |
303 ); | |
304 '), | |
305 'force_fix' => array('stats_topics'), | |
306 'messages' => array('repair_missing_topics', 'id_msg', 'id_topic'), | |
307 ), | |
308 // Find topics with no messages. | |
309 'missing_messages' => array( | |
310 'substeps' => array( | |
311 'step_size' => 1000, | |
312 'step_max' => ' | |
313 SELECT MAX(id_topic) | |
314 FROM {db_prefix}topics' | |
315 ), | |
316 'check_query' => ' | |
317 SELECT t.id_topic, COUNT(m.id_msg) AS num_msg | |
318 FROM {db_prefix}topics AS t | |
319 LEFT JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic) | |
320 WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
321 GROUP BY t.id_topic | |
322 HAVING COUNT(m.id_msg) = 0', | |
323 // Remove all topics that have zero messages in the messages table. | |
324 'fix_collect' => array( | |
325 'index' => 'id_topic', | |
326 'process' => create_function('$topics', ' | |
327 global $smcFunc; | |
328 $smcFunc[\'db_query\'](\'\', " | |
329 DELETE FROM {db_prefix}topics | |
330 WHERE id_topic IN ({array_int:topics})", | |
331 array( | |
332 \'topics\' => $topics | |
333 ) | |
334 ); | |
335 $smcFunc[\'db_query\'](\'\', " | |
336 DELETE FROM {db_prefix}log_topics | |
337 WHERE id_topic IN ({array_int:topics})", | |
338 array( | |
339 \'topics\' => $topics | |
340 ) | |
341 ); | |
342 '), | |
343 ), | |
344 'messages' => array('repair_missing_messages', 'id_topic'), | |
345 ), | |
346 'polls_missing_topics' => array( | |
347 'substeps' => array( | |
348 'step_size' => 500, | |
349 'step_max' => ' | |
350 SELECT MAX(id_poll) | |
351 FROM {db_prefix}polls' | |
352 ), | |
353 'check_query' => ' | |
354 SELECT p.id_poll, p.id_member, p.poster_name, t.id_board | |
355 FROM {db_prefix}polls AS p | |
356 LEFT JOIN {db_prefix}topics AS t ON (t.id_poll = p.id_poll) | |
357 WHERE p.id_poll BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
358 AND t.id_poll IS NULL', | |
359 'fix_processing' => create_function('$row', ' | |
360 global $smcFunc, $salvageBoardID, $txt; | |
361 | |
362 // Only if we don\'t have a reasonable idea of where to put it. | |
363 if ($row[\'id_board\'] == 0) | |
364 { | |
365 createSalvageArea(); | |
366 $row[\'id_board\'] = (int) $salvageBoardID; | |
367 } | |
368 | |
369 $row[\'poster_name\'] = !empty($row[\'poster_name\']) ? $row[\'poster_name\'] : $txt[\'guest\']; | |
370 | |
371 $smcFunc[\'db_insert\'](\'\', | |
372 \'{db_prefix}messages\', | |
373 array( | |
374 \'id_board\' => \'int\', | |
375 \'id_topic\' => \'int\', | |
376 \'poster_time\' => \'int\', | |
377 \'id_member\' => \'int\', | |
378 \'subject\' => \'string-255\', | |
379 \'poster_name\' => \'string-255\', | |
380 \'poster_email\' => \'string-255\', | |
381 \'poster_ip\' => \'string-16\', | |
382 \'smileys_enabled\' => \'int\', | |
383 \'body\' => \'string-65534\', | |
384 \'icon\' => \'string-16\', | |
385 \'approved\' => \'int\', | |
386 ), | |
387 array( | |
388 $row[\'id_board\'], | |
389 0, | |
390 time(), | |
391 $row[\'id_member\'], | |
392 $txt[\'salvaged_poll_topic_name\'], | |
393 $row[\'poster_name\'], | |
394 \'\', | |
395 \'127.0.0.1\', | |
396 1, | |
397 $txt[\'salvaged_poll_message_body\'], | |
398 \'xx\', | |
399 1, | |
400 ), | |
401 array(\'id_topic\') | |
402 ); | |
403 | |
404 $newMessageID = $smcFunc[\'db_insert_id\']("{db_prefix}messages", \'id_msg\'); | |
405 | |
406 $smcFunc[\'db_insert\'](\'\', | |
407 \'{db_prefix}topics\', | |
408 array( | |
409 \'id_board\' => \'int\', | |
410 \'id_poll\' => \'int\', | |
411 \'id_member_started\' => \'int\', | |
412 \'id_member_updated\' => \'int\', | |
413 \'id_first_msg\' => \'int\', | |
414 \'id_last_msg\' => \'int\', | |
415 \'num_replies\' => \'int\', | |
416 ), | |
417 array( | |
418 $row[\'id_board\'], | |
419 $row[\'id_poll\'], | |
420 $row[\'id_member\'], | |
421 $row[\'id_member\'], | |
422 $newMessageID, | |
423 $newMessageID, | |
424 0, | |
425 ), | |
426 array(\'id_topic\') | |
427 ); | |
428 | |
429 $newTopicID = $smcFunc[\'db_insert_id\']("{db_prefix}topics", \'id_topic\'); | |
430 | |
431 $smcFunc[\'db_query\'](\'\', " | |
432 UPDATE {db_prefix}messages | |
433 SET id_topic = $newTopicID, id_board = $row[id_board] | |
434 WHERE id_msg = $newMessageID", | |
435 array( | |
436 ) | |
437 ); | |
438 | |
439 updateStats(\'subject\', $newTopicID, $txt[\'salvaged_poll_topic_name\']); | |
440 | |
441 '), | |
442 'force_fix' => array('stats_topics'), | |
443 'messages' => array('repair_polls_missing_topics', 'id_poll', 'id_topic'), | |
444 ), | |
445 'stats_topics' => array( | |
446 'substeps' => array( | |
447 'step_size' => 200, | |
448 'step_max' => ' | |
449 SELECT MAX(id_topic) | |
450 FROM {db_prefix}topics' | |
451 ), | |
452 'check_query' => ' | |
453 SELECT | |
454 t.id_topic, t.id_first_msg, t.id_last_msg, | |
455 CASE WHEN MIN(ma.id_msg) > 0 THEN | |
456 CASE WHEN MIN(mu.id_msg) > 0 THEN | |
457 CASE WHEN MIN(mu.id_msg) < MIN(ma.id_msg) THEN MIN(mu.id_msg) ELSE MIN(ma.id_msg) END ELSE | |
458 MIN(ma.id_msg) END ELSE | |
459 MIN(mu.id_msg) END AS myid_first_msg, | |
460 CASE WHEN MAX(ma.id_msg) > 0 THEN MAX(ma.id_msg) ELSE MIN(mu.id_msg) END AS myid_last_msg, | |
461 t.approved, mf.approved, mf.approved AS firstmsg_approved | |
462 FROM {db_prefix}topics AS t | |
463 LEFT JOIN {db_prefix}messages AS ma ON (ma.id_topic = t.id_topic AND ma.approved = 1) | |
464 LEFT JOIN {db_prefix}messages AS mu ON (mu.id_topic = t.id_topic AND mu.approved = 0) | |
465 LEFT JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) | |
466 WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
467 GROUP BY t.id_topic, t.id_first_msg, t.id_last_msg, t.approved, mf.approved | |
468 ORDER BY t.id_topic', | |
469 'fix_processing' => create_function('$row', ' | |
470 global $smcFunc; | |
471 $row[\'firstmsg_approved\'] = (int) $row[\'firstmsg_approved\']; | |
472 $row[\'myid_first_msg\'] = (int) $row[\'myid_first_msg\']; | |
473 $row[\'myid_last_msg\'] = (int) $row[\'myid_last_msg\']; | |
474 | |
475 // Not really a problem? | |
476 if ($row[\'myid_first_msg\'] == $row[\'myid_first_msg\'] && $row[\'myid_first_msg\'] == $row[\'myid_first_msg\'] && $row[\'approved\'] == $row[\'firstmsg_approved\']) | |
477 return false; | |
478 | |
479 $memberStartedID = (int) getMsgMemberID($row[\'myid_first_msg\']); | |
480 $memberUpdatedID = (int) getMsgMemberID($row[\'myid_last_msg\']); | |
481 | |
482 $smcFunc[\'db_query\'](\'\', " | |
483 UPDATE {db_prefix}topics | |
484 SET id_first_msg = $row[myid_first_msg], | |
485 id_member_started = $memberStartedID, id_last_msg = $row[myid_last_msg], | |
486 id_member_updated = $memberUpdatedID, approved = $row[firstmsg_approved] | |
487 WHERE id_topic = $row[id_topic]", | |
488 array( | |
489 ) | |
490 ); | |
491 '), | |
492 'message_function' => create_function('$row', ' | |
493 global $txt, $context; | |
494 | |
495 // A pretend error? | |
496 if ($row[\'myid_first_msg\'] == $row[\'myid_first_msg\'] && $row[\'myid_first_msg\'] == $row[\'myid_first_msg\'] && $row[\'approved\'] == $row[\'firstmsg_approved\']) | |
497 return false; | |
498 | |
499 if ($row[\'id_first_msg\'] != $row[\'myid_first_msg\']) | |
500 $context[\'repair_errors\'][] = sprintf($txt[\'repair_stats_topics_1\'], $row[\'id_topic\'], $row[\'id_first_msg\']); | |
501 if ($row[\'id_last_msg\'] != $row[\'myid_last_msg\']) | |
502 $context[\'repair_errors\'][] = sprintf($txt[\'repair_stats_topics_2\'], $row[\'id_topic\'], $row[\'id_last_msg\']); | |
503 if ($row[\'approved\'] != $row[\'firstmsg_approved\']) | |
504 $context[\'repair_errors\'][] = sprintf($txt[\'repair_stats_topics_5\'], $row[\'id_topic\']); | |
505 | |
506 return true; | |
507 '), | |
508 ), | |
509 // Find topics with incorrect num_replies. | |
510 'stats_topics2' => array( | |
511 'substeps' => array( | |
512 'step_size' => 300, | |
513 'step_max' => ' | |
514 SELECT MAX(id_topic) | |
515 FROM {db_prefix}topics' | |
516 ), | |
517 'check_query' => ' | |
518 SELECT | |
519 t.id_topic, t.num_replies, mf.approved, | |
520 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 | |
521 FROM {db_prefix}topics AS t | |
522 LEFT JOIN {db_prefix}messages AS ma ON (ma.id_topic = t.id_topic AND ma.approved = 1) | |
523 LEFT JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) | |
524 WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
525 GROUP BY t.id_topic, t.num_replies, mf.approved | |
526 ORDER BY t.id_topic', | |
527 'fix_processing' => create_function('$row', ' | |
528 global $smcFunc; | |
529 $row[\'my_num_replies\'] = (int) $row[\'my_num_replies\']; | |
530 | |
531 // Not really a problem? | |
532 if ($row[\'my_num_replies\'] == $row[\'num_replies\']) | |
533 return false; | |
534 | |
535 $smcFunc[\'db_query\'](\'\', " | |
536 UPDATE {db_prefix}topics | |
537 SET num_replies = $row[my_num_replies] | |
538 WHERE id_topic = $row[id_topic]", | |
539 array( | |
540 ) | |
541 ); | |
542 '), | |
543 'message_function' => create_function('$row', ' | |
544 global $txt, $context; | |
545 | |
546 // Just joking? | |
547 if ($row[\'my_num_replies\'] == $row[\'num_replies\']) | |
548 return false; | |
549 | |
550 if ($row[\'num_replies\'] != $row[\'my_num_replies\']) | |
551 $context[\'repair_errors\'][] = sprintf($txt[\'repair_stats_topics_3\'], $row[\'id_topic\'], $row[\'num_replies\']); | |
552 | |
553 return true; | |
554 '), | |
555 ), | |
556 // Find topics with incorrect unapproved_posts. | |
557 'stats_topics3' => array( | |
558 'substeps' => array( | |
559 'step_size' => 1000, | |
560 'step_max' => ' | |
561 SELECT MAX(id_topic) | |
562 FROM {db_prefix}topics' | |
563 ), | |
564 'check_query' => ' | |
565 SELECT | |
566 t.id_topic, t.unapproved_posts, COUNT(mu.id_msg) AS my_unapproved_posts | |
567 FROM {db_prefix}topics AS t | |
568 LEFT JOIN {db_prefix}messages AS mu ON (mu.id_topic = t.id_topic AND mu.approved = 0) | |
569 WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
570 GROUP BY t.id_topic, t.unapproved_posts | |
571 HAVING unapproved_posts != COUNT(mu.id_msg) | |
572 ORDER BY t.id_topic', | |
573 'fix_processing' => create_function('$row', ' | |
574 global $smcFunc; | |
575 $row[\'my_unapproved_posts\'] = (int) $row[\'my_unapproved_posts\']; | |
576 | |
577 $smcFunc[\'db_query\'](\'\', " | |
578 UPDATE {db_prefix}topics | |
579 SET unapproved_posts = $row[my_unapproved_posts] | |
580 WHERE id_topic = $row[id_topic]", | |
581 array( | |
582 ) | |
583 ); | |
584 '), | |
585 'messages' => array('repair_stats_topics_4', 'id_topic', 'unapproved_posts'), | |
586 ), | |
587 // Find topics with nonexistent boards. | |
588 'missing_boards' => array( | |
589 'substeps' => array( | |
590 'step_size' => 1000, | |
591 'step_max' => ' | |
592 SELECT MAX(id_topic) | |
593 FROM {db_prefix}topics' | |
594 ), | |
595 'check_query' => ' | |
596 SELECT t.id_topic, t.id_board | |
597 FROM {db_prefix}topics AS t | |
598 LEFT JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) | |
599 WHERE b.id_board IS NULL | |
600 AND t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
601 ORDER BY t.id_board, t.id_topic', | |
602 'fix_query' => ' | |
603 SELECT t.id_board, COUNT(*) AS my_num_topics, COUNT(m.id_msg) AS my_num_posts | |
604 FROM {db_prefix}topics AS t | |
605 LEFT JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) | |
606 LEFT JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic) | |
607 WHERE b.id_board IS NULL | |
608 AND t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
609 GROUP BY t.id_board', | |
610 'fix_processing' => create_function('$row', ' | |
611 global $smcFunc, $salvageCatID; | |
612 createSalvageArea(); | |
613 | |
614 $row[\'my_num_topics\'] = (int) $row[\'my_num_topics\']; | |
615 $row[\'my_num_posts\'] = (int) $row[\'my_num_posts\']; | |
616 | |
617 $smcFunc[\'db_insert\'](\'\', | |
618 \'{db_prefix}boards\', | |
619 array(\'id_cat\' => \'int\', \'name\' => \'string\', \'description\' => \'string\', \'num_topics\' => \'int\', \'num_posts\' => \'int\', \'member_groups\' => \'string\'), | |
620 array($salvageCatID, \'Salvaged board\', \'\', $row[\'my_num_topics\'], $row[\'my_num_posts\'], \'1\'), | |
621 array(\'id_board\') | |
622 ); | |
623 $newBoardID = $smcFunc[\'db_insert_id\'](\'{db_prefix}boards\', \'id_board\'); | |
624 | |
625 $smcFunc[\'db_query\'](\'\', " | |
626 UPDATE {db_prefix}topics | |
627 SET id_board = $newBoardID | |
628 WHERE id_board = $row[id_board]", | |
629 array( | |
630 ) | |
631 ); | |
632 $smcFunc[\'db_query\'](\'\', " | |
633 UPDATE {db_prefix}messages | |
634 SET id_board = $newBoardID | |
635 WHERE id_board = $row[id_board]", | |
636 array( | |
637 ) | |
638 ); | |
639 '), | |
640 'messages' => array('repair_missing_boards', 'id_topic', 'id_board'), | |
641 ), | |
642 // Find boards with nonexistent categories. | |
643 'missing_categories' => array( | |
644 'check_query' => ' | |
645 SELECT b.id_board, b.id_cat | |
646 FROM {db_prefix}boards AS b | |
647 LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat) | |
648 WHERE c.id_cat IS NULL | |
649 ORDER BY b.id_cat, b.id_board', | |
650 'fix_collect' => array( | |
651 'index' => 'id_cat', | |
652 'process' => create_function('$cats', ' | |
653 global $smcFunc, $salvageCatID; | |
654 createSalvageArea(); | |
655 $smcFunc[\'db_query\'](\'\', " | |
656 UPDATE {db_prefix}boards | |
657 SET id_cat = $salvageCatID | |
658 WHERE id_cat IN ({array_int:categories})", | |
659 array( | |
660 \'categories\' => $cats | |
661 ) | |
662 ); | |
663 '), | |
664 ), | |
665 'messages' => array('repair_missing_categories', 'id_board', 'id_cat'), | |
666 ), | |
667 // Find messages with nonexistent members. | |
668 'missing_posters' => array( | |
669 'substeps' => array( | |
670 'step_size' => 2000, | |
671 'step_max' => ' | |
672 SELECT MAX(id_msg) | |
673 FROM {db_prefix}messages' | |
674 ), | |
675 'check_query' => ' | |
676 SELECT m.id_msg, m.id_member | |
677 FROM {db_prefix}messages AS m | |
678 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) | |
679 WHERE mem.id_member IS NULL | |
680 AND m.id_member != 0 | |
681 AND m.id_msg BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
682 ORDER BY m.id_msg', | |
683 // Last step-make sure all non-guest posters still exist. | |
684 'fix_collect' => array( | |
685 'index' => 'id_msg', | |
686 'process' => create_function('$msgs', ' | |
687 global $smcFunc; | |
688 $smcFunc[\'db_query\'](\'\', " | |
689 UPDATE {db_prefix}messages | |
690 SET id_member = 0 | |
691 WHERE id_msg IN ({array_int:msgs})", | |
692 array( | |
693 \'msgs\' => $msgs | |
694 ) | |
695 ); | |
696 '), | |
697 ), | |
698 'messages' => array('repair_missing_posters', 'id_msg', 'id_member'), | |
699 ), | |
700 // Find boards with nonexistent parents. | |
701 'missing_parents' => array( | |
702 'check_query' => ' | |
703 SELECT b.id_board, b.id_parent | |
704 FROM {db_prefix}boards AS b | |
705 LEFT JOIN {db_prefix}boards AS p ON (p.id_board = b.id_parent) | |
706 WHERE b.id_parent != 0 | |
707 AND (p.id_board IS NULL OR p.id_board = b.id_board) | |
708 ORDER BY b.id_parent, b.id_board', | |
709 'fix_collect' => array( | |
710 'index' => 'id_parent', | |
711 'process' => create_function('$parents', ' | |
712 global $smcFunc, $salvageBoardID, $salvageCatID; | |
713 createSalvageArea(); | |
714 $smcFunc[\'db_query\'](\'\', " | |
715 UPDATE {db_prefix}boards | |
716 SET id_parent = $salvageBoardID, id_cat = $salvageCatID, child_level = 1 | |
717 WHERE id_parent IN ({array_int:parents})", | |
718 array( | |
719 \'parents\' => $parents | |
720 ) | |
721 ); | |
722 '), | |
723 ), | |
724 'messages' => array('repair_missing_parents', 'id_board', 'id_parent'), | |
725 ), | |
726 'missing_polls' => array( | |
727 'substeps' => array( | |
728 'step_size' => 500, | |
729 'step_max' => ' | |
730 SELECT MAX(id_poll) | |
731 FROM {db_prefix}topics' | |
732 ), | |
733 'check_query' => ' | |
734 SELECT t.id_poll, t.id_topic | |
735 FROM {db_prefix}topics AS t | |
736 LEFT JOIN {db_prefix}polls AS p ON (p.id_poll = t.id_poll) | |
737 WHERE t.id_poll != 0 | |
738 AND t.id_poll BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
739 AND p.id_poll IS NULL', | |
740 'fix_collect' => array( | |
741 'index' => 'id_poll', | |
742 'process' => create_function('$polls', ' | |
743 global $smcFunc; | |
744 $smcFunc[\'db_query\'](\'\', " | |
745 UPDATE {db_prefix}topics | |
746 SET id_poll = 0 | |
747 WHERE id_poll IN ({array_int:polls})", | |
748 array( | |
749 \'polls\' => $polls | |
750 ) | |
751 ); | |
752 '), | |
753 ), | |
754 'messages' => array('repair_missing_polls', 'id_topic', 'id_poll'), | |
755 ), | |
756 'missing_calendar_topics' => array( | |
757 'substeps' => array( | |
758 'step_size' => 1000, | |
759 'step_max' => ' | |
760 SELECT MAX(id_topic) | |
761 FROM {db_prefix}calendar' | |
762 ), | |
763 'check_query' => ' | |
764 SELECT cal.id_topic, cal.id_event | |
765 FROM {db_prefix}calendar AS cal | |
766 LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = cal.id_topic) | |
767 WHERE cal.id_topic != 0 | |
768 AND cal.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
769 AND t.id_topic IS NULL | |
770 ORDER BY cal.id_topic', | |
771 'fix_collect' => array( | |
772 'index' => 'id_topic', | |
773 'process' => create_function('$events', ' | |
774 global $smcFunc; | |
775 $smcFunc[\'db_query\'](\'\', \' | |
776 UPDATE {db_prefix}calendar | |
777 SET id_topic = 0, id_board = 0 | |
778 WHERE id_topic IN ({array_int:events})\', | |
779 array( | |
780 \'events\' => $events | |
781 ) | |
782 ); | |
783 '), | |
784 ), | |
785 'messages' => array('repair_missing_calendar_topics', 'id_event', 'id_topic'), | |
786 ), | |
787 'missing_log_topics' => array( | |
788 'substeps' => array( | |
789 'step_size' => 150, | |
790 'step_max' => ' | |
791 SELECT MAX(id_member) | |
792 FROM {db_prefix}log_topics' | |
793 ), | |
794 'check_query' => ' | |
795 SELECT lt.id_topic | |
796 FROM {db_prefix}log_topics AS lt | |
797 LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = lt.id_topic) | |
798 WHERE t.id_topic IS NULL | |
799 AND lt.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH}', | |
800 'fix_collect' => array( | |
801 'index' => 'id_topic', | |
802 'process' => create_function('$topics', ' | |
803 global $smcFunc; | |
804 $smcFunc[\'db_query\'](\'\', " | |
805 DELETE FROM {db_prefix}log_topics | |
806 WHERE id_topic IN ({array_int:topics})", | |
807 array( | |
808 \'topics\' => $topics | |
809 ) | |
810 ); | |
811 '), | |
812 ), | |
813 'messages' => array('repair_missing_log_topics', 'id_topic'), | |
814 ), | |
815 'missing_log_topics_members' => array( | |
816 'substeps' => array( | |
817 'step_size' => 150, | |
818 'step_max' => ' | |
819 SELECT MAX(id_member) | |
820 FROM {db_prefix}log_topics' | |
821 ), | |
822 'check_query' => ' | |
823 SELECT lt.id_member | |
824 FROM {db_prefix}log_topics AS lt | |
825 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lt.id_member) | |
826 WHERE mem.id_member IS NULL | |
827 AND lt.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
828 GROUP BY lt.id_member', | |
829 'fix_collect' => array( | |
830 'index' => 'id_member', | |
831 'process' => create_function('$members', ' | |
832 global $smcFunc; | |
833 $smcFunc[\'db_query\'](\'\', " | |
834 DELETE FROM {db_prefix}log_topics | |
835 WHERE id_member IN ({array_int:members})", | |
836 array( | |
837 \'members\' => $members | |
838 ) | |
839 ); | |
840 '), | |
841 ), | |
842 'messages' => array('repair_missing_log_topics_members', 'id_member'), | |
843 ), | |
844 'missing_log_boards' => array( | |
845 'substeps' => array( | |
846 'step_size' => 500, | |
847 'step_max' => ' | |
848 SELECT MAX(id_member) | |
849 FROM {db_prefix}log_boards' | |
850 ), | |
851 'check_query' => ' | |
852 SELECT lb.id_board | |
853 FROM {db_prefix}log_boards AS lb | |
854 LEFT JOIN {db_prefix}boards AS b ON (b.id_board = lb.id_board) | |
855 WHERE b.id_board IS NULL | |
856 AND lb.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
857 GROUP BY lb.id_board', | |
858 'fix_collect' => array( | |
859 'index' => 'id_board', | |
860 'process' => create_function('$boards', ' | |
861 global $smcFunc; | |
862 $smcFunc[\'db_query\'](\'\', " | |
863 DELETE FROM {db_prefix}log_boards | |
864 WHERE id_board IN ({array_int:boards})", | |
865 array( | |
866 \'boards\' => $boards | |
867 ) | |
868 ); | |
869 '), | |
870 ), | |
871 'messages' => array('repair_missing_log_boards', 'id_board'), | |
872 ), | |
873 'missing_log_boards_members' => array( | |
874 'substeps' => array( | |
875 'step_size' => 500, | |
876 'step_max' => ' | |
877 SELECT MAX(id_member) | |
878 FROM {db_prefix}log_boards' | |
879 ), | |
880 'check_query' => ' | |
881 SELECT lb.id_member | |
882 FROM {db_prefix}log_boards AS lb | |
883 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lb.id_member) | |
884 WHERE mem.id_member IS NULL | |
885 AND lb.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
886 GROUP BY lb.id_member', | |
887 'fix_collect' => array( | |
888 'index' => 'id_member', | |
889 'process' => create_function('$members', ' | |
890 global $smcFunc; | |
891 $smcFunc[\'db_query\'](\'\', " | |
892 DELETE FROM {db_prefix}log_boards | |
893 WHERE id_member IN ({array_int:members})", | |
894 array( | |
895 \'members\' => $members | |
896 ) | |
897 ); | |
898 '), | |
899 ), | |
900 'messages' => array('repair_missing_log_boards_members', 'id_member'), | |
901 ), | |
902 'missing_log_mark_read' => array( | |
903 'substeps' => array( | |
904 'step_size' => 500, | |
905 'step_max' => ' | |
906 SELECT MAX(id_member) | |
907 FROM {db_prefix}log_mark_read' | |
908 ), | |
909 'check_query' => ' | |
910 SELECT lmr.id_board | |
911 FROM {db_prefix}log_mark_read AS lmr | |
912 LEFT JOIN {db_prefix}boards AS b ON (b.id_board = lmr.id_board) | |
913 WHERE b.id_board IS NULL | |
914 AND lmr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
915 GROUP BY lmr.id_board', | |
916 'fix_collect' => array( | |
917 'index' => 'id_board', | |
918 'process' => create_function('$boards', ' | |
919 global $smcFunc; | |
920 $smcFunc[\'db_query\'](\'\', " | |
921 DELETE FROM {db_prefix}log_mark_read | |
922 WHERE id_board IN ({array_int:boards})", | |
923 array( | |
924 \'boards\' => $boards | |
925 ) | |
926 ); | |
927 '), | |
928 ), | |
929 'messages' => array('repair_missing_log_mark_read', 'id_board'), | |
930 ), | |
931 'missing_log_mark_read_members' => array( | |
932 'substeps' => array( | |
933 'step_size' => 500, | |
934 'step_max' => ' | |
935 SELECT MAX(id_member) | |
936 FROM {db_prefix}log_mark_read' | |
937 ), | |
938 'check_query' => ' | |
939 SELECT lmr.id_member | |
940 FROM {db_prefix}log_mark_read AS lmr | |
941 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lmr.id_member) | |
942 WHERE mem.id_member IS NULL | |
943 AND lmr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
944 GROUP BY lmr.id_member', | |
945 'fix_collect' => array( | |
946 'index' => 'id_member', | |
947 'process' => create_function('$members', ' | |
948 global $smcFunc; | |
949 $smcFunc[\'db_query\'](\'\', " | |
950 DELETE FROM {db_prefix}log_mark_read | |
951 WHERE id_member IN ({array_int:members})", | |
952 array( | |
953 \'members\' => $members | |
954 ) | |
955 ); | |
956 '), | |
957 ), | |
958 'messages' => array('repair_missing_log_mark_read_members', 'id_member'), | |
959 ), | |
960 'missing_pms' => array( | |
961 'substeps' => array( | |
962 'step_size' => 500, | |
963 'step_max' => ' | |
964 SELECT MAX(id_pm) | |
965 FROM {db_prefix}pm_recipients' | |
966 ), | |
967 'check_query' => ' | |
968 SELECT pmr.id_pm | |
969 FROM {db_prefix}pm_recipients AS pmr | |
970 LEFT JOIN {db_prefix}personal_messages AS pm ON (pm.id_pm = pmr.id_pm) | |
971 WHERE pm.id_pm IS NULL | |
972 AND pmr.id_pm BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
973 GROUP BY pmr.id_pm', | |
974 'fix_collect' => array( | |
975 'index' => 'id_pm', | |
976 'process' => create_function('$pms', ' | |
977 global $smcFunc; | |
978 $smcFunc[\'db_query\'](\'\', " | |
979 DELETE FROM {db_prefix}pm_recipients | |
980 WHERE id_pm IN ({array_int:pms})", | |
981 array( | |
982 \'pms\' => $pms | |
983 ) | |
984 ); | |
985 '), | |
986 ), | |
987 'messages' => array('repair_missing_pms', 'id_pm'), | |
988 ), | |
989 'missing_recipients' => array( | |
990 'substeps' => array( | |
991 'step_size' => 500, | |
992 'step_max' => ' | |
993 SELECT MAX(id_member) | |
994 FROM {db_prefix}pm_recipients' | |
995 ), | |
996 'check_query' => ' | |
997 SELECT pmr.id_member | |
998 FROM {db_prefix}pm_recipients AS pmr | |
999 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = pmr.id_member) | |
1000 WHERE pmr.id_member != 0 | |
1001 AND pmr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1002 AND mem.id_member IS NULL | |
1003 GROUP BY pmr.id_member', | |
1004 'fix_collect' => array( | |
1005 'index' => 'id_member', | |
1006 'process' => create_function('$members', ' | |
1007 global $smcFunc; | |
1008 $smcFunc[\'db_query\'](\'\', " | |
1009 DELETE FROM {db_prefix}pm_recipients | |
1010 WHERE id_member IN ({array_int:members})", | |
1011 array( | |
1012 \'members\' => $members | |
1013 ) | |
1014 ); | |
1015 '), | |
1016 ), | |
1017 'messages' => array('repair_missing_recipients', 'id_member'), | |
1018 ), | |
1019 'missing_senders' => array( | |
1020 'substeps' => array( | |
1021 'step_size' => 500, | |
1022 'step_max' => ' | |
1023 SELECT MAX(id_pm) | |
1024 FROM {db_prefix}personal_messages' | |
1025 ), | |
1026 'check_query' => ' | |
1027 SELECT pm.id_pm, pm.id_member_from | |
1028 FROM {db_prefix}personal_messages AS pm | |
1029 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = pm.id_member_from) | |
1030 WHERE pm.id_member_from != 0 | |
1031 AND pm.id_pm BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1032 AND mem.id_member IS NULL', | |
1033 'fix_collect' => array( | |
1034 'index' => 'id_pm', | |
1035 'process' => create_function('$guestMessages', ' | |
1036 global $smcFunc; | |
1037 $smcFunc[\'db_query\'](\'\', " | |
1038 UPDATE {db_prefix}personal_messages | |
1039 SET id_member_from = 0 | |
1040 WHERE id_pm IN ({array_int:guestMessages})", | |
1041 array( | |
1042 \'guestMessages\' => $guestMessages | |
1043 )); | |
1044 '), | |
1045 ), | |
1046 'messages' => array('repair_missing_senders', 'id_pm', 'id_member_from'), | |
1047 ), | |
1048 'missing_notify_members' => array( | |
1049 'substeps' => array( | |
1050 'step_size' => 500, | |
1051 'step_max' => ' | |
1052 SELECT MAX(id_member) | |
1053 FROM {db_prefix}log_notify' | |
1054 ), | |
1055 'check_query' => ' | |
1056 SELECT ln.id_member | |
1057 FROM {db_prefix}log_notify AS ln | |
1058 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = ln.id_member) | |
1059 WHERE ln.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1060 AND mem.id_member IS NULL | |
1061 GROUP BY ln.id_member', | |
1062 'fix_collect' => array( | |
1063 'index' => 'id_member', | |
1064 'process' => create_function('$members', ' | |
1065 global $smcFunc; | |
1066 $smcFunc[\'db_query\'](\'\', " | |
1067 DELETE FROM {db_prefix}log_notify | |
1068 WHERE id_member IN ({array_int:members})", | |
1069 array( | |
1070 \'members\' => $members | |
1071 ) | |
1072 ); | |
1073 '), | |
1074 ), | |
1075 'messages' => array('repair_missing_notify_members', 'id_member'), | |
1076 ), | |
1077 'missing_cached_subject' => array( | |
1078 'substeps' => array( | |
1079 'step_size' => 100, | |
1080 'step_max' => ' | |
1081 SELECT MAX(id_topic) | |
1082 FROM {db_prefix}topics' | |
1083 ), | |
1084 'check_query' => ' | |
1085 SELECT t.id_topic, fm.subject | |
1086 FROM {db_prefix}topics AS t | |
1087 INNER JOIN {db_prefix}messages AS fm ON (fm.id_msg = t.id_first_msg) | |
1088 LEFT JOIN {db_prefix}log_search_subjects AS lss ON (lss.id_topic = t.id_topic) | |
1089 WHERE t.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1090 AND lss.id_topic IS NULL', | |
1091 'fix_full_processing' => create_function('$result', ' | |
1092 global $smcFunc; | |
1093 | |
1094 $inserts = array(); | |
1095 while ($row = $smcFunc[\'db_fetch_assoc\']($result)) | |
1096 { | |
1097 foreach (text2words($row[\'subject\']) as $word) | |
1098 $inserts[] = array($word, $row[\'id_topic\']); | |
1099 if (count($inserts) > 500) | |
1100 { | |
1101 $smcFunc[\'db_insert\'](\'ignore\', | |
1102 "{db_prefix}log_search_subjects", | |
1103 array(\'word\' => \'string\', \'id_topic\' => \'int\'), | |
1104 $inserts, | |
1105 array(\'word\', \'id_topic\') | |
1106 ); | |
1107 $inserts = array(); | |
1108 } | |
1109 | |
1110 } | |
1111 | |
1112 if (!empty($inserts)) | |
1113 $smcFunc[\'db_insert\'](\'ignore\', | |
1114 "{db_prefix}log_search_subjects", | |
1115 array(\'word\' => \'string\', \'id_topic\' => \'int\'), | |
1116 $inserts, | |
1117 array(\'word\', \'id_topic\') | |
1118 ); | |
1119 '), | |
1120 'message_function' => create_function('$row', ' | |
1121 global $txt, $context; | |
1122 | |
1123 if (count(text2words($row[\'subject\'])) != 0) | |
1124 { | |
1125 $context[\'repair_errors\'][] = sprintf($txt[\'repair_missing_cached_subject\'], $row[\'id_topic\']); | |
1126 return true; | |
1127 } | |
1128 | |
1129 return false; | |
1130 '), | |
1131 ), | |
1132 'missing_topic_for_cache' => array( | |
1133 'substeps' => array( | |
1134 'step_size' => 50, | |
1135 'step_max' => ' | |
1136 SELECT MAX(id_topic) | |
1137 FROM {db_prefix}log_search_subjects' | |
1138 ), | |
1139 'check_query' => ' | |
1140 SELECT lss.id_topic, lss.word | |
1141 FROM {db_prefix}log_search_subjects AS lss | |
1142 LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = lss.id_topic) | |
1143 WHERE lss.id_topic BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1144 AND t.id_topic IS NULL', | |
1145 'fix_collect' => array( | |
1146 'index' => 'id_topic', | |
1147 'process' => create_function('$deleteTopics', ' | |
1148 global $smcFunc; | |
1149 $smcFunc[\'db_query\'](\'\', " | |
1150 DELETE FROM {db_prefix}log_search_subjects | |
1151 WHERE id_topic IN ({array_int:deleteTopics})", | |
1152 array( | |
1153 \'deleteTopics\' => $deleteTopics | |
1154 ) | |
1155 ); | |
1156 '), | |
1157 ), | |
1158 'messages' => array('repair_missing_topic_for_cache', 'word'), | |
1159 ), | |
1160 'missing_member_vote' => array( | |
1161 'substeps' => array( | |
1162 'step_size' => 500, | |
1163 'step_max' => ' | |
1164 SELECT MAX(id_member) | |
1165 FROM {db_prefix}log_polls' | |
1166 ), | |
1167 'check_query' => ' | |
1168 SELECT lp.id_poll, lp.id_member | |
1169 FROM {db_prefix}log_polls AS lp | |
1170 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lp.id_member) | |
1171 WHERE lp.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1172 AND lp.id_member > 0 | |
1173 AND mem.id_member IS NULL', | |
1174 'fix_collect' => array( | |
1175 'index' => 'id_member', | |
1176 'process' => create_function('$members', ' | |
1177 global $smcFunc; | |
1178 $smcFunc[\'db_query\'](\'\', " | |
1179 DELETE FROM {db_prefix}log_polls | |
1180 WHERE id_member IN ({array_int:members})", | |
1181 array( | |
1182 \'members\' => $members | |
1183 ) | |
1184 ); | |
1185 '), | |
1186 ), | |
1187 'messages' => array('repair_missing_log_poll_member', 'id_poll', 'id_member'), | |
1188 ), | |
1189 'missing_log_poll_vote' => array( | |
1190 'substeps' => array( | |
1191 'step_size' => 500, | |
1192 'step_max' => ' | |
1193 SELECT MAX(id_poll) | |
1194 FROM {db_prefix}log_polls' | |
1195 ), | |
1196 'check_query' => ' | |
1197 SELECT lp.id_poll, lp.id_member | |
1198 FROM {db_prefix}log_polls AS lp | |
1199 LEFT JOIN {db_prefix}polls AS p ON (p.id_poll = lp.id_poll) | |
1200 WHERE lp.id_poll BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1201 AND p.id_poll IS NULL', | |
1202 'fix_collect' => array( | |
1203 'index' => 'id_poll', | |
1204 'process' => create_function('$polls', ' | |
1205 global $smcFunc; | |
1206 $smcFunc[\'db_query\'](\'\', " | |
1207 DELETE FROM {db_prefix}log_polls | |
1208 WHERE id_poll IN ({array_int:polls})", | |
1209 array( | |
1210 \'polls\' => $polls | |
1211 ) | |
1212 ); | |
1213 '), | |
1214 ), | |
1215 'messages' => array('repair_missing_log_poll_vote', 'id_member', 'id_poll'), | |
1216 ), | |
1217 'report_missing_comments' => array( | |
1218 'substeps' => array( | |
1219 'step_size' => 500, | |
1220 'step_max' => ' | |
1221 SELECT MAX(id_report) | |
1222 FROM {db_prefix}log_reported' | |
1223 ), | |
1224 'check_query' => ' | |
1225 SELECT lr.id_report, lr.subject | |
1226 FROM {db_prefix}log_reported AS lr | |
1227 LEFT JOIN {db_prefix}log_reported_comments AS lrc ON (lrc.id_report = lr.id_report) | |
1228 WHERE lr.id_report BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1229 AND lrc.id_report IS NULL', | |
1230 'fix_collect' => array( | |
1231 'index' => 'id_report', | |
1232 'process' => create_function('$reports', ' | |
1233 global $smcFunc; | |
1234 $smcFunc[\'db_query\'](\'\', " | |
1235 DELETE FROM {db_prefix}log_reported | |
1236 WHERE id_report IN ({array_int:reports})", | |
1237 array( | |
1238 \'reports\' => $reports | |
1239 ) | |
1240 ); | |
1241 '), | |
1242 ), | |
1243 'messages' => array('repair_report_missing_comments', 'id_report', 'subject'), | |
1244 ), | |
1245 'comments_missing_report' => array( | |
1246 'substeps' => array( | |
1247 'step_size' => 200, | |
1248 'step_max' => ' | |
1249 SELECT MAX(id_report) | |
1250 FROM {db_prefix}log_reported_comments' | |
1251 ), | |
1252 'check_query' => ' | |
1253 SELECT lrc.id_report, lrc.membername | |
1254 FROM {db_prefix}log_reported_comments AS lrc | |
1255 LEFT JOIN {db_prefix}log_reported AS lr ON (lr.id_report = lrc.id_report) | |
1256 WHERE lrc.id_report BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1257 AND lr.id_report IS NULL', | |
1258 'fix_collect' => array( | |
1259 'index' => 'id_report', | |
1260 'process' => create_function('$reports', ' | |
1261 global $smcFunc; | |
1262 $smcFunc[\'db_query\'](\'\', " | |
1263 DELETE FROM {db_prefix}log_reported_comments | |
1264 WHERE id_report IN ({array_int:reports})", | |
1265 array( | |
1266 \'reports\' => $reports | |
1267 ) | |
1268 ); | |
1269 '), | |
1270 ), | |
1271 'messages' => array('repair_comments_missing_report', 'id_report', 'membername'), | |
1272 ), | |
1273 'group_request_missing_member' => array( | |
1274 'substeps' => array( | |
1275 'step_size' => 200, | |
1276 'step_max' => ' | |
1277 SELECT MAX(id_member) | |
1278 FROM {db_prefix}log_group_requests' | |
1279 ), | |
1280 'check_query' => ' | |
1281 SELECT lgr.id_member | |
1282 FROM {db_prefix}log_group_requests AS lgr | |
1283 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lgr.id_member) | |
1284 WHERE lgr.id_member BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1285 AND mem.id_member IS NULL | |
1286 GROUP BY lgr.id_member', | |
1287 'fix_collect' => array( | |
1288 'index' => 'id_member', | |
1289 'process' => create_function('$members', ' | |
1290 global $smcFunc; | |
1291 $smcFunc[\'db_query\'](\'\', " | |
1292 DELETE FROM {db_prefix}log_group_requests | |
1293 WHERE id_member IN ({array_int:members})", | |
1294 array( | |
1295 \'members\' => $members | |
1296 ) | |
1297 ); | |
1298 '), | |
1299 ), | |
1300 'messages' => array('repair_group_request_missing_member', 'id_member'), | |
1301 ), | |
1302 'group_request_missing_group' => array( | |
1303 'substeps' => array( | |
1304 'step_size' => 200, | |
1305 'step_max' => ' | |
1306 SELECT MAX(id_group) | |
1307 FROM {db_prefix}log_group_requests' | |
1308 ), | |
1309 'check_query' => ' | |
1310 SELECT lgr.id_group | |
1311 FROM {db_prefix}log_group_requests AS lgr | |
1312 LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = lgr.id_group) | |
1313 WHERE lgr.id_group BETWEEN {STEP_LOW} AND {STEP_HIGH} | |
1314 AND mg.id_group IS NULL | |
1315 GROUP BY lgr.id_group', | |
1316 'fix_collect' => array( | |
1317 'index' => 'id_group', | |
1318 'process' => create_function('$groups', ' | |
1319 global $smcFunc; | |
1320 $smcFunc[\'db_query\'](\'\', \' | |
1321 DELETE FROM {db_prefix}log_group_requests | |
1322 WHERE id_group IN ({array_int:groups})\', | |
1323 array( | |
1324 \'groups\' => $groups | |
1325 ) | |
1326 ); | |
1327 '), | |
1328 ), | |
1329 'messages' => array('repair_group_request_missing_group', 'id_group'), | |
1330 ), | |
1331 ); | |
1332 } | |
1333 | |
1334 function findForumErrors($do_fix = false) | |
1335 { | |
1336 global $context, $txt, $smcFunc, $errorTests, $db_cache, $db_temp_cache; | |
1337 | |
1338 // This may take some time... | |
1339 @set_time_limit(600); | |
1340 | |
1341 $to_fix = !empty($_SESSION['repairboards_to_fix']) ? $_SESSION['repairboards_to_fix'] : array(); | |
1342 $context['repair_errors'] = isset($_SESSION['repairboards_to_fix2']) ? $_SESSION['repairboards_to_fix2'] : array(); | |
1343 | |
1344 $_GET['step'] = empty($_GET['step']) ? 0 : (int) $_GET['step']; | |
1345 $_GET['substep'] = empty($_GET['substep']) ? 0 : (int) $_GET['substep']; | |
1346 | |
1347 // Don't allow the cache to get too full. | |
1348 $db_temp_cache = $db_cache; | |
1349 $db_cache = ''; | |
1350 | |
1351 $context['total_steps'] = count($errorTests); | |
1352 | |
1353 // For all the defined error types do the necessary tests. | |
1354 $current_step = -1; | |
1355 $total_queries = 0; | |
1356 foreach ($errorTests as $error_type => $test) | |
1357 { | |
1358 $current_step++; | |
1359 | |
1360 // Already done this? | |
1361 if ($_GET['step'] > $current_step) | |
1362 continue; | |
1363 | |
1364 // If we're fixing it but it ain't broke why try? | |
1365 if ($do_fix && !in_array($error_type, $to_fix)) | |
1366 { | |
1367 $_GET['step']++; | |
1368 continue; | |
1369 } | |
1370 | |
1371 // Has it got substeps? | |
1372 if (isset($test['substeps'])) | |
1373 { | |
1374 $step_size = isset($test['substeps']['step_size']) ? $test['substeps']['step_size'] : 100; | |
1375 $request = $smcFunc['db_query']('', | |
1376 $test['substeps']['step_max'], | |
1377 array( | |
1378 ) | |
1379 ); | |
1380 list ($step_max) = $smcFunc['db_fetch_row']($request); | |
1381 | |
1382 $total_queries++; | |
1383 $smcFunc['db_free_result']($request); | |
1384 } | |
1385 | |
1386 // We in theory keep doing this... the substeps. | |
1387 $done = false; | |
1388 while (!$done) | |
1389 { | |
1390 // Make sure there's at least one ID to test. | |
1391 if (isset($test['substeps']) && empty($step_max)) | |
1392 break; | |
1393 | |
1394 // What is the testing query (Changes if we are testing or fixing) | |
1395 if (!$do_fix) | |
1396 $test_query = 'check_query'; | |
1397 else | |
1398 $test_query = isset($test['fix_query']) ? 'fix_query' : 'check_query'; | |
1399 | |
1400 // Do the test... | |
1401 $request = $smcFunc['db_query']('', | |
1402 isset($test['substeps']) ? strtr($test[$test_query], array('{STEP_LOW}' => $_GET['substep'], '{STEP_HIGH}' => $_GET['substep'] + $step_size - 1)) : $test[$test_query], | |
1403 array( | |
1404 ) | |
1405 ); | |
1406 $needs_fix = false; | |
1407 | |
1408 // Does it need a fix? | |
1409 if (!empty($test['check_type']) && $test['check_type'] == 'count') | |
1410 list ($needs_fix) = $smcFunc['db_fetch_row']($request); | |
1411 else | |
1412 $needs_fix = $smcFunc['db_num_rows']($request); | |
1413 | |
1414 $total_queries++; | |
1415 | |
1416 if ($needs_fix) | |
1417 { | |
1418 // What about a message to the user? | |
1419 if (!$do_fix) | |
1420 { | |
1421 // Assume need to fix. | |
1422 $found_errors = true; | |
1423 | |
1424 if (isset($test['message'])) | |
1425 $context['repair_errors'][] = $txt[$test['message']]; | |
1426 | |
1427 // One per row! | |
1428 elseif (isset($test['messages'])) | |
1429 { | |
1430 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
1431 { | |
1432 $variables = $test['messages']; | |
1433 foreach ($variables as $k => $v) | |
1434 { | |
1435 if ($k == 0 && isset($txt[$v])) | |
1436 $variables[$k] = $txt[$v]; | |
1437 elseif ($k > 0 && isset($row[$v])) | |
1438 $variables[$k] = $row[$v]; | |
1439 } | |
1440 $context['repair_errors'][] = call_user_func_array('sprintf', $variables); | |
1441 } | |
1442 } | |
1443 | |
1444 // A function to process? | |
1445 elseif (isset($test['message_function'])) | |
1446 { | |
1447 // Find out if there are actually errors. | |
1448 $found_errors = false; | |
1449 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
1450 $found_errors |= $test['message_function']($row); | |
1451 } | |
1452 | |
1453 // Actually have something to fix? | |
1454 if ($found_errors) | |
1455 $to_fix[] = $error_type; | |
1456 } | |
1457 | |
1458 // We want to fix, we need to fix - so work out what exactly to do! | |
1459 else | |
1460 { | |
1461 // Are we simply getting a collection of ids? | |
1462 if (isset($test['fix_collect'])) | |
1463 { | |
1464 $ids = array(); | |
1465 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
1466 $ids[] = $row[$test['fix_collect']['index']]; | |
1467 if (!empty($ids)) | |
1468 { | |
1469 // Fix it! | |
1470 $test['fix_collect']['process']($ids); | |
1471 } | |
1472 } | |
1473 | |
1474 // Simply executing a fix it query? | |
1475 elseif (isset($test['fix_it_query'])) | |
1476 $smcFunc['db_query']('', | |
1477 $test['fix_it_query'], | |
1478 array( | |
1479 ) | |
1480 ); | |
1481 | |
1482 // Do we have some processing to do? | |
1483 elseif (isset($test['fix_processing'])) | |
1484 { | |
1485 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
1486 $test['fix_processing']($row); | |
1487 } | |
1488 | |
1489 // What about the full set of processing? | |
1490 elseif (isset($test['fix_full_processing'])) | |
1491 $test['fix_full_processing']($request); | |
1492 | |
1493 // Do we have other things we need to fix as a result? | |
1494 if (!empty($test['force_fix'])) | |
1495 { | |
1496 foreach ($test['force_fix'] as $item) | |
1497 if (!in_array($item, $to_fix)) | |
1498 $to_fix[] = $item; | |
1499 } | |
1500 } | |
1501 } | |
1502 | |
1503 // Free the result. | |
1504 $smcFunc['db_free_result']($request); | |
1505 // Keep memory down. | |
1506 $db_cache = ''; | |
1507 | |
1508 // Are we done yet? | |
1509 if (isset($test['substeps'])) | |
1510 { | |
1511 $_GET['substep'] += $step_size; | |
1512 // Not done? | |
1513 if ($_GET['substep'] <= $step_max) | |
1514 { | |
1515 pauseRepairProcess($to_fix, $error_type, $step_max); | |
1516 } | |
1517 else | |
1518 $done = true; | |
1519 } | |
1520 else | |
1521 $done = true; | |
1522 | |
1523 // Don't allow more than 1000 queries at a time. | |
1524 if ($total_queries >= 1000) | |
1525 pauseRepairProcess($to_fix, $error_type, $step_max, true); | |
1526 } | |
1527 | |
1528 // Keep going. | |
1529 $_GET['step']++; | |
1530 $_GET['substep'] = 0; | |
1531 | |
1532 $to_fix = array_unique($to_fix); | |
1533 | |
1534 // If we're doing fixes and this needed a fix and we're all done then don't do it again. | |
1535 if ($do_fix) | |
1536 { | |
1537 $key = array_search($error_type, $to_fix); | |
1538 if ($key !== false && isset($to_fix[$key])) | |
1539 unset($to_fix[$key]); | |
1540 } | |
1541 | |
1542 // Are we done? | |
1543 pauseRepairProcess($to_fix, $error_type); | |
1544 } | |
1545 | |
1546 // Restore the cache. | |
1547 $db_cache = $db_temp_cache; | |
1548 | |
1549 return $to_fix; | |
1550 } | |
1551 | |
1552 // Create a salvage area for repair purposes. | |
1553 function createSalvageArea() | |
1554 { | |
1555 global $txt, $language, $salvageBoardID, $salvageCatID, $smcFunc; | |
1556 static $createOnce = false; | |
1557 | |
1558 // Have we already created it? | |
1559 if ($createOnce) | |
1560 return; | |
1561 else | |
1562 $createOnce = true; | |
1563 | |
1564 // Back to the forum's default language. | |
1565 loadLanguage('Admin', $language); | |
1566 | |
1567 // Check to see if a 'Salvage Category' exists, if not => insert one. | |
1568 $result = $smcFunc['db_query']('', ' | |
1569 SELECT id_cat | |
1570 FROM {db_prefix}categories | |
1571 WHERE name = {string:cat_name} | |
1572 LIMIT 1', | |
1573 array( | |
1574 'cat_name' => $txt['salvaged_category_name'], | |
1575 ) | |
1576 ); | |
1577 if ($smcFunc['db_num_rows']($result) != 0) | |
1578 list ($salvageCatID) = $smcFunc['db_fetch_row']($result); | |
1579 $smcFunc['db_free_result']($result); | |
1580 | |
1581 if (empty($salveageCatID)) | |
1582 { | |
1583 $smcFunc['db_insert']('', | |
1584 '{db_prefix}categories', | |
1585 array('name' => 'string-255', 'cat_order' => 'int'), | |
1586 array($txt['salvaged_category_name'], -1), | |
1587 array('id_cat') | |
1588 ); | |
1589 | |
1590 if ($smcFunc['db_affected_rows']() <= 0) | |
1591 { | |
1592 loadLanguage('Admin'); | |
1593 fatal_lang_error('salvaged_category_error', false); | |
1594 } | |
1595 | |
1596 $salvageCatID = $smcFunc['db_insert_id']('{db_prefix}categories', 'id_cat'); | |
1597 } | |
1598 | |
1599 // Check to see if a 'Salvage Board' exists, if not => insert one. | |
1600 $result = $smcFunc['db_query']('', ' | |
1601 SELECT id_board | |
1602 FROM {db_prefix}boards | |
1603 WHERE id_cat = {int:id_cat} | |
1604 AND name = {string:board_name} | |
1605 LIMIT 1', | |
1606 array( | |
1607 'id_cat' => $salvageCatID, | |
1608 'board_name' => $txt['salvaged_board_name'], | |
1609 ) | |
1610 ); | |
1611 if ($smcFunc['db_num_rows']($result) != 0) | |
1612 list ($salvageBoardID) = $smcFunc['db_fetch_row']($result); | |
1613 $smcFunc['db_free_result']($result); | |
1614 | |
1615 if (empty($salvageBoardID)) | |
1616 { | |
1617 $smcFunc['db_insert']('', | |
1618 '{db_prefix}boards', | |
1619 array('name' => 'string-255', 'description' => 'string-255', 'id_cat' => 'int', 'member_groups' => 'string', 'board_order' => 'int', 'redirect' => 'string'), | |
1620 array($txt['salvaged_board_name'], $txt['salvaged_board_description'], $salvageCatID, '1', -1, ''), | |
1621 array('id_board') | |
1622 ); | |
1623 | |
1624 if ($smcFunc['db_affected_rows']() <= 0) | |
1625 { | |
1626 loadLanguage('Admin'); | |
1627 fatal_lang_error('salvaged_board_error', false); | |
1628 } | |
1629 | |
1630 $salvageBoardID = $smcFunc['db_insert_id']('{db_prefix}boards', 'id_board'); | |
1631 } | |
1632 | |
1633 $smcFunc['db_query']('alter_table_boards', ' | |
1634 ALTER TABLE {db_prefix}boards | |
1635 ORDER BY board_order', | |
1636 array( | |
1637 ) | |
1638 ); | |
1639 | |
1640 // Restore the user's language. | |
1641 loadLanguage('Admin'); | |
1642 } | |
1643 | |
1644 ?> |