comment_id = $comment_id; } } // }}} class Comment { // {{{ public function Comment($row) { $this->owner_id = $row['user_id']; $this->owner_name = $row['user_name']; $this->comment = $row['comment']; $this->comment_id = $row['comment_id']; $this->image_id = $row['image_id']; $this->poster_ip = $row['poster_ip']; } public function to_html($trim=false) { global $user; $i_uid = int_escape($this->owner_id); $h_name = html_escape($this->owner_name); $h_poster_ip = html_escape($this->poster_ip); $h_comment = ($trim ? substr(bbcode_to_text($this->comment), 0, 50)."..." : bbcode_to_html($this->comment)); $i_comment_id = int_escape($this->comment_id); $i_image_id = int_escape($this->image_id); $h_userlink = "$h_name"; $h_dellink = $user->is_admin() ? "
($h_poster_ip, Del)" : ""; $h_imagelink = $trim ? ">>>\n" : ""; return "

$h_userlink: $h_comment $h_imagelink $h_dellink

"; } } // }}} class CommentList extends Extension { // event handler {{{ public function receive_event($event) { if(is_a($event, 'InitExtEvent')) { global $config; if($config->get_int("ext_comments_version") < 1) { $this->install(); } } if(is_a($event, 'PageRequestEvent') && ($event->page == "comment")) { if($event->get_arg(0) == "add") { $this->add_comment_wrapper($_POST['image_id'], $_POST['comment']); } else if($event->get_arg(0) == "delete") { global $user; global $page; if($user->is_admin()) { // FIXME: post, not args if($event->count_args() == 3) { send_event(new CommentDeletionEvent($event->get_arg(1))); $page->set_mode("redirect"); $page->set_redirect(make_link("post/view/".$event->get_arg(2))); } } else { // FIXME: denied message } } else if($event->get_arg(0) == "rss") { $this->build_rss(); } else if($event->get_arg(0) == "list") { $this->build_page($event->get_arg(1)); } } if(is_a($event, 'PageRequestEvent') && ($event->page == "index")) { global $page; global $config; if($config->get_int("comment_count") > 0) { $page->add_side_block(new Block("Comments", $this->build_recent_comments()), 50); } } if(is_a($event, 'DisplayingImageEvent')) { global $page; $page->add_main_block(new Block("Comments", $this->build_image_comments($event->image->id). $this->build_postbox($event->image->id)), 50); } if(is_a($event, 'ImageDeletionEvent')) { $this->delete_comments($event->image->id); } if(is_a($event, 'CommentDeletionEvent')) { $this->delete_comment($event->comment_id); } if(is_a($event, 'SetupBuildingEvent')) { $sb = new SetupBlock("Comment Options"); $sb->add_label("Allow anonymous comments "); $sb->add_bool_option("comment_anon"); $sb->add_label("
Limit to "); $sb->add_int_option("comment_limit"); $sb->add_label(" comments per "); $sb->add_int_option("comment_window"); $sb->add_label(" minutes"); $sb->add_label("
Show "); $sb->add_int_option("comment_count"); $sb->add_label(" recent comments on the index"); $sb->add_label("
Akismet Key "); $sb->add_text_option("comment_wordpress_key"); $event->panel->add_main_block($sb); } if(is_a($event, 'ConfigSaveEvent')) { $event->config->set_bool_from_post("comment_anon"); $event->config->set_int_from_post("comment_limit"); $event->config->set_int_from_post("comment_window"); $event->config->set_int_from_post("comment_count"); $event->config->set_string_from_post("comment_wordpress_key"); } } // }}} // installer {{{ protected function install() { global $database; global $config; $database->db->Execute("CREATE TABLE `comments` ( `id` int(11) NOT NULL auto_increment, `image_id` int(11) NOT NULL, `owner_id` int(11) NOT NULL, `owner_ip` char(16) NOT NULL, `posted` datetime default NULL, `comment` text NOT NULL, PRIMARY KEY (`id`), KEY `comments_image_id` (`image_id`) )"); $config->set_int("ext_comments_version", 1); } // }}} // page building {{{ private function build_rss() { global $page; $page->set_mode("data"); $page->set_type("application/rss+xml"); $rss = "moo"; // FIXME $page->set_data($rss); } private function build_page($current_page) { global $page; global $database; if(is_null($current_page) || $current_page <= 0) { $current_page = 1; } $threads_per_page = 10; $start = $threads_per_page * ($current_page - 1); $get_threads = " SELECT image_id,MAX(posted) AS latest FROM comments GROUP BY image_id ORDER BY latest DESC LIMIT ?,? "; $result = $database->db->Execute($get_threads, array($start, $threads_per_page)); $total_pages = (int)($database->db->GetOne("SELECT COUNT(distinct image_id) AS count FROM comments") / 10); $page->set_title("Comments"); $page->set_heading("Comments"); $page->add_side_block(new Block("Navigation", $this->build_navigation($current_page, $total_pages))); $page->add_main_block(new Paginator("comment/list", null, $current_page, $total_pages), 90); $n = 10; while(!$result->EOF) { $image = $database->get_image($result->fields["image_id"]); $html = "
"; $html .= "
" . build_thumb_html($image) . "
"; $html .= $this->build_image_comments($image->id); $html .= "
"; $html .= "
".($this->build_postbox($image->id))."
"; $page->add_main_block(new Block("{$image->id}: ".($image->get_tag_list()), $html), $n); $n += 1; $result->MoveNext(); } } private function build_navigation($page_number, $total_pages) { $prev = $page_number - 1; $next = $page_number + 1; $h_prev = ($page_number <= 1) ? "Prev" : "Prev"; $h_index = "Index"; $h_next = ($page_number >= $total_pages) ? "Next" : "Next"; return "$h_prev | $h_index | $h_next"; } private function build_image_comments($image_id) { global $config; $i_image_id = int_escape($image_id); $html = "
"; $html .= $this->query_to_html(" SELECT users.id as user_id, users.name as user_name, comments.comment as comment, comments.id as comment_id, comments.image_id as image_id, comments.owner_ip as poster_ip FROM comments LEFT JOIN users ON comments.owner_id=users.id WHERE comments.image_id=? ORDER BY comments.id ASC ", array($i_image_id), false); $html .= "
"; return $html; } private function build_recent_comments() { global $config; $html = $this->query_to_html(" SELECT users.id as user_id, users.name as user_name, comments.comment as comment, comments.id as comment_id, comments.image_id as image_id, comments.owner_ip as poster_ip FROM comments LEFT JOIN users ON comments.owner_id=users.id ORDER BY comments.id DESC LIMIT ? ", array($config->get_int('comment_count')), true); $html .= "

