Commit f5aaabc6 by Scott

Coding style (db functions)

parent b8eaff85
...@@ -20,21 +20,28 @@ ...@@ -20,21 +20,28 @@
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_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
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); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
for ($attempt=0; $attempt<10; $attempt++) { for ($attempt = 0; $attempt < 10; $attempt++) {
$blobid=qa_db_random_bigint(); $blobid = qa_db_random_bigint();
if (qa_db_blob_exists($blobid)) if (qa_db_blob_exists($blobid))
continue; continue;
...@@ -48,63 +55,68 @@ ...@@ -48,63 +55,68 @@
} }
return null; return null;
} }
function qa_db_blob_read($blobid) /**
/* * Get the information about blob $blobid from the database
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); } 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( return qa_db_read_one_assoc(qa_db_query_sub(
'SELECT content, format, filename FROM ^blobs WHERE blobid=#', 'SELECT content, format, filename FROM ^blobs WHERE blobid=#',
$blobid $blobid
), true); ), true);
} }
function qa_db_blob_set_content($blobid, $content) /**
/* * Change the content of blob $blobid in the database to $content (can also be null)
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( qa_db_query_sub(
'UPDATE ^blobs SET content=$ WHERE blobid=#', 'UPDATE ^blobs SET content=$ WHERE blobid=#',
$content, $blobid $content, $blobid
); );
} }
function qa_db_blob_delete($blobid) /**
/* * Delete blob $blobid in the database
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); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^blobs WHERE blobid=#', 'DELETE FROM ^blobs WHERE blobid=#',
$blobid $blobid
); );
} }
function qa_db_blob_exists($blobid) /**
/* * Check if blob $blobid exists in the database
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); } 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( $blob = qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^blobs WHERE blobid=#', 'SELECT COUNT(*) FROM ^blobs WHERE blobid=#',
$blobid $blobid
)) > 0; ));
}
/* return $blob > 0;
Omit PHP closing tag to help avoid accidental output }
*/
...@@ -20,19 +20,23 @@ ...@@ -20,19 +20,23 @@
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.'db/maxima.php'; 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
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); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
qa_db_query_sub( qa_db_query_sub(
...@@ -45,17 +49,20 @@ ...@@ -45,17 +49,20 @@
'ON DUPLICATE KEY UPDATE content = VALUES(content), created = VALUES(created), lastread = VALUES(lastread)', 'ON DUPLICATE KEY UPDATE content = VALUES(content), created = VALUES(created), lastread = VALUES(lastread)',
$type, $cacheid, $content $type, $cacheid, $content
); );
} }
function qa_db_cache_get($type, $cacheid) /**
/* * Retrieve the item ($type, $cacheid) from the database cache table
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); } 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( $content = qa_db_read_one_value(qa_db_query_sub(
'SELECT content FROM ^cache WHERE type=$ AND cacheid=#', 'SELECT content FROM ^cache WHERE type=$ AND cacheid=#',
$type, $cacheid $type, $cacheid
), true); ), true);
...@@ -67,9 +74,4 @@ ...@@ -67,9 +74,4 @@
); );
return $content; return $content;
} }
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
...@@ -20,25 +20,27 @@ ...@@ -20,25 +20,27 @@
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_cookie_create($ipaddress) /**
/* * Create a new random cookie for $ipaddress and insert into database, returning it
Create a new random cookie for $ipaddress and insert into database, returning it * @param $ipaddress
*/ * @return null|string
{ */
for ($attempt=0; $attempt<10; $attempt++) { function qa_db_cookie_create($ipaddress)
$cookieid=qa_db_random_bigint(); {
for ($attempt = 0; $attempt < 10; $attempt++) {
$cookieid = qa_db_random_bigint();
if (qa_db_cookie_exists($cookieid)) if (qa_db_cookie_exists($cookieid))
continue; continue;
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^cookies (cookieid, created, createip) '. 'INSERT INTO ^cookies (cookieid, created, createip) ' .
'VALUES (#, NOW(), $)', 'VALUES (#, NOW(), $)',
$cookieid, @inet_pton($ipaddress) $cookieid, @inet_pton($ipaddress)
); );
...@@ -47,33 +49,34 @@ ...@@ -47,33 +49,34 @@
} }
return null; 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
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( qa_db_query_sub(
'UPDATE ^cookies SET written=NOW(), writeip=$ WHERE cookieid=#', 'UPDATE ^cookies SET written=NOW(), writeip=$ WHERE cookieid=#',
@inet_pton($ipaddress), $cookieid @inet_pton($ipaddress), $cookieid
); );
} }
function qa_db_cookie_exists($cookieid) /**
/* * Return whether $cookieid exists in database
Return whether $cookieid exists in database * @param $cookieid
*/ * @return bool
{ */
return qa_db_read_one_value(qa_db_query_sub( function qa_db_cookie_exists($cookieid)
{
$cookie = qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^cookies WHERE cookieid=#', 'SELECT COUNT(*) FROM ^cookies WHERE cookieid=#',
$cookieid $cookieid
)) > 0; ));
}
return $cookie > 0;
/* }
Omit PHP closing tag to help avoid accidental output
*/
...@@ -20,40 +20,47 @@ ...@@ -20,40 +20,47 @@
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_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
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
$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
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
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.
qa-db-favorites.php). Also handles truncation. * @param $entitytype
*/ * @param $entityid
{ * @param $questionid
require_once QA_INCLUDE_DIR.'db/maxima.php'; * @param $lastpostid
require_once QA_INCLUDE_DIR.'app/updates.php'; * @param $updatetype
* @param $lastuserid
$updatedsql=isset($timestamp) ? ('FROM_UNIXTIME('.qa_db_argument_to_mysql($timestamp, false).')') : 'NOW()'; * @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 // Enter it into the appropriate shared event stream for that entity
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^sharedevents (entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) '. 'INSERT INTO ^sharedevents (entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) ' .
'VALUES ($, #, #, #, $, $, '.$updatedsql.')', 'VALUES ($, #, #, #, $, $, ' . $updatedsql . ')',
$entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid $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 // If this is for a question entity, check the shared event stream doesn't have too many entries for that question
$questiontruncated=false; $questiontruncated = false;
if ($entitytype==QA_ENTITY_QUESTION) { if ($entitytype == QA_ENTITY_QUESTION) {
$truncate=qa_db_read_one_value(qa_db_query_sub( $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', '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 $entitytype, $entityid, $questionid, QA_DB_MAX_EVENTS_PER_Q
), true); ), true);
...@@ -64,14 +71,14 @@ ...@@ -64,14 +71,14 @@
$entitytype, $entityid, $questionid, $truncate $entitytype, $entityid, $questionid, $truncate
); );
$questiontruncated=true; $questiontruncated = true;
} }
} }
// If we didn't truncate due to a specific question, truncate the shared event stream for its overall length // If we didn't truncate due to a specific question, truncate the shared event stream for its overall length
if (!$questiontruncated) { if (!$questiontruncated) {
$truncate=qa_db_read_one_value(qa_db_query_sub( $truncate = qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^sharedevents WHERE entitytype=$ AND entityid=$ ORDER BY updated DESC LIMIT #,1', 'SELECT updated FROM ^sharedevents WHERE entitytype=$ AND entityid=$ ORDER BY updated DESC LIMIT #,1',
$entitytype, $entityid, (int)qa_opt('max_store_user_updates') $entitytype, $entityid, (int)qa_opt('max_store_user_updates')
), true); ), true);
...@@ -85,7 +92,7 @@ ...@@ -85,7 +92,7 @@
// See if we can identify a user who has favorited this entity, but is not using its shared event stream // See if we can identify a user who has favorited this entity, but is not using its shared event stream
$randomuserid=qa_db_read_one_value(qa_db_query_sub( $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', 'SELECT userid FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0 ORDER BY RAND() LIMIT 1',
$entitytype, $entityid $entitytype, $entityid
), true); ), true);
...@@ -95,8 +102,8 @@ ...@@ -95,8 +102,8 @@
// If one was found, this means we have one or more individual event streams, so update them all // If one was found, this means we have one or more individual event streams, so update them all
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) '. 'INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) ' .
'SELECT userid, $, #, #, #, $, $, '.$updatedsql.' FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0', 'SELECT userid, $, #, #, #, $, $, ' . $updatedsql . ' FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0',
$entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid, $entitytype, $entityid $entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid, $entitytype, $entityid
); );
...@@ -105,44 +112,51 @@ ...@@ -105,44 +112,51 @@
qa_db_user_events_truncate($randomuserid, $questionid); qa_db_user_events_truncate($randomuserid, $questionid);
} }
} }
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
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
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
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.
$timestamp for the event time or leave as null to use now. Also handles truncation of event streams. * @param $userid
*/ * @param $questionid
{ * @param $lastpostid
require_once QA_INCLUDE_DIR.'app/updates.php'; * @param $updatetype
* @param $lastuserid
$updatedsql=isset($timestamp) ? ('FROM_UNIXTIME('.qa_db_argument_to_mysql($timestamp, false).')') : 'NOW()'; * @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( qa_db_query_sub(
"INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) ". "INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) " .
"VALUES ($, $, 0, #, #, $, $, ".$updatedsql.")", "VALUES ($, $, 0, #, #, $, $, " . $updatedsql . ")",
$userid, QA_ENTITY_NONE, $questionid, $lastpostid, $updatetype, $lastuserid $userid, QA_ENTITY_NONE, $questionid, $lastpostid, $updatetype, $lastuserid
); );
qa_db_user_events_truncate($userid, $questionid); 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).
*/
{
/**
* 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 // First try truncating based on there being too many events for this question
$questiontruncated=false; $questiontruncated = false;
if (isset($questionid)) { if (isset($questionid)) {
$truncate=qa_db_read_one_value(qa_db_query_sub( $truncate = qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^userevents WHERE userid=$ AND questionid=# ORDER BY updated DESC LIMIT #,1', 'SELECT updated FROM ^userevents WHERE userid=$ AND questionid=# ORDER BY updated DESC LIMIT #,1',
$userid, $questionid, QA_DB_MAX_EVENTS_PER_Q $userid, $questionid, QA_DB_MAX_EVENTS_PER_Q
), true); ), true);
...@@ -153,14 +167,14 @@ ...@@ -153,14 +167,14 @@
$userid, $questionid, $truncate $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) { if (!$questiontruncated) {
$truncate=qa_db_read_one_value(qa_db_query_sub( $truncate = qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^userevents WHERE userid=$ ORDER BY updated DESC LIMIT #,1', 'SELECT updated FROM ^userevents WHERE userid=$ ORDER BY updated DESC LIMIT #,1',
$userid, (int)qa_opt('max_store_user_updates') $userid, (int)qa_opt('max_store_user_updates')
), true); ), true);
...@@ -171,9 +185,4 @@ ...@@ -171,9 +185,4 @@
$userid, $truncate $userid, $truncate
); );
} }
} }
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
...@@ -20,10 +20,10 @@ ...@@ -20,10 +20,10 @@
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;
} }
/* /*
...@@ -103,14 +103,17 @@ ...@@ -103,14 +103,17 @@
*/ */
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
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
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.
appropriate, it also adds recent events from that entity to the user's event stream. * @param $userid
*/ * @param $entitytype
{ * @param $entityid
$threshold=qa_opt('max_copy_user_updates'); // if this many users subscribe to it, create a shared stream */
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)
...@@ -121,7 +124,7 @@ ...@@ -121,7 +124,7 @@
// 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( $useshared = qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents>0 LIMIT 1', 'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents>0 LIMIT 1',
$entitytype, $entityid $entitytype, $entityid
)); ));
...@@ -129,12 +132,12 @@ ...@@ -129,12 +132,12 @@
// 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) { if (!$useshared) {
$favoriters=qa_db_read_one_value(qa_db_query_sub( $favoriters = qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# LIMIT #', 'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# LIMIT #',
$entitytype, $entityid, $threshold $entitytype, $entityid, $threshold
)); ));
$useshared=($favoriters >= $threshold); $useshared = ($favoriters >= $threshold);
} }
// If we're going to use the shared stream... // If we're going to use the shared stream...
...@@ -143,16 +146,16 @@ ...@@ -143,16 +146,16 @@
// ... for all the people for whom we're switching this to a shared stream, find the highest number of other shared streams they have // ... 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( $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 '. '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', '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 $entitytype, $entityid
)); ));
// ... if this number is greater than our current 'max_copy_user_updates' threshold, increase that threshold (see long comment above) // ... if this number is greater than our current 'max_copy_user_updates' threshold, increase that threshold (see long comment above)
if (($maxshared+1)>$threshold) if (($maxshared + 1) > $threshold)
qa_opt('max_copy_user_updates', $maxshared+1); qa_opt('max_copy_user_updates', $maxshared + 1);
// ... now switch all unshared favoriters (including this new one) over to be shared // ... now switch all unshared favoriters (including this new one) over to be shared
...@@ -161,16 +164,16 @@ ...@@ -161,16 +164,16 @@
$entitytype, $entityid $entitytype, $entityid
); );
} else {
// Otherwise if we're going to record this in user-specific streams ... // Otherwise if we're going to record this in user-specific streams ...
} else { require_once QA_INCLUDE_DIR . 'db/events.php';
require_once QA_INCLUDE_DIR.'db/events.php';
// ... copy across recent events from the shared stream // ... copy across recent events from the shared stream
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) '. 'INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) ' .
'SELECT #, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated FROM '. 'SELECT #, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated FROM ' .
'^sharedevents WHERE entitytype=$ AND entityid=#', '^sharedevents WHERE entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid $userid, $entitytype, $entityid
); );
...@@ -179,15 +182,18 @@ ...@@ -179,15 +182,18 @@
qa_db_user_events_truncate($userid); qa_db_user_events_truncate($userid);
} }
} }
function qa_db_favorite_delete($userid, $entitytype, $entityid) /**
/* * Delete the entity $entitytype with $entityid from the favorites list of $userid, removing any corresponding events
Delete the entity $entitytype with $entityid from the favorites list of $userid, removing any corresponding events * from the user's stream.
from the user's stream. * @param $userid
*/ * @param $entitytype
{ * @param $entityid
*/
function qa_db_favorite_delete($userid, $entitytype, $entityid)
{
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^userfavorites WHERE userid=$ AND entitytype=$ AND entityid=#', 'DELETE FROM ^userfavorites WHERE userid=$ AND entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid $userid, $entitytype, $entityid
...@@ -197,9 +203,4 @@ ...@@ -197,9 +203,4 @@
'DELETE FROM ^userevents WHERE userid=$ AND entitytype=$ AND entityid=#', 'DELETE FROM ^userevents WHERE userid=$ AND entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid $userid, $entitytype, $entityid
); );
} }
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
...@@ -20,45 +20,49 @@ ...@@ -20,45 +20,49 @@
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_hotness_update($firstpostid, $lastpostid=null, $viewincrement=false) /**
/* * Recalculate the hotness in the database for posts $firstpostid to $lastpostid (if specified)
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),
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
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_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if (qa_should_update_counts()) { if (qa_should_update_counts()) {
if (!isset($lastpostid)) if (!isset($lastpostid))
$lastpostid=$firstpostid; $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=(". $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.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))*# + '. '((TO_DAYS(a.acreated)-734138)*86400.0+TIME_TO_SEC(a.acreated))*# + ' .
'(a.acount+0.0)*# + '. '(a.acount+0.0)*# + ' .
'(a.netvotes+0.0)*# + '. '(a.netvotes+0.0)*# + ' .
'(a.views+0.0+#)*#'. '(a.views+0.0+#)*#' .
')'.($viewincrement ? ', x.views=x.views+1, x.lastviewip=$' : ''). ')' . ($viewincrement ? ', x.views=x.views+1, x.lastviewip=$' : '') .
' WHERE x.postid=a.postid'.($viewincrement ? ' AND (x.lastviewip IS NULL OR 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 // Additional multiples based on empirical analysis of activity on Q2A meta site to give approx equal influence for all factors
$arguments=array( $arguments = array(
$firstpostid, $firstpostid,
$lastpostid, $lastpostid,
qa_opt('hot_weight_q_age'), qa_opt('hot_weight_q_age'),
qa_opt('hot_weight_a_age'), qa_opt('hot_weight_a_age'),
qa_opt('hot_weight_answers')*160000, qa_opt('hot_weight_answers') * 160000,
qa_opt('hot_weight_votes')*160000, qa_opt('hot_weight_votes') * 160000,
$viewincrement ? 1 : 0, $viewincrement ? 1 : 0,
qa_opt('hot_weight_views')*4000, qa_opt('hot_weight_views') * 4000,
); );
if ($viewincrement) { if ($viewincrement) {
...@@ -68,9 +72,4 @@ ...@@ -68,9 +72,4 @@
qa_db_query_raw(qa_db_apply_sub($query, $arguments)); qa_db_query_raw(qa_db_apply_sub($query, $arguments));
} }
} }
/*
Omit PHP closing tag to help avoid accidental output
*/
...@@ -20,68 +20,75 @@ ...@@ -20,68 +20,75 @@
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_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.
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.
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
$selects=array(); * @return array
$arguments=array(); */
function qa_db_limits_get($userid, $ip, $action)
{
$selects = array();
$arguments = array();
if (isset($userid)) { if (isset($userid)) {
$selects[]="(SELECT 'user' AS limitkey, period, count FROM ^userlimits WHERE userid=$ AND action=$)"; $selects[] = "(SELECT 'user' AS limitkey, period, count FROM ^userlimits WHERE userid=$ AND action=$)";
$arguments[]=$userid; $arguments[] = $userid;
$arguments[]=$action; $arguments[] = $action;
} }
if (isset($ip)) { if (isset($ip)) {
$selects[]="(SELECT 'ip' AS limitkey, period, count FROM ^iplimits WHERE ip=$ AND action=$)"; $selects[] = "(SELECT 'ip' AS limitkey, period, count FROM ^iplimits WHERE ip=$ AND action=$)";
$arguments[]=@inet_pton($ip); $arguments[] = @inet_pton($ip);
$arguments[]=$action; $arguments[] = $action;
} }
if (count($selects)) { if (count($selects)) {
$query=qa_db_apply_sub(implode(' UNION ALL ', $selects), $arguments); $query = qa_db_apply_sub(implode(' UNION ALL ', $selects), $arguments);
return qa_db_read_all_assoc(qa_db_query_raw($query), 'limitkey'); return qa_db_read_all_assoc(qa_db_query_raw($query), 'limitkey');
} else } else
return array(); 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
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( qa_db_query_sub(
'INSERT INTO ^userlimits (userid, action, period, count) VALUES ($, $, #, #) '. 'INSERT INTO ^userlimits (userid, action, period, count) VALUES ($, $, #, #) ' .
'ON DUPLICATE KEY UPDATE count=IF(period=#, count+#, #), period=#', 'ON DUPLICATE KEY UPDATE count=IF(period=#, count+#, #), period=#',
$userid, $action, $period, $count, $period, $count, $count, $period $userid, $action, $period, $count, $period, $count, $count, $period
); );
} }
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
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( qa_db_query_sub(
'INSERT INTO ^iplimits (ip, action, period, count) VALUES ($, $, #, #) '. 'INSERT INTO ^iplimits (ip, action, period, count) VALUES ($, $, #, #) ' .
'ON DUPLICATE KEY UPDATE count=IF(period=#, count+#, #), period=#', 'ON DUPLICATE KEY UPDATE count=IF(period=#, count+#, #), period=#',
@inet_pton($ip), $action, $period, $count, $period, $count, $count, $period @inet_pton($ip), $action, $period, $count, $period, $count, $count, $period
); );
} }
/*
Omit PHP closing tag to help avoid accidental output
*/
...@@ -20,54 +20,49 @@ ...@@ -20,54 +20,49 @@
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;
} }
// Maximum column sizes - any of these can be defined in qa-config.php to override the defaults below, // 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. // 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_EMAIL_LENGTH', 80);
@define('QA_DB_MAX_HANDLE_LENGTH', 20); @define('QA_DB_MAX_HANDLE_LENGTH', 20);
@define('QA_DB_MAX_TITLE_LENGTH', 800); @define('QA_DB_MAX_TITLE_LENGTH', 800);
@define('QA_DB_MAX_CONTENT_LENGTH', 12000); @define('QA_DB_MAX_CONTENT_LENGTH', 12000);
@define('QA_DB_MAX_FORMAT_LENGTH', 20); @define('QA_DB_MAX_FORMAT_LENGTH', 20);
@define('QA_DB_MAX_TAGS_LENGTH', 800); @define('QA_DB_MAX_TAGS_LENGTH', 800);
@define('QA_DB_MAX_NAME_LENGTH', 40); @define('QA_DB_MAX_NAME_LENGTH', 40);
@define('QA_DB_MAX_WORD_LENGTH', 80); @define('QA_DB_MAX_WORD_LENGTH', 80);
@define('QA_DB_MAX_CAT_PAGE_TITLE_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_PAGE_TAGS_LENGTH', 200);
@define('QA_DB_MAX_CAT_CONTENT_LENGTH', 800); @define('QA_DB_MAX_CAT_CONTENT_LENGTH', 800);
@define('QA_DB_MAX_WIDGET_TAGS_LENGTH', 800); @define('QA_DB_MAX_WIDGET_TAGS_LENGTH', 800);
@define('QA_DB_MAX_WIDGET_TITLE_LENGTH', 80); @define('QA_DB_MAX_WIDGET_TITLE_LENGTH', 80);
@define('QA_DB_MAX_OPTION_TITLE_LENGTH', 40); @define('QA_DB_MAX_OPTION_TITLE_LENGTH', 40);
@define('QA_DB_MAX_PROFILE_TITLE_LENGTH', 40); @define('QA_DB_MAX_PROFILE_TITLE_LENGTH', 40);
@define('QA_DB_MAX_PROFILE_CONTENT_LENGTH', 8000); @define('QA_DB_MAX_PROFILE_CONTENT_LENGTH', 8000);
@define('QA_DB_MAX_CACHE_AGE', 86400); @define('QA_DB_MAX_CACHE_AGE', 86400);
@define('QA_DB_MAX_BLOB_FILE_NAME_LENGTH', 255); @define('QA_DB_MAX_BLOB_FILE_NAME_LENGTH', 255);
@define('QA_DB_MAX_META_TITLE_LENGTH', 40); @define('QA_DB_MAX_META_TITLE_LENGTH', 40);
@define('QA_DB_MAX_META_CONTENT_LENGTH', 8000); @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 // 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. // 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_QS_AS', 50);
@define('QA_DB_RETRIEVE_TAGS', 200); @define('QA_DB_RETRIEVE_TAGS', 200);
@define('QA_DB_RETRIEVE_USERS', 200); @define('QA_DB_RETRIEVE_USERS', 200);
@define('QA_DB_RETRIEVE_ASK_TAG_QS', 500); @define('QA_DB_RETRIEVE_ASK_TAG_QS', 500);
@define('QA_DB_RETRIEVE_COMPLETE_TAGS', 1000); @define('QA_DB_RETRIEVE_COMPLETE_TAGS', 1000);
@define('QA_DB_RETRIEVE_MESSAGES', 20); @define('QA_DB_RETRIEVE_MESSAGES', 20);
// Keep event streams trimmed - not worth storing too many events per question because we only display the // 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... // most recent event for each question, that has not been invalidated due to hiding/unselection/etc...
@define('QA_DB_MAX_EVENTS_PER_Q', 5); @define('QA_DB_MAX_EVENTS_PER_Q', 5);
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
...@@ -20,69 +20,76 @@ ...@@ -20,69 +20,76 @@
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_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
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.
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( qa_db_query_sub(
'INSERT INTO ^messages (type, fromuserid, touserid, content, format, created) VALUES ($, #, #, $, $, NOW())', 'INSERT INTO ^messages (type, fromuserid, touserid, content, format, created) VALUES ($, #, #, $, $, NOW())',
$public ? 'PUBLIC' : 'PRIVATE', $fromuserid, $touserid, $content, $format $public ? 'PUBLIC' : 'PRIVATE', $fromuserid, $touserid, $content, $format
); );
return qa_db_last_insert_id(); 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.
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'); $field = ($box === 'inbox' ? 'tohidden' : 'fromhidden');
qa_db_query_sub( qa_db_query_sub(
"UPDATE ^messages SET $field=1 WHERE messageid=#", "UPDATE ^messages SET $field=1 WHERE messageid=#",
$messageid $messageid
); );
} }
function qa_db_message_delete($messageid, $public=true) /**
/* * Delete the message with $messageid from the database.
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 // delete PM only if both sender and receiver have hidden it
$clause = $public ? '' : ' AND fromhidden=1 AND tohidden=1'; $clause = $public ? '' : ' AND fromhidden=1 AND tohidden=1';
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^messages WHERE messageid=#'.$clause, 'DELETE FROM ^messages WHERE messageid=#' . $clause,
$messageid $messageid
); );
} }
function qa_db_user_recount_posts($userid) /**
/* * Recalculate the cached count of wall posts for user $userid in the database
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()) {
if (qa_should_update_counts()) {
qa_db_query_sub( 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=#", "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 $userid, $userid
); );
} }
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
...@@ -20,179 +20,223 @@ ...@@ -20,179 +20,223 @@
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_usermeta_set($userid, $key, $value) /**
/* * Set the metadata for user $userid with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
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); 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)
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); 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
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).
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); 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.
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); 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)
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); 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
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).
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); 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.
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); 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)
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); 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
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).
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); 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.
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); 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)
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); 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
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).
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); 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
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( qa_db_query_sub(
'INSERT INTO ^' . $metatable . ' (' . $idcolumn . ', title, content) VALUES ($, $, $) ' . 'INSERT INTO ^' . $metatable . ' (' . $idcolumn . ', title, content) VALUES ($, $, $) ' .
'ON DUPLICATE KEY UPDATE content = VALUES(content)', 'ON DUPLICATE KEY UPDATE content = VALUES(content)',
$idvalue, $title, $content $idvalue, $title, $content
); );
} }
function qa_db_meta_clear($metatable, $idcolumn, $idvalue, $title) /**
/* * Internal general function to clear metadata
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 (is_array($title)) {
if (count($title)) if (count($title)) {
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title IN ($)', 'DELETE FROM ^' . $metatable . ' WHERE ' . $idcolumn . '=$ AND title IN ($)',
$idvalue, $title $idvalue, $title
); );
}
} else } else {
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title=$', 'DELETE FROM ^' . $metatable . ' WHERE ' . $idcolumn . '=$ AND title=$',
$idvalue, $title $idvalue, $title
); );
} }
}
function qa_db_meta_get($metatable, $idcolumn, $idvalue, $title) /**
/* * Internal general function to return metadata
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 (is_array($title)) {
if (count($title)) if (count($title)) {
return qa_db_read_all_assoc(qa_db_query_sub( return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT title, content FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title IN($)', 'SELECT title, content FROM ^' . $metatable . ' WHERE ' . $idcolumn . '=$ AND title IN($)',
$idvalue, $title $idvalue, $title
), 'title', 'content'); ), 'title', 'content');
else } else {
return array(); return array();
}
} else } else {
return qa_db_read_one_value(qa_db_query_sub( return qa_db_read_one_value(qa_db_query_sub(
'SELECT content FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title=$', 'SELECT content FROM ^' . $metatable . ' WHERE ' . $idcolumn . '=$ AND title=$',
$idvalue, $title $idvalue, $title
), true); ), true);
} }
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
...@@ -20,50 +20,54 @@ ...@@ -20,50 +20,54 @@
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_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
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( qa_db_query_sub(
'INSERT INTO ^usernotices (userid, content, format, tags, created) VALUES ($, $, $, $, NOW())', 'INSERT INTO ^usernotices (userid, content, format, tags, created) VALUES ($, $, $, $, NOW())',
$userid, $content, $format, $tags $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
Delete the notice $notice which belongs to $userid * @param $userid
*/ * @param $noticeid
{ */
function qa_db_usernotice_delete($userid, $noticeid)
{
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^usernotices WHERE userid=$ AND noticeid=#', 'DELETE FROM ^usernotices WHERE userid=$ AND noticeid=#',
$userid, $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 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( 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', 'SELECT noticeid, tags, UNIX_TIMESTAMP(created) AS created FROM ^usernotices WHERE userid=$ ORDER BY created',
$userid $userid
)); ));
} }
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
...@@ -20,25 +20,22 @@ ...@@ -20,25 +20,22 @@
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_set_option($name, $value) /**
/* * Set option $name to $value in the database
Set option $name to $value in the database * @param $name
*/ * @param $value
{ */
function qa_db_set_option($name, $value)
{
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^options (title, content) VALUES ($, $) ' . 'INSERT INTO ^options (title, content) VALUES ($, $) ' .
'ON DUPLICATE KEY UPDATE content = VALUES(content)', 'ON DUPLICATE KEY UPDATE content = VALUES(content)',
$name, $value $name, $value
); );
} }
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
...@@ -20,17 +20,17 @@ ...@@ -20,17 +20,17 @@
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_points_option_names() /**
/* * Returns an array of option names required to perform calculations in userpoints table
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); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return array( return array(
...@@ -40,32 +40,32 @@ ...@@ -40,32 +40,32 @@
'points_multiple', 'points_base', '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
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.
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,
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.
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.
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); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'app/options.php'; require_once QA_INCLUDE_DIR . 'app/options.php';
$options=qa_get_options(qa_db_points_option_names()); $options = qa_get_options(qa_db_points_option_names());
return array( return array(
'qposts' => array( 'qposts' => array(
'multiple' => $options['points_multiple']*$options['points_post_q'], 'multiple' => $options['points_multiple'] * $options['points_post_q'],
'formula' => "COUNT(*) AS qposts FROM ^posts AS userid_src WHERE userid~ AND type='Q'", 'formula' => "COUNT(*) AS qposts FROM ^posts AS userid_src WHERE userid~ AND type='Q'",
), ),
'aposts' => array( 'aposts' => array(
'multiple' => $options['points_multiple']*$options['points_post_a'], 'multiple' => $options['points_multiple'] * $options['points_post_a'],
'formula' => "COUNT(*) AS aposts FROM ^posts AS userid_src WHERE userid~ AND type='A'", 'formula' => "COUNT(*) AS aposts FROM ^posts AS userid_src WHERE userid~ AND type='A'",
), ),
...@@ -75,50 +75,50 @@ ...@@ -75,50 +75,50 @@
), ),
'aselects' => array( 'aselects' => array(
'multiple' => $options['points_multiple']*$options['points_select_a'], '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", 'formula' => "COUNT(*) AS aselects FROM ^posts AS userid_src WHERE userid~ AND type='Q' AND selchildid IS NOT NULL",
), ),
'aselecteds' => array( 'aselecteds' => array(
'multiple' => $options['points_multiple']*$options['points_a_selected'], '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)", '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( 'qupvotes' => array(
'multiple' => $options['points_multiple']*$options['points_vote_up_q'], '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", '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( 'qdownvotes' => array(
'multiple' => $options['points_multiple']*$options['points_vote_down_q'], '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", '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( 'aupvotes' => array(
'multiple' => $options['points_multiple']*$options['points_vote_up_a'], '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", '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( 'adownvotes' => array(
'multiple' => $options['points_multiple']*$options['points_vote_down_a'], '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", '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( 'qvoteds' => array(
'multiple' => $options['points_multiple'], 'multiple' => $options['points_multiple'],
'formula' => "COALESCE(SUM(". '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_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']).")". "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~", "), 0) AS qvoteds FROM ^posts AS userid_src WHERE LEFT(type, 1)='Q' AND userid~",
), ),
'avoteds' => array( 'avoteds' => array(
'multiple' => $options['points_multiple'], 'multiple' => $options['points_multiple'],
'formula' => "COALESCE(SUM(". '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_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']).")". "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~", "), 0) AS avoteds FROM ^posts AS userid_src WHERE LEFT(type, 1)='A' AND userid~",
), ),
...@@ -132,16 +132,19 @@ ...@@ -132,16 +132,19 @@
'formula' => "COALESCE(SUM(downvotes), 0) AS downvoteds FROM ^posts AS userid_src WHERE userid~", '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.
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.
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.
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_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if (qa_should_update_counts() && isset($userid)) { if (qa_should_update_counts() && isset($userid)) {
...@@ -188,26 +191,28 @@ ...@@ -188,26 +191,28 @@
if (qa_db_insert_on_duplicate_inserted()) if (qa_db_insert_on_duplicate_inserted())
qa_db_userpointscount_update(); qa_db_userpointscount_update();
} }
} }
function qa_db_points_set_bonus($userid, $bonus) /**
/* * Set the number of explicit bonus points for $userid to $bonus
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( qa_db_query_sub(
"INSERT INTO ^userpoints (userid, bonus) VALUES ($, #) ON DUPLICATE KEY UPDATE bonus=#", "INSERT INTO ^userpoints (userid, bonus) VALUES ($, #) ON DUPLICATE KEY UPDATE bonus=#",
$userid, $bonus, $bonus $userid, $bonus, $bonus
); );
} }
function qa_db_userpointscount_update() /**
/* * Update the cached count in the database of the number of rows in the userpoints table
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()) { if (qa_should_update_counts()) {
qa_db_query_sub( qa_db_query_sub(
"INSERT INTO ^options (title, content) " . "INSERT INTO ^options (title, content) " .
...@@ -215,9 +220,4 @@ ...@@ -215,9 +220,4 @@
"ON DUPLICATE KEY UPDATE content = VALUES(content)" "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