function check_merge(&$useraccount, &$mylogins, $tolink) { global $qa_cached_logged_in_user, $qa_logged_in_userid_checked; $userid = $findid = $useraccount['userid']; $findemail = $useraccount['oemail']; // considering this is an openid user, so use the openid email if (empty($findemail)) { $findemail = $useraccount['email']; // fallback } if ($tolink) { // user is logged in with $userid but wants to merge $findid $findemail = null; $findid = $tolink['userid']; } else { if (qa_get('confirm') == 2 || qa_post_text('confirm') == 2) { // bogus confirm page, stop right here qa_redirect('logins'); } } // find other un-linked accounts with the same email $otherlogins = qa_db_user_login_find_other__open($findid, $findemail, $userid); if (qa_clicked('domerge') && !empty($otherlogins)) { // if cancel was requested, just redirect if ($_POST['domerge'] == 0) { $tourl = qa_post_text('to'); if (!empty($tourl)) { qa_redirect($tourl); } else { qa_redirect($tolink ? 'logins' : ''); } } // a request to merge (link) multiple accounts was made require_once QA_INCLUDE_DIR . 'qa-app-users-edit.php'; $recompute = false; $email = null; $baseid = $_POST["base{$_POST['domerge']}"]; // POST[base1] or POST[base2] // see which account was selected, if any if ($baseid != 0) { // just in case foreach ($otherlogins as $login) { // see if this is the currently logged in account $loginid = $login['details']['userid']; $is_current = $loginid == $userid; // see if this user was selected for merge if (isset($_POST["user_{$loginid}"]) || $is_current) { if ($baseid != $loginid) { // this account should be deleted as it's different from the selected base id if (!empty($login['logins'])) { // update all associated logins qa_db_user_login_sync(true); qa_db_user_login_replace_userid__open($loginid, $baseid); qa_db_user_login_sync(false); } // delete old user but keep the email qa_delete_user($loginid); $recompute = true; if (empty($email)) { $email = $login['details']['email']; } if (empty($email)) { $email = $login['details']['oemail']; } } } } } // recompute the stats, if needed if ($recompute) { require_once QA_INCLUDE_DIR . 'qa-db-points.php'; qa_db_userpointscount_update(); // check if the current account has been deleted if ($userid != $baseid) { $oldsrc = $useraccount['sessionsource']; qa_set_logged_in_user($baseid, $useraccount['handle'], false, $oldsrc); $useraccount = qa_db_user_find_by_id__open($baseid); $userid = $baseid; // clear some cached data qa_db_flush_pending_result('loggedinuser'); $qa_logged_in_userid_checked = false; unset($qa_cached_logged_in_user); } // also check the email address on the remaining user account if (empty($useraccount['email']) && !empty($email)) { // update the account if the email address is not used anymore $emailusers = qa_db_user_find_by_email($email); if (count($emailusers) == 0) { qa_db_user_set($userid, 'email', $email); $useraccount['email'] = $email; // to show on the page } } } $conf = qa_post_text('confirm'); $tourl = qa_post_text('to'); if ($conf) { $tourl = qa_post_text('to'); if (!empty($tourl)) { qa_redirect($tourl); } else { qa_redirect($tolink ? 'logins' : ''); } } // update the arrays $otherlogins = qa_db_user_login_find_other__open($userid, $findemail); $mylogins = qa_db_user_login_find_mine__open($userid); } // remove the current user id unset($otherlogins[$userid]); return $otherlogins; }
function qa_recalc_perform_step(&$state) { $continue = false; @(list($operation, $length, $next, $done) = explode("\t", $state)); switch ($operation) { case 'doreindexcontent': qa_recalc_transition($state, 'doreindexcontent_pagereindex'); break; case 'doreindexcontent_pagereindex': $pages = qa_db_pages_get_for_reindexing($next, 10); if (count($pages)) { require_once QA_INCLUDE_DIR . 'app/format.php'; $lastpageid = max(array_keys($pages)); foreach ($pages as $pageid => $page) { if (!($page['flags'] & QA_PAGE_FLAGS_EXTERNAL)) { $searchmodules = qa_load_modules_with('search', 'unindex_page'); foreach ($searchmodules as $searchmodule) { $searchmodule->unindex_page($pageid); } $searchmodules = qa_load_modules_with('search', 'index_page'); if (count($searchmodules)) { $indextext = qa_viewer_text($page['content'], 'html'); foreach ($searchmodules as $searchmodule) { $searchmodule->index_page($pageid, $page['tags'], $page['heading'], $page['content'], 'html', $indextext); } } } } $next = 1 + $lastpageid; $done += count($pages); $continue = true; } else { qa_recalc_transition($state, 'doreindexcontent_postcount'); } break; case 'doreindexcontent_postcount': qa_db_qcount_update(); qa_db_acount_update(); qa_db_ccount_update(); qa_recalc_transition($state, 'doreindexcontent_postreindex'); break; case 'doreindexcontent_postreindex': $posts = qa_db_posts_get_for_reindexing($next, 10); if (count($posts)) { require_once QA_INCLUDE_DIR . 'app/format.php'; $lastpostid = max(array_keys($posts)); qa_db_prepare_for_reindexing($next, $lastpostid); qa_suspend_update_counts(); foreach ($posts as $postid => $post) { qa_post_unindex($postid); qa_post_index($postid, $post['type'], $post['questionid'], $post['parentid'], $post['title'], $post['content'], $post['format'], qa_viewer_text($post['content'], $post['format']), $post['tags'], $post['categoryid']); } $next = 1 + $lastpostid; $done += count($posts); $continue = true; } else { qa_db_truncate_indexes($next); qa_recalc_transition($state, 'doreindexposts_wordcount'); } break; case 'doreindexposts_wordcount': $wordids = qa_db_words_prepare_for_recounting($next, 1000); if (count($wordids)) { $lastwordid = max($wordids); qa_db_words_recount($next, $lastwordid); $next = 1 + $lastwordid; $done += count($wordids); $continue = true; } else { qa_db_tagcount_update(); // this is quick so just do it here qa_recalc_transition($state, 'doreindexposts_complete'); } break; case 'dorecountposts': qa_recalc_transition($state, 'dorecountposts_postcount'); break; case 'dorecountposts_postcount': qa_db_qcount_update(); qa_db_acount_update(); qa_db_ccount_update(); qa_db_unaqcount_update(); qa_db_unselqcount_update(); qa_recalc_transition($state, 'dorecountposts_votecount'); break; case 'dorecountposts_votecount': $postids = qa_db_posts_get_for_recounting($next, 1000); if (count($postids)) { $lastpostid = max($postids); qa_db_posts_votes_recount($next, $lastpostid); $next = 1 + $lastpostid; $done += count($postids); $continue = true; } else { qa_recalc_transition($state, 'dorecountposts_acount'); } break; case 'dorecountposts_acount': $postids = qa_db_posts_get_for_recounting($next, 1000); if (count($postids)) { $lastpostid = max($postids); qa_db_posts_answers_recount($next, $lastpostid); $next = 1 + $lastpostid; $done += count($postids); $continue = true; } else { qa_db_unupaqcount_update(); qa_recalc_transition($state, 'dorecountposts_complete'); } break; case 'dorecalcpoints': qa_recalc_transition($state, 'dorecalcpoints_usercount'); break; case 'dorecalcpoints_usercount': qa_db_userpointscount_update(); // for progress update - not necessarily accurate qa_db_uapprovecount_update(); // needs to be somewhere and this is the most appropriate place qa_recalc_transition($state, 'dorecalcpoints_recalc'); break; case 'dorecalcpoints_recalc': $recalccount = 10; $userids = qa_db_users_get_for_recalc_points($next, $recalccount + 1); // get one extra so we know where to start from next $gotcount = count($userids); $recalccount = min($recalccount, $gotcount); // can't recalc more than we got if ($recalccount > 0) { $lastuserid = $userids[$recalccount - 1]; qa_db_users_recalc_points($next, $lastuserid); $done += $recalccount; } else { $lastuserid = $next; } // for truncation if ($gotcount > $recalccount) { // more left to do $next = $userids[$recalccount]; // start next round at first one not recalculated $continue = true; } else { qa_db_truncate_userpoints($lastuserid); qa_db_userpointscount_update(); // quick so just do it here qa_recalc_transition($state, 'dorecalcpoints_complete'); } break; case 'dorefillevents': qa_recalc_transition($state, 'dorefillevents_qcount'); break; case 'dorefillevents_qcount': qa_db_qcount_update(); qa_recalc_transition($state, 'dorefillevents_refill'); break; case 'dorefillevents_refill': $questionids = qa_db_qs_get_for_event_refilling($next, 1); if (count($questionids)) { require_once QA_INCLUDE_DIR . 'app/events.php'; require_once QA_INCLUDE_DIR . 'app/updates.php'; require_once QA_INCLUDE_DIR . 'util/sort.php'; $lastquestionid = max($questionids); foreach ($questionids as $questionid) { // Retrieve all posts relating to this question list($question, $childposts, $achildposts) = qa_db_select_with_pending(qa_db_full_post_selectspec(null, $questionid), qa_db_full_child_posts_selectspec(null, $questionid), qa_db_full_a_child_posts_selectspec(null, $questionid)); // Merge all posts while preserving keys as postids $posts = array($questionid => $question); foreach ($childposts as $postid => $post) { $posts[$postid] = $post; } foreach ($achildposts as $postid => $post) { $posts[$postid] = $post; } // Creation and editing of each post foreach ($posts as $postid => $post) { $followonq = $post['basetype'] == 'Q' && $postid != $questionid; if ($followonq) { $updatetype = QA_UPDATE_FOLLOWS; } elseif ($post['basetype'] == 'C' && @$posts[$post['parentid']]['basetype'] == 'Q') { $updatetype = QA_UPDATE_C_FOR_Q; } elseif ($post['basetype'] == 'C' && @$posts[$post['parentid']]['basetype'] == 'A') { $updatetype = QA_UPDATE_C_FOR_A; } else { $updatetype = null; } qa_create_event_for_q_user($questionid, $postid, $updatetype, $post['userid'], @$posts[$post['parentid']]['userid'], $post['created']); if (isset($post['updated']) && !$followonq) { qa_create_event_for_q_user($questionid, $postid, $post['updatetype'], $post['lastuserid'], $post['userid'], $post['updated']); } } // Tags and categories of question qa_create_event_for_tags($question['tags'], $questionid, null, $question['userid'], $question['created']); qa_create_event_for_category($question['categoryid'], $questionid, null, $question['userid'], $question['created']); // Collect comment threads $parentidcomments = array(); foreach ($posts as $postid => $post) { if ($post['basetype'] == 'C') { $parentidcomments[$post['parentid']][$postid] = $post; } } // For each comment thread, notify all previous comment authors of each comment in the thread (could get slow) foreach ($parentidcomments as $parentid => $comments) { $keyuserids = array(); qa_sort_by($comments, 'created'); foreach ($comments as $comment) { foreach ($keyuserids as $keyuserid => $dummy) { if ($keyuserid != $comment['userid'] && $keyuserid != @$posts[$parentid]['userid']) { qa_db_event_create_not_entity($keyuserid, $questionid, $comment['postid'], QA_UPDATE_FOLLOWS, $comment['userid'], $comment['created']); } } if (isset($comment['userid'])) { $keyuserids[$comment['userid']] = true; } } } } $next = 1 + $lastquestionid; $done += count($questionids); $continue = true; } else { qa_recalc_transition($state, 'dorefillevents_complete'); } break; case 'dorecalccategories': qa_recalc_transition($state, 'dorecalccategories_postcount'); break; case 'dorecalccategories_postcount': qa_db_acount_update(); qa_db_ccount_update(); qa_recalc_transition($state, 'dorecalccategories_postupdate'); break; case 'dorecalccategories_postupdate': $postids = qa_db_posts_get_for_recategorizing($next, 100); if (count($postids)) { $lastpostid = max($postids); qa_db_posts_recalc_categoryid($next, $lastpostid); qa_db_posts_calc_category_path($next, $lastpostid); $next = 1 + $lastpostid; $done += count($postids); $continue = true; } else { qa_recalc_transition($state, 'dorecalccategories_recount'); } break; case 'dorecalccategories_recount': $categoryids = qa_db_categories_get_for_recalcs($next, 10); if (count($categoryids)) { $lastcategoryid = max($categoryids); foreach ($categoryids as $categoryid) { qa_db_ifcategory_qcount_update($categoryid); } $next = 1 + $lastcategoryid; $done += count($categoryids); $continue = true; } else { qa_recalc_transition($state, 'dorecalccategories_backpaths'); } break; case 'dorecalccategories_backpaths': $categoryids = qa_db_categories_get_for_recalcs($next, 10); if (count($categoryids)) { $lastcategoryid = max($categoryids); qa_db_categories_recalc_backpaths($next, $lastcategoryid); $next = 1 + $lastcategoryid; $done += count($categoryids); $continue = true; } else { qa_recalc_transition($state, 'dorecalccategories_complete'); } break; case 'dodeletehidden': qa_recalc_transition($state, 'dodeletehidden_comments'); break; case 'dodeletehidden_comments': $posts = qa_db_posts_get_for_deleting('C', $next, 1); if (count($posts)) { require_once QA_INCLUDE_DIR . 'app/posts.php'; $postid = $posts[0]; qa_post_delete($postid); $next = 1 + $postid; $done++; $continue = true; } else { qa_recalc_transition($state, 'dodeletehidden_answers'); } break; case 'dodeletehidden_answers': $posts = qa_db_posts_get_for_deleting('A', $next, 1); if (count($posts)) { require_once QA_INCLUDE_DIR . 'app/posts.php'; $postid = $posts[0]; qa_post_delete($postid); $next = 1 + $postid; $done++; $continue = true; } else { qa_recalc_transition($state, 'dodeletehidden_questions'); } break; case 'dodeletehidden_questions': $posts = qa_db_posts_get_for_deleting('Q', $next, 1); if (count($posts)) { require_once QA_INCLUDE_DIR . 'app/posts.php'; $postid = $posts[0]; qa_post_delete($postid); $next = 1 + $postid; $done++; $continue = true; } else { qa_recalc_transition($state, 'dodeletehidden_complete'); } break; case 'doblobstodisk': qa_recalc_transition($state, 'doblobstodisk_move'); break; case 'doblobstodisk_move': $blob = qa_db_get_next_blob_in_db($next); if (isset($blob)) { require_once QA_INCLUDE_DIR . 'app/blobs.php'; require_once QA_INCLUDE_DIR . 'db/blobs.php'; if (qa_write_blob_file($blob['blobid'], $blob['content'], $blob['format'])) { qa_db_blob_set_content($blob['blobid'], null); } $next = 1 + $blob['blobid']; $done++; $continue = true; } else { qa_recalc_transition($state, 'doblobstodisk_complete'); } break; case 'doblobstodb': qa_recalc_transition($state, 'doblobstodb_move'); break; case 'doblobstodb_move': $blob = qa_db_get_next_blob_on_disk($next); if (isset($blob)) { require_once QA_INCLUDE_DIR . 'app/blobs.php'; require_once QA_INCLUDE_DIR . 'db/blobs.php'; $content = qa_read_blob_file($blob['blobid'], $blob['format']); qa_db_blob_set_content($blob['blobid'], $content); qa_delete_blob_file($blob['blobid'], $blob['format']); $next = 1 + $blob['blobid']; $done++; $continue = true; } else { qa_recalc_transition($state, 'doblobstodb_complete'); } break; default: $state = ''; break; } if ($continue) { $state = $operation . "\t" . $length . "\t" . $next . "\t" . $done; } return $continue && $done < $length; }
function qa_delete_user($userid) { if (qa_to_override(__FUNCTION__)) { $args = func_get_args(); return qa_call_override(__FUNCTION__, $args); } require_once QA_INCLUDE_DIR . 'db/votes.php'; require_once QA_INCLUDE_DIR . 'db/users.php'; require_once QA_INCLUDE_DIR . 'db/post-update.php'; require_once QA_INCLUDE_DIR . 'db/points.php'; $postids = qa_db_uservoteflag_user_get($userid); // posts this user has flagged or voted on, whose counts need updating qa_db_user_delete($userid); qa_db_uapprovecount_update(); qa_db_userpointscount_update(); foreach ($postids as $postid) { // hoping there aren't many of these - saves a lot of new SQL code... qa_db_post_recount_votes($postid); qa_db_post_recount_flags($postid); } $postuserids = qa_db_posts_get_userids($postids); foreach ($postuserids as $postuserid) { qa_db_points_update_ifuser($postuserid, array('avoteds', 'qvoteds', 'upvoteds', 'downvoteds')); } }
function qa_recalc_perform_step(&$state) { $continue = false; @(list($operation, $length, $next, $done) = explode(',', $state)); switch ($operation) { case 'doreindexcontent': qa_recalc_transition($state, 'doreindexcontent_pagereindex'); break; case 'doreindexcontent_pagereindex': $pages = qa_db_pages_get_for_reindexing($next, 10); if (count($pages)) { require_once QA_INCLUDE_DIR . 'qa-app-format.php'; $lastpageid = max(array_keys($pages)); foreach ($pages as $pageid => $page) { if (!($page['flags'] & QA_PAGE_FLAGS_EXTERNAL)) { $searchmodules = qa_load_modules_with('search', 'unindex_page'); foreach ($searchmodules as $searchmodule) { $searchmodule->unindex_page($pageid); } $searchmodules = qa_load_modules_with('search', 'index_page'); if (count($searchmodules)) { $indextext = qa_viewer_text($page['content'], 'html'); foreach ($searchmodules as $searchmodule) { $searchmodule->index_page($pageid, $page['tags'], $page['heading'], $page['content'], 'html', $indextext); } } } } $next = 1 + $lastpageid; $done += count($pages); $continue = true; } else { qa_recalc_transition($state, 'doreindexcontent_postcount'); } break; case 'doreindexcontent_postcount': qa_db_qcount_update(); qa_db_acount_update(); qa_db_ccount_update(); qa_recalc_transition($state, 'doreindexcontent_postreindex'); break; case 'doreindexcontent_postreindex': $posts = qa_db_posts_get_for_reindexing($next, 10); if (count($posts)) { require_once QA_INCLUDE_DIR . 'qa-app-format.php'; $lastpostid = max(array_keys($posts)); qa_db_prepare_for_reindexing($next, $lastpostid); qa_suspend_update_counts(); foreach ($posts as $postid => $post) { qa_post_unindex($postid); qa_post_index($postid, $post['type'], $post['questionid'], $post['parentid'], $post['title'], $post['content'], $post['format'], qa_viewer_text($post['content'], $post['format']), $post['tags'], $post['categoryid']); } $next = 1 + $lastpostid; $done += count($posts); $continue = true; } else { qa_db_truncate_indexes($next); qa_recalc_transition($state, 'doreindexposts_wordcount'); } break; case 'doreindexposts_wordcount': $wordids = qa_db_words_prepare_for_recounting($next, 1000); if (count($wordids)) { $lastwordid = max($wordids); qa_db_words_recount($next, $lastwordid); $next = 1 + $lastwordid; $done += count($wordids); $continue = true; } else { qa_db_tagcount_update(); // this is quick so just do it here qa_recalc_transition($state, 'doreindexposts_complete'); } break; case 'dorecountposts': qa_recalc_transition($state, 'dorecountposts_postcount'); break; case 'dorecountposts_postcount': qa_db_qcount_update(); qa_db_acount_update(); qa_db_ccount_update(); qa_db_unaqcount_update(); qa_db_unselqcount_update(); qa_recalc_transition($state, 'dorecountposts_votecount'); break; case 'dorecountposts_votecount': $postids = qa_db_posts_get_for_recounting($next, 1000); if (count($postids)) { $lastpostid = max($postids); qa_db_posts_votes_recount($next, $lastpostid); $next = 1 + $lastpostid; $done += count($postids); $continue = true; } else { qa_recalc_transition($state, 'dorecountposts_acount'); } break; case 'dorecountposts_acount': $postids = qa_db_posts_get_for_recounting($next, 1000); if (count($postids)) { $lastpostid = max($postids); qa_db_posts_answers_recount($next, $lastpostid); $next = 1 + $lastpostid; $done += count($postids); $continue = true; } else { qa_db_unupaqcount_update(); qa_recalc_transition($state, 'dorecountposts_complete'); } break; case 'dorecalcpoints': qa_recalc_transition($state, 'dorecalcpoints_usercount'); break; case 'dorecalcpoints_usercount': qa_db_userpointscount_update(); // for progress update - not necessarily accurate qa_recalc_transition($state, 'dorecalcpoints_recalc'); break; case 'dorecalcpoints_recalc': $userids = qa_db_users_get_for_recalc_points($next, 10); if (count($userids)) { $lastuserid = max($userids); qa_db_users_recalc_points($next, $lastuserid); $next = 1 + $lastuserid; $done += count($userids); $continue = true; } else { qa_db_truncate_userpoints($next); qa_db_userpointscount_update(); // quick so just do it here qa_recalc_transition($state, 'dorecalcpoints_complete'); } break; case 'dorefillevents': qa_recalc_transition($state, 'dorefillevents_qcount'); break; case 'dorefillevents_qcount': qa_db_qcount_update(); qa_recalc_transition($state, 'dorefillevents_refill'); break; case 'dorefillevents_refill': $questionids = qa_db_qs_get_for_event_refilling($next, 1); if (count($questionids)) { require_once QA_INCLUDE_DIR . 'qa-app-events.php'; require_once QA_INCLUDE_DIR . 'qa-app-updates.php'; require_once QA_INCLUDE_DIR . 'qa-util-sort.php'; $lastquestionid = max($questionids); foreach ($questionids as $questionid) { // Retrieve all posts relating to this question list($question, $childposts, $achildposts) = qa_db_select_with_pending(qa_db_full_post_selectspec(null, $questionid), qa_db_full_child_posts_selectspec(null, $questionid), qa_db_full_a_child_posts_selectspec(null, $questionid)); // Merge all posts while preserving keys as postids $posts = array($questionid => $question); foreach ($childposts as $postid => $post) { $posts[$postid] = $post; } foreach ($achildposts as $postid => $post) { $posts[$postid] = $post; } // Creation and editing of each post foreach ($posts as $postid => $post) { $followonq = $post['basetype'] == 'Q' && $postid != $questionid; qa_create_event_for_q_user($questionid, $postid, $followonq ? QA_UPDATE_FOLLOWS : null, $post['userid'], @$posts[$post['parentid']]['userid'], $post['created']); if (isset($post['updated']) && !$followonq) { qa_create_event_for_q_user($questionid, $postid, $post['updatetype'], $post['lastuserid'], $post['userid'], $post['updated']); } } // Tags and categories of question qa_create_event_for_tags($question['tags'], $questionid, null, $question['userid'], $question['created']); qa_create_event_for_category($question['categoryid'], $questionid, null, $question['userid'], $question['created']); // Collect comment threads $parentidcomments = array(); foreach ($posts as $postid => $post) { if ($post['basetype'] == 'C') { $parentidcomments[$post['parentid']][$postid] = $post; } } // For each comment thread, notify all previous comment authors of each comment in the thread (could get slow) foreach ($parentidcomments as $parentid => $comments) { $keyuserids = array(); qa_sort_by($comments, 'created'); foreach ($comments as $comment) { foreach ($keyuserids as $keyuserid => $dummy) { if ($keyuserid != $comment['userid'] && $keyuserid != @$posts[$parentid]['userid']) { qa_db_event_create_not_entity($keyuserid, $questionid, $comment['postid'], null, $comment['userid'], $comment['created']); } } if (isset($comment['userid'])) { $keyuserids[$comment['userid']] = true; } } } } $next = 1 + $lastquestionid; $done += count($questionids); $continue = true; } else { qa_recalc_transition($state, 'dorefillevents_complete'); } break; case 'dorecalccategories': qa_recalc_transition($state, 'dorecalccategories_postcount'); break; case 'dorecalccategories_postcount': qa_db_acount_update(); qa_db_ccount_update(); qa_recalc_transition($state, 'dorecalccategories_postupdate'); break; case 'dorecalccategories_postupdate': $postids = qa_db_posts_get_for_recategorizing($next, 100); if (count($postids)) { $lastpostid = max($postids); qa_db_posts_recalc_categoryid($next, $lastpostid); qa_db_posts_calc_category_path($next, $lastpostid); $next = 1 + $lastpostid; $done += count($postids); $continue = true; } else { qa_recalc_transition($state, 'dorecalccategories_recount'); } break; case 'dorecalccategories_recount': $categoryids = qa_db_categories_get_for_recalcs($next, 10); if (count($categoryids)) { $lastcategoryid = max($categoryids); foreach ($categoryids as $categoryid) { qa_db_ifcategory_qcount_update($categoryid); } $next = 1 + $lastcategoryid; $done += count($categoryids); $continue = true; } else { qa_recalc_transition($state, 'dorecalccategories_backpaths'); } break; case 'dorecalccategories_backpaths': $categoryids = qa_db_categories_get_for_recalcs($next, 10); if (count($categoryids)) { $lastcategoryid = max($categoryids); qa_db_categories_recalc_backpaths($next, $lastcategoryid); $next = 1 + $lastcategoryid; $done += count($categoryids); $continue = true; } else { qa_recalc_transition($state, 'dorecalccategories_complete'); } break; case 'dodeletehidden': qa_recalc_transition($state, 'dodeletehidden_comments'); break; case 'dodeletehidden_comments': $posts = qa_db_posts_get_for_deleting('C', $next, 1); if (count($posts)) { require_once QA_INCLUDE_DIR . 'qa-app-posts.php'; $postid = $posts[0]; qa_post_delete($postid); $next = 1 + $postid; $done++; $continue = true; } else { qa_recalc_transition($state, 'dodeletehidden_answers'); } break; case 'dodeletehidden_answers': $posts = qa_db_posts_get_for_deleting('A', $next, 1); if (count($posts)) { require_once QA_INCLUDE_DIR . 'qa-app-posts.php'; $postid = $posts[0]; qa_post_delete($postid); $next = 1 + $postid; $done++; $continue = true; } else { qa_recalc_transition($state, 'dodeletehidden_questions'); } break; case 'dodeletehidden_questions': $posts = qa_db_posts_get_for_deleting('Q', $next, 1); if (count($posts)) { require_once QA_INCLUDE_DIR . 'qa-app-posts.php'; $postid = $posts[0]; qa_post_delete($postid); $next = 1 + $postid; $done++; $continue = true; } else { qa_recalc_transition($state, 'dodeletehidden_complete'); } break; default: $state = ''; break; } if ($continue) { $state = $operation . ',' . $length . ',' . $next . ',' . $done; } return $continue && $done < $length; }
function qa_recalc_perform_step(&$state) { $continue = false; @(list($operation, $length, $next, $done) = explode(',', $state)); switch ($operation) { case 'doreindexposts': qa_recalc_transition($state, 'doreindexposts_postcount'); break; case 'doreindexposts_postcount': qa_db_qcount_update(); qa_db_acount_update(); qa_db_ccount_update(); qa_recalc_transition($state, 'doreindexposts_reindex'); break; case 'doreindexposts_reindex': $posts = qa_db_posts_get_for_reindexing($next, 10); if (count($posts)) { require_once QA_INCLUDE_DIR . 'qa-app-format.php'; $lastpostid = max(array_keys($posts)); qa_db_prepare_for_reindexing($next, $lastpostid); foreach ($posts as $postid => $post) { qa_post_index($postid, $post['type'], $post['questionid'], $post['title'], qa_viewer_text($post['content'], $post['format']), $post['tags'], true); } $next = 1 + $lastpostid; $done += count($posts); $continue = true; } else { qa_db_truncate_indexes($next); qa_recalc_transition($state, 'doreindexposts_wordcount'); } break; case 'doreindexposts_wordcount': $wordids = qa_db_words_prepare_for_recounting($next, 1000); if (count($wordids)) { $lastwordid = max($wordids); qa_db_words_recount($next, $lastwordid); $next = 1 + $lastwordid; $done += count($wordids); $continue = true; } else { qa_db_tagcount_update(); // this is quick so just do it here qa_recalc_transition($state, 'doreindexposts_complete'); } break; case 'dorecountposts': qa_recalc_transition($state, 'dorecountposts_postcount'); break; case 'dorecountposts_postcount': qa_db_qcount_update(); qa_db_acount_update(); qa_db_ccount_update(); qa_db_unaqcount_update(); qa_recalc_transition($state, 'dorecountposts_recount'); break; case 'dorecountposts_recount': $postids = qa_db_posts_get_for_recounting($next, 1000); if (count($postids)) { $lastpostid = max($postids); qa_db_posts_recount($next, $lastpostid); $next = 1 + $lastpostid; $done += count($postids); $continue = true; } else { qa_recalc_transition($state, 'dorecountposts_complete'); } break; case 'dorecalcpoints': qa_recalc_transition($state, 'dorecalcpoints_usercount'); break; case 'dorecalcpoints_usercount': qa_db_userpointscount_update(); // for progress update - not necessarily accurate qa_recalc_transition($state, 'dorecalcpoints_recalc'); break; case 'dorecalcpoints_recalc': $userids = qa_db_users_get_for_recalc_points($next, 10); if (count($userids)) { $lastuserid = max($userids); qa_db_users_recalc_points($next, $lastuserid); $next = 1 + $lastuserid; $done += count($userids); $continue = true; } else { qa_db_truncate_userpoints($next); qa_db_userpointscount_update(); // quick so just do it here qa_recalc_transition($state, 'dorecalcpoints_complete'); } break; case 'dorecalccategories': qa_recalc_transition($state, 'dorecalccategories_postcount'); break; case 'dorecalccategories_postcount': qa_db_acount_update(); qa_db_ccount_update(); qa_recalc_transition($state, 'dorecalccategories_postupdate'); break; case 'dorecalccategories_postupdate': $postids = qa_db_posts_get_for_recategorizing($next, 100); if (count($postids)) { $lastpostid = max($postids); qa_db_posts_recalc_categoryid($next, $lastpostid); qa_db_posts_calc_category_path($next, $lastpostid); $next = 1 + $lastpostid; $done += count($postids); $continue = true; } else { qa_recalc_transition($state, 'dorecalccategories_recount'); } break; case 'dorecalccategories_recount': $categoryids = qa_db_categories_get_for_recalcs($next, 10); if (count($categoryids)) { $lastcategoryid = max($categoryids); foreach ($categoryids as $categoryid) { qa_db_ifcategory_qcount_update($categoryid); } $next = 1 + $lastcategoryid; $done += count($categoryids); $continue = true; } else { qa_recalc_transition($state, 'dorecalccategories_backpaths'); } break; case 'dorecalccategories_backpaths': $categoryids = qa_db_categories_get_for_recalcs($next, 10); if (count($categoryids)) { $lastcategoryid = max($categoryids); qa_db_categories_recalc_backpaths($next, $lastcategoryid); $next = 1 + $lastcategoryid; $done += count($categoryids); $continue = true; } else { qa_recalc_transition($state, 'dorecalccategories_complete'); } break; case 'dodeletehidden': qa_recalc_transition($state, 'dodeletehidden_comments'); break; case 'dodeletehidden_comments': $posts = qa_db_posts_get_for_deleting('C', $next, 1); if (count($posts)) { $postid = $posts[0]; $oldcomment = qa_db_single_select(qa_db_full_post_selectspec(null, $postid)); $parent = qa_db_single_select(qa_db_full_post_selectspec(null, $oldcomment['parentid'])); if ($parent['basetype'] == 'Q') { $question = $parent; $answer = null; } else { $question = qa_db_single_select(qa_db_full_post_selectspec(null, $parent['parentid'])); $answer = $parent; } qa_comment_delete($oldcomment, $question, $answer, null, null, null); $next = 1 + $postid; $done++; $continue = true; } else { qa_recalc_transition($state, 'dodeletehidden_answers'); } break; case 'dodeletehidden_answers': $posts = qa_db_posts_get_for_deleting('A', $next, 1); if (count($posts)) { $postid = $posts[0]; $oldanswer = qa_db_single_select(qa_db_full_post_selectspec(null, $postid)); $question = qa_db_single_select(qa_db_full_post_selectspec(null, $oldanswer['parentid'])); qa_answer_delete($oldanswer, $question, null, null, null); $next = 1 + $postid; $done++; $continue = true; } else { qa_recalc_transition($state, 'dodeletehidden_questions'); } break; case 'dodeletehidden_questions': $posts = qa_db_posts_get_for_deleting('Q', $next, 1); if (count($posts)) { $postid = $posts[0]; $oldquestion = qa_db_single_select(qa_db_full_post_selectspec(null, $postid)); qa_question_delete($oldquestion, null, null, null); $next = 1 + $postid; $done++; $continue = true; } else { qa_recalc_transition($state, 'dodeletehidden_complete'); } break; default: $state = ''; break; } if ($continue) { $state = $operation . ',' . $length . ',' . $next . ',' . $done; } return $continue && $done < $length; }
function qa_db_points_update_ifuser($userid, $columns) { if (qa_to_override(__FUNCTION__)) { $args = func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_should_update_counts() && isset($userid)) { require_once QA_INCLUDE_DIR . 'app/options.php'; require_once QA_INCLUDE_DIR . 'app/cookies.php'; $calculations = qa_db_points_calculations(); if ($columns === true) { $keycolumns = $calculations; } elseif (empty($columns)) { $keycolumns = array(); } elseif (is_array($columns)) { $keycolumns = array_flip($columns); } else { $keycolumns = array($columns => true); } $insertfields = 'userid, '; $insertvalues = '$, '; $insertpoints = (int) qa_opt('points_base'); $updates = ''; $updatepoints = $insertpoints; foreach ($calculations as $field => $calculation) { $multiple = (int) $calculation['multiple']; if (isset($keycolumns[$field])) { $insertfields .= $field . ', '; $insertvalues .= '@_' . $field . ':=(SELECT ' . $calculation['formula'] . '), '; $updates .= $field . '=@_' . $field . ', '; $insertpoints .= '+(' . (int) $multiple . '*@_' . $field . ')'; } $updatepoints .= '+(' . $multiple . '*' . (isset($keycolumns[$field]) ? '@_' : '') . $field . ')'; } $query = 'INSERT INTO ^userpoints (' . $insertfields . 'points) VALUES (' . $insertvalues . $insertpoints . ') ' . 'ON DUPLICATE KEY UPDATE ' . $updates . 'points=' . $updatepoints . '+bonus'; qa_db_query_raw(str_replace('~', "='" . qa_db_escape_string($userid) . "'", qa_db_apply_sub($query, array($userid)))); // build like this so that a #, $ or ^ character in the $userid (if external integration) isn't substituted if (qa_db_insert_on_duplicate_inserted()) { qa_db_userpointscount_update(); } } }
function qa_db_points_update_ifuser($userid, $columns) { if (qa_should_update_counts() && isset($userid)) { require_once QA_INCLUDE_DIR . 'qa-app-options.php'; $calculations = qa_db_points_calculations(); if ($columns === true) { $keycolumns = $calculations; } elseif (empty($columns)) { $keycolumns = array(); } elseif (is_array($columns)) { $keycolumns = array_flip($columns); } else { $keycolumns = array($columns => true); } $insertfields = 'userid, '; $insertvalues = '$, '; $insertpoints = (int) qa_opt('points_base'); $updates = ''; $updatepoints = $insertpoints; foreach ($calculations as $field => $calculation) { $multiple = (int) $calculation['multiple']; if (isset($keycolumns[$field])) { $insertfields .= $field . ', '; $insertvalues .= '@_' . $field . ':=(SELECT ' . $calculation['formula'] . '), '; $updates .= $field . '=@_' . $field . ', '; $insertpoints .= '+(' . $multiple . '*@_' . $field . ')'; } $updatepoints .= '+(' . $multiple . '*' . (isset($keycolumns[$field]) ? '@_' : '') . $field . ')'; } $query = 'INSERT INTO ^userpoints (' . $insertfields . 'points) VALUES (' . $insertvalues . $insertpoints . ') ' . 'ON DUPLICATE KEY UPDATE ' . $updates . 'points=' . $updatepoints; qa_db_query_sub(str_replace('~', "=_utf8 '" . qa_db_escape_string($userid) . "'", $query), $userid); if (qa_db_insert_on_duplicate_inserted()) { qa_db_userpointscount_update(); } } }