Full List >>>"; return $html; } private function build_postbox($image_id) { if($this->can_comment()) { $i_image_id = int_escape($image_id); return "


"; } else { return "

You need to create an account before you can comment

"; } } private function query_to_html($query, $args, $trim=false) { global $database; global $config; $html = ""; $result = $database->db->Execute($query, $args); while(!$result->EOF) { $comment = new Comment($result->fields); $html .= $comment->to_html($trim); $result->MoveNext(); } return $html; } // }}} // add / remove / edit comments {{{ private function is_comment_limit_hit() { global $user; global $config; global $database; $window = int_escape($config->get_int('comment_window')); $max = int_escape($config->get_int('comment_limit')); $result = $database->db->Execute("SELECT * FROM comments WHERE owner_ip = ? ". "AND posted > date_sub(now(), interval ? minute)", Array($_SERVER['REMOTE_ADDR'], $window)); $recent_comments = $result->RecordCount(); return ($recent_comments >= $max); } private function is_spam($text) { global $user; global $config; if(strlen($config->get_string('comment_wordpress_key')) == 0) { return false; } else { $comment = array( 'author' => $user->name, 'email' => $user->email, 'website' => '', 'body' => $text, 'permalink' => '', ); $akismet = new Akismet( 'http://www.yourdomain.com/', $config->get_string('comment_wordpress_key'), $comment); if($akismet->errorsExist()) { return false; } else { return $akismet->isSpam(); } } } private function can_comment() { global $config; global $user; return ($config->get_bool('comment_anon') || !$user->is_anonymous()); } private function add_comment_wrapper($image_id, $comment) { global $user; global $database; global $config; global $page; $page->set_title("Error"); $page->set_heading("Error"); $page->add_side_block(new NavBlock()); if(!$config->get_bool('comment_anon') && $user->is_anonymous()) { $page->add_main_block(new Block("Permission Denied", "Anonymous posting has been disabled")); } else if(trim($comment) == "") { $page->add_main_block(new Block("Comment Empty", "Comments need text...")); } else if($this->is_comment_limit_hit()) { $page->add_main_block(new Block("Comment Limit Hit", "You've posted several comments recently; wait a minute and try again...")); } else if($this->is_spam($comment)) { $page->add_main_block(new Block("Spam Detected", "Akismet thinks that your comment is spam. Try rewriting the comment?")); } else { $database->db->Execute( "INSERT INTO comments(image_id, owner_id, owner_ip, posted, comment) ". "VALUES(?, ?, ?, now(), ?)", array($image_id, $user->id, $_SERVER['REMOTE_ADDR'], $comment)); $page->set_mode("redirect"); $page->set_redirect(make_link("post/view/".int_escape($image_id))); } } private function delete_comments($image_id) { global $database; $database->db->Execute("DELETE FROM comments WHERE image_id=?", array($image_id)); } private function delete_comment($comment_id) { global $database; $database->db->Execute("DELETE FROM comments WHERE id=?", array($comment_id)); } // }}} } add_event_listener(new CommentList()); ?>