Hoeray! I have a first core version of submission moderation up and

running.  This means people can submit stories, and moderators can
moderate stories.  When a submission reaches a certain positive
threshold (currently set to 2) the submission becomes a story and up
it goes.   If a submission reaches a certain negative threshold
(currently set to -2) the submission is dumped.

The fact this is all done by our visitors (without our intervention)
makes it truly spiffy imho.  The website can live a life on it's own,
fed by the visitors.

Beware, a lot of work need to be done though ... it's just a first
basic implementation with the core functionality.  There are quite
a lot of things that I'll need to change, extend and improve.  But
comments, suggestions and ideas are - as always - welcomed.

Please read this log message carefully!  It features quite a lot of
important information.

To test the moderation, log in, select theme 'Dries' (the other themes
need a small update) and head by clicking the one and only 'submission
moderation' link.  Don't be afraid to submit lame/funny/useless
stories for testing purpose ... as soon we go public, we'll wipe out
the story database.  ;-)


WHAT'S NEW?
-----------
* Added 2 new operations to user.class.php to set and retrieve the
  user's "history".  Very evil but required to avoid people voting
  twice.
* Moved dbsave() from account.php to functions.php.  In addition, I
  added a new function to user.class.php called `save()' that ...
  well, saves the object back to the database.  It's (IMHO) a better
  approach compared to dbsave(): it keeps things organized. ;-)


BUGFIXES:
---------
* Fixed a (heavy) memory leak in the constructor of user.class.php:
  mysql_fetch_array() returns an _associative_ array which made the
  constructor `pollute' the object with a lot of useless variables.
* Fixed the slash-problem on the account pages. :-)
* Fixed UnConeD's theme glitch, alas the warning.
* Fixed the e-mail address not showing in the confirmation email
  (upon registration).
* Fixed the typical quote and backslash problems in submit.php.
* submit.php now uses the database abstraction layer.

IMPORTANT:
----------
* You can check the new submission system at:
    http://beta.drop.org/submission.php
  or by following the `submission moderation' link from my theme.
* UnConeD, Jeroen: you'll need to update your themes to take
  advantage of the new function: displayAccount().  This function
  will display the `submission moderation' link when a user is
  logged on.
* Natrak: you might want to apply the patches in user.class.php
  on the other sites using the same user-system.
3-00
Dries Buytaert 2000-06-13 09:42:58 +00:00
parent 00ff842a08
commit 1887ba8018
7 changed files with 217 additions and 38 deletions

View File

@ -2,16 +2,6 @@
include "config.inc";
include "functions.inc";
function dbsave($dbase, $data, $id=0) {
foreach ($data as $key=>$value) {
if ($key == "passwd") { $query .= "$key=PASSWORD('". addslashes($value) ."'), "; }
else { $query .= "$key='". addslashes($value) ."', "; }
}
$query = substr($query, 0, -2);
dbconnect();
if (!empty($id)) { mysql_query("UPDATE $dbase SET $query WHERE id=$id") or die(mysql_error()); return $id; }
else { mysql_query("INSERT INTO $dbase SET $query") or die(mysql_error()); return mysql_insert_id(); }
}
function showLogin($userid = "") {
print("<FORM ACTION=\"account.php\" METHOD=post>\n");
print("<TABLE BORDER=0 CELLPADDING=2 CELLSPACING=2>\n");
@ -112,7 +102,7 @@ switch ($op) {
print("Your password is: <B>$new[passwd]</B><BR>");
print("<A HREF=\"account.php?op=Login&userid=$new[userid]&passwd=$new[passwd]\">Login</A> to change your personal settings.");
} else {
$message = "Your $sitename member account has been created succesfully. To be able to use it you must login using the information below. Please save this mail for further reference.\n\n username: $new[userid]\n e-mail: $newu[email]\n password: $new[passwd]\n\nThis password is generated by a randomizer. It is recommended that you change this password immediately.\n\n$contact_signature";
$message = "Your $sitename member account has been created succesfully. To be able to use it you must login using the information below. Please save this mail for further reference.\n\n username: $new[userid]\n e-mail: $new[email]\n password: $new[passwd]\n\nThis password is generated by a randomizer. It is recommended that you change this password immediately.\n\n$contact_signature";
$subject = "Account details for $sitename";
mail($new[email], $subject, $message, "From: $contact_email\nX-Mailer: PHP/" . phpversion());
print("Your member account has been created and the details necessary to login have been sent to your e-mail account <B>$new[email]</B>. Once you received the account confirmation, hit <A HREF=\"account.php\">this link</A> to login.");

View File

@ -20,6 +20,13 @@ $sitename = "drop.org";
$contact_email = "droppies@zind.net";
$contact_signature = "Kind regards,\n\n-- the drop.org crew\nhttp://www.drop.org/";
#
# Notify:
# Set to '1' to receive an e-mail when news has been submitted
# through submit.php
#
$notify = 0;
#
# Notify information:
# The notify information will be used to send out automated mails
@ -44,12 +51,6 @@ $comments_meta_reasons = array('Off topic', 'Redundant', 'Insightfull', 'As is',
#
$categories = array('Announcements', 'Coding', 'Geeking', 'Drop.org', 'Gaming', 'Girls', 'Graphics', 'Hardware', 'Humor', 'Internet', 'Music', 'Movies', 'Politics', 'Science', 'Software', 'Space', 'Webdesign', 'Quickies');
#
# Notify:
# Set to '1' to receive an e-mail when news has been submitted
# through submit.php
#
$notify = 1;
#
# Allowed HTML tags:
@ -62,11 +63,28 @@ $allowableHTML = array('B','/B','I','/I','P .*','P','/P','A .*','/A','LI','OL'
$anonymous = "Anonymous Chicken";
#
#
# Default theme:
#
$cfg_theme = "default";
#
# Submission moderation votes:
#
// NOTE: changing $submission_votes will affect the integrity of your
// database. In short, the database field user.history will
// become invalid, and will need to be reset! Please, do not
// just change this setting unless you have an empty database
// or unless you know what you are doing.
$submission_votes = array("neutral (+0)" => "+ 0",
"post it (+1)" => "+ 1",
"dump it (-1)" => "- 1");
#
# Submission moderation thresholds:
#
$submission_post_threshold = "2";
$submission_dump_threshold = "-2";
#
# Debug flag:
# Set to '1' if you are using Windows so the engine won't try
@ -74,12 +92,4 @@ $cfg_theme = "default";
# to '0'
$system = 0;
/*
class config {
var $path = "/home/buytaert/public_html/projects/drop";
}
if (!$config) $config = new config();
*/
?>

View File

@ -7,6 +7,17 @@ session_start();
include "config.inc";
$functions = 1;
function dbsave($dbase, $data, $id=0) {
foreach ($data as $key=>$value) {
if ($key == "passwd") { $query .= "$key=PASSWORD('". addslashes($value) ."'), "; }
else { $query .= "$key='". addslashes($value) ."', "; }
}
$query = substr($query, 0, -2);
dbconnect();
if (!empty($id)) { mysql_query("UPDATE $dbase SET $query WHERE id=$id") or die(mysql_error()); return $id; }
else { mysql_query("INSERT INTO $dbase SET $query") or die(mysql_error()); return mysql_insert_id(); }
}
function dbconnect() {
include "config.inc";
mysql_pconnect($dbhost, $dbuname, $dbpass) or die(mysql_Error());
@ -191,7 +202,7 @@ function displayAccount($theme) {
if ($user) {
### Display account settings:
// $content .= "<LI><A HREF=\"submission.php\">moderate submissions</A> (". submission_count() .")</LI>";
$content .= "<LI><A HREF=\"submission.php\">moderate submissions</A> (". submission_count() .")</LI>";
$theme->box("$user->userid's account", "$content");
}
}

44
submission.inc Normal file
View File

@ -0,0 +1,44 @@
<?
function submission_count() {
$result = db_query("SELECT COUNT(id) FROM submissions");
return ($result) ? mysql_result($result, 0) : 0;
}
function submission_score($id) {
$result = db_query("SELECT score FROM submissions WHERE id = $id");
return ($result) ? mysql_result($result, 0) : 0;
}
function submission_vote($id, $vote) {
global $user;
include "config.inc";
if (!$user->getHistory("s$id")) {
### Update submission table:
db_query("UPDATE submissions SET score = score $vote, votes = votes + 1 WHERE id = $id");
### Update user record:
$user->setHistory("s$id", "$vote"); // s = submission
$user->save();
### Update story and submission table (if required):
$result = db_query("SELECT * FROM submissions WHERE id = $id");
if ($submission = db_fetch_object($result)) {
if ($submission->score >= $submission_post_threshold) {
### Hide submission from submission table:
db_query("UPDATE submissions SET status = 0 WHERE id = $id");
### Copy sumbission to news table:
db_query("INSERT INTO stories (aid, subject, time, abstract, article, category, informant) VALUES ('$submission->uid', '". addslashes($submission->subject) ."', '$submission->timestamp', '". addslashes($submission->abstract) ."', '". addslashes($submission->article) ."', '". addslashes($submission->category) ."', '". addslashes($submission->uname) ."')");
}
if ($submission->score <= $submission_dump_threshold) {
### Hide submission from submission table:
db_query("UPDATE submissions SET status = 0 WHERE id = $id");
}
}
}
}
?>

79
submission.php Normal file
View File

@ -0,0 +1,79 @@
<?
include "functions.inc";
include "theme.inc";
include "submission.inc";
function submission_displayMain() {
global $PHP_SELF, $theme, $user;
### Perform query:
$result = db_query("SELECT * FROM submissions WHERE status = 1");
$content .= "<P>Anyone who happens by, and has some news or some thoughts they'd like to share, can <A HREF=\"submit.php\">submit</A> new content for consideration. After someone has submitted something, their story is added to a queue. All registered users can access this list of pending stories, that is, stories that have been submitted, but do not yet appear on the public front page. Those registered users can vote whether they think the story should be posted or not. When enough people vote to post a story, the story is pushed over the threshold and up it goes on the public page. On the other hand, when too many people voted to drop a story, the story will be trashed.</P><P>Basically, this means that you, the community, are truly the editors of this site as you have the final decision on the content of this site. It's you judging the overall quality of a story. But remember, vote on whether the story is interesting, not on whether you agree with it or not. If the story goes up, you can disagree all you want, but don't vote 'no' because you think the ideas expressed are wrong. Instead, vote 'no' when you think the story is plain boring.</P>";
$content .= "<TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"2\">\n";
$content .= " <TR BGCOLOR=\"$bgcolor1\"><TH>Subject</TH><TH>Category</TH><TH>Date</TH><TH>Author</TH><TH>Score</TH></TR>\n";
while ($submission = db_fetch_object($result)) {
if ($user->getHistory("s$submission->id")) $content .= " <TR><TD WIDTH=\"100%\"><A HREF=\"$PHP_SELF?op=view&id=$submission->id\">$submission->subject</A></TD><TD>$submission->category</TD><TD NOWRAP>". date("Y-m-d h:m:s", $submission->timestamp) ."</TD><TD NOWRAP>$submission->uname</TD><TD ALIGN=\"center\">". submission_score($submission->id) ."</TD></TR>\n";
else $content .= " <TR><TD WIDTH=\"100%\"><A HREF=\"$PHP_SELF?op=view&id=$submission->id\">$submission->subject</A></TD><TD>$submission->category</TD><TD NOWRAP>". date("Y-m-d h:m:s", $submission->timestamp) ."</TD><TD NOWRAP>$submission->uname</TD><TD ALIGN=\"center\"><A HREF=\"$PHP_SELF?op=view&id=$submission->id\">vote</A></TD></TR>\n";
}
$content .= "</TABLE>\n";
$theme->header();
$theme->box("Pending stories", $content);
$theme->footer();
}
function submission_displayItem($id) {
global $PHP_SELF, $theme, $user;
include "config.inc";
$result = mysql_query("SELECT * FROM submissions WHERE id = $id");
$submission = db_fetch_object($result);
$theme->header();
$theme->article("", $submission->uname, $submission->time, $submission->subject, "", $submission->abstract, "", $submission->article, "[ <A HREF=\"$PHP_SELF\"><FONT COLOR=\"$theme->hlcolor2\">back</FONT></A> ]");
if ($vote = $user->getHistory("s$submission->id")) {
print "<P><B>You voted `$vote' for this story!</B><BR><B>Score:</B> $submission->score<BR><B>Votes:</B> $submission->votes</P>\n";
print "<P>\n";
print "<B>Other people voted:</B><BR>\n";
$result = db_query("SELECT * FROM users WHERE history LIKE '%s$submission->id%'");
while ($account = db_fetch_object($result)) {
print "<A HREF=\"account.php?op=userinfo&uname=$account->userid\">$account->userid</A> voted `". getHistory($account->history, "s$submission->id") ."'.<BR>";
}
}
else {
print "<FORM ACTION=\"$PHP_SELF\" METHOD=\"post\">\n";
print " <SELECT NAME=\"vote\">\n";
foreach ($submission_votes as $key=>$value) {
print " <OPTION VALUE=\"$value\">". $key ."</OPTION>\n";
}
print " </SELECT>\n";
print " <INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$submission->id\">\n";
print " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Vote\">\n";
print "</FORM>\n";
}
$theme->footer();
}
if ($user) {
switch($op) {
case "view":
submission_displayItem($id);
break;
case "Vote";
submission_vote($id, $vote);
submission_displayItem($id);
break;
default:
submission_displayMain();
break;
}
}
?>

View File

@ -80,7 +80,7 @@ function PreviewStory($name, $address, $subject, $abstract, $story, $category) {
<P>
<B>Subject:</B><BR>
<INPUT TYPE="text" NAME="subject" SIZE="50" VALUE="<? print $subject; ?>"><BR>
<INPUT TYPE="text" NAME="subject" SIZE="50" VALUE="<? print stripslashes($subject); ?>"><BR>
<FONT SIZE="2"><I>Bad subjects are 'Check this out!' or 'An article'. Be descriptive, clear and simple!</I></FONT>
</P>
@ -98,13 +98,13 @@ function PreviewStory($name, $address, $subject, $abstract, $story, $category) {
<P>
<B>Abstract:</B></I><BR>
<TEXTAREA WRAP="virtual" COLS="50" ROWS="8" NAME="abstract"><? print $abstract; ?></TEXTAREA><BR>
<TEXTAREA WRAP="virtual" COLS="50" ROWS="8" NAME="abstract"><? print stripslashes($abstract); ?></TEXTAREA><BR>
<FONT SIZE="2"><I>HTML is nice and dandy, but double check those URLs and HTML tags!</FONT>
</P>
<P>
<B>Extended story:</B></I><BR>
<TEXTAREA WRAP="virtual" COLS="50" ROWS="15" NAME="story"><? print $story; ?></TEXTAREA><BR>
<TEXTAREA WRAP="virtual" COLS="50" ROWS="15" NAME="story"><? print stripslashes($story); ?></TEXTAREA><BR>
<FONT SIZE="2"><I>HTML is nice and dandy, but double check those URLs and HTML tags!</FONT>
</P>
@ -128,11 +128,10 @@ function submitStory($name, $address, $subject, $abstract, $article, $category)
### Display confirmation message:
include "theme.inc";
$theme->header();
$theme->box("Thanks for your submission.", "Thanks for your submission. The gnomes in our basement will frown at it, poke at it, and - if you are lucky - even post it!");
$theme->box("Thanks for your submission.", "Thanks for your submission. The submission moderators in our basement will frown at it, poke at it, and vote for it!");
$theme->footer();
### Add submission to queue:
dbconnect();
if ($user) {
$uid = $user->id;
$name = $user->userid;
@ -141,12 +140,8 @@ function submitStory($name, $address, $subject, $abstract, $article, $category)
$uid = -1;
$name = $anonymous;
}
$subject = stripslashes(FixQuotes(check_html($subject, "nohtml")));
$abstract = stripslashes(FixQuotes(check_html($abstract)));
$article = stripslashes(FixQuotes(check_html($article)));
$result = mysql_query("INSERT INTO queue VALUES (NULL, '$uid', '$name', '$subject', '$article', '". time() ."', '$category', '$abstract', 0, 0)");
db_query("INSERT INTO submissions (uid, uname, subject, article, timestamp, category, abstract, score, votes) VALUES ('$uid', '$name', '$subject', '$article', '". time() ."', '$category', '$abstract', '0', '0')");
### Send notification mail (if required):
if ($notify) {

View File

@ -8,9 +8,17 @@ class User {
dbconnect();
$result = mysql_query("SELECT * FROM users WHERE LOWER(userid)=LOWER('$userid') && passwd=PASSWORD('$passwd') && STATUS=0") or die(sprintf("Critical error at line %d in %s: %s", __LINE__, __FILE__, mysql_error()));
if (mysql_num_rows($result) == 1) {
foreach (mysql_fetch_array($result) as $key=>$value) { $this->$key = $value; }
foreach (mysql_fetch_row($result) as $key=>$value) { $field = mysql_field_name($result, $key); $this->$field = stripslashes($value); $this->field[] = $field; }
}
}
function save() {
### Compose query to update user record:
$query .= "UPDATE users SET ";
foreach ($this->field as $key=>$field) { $value = $this->$field; $query .= "$field = '". addslashes($value) ."', "; }
$query .= " id = $this->id WHERE id = $this->id";
### Perform query:
mysql_query($query);
}
function update() {
dbconnect();
$result = mysql_query("SELECT * FROM users WHERE id=$this->id") or die(sprintf("Critical error at line %d in %s: %s", __LINE__, __FILE__, mysql_error()));
@ -20,6 +28,7 @@ class User {
}
function valid($access=0) {
if (!empty($this->userid)) {
$this->update(); // synchronisation purpose
$this->last_access = time();
$this->last_host = (!empty($GLOBALS[REMOTE_HOST]) ? $GLOBALS[REMOTE_HOST] : $GLOBALS[REMOTE_ADDR] );
dbconnect();
@ -28,5 +37,46 @@ class User {
}
return 0;
}
function getHistory($field) {
return getHistory($this->history, $field);
}
function setHistory($field, $value) {
$this->history = setHistory($this->history, $field, $value);
}
}
function getHistory($history, $field) {
$data = explode(";", $history);
for (reset($data); current($data); next($data)) {
$entry = explode(":", current($data));
if (reset($entry) == $field) $rval = end($entry);
}
return $rval;
}
function setHistory($history, $field, $value) {
if (!$value) {
### remove entry:
$data = explode(";", $history);
for (reset($data); current($data); next($data)) {
$entry = explode(":", current($data));
if ($entry[0] != $field) $rval .= "$entry[0]:$entry[1];";
}
}
else if (strstr($history, "$field:")) {
### found: update exsisting entry:
$data = explode(";", $history);
for (reset($data); current($data); next($data)) {
$entry = explode(":", current($data));
if ($entry[0] == $field) $entry[1] = $value;
$rval .= "$entry[0]:$entry[1];";
}
}
else {
### not found: add new entry:
$rval = "$history$field:$value;";
}
return $rval;
}
?>