Commit 0794e784 by Scott

Coding style (db posts/users)

parent f5aaabc6
...@@ -20,394 +20,437 @@ ...@@ -20,394 +20,437 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
} }
function qa_db_post_create($type, $parentid, $userid, $cookieid, $ip, $title, $content, $format, $tagstring, $notify, $categoryid=null, $name=null) /**
/* * Create a new post in the database and return its ID (based on auto-incrementing)
Create a new post in the database and return its ID (based on auto-incrementing) * @param $type
*/ * @param $parentid
{ * @param $userid
* @param $cookieid
* @param $ip
* @param $title
* @param $content
* @param $format
* @param $tagstring
* @param $notify
* @param $categoryid
* @param $name
* @return mixed
*/
function qa_db_post_create($type, $parentid, $userid, $cookieid, $ip, $title, $content, $format, $tagstring, $notify, $categoryid = null, $name = null)
{
qa_db_query_sub(
'INSERT INTO ^posts (categoryid, type, parentid, userid, cookieid, createip, title, content, format, tags, notify, name, created) ' .
'VALUES (#, $, #, $, #, $, $, $, $, $, $, $, NOW())',
$categoryid, $type, $parentid, $userid, $cookieid, @inet_pton($ip), $title, $content, $format, $tagstring, $notify, $name
);
return qa_db_last_insert_id();
}
/**
* Recalculate the full category path (i.e. columns catidpath1/2/3) for posts from $firstpostid to $lastpostid (if specified)
* @param $firstpostid
* @param $lastpostid
*/
function qa_db_posts_calc_category_path($firstpostid, $lastpostid = null)
{
if (!isset($lastpostid))
$lastpostid = $firstpostid;
qa_db_query_sub(
"UPDATE ^posts AS x, (SELECT ^posts.postid, " .
"COALESCE(parent2.parentid, parent1.parentid, parent0.parentid, parent0.categoryid) AS catidpath1, " .
"IF (parent2.parentid IS NOT NULL, parent1.parentid, IF (parent1.parentid IS NOT NULL, parent0.parentid, IF (parent0.parentid IS NOT NULL, parent0.categoryid, NULL))) AS catidpath2, " .
"IF (parent2.parentid IS NOT NULL, parent0.parentid, IF (parent1.parentid IS NOT NULL, parent0.categoryid, NULL)) AS catidpath3 " .
"FROM ^posts LEFT JOIN ^categories AS parent0 ON ^posts.categoryid=parent0.categoryid LEFT JOIN ^categories AS parent1 ON parent0.parentid=parent1.categoryid LEFT JOIN ^categories AS parent2 ON parent1.parentid=parent2.categoryid WHERE ^posts.postid BETWEEN # AND #) AS a SET x.catidpath1=a.catidpath1, x.catidpath2=a.catidpath2, x.catidpath3=a.catidpath3 WHERE x.postid=a.postid",
$firstpostid, $lastpostid
); // requires QA_CATEGORY_DEPTH=4
}
/**
* Get the full category path (including categoryid) for $postid
* @param $postid
* @return array|null
*/
function qa_db_post_get_category_path($postid)
{
return qa_db_read_one_assoc(qa_db_query_sub(
'SELECT categoryid, catidpath1, catidpath2, catidpath3 FROM ^posts WHERE postid=#',
$postid
)); // requires QA_CATEGORY_DEPTH=4
}
/**
* Update the cached number of answers for $questionid in the database, along with the highest netvotes of any of its answers
* @param $questionid
*/
function qa_db_post_acount_update($questionid)
{
if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^posts (categoryid, type, parentid, userid, cookieid, createip, title, content, format, tags, notify, name, created) '. "UPDATE ^posts AS x, (SELECT COUNT(*) AS acount, COALESCE(GREATEST(MAX(netvotes), 0), 0) AS amaxvote FROM ^posts WHERE parentid=# AND type='A') AS a SET x.acount=a.acount, x.amaxvote=a.amaxvote WHERE x.postid=#",
'VALUES (#, $, #, $, #, $, $, $, $, $, $, $, NOW())', $questionid, $questionid
$categoryid, $type, $parentid, $userid, $cookieid, @inet_pton($ip), $title, $content, $format, $tagstring, $notify, $name
); );
return qa_db_last_insert_id();
} }
}
function qa_db_posts_calc_category_path($firstpostid, $lastpostid=null)
/* /**
Recalculate the full category path (i.e. columns catidpath1/2/3) for posts from $firstpostid to $lastpostid (if specified) * Recalculate the number of questions for each category in $path retrieved via qa_db_post_get_category_path()
*/ * @param $path
{ */
if (!isset($lastpostid)) function qa_db_category_path_qcount_update($path)
$lastpostid=$firstpostid; {
qa_db_ifcategory_qcount_update($path['categoryid']); // requires QA_CATEGORY_DEPTH=4
qa_db_ifcategory_qcount_update($path['catidpath1']);
qa_db_ifcategory_qcount_update($path['catidpath2']);
qa_db_ifcategory_qcount_update($path['catidpath3']);
}
/**
* Update the cached number of questions for category $categoryid in the database, including its subcategories
* @param $categoryid
*/
function qa_db_ifcategory_qcount_update($categoryid)
{
if (qa_should_update_counts() && isset($categoryid)) {
// This seemed like the most sensible approach which avoids explicitly calculating the category's depth in the hierarchy
qa_db_query_sub( qa_db_query_sub(
"UPDATE ^posts AS x, (SELECT ^posts.postid, ". "UPDATE ^categories SET qcount=GREATEST( (SELECT COUNT(*) FROM ^posts WHERE categoryid=# AND type='Q'), (SELECT COUNT(*) FROM ^posts WHERE catidpath1=# AND type='Q'), (SELECT COUNT(*) FROM ^posts WHERE catidpath2=# AND type='Q'), (SELECT COUNT(*) FROM ^posts WHERE catidpath3=# AND type='Q') ) WHERE categoryid=#",
"COALESCE(parent2.parentid, parent1.parentid, parent0.parentid, parent0.categoryid) AS catidpath1, ". $categoryid, $categoryid, $categoryid, $categoryid, $categoryid
"IF (parent2.parentid IS NOT NULL, parent1.parentid, IF (parent1.parentid IS NOT NULL, parent0.parentid, IF (parent0.parentid IS NOT NULL, parent0.categoryid, NULL))) AS catidpath2, ".
"IF (parent2.parentid IS NOT NULL, parent0.parentid, IF (parent1.parentid IS NOT NULL, parent0.categoryid, NULL)) AS catidpath3 ".
"FROM ^posts LEFT JOIN ^categories AS parent0 ON ^posts.categoryid=parent0.categoryid LEFT JOIN ^categories AS parent1 ON parent0.parentid=parent1.categoryid LEFT JOIN ^categories AS parent2 ON parent1.parentid=parent2.categoryid WHERE ^posts.postid BETWEEN # AND #) AS a SET x.catidpath1=a.catidpath1, x.catidpath2=a.catidpath2, x.catidpath3=a.catidpath3 WHERE x.postid=a.postid",
$firstpostid, $lastpostid
); // requires QA_CATEGORY_DEPTH=4 ); // requires QA_CATEGORY_DEPTH=4
} }
}
/**
* Add rows into the database title index, where $postid contains the words $wordids - this does the same sort
* of thing as qa_db_posttags_add_post_wordids() in a different way, for no particularly good reason.
* @param $postid
* @param $wordids
*/
function qa_db_titlewords_add_post_wordids($postid, $wordids)
{
if (count($wordids)) {
$rowstoadd = array();
foreach ($wordids as $wordid)
$rowstoadd[] = array($postid, $wordid);
qa_db_query_sub(
function qa_db_post_get_category_path($postid) 'INSERT INTO ^titlewords (postid, wordid) VALUES #',
/* $rowstoadd
Get the full category path (including categoryid) for $postid );
*/
{
return qa_db_read_one_assoc(qa_db_query_sub(
'SELECT categoryid, catidpath1, catidpath2, catidpath3 FROM ^posts WHERE postid=#',
$postid
)); // requires QA_CATEGORY_DEPTH=4
}
function qa_db_post_acount_update($questionid)
/*
Update the cached number of answers for $questionid in the database, along with the highest netvotes of any of its answers
*/
{
if (qa_should_update_counts())
qa_db_query_sub(
"UPDATE ^posts AS x, (SELECT COUNT(*) AS acount, COALESCE(GREATEST(MAX(netvotes), 0), 0) AS amaxvote FROM ^posts WHERE parentid=# AND type='A') AS a SET x.acount=a.acount, x.amaxvote=a.amaxvote WHERE x.postid=#",
$questionid, $questionid
);
} }
}
/**
* Add rows into the database content index, where $postid (of $type, with the antecedent $questionid)
* has words as per the keys of $wordidcounts, and the corresponding number of those words in the values.
* @param $postid
* @param $type
* @param $questionid
* @param $wordidcounts
*/
function qa_db_contentwords_add_post_wordidcounts($postid, $type, $questionid, $wordidcounts)
{
if (count($wordidcounts)) {
$rowstoadd = array();
foreach ($wordidcounts as $wordid => $count)
$rowstoadd[] = array($postid, $wordid, $count, $type, $questionid);
qa_db_query_sub(
function qa_db_category_path_qcount_update($path) 'INSERT INTO ^contentwords (postid, wordid, count, type, questionid) VALUES #',
/* $rowstoadd
Recalculate the number of questions for each category in $path retrieved via qa_db_post_get_category_path() );
*/
{
qa_db_ifcategory_qcount_update($path['categoryid']); // requires QA_CATEGORY_DEPTH=4
qa_db_ifcategory_qcount_update($path['catidpath1']);
qa_db_ifcategory_qcount_update($path['catidpath2']);
qa_db_ifcategory_qcount_update($path['catidpath3']);
} }
}
function qa_db_ifcategory_qcount_update($categoryid) /**
/* * Add rows into the database index of individual tag words, where $postid contains the words $wordids
Update the cached number of questions for category $categoryid in the database, including its subcategories * @param $postid
*/ * @param $wordids
{ */
if (qa_should_update_counts() && isset($categoryid)) { function qa_db_tagwords_add_post_wordids($postid, $wordids)
// This seemed like the most sensible approach which avoids explicitly calculating the category's depth in the hierarchy {
if (count($wordids)) {
qa_db_query_sub( $rowstoadd = array();
"UPDATE ^categories SET qcount=GREATEST( (SELECT COUNT(*) FROM ^posts WHERE categoryid=# AND type='Q'), (SELECT COUNT(*) FROM ^posts WHERE catidpath1=# AND type='Q'), (SELECT COUNT(*) FROM ^posts WHERE catidpath2=# AND type='Q'), (SELECT COUNT(*) FROM ^posts WHERE catidpath3=# AND type='Q') ) WHERE categoryid=#", foreach ($wordids as $wordid)
$categoryid, $categoryid, $categoryid, $categoryid, $categoryid $rowstoadd[] = array($postid, $wordid);
); // requires QA_CATEGORY_DEPTH=4
}
}
function qa_db_titlewords_add_post_wordids($postid, $wordids) qa_db_query_sub(
/* 'INSERT INTO ^tagwords (postid, wordid) VALUES #',
Add rows into the database title index, where $postid contains the words $wordids - this does the same sort $rowstoadd
of thing as qa_db_posttags_add_post_wordids() in a different way, for no particularly good reason. );
*/
{
if (count($wordids)) {
$rowstoadd=array();
foreach ($wordids as $wordid)
$rowstoadd[]=array($postid, $wordid);
qa_db_query_sub(
'INSERT INTO ^titlewords (postid, wordid) VALUES #',
$rowstoadd
);
}
} }
}
function qa_db_contentwords_add_post_wordidcounts($postid, $type, $questionid, $wordidcounts) /**
/* * Add rows into the database index of whole tags, where $postid contains the tags $wordids
Add rows into the database content index, where $postid (of $type, with the antecedent $questionid) * @param $postid
has words as per the keys of $wordidcounts, and the corresponding number of those words in the values. * @param $wordids
*/ */
{ function qa_db_posttags_add_post_wordids($postid, $wordids)
if (count($wordidcounts)) { {
$rowstoadd=array(); if (count($wordids)) {
foreach ($wordidcounts as $wordid => $count) qa_db_query_sub(
$rowstoadd[]=array($postid, $wordid, $count, $type, $questionid); 'INSERT INTO ^posttags (postid, wordid, postcreated) SELECT postid, wordid, created FROM ^words, ^posts WHERE postid=# AND wordid IN ($)',
$postid, $wordids
qa_db_query_sub( );
'INSERT INTO ^contentwords (postid, wordid, count, type, questionid) VALUES #',
$rowstoadd
);
}
} }
}
function qa_db_tagwords_add_post_wordids($postid, $wordids)
/* /**
Add rows into the database index of individual tag words, where $postid contains the words $wordids * Return an array mapping each word in $words to its corresponding wordid in the database
*/ * @param $words
{ * @return array
if (count($wordids)) { */
$rowstoadd=array(); function qa_db_word_mapto_ids($words)
foreach ($wordids as $wordid) {
$rowstoadd[]=array($postid, $wordid); if (count($words)) {
return qa_db_read_all_assoc(qa_db_query_sub(
qa_db_query_sub( 'SELECT wordid, word FROM ^words WHERE word IN ($)', $words
'INSERT INTO ^tagwords (postid, wordid) VALUES #', ), 'word', 'wordid');
$rowstoadd
);
}
} }
return array();
}
function qa_db_posttags_add_post_wordids($postid, $wordids)
/*
Add rows into the database index of whole tags, where $postid contains the tags $wordids
*/
{
if (count($wordids))
qa_db_query_sub(
'INSERT INTO ^posttags (postid, wordid, postcreated) SELECT postid, wordid, created FROM ^words, ^posts WHERE postid=# AND wordid IN ($)',
$postid, $wordids
);
}
/**
* Return an array mapping each word in $words to its corresponding wordid in the database, adding any that are missing
* @param $words
* @return array
*/
function qa_db_word_mapto_ids_add($words)
{
$wordtoid = qa_db_word_mapto_ids($words);
function qa_db_word_mapto_ids($words) $wordstoadd = array();
/* foreach ($words as $word) {
Return an array mapping each word in $words to its corresponding wordid in the database if (!isset($wordtoid[$word]))
*/ $wordstoadd[] = $word;
{
if (count($words))
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT wordid, word FROM ^words WHERE word IN ($)', $words
), 'word', 'wordid');
else
return array();
} }
if (count($wordstoadd)) {
qa_db_query_sub('LOCK TABLES ^words WRITE'); // to prevent two requests adding the same word
function qa_db_word_mapto_ids_add($words) $wordtoid = qa_db_word_mapto_ids($words); // map it again in case table content changed before it was locked
/*
Return an array mapping each word in $words to its corresponding wordid in the database, adding any that are missing
*/
{
$wordtoid=qa_db_word_mapto_ids($words);
$wordstoadd=array(); $rowstoadd = array();
foreach ($words as $word) foreach ($words as $word) {
if (!isset($wordtoid[$word])) if (!isset($wordtoid[$word]))
$wordstoadd[]=$word; $rowstoadd[] = array($word);
}
if (count($wordstoadd)) {
qa_db_query_sub('LOCK TABLES ^words WRITE'); // to prevent two requests adding the same word
$wordtoid=qa_db_word_mapto_ids($words); // map it again in case table content changed before it was locked
$rowstoadd=array();
foreach ($words as $word)
if (!isset($wordtoid[$word]))
$rowstoadd[]=array($word);
qa_db_query_sub('INSERT IGNORE INTO ^words (word) VALUES $', $rowstoadd);
qa_db_query_sub('UNLOCK TABLES'); qa_db_query_sub('INSERT IGNORE INTO ^words (word) VALUES $', $rowstoadd);
$wordtoid=qa_db_word_mapto_ids($words); // do it one last time qa_db_query_sub('UNLOCK TABLES');
}
return $wordtoid; $wordtoid = qa_db_word_mapto_ids($words); // do it one last time
} }
return $wordtoid;
}
function qa_db_word_titlecount_update($wordids)
/* /**
Update the titlecount column in the database for the words in $wordids, based on how many posts they appear in the title of * Update the titlecount column in the database for the words in $wordids, based on how many posts they appear in the title of
*/ * @param $wordids
{ */
if (qa_should_update_counts() && count($wordids)) function qa_db_word_titlecount_update($wordids)
qa_db_query_sub( {
'UPDATE ^words AS x, (SELECT ^words.wordid, COUNT(^titlewords.wordid) AS titlecount FROM ^words LEFT JOIN ^titlewords ON ^titlewords.wordid=^words.wordid WHERE ^words.wordid IN (#) GROUP BY wordid) AS a SET x.titlecount=a.titlecount WHERE x.wordid=a.wordid', if (qa_should_update_counts() && count($wordids)) {
$wordids qa_db_query_sub(
); 'UPDATE ^words AS x, (SELECT ^words.wordid, COUNT(^titlewords.wordid) AS titlecount FROM ^words LEFT JOIN ^titlewords ON ^titlewords.wordid=^words.wordid WHERE ^words.wordid IN (#) GROUP BY wordid) AS a SET x.titlecount=a.titlecount WHERE x.wordid=a.wordid',
$wordids
);
} }
}
function qa_db_word_contentcount_update($wordids) /**
/* * Update the contentcount column in the database for the words in $wordids, based on how many posts they appear in the content of
Update the contentcount column in the database for the words in $wordids, based on how many posts they appear in the content of * @param $wordids
*/ */
{ function qa_db_word_contentcount_update($wordids)
if (qa_should_update_counts() && count($wordids)) {
qa_db_query_sub( if (qa_should_update_counts() && count($wordids)) {
'UPDATE ^words AS x, (SELECT ^words.wordid, COUNT(^contentwords.wordid) AS contentcount FROM ^words LEFT JOIN ^contentwords ON ^contentwords.wordid=^words.wordid WHERE ^words.wordid IN (#) GROUP BY wordid) AS a SET x.contentcount=a.contentcount WHERE x.wordid=a.wordid', qa_db_query_sub(
$wordids 'UPDATE ^words AS x, (SELECT ^words.wordid, COUNT(^contentwords.wordid) AS contentcount FROM ^words LEFT JOIN ^contentwords ON ^contentwords.wordid=^words.wordid WHERE ^words.wordid IN (#) GROUP BY wordid) AS a SET x.contentcount=a.contentcount WHERE x.wordid=a.wordid',
); $wordids
);
} }
}
function qa_db_word_tagwordcount_update($wordids) /**
/* * Update the tagwordcount column in the database for the individual tag words in $wordids, based on how many posts they appear in the tags of
Update the tagwordcount column in the database for the individual tag words in $wordids, based on how many posts they appear in the tags of * @param $wordids
*/ */
{ function qa_db_word_tagwordcount_update($wordids)
if (qa_should_update_counts() && count($wordids)) {
qa_db_query_sub( if (qa_should_update_counts() && count($wordids)) {
'UPDATE ^words AS x, (SELECT ^words.wordid, COUNT(^tagwords.wordid) AS tagwordcount FROM ^words LEFT JOIN ^tagwords ON ^tagwords.wordid=^words.wordid WHERE ^words.wordid IN (#) GROUP BY wordid) AS a SET x.tagwordcount=a.tagwordcount WHERE x.wordid=a.wordid', qa_db_query_sub(
$wordids 'UPDATE ^words AS x, (SELECT ^words.wordid, COUNT(^tagwords.wordid) AS tagwordcount FROM ^words LEFT JOIN ^tagwords ON ^tagwords.wordid=^words.wordid WHERE ^words.wordid IN (#) GROUP BY wordid) AS a SET x.tagwordcount=a.tagwordcount WHERE x.wordid=a.wordid',
); $wordids
);
} }
}
function qa_db_word_tagcount_update($wordids) /**
/* * Update the tagcount column in the database for the whole tags in $wordids, based on how many posts they appear as tags of
Update the tagcount column in the database for the whole tags in $wordids, based on how many posts they appear as tags of * @param $wordids
*/ */
{ function qa_db_word_tagcount_update($wordids)
if (qa_should_update_counts() && count($wordids)) {
qa_db_query_sub( if (qa_should_update_counts() && count($wordids)) {
'UPDATE ^words AS x, (SELECT ^words.wordid, COUNT(^posttags.wordid) AS tagcount FROM ^words LEFT JOIN ^posttags ON ^posttags.wordid=^words.wordid WHERE ^words.wordid IN (#) GROUP BY wordid) AS a SET x.tagcount=a.tagcount WHERE x.wordid=a.wordid', qa_db_query_sub(
$wordids 'UPDATE ^words AS x, (SELECT ^words.wordid, COUNT(^posttags.wordid) AS tagcount FROM ^words LEFT JOIN ^posttags ON ^posttags.wordid=^words.wordid WHERE ^words.wordid IN (#) GROUP BY wordid) AS a SET x.tagcount=a.tagcount WHERE x.wordid=a.wordid',
); $wordids
);
} }
}
function qa_db_qcount_update() /**
/* * Update the cached count in the database of the number of questions (excluding hidden/queued)
Update the cached count in the database of the number of questions (excluding hidden/queued) */
*/ function qa_db_qcount_update()
{ {
if (qa_should_update_counts()) { if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
"INSERT INTO ^options (title, content) " . "INSERT INTO ^options (title, content) " .
"SELECT 'cache_qcount', COUNT(*) FROM ^posts " . "SELECT 'cache_qcount', COUNT(*) FROM ^posts " .
"WHERE type = 'Q' " . "WHERE type = 'Q' " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)" "ON DUPLICATE KEY UPDATE content = VALUES(content)"
); );
}
} }
}
function qa_db_acount_update() /**
/* * Update the cached count in the database of the number of answers (excluding hidden/queued)
Update the cached count in the database of the number of answers (excluding hidden/queued) */
*/ function qa_db_acount_update()
{ {
if (qa_should_update_counts()) { if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
"INSERT INTO ^options (title, content) " . "INSERT INTO ^options (title, content) " .
"SELECT 'cache_acount', COUNT(*) FROM ^posts " . "SELECT 'cache_acount', COUNT(*) FROM ^posts " .
"WHERE type = 'A' " . "WHERE type = 'A' " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)" "ON DUPLICATE KEY UPDATE content = VALUES(content)"
); );
}
} }
}
function qa_db_ccount_update() /**
/* * Update the cached count in the database of the number of comments (excluding hidden/queued)
Update the cached count in the database of the number of comments (excluding hidden/queued) */
*/ function qa_db_ccount_update()
{ {
if (qa_should_update_counts()) { if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
"INSERT INTO ^options (title, content) " . "INSERT INTO ^options (title, content) " .
"SELECT 'cache_ccount', COUNT(*) FROM ^posts " . "SELECT 'cache_ccount', COUNT(*) FROM ^posts " .
"WHERE type = 'C' " . "WHERE type = 'C' " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)" "ON DUPLICATE KEY UPDATE content = VALUES(content)"
); );
}
} }
}
function qa_db_tagcount_update() /**
/* * Update the cached count in the database of the number of different tags used
Update the cached count in the database of the number of different tags used */
*/ function qa_db_tagcount_update()
{ {
if (qa_should_update_counts()) { if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
"INSERT INTO ^options (title, content) " . "INSERT INTO ^options (title, content) " .
"SELECT 'cache_tagcount', COUNT(*) FROM ^words " . "SELECT 'cache_tagcount', COUNT(*) FROM ^words " .
"WHERE tagcount > 0 " . "WHERE tagcount > 0 " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)" "ON DUPLICATE KEY UPDATE content = VALUES(content)"
); );
}
} }
}
function qa_db_unaqcount_update() /**
/* * Update the cached count in the database of the number of unanswered questions (excluding hidden/queued)
Update the cached count in the database of the number of unanswered questions (excluding hidden/queued) */
*/ function qa_db_unaqcount_update()
{ {
if (qa_should_update_counts()) { if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
"INSERT INTO ^options (title, content) " . "INSERT INTO ^options (title, content) " .
"SELECT 'cache_unaqcount', COUNT(*) FROM ^posts " . "SELECT 'cache_unaqcount', COUNT(*) FROM ^posts " .
"WHERE type = 'Q' AND acount = 0 AND closedbyid IS NULL " . "WHERE type = 'Q' AND acount = 0 AND closedbyid IS NULL " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)" "ON DUPLICATE KEY UPDATE content = VALUES(content)"
); );
}
} }
}
function qa_db_unselqcount_update() /**
/* * Update the cached count in the database of the number of questions with no answer selected (excluding hidden/queued)
Update the cached count in the database of the number of questions with no answer selected (excluding hidden/queued) */
*/ function qa_db_unselqcount_update()
{ {
if (qa_should_update_counts()) { if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
"INSERT INTO ^options (title, content) " . "INSERT INTO ^options (title, content) " .
"SELECT 'cache_unselqcount', COUNT(*) FROM ^posts " . "SELECT 'cache_unselqcount', COUNT(*) FROM ^posts " .
"WHERE type = 'Q' AND selchildid IS NULL AND closedbyid IS NULL " . "WHERE type = 'Q' AND selchildid IS NULL AND closedbyid IS NULL " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)" "ON DUPLICATE KEY UPDATE content = VALUES(content)"
); );
}
} }
}
function qa_db_unupaqcount_update() /**
/* * Update the cached count in the database of the number of questions with no upvoted answers (excluding hidden/queued)
Update the cached count in the database of the number of questions with no upvoted answers (excluding hidden/queued) */
*/ function qa_db_unupaqcount_update()
{ {
if (qa_should_update_counts()) { if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
"INSERT INTO ^options (title, content) " . "INSERT INTO ^options (title, content) " .
"SELECT 'cache_unupaqcount', COUNT(*) FROM ^posts " . "SELECT 'cache_unupaqcount', COUNT(*) FROM ^posts " .
"WHERE type = 'Q' AND amaxvote = 0 AND closedbyid IS NULL " . "WHERE type = 'Q' AND amaxvote = 0 AND closedbyid IS NULL " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)" "ON DUPLICATE KEY UPDATE content = VALUES(content)"
); );
}
} }
}
function qa_db_queuedcount_update() /**
/* * Update the cached count in the database of the number of posts which are queued for moderation
Update the cached count in the database of the number of posts which are queued for moderation */
*/ function qa_db_queuedcount_update()
{ {
if (qa_should_update_counts()) { if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
"INSERT INTO ^options (title, content) " . "INSERT INTO ^options (title, content) " .
"SELECT 'cache_queuedcount', COUNT(*) FROM ^posts " . "SELECT 'cache_queuedcount', COUNT(*) FROM ^posts " .
"WHERE type IN ('Q_QUEUED', 'A_QUEUED', 'C_QUEUED') " . "WHERE type IN ('Q_QUEUED', 'A_QUEUED', 'C_QUEUED') " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)" "ON DUPLICATE KEY UPDATE content = VALUES(content)"
); );
}
} }
}
/*
Omit PHP closing tag to help avoid accidental output
*/
...@@ -20,349 +20,414 @@ ...@@ -20,349 +20,414 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
}
require_once QA_INCLUDE_DIR . 'app/updates.php';
/**
* Update the selected answer in the database for $questionid to $selchildid, and optionally record that $lastuserid did it from $lastip
* @param $questionid
* @param $selchildid
* @param $lastuserid
* @param $lastip
*/
function qa_db_post_set_selchildid($questionid, $selchildid, $lastuserid = null, $lastip = null)
{
qa_db_query_sub(
"UPDATE ^posts AS x, (SELECT selchildid FROM ^posts WHERE postid=#) AS a " .
"SET x.updated=NULL, x.updatetype=NULL, x.lastuserid=NULL, x.lastip=NULL WHERE " . // if previous answer's last edit was to be selected, remove that
"x.postid=a.selchildid AND x.updatetype=$",
$questionid, QA_UPDATE_SELECTED
);
qa_db_query_sub(
'UPDATE ^posts SET selchildid=# WHERE postid=#',
$selchildid, $questionid
);
if (isset($selchildid) && isset($lastuserid) && isset($lastip)) {
qa_db_query_sub(
"UPDATE ^posts SET updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#",
QA_UPDATE_SELECTED, $lastuserid, @inet_pton($lastip), $selchildid
);
} }
}
require_once QA_INCLUDE_DIR.'app/updates.php';
/**
* Set $questionid to be closed by post $closedbyid (null if not closed) in the database, and optionally record that
function qa_db_post_set_selchildid($questionid, $selchildid, $lastuserid=null, $lastip=null) * $lastuserid did it from $lastip
/* * @param $questionid
Update the selected answer in the database for $questionid to $selchildid, and optionally record that $lastuserid did it from $lastip * @param $closedbyid
*/ * @param $lastuserid
{ * @param $lastip
*/
function qa_db_post_set_closed($questionid, $closedbyid, $lastuserid = null, $lastip = null)
{
if (isset($lastuserid) || isset($lastip)) {
qa_db_query_sub( qa_db_query_sub(
"UPDATE ^posts AS x, (SELECT selchildid FROM ^posts WHERE postid=#) AS a ". "UPDATE ^posts SET closedbyid=#, updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#",
"SET x.updated=NULL, x.updatetype=NULL, x.lastuserid=NULL, x.lastip=NULL WHERE ". // if previous answer's last edit was to be selected, remove that $closedbyid, QA_UPDATE_CLOSED, $lastuserid, @inet_pton($lastip), $questionid
"x.postid=a.selchildid AND x.updatetype=$",
$questionid, QA_UPDATE_SELECTED
); );
} else {
qa_db_query_sub( qa_db_query_sub(
'UPDATE ^posts SET selchildid=# WHERE postid=#', 'UPDATE ^posts SET closedbyid=# WHERE postid=#',
$selchildid, $questionid $closedbyid, $questionid
); );
if (isset($selchildid) && isset($lastuserid) && isset($lastip))
qa_db_query_sub(
"UPDATE ^posts SET updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#",
QA_UPDATE_SELECTED, $lastuserid, @inet_pton($lastip), $selchildid
);
}
function qa_db_post_set_closed($questionid, $closedbyid, $lastuserid=null, $lastip=null)
/*
Set $questionid to be closed by post $closedbyid (null if not closed) in the database, and optionally record that
$lastuserid did it from $lastip
*/
{
if (isset($lastuserid) || isset($lastip)) {
qa_db_query_sub(
"UPDATE ^posts SET closedbyid=#, updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#",
$closedbyid, QA_UPDATE_CLOSED, $lastuserid, @inet_pton($lastip), $questionid
);
} else
qa_db_query_sub(
'UPDATE ^posts SET closedbyid=# WHERE postid=#',
$closedbyid, $questionid
);
} }
}
function qa_db_post_set_type($postid, $type, $lastuserid=null, $lastip=null, $updatetype=QA_UPDATE_TYPE)
/* /**
Set the type in the database of $postid to $type, and optionally record that $lastuserid did it from $lastip * Set the type in the database of $postid to $type, and optionally record that $lastuserid did it from $lastip
*/ * @param $postid
{ * @param $type
if (isset($lastuserid) || isset($lastip)) { * @param $lastuserid
qa_db_query_sub( * @param $lastip
'UPDATE ^posts SET type=$, updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#', * @param string $updatetype
$type, $updatetype, $lastuserid, @inet_pton($lastip), $postid */
); function qa_db_post_set_type($postid, $type, $lastuserid = null, $lastip = null, $updatetype = QA_UPDATE_TYPE)
} else {
qa_db_query_sub( if (isset($lastuserid) || isset($lastip)) {
'UPDATE ^posts SET type=$ WHERE postid=#',
$type, $postid
);
}
function qa_db_post_set_parent($postid, $parentid, $lastuserid=null, $lastip=null)
/*
Set the parent in the database of $postid to $parentid, and optionally record that $lastuserid did it from $lastip
(if at least one is specified)
*/
{
if (isset($lastuserid) || isset($lastip))
qa_db_query_sub(
"UPDATE ^posts SET parentid=#, updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#",
$parentid, QA_UPDATE_PARENT, $lastuserid, @inet_pton($lastip), $postid
);
else
qa_db_query_sub(
'UPDATE ^posts SET parentid=# WHERE postid=#',
$parentid, $postid
);
}
function qa_db_post_set_content($postid, $title, $content, $format, $tagstring, $notify, $lastuserid=null, $lastip=null, $updatetype=QA_UPDATE_CONTENT, $name=null)
/*
Set the text fields in the database of $postid to $title, $content, $tagstring, $notify and $name, and record that
$lastuserid did it from $lastip (if at least one is specified) with $updatetype. For backwards compatibility if $name
is null then the name will not be changed.
*/
{
if (isset($lastuserid) || isset($lastip)) // use COALESCE() for name since $name=null means it should not be modified (for backwards compatibility)
qa_db_query_sub(
'UPDATE ^posts SET title=$, content=$, format=$, tags=$, name=COALESCE($, name), notify=$, updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#',
$title, $content, $format, $tagstring, $name, $notify, $updatetype, $lastuserid, @inet_pton($lastip), $postid
);
else
qa_db_query_sub(
'UPDATE ^posts SET title=$, content=$, format=$, tags=$, name=COALESCE($, name), notify=$ WHERE postid=#',
$title, $content, $format, $tagstring, $name, $notify, $postid
);
}
function qa_db_post_set_userid($postid, $userid)
/*
Set the author in the database of $postid to $userid, and set the lastuserid to $userid as well if appropriate
*/
{
qa_db_query_sub( qa_db_query_sub(
'UPDATE ^posts SET userid=$, lastuserid=IF(updated IS NULL, lastuserid, COALESCE(lastuserid,$)) WHERE postid=#', 'UPDATE ^posts SET type=$, updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#',
$userid, $userid, $postid $type, $updatetype, $lastuserid, @inet_pton($lastip), $postid
);
} else {
qa_db_query_sub(
'UPDATE ^posts SET type=$ WHERE postid=#',
$type, $postid
); );
} }
}
function qa_db_post_set_category($postid, $categoryid, $lastuserid=null, $lastip=null)
/* /**
Set the (exact) category in the database of $postid to $categoryid, and optionally record that $lastuserid did it from * Set the parent in the database of $postid to $parentid, and optionally record that $lastuserid did it from $lastip
$lastip (if at least one is specified) * (if at least one is specified)
*/ * @param $postid
{ * @param $parentid
if (isset($lastuserid) || isset($lastip)) * @param $lastuserid
qa_db_query_sub( * @param $lastip
"UPDATE ^posts SET categoryid=#, updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#", */
$categoryid, QA_UPDATE_CATEGORY, $lastuserid, @inet_pton($lastip), $postid function qa_db_post_set_parent($postid, $parentid, $lastuserid = null, $lastip = null)
); {
else if (isset($lastuserid) || isset($lastip)) {
qa_db_query_sub( qa_db_query_sub(
'UPDATE ^posts SET categoryid=# WHERE postid=#', "UPDATE ^posts SET parentid=#, updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#",
$categoryid, $postid $parentid, QA_UPDATE_PARENT, $lastuserid, @inet_pton($lastip), $postid
); );
} } else {
qa_db_query_sub(
'UPDATE ^posts SET parentid=# WHERE postid=#',
function qa_db_posts_set_category_path($postids, $path) $parentid, $postid
/* );
Set the category path in the database of each of $postids to $path retrieved via qa_db_post_get_category_path()
*/
{
if (count($postids))
qa_db_query_sub(
'UPDATE ^posts SET categoryid=#, catidpath1=#, catidpath2=#, catidpath3=# WHERE postid IN (#)',
$path['categoryid'], $path['catidpath1'], $path['catidpath2'], $path['catidpath3'], $postids
); // requires QA_CATEGORY_DEPTH=4
}
function qa_db_post_set_created($postid, $created)
/*
Set the created date of $postid to $created, which is a unix timestamp. If created is null, set to now.
*/
{
if (isset($created))
qa_db_query_sub(
'UPDATE ^posts SET created=FROM_UNIXTIME(#) WHERE postid=#',
$created, $postid
);
else
qa_db_query_sub(
'UPDATE ^posts SET created=NOW() WHERE postid=#',
$postid
);
}
function qa_db_post_set_updated($postid, $updated)
/*
Set the last updated date of $postid to $updated, which is a unix timestamp. If updated is null, set to now.
*/
{
if (isset($updated))
qa_db_query_sub(
'UPDATE ^posts SET updated=FROM_UNIXTIME(#) WHERE postid=#',
$updated, $postid
);
else
qa_db_query_sub(
'UPDATE ^posts SET updated=NOW() WHERE postid=#',
$postid
);
} }
}
function qa_db_post_delete($postid)
/* /**
Deletes post $postid from the database (will also delete any votes on the post due to foreign key cascading) * Set the text fields in the database of $postid to $title, $content, $tagstring, $notify and $name, and record that
*/ * $lastuserid did it from $lastip (if at least one is specified) with $updatetype. For backwards compatibility if $name
{ * is null then the name will not be changed.
* @param $postid
* @param $title
* @param $content
* @param $format
* @param $tagstring
* @param $notify
* @param $lastuserid
* @param $lastip
* @param string $updatetype
* @param $name
*/
function qa_db_post_set_content($postid, $title, $content, $format, $tagstring, $notify, $lastuserid = null, $lastip = null, $updatetype = QA_UPDATE_CONTENT, $name = null)
{
if (isset($lastuserid) || isset($lastip)) {
// use COALESCE() for name since $name=null means it should not be modified (for backwards compatibility)
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^posts WHERE postid=#', 'UPDATE ^posts SET title=$, content=$, format=$, tags=$, name=COALESCE($, name), notify=$, updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#',
$postid $title, $content, $format, $tagstring, $name, $notify, $updatetype, $lastuserid, @inet_pton($lastip), $postid
);
} else {
qa_db_query_sub(
'UPDATE ^posts SET title=$, content=$, format=$, tags=$, name=COALESCE($, name), notify=$ WHERE postid=#',
$title, $content, $format, $tagstring, $name, $notify, $postid
); );
} }
}
function qa_db_titlewords_get_post_wordids($postid)
/* /**
Return an array of wordids that were indexed in the database for the title of $postid * Set the author in the database of $postid to $userid, and set the lastuserid to $userid as well if appropriate
*/ * @param $postid
{ * @param $userid
return qa_db_read_all_values(qa_db_query_sub( */
'SELECT wordid FROM ^titlewords WHERE postid=#', function qa_db_post_set_userid($postid, $userid)
$postid {
)); qa_db_query_sub(
'UPDATE ^posts SET userid=$, lastuserid=IF(updated IS NULL, lastuserid, COALESCE(lastuserid,$)) WHERE postid=#',
$userid, $userid, $postid
);
}
/**
* Set the (exact) category in the database of $postid to $categoryid, and optionally record that $lastuserid did it from
* $lastip (if at least one is specified)
* @param $postid
* @param $categoryid
* @param $lastuserid
* @param $lastip
*/
function qa_db_post_set_category($postid, $categoryid, $lastuserid = null, $lastip = null)
{
if (isset($lastuserid) || isset($lastip)) {
qa_db_query_sub(
"UPDATE ^posts SET categoryid=#, updated=NOW(), updatetype=$, lastuserid=$, lastip=$ WHERE postid=#",
$categoryid, QA_UPDATE_CATEGORY, $lastuserid, @inet_pton($lastip), $postid
);
} else {
qa_db_query_sub(
'UPDATE ^posts SET categoryid=# WHERE postid=#',
$categoryid, $postid
);
} }
}
function qa_db_titlewords_delete_post($postid)
/* /**
Remove all entries in the database index of title words for $postid * Set the category path in the database of each of $postids to $path retrieved via qa_db_post_get_category_path()
*/ * @param $postids
{ * @param $path
*/
function qa_db_posts_set_category_path($postids, $path)
{
if (count($postids)) {
// requires QA_CATEGORY_DEPTH=4
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^titlewords WHERE postid=#', 'UPDATE ^posts SET categoryid=#, catidpath1=#, catidpath2=#, catidpath3=# WHERE postid IN (#)',
$postid $path['categoryid'], $path['catidpath1'], $path['catidpath2'], $path['catidpath3'], $postids
); );
} }
}
function qa_db_contentwords_get_post_wordids($postid) /**
/* * Set the created date of $postid to $created, which is a unix timestamp. If created is null, set to now.
Return an array of wordids that were indexed in the database for the content of $postid * @param $postid
*/ * @param $created
{ */
return qa_db_read_all_values(qa_db_query_sub( function qa_db_post_set_created($postid, $created)
'SELECT wordid FROM ^contentwords WHERE postid=#', {
if (isset($created)) {
qa_db_query_sub(
'UPDATE ^posts SET created=FROM_UNIXTIME(#) WHERE postid=#',
$created, $postid
);
} else {
qa_db_query_sub(
'UPDATE ^posts SET created=NOW() WHERE postid=#',
$postid $postid
)); );
} }
}
function qa_db_contentwords_delete_post($postid) /**
/* * Set the last updated date of $postid to $updated, which is a unix timestamp. If updated is null, set to now.
Remove all entries in the database index of content words for $postid * @param $postid
*/ * @param $updated
{ */
function qa_db_post_set_updated($postid, $updated)
{
if (isset($updated)) {
qa_db_query_sub(
'UPDATE ^posts SET updated=FROM_UNIXTIME(#) WHERE postid=#',
$updated, $postid
);
} else {
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^contentwords WHERE postid=#', 'UPDATE ^posts SET updated=NOW() WHERE postid=#',
$postid $postid
); );
} }
}
function qa_db_tagwords_get_post_wordids($postid)
/* /**
Return an array of wordids that were indexed in the database for the individual words in tags of $postid * Deletes post $postid from the database (will also delete any votes on the post due to foreign key cascading)
*/ * @param $postid
{ */
function qa_db_post_delete($postid)
{
qa_db_query_sub(
'DELETE FROM ^posts WHERE postid=#',
$postid
);
}
/**
* Return an array of wordids that were indexed in the database for the title of $postid
* @param $postid
* @return array
*/
function qa_db_titlewords_get_post_wordids($postid)
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT wordid FROM ^titlewords WHERE postid=#',
$postid
));
}
/**
* Remove all entries in the database index of title words for $postid
* @param $postid
*/
function qa_db_titlewords_delete_post($postid)
{
qa_db_query_sub(
'DELETE FROM ^titlewords WHERE postid=#',
$postid
);
}
/**
* Return an array of wordids that were indexed in the database for the content of $postid
* @param $postid
* @return array
*/
function qa_db_contentwords_get_post_wordids($postid)
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT wordid FROM ^contentwords WHERE postid=#',
$postid
));
}
/**
* Remove all entries in the database index of content words for $postid
* @param $postid
*/
function qa_db_contentwords_delete_post($postid)
{
qa_db_query_sub(
'DELETE FROM ^contentwords WHERE postid=#',
$postid
);
}
/**
* Return an array of wordids that were indexed in the database for the individual words in tags of $postid
* @param $postid
* @return array
*/
function qa_db_tagwords_get_post_wordids($postid)
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT wordid FROM ^tagwords WHERE postid=#',
$postid
));
}
/**
* Remove all entries in the database index of individual words in tags of $postid
* @param $postid
*/
function qa_db_tagwords_delete_post($postid)
{
qa_db_query_sub(
'DELETE FROM ^tagwords WHERE postid=#',
$postid
);
}
/**
* Return an array of wordids that were indexed in the database for the whole tags of $postid
* @param $postid
* @return array
*/
function qa_db_posttags_get_post_wordids($postid)
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT wordid FROM ^posttags WHERE postid=#',
$postid
));
}
/**
* Remove all entries in the database index of whole tags for $postid
* @param $postid
*/
function qa_db_posttags_delete_post($postid)
{
qa_db_query_sub(
'DELETE FROM ^posttags WHERE postid=#',
$postid
);
}
/**
* Return the array $postids containing only those elements which are the postid of a question in the database
* @param $postids
* @return array
*/
function qa_db_posts_filter_q_postids($postids)
{
if (count($postids)) {
return qa_db_read_all_values(qa_db_query_sub( return qa_db_read_all_values(qa_db_query_sub(
'SELECT wordid FROM ^tagwords WHERE postid=#', "SELECT postid FROM ^posts WHERE type='Q' AND postid IN (#)",
$postid $postids
)); ));
} }
return array();
}
function qa_db_tagwords_delete_post($postid)
/*
Remove all entries in the database index of individual words in tags of $postid
*/
{
qa_db_query_sub(
'DELETE FROM ^tagwords WHERE postid=#',
$postid
);
}
/**
function qa_db_posttags_get_post_wordids($postid) * Return an array of all the userids of authors of posts in the array $postids
/* * @param $postids
Return an array of wordids that were indexed in the database for the whole tags of $postid * @return array
*/ */
{ function qa_db_posts_get_userids($postids)
{
if (count($postids)) {
return qa_db_read_all_values(qa_db_query_sub( return qa_db_read_all_values(qa_db_query_sub(
'SELECT wordid FROM ^posttags WHERE postid=#', "SELECT DISTINCT userid FROM ^posts WHERE postid IN (#) AND userid IS NOT NULL",
$postid $postids
)); ));
} }
return array();
}
function qa_db_posttags_delete_post($postid)
/* /**
Remove all entries in the database index of whole tags for $postid * Update the cached count of the number of flagged posts in the database
*/ */
{ function qa_db_flaggedcount_update()
{
if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^posttags WHERE postid=#', "INSERT INTO ^options (title, content) " .
$postid "SELECT 'cache_flaggedcount', COUNT(*) FROM ^posts " .
"WHERE flagcount > 0 AND type IN ('Q', 'A', 'C') " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)"
); );
} }
}
function qa_db_posts_filter_q_postids($postids)
/*
Return the array $postids containing only those elements which are the postid of a question in the database
*/
{
if (count($postids))
return qa_db_read_all_values(qa_db_query_sub(
"SELECT postid FROM ^posts WHERE type='Q' AND postid IN (#)",
$postids
));
else
return array();
}
function qa_db_posts_get_userids($postids)
/*
Return an array of all the userids of authors of posts in the array $postids
*/
{
if (count($postids))
return qa_db_read_all_values(qa_db_query_sub(
"SELECT DISTINCT userid FROM ^posts WHERE postid IN (#) AND userid IS NOT NULL",
$postids
));
else
return array();
}
function qa_db_flaggedcount_update()
/*
Update the cached count of the number of flagged posts in the database
*/
{
if (qa_should_update_counts()) {
qa_db_query_sub(
"INSERT INTO ^options (title, content) " .
"SELECT 'cache_flaggedcount', COUNT(*) FROM ^posts " .
"WHERE flagcount > 0 AND type IN ('Q', 'A', 'C') " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)"
);
}
}
/*
Omit PHP closing tag to help avoid accidental output
*/
...@@ -20,337 +20,381 @@ ...@@ -20,337 +20,381 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
} }
function qa_db_calc_passcheck($password, $salt) /**
/* * Return the expected value for the passcheck column given the $password and password $salt
Return the expected value for the passcheck column given the $password and password $salt * @param $password
*/ * @param $salt
{ * @return mixed|string
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } */
function qa_db_calc_passcheck($password, $salt)
return sha1(substr($salt, 0, 8).$password.substr($salt, 8)); {
} if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return sha1(substr($salt, 0, 8) . $password . substr($salt, 8));
function qa_db_user_create($email, $password, $handle, $level, $ip) }
/*
Create a new user in the database with $email, $password, $handle, privilege $level, and $ip address
*/ /**
{ * Create a new user in the database with $email, $password, $handle, privilege $level, and $ip address
require_once QA_INCLUDE_DIR.'util/string.php'; * @param $email
* @param $password
$ipbin = @inet_pton($ip); * @param $handle
* @param $level
if (QA_PASSWORD_HASH) { * @param $ip
qa_db_query_sub( * @return mixed
'INSERT INTO ^users (created, createip, email, passhash, level, handle, loggedin, loginip) '. */
'VALUES (NOW(), $, $, $, #, $, NOW(), $)', function qa_db_user_create($email, $password, $handle, $level, $ip)
$ipbin, $email, isset($password) ? password_hash($password, PASSWORD_BCRYPT) : null, (int)$level, $handle, $ipbin {
); require_once QA_INCLUDE_DIR . 'util/string.php';
} else {
$salt = isset($password) ? qa_random_alphanum(16) : null; $ipbin = @inet_pton($ip);
qa_db_query_sub( if (QA_PASSWORD_HASH) {
'INSERT INTO ^users (created, createip, email, passsalt, passcheck, level, handle, loggedin, loginip) '.
'VALUES (NOW(), $, $, $, UNHEX($), #, $, NOW(), $)',
$ipbin, $email, $salt, isset($password) ? qa_db_calc_passcheck($password, $salt) : null, (int)$level, $handle, $ipbin
);
}
return qa_db_last_insert_id();
}
function qa_db_user_delete($userid)
/*
Delete user $userid from the database, along with everything they have ever done (to the extent that it's possible)
*/
{
qa_db_query_sub('UPDATE ^posts SET lastuserid=NULL WHERE lastuserid=$', $userid);
qa_db_query_sub('DELETE FROM ^userpoints WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^blobs WHERE blobid=(SELECT avatarblobid FROM ^users WHERE userid=$)', $userid);
qa_db_query_sub('DELETE FROM ^users WHERE userid=$', $userid);
// All the queries below should be superfluous due to foreign key constraints, but just in case the user switched to MyISAM.
// Note also that private messages to/from that user are kept since we don't have all the keys we need to delete efficiently.
qa_db_query_sub('UPDATE ^posts SET userid=NULL WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^userlogins WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^userprofile WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^userfavorites WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^userevents WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^uservotes WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^userlimits WHERE userid=$', $userid);
}
function qa_db_user_find_by_email($email)
/*
Return the ids of all users in the database which match $email (should be one or none)
*/
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT userid FROM ^users WHERE email=$',
$email
));
}
function qa_db_user_find_by_handle($handle)
/*
Return the ids of all users in the database which match $handle (=username), should be one or none
*/
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT userid FROM ^users WHERE handle=$',
$handle
));
}
function qa_db_user_get_userid_handles($userids)
/*
Return an array mapping each userid in $userids that can be found to that user's handle
*/
{
if (count($userids))
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT userid, handle FROM ^users WHERE userid IN (#)',
$userids
), 'userid', 'handle');
else
return array();
}
function qa_db_user_get_handle_userids($handles)
/*
Return an array mapping mapping each handle in $handle that can be found to that user's userid
*/
{
if (count($handles))
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT handle, userid FROM ^users WHERE handle IN ($)',
$handles
), 'handle', 'userid');
else
return array();
}
function qa_db_user_set($userid, $field, $value)
/*
Set $field of $userid to $value in the database users table
*/
{
qa_db_query_sub( qa_db_query_sub(
'UPDATE ^users SET '.qa_db_escape_string($field).'=$ WHERE userid=$', 'INSERT INTO ^users (created, createip, email, passhash, level, handle, loggedin, loginip) ' .
$value, $userid 'VALUES (NOW(), $, $, $, #, $, NOW(), $)',
$ipbin, $email, isset($password) ? password_hash($password, PASSWORD_BCRYPT) : null, (int)$level, $handle, $ipbin
); );
} } else {
$salt = isset($password) ? qa_random_alphanum(16) : null;
function qa_db_user_set_password($userid, $password)
/*
Set the password of $userid to $password, and reset their salt at the same time
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'util/string.php';
if (QA_PASSWORD_HASH) {
qa_db_query_sub(
'UPDATE ^users SET passhash=$, passsalt=NULL, passcheck=NULL WHERE userid=$',
password_hash($password, PASSWORD_BCRYPT), $userid
);
} else {
$salt = qa_random_alphanum(16);
qa_db_query_sub(
'UPDATE ^users SET passsalt=$, passcheck=UNHEX($) WHERE userid=$',
$salt, qa_db_calc_passcheck($password, $salt), $userid
);
}
}
function qa_db_user_set_flag($userid, $flag, $set)
/*
Switch on the $flag bit of the flags column for $userid if $set is true, or switch off otherwise
*/
{
qa_db_query_sub( qa_db_query_sub(
'UPDATE ^users SET flags=flags'.($set ? '|' : '&~').'# WHERE userid=$', 'INSERT INTO ^users (created, createip, email, passsalt, passcheck, level, handle, loggedin, loginip) ' .
$flag, $userid 'VALUES (NOW(), $, $, $, UNHEX($), #, $, NOW(), $)',
$ipbin, $email, $salt, isset($password) ? qa_db_calc_passcheck($password, $salt) : null, (int)$level, $handle, $ipbin
); );
} }
function qa_db_user_rand_emailcode() return qa_db_last_insert_id();
/* }
Return a random string to be used for a user's emailcode column
*/
{ /**
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } * Delete user $userid from the database, along with everything they have ever done (to the extent that it's possible)
* @param $userid
require_once QA_INCLUDE_DIR.'util/string.php'; */
function qa_db_user_delete($userid)
return qa_random_alphanum(8); {
qa_db_query_sub('UPDATE ^posts SET lastuserid=NULL WHERE lastuserid=$', $userid);
qa_db_query_sub('DELETE FROM ^userpoints WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^blobs WHERE blobid=(SELECT avatarblobid FROM ^users WHERE userid=$)', $userid);
qa_db_query_sub('DELETE FROM ^users WHERE userid=$', $userid);
// All the queries below should be superfluous due to foreign key constraints, but just in case the user switched to MyISAM.
// Note also that private messages to/from that user are kept since we don't have all the keys we need to delete efficiently.
qa_db_query_sub('UPDATE ^posts SET userid=NULL WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^userlogins WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^userprofile WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^userfavorites WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^userevents WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^uservotes WHERE userid=$', $userid);
qa_db_query_sub('DELETE FROM ^userlimits WHERE userid=$', $userid);
}
/**
* Return the ids of all users in the database which match $email (should be one or none)
* @param $email
* @return array
*/
function qa_db_user_find_by_email($email)
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT userid FROM ^users WHERE email=$',
$email
));
}
/**
* Return the ids of all users in the database which match $handle (=username), should be one or none
* @param $handle
* @return array
*/
function qa_db_user_find_by_handle($handle)
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT userid FROM ^users WHERE handle=$',
$handle
));
}
/**
* Return an array mapping each userid in $userids that can be found to that user's handle
* @param $userids
* @return array
*/
function qa_db_user_get_userid_handles($userids)
{
if (count($userids)) {
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT userid, handle FROM ^users WHERE userid IN (#)',
$userids
), 'userid', 'handle');
} }
return array();
}
function qa_db_user_rand_sessioncode()
/*
Return a random string to be used for a user's sessioncode column (for browser session cookies)
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'util/string.php';
return qa_random_alphanum(8); /**
* Return an array mapping mapping each handle in $handle that can be found to that user's userid
* @param $handles
* @return array
*/
function qa_db_user_get_handle_userids($handles)
{
if (count($handles)) {
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT handle, userid FROM ^users WHERE handle IN ($)',
$handles
), 'handle', 'userid');
} }
return array();
function qa_db_user_profile_set($userid, $field, $value) }
/*
Set a row in the database user profile table to store $value for $field for $userid
*/ /**
{ * Set $field of $userid to $value in the database users table
* @param $userid
* @param $field
* @param $value
*/
function qa_db_user_set($userid, $field, $value)
{
qa_db_query_sub(
'UPDATE ^users SET ' . qa_db_escape_string($field) . '=$ WHERE userid=$',
$value, $userid
);
}
/**
* Set the password of $userid to $password, and reset their salt at the same time
* @param $userid
* @param $password
* @return mixed
*/
function qa_db_user_set_password($userid, $password)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR . 'util/string.php';
if (QA_PASSWORD_HASH) {
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^userprofile (userid, title, content) VALUES ($, $, $) ' . 'UPDATE ^users SET passhash=$, passsalt=NULL, passcheck=NULL WHERE userid=$',
'ON DUPLICATE KEY UPDATE content = VALUES(content)', password_hash($password, PASSWORD_BCRYPT), $userid
$userid, $field, $value
); );
} } else {
$salt = qa_random_alphanum(16);
function qa_db_user_logged_in($userid, $ip)
/*
Note in the database that $userid just logged in from $ip address
*/
{
qa_db_query_sub( qa_db_query_sub(
'UPDATE ^users SET loggedin=NOW(), loginip=$ WHERE userid=$', 'UPDATE ^users SET passsalt=$, passcheck=UNHEX($) WHERE userid=$',
@inet_pton($ip), $userid $salt, qa_db_calc_passcheck($password, $salt), $userid
); );
} }
}
function qa_db_user_written($userid, $ip)
/* /**
Note in the database that $userid just performed a write operation from $ip address * Switch on the $flag bit of the flags column for $userid if $set is true, or switch off otherwise
*/ * @param $userid
{ * @param $flag
qa_db_query_sub( * @param $set
'UPDATE ^users SET written=NOW(), writeip=$ WHERE userid=$', */
@inet_pton($ip), $userid function qa_db_user_set_flag($userid, $flag, $set)
); {
qa_db_query_sub(
'UPDATE ^users SET flags=flags' . ($set ? '|' : '&~') . '# WHERE userid=$',
$flag, $userid
);
}
/**
* Return a random string to be used for a user's emailcode column
*/
function qa_db_user_rand_emailcode()
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR . 'util/string.php';
return qa_random_alphanum(8);
}
/**
* Return a random string to be used for a user's sessioncode column (for browser session cookies)
*/
function qa_db_user_rand_sessioncode()
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR . 'util/string.php';
return qa_random_alphanum(8);
}
/**
* Set a row in the database user profile table to store $value for $field for $userid
* @param $userid
* @param $field
* @param $value
*/
function qa_db_user_profile_set($userid, $field, $value)
{
qa_db_query_sub(
'INSERT INTO ^userprofile (userid, title, content) VALUES ($, $, $) ' .
'ON DUPLICATE KEY UPDATE content = VALUES(content)',
$userid, $field, $value
);
}
/**
* Note in the database that $userid just logged in from $ip address
* @param $userid
* @param $ip
*/
function qa_db_user_logged_in($userid, $ip)
{
qa_db_query_sub(
'UPDATE ^users SET loggedin=NOW(), loginip=$ WHERE userid=$',
@inet_pton($ip), $userid
);
}
/**
* Note in the database that $userid just performed a write operation from $ip address
* @param $userid
* @param $ip
*/
function qa_db_user_written($userid, $ip)
{
qa_db_query_sub(
'UPDATE ^users SET written=NOW(), writeip=$ WHERE userid=$',
@inet_pton($ip), $userid
);
}
/**
* Add an external login in the database for $source and $identifier for user $userid
* @param $userid
* @param $source
* @param $identifier
*/
function qa_db_user_login_add($userid, $source, $identifier)
{
qa_db_query_sub(
'INSERT INTO ^userlogins (userid, source, identifier, identifiermd5) ' .
'VALUES ($, $, $, UNHEX($))',
$userid, $source, $identifier, md5($identifier)
);
}
/**
* Return some information about the user with external login $source and $identifier in the database, if a match is found
* @param $source
* @param $identifier
* @return array
*/
function qa_db_user_login_find($source, $identifier)
{
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT ^userlogins.userid, handle, email FROM ^userlogins LEFT JOIN ^users ON ^userlogins.userid=^users.userid ' .
'WHERE source=$ AND identifiermd5=UNHEX($) AND identifier=$',
$source, md5($identifier), $identifier
));
}
/**
* Lock all tables if $sync is true, otherwise unlock them. Used to synchronize creation of external login mappings.
* @param $sync
*/
function qa_db_user_login_sync($sync)
{
if ($sync) { // need to lock all tables since any could be used by a plugin's event module
$tables = qa_db_list_tables();
$locks = array();
foreach ($tables as $table)
$locks[] = $table . ' WRITE';
qa_db_query_sub('LOCK TABLES ' . implode(', ', $locks));
} else {
qa_db_query_sub('UNLOCK TABLES');
} }
}
function qa_db_user_login_add($userid, $source, $identifier)
/* /**
Add an external login in the database for $source and $identifier for user $userid * Reset the full set of context-specific (currently, per category) user levels for user $userid to $userlevels, where
*/ * $userlevels is an array of arrays, the inner arrays containing items 'entitytype', 'entityid' and 'level'.
{ * @param $userid
* @param $userlevels
*/
function qa_db_user_levels_set($userid, $userlevels)
{
qa_db_query_sub(
'DELETE FROM ^userlevels WHERE userid=$',
$userid
);
foreach ($userlevels as $userlevel) {
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^userlogins (userid, source, identifier, identifiermd5) '. 'INSERT INTO ^userlevels (userid, entitytype, entityid, level) VALUES ($, $, #, #) ' .
'VALUES ($, $, $, UNHEX($))', 'ON DUPLICATE KEY UPDATE level = VALUES(level)',
$userid, $source, $identifier, md5($identifier) $userid, $userlevel['entitytype'], $userlevel['entityid'], $userlevel['level']
); );
} }
}
function qa_db_user_login_find($source, $identifier)
/* /**
Return some information about the user with external login $source and $identifier in the database, if a match is found * Get the information required for sending a mailing to the next $count users with userids greater than $lastuserid
*/ * @param $lastuserid
{ * @param $count
return qa_db_read_all_assoc(qa_db_query_sub( * @return array
'SELECT ^userlogins.userid, handle, email FROM ^userlogins LEFT JOIN ^users ON ^userlogins.userid=^users.userid '. */
'WHERE source=$ AND identifiermd5=UNHEX($) AND identifier=$', function qa_db_users_get_mailing_next($lastuserid, $count)
$source, md5($identifier), $identifier {
)); return qa_db_read_all_assoc(qa_db_query_sub(
} 'SELECT userid, email, handle, emailcode, flags FROM ^users WHERE userid># ORDER BY userid LIMIT #',
$lastuserid, $count
));
function qa_db_user_login_sync($sync) }
/*
Lock all tables if $sync is true, otherwise unlock them. Used to synchronize creation of external login mappings.
*/ /**
{ * Update the cached count of the number of users who are awaiting approval after registration
if ($sync) { // need to lock all tables since any could be used by a plugin's event module */
$tables=qa_db_list_tables(); function qa_db_uapprovecount_update()
{
$locks=array(); if (qa_should_update_counts() && !QA_FINAL_EXTERNAL_USERS) {
foreach ($tables as $table)
$locks[]=$table.' WRITE';
qa_db_query_sub('LOCK TABLES '.implode(', ', $locks));
} else
qa_db_query_sub('UNLOCK TABLES');
}
function qa_db_user_levels_set($userid, $userlevels)
/*
Reset the full set of context-specific (currently, per category) user levels for user $userid to $userlevels, where
$userlevels is an array of arrays, the inner arrays containing items 'entitytype', 'entityid' and 'level'.
*/
{
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^userlevels WHERE userid=$', "INSERT INTO ^options (title, content) " .
$userid "SELECT 'cache_uapprovecount', COUNT(*) FROM ^users " .
"WHERE level < # AND NOT (flags & #) " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)",
QA_USER_LEVEL_APPROVED, QA_USER_FLAGS_USER_BLOCKED
); );
foreach ($userlevels as $userlevel) {
qa_db_query_sub(
'INSERT INTO ^userlevels (userid, entitytype, entityid, level) VALUES ($, $, #, #) ' .
'ON DUPLICATE KEY UPDATE level = VALUES(level)',
$userid, $userlevel['entitytype'], $userlevel['entityid'], $userlevel['level']
);
}
}
function qa_db_users_get_mailing_next($lastuserid, $count)
/*
Get the information required for sending a mailing to the next $count users with userids greater than $lastuserid
*/
{
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT userid, email, handle, emailcode, flags FROM ^users WHERE userid># ORDER BY userid LIMIT #',
$lastuserid, $count
));
}
function qa_db_uapprovecount_update()
/*
Update the cached count of the number of users who are awaiting approval after registration
*/
{
if ( qa_should_update_counts() && !QA_FINAL_EXTERNAL_USERS ) {
qa_db_query_sub(
"INSERT INTO ^options (title, content) " .
"SELECT 'cache_uapprovecount', COUNT(*) FROM ^users " .
"WHERE level < # AND NOT (flags & #) " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)",
QA_USER_LEVEL_APPROVED, QA_USER_FLAGS_USER_BLOCKED
);
}
} }
}
/*
Omit PHP closing tag to help avoid accidental output
*/
...@@ -20,145 +20,159 @@ ...@@ -20,145 +20,159 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
} }
function qa_db_uservote_set($postid, $userid, $vote) /**
/* * Set the vote for $userid on $postid to $vote in the database
Set the vote for $userid on $postid to $vote in the database * @param $postid
*/ * @param $userid
{ * @param $vote
$vote=max(min(($vote), 1), -1); */
function qa_db_uservote_set($postid, $userid, $vote)
qa_db_query_sub( {
'INSERT INTO ^uservotes (postid, userid, vote, flag) VALUES (#, #, #, 0) ON DUPLICATE KEY UPDATE vote=#', $vote = max(min(($vote), 1), -1);
$postid, $userid, $vote, $vote
); qa_db_query_sub(
} 'INSERT INTO ^uservotes (postid, userid, vote, flag) VALUES (#, #, #, 0) ON DUPLICATE KEY UPDATE vote=#',
$postid, $userid, $vote, $vote
);
function qa_db_uservote_get($postid, $userid) }
/*
Get the vote for $userid on $postid from the database (or NULL if none)
*/ /**
{ * Get the vote for $userid on $postid from the database (or NULL if none)
return qa_db_read_one_value(qa_db_query_sub( * @param $postid
'SELECT vote FROM ^uservotes WHERE postid=# AND userid=#', * @param $userid
$postid, $userid * @return mixed|null
), true); */
} function qa_db_uservote_get($postid, $userid)
{
return qa_db_read_one_value(qa_db_query_sub(
function qa_db_userflag_set($postid, $userid, $flag) 'SELECT vote FROM ^uservotes WHERE postid=# AND userid=#',
/* $postid, $userid
Set the flag for $userid on $postid to $flag (true or false) in the database ), true);
*/ }
{
$flag=$flag ? 1 : 0;
/**
* Set the flag for $userid on $postid to $flag (true or false) in the database
* @param $postid
* @param $userid
* @param $flag
*/
function qa_db_userflag_set($postid, $userid, $flag)
{
$flag = $flag ? 1 : 0;
qa_db_query_sub(
'INSERT INTO ^uservotes (postid, userid, vote, flag) VALUES (#, #, 0, #) ON DUPLICATE KEY UPDATE flag=#',
$postid, $userid, $flag, $flag
);
}
/**
* Clear all flags for $postid in the database
* @param $postid
*/
function qa_db_userflags_clear_all($postid)
{
qa_db_query_sub(
'UPDATE ^uservotes SET flag=0 WHERE postid=#',
$postid
);
}
/**
* Recalculate the cached count of upvotes, downvotes and netvotes for $postid in the database
* @param $postid
*/
function qa_db_post_recount_votes($postid)
{
if (qa_should_update_counts())
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^uservotes (postid, userid, vote, flag) VALUES (#, #, 0, #) ON DUPLICATE KEY UPDATE flag=#', 'UPDATE ^posts AS x, (SELECT COALESCE(SUM(GREATEST(0,vote)),0) AS upvotes, -COALESCE(SUM(LEAST(0,vote)),0) AS downvotes FROM ^uservotes WHERE postid=#) AS a SET x.upvotes=a.upvotes, x.downvotes=a.downvotes, x.netvotes=a.upvotes-a.downvotes WHERE x.postid=#',
$postid, $userid, $flag, $flag $postid, $postid
); );
} }
function qa_db_userflags_clear_all($postid) /**
/* * Recalculate the cached count of flags for $postid in the database
Clear all flags for $postid in the database * @param $postid
*/ */
{ function qa_db_post_recount_flags($postid)
{
if (qa_should_update_counts())
qa_db_query_sub( qa_db_query_sub(
'UPDATE ^uservotes SET flag=0 WHERE postid=#', 'UPDATE ^posts AS x, (SELECT COALESCE(SUM(IF(flag, 1, 0)),0) AS flagcount FROM ^uservotes WHERE postid=#) AS a SET x.flagcount=a.flagcount WHERE x.postid=#',
$postid $postid, $postid
); );
} }
function qa_db_post_recount_votes($postid) /**
/* * Returns all non-zero votes on post $postid from the database as an array of [userid] => [vote]
Recalculate the cached count of upvotes, downvotes and netvotes for $postid in the database * @param $postid
*/ * @return array
{ */
if (qa_should_update_counts()) function qa_db_uservote_post_get($postid)
qa_db_query_sub( {
'UPDATE ^posts AS x, (SELECT COALESCE(SUM(GREATEST(0,vote)),0) AS upvotes, -COALESCE(SUM(LEAST(0,vote)),0) AS downvotes FROM ^uservotes WHERE postid=#) AS a SET x.upvotes=a.upvotes, x.downvotes=a.downvotes, x.netvotes=a.upvotes-a.downvotes WHERE x.postid=#', return qa_db_read_all_assoc(qa_db_query_sub(
$postid, $postid 'SELECT userid, vote FROM ^uservotes WHERE postid=# AND vote!=0',
); $postid
} ), 'userid', 'vote');
}
function qa_db_post_recount_flags($postid)
/* /**
Recalculate the cached count of flags for $postid in the database * Returns all the postids from the database for posts that $userid has voted on or flagged
*/ * @param $userid
{ * @return array
if (qa_should_update_counts()) */
qa_db_query_sub( function qa_db_uservoteflag_user_get($userid)
'UPDATE ^posts AS x, (SELECT COALESCE(SUM(IF(flag, 1, 0)),0) AS flagcount FROM ^uservotes WHERE postid=#) AS a SET x.flagcount=a.flagcount WHERE x.postid=#', {
$postid, $postid return qa_db_read_all_values(qa_db_query_sub(
); 'SELECT postid FROM ^uservotes WHERE userid=# AND (vote!=0) OR (flag!=0)',
} $userid
));
}
function qa_db_uservote_post_get($postid)
/*
Returns all non-zero votes on post $postid from the database as an array of [userid] => [vote] /**
*/ * Return information about all the non-zero votes and/or flags on the posts in postids, including user handles for internal user management
{ * @param $postids
* @return array
*/
function qa_db_uservoteflag_posts_get($postids)
{
if (QA_FINAL_EXTERNAL_USERS) {
return qa_db_read_all_assoc(qa_db_query_sub( return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT userid, vote FROM ^uservotes WHERE postid=# AND vote!=0', 'SELECT postid, userid, vote, flag FROM ^uservotes WHERE postid IN (#) AND ((vote!=0) OR (flag!=0))',
$postid $postids
), 'userid', 'vote'); ));
} } else {
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT postid, handle, vote, flag FROM ^uservotes LEFT JOIN ^users ON ^uservotes.userid=^users.userid WHERE postid IN (#) AND ((vote!=0) OR (flag!=0))',
function qa_db_uservoteflag_user_get($userid) $postids
/*
Returns all the postids from the database for posts that $userid has voted on or flagged
*/
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT postid FROM ^uservotes WHERE userid=# AND (vote!=0) OR (flag!=0)',
$userid
)); ));
} }
}
function qa_db_uservoteflag_posts_get($postids)
/* /**
Return information about all the non-zero votes and/or flags on the posts in postids, including user handles for internal user management * Remove all votes assigned to a post that had been cast by the owner of the post.
*/ *
{ * @param int $postid The post ID from which the owner's votes will be removed.
if (QA_FINAL_EXTERNAL_USERS) */
return qa_db_read_all_assoc(qa_db_query_sub( function qa_db_uservote_remove_own($postid)
'SELECT postid, userid, vote, flag FROM ^uservotes WHERE postid IN (#) AND ((vote!=0) OR (flag!=0))', {
$postids qa_db_query_sub(
)); 'DELETE uv FROM ^uservotes uv JOIN ^posts p ON uv.postid=p.postid AND uv.userid=p.userid WHERE uv.postid=#', $postid
);
else }
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT postid, handle, vote, flag FROM ^uservotes LEFT JOIN ^users ON ^uservotes.userid=^users.userid WHERE postid IN (#) AND ((vote!=0) OR (flag!=0))',
$postids
));
}
/**
* Remove all votes assigned to a post that had been cast by the owner of the post.
*
* @param int $postid The post ID from which the owner's votes will be removed.
*/
function qa_db_uservote_remove_own($postid)
{
qa_db_query_sub(
'DELETE uv FROM ^uservotes uv JOIN ^posts p ON uv.postid=p.postid AND uv.userid=p.userid WHERE uv.postid=#', $postid
);
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment