Commit f5aaabc6 by Scott

Coding style (db functions)

parent b8eaff85
......@@ -20,91 +20,103 @@
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
header('Location: ../');
exit;
}
function qa_db_blob_create($content, $format, $sourcefilename=null, $userid=null, $cookieid=null, $ip=null)
/*
Create a new blob in the database with $content and $format, other fields as provided
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
for ($attempt=0; $attempt<10; $attempt++) {
$blobid=qa_db_random_bigint();
if (qa_db_blob_exists($blobid))
continue;
qa_db_query_sub(
'INSERT INTO ^blobs (blobid, format, content, filename, userid, cookieid, createip, created) VALUES (#, $, $, $, $, #, $, NOW())',
$blobid, $format, $content, $sourcefilename, $userid, $cookieid, @inet_pton($ip)
);
return $blobid;
}
return null;
}
function qa_db_blob_read($blobid)
/*
Get the information about blob $blobid from the database
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_db_read_one_assoc(qa_db_query_sub(
'SELECT content, format, filename FROM ^blobs WHERE blobid=#',
$blobid
), true);
}
function qa_db_blob_set_content($blobid, $content)
/*
Change the content of blob $blobid in the database to $content (can also be null)
*/
{
qa_db_query_sub(
'UPDATE ^blobs SET content=$ WHERE blobid=#',
$content, $blobid
);
}
function qa_db_blob_delete($blobid)
/*
Delete blob $blobid in the database
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
/**
* Create a new blob in the database with $content and $format, other fields as provided
* @param $content
* @param $format
* @param $sourcefilename
* @param $userid
* @param $cookieid
* @param $ip
* @return mixed|null|string
*/
function qa_db_blob_create($content, $format, $sourcefilename = null, $userid = null, $cookieid = null, $ip = null)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
for ($attempt = 0; $attempt < 10; $attempt++) {
$blobid = qa_db_random_bigint();
if (qa_db_blob_exists($blobid))
continue;
qa_db_query_sub(
'DELETE FROM ^blobs WHERE blobid=#',
$blobid
'INSERT INTO ^blobs (blobid, format, content, filename, userid, cookieid, createip, created) VALUES (#, $, $, $, $, #, $, NOW())',
$blobid, $format, $content, $sourcefilename, $userid, $cookieid, @inet_pton($ip)
);
}
function qa_db_blob_exists($blobid)
/*
Check if blob $blobid exists in the database
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^blobs WHERE blobid=#',
$blobid
)) > 0;
return $blobid;
}
/*
Omit PHP closing tag to help avoid accidental output
*/
return null;
}
/**
* Get the information about blob $blobid from the database
* @param $blobid
* @return array|mixed|null
*/
function qa_db_blob_read($blobid)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_db_read_one_assoc(qa_db_query_sub(
'SELECT content, format, filename FROM ^blobs WHERE blobid=#',
$blobid
), true);
}
/**
* Change the content of blob $blobid in the database to $content (can also be null)
* @param $blobid
* @param $content
*/
function qa_db_blob_set_content($blobid, $content)
{
qa_db_query_sub(
'UPDATE ^blobs SET content=$ WHERE blobid=#',
$content, $blobid
);
}
/**
* Delete blob $blobid in the database
* @param $blobid
* @return mixed
*/
function qa_db_blob_delete($blobid)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
qa_db_query_sub(
'DELETE FROM ^blobs WHERE blobid=#',
$blobid
);
}
/**
* Check if blob $blobid exists in the database
* @param $blobid
* @return bool|mixed
*/
function qa_db_blob_exists($blobid)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$blob = qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^blobs WHERE blobid=#',
$blobid
));
return $blob > 0;
}
......@@ -20,56 +20,58 @@
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
header('Location: ../');
exit;
}
require_once QA_INCLUDE_DIR.'db/maxima.php';
function qa_db_cache_set($type, $cacheid, $content)
/*
Create (or replace) the item ($type, $cacheid) in the database cache table with $content
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
require_once QA_INCLUDE_DIR . 'db/maxima.php';
/**
* Create (or replace) the item ($type, $cacheid) in the database cache table with $content
* @param $type
* @param $cacheid
* @param $content
* @return mixed
*/
function qa_db_cache_set($type, $cacheid, $content)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
qa_db_query_sub(
'DELETE FROM ^cache WHERE lastread<NOW()-INTERVAL # SECOND',
QA_DB_MAX_CACHE_AGE
);
qa_db_query_sub(
'INSERT INTO ^cache (type, cacheid, content, created, lastread) VALUES ($, #, $, NOW(), NOW()) ' .
'ON DUPLICATE KEY UPDATE content = VALUES(content), created = VALUES(created), lastread = VALUES(lastread)',
$type, $cacheid, $content
);
}
/**
* Retrieve the item ($type, $cacheid) from the database cache table
* @param $type
* @param $cacheid
* @return mixed|null
*/
function qa_db_cache_get($type, $cacheid)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$content = qa_db_read_one_value(qa_db_query_sub(
'SELECT content FROM ^cache WHERE type=$ AND cacheid=#',
$type, $cacheid
), true);
if (isset($content))
qa_db_query_sub(
'DELETE FROM ^cache WHERE lastread<NOW()-INTERVAL # SECOND',
QA_DB_MAX_CACHE_AGE
);
qa_db_query_sub(
'INSERT INTO ^cache (type, cacheid, content, created, lastread) VALUES ($, #, $, NOW(), NOW()) ' .
'ON DUPLICATE KEY UPDATE content = VALUES(content), created = VALUES(created), lastread = VALUES(lastread)',
$type, $cacheid, $content
);
}
function qa_db_cache_get($type, $cacheid)
/*
Retrieve the item ($type, $cacheid) from the database cache table
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$content=qa_db_read_one_value(qa_db_query_sub(
'SELECT content FROM ^cache WHERE type=$ AND cacheid=#',
'UPDATE ^cache SET lastread=NOW() WHERE type=$ AND cacheid=#',
$type, $cacheid
), true);
if (isset($content))
qa_db_query_sub(
'UPDATE ^cache SET lastread=NOW() WHERE type=$ AND cacheid=#',
$type, $cacheid
);
return $content;
}
);
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
return $content;
}
......@@ -20,60 +20,63 @@
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
header('Location: ../');
exit;
}
function qa_db_cookie_create($ipaddress)
/*
Create a new random cookie for $ipaddress and insert into database, returning it
*/
{
for ($attempt=0; $attempt<10; $attempt++) {
$cookieid=qa_db_random_bigint();
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
if (qa_db_cookie_exists($cookieid))
continue;
qa_db_query_sub(
'INSERT INTO ^cookies (cookieid, created, createip) '.
'VALUES (#, NOW(), $)',
$cookieid, @inet_pton($ipaddress)
);
/**
* Create a new random cookie for $ipaddress and insert into database, returning it
* @param $ipaddress
* @return null|string
*/
function qa_db_cookie_create($ipaddress)
{
for ($attempt = 0; $attempt < 10; $attempt++) {
$cookieid = qa_db_random_bigint();
return $cookieid;
}
if (qa_db_cookie_exists($cookieid))
continue;
return null;
}
function qa_db_cookie_written($cookieid, $ipaddress)
/*
Note in database that a write operation has been done by user identified by $cookieid and from $ipaddress
*/
{
qa_db_query_sub(
'UPDATE ^cookies SET written=NOW(), writeip=$ WHERE cookieid=#',
@inet_pton($ipaddress), $cookieid
'INSERT INTO ^cookies (cookieid, created, createip) ' .
'VALUES (#, NOW(), $)',
$cookieid, @inet_pton($ipaddress)
);
}
function qa_db_cookie_exists($cookieid)
/*
Return whether $cookieid exists in database
*/
{
return qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^cookies WHERE cookieid=#',
$cookieid
)) > 0;
return $cookieid;
}
/*
Omit PHP closing tag to help avoid accidental output
*/
return null;
}
/**
* Note in database that a write operation has been done by user identified by $cookieid and from $ipaddress
* @param $cookieid
* @param $ipaddress
*/
function qa_db_cookie_written($cookieid, $ipaddress)
{
qa_db_query_sub(
'UPDATE ^cookies SET written=NOW(), writeip=$ WHERE cookieid=#',
@inet_pton($ipaddress), $cookieid
);
}
/**
* Return whether $cookieid exists in database
* @param $cookieid
* @return bool
*/
function qa_db_cookie_exists($cookieid)
{
$cookie = qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^cookies WHERE cookieid=#',
$cookieid
));
return $cookie > 0;
}
......@@ -20,160 +20,169 @@
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
header('Location: ../');
exit;
}
function qa_db_event_create_for_entity($entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid, $timestamp=null)
/*
Add an event to the event streams for entity $entitytype with $entityid. The event of type $updatetype relates to
$lastpostid whose antecedent question is $questionid, and was caused by $lastuserid. Pass a unix $timestamp for the
event time or leave as null to use now. This will add the event both to the entity's shared stream, and the
individual user streams for any users following the entity not via its shared stream (See long comment in
qa-db-favorites.php). Also handles truncation.
*/
{
require_once QA_INCLUDE_DIR.'db/maxima.php';
require_once QA_INCLUDE_DIR.'app/updates.php';
$updatedsql=isset($timestamp) ? ('FROM_UNIXTIME('.qa_db_argument_to_mysql($timestamp, false).')') : 'NOW()';
// Enter it into the appropriate shared event stream for that entity
qa_db_query_sub(
'INSERT INTO ^sharedevents (entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) '.
'VALUES ($, #, #, #, $, $, '.$updatedsql.')',
$entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid
);
// If this is for a question entity, check the shared event stream doesn't have too many entries for that question
$questiontruncated=false;
if ($entitytype==QA_ENTITY_QUESTION) {
$truncate=qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^sharedevents WHERE entitytype=$ AND entityid=# AND questionid=# ORDER BY updated DESC LIMIT #,1',
$entitytype, $entityid, $questionid, QA_DB_MAX_EVENTS_PER_Q
), true);
if (isset($truncate)) {
qa_db_query_sub(
'DELETE FROM ^sharedevents WHERE entitytype=$ AND entityid=# AND questionid=# AND updated<=$',
$entitytype, $entityid, $questionid, $truncate
);
$questiontruncated=true;
}
}
// If we didn't truncate due to a specific question, truncate the shared event stream for its overall length
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
/**
* Add an event to the event streams for entity $entitytype with $entityid. The event of type $updatetype relates to
* $lastpostid whose antecedent question is $questionid, and was caused by $lastuserid. Pass a unix $timestamp for the
* event time or leave as null to use now. This will add the event both to the entity's shared stream, and the
* individual user streams for any users following the entity not via its shared stream (See long comment in
* qa-db-favorites.php). Also handles truncation.
* @param $entitytype
* @param $entityid
* @param $questionid
* @param $lastpostid
* @param $updatetype
* @param $lastuserid
* @param $timestamp
*/
function qa_db_event_create_for_entity($entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid, $timestamp = null)
{
require_once QA_INCLUDE_DIR . 'db/maxima.php';
require_once QA_INCLUDE_DIR . 'app/updates.php';
$updatedsql = isset($timestamp) ? ('FROM_UNIXTIME(' . qa_db_argument_to_mysql($timestamp, false) . ')') : 'NOW()';
// Enter it into the appropriate shared event stream for that entity
qa_db_query_sub(
'INSERT INTO ^sharedevents (entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) ' .
'VALUES ($, #, #, #, $, $, ' . $updatedsql . ')',
$entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid
);
// If this is for a question entity, check the shared event stream doesn't have too many entries for that question
$questiontruncated = false;
if ($entitytype == QA_ENTITY_QUESTION) {
$truncate = qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^sharedevents WHERE entitytype=$ AND entityid=# AND questionid=# ORDER BY updated DESC LIMIT #,1',
$entitytype, $entityid, $questionid, QA_DB_MAX_EVENTS_PER_Q
), true);
if (!$questiontruncated) {
$truncate=qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^sharedevents WHERE entitytype=$ AND entityid=$ ORDER BY updated DESC LIMIT #,1',
$entitytype, $entityid, (int)qa_opt('max_store_user_updates')
), true);
if (isset($truncate)) {
qa_db_query_sub(
'DELETE FROM ^sharedevents WHERE entitytype=$ AND entityid=# AND questionid=# AND updated<=$',
$entitytype, $entityid, $questionid, $truncate
);
if (isset($truncate))
qa_db_query_sub(
'DELETE FROM ^sharedevents WHERE entitytype=$ AND entityid=$ AND updated<=$',
$entitytype, $entityid, $truncate
);
$questiontruncated = true;
}
}
// See if we can identify a user who has favorited this entity, but is not using its shared event stream
// If we didn't truncate due to a specific question, truncate the shared event stream for its overall length
$randomuserid=qa_db_read_one_value(qa_db_query_sub(
'SELECT userid FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0 ORDER BY RAND() LIMIT 1',
$entitytype, $entityid
if (!$questiontruncated) {
$truncate = qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^sharedevents WHERE entitytype=$ AND entityid=$ ORDER BY updated DESC LIMIT #,1',
$entitytype, $entityid, (int)qa_opt('max_store_user_updates')
), true);
if (isset($randomuserid)) {
// If one was found, this means we have one or more individual event streams, so update them all
if (isset($truncate))
qa_db_query_sub(
'INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) '.
'SELECT userid, $, #, #, #, $, $, '.$updatedsql.' FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0',
$entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid, $entitytype, $entityid
'DELETE FROM ^sharedevents WHERE entitytype=$ AND entityid=$ AND updated<=$',
$entitytype, $entityid, $truncate
);
// Now truncate the random individual event stream that was found earlier
// (in theory we should truncate them all, but truncation is just a 'housekeeping' activity, so it's not necessary)
qa_db_user_events_truncate($randomuserid, $questionid);
}
}
// See if we can identify a user who has favorited this entity, but is not using its shared event stream
function qa_db_event_create_not_entity($userid, $questionid, $lastpostid, $updatetype, $lastuserid, $timestamp=null)
/*
Add an event to the event stream for $userid which is not related to an entity they are following (but rather a
notification which is relevant for them, e.g. if someone answers their question). The event of type $updatetype
relates to $lastpostid whose antecedent question is $questionid, and was caused by $lastuserid. Pass a unix
$timestamp for the event time or leave as null to use now. Also handles truncation of event streams.
*/
{
require_once QA_INCLUDE_DIR.'app/updates.php';
$randomuserid = qa_db_read_one_value(qa_db_query_sub(
'SELECT userid FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0 ORDER BY RAND() LIMIT 1',
$entitytype, $entityid
), true);
if (isset($randomuserid)) {
$updatedsql=isset($timestamp) ? ('FROM_UNIXTIME('.qa_db_argument_to_mysql($timestamp, false).')') : 'NOW()';
// If one was found, this means we have one or more individual event streams, so update them all
qa_db_query_sub(
"INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) ".
"VALUES ($, $, 0, #, #, $, $, ".$updatedsql.")",
$userid, QA_ENTITY_NONE, $questionid, $lastpostid, $updatetype, $lastuserid
'INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) ' .
'SELECT userid, $, #, #, #, $, $, ' . $updatedsql . ' FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0',
$entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid, $entitytype, $entityid
);
qa_db_user_events_truncate($userid, $questionid);
}
function qa_db_user_events_truncate($userid, $questionid=null)
/*
Trim the number of events in the event stream for $userid. If an event was just added for a particular question,
pass the question's id in $questionid (to help focus the truncation).
*/
{
// First try truncating based on there being too many events for this question
$questiontruncated=false;
// Now truncate the random individual event stream that was found earlier
// (in theory we should truncate them all, but truncation is just a 'housekeeping' activity, so it's not necessary)
if (isset($questionid)) {
$truncate=qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^userevents WHERE userid=$ AND questionid=# ORDER BY updated DESC LIMIT #,1',
$userid, $questionid, QA_DB_MAX_EVENTS_PER_Q
), true);
qa_db_user_events_truncate($randomuserid, $questionid);
}
}
/**
* Add an event to the event stream for $userid which is not related to an entity they are following (but rather a
* notification which is relevant for them, e.g. if someone answers their question). The event of type $updatetype
* relates to $lastpostid whose antecedent question is $questionid, and was caused by $lastuserid. Pass a unix
* $timestamp for the event time or leave as null to use now. Also handles truncation of event streams.
* @param $userid
* @param $questionid
* @param $lastpostid
* @param $updatetype
* @param $lastuserid
* @param $timestamp
*/
function qa_db_event_create_not_entity($userid, $questionid, $lastpostid, $updatetype, $lastuserid, $timestamp = null)
{
require_once QA_INCLUDE_DIR . 'app/updates.php';
$updatedsql = isset($timestamp) ? ('FROM_UNIXTIME(' . qa_db_argument_to_mysql($timestamp, false) . ')') : 'NOW()';
qa_db_query_sub(
"INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) " .
"VALUES ($, $, 0, #, #, $, $, " . $updatedsql . ")",
$userid, QA_ENTITY_NONE, $questionid, $lastpostid, $updatetype, $lastuserid
);
qa_db_user_events_truncate($userid, $questionid);
}
/**
* Trim the number of events in the event stream for $userid. If an event was just added for a particular question,
* pass the question's id in $questionid (to help focus the truncation).
* @param $userid
* @param $questionid
*/
function qa_db_user_events_truncate($userid, $questionid = null)
{
// First try truncating based on there being too many events for this question
$questiontruncated = false;
if (isset($questionid)) {
$truncate = qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^userevents WHERE userid=$ AND questionid=# ORDER BY updated DESC LIMIT #,1',
$userid, $questionid, QA_DB_MAX_EVENTS_PER_Q
), true);
if (isset($truncate)) {
qa_db_query_sub(
'DELETE FROM ^userevents WHERE userid=$ AND questionid=# AND updated<=$',
$userid, $questionid, $truncate
);
if (isset($truncate)) {
qa_db_query_sub(
'DELETE FROM ^userevents WHERE userid=$ AND questionid=# AND updated<=$',
$userid, $questionid, $truncate
);
$questiontruncated=true;
}
$questiontruncated = true;
}
}
// If that didn't happen, try truncating the stream in general based on its total length
// If that didn't happen, try truncating the stream in general based on its total length
if (!$questiontruncated) {
$truncate=qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^userevents WHERE userid=$ ORDER BY updated DESC LIMIT #,1',
$userid, (int)qa_opt('max_store_user_updates')
), true);
if (!$questiontruncated) {
$truncate = qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^userevents WHERE userid=$ ORDER BY updated DESC LIMIT #,1',
$userid, (int)qa_opt('max_store_user_updates')
), true);
if (isset($truncate))
qa_db_query_sub(
'DELETE FROM ^userevents WHERE userid=$ AND updated<=$',
$userid, $truncate
);
}
if (isset($truncate))
qa_db_query_sub(
'DELETE FROM ^userevents WHERE userid=$ AND updated<=$',
$userid, $truncate
);
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
}
......@@ -20,10 +20,10 @@
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
header('Location: ../');
exit;
}
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
/*
......@@ -103,103 +103,104 @@
*/
function qa_db_favorite_create($userid, $entitytype, $entityid)
/*
Add the entity $entitytype with $entityid to the favorites list of $userid. Handles switching streams across from
per-user to per-entity based on how many other users have favorited the entity (see long explanation above). If
appropriate, it also adds recent events from that entity to the user's event stream.
*/
{
$threshold=qa_opt('max_copy_user_updates'); // if this many users subscribe to it, create a shared stream
/**
* Add the entity $entitytype with $entityid to the favorites list of $userid. Handles switching streams across from
* per-user to per-entity based on how many other users have favorited the entity (see long explanation above). If
* appropriate, it also adds recent events from that entity to the user's event stream.
* @param $userid
* @param $entitytype
* @param $entityid
*/
function qa_db_favorite_create($userid, $entitytype, $entityid)
{
$threshold = qa_opt('max_copy_user_updates'); // if this many users subscribe to it, create a shared stream
// Add in the favorite for this user, unshared events at first (will be switched later if appropriate)
// Add in the favorite for this user, unshared events at first (will be switched later if appropriate)
qa_db_query_sub(
'INSERT IGNORE INTO ^userfavorites (userid, entitytype, entityid, nouserevents) VALUES ($, $, #, 0)',
$userid, $entitytype, $entityid
);
qa_db_query_sub(
'INSERT IGNORE INTO ^userfavorites (userid, entitytype, entityid, nouserevents) VALUES ($, $, #, 0)',
$userid, $entitytype, $entityid
);
// See whether this entity already has another favoriter who uses its shared event stream
// See whether this entity already has another favoriter who uses its shared event stream
$useshared=qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents>0 LIMIT 1',
$entitytype, $entityid
));
$useshared = qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents>0 LIMIT 1',
$entitytype, $entityid
));
// If not, check whether it's time to switch it over to a shared stream
// If not, check whether it's time to switch it over to a shared stream
if (!$useshared) {
$favoriters=qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# LIMIT #',
$entitytype, $entityid, $threshold
));
$useshared=($favoriters >= $threshold);
}
// If we're going to use the shared stream...
if ($useshared) {
// ... for all the people for whom we're switching this to a shared stream, find the highest number of other shared streams they have
$maxshared=qa_db_read_one_value(qa_db_query_sub(
'SELECT MAX(c) FROM (SELECT COUNT(*) AS c FROM ^userfavorites AS shared JOIN ^userfavorites AS unshared '.
'WHERE shared.userid=unshared.userid AND shared.nouserevents>0 AND unshared.entitytype=$ AND unshared.entityid=# AND unshared.nouserevents=0 GROUP BY shared.userid) y',
$entitytype, $entityid
));
if (!$useshared) {
$favoriters = qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# LIMIT #',
$entitytype, $entityid, $threshold
));
// ... if this number is greater than our current 'max_copy_user_updates' threshold, increase that threshold (see long comment above)
$useshared = ($favoriters >= $threshold);
}
if (($maxshared+1)>$threshold)
qa_opt('max_copy_user_updates', $maxshared+1);
// If we're going to use the shared stream...
// ... now switch all unshared favoriters (including this new one) over to be shared
if ($useshared) {
qa_db_query_sub(
'UPDATE ^userfavorites SET nouserevents=1 WHERE entitytype=$ AND entityid=# AND nouserevents=0',
$entitytype, $entityid
);
// ... for all the people for whom we're switching this to a shared stream, find the highest number of other shared streams they have
// Otherwise if we're going to record this in user-specific streams ...
$maxshared = qa_db_read_one_value(qa_db_query_sub(
'SELECT MAX(c) FROM (SELECT COUNT(*) AS c FROM ^userfavorites AS shared JOIN ^userfavorites AS unshared ' .
'WHERE shared.userid=unshared.userid AND shared.nouserevents>0 AND unshared.entitytype=$ AND unshared.entityid=# AND unshared.nouserevents=0 GROUP BY shared.userid) y',
$entitytype, $entityid
));
} else {
require_once QA_INCLUDE_DIR.'db/events.php';
// ... if this number is greater than our current 'max_copy_user_updates' threshold, increase that threshold (see long comment above)
// ... copy across recent events from the shared stream
if (($maxshared + 1) > $threshold)
qa_opt('max_copy_user_updates', $maxshared + 1);
qa_db_query_sub(
'INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) '.
'SELECT #, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated FROM '.
'^sharedevents WHERE entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid
);
// ... now switch all unshared favoriters (including this new one) over to be shared
// ... and truncate the user's stream as appropriate
qa_db_query_sub(
'UPDATE ^userfavorites SET nouserevents=1 WHERE entitytype=$ AND entityid=# AND nouserevents=0',
$entitytype, $entityid
);
qa_db_user_events_truncate($userid);
}
}
} else {
// Otherwise if we're going to record this in user-specific streams ...
require_once QA_INCLUDE_DIR . 'db/events.php';
function qa_db_favorite_delete($userid, $entitytype, $entityid)
/*
Delete the entity $entitytype with $entityid from the favorites list of $userid, removing any corresponding events
from the user's stream.
*/
{
qa_db_query_sub(
'DELETE FROM ^userfavorites WHERE userid=$ AND entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid
);
// ... copy across recent events from the shared stream
qa_db_query_sub(
'DELETE FROM ^userevents WHERE userid=$ AND entitytype=$ AND entityid=#',
'INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) ' .
'SELECT #, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated FROM ' .
'^sharedevents WHERE entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid
);
}
// ... and truncate the user's stream as appropriate
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
qa_db_user_events_truncate($userid);
}
}
/**
* Delete the entity $entitytype with $entityid from the favorites list of $userid, removing any corresponding events
* from the user's stream.
* @param $userid
* @param $entitytype
* @param $entityid
*/
function qa_db_favorite_delete($userid, $entitytype, $entityid)
{
qa_db_query_sub(
'DELETE FROM ^userfavorites WHERE userid=$ AND entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid
);
qa_db_query_sub(
'DELETE FROM ^userevents WHERE userid=$ AND entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid
);
}
......@@ -20,57 +20,56 @@
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
header('Location: ../');
exit;
}
function qa_db_hotness_update($firstpostid, $lastpostid=null, $viewincrement=false)
/*
Recalculate the hotness in the database for posts $firstpostid to $lastpostid (if specified)
If $viewincrement is true, also increment the views counter for the post (if different IP from last view),
and include that in the hotness calculation
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if (qa_should_update_counts()) {
if (!isset($lastpostid))
$lastpostid=$firstpostid;
$query= "UPDATE ^posts AS x, (SELECT parents.postid, parents.created AS qcreated, COALESCE(MAX(children.created), parents.created) as acreated, COUNT(children.postid) AS acount, parents.netvotes, parents.views FROM ^posts AS parents LEFT JOIN ^posts AS children ON parents.postid=children.parentid AND children.type='A' WHERE parents.postid>=# AND parents.postid<=# AND LEFT(parents.type, 1)='Q' GROUP BY postid) AS a SET x.hotness=(".
'((TO_DAYS(a.qcreated)-734138)*86400.0+TIME_TO_SEC(a.qcreated))*# + '. // zero-point is Jan 1, 2010
'((TO_DAYS(a.acreated)-734138)*86400.0+TIME_TO_SEC(a.acreated))*# + '.
'(a.acount+0.0)*# + '.
'(a.netvotes+0.0)*# + '.
'(a.views+0.0+#)*#'.
')'.($viewincrement ? ', x.views=x.views+1, x.lastviewip=$' : '').
' WHERE x.postid=a.postid'.($viewincrement ? ' AND (x.lastviewip IS NULL OR x.lastviewip!=$)' : '');
// Additional multiples based on empirical analysis of activity on Q2A meta site to give approx equal influence for all factors
$arguments=array(
$firstpostid,
$lastpostid,
qa_opt('hot_weight_q_age'),
qa_opt('hot_weight_a_age'),
qa_opt('hot_weight_answers')*160000,
qa_opt('hot_weight_votes')*160000,
$viewincrement ? 1 : 0,
qa_opt('hot_weight_views')*4000,
);
if ($viewincrement) {
$ipbin = @inet_pton(qa_remote_ip_address());
array_push($arguments, $ipbin, $ipbin);
}
qa_db_query_raw(qa_db_apply_sub($query, $arguments));
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
/**
* Recalculate the hotness in the database for posts $firstpostid to $lastpostid (if specified)
* If $viewincrement is true, also increment the views counter for the post (if different IP from last view),
* and include that in the hotness calculation
* @param $firstpostid
* @param $lastpostid
* @param bool $viewincrement
* @return mixed
*/
function qa_db_hotness_update($firstpostid, $lastpostid=null, $viewincrement=false)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if (qa_should_update_counts()) {
if (!isset($lastpostid))
$lastpostid = $firstpostid;
$query = "UPDATE ^posts AS x, (SELECT parents.postid, parents.created AS qcreated, COALESCE(MAX(children.created), parents.created) as acreated, COUNT(children.postid) AS acount, parents.netvotes, parents.views FROM ^posts AS parents LEFT JOIN ^posts AS children ON parents.postid=children.parentid AND children.type='A' WHERE parents.postid>=# AND parents.postid<=# AND LEFT(parents.type, 1)='Q' GROUP BY postid) AS a SET x.hotness=(" .
'((TO_DAYS(a.qcreated)-734138)*86400.0+TIME_TO_SEC(a.qcreated))*# + ' . // zero-point is Jan 1, 2010
'((TO_DAYS(a.acreated)-734138)*86400.0+TIME_TO_SEC(a.acreated))*# + ' .
'(a.acount+0.0)*# + ' .
'(a.netvotes+0.0)*# + ' .
'(a.views+0.0+#)*#' .
')' . ($viewincrement ? ', x.views=x.views+1, x.lastviewip=$' : '') .
' WHERE x.postid=a.postid' . ($viewincrement ? ' AND (x.lastviewip IS NULL OR x.lastviewip!=$)' : '');
// Additional multiples based on empirical analysis of activity on Q2A meta site to give approx equal influence for all factors
$arguments = array(
$firstpostid,
$lastpostid,
qa_opt('hot_weight_q_age'),
qa_opt('hot_weight_a_age'),
qa_opt('hot_weight_answers') * 160000,
qa_opt('hot_weight_votes') * 160000,
$viewincrement ? 1 : 0,
qa_opt('hot_weight_views') * 4000,
);
if ($viewincrement) {
$ipbin = @inet_pton(qa_remote_ip_address());
array_push($arguments, $ipbin, $ipbin);
}
}
/*
Omit PHP closing tag to help avoid accidental output
*/
qa_db_query_raw(qa_db_apply_sub($query, $arguments));
}
}
......@@ -20,68 +20,75 @@
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
header('Location: ../');
exit;
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
/**
* Get rate limit information for $action from the database for user $userid and/or IP address $ip, if they're set.
* Return as an array with the limit type in the key, and a labelled array of the period and count.
* @param $userid
* @param $ip
* @param $action
* @return array
*/
function qa_db_limits_get($userid, $ip, $action)
{
$selects = array();
$arguments = array();
if (isset($userid)) {
$selects[] = "(SELECT 'user' AS limitkey, period, count FROM ^userlimits WHERE userid=$ AND action=$)";
$arguments[] = $userid;
$arguments[] = $action;
}
function qa_db_limits_get($userid, $ip, $action)
/*
Get rate limit information for $action from the database for user $userid and/or IP address $ip, if they're set.
Return as an array with the limit type in the key, and a labelled array of the period and count.
*/
{
$selects=array();
$arguments=array();
if (isset($userid)) {
$selects[]="(SELECT 'user' AS limitkey, period, count FROM ^userlimits WHERE userid=$ AND action=$)";
$arguments[]=$userid;
$arguments[]=$action;
}
if (isset($ip)) {
$selects[]="(SELECT 'ip' AS limitkey, period, count FROM ^iplimits WHERE ip=$ AND action=$)";
$arguments[]=@inet_pton($ip);
$arguments[]=$action;
}
if (count($selects)) {
$query=qa_db_apply_sub(implode(' UNION ALL ', $selects), $arguments);
return qa_db_read_all_assoc(qa_db_query_raw($query), 'limitkey');
} else
return array();
}
function qa_db_limits_user_add($userid, $action, $period, $count)
/*
Increment the database rate limit count for user $userid and $action by $count within $period
*/
{
qa_db_query_sub(
'INSERT INTO ^userlimits (userid, action, period, count) VALUES ($, $, #, #) '.
'ON DUPLICATE KEY UPDATE count=IF(period=#, count+#, #), period=#',
$userid, $action, $period, $count, $period, $count, $count, $period
);
if (isset($ip)) {
$selects[] = "(SELECT 'ip' AS limitkey, period, count FROM ^iplimits WHERE ip=$ AND action=$)";
$arguments[] = @inet_pton($ip);
$arguments[] = $action;
}
function qa_db_limits_ip_add($ip, $action, $period, $count)
/*
Increment the database rate limit count for IP address $ip and $action by $count within $period
*/
{
qa_db_query_sub(
'INSERT INTO ^iplimits (ip, action, period, count) VALUES ($, $, #, #) '.
'ON DUPLICATE KEY UPDATE count=IF(period=#, count+#, #), period=#',
@inet_pton($ip), $action, $period, $count, $period, $count, $count, $period
);
}
/*
Omit PHP closing tag to help avoid accidental output
*/
if (count($selects)) {
$query = qa_db_apply_sub(implode(' UNION ALL ', $selects), $arguments);
return qa_db_read_all_assoc(qa_db_query_raw($query), 'limitkey');
} else
return array();
}
/**
* Increment the database rate limit count for user $userid and $action by $count within $period
* @param $userid
* @param $action
* @param $period
* @param $count
*/
function qa_db_limits_user_add($userid, $action, $period, $count)
{
qa_db_query_sub(
'INSERT INTO ^userlimits (userid, action, period, count) VALUES ($, $, #, #) ' .
'ON DUPLICATE KEY UPDATE count=IF(period=#, count+#, #), period=#',
$userid, $action, $period, $count, $period, $count, $count, $period
);
}
/**
* Increment the database rate limit count for IP address $ip and $action by $count within $period
* @param $ip
* @param $action
* @param $period
* @param $count
*/
function qa_db_limits_ip_add($ip, $action, $period, $count)
{
qa_db_query_sub(
'INSERT INTO ^iplimits (ip, action, period, count) VALUES ($, $, #, #) ' .
'ON DUPLICATE KEY UPDATE count=IF(period=#, count+#, #), period=#',
@inet_pton($ip), $action, $period, $count, $period, $count, $count, $period
);
}
......@@ -20,54 +20,49 @@
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
header('Location: ../');
exit;
}
// Maximum column sizes - any of these can be defined in qa-config.php to override the defaults below,
// but you need to do so before creating the database, otherwise it's too late.
@define('QA_DB_MAX_EMAIL_LENGTH', 80);
@define('QA_DB_MAX_HANDLE_LENGTH', 20);
@define('QA_DB_MAX_TITLE_LENGTH', 800);
@define('QA_DB_MAX_CONTENT_LENGTH', 12000);
@define('QA_DB_MAX_FORMAT_LENGTH', 20);
@define('QA_DB_MAX_TAGS_LENGTH', 800);
@define('QA_DB_MAX_NAME_LENGTH', 40);
@define('QA_DB_MAX_WORD_LENGTH', 80);
@define('QA_DB_MAX_CAT_PAGE_TITLE_LENGTH', 80);
@define('QA_DB_MAX_CAT_PAGE_TAGS_LENGTH', 200);
@define('QA_DB_MAX_CAT_CONTENT_LENGTH', 800);
@define('QA_DB_MAX_WIDGET_TAGS_LENGTH', 800);
@define('QA_DB_MAX_WIDGET_TITLE_LENGTH', 80);
@define('QA_DB_MAX_OPTION_TITLE_LENGTH', 40);
@define('QA_DB_MAX_PROFILE_TITLE_LENGTH', 40);
@define('QA_DB_MAX_PROFILE_CONTENT_LENGTH', 8000);
@define('QA_DB_MAX_CACHE_AGE', 86400);
@define('QA_DB_MAX_BLOB_FILE_NAME_LENGTH', 255);
@define('QA_DB_MAX_META_TITLE_LENGTH', 40);
@define('QA_DB_MAX_META_CONTENT_LENGTH', 8000);
// How many records to retrieve for different circumstances. In many cases we retrieve more records than we
// end up needing to display once we know the value of an option. Wasteful, but allows one query per page.
@define('QA_DB_RETRIEVE_QS_AS', 50);
@define('QA_DB_RETRIEVE_TAGS', 200);
@define('QA_DB_RETRIEVE_USERS', 200);
@define('QA_DB_RETRIEVE_ASK_TAG_QS', 500);
@define('QA_DB_RETRIEVE_COMPLETE_TAGS', 1000);
@define('QA_DB_RETRIEVE_MESSAGES', 20);
// Keep event streams trimmed - not worth storing too many events per question because we only display the
// most recent event for each question, that has not been invalidated due to hiding/unselection/etc...
@define('QA_DB_MAX_EVENTS_PER_Q', 5);
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
// Maximum column sizes - any of these can be defined in qa-config.php to override the defaults below,
// but you need to do so before creating the database, otherwise it's too late.
@define('QA_DB_MAX_EMAIL_LENGTH', 80);
@define('QA_DB_MAX_HANDLE_LENGTH', 20);
@define('QA_DB_MAX_TITLE_LENGTH', 800);
@define('QA_DB_MAX_CONTENT_LENGTH', 12000);
@define('QA_DB_MAX_FORMAT_LENGTH', 20);
@define('QA_DB_MAX_TAGS_LENGTH', 800);
@define('QA_DB_MAX_NAME_LENGTH', 40);
@define('QA_DB_MAX_WORD_LENGTH', 80);
@define('QA_DB_MAX_CAT_PAGE_TITLE_LENGTH', 80);
@define('QA_DB_MAX_CAT_PAGE_TAGS_LENGTH', 200);
@define('QA_DB_MAX_CAT_CONTENT_LENGTH', 800);
@define('QA_DB_MAX_WIDGET_TAGS_LENGTH', 800);
@define('QA_DB_MAX_WIDGET_TITLE_LENGTH', 80);
@define('QA_DB_MAX_OPTION_TITLE_LENGTH', 40);
@define('QA_DB_MAX_PROFILE_TITLE_LENGTH', 40);
@define('QA_DB_MAX_PROFILE_CONTENT_LENGTH', 8000);
@define('QA_DB_MAX_CACHE_AGE', 86400);
@define('QA_DB_MAX_BLOB_FILE_NAME_LENGTH', 255);
@define('QA_DB_MAX_META_TITLE_LENGTH', 40);
@define('QA_DB_MAX_META_CONTENT_LENGTH', 8000);
// How many records to retrieve for different circumstances. In many cases we retrieve more records than we
// end up needing to display once we know the value of an option. Wasteful, but allows one query per page.
@define('QA_DB_RETRIEVE_QS_AS', 50);
@define('QA_DB_RETRIEVE_TAGS', 200);
@define('QA_DB_RETRIEVE_USERS', 200);
@define('QA_DB_RETRIEVE_ASK_TAG_QS', 500);
@define('QA_DB_RETRIEVE_COMPLETE_TAGS', 1000);
@define('QA_DB_RETRIEVE_MESSAGES', 20);
// Keep event streams trimmed - not worth storing too many events per question because we only display the
// most recent event for each question, that has not been invalidated due to hiding/unselection/etc...
@define('QA_DB_MAX_EVENTS_PER_Q', 5);
......@@ -20,69 +20,76 @@
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
header('Location: ../');
exit;
}
function qa_db_message_create($fromuserid, $touserid, $content, $format, $public=false)
/*
Record a message sent from $fromuserid to $touserid with $content in $format in the database. $public sets whether
public (on wall) or private. Return the messageid of the row created.
*/
{
qa_db_query_sub(
'INSERT INTO ^messages (type, fromuserid, touserid, content, format, created) VALUES ($, #, #, $, $, NOW())',
$public ? 'PUBLIC' : 'PRIVATE', $fromuserid, $touserid, $content, $format
);
return qa_db_last_insert_id();
}
function qa_db_message_user_hide($messageid, $box)
/*
Hide the message with $messageid, in $box (inbox|outbox) from the user.
*/
{
$field = ($box === 'inbox' ? 'tohidden' : 'fromhidden');
qa_db_query_sub(
"UPDATE ^messages SET $field=1 WHERE messageid=#",
$messageid
);
}
function qa_db_message_delete($messageid, $public=true)
/*
Delete the message with $messageid from the database.
*/
{
// delete PM only if both sender and receiver have hidden it
$clause = $public ? '' : ' AND fromhidden=1 AND tohidden=1';
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
/**
* Record a message sent from $fromuserid to $touserid with $content in $format in the database. $public sets whether
* public (on wall) or private. Return the messageid of the row created.
* @param $fromuserid
* @param $touserid
* @param $content
* @param $format
* @param bool $public
* @return mixed
*/
function qa_db_message_create($fromuserid, $touserid, $content, $format, $public = false)
{
qa_db_query_sub(
'INSERT INTO ^messages (type, fromuserid, touserid, content, format, created) VALUES ($, #, #, $, $, NOW())',
$public ? 'PUBLIC' : 'PRIVATE', $fromuserid, $touserid, $content, $format
);
return qa_db_last_insert_id();
}
/**
* Hide the message with $messageid, in $box (inbox|outbox) from the user.
* @param $messageid
* @param $box
*/
function qa_db_message_user_hide($messageid, $box)
{
$field = ($box === 'inbox' ? 'tohidden' : 'fromhidden');
qa_db_query_sub(
"UPDATE ^messages SET $field=1 WHERE messageid=#",
$messageid
);
}
/**
* Delete the message with $messageid from the database.
* @param $messageid
* @param bool $public
*/
function qa_db_message_delete($messageid, $public = true)
{
// delete PM only if both sender and receiver have hidden it
$clause = $public ? '' : ' AND fromhidden=1 AND tohidden=1';
qa_db_query_sub(
'DELETE FROM ^messages WHERE messageid=#' . $clause,
$messageid
);
}
/**
* Recalculate the cached count of wall posts for user $userid in the database
* @param $userid
*/
function qa_db_user_recount_posts($userid)
{
if (qa_should_update_counts()) {
qa_db_query_sub(
'DELETE FROM ^messages WHERE messageid=#'.$clause,
$messageid
"UPDATE ^users AS x, (SELECT COUNT(*) AS wallposts FROM ^messages WHERE touserid=# AND type='PUBLIC') AS a SET x.wallposts=a.wallposts WHERE x.userid=#",
$userid, $userid
);
}
function qa_db_user_recount_posts($userid)
/*
Recalculate the cached count of wall posts for user $userid in the database
*/
{
if (qa_should_update_counts())
qa_db_query_sub(
"UPDATE ^users AS x, (SELECT COUNT(*) AS wallposts FROM ^messages WHERE touserid=# AND type='PUBLIC') AS a SET x.wallposts=a.wallposts WHERE x.userid=#",
$userid, $userid
);
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
}
......@@ -20,179 +20,223 @@
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
header('Location: ../');
exit;
}
function qa_db_usermeta_set($userid, $key, $value)
/*
Set the metadata for user $userid with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
*/
{
qa_db_meta_set('usermetas', 'userid', $userid, $key, $value);
}
function qa_db_usermeta_clear($userid, $key)
/*
Clear the metadata for user $userid with $key ($key can also be an array of keys)
*/
{
qa_db_meta_clear('usermetas', 'userid', $userid, $key);
}
function qa_db_usermeta_get($userid, $key)
/*
Return the metadata value for user $userid with $key ($key can also be an array of keys in which case this
returns an array of metadata key => value).
*/
{
return qa_db_meta_get('usermetas', 'userid', $userid, $key);
}
function qa_db_postmeta_set($postid, $key, $value)
/*
Set the metadata for post $postid with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
*/
{
qa_db_meta_set('postmetas', 'postid', $postid, $key, $value);
}
function qa_db_postmeta_clear($postid, $key)
/*
Clear the metadata for post $postid with $key ($key can also be an array of keys)
*/
{
qa_db_meta_clear('postmetas', 'postid', $postid, $key);
}
function qa_db_postmeta_get($postid, $key)
/*
Return the metadata value for post $postid with $key ($key can also be an array of keys in which case this
returns an array of metadata key => value).
*/
{
return qa_db_meta_get('postmetas', 'postid', $postid, $key);
}
function qa_db_categorymeta_set($categoryid, $key, $value)
/*
Set the metadata for category $categoryid with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
*/
{
qa_db_meta_set('categorymetas', 'categoryid', $categoryid, $key, $value);
}
function qa_db_categorymeta_clear($categoryid, $key)
/*
Clear the metadata for category $categoryid with $key ($key can also be an array of keys)
*/
{
qa_db_meta_clear('categorymetas', 'categoryid', $categoryid, $key);
}
function qa_db_categorymeta_get($categoryid, $key)
/*
Return the metadata value for category $categoryid with $key ($key can also be an array of keys in which
case this returns an array of metadata key => value).
*/
{
return qa_db_meta_get('categorymetas', 'categoryid', $categoryid, $key);
}
function qa_db_tagmeta_set($tag, $key, $value)
/*
Set the metadata for tag $tag with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
*/
{
qa_db_meta_set('tagmetas', 'tag', $tag, $key, $value);
}
function qa_db_tagmeta_clear($tag, $key)
/*
Clear the metadata for tag $tag with $key ($key can also be an array of keys)
*/
{
qa_db_meta_clear('tagmetas', 'tag', $tag, $key);
}
function qa_db_tagmeta_get($tag, $key)
/*
Return the metadata value for tag $tag with $key ($key can also be an array of keys in which case this
returns an array of metadata key => value).
*/
{
return qa_db_meta_get('tagmetas', 'tag', $tag, $key);
}
function qa_db_meta_set($metatable, $idcolumn, $idvalue, $title, $content)
/*
Internal general function to set metadata
*/
{
qa_db_query_sub(
'INSERT INTO ^' . $metatable . ' (' . $idcolumn . ', title, content) VALUES ($, $, $) ' .
'ON DUPLICATE KEY UPDATE content = VALUES(content)',
$idvalue, $title, $content
);
}
function qa_db_meta_clear($metatable, $idcolumn, $idvalue, $title)
/*
Internal general function to clear metadata
*/
{
if (is_array($title)) {
if (count($title))
qa_db_query_sub(
'DELETE FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title IN ($)',
$idvalue, $title
);
} else
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
/**
* Set the metadata for user $userid with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
* @param $userid
* @param $key
* @param $value
*/
function qa_db_usermeta_set($userid, $key, $value)
{
qa_db_meta_set('usermetas', 'userid', $userid, $key, $value);
}
/**
* Clear the metadata for user $userid with $key ($key can also be an array of keys)
* @param $userid
* @param $key
*/
function qa_db_usermeta_clear($userid, $key)
{
qa_db_meta_clear('usermetas', 'userid', $userid, $key);
}
/**
* Return the metadata value for user $userid with $key ($key can also be an array of keys in which case this
* returns an array of metadata key => value).
* @param $userid
* @param $key
* @return array|mixed|null
*/
function qa_db_usermeta_get($userid, $key)
{
return qa_db_meta_get('usermetas', 'userid', $userid, $key);
}
/**
* Set the metadata for post $postid with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
* @param $postid
* @param $key
* @param $value
*/
function qa_db_postmeta_set($postid, $key, $value)
{
qa_db_meta_set('postmetas', 'postid', $postid, $key, $value);
}
/**
* Clear the metadata for post $postid with $key ($key can also be an array of keys)
* @param $postid
* @param $key
*/
function qa_db_postmeta_clear($postid, $key)
{
qa_db_meta_clear('postmetas', 'postid', $postid, $key);
}
/**
* Return the metadata value for post $postid with $key ($key can also be an array of keys in which case this
* returns an array of metadata key => value).
* @param $postid
* @param $key
* @return array|mixed|null
*/
function qa_db_postmeta_get($postid, $key)
{
return qa_db_meta_get('postmetas', 'postid', $postid, $key);
}
/**
* Set the metadata for category $categoryid with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
* @param $categoryid
* @param $key
* @param $value
*/
function qa_db_categorymeta_set($categoryid, $key, $value)
{
qa_db_meta_set('categorymetas', 'categoryid', $categoryid, $key, $value);
}
/**
* Clear the metadata for category $categoryid with $key ($key can also be an array of keys)
* @param $categoryid
* @param $key
*/
function qa_db_categorymeta_clear($categoryid, $key)
{
qa_db_meta_clear('categorymetas', 'categoryid', $categoryid, $key);
}
/**
* Return the metadata value for category $categoryid with $key ($key can also be an array of keys in which
* case this returns an array of metadata key => value).
* @param $categoryid
* @param $key
* @return array|mixed|null
*/
function qa_db_categorymeta_get($categoryid, $key)
{
return qa_db_meta_get('categorymetas', 'categoryid', $categoryid, $key);
}
/**
* Set the metadata for tag $tag with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
* @param $tag
* @param $key
* @param $value
*/
function qa_db_tagmeta_set($tag, $key, $value)
{
qa_db_meta_set('tagmetas', 'tag', $tag, $key, $value);
}
/**
* Clear the metadata for tag $tag with $key ($key can also be an array of keys)
* @param $tag
* @param $key
*/
function qa_db_tagmeta_clear($tag, $key)
{
qa_db_meta_clear('tagmetas', 'tag', $tag, $key);
}
/**
* Return the metadata value for tag $tag with $key ($key can also be an array of keys in which case this
* returns an array of metadata key => value).
* @param $tag
* @param $key
* @return array|mixed|null
*/
function qa_db_tagmeta_get($tag, $key)
{
return qa_db_meta_get('tagmetas', 'tag', $tag, $key);
}
/**
* Internal general function to set metadata
* @param $metatable
* @param $idcolumn
* @param $idvalue
* @param $title
* @param $content
*/
function qa_db_meta_set($metatable, $idcolumn, $idvalue, $title, $content)
{
qa_db_query_sub(
'INSERT INTO ^' . $metatable . ' (' . $idcolumn . ', title, content) VALUES ($, $, $) ' .
'ON DUPLICATE KEY UPDATE content = VALUES(content)',
$idvalue, $title, $content
);
}
/**
* Internal general function to clear metadata
* @param $metatable
* @param $idcolumn
* @param $idvalue
* @param $title
*/
function qa_db_meta_clear($metatable, $idcolumn, $idvalue, $title)
{
if (is_array($title)) {
if (count($title)) {
qa_db_query_sub(
'DELETE FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title=$',
'DELETE FROM ^' . $metatable . ' WHERE ' . $idcolumn . '=$ AND title IN ($)',
$idvalue, $title
);
}
} else {
qa_db_query_sub(
'DELETE FROM ^' . $metatable . ' WHERE ' . $idcolumn . '=$ AND title=$',
$idvalue, $title
);
}
function qa_db_meta_get($metatable, $idcolumn, $idvalue, $title)
/*
Internal general function to return metadata
*/
{
if (is_array($title)) {
if (count($title))
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT title, content FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title IN($)',
$idvalue, $title
), 'title', 'content');
else
return array();
} else
return qa_db_read_one_value(qa_db_query_sub(
'SELECT content FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title=$',
}
/**
* Internal general function to return metadata
* @param $metatable
* @param $idcolumn
* @param $idvalue
* @param $title
* @return array|mixed|null
*/
function qa_db_meta_get($metatable, $idcolumn, $idvalue, $title)
{
if (is_array($title)) {
if (count($title)) {
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT title, content FROM ^' . $metatable . ' WHERE ' . $idcolumn . '=$ AND title IN($)',
$idvalue, $title
), true);
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
), 'title', 'content');
} else {
return array();
}
} else {
return qa_db_read_one_value(qa_db_query_sub(
'SELECT content FROM ^' . $metatable . ' WHERE ' . $idcolumn . '=$ AND title=$',
$idvalue, $title
), true);
}
}
......@@ -20,50 +20,54 @@
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
header('Location: ../');
exit;
}
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
function qa_db_usernotice_create($userid, $content, $format='', $tags=null)
/*
Create a notice for $userid with $content in $format and optional $tags (not displayed) and return its noticeid
*/
{
qa_db_query_sub(
'INSERT INTO ^usernotices (userid, content, format, tags, created) VALUES ($, $, $, $, NOW())',
$userid, $content, $format, $tags
);
/**
* Create a notice for $userid with $content in $format and optional $tags (not displayed) and return its noticeid
* @param $userid
* @param $content
* @param string $format
* @param $tags
* @return mixed
*/
function qa_db_usernotice_create($userid, $content, $format = '', $tags = null)
{
qa_db_query_sub(
'INSERT INTO ^usernotices (userid, content, format, tags, created) VALUES ($, $, $, $, NOW())',
$userid, $content, $format, $tags
);
return qa_db_last_insert_id();
}
return qa_db_last_insert_id();
}
function qa_db_usernotice_delete($userid, $noticeid)
/*
Delete the notice $notice which belongs to $userid
*/
{
qa_db_query_sub(
'DELETE FROM ^usernotices WHERE userid=$ AND noticeid=#',
$userid, $noticeid
);
}
/**
* Delete the notice $notice which belongs to $userid
* @param $userid
* @param $noticeid
*/
function qa_db_usernotice_delete($userid, $noticeid)
{
qa_db_query_sub(
'DELETE FROM ^usernotices WHERE userid=$ AND noticeid=#',
$userid, $noticeid
);
}
function qa_db_usernotices_list($userid)
/*
Return an array summarizing the notices to be displayed for $userid, including the tags (not displayed)
*/
{
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT noticeid, tags, UNIX_TIMESTAMP(created) AS created FROM ^usernotices WHERE userid=$ ORDER BY created',
$userid
));
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
/**
* Return an array summarizing the notices to be displayed for $userid, including the tags (not displayed)
* @param $userid
* @return array
*/
function qa_db_usernotices_list($userid)
{
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT noticeid, tags, UNIX_TIMESTAMP(created) AS created FROM ^usernotices WHERE userid=$ ORDER BY created',
$userid
));
}
......@@ -20,25 +20,22 @@
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
header('Location: ../');
exit;
}
function qa_db_set_option($name, $value)
/*
Set option $name to $value in the database
*/
{
qa_db_query_sub(
'INSERT INTO ^options (title, content) VALUES ($, $) ' .
'ON DUPLICATE KEY UPDATE content = VALUES(content)',
$name, $value
);
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
/**
* Set option $name to $value in the database
* @param $name
* @param $value
*/
function qa_db_set_option($name, $value)
{
qa_db_query_sub(
'INSERT INTO ^options (title, content) VALUES ($, $) ' .
'ON DUPLICATE KEY UPDATE content = VALUES(content)',
$name, $value
);
}
......@@ -20,204 +20,204 @@
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
header('Location: ../');
exit;
}
function qa_db_points_option_names()
/*
Returns an array of option names required to perform calculations in userpoints table
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return array(
'points_post_q', 'points_select_a', 'points_per_q_voted_up', 'points_per_q_voted_down', 'points_q_voted_max_gain', 'points_q_voted_max_loss',
'points_post_a', 'points_a_selected', 'points_per_a_voted_up', 'points_per_a_voted_down', 'points_a_voted_max_gain', 'points_a_voted_max_loss',
'points_vote_up_q', 'points_vote_down_q', 'points_vote_up_a', 'points_vote_down_a',
'points_multiple', 'points_base',
);
}
function qa_db_points_calculations()
/*
Returns an array containing all the calculation formulae for the userpoints table. Each element of this
array is for one column - the key contains the column name, and the value is a further array of two elements.
The element 'formula' contains the SQL fragment that calculates the columns value for one or more users,
where the ~ symbol within the fragment is substituted for a constraint on which users we are interested in.
The element 'multiple' specifies what to multiply each column by to create the final sum in the points column.
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
/**
* Returns an array of option names required to perform calculations in userpoints table
*/
function qa_db_points_option_names()
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return array(
'points_post_q', 'points_select_a', 'points_per_q_voted_up', 'points_per_q_voted_down', 'points_q_voted_max_gain', 'points_q_voted_max_loss',
'points_post_a', 'points_a_selected', 'points_per_a_voted_up', 'points_per_a_voted_down', 'points_a_voted_max_gain', 'points_a_voted_max_loss',
'points_vote_up_q', 'points_vote_down_q', 'points_vote_up_a', 'points_vote_down_a',
'points_multiple', 'points_base',
);
}
/**
* Returns an array containing all the calculation formulae for the userpoints table. Each element of this
* array is for one column - the key contains the column name, and the value is a further array of two elements.
* The element 'formula' contains the SQL fragment that calculates the columns value for one or more users,
* where the ~ symbol within the fragment is substituted for a constraint on which users we are interested in.
* The element 'multiple' specifies what to multiply each column by to create the final sum in the points column.
*/
function qa_db_points_calculations()
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR . 'app/options.php';
$options = qa_get_options(qa_db_points_option_names());
return array(
'qposts' => array(
'multiple' => $options['points_multiple'] * $options['points_post_q'],
'formula' => "COUNT(*) AS qposts FROM ^posts AS userid_src WHERE userid~ AND type='Q'",
),
'aposts' => array(
'multiple' => $options['points_multiple'] * $options['points_post_a'],
'formula' => "COUNT(*) AS aposts FROM ^posts AS userid_src WHERE userid~ AND type='A'",
),
'cposts' => array(
'multiple' => 0,
'formula' => "COUNT(*) AS cposts FROM ^posts AS userid_src WHERE userid~ AND type='C'",
),
'aselects' => array(
'multiple' => $options['points_multiple'] * $options['points_select_a'],
'formula' => "COUNT(*) AS aselects FROM ^posts AS userid_src WHERE userid~ AND type='Q' AND selchildid IS NOT NULL",
),
'aselecteds' => array(
'multiple' => $options['points_multiple'] * $options['points_a_selected'],
'formula' => "COUNT(*) AS aselecteds FROM ^posts AS userid_src JOIN ^posts AS questions ON questions.selchildid=userid_src.postid WHERE userid_src.userid~ AND userid_src.type='A' AND NOT (questions.userid<=>userid_src.userid)",
),
'qupvotes' => array(
'multiple' => $options['points_multiple'] * $options['points_vote_up_q'],
'formula' => "COUNT(*) AS qupvotes FROM ^uservotes AS userid_src JOIN ^posts ON userid_src.postid=^posts.postid WHERE userid_src.userid~ AND LEFT(^posts.type, 1)='Q' AND userid_src.vote>0",
),
'qdownvotes' => array(
'multiple' => $options['points_multiple'] * $options['points_vote_down_q'],
'formula' => "COUNT(*) AS qdownvotes FROM ^uservotes AS userid_src JOIN ^posts ON userid_src.postid=^posts.postid WHERE userid_src.userid~ AND LEFT(^posts.type, 1)='Q' AND userid_src.vote<0",
),
'aupvotes' => array(
'multiple' => $options['points_multiple'] * $options['points_vote_up_a'],
'formula' => "COUNT(*) AS aupvotes FROM ^uservotes AS userid_src JOIN ^posts ON userid_src.postid=^posts.postid WHERE userid_src.userid~ AND LEFT(^posts.type, 1)='A' AND userid_src.vote>0",
),
'adownvotes' => array(
'multiple' => $options['points_multiple'] * $options['points_vote_down_a'],
'formula' => "COUNT(*) AS adownvotes FROM ^uservotes AS userid_src JOIN ^posts ON userid_src.postid=^posts.postid WHERE userid_src.userid~ AND LEFT(^posts.type, 1)='A' AND userid_src.vote<0",
),
'qvoteds' => array(
'multiple' => $options['points_multiple'],
'formula' => "COALESCE(SUM(" .
"LEAST(" . ((int)$options['points_per_q_voted_up']) . "*upvotes," . ((int)$options['points_q_voted_max_gain']) . ")" .
"-" .
"LEAST(" . ((int)$options['points_per_q_voted_down']) . "*downvotes," . ((int)$options['points_q_voted_max_loss']) . ")" .
"), 0) AS qvoteds FROM ^posts AS userid_src WHERE LEFT(type, 1)='Q' AND userid~",
),
'avoteds' => array(
'multiple' => $options['points_multiple'],
'formula' => "COALESCE(SUM(" .
"LEAST(" . ((int)$options['points_per_a_voted_up']) . "*upvotes," . ((int)$options['points_a_voted_max_gain']) . ")" .
"-" .
"LEAST(" . ((int)$options['points_per_a_voted_down']) . "*downvotes," . ((int)$options['points_a_voted_max_loss']) . ")" .
"), 0) AS avoteds FROM ^posts AS userid_src WHERE LEFT(type, 1)='A' AND userid~",
),
'upvoteds' => array(
'multiple' => 0,
'formula' => "COALESCE(SUM(upvotes), 0) AS upvoteds FROM ^posts AS userid_src WHERE userid~",
),
'downvoteds' => array(
'multiple' => 0,
'formula' => "COALESCE(SUM(downvotes), 0) AS downvoteds FROM ^posts AS userid_src WHERE userid~",
),
);
}
/**
* Update the userpoints table in the database for $userid and $columns, plus the summary points column.
* Set $columns to true for all, empty for none, an array for several, or a single value for one.
* This dynamically builds some fairly crazy looking SQL, but it works, and saves repeat calculations.
* @param $userid
* @param $columns
* @return mixed
*/
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';
$options=qa_get_options(qa_db_points_option_names());
return array(
'qposts' => array(
'multiple' => $options['points_multiple']*$options['points_post_q'],
'formula' => "COUNT(*) AS qposts FROM ^posts AS userid_src WHERE userid~ AND type='Q'",
),
'aposts' => array(
'multiple' => $options['points_multiple']*$options['points_post_a'],
'formula' => "COUNT(*) AS aposts FROM ^posts AS userid_src WHERE userid~ AND type='A'",
),
'cposts' => array(
'multiple' => 0,
'formula' => "COUNT(*) AS cposts FROM ^posts AS userid_src WHERE userid~ AND type='C'",
),
'aselects' => array(
'multiple' => $options['points_multiple']*$options['points_select_a'],
'formula' => "COUNT(*) AS aselects FROM ^posts AS userid_src WHERE userid~ AND type='Q' AND selchildid IS NOT NULL",
),
'aselecteds' => array(
'multiple' => $options['points_multiple']*$options['points_a_selected'],
'formula' => "COUNT(*) AS aselecteds FROM ^posts AS userid_src JOIN ^posts AS questions ON questions.selchildid=userid_src.postid WHERE userid_src.userid~ AND userid_src.type='A' AND NOT (questions.userid<=>userid_src.userid)",
),
'qupvotes' => array(
'multiple' => $options['points_multiple']*$options['points_vote_up_q'],
'formula' => "COUNT(*) AS qupvotes FROM ^uservotes AS userid_src JOIN ^posts ON userid_src.postid=^posts.postid WHERE userid_src.userid~ AND LEFT(^posts.type, 1)='Q' AND userid_src.vote>0",
),
'qdownvotes' => array(
'multiple' => $options['points_multiple']*$options['points_vote_down_q'],
'formula' => "COUNT(*) AS qdownvotes FROM ^uservotes AS userid_src JOIN ^posts ON userid_src.postid=^posts.postid WHERE userid_src.userid~ AND LEFT(^posts.type, 1)='Q' AND userid_src.vote<0",
),
'aupvotes' => array(
'multiple' => $options['points_multiple']*$options['points_vote_up_a'],
'formula' => "COUNT(*) AS aupvotes FROM ^uservotes AS userid_src JOIN ^posts ON userid_src.postid=^posts.postid WHERE userid_src.userid~ AND LEFT(^posts.type, 1)='A' AND userid_src.vote>0",
),
'adownvotes' => array(
'multiple' => $options['points_multiple']*$options['points_vote_down_a'],
'formula' => "COUNT(*) AS adownvotes FROM ^uservotes AS userid_src JOIN ^posts ON userid_src.postid=^posts.postid WHERE userid_src.userid~ AND LEFT(^posts.type, 1)='A' AND userid_src.vote<0",
),
'qvoteds' => array(
'multiple' => $options['points_multiple'],
'formula' => "COALESCE(SUM(".
"LEAST(".((int)$options['points_per_q_voted_up'])."*upvotes,".((int)$options['points_q_voted_max_gain']).")".
"-".
"LEAST(".((int)$options['points_per_q_voted_down'])."*downvotes,".((int)$options['points_q_voted_max_loss']).")".
"), 0) AS qvoteds FROM ^posts AS userid_src WHERE LEFT(type, 1)='Q' AND userid~",
),
'avoteds' => array(
'multiple' => $options['points_multiple'],
'formula' => "COALESCE(SUM(".
"LEAST(".((int)$options['points_per_a_voted_up'])."*upvotes,".((int)$options['points_a_voted_max_gain']).")".
"-".
"LEAST(".((int)$options['points_per_a_voted_down'])."*downvotes,".((int)$options['points_a_voted_max_loss']).")".
"), 0) AS avoteds FROM ^posts AS userid_src WHERE LEFT(type, 1)='A' AND userid~",
),
'upvoteds' => array(
'multiple' => 0,
'formula' => "COALESCE(SUM(upvotes), 0) AS upvoteds FROM ^posts AS userid_src WHERE userid~",
),
'downvoteds' => array(
'multiple' => 0,
'formula' => "COALESCE(SUM(downvotes), 0) AS downvoteds FROM ^posts AS userid_src WHERE userid~",
),
);
}
function qa_db_points_update_ifuser($userid, $columns)
/*
Update the userpoints table in the database for $userid and $columns, plus the summary points column.
Set $columns to true for all, empty for none, an array for several, or a single value for one.
This dynamically builds some fairly crazy looking SQL, but it works, and saves repeat calculations.
*/
{
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.')';
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.')';
}
$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();
$updatepoints.='+('.$multiple.'*'.(isset($keycolumns[$field]) ? '@_' : '').$field.')';
}
}
$query='INSERT INTO ^userpoints ('.$insertfields.'points) VALUES ('.$insertvalues.$insertpoints.') '.
'ON DUPLICATE KEY UPDATE '.$updates.'points='.$updatepoints.'+bonus';
function qa_db_points_set_bonus($userid, $bonus)
/*
Set the number of explicit bonus points for $userid to $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();
}
}
/**
* Set the number of explicit bonus points for $userid to $bonus
* @param $userid
* @param $bonus
*/
function qa_db_points_set_bonus($userid, $bonus)
{
qa_db_query_sub(
"INSERT INTO ^userpoints (userid, bonus) VALUES ($, #) ON DUPLICATE KEY UPDATE bonus=#",
$userid, $bonus, $bonus
);
}
/**
* Update the cached count in the database of the number of rows in the userpoints table
*/
function qa_db_userpointscount_update()
{
if (qa_should_update_counts()) {
qa_db_query_sub(
"INSERT INTO ^userpoints (userid, bonus) VALUES ($, #) ON DUPLICATE KEY UPDATE bonus=#",
$userid, $bonus, $bonus
"INSERT INTO ^options (title, content) " .
"SELECT 'cache_userpointscount', COUNT(*) FROM ^userpoints " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)"
);
}
function qa_db_userpointscount_update()
/*
Update the cached count in the database of the number of rows in the userpoints table
*/
{
if (qa_should_update_counts()) {
qa_db_query_sub(
"INSERT INTO ^options (title, content) " .
"SELECT 'cache_userpointscount', COUNT(*) FROM ^userpoints " .
"ON DUPLICATE KEY UPDATE content = VALUES(content)"
);
}
}
/*
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