summaryrefslogtreecommitdiff
path: root/modules/comment
diff options
context:
space:
mode:
authorTristan Zur <tzur@webserver.ccwn.org>2015-06-10 20:55:53 +0200
committerTristan Zur <tzur@webserver.ccwn.org>2015-06-10 20:55:53 +0200
commit406abd7c4df1ace2cd3e4e17159e8941a2e8c0c4 (patch)
treea324be16021f44f2fd6d55e609f47024e945b1db /modules/comment
Initial import
Diffstat (limited to 'modules/comment')
-rw-r--r--modules/comment/controllers/admin_comments.php60
-rw-r--r--modules/comment/controllers/admin_manage_comments.php144
-rw-r--r--modules/comment/controllers/comments.php81
-rw-r--r--modules/comment/css/comment.css45
-rw-r--r--modules/comment/helpers/comment.php71
-rw-r--r--modules/comment/helpers/comment_block.php39
-rw-r--r--modules/comment/helpers/comment_event.php97
-rw-r--r--modules/comment/helpers/comment_installer.php118
-rw-r--r--modules/comment/helpers/comment_rest.php74
-rw-r--r--modules/comment/helpers/comment_rss.php92
-rw-r--r--modules/comment/helpers/comment_theme.php46
-rw-r--r--modules/comment/helpers/comments_rest.php62
-rw-r--r--modules/comment/helpers/item_comments_rest.php50
-rw-r--r--modules/comment/js/comment.js45
-rw-r--r--modules/comment/models/comment.php194
-rw-r--r--modules/comment/module.info7
-rw-r--r--modules/comment/views/admin_block_recent_comments.html.php23
-rw-r--r--modules/comment/views/admin_comments.html.php7
-rw-r--r--modules/comment/views/admin_manage_comments.html.php46
-rw-r--r--modules/comment/views/admin_manage_comments_queue.html.php157
-rw-r--r--modules/comment/views/comment.html.php25
-rw-r--r--modules/comment/views/comment.mrss.php43
-rw-r--r--modules/comment/views/comments.html.php56
-rw-r--r--modules/comment/views/user_profile_comments.html.php20
24 files changed, 1602 insertions, 0 deletions
diff --git a/modules/comment/controllers/admin_comments.php b/modules/comment/controllers/admin_comments.php
new file mode 100644
index 0000000..3018340
--- /dev/null
+++ b/modules/comment/controllers/admin_comments.php
@@ -0,0 +1,60 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Admin_Comments_Controller extends Admin_Controller {
+ public function index() {
+ $view = new Admin_View("admin.html");
+ $view->page_title = t("Comment settings");
+ $view->content = new View("admin_comments.html");
+ $view->content->form = $this->_get_admin_form();
+ print $view;
+ }
+
+ public function save() {
+ access::verify_csrf();
+ $form = $this->_get_admin_form();
+ $form->validate();
+ module::set_var("comment", "access_permissions",
+ $form->comment_settings->access_permissions->value);
+ module::set_var("comment", "rss_visible",
+ $form->comment_settings->rss_visible->value);
+ message::success(t("Comment settings updated"));
+ url::redirect("admin/comments");
+ }
+
+ private function _get_admin_form() {
+ $form = new Forge("admin/comments/save", "", "post",
+ array("id" => "g-comments-admin-form"));
+ $comment_settings = $form->group("comment_settings")->label(t("Permissions"));
+ $comment_settings->dropdown("access_permissions")
+ ->label(t("Who can leave comments?"))
+ ->options(array("everybody" => t("Everybody"),
+ "registered_users" => t("Only registered users")))
+ ->selected(module::get_var("comment", "access_permissions"));
+ $comment_settings->dropdown("rss_visible")
+ ->label(t("Which RSS feeds can users see?"))
+ ->options(array("all" => t("All comment feeds"),
+ "newest" => t("New comments feed only"),
+ "per_item" => t("Comments on photos, movies and albums only")))
+ ->selected(module::get_var("comment", "rss_visible"));
+ $comment_settings->submit("save")->value(t("Save"));
+ return $form;
+ }
+}
+
diff --git a/modules/comment/controllers/admin_manage_comments.php b/modules/comment/controllers/admin_manage_comments.php
new file mode 100644
index 0000000..ef31c95
--- /dev/null
+++ b/modules/comment/controllers/admin_manage_comments.php
@@ -0,0 +1,144 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Admin_Manage_Comments_Controller extends Admin_Controller {
+ private static $items_per_page = 20;
+
+ public function index() {
+ // Get rid of old deleted/spam comments once in a while
+ db::build()
+ ->delete("comments")
+ ->where("state", "IN", array("deleted", "spam"))
+ ->where("updated", "<", db::expr("UNIX_TIMESTAMP() - 86400 * 7"))
+ ->execute();
+
+ $view = new Admin_View("admin.html");
+ $view->content = new View("admin_manage_comments.html");
+ $view->content->menu = $this->_menu($this->_counts());
+ print $view;
+ }
+
+ public function menu_labels() {
+ $menu = $this->_menu($this->_counts());
+ json::reply(array((string) $menu->get("unpublished")->label,
+ (string) $menu->get("published")->label,
+ (string) $menu->get("spam")->label,
+ (string) $menu->get("deleted")->label));
+ }
+
+ public function queue($state) {
+ $page = max(Input::instance()->get("page"), 1);
+
+ $view = new Gallery_View("admin_manage_comments_queue.html");
+ $view->counts = $this->_counts();
+ $view->menu = $this->_menu($view->counts);
+ $view->state = $state;
+ $view->comments = ORM::factory("comment")
+ ->order_by("created", "DESC")
+ ->order_by("id", "DESC")
+ ->where("state", "=", $state)
+ ->limit(self::$items_per_page)
+ ->offset(($page - 1) * self::$items_per_page)
+ ->find_all();
+
+ // This view is not themed so we can't use $theme->url() in the view and have to
+ // reproduce Gallery_View::url() logic here.
+ $atn = theme::$admin_theme_name;
+ $view->fallback_avatar_url = url::abs_file("themes/$atn/images/avatar.jpg");
+
+ $view->page = $page;
+ $view->page_type = "collection";
+ $view->page_subtype = "admin_comments";
+ $view->page_size = self::$items_per_page;
+ $view->children_count = $this->_counts()->$state;
+ $view->max_pages = ceil($view->children_count / $view->page_size);
+
+ // Also we want to use $theme->paginator() so we need a dummy theme
+ $view->theme = $view;
+
+ print $view;
+ }
+
+ private function _menu($counts) {
+ return Menu::factory("root")
+ ->append(Menu::factory("link")
+ ->id("unpublished")
+ ->label(t2("Awaiting Moderation (%count)",
+ "Awaiting Moderation (%count)",
+ $counts->unpublished))
+ ->url(url::site("admin/manage_comments/queue/unpublished")))
+ ->append(Menu::factory("link")
+ ->id("published")
+ ->label(t2("Approved (%count)",
+ "Approved (%count)",
+ $counts->published))
+ ->url(url::site("admin/manage_comments/queue/published")))
+ ->append(Menu::factory("link")
+ ->id("spam")
+ ->label(t2("Spam (%count)",
+ "Spam (%count)",
+ $counts->spam))
+ ->url(url::site("admin/manage_comments/queue/spam")))
+ ->append(Menu::factory("link")
+ ->id("deleted")
+ ->label(t2("Recently Deleted (%count)",
+ "Recently Deleted (%count)",
+ $counts->deleted))
+ ->url(url::site("admin/manage_comments/queue/deleted")));
+ }
+
+ private function _counts() {
+ $counts = new stdClass();
+ $counts->unpublished = 0;
+ $counts->published = 0;
+ $counts->spam = 0;
+ $counts->deleted = 0;
+ foreach (db::build()
+ ->select("state")
+ ->select(array("c" => 'COUNT("*")'))
+ ->from("comments")
+ ->group_by("state")
+ ->execute() as $row) {
+ $counts->{$row->state} = $row->c;
+ }
+ return $counts;
+ }
+
+ public function set_state($id, $state) {
+ access::verify_csrf();
+
+ $comment = ORM::factory("comment", $id);
+ $orig = clone $comment;
+ if ($comment->loaded()) {
+ $comment->state = $state;
+ $comment->save();
+ }
+ }
+
+ public function delete_all_spam() {
+ access::verify_csrf();
+
+ db::build()
+ ->delete("comments")
+ ->where("state", "=", "spam")
+ ->execute();
+ url::redirect("admin/manage_comments/queue/spam");
+ }
+}
+
diff --git a/modules/comment/controllers/comments.php b/modules/comment/controllers/comments.php
new file mode 100644
index 0000000..64aa0b4
--- /dev/null
+++ b/modules/comment/controllers/comments.php
@@ -0,0 +1,81 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Comments_Controller extends Controller {
+ /**
+ * Add a new comment to the collection.
+ */
+ public function create($id) {
+ $item = ORM::factory("item", $id);
+ access::required("view", $item);
+ if (!comment::can_comment()) {
+ access::forbidden();
+ }
+
+ $form = comment::get_add_form($item);
+ try {
+ $valid = $form->validate();
+ $comment = ORM::factory("comment");
+ $comment->item_id = $id;
+ $comment->author_id = identity::active_user()->id;
+ $comment->text = $form->add_comment->text->value;
+ $comment->guest_name = $form->add_comment->inputs["name"]->value;
+ $comment->guest_email = $form->add_comment->email->value;
+ $comment->guest_url = $form->add_comment->url->value;
+ $comment->validate();
+ } catch (ORM_Validation_Exception $e) {
+ // Translate ORM validation errors into form error messages
+ foreach ($e->validation->errors() as $key => $error) {
+ switch ($key) {
+ case "guest_name": $key = "name"; break;
+ case "guest_email": $key = "email"; break;
+ case "guest_url": $key = "url"; break;
+ }
+ $form->add_comment->inputs[$key]->add_error($error, 1);
+ }
+ $valid = false;
+ }
+
+ if ($valid) {
+ $comment->save();
+ $view = new Theme_View("comment.html", "other", "comment-fragment");
+ $view->comment = $comment;
+
+ json::reply(array("result" => "success",
+ "view" => (string)$view,
+ "form" => (string)comment::get_add_form($item)));
+ } else {
+ $form = comment::prefill_add_form($form);
+ json::reply(array("result" => "error", "form" => (string)$form));
+ }
+ }
+
+ /**
+ * Present a form for adding a new comment to this item or editing an existing comment.
+ */
+ public function form_add($item_id) {
+ $item = ORM::factory("item", $item_id);
+ access::required("view", $item);
+ if (!comment::can_comment()) {
+ access::forbidden();
+ }
+
+ print comment::prefill_add_form(comment::get_add_form($item));
+ }
+}
diff --git a/modules/comment/css/comment.css b/modules/comment/css/comment.css
new file mode 100644
index 0000000..db096f2
--- /dev/null
+++ b/modules/comment/css/comment.css
@@ -0,0 +1,45 @@
+#g-content #g-comment-form {
+ margin-top: 2em;
+}
+
+#g-content #g-comments {
+ margin-top: 2em;
+ position: relative;
+}
+
+#g-content #g-comments ul li {
+ margin: 1em 0;
+}
+
+#g-content #g-comments .g-author {
+ border-bottom: 1px solid #ccc;
+ color: #999;
+ height: 32px;
+ line-height: 32px;
+}
+
+#g-content #g-comments ul li div {
+ padding: 0 8px 8px 43px;
+}
+
+#g-content #g-comments .g-avatar {
+ height: 32px;
+ margin-right: .4em;
+ width: 32px;
+}
+
+#g-add-comment {
+ position: absolute;
+ right: 0;
+ top: 2px;
+}
+
+#g-admin-comments-menu {
+ margin: 1em 0;
+}
+
+#g-admin-comments-menu a {
+ margin: 0;
+ padding: .2em .6em;
+}
+
diff --git a/modules/comment/helpers/comment.php b/modules/comment/helpers/comment.php
new file mode 100644
index 0000000..0d922eb
--- /dev/null
+++ b/modules/comment/helpers/comment.php
@@ -0,0 +1,71 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * This is the API for handling comments.
+ *
+ * Note: by design, this class does not do any permission checking.
+ */
+class comment_Core {
+ static function get_add_form($item) {
+ $form = new Forge("comments/create/{$item->id}", "", "post", array("id" => "g-comment-form"));
+ $group = $form->group("add_comment")->label(t("Add comment"));
+ $group->input("name")
+ ->label(t("Name"))
+ ->id("g-author")
+ ->error_messages("required", t("You must enter a name for yourself"));
+ $group->input("email")
+ ->label(t("Email (hidden)"))
+ ->id("g-email")
+ ->error_messages("required", t("You must enter a valid email address"))
+ ->error_messages("invalid", t("You must enter a valid email address"));
+ $group->input("url")
+ ->label(t("Website (hidden)"))
+ ->id("g-url")
+ ->error_messages("url", t("You must enter a valid url"));
+ $group->textarea("text")
+ ->label(t("Comment"))
+ ->id("g-text")
+ ->error_messages("required", t("You must enter a comment"));
+ $group->hidden("item_id")->value($item->id);
+ module::event("comment_add_form", $form);
+ module::event("captcha_protect_form", $form);
+ $group->submit("")->value(t("Add"))->class("ui-state-default ui-corner-all");
+
+ return $form;
+ }
+
+ static function prefill_add_form($form) {
+ $active = identity::active_user();
+ if (!$active->guest) {
+ $group = $form->add_comment;
+ $group->inputs["name"]->value($active->full_name)->disabled("disabled");
+ $group->email->value($active->email)->disabled("disabled");
+ $group->url->value($active->url)->disabled("disabled");
+ }
+ return $form;
+ }
+
+ static function can_comment() {
+ return !identity::active_user()->guest ||
+ module::get_var("comment", "access_permissions") == "everybody";
+ }
+}
+
diff --git a/modules/comment/helpers/comment_block.php b/modules/comment/helpers/comment_block.php
new file mode 100644
index 0000000..b602595
--- /dev/null
+++ b/modules/comment/helpers/comment_block.php
@@ -0,0 +1,39 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class comment_block_Core {
+ static function get_admin_list() {
+ return array("recent_comments" => t("Recent comments"));
+ }
+
+ static function get($block_id) {
+ $block = new Block();
+ switch ($block_id) {
+ case "recent_comments":
+ $block->css_id = "g-recent-comments";
+ $block->title = t("Recent comments");
+ $block->content = new View("admin_block_recent_comments.html");
+ $block->content->comments =
+ ORM::factory("comment")->order_by("created", "DESC")->limit(5)->find_all();
+ break;
+ }
+
+ return $block;
+ }
+} \ No newline at end of file
diff --git a/modules/comment/helpers/comment_event.php b/modules/comment/helpers/comment_event.php
new file mode 100644
index 0000000..f73e545
--- /dev/null
+++ b/modules/comment/helpers/comment_event.php
@@ -0,0 +1,97 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class comment_event_Core {
+ static function item_deleted($item) {
+ db::build()
+ ->delete("comments")
+ ->where("item_id", "=", $item->id)
+ ->execute();
+ }
+
+ static function user_deleted($user) {
+ $guest = identity::guest();
+ if (!empty($guest)) { // could be empty if there is not identity provider
+ db::build()
+ ->update("comments")
+ ->set("author_id", $guest->id)
+ ->set("guest_email", null)
+ ->set("guest_name", "guest")
+ ->set("guest_url", null)
+ ->where("author_id", "=", $user->id)
+ ->execute();
+ }
+ }
+
+ static function identity_provider_changed($old_provider, $new_provider) {
+ $guest = identity::guest();
+ db::build()
+ ->update("comments")
+ ->set("author_id", $guest->id)
+ ->set("guest_email", null)
+ ->set("guest_name", "guest")
+ ->set("guest_url", null)
+ ->execute();
+ }
+
+ static function admin_menu($menu, $theme) {
+ $menu->get("settings_menu")
+ ->append(Menu::factory("link")
+ ->id("comment")
+ ->label(t("Comments"))
+ ->url(url::site("admin/comments")));
+
+ $menu->get("content_menu")
+ ->append(Menu::factory("link")
+ ->id("comments")
+ ->label(t("Comments"))
+ ->url(url::site("admin/manage_comments")));
+ }
+
+ static function photo_menu($menu, $theme) {
+ $menu
+ ->append(Menu::factory("link")
+ ->id("comments")
+ ->label(t("View comments on this item"))
+ ->url("#comments")
+ ->css_id("g-comments-link"));
+ }
+
+ static function item_index_data($item, $data) {
+ foreach (db::build()
+ ->select("text")
+ ->from("comments")
+ ->where("item_id", "=", $item->id)
+ ->execute() as $row) {
+ $data[] = $row->text;
+ }
+ }
+
+ static function show_user_profile($data) {
+ $view = new View("user_profile_comments.html");
+ $view->comments = ORM::factory("comment")
+ ->order_by("created", "DESC")
+ ->where("state", "=", "published")
+ ->where("author_id", "=", $data->user->id)
+ ->find_all();
+ if ($view->comments->count()) {
+ $data->content[] = (object)array("title" => t("Comments"), "view" => $view);
+ }
+ }
+}
diff --git a/modules/comment/helpers/comment_installer.php b/modules/comment/helpers/comment_installer.php
new file mode 100644
index 0000000..136f96e
--- /dev/null
+++ b/modules/comment/helpers/comment_installer.php
@@ -0,0 +1,118 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class comment_installer {
+ static function install() {
+ $db = Database::instance();
+ $db->query("CREATE TABLE IF NOT EXISTS {comments} (
+ `author_id` int(9) default NULL,
+ `created` int(9) NOT NULL,
+ `guest_email` varchar(128) default NULL,
+ `guest_name` varchar(128) default NULL,
+ `guest_url` varchar(255) default NULL,
+ `id` int(9) NOT NULL auto_increment,
+ `item_id` int(9) NOT NULL,
+ `server_http_accept_charset` varchar(64) default NULL,
+ `server_http_accept_encoding` varchar(64) default NULL,
+ `server_http_accept_language` varchar(64) default NULL,
+ `server_http_accept` varchar(128) default NULL,
+ `server_http_connection` varchar(64) default NULL,
+ `server_http_host` varchar(64) default NULL,
+ `server_http_referer` varchar(255) default NULL,
+ `server_http_user_agent` varchar(128) default NULL,
+ `server_query_string` varchar(64) default NULL,
+ `server_remote_addr` varchar(40) default NULL,
+ `server_remote_host` varchar(255) default NULL,
+ `server_remote_port` varchar(16) default NULL,
+ `state` varchar(15) default 'unpublished',
+ `text` text,
+ `updated` int(9) NOT NULL,
+ PRIMARY KEY (`id`))
+ DEFAULT CHARSET=utf8;");
+
+ module::set_var("comment", "spam_caught", 0);
+ module::set_var("comment", "access_permissions", "everybody");
+ module::set_var("comment", "rss_visible", "all");
+ }
+
+ static function upgrade($version) {
+ $db = Database::instance();
+ if ($version == 1) {
+ $db->query("ALTER TABLE {comments} CHANGE `state` `state` varchar(15) default 'unpublished'");
+ module::set_version("comment", $version = 2);
+ }
+
+ if ($version == 2) {
+ module::set_var("comment", "access_permissions", "everybody");
+ module::set_version("comment", $version = 3);
+ }
+
+ if ($version == 3) {
+ // 40 bytes for server_remote_addr is enough to swallow the longest
+ // representation of an IPv6 addy.
+ //
+ // 255 bytes for server_remote_host is enough to swallow the longest
+ // legit DNS entry, with a few bytes to spare.
+ $db->query(
+ "ALTER TABLE {comments} CHANGE `server_remote_addr` `server_remote_addr` varchar(40)");
+ $db->query(
+ "ALTER TABLE {comments} CHANGE `server_remote_host` `server_remote_host` varchar(255)");
+ module::set_version("comment", $version = 4);
+ }
+
+ if ($version == 4) {
+ module::set_var("comment", "rss_visible", "all");
+ module::set_version("comment", $version = 5);
+ }
+
+ // In version 5 we accidentally set the installer variable to rss_available when it should
+ // have been rss_visible. Migrate it over now, if necessary.
+ if ($version == 5) {
+ if (!module::get_var("comment", "rss_visible")) {
+ module::set_var("comment", "rss_visible", module::get_var("comment", "rss_available"));
+ }
+ module::clear_var("comment", "rss_available");
+ module::set_version("comment", $version = 6);
+ }
+
+ // In version 6 we accidentally left the install value of "rss_visible" to "both" when it
+ // should have been "all"
+ if ($version == 6) {
+ if (module::get_var("comment", "rss_visible") == "both") {
+ module::set_var("comment", "rss_visible", "all");
+ }
+ module::set_version("comment", $version = 7);
+ }
+ }
+
+ static function uninstall() {
+ $db = Database::instance();
+
+ // Notify listeners that we're deleting some data. This is probably going to be very
+ // inefficient for large uninstalls, and we could make it better by doing things like passing
+ // a SQL fragment through so that the listeners could use subselects. But by using a single,
+ // simple event API we lighten the load on module developers.
+ foreach (ORM::factory("item")
+ ->join("comments", "items.id", "comments.item_id")
+ ->find_all() as $item) {
+ module::event("item_related_update", $item);
+ }
+ $db->query("DROP TABLE IF EXISTS {comments};");
+ }
+}
diff --git a/modules/comment/helpers/comment_rest.php b/modules/comment/helpers/comment_rest.php
new file mode 100644
index 0000000..1971edc
--- /dev/null
+++ b/modules/comment/helpers/comment_rest.php
@@ -0,0 +1,74 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class comment_rest_Core {
+ static function get($request) {
+ $comment = rest::resolve($request->url);
+ access::required("view", $comment->item());
+
+ return array(
+ "url" => $request->url,
+ "entity" => $comment->as_restful_array(),
+ "relationships" => rest::relationships("comment", $comment));
+ }
+
+ static function put($request) {
+ // Only admins can edit comments, for now
+ if (!identity::active_user()->admin) {
+ access::forbidden();
+ }
+
+ $comment = rest::resolve($request->url);
+ $comment = ORM::factory("comment");
+ $comment->text = $request->params->text;
+ $comment->save();
+ }
+
+ static function delete($request) {
+ if (!identity::active_user()->admin) {
+ access::forbidden();
+ }
+
+ $comment = rest::resolve($request->url);
+ access::required("edit", $comment->item());
+
+ $comment->delete();
+ }
+
+ static function relationships($resource_type, $resource) {
+ switch ($resource_type) {
+ case "item":
+ return array(
+ "comments" => array(
+ "url" => rest::url("item_comments", $resource)));
+ }
+ }
+
+ static function resolve($id) {
+ $comment = ORM::factory("comment", $id);
+ if (!access::can("view", $comment->item())) {
+ throw new Kohana_404_Exception();
+ }
+ return $comment;
+ }
+
+ static function url($comment) {
+ return url::abs_site("rest/comment/{$comment->id}");
+ }
+}
diff --git a/modules/comment/helpers/comment_rss.php b/modules/comment/helpers/comment_rss.php
new file mode 100644
index 0000000..924710f
--- /dev/null
+++ b/modules/comment/helpers/comment_rss.php
@@ -0,0 +1,92 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+class comment_rss_Core {
+ static function feed_visible($feed_id) {
+ $visible = module::get_var("comment", "rss_visible");
+ if (!in_array($feed_id, array("newest", "per_item"))) {
+ return false;
+ }
+
+ return ($visible == "all" || $visible == $feed_id);
+ }
+
+ static function available_feeds($item, $tag) {
+ $feeds = array();
+
+ if (comment_rss::feed_visible("newest")) {
+ $feeds["comment/newest"] = t("All new comments");
+ }
+
+ if ($item && comment_rss::feed_visible("per_item")) {
+ $feeds["comment/per_item/$item->id"] =
+ t("Comments on %title", array("title" => html::purify($item->title)));
+ }
+ return $feeds;
+ }
+
+ static function feed($feed_id, $offset, $limit, $id) {
+ if (!comment_rss::feed_visible($feed_id)) {
+ return;
+ }
+
+ $comments = ORM::factory("comment")
+ ->viewable()
+ ->where("comments.state", "=", "published")
+ ->order_by("comments.created", "DESC");
+
+ if ($feed_id == "item") {
+ $item = ORM::factory("item", $id);
+ $comments
+ ->where("items.left_ptr", ">=", $item->left_ptr)
+ ->where("items.right_ptr", "<=", $item->right_ptr);
+ }
+
+ $feed = new stdClass();
+ $feed->view = "comment.mrss";
+ $feed->comments = array();
+ foreach ($comments->find_all($limit, $offset) as $comment) {
+ $item = $comment->item();
+ $feed->comments[] = new ArrayObject(
+ array("pub_date" => date("D, d M Y H:i:s O", $comment->created),
+ "text" => nl2br(html::purify($comment->text)),
+ "thumb_url" => $item->thumb_url(),
+ "thumb_height" => $item->thumb_height,
+ "thumb_width" => $item->thumb_width,
+ "item_uri" => url::abs_site("{$item->type}s/$item->id"),
+ "title" => (
+ ($item->id == item::root()->id) ?
+ html::purify($item->title) :
+ t("%site_title - %item_title",
+ array("site_title" => item::root()->title,
+ "item_title" => $item->title))),
+ "author" => html::clean($comment->author_name())),
+ ArrayObject::ARRAY_AS_PROPS);
+ }
+
+ $feed->max_pages = ceil($comments->count_all() / $limit);
+ $feed->title = html::purify(t("%site_title - Recent Comments",
+ array("site_title" => item::root()->title)));
+ $feed->uri = url::abs_site("albums/" . (empty($id) ? "1" : $id));
+ $feed->description = t("Recent comments");
+
+ return $feed;
+ }
+}
diff --git a/modules/comment/helpers/comment_theme.php b/modules/comment/helpers/comment_theme.php
new file mode 100644
index 0000000..1c2d7c5
--- /dev/null
+++ b/modules/comment/helpers/comment_theme.php
@@ -0,0 +1,46 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class comment_theme_Core {
+ static function head($theme) {
+ return $theme->css("comment.css")
+ . $theme->script("comment.js");
+ }
+
+ static function admin_head($theme) {
+ return $theme->css("comment.css");
+ }
+
+ static function photo_bottom($theme) {
+ $block = new Block;
+ $block->css_id = "g-comments";
+ $block->title = t("Comments");
+ $block->anchor = "comments";
+
+ $view = new View("comments.html");
+ $view->comments = ORM::factory("comment")
+ ->where("item_id", "=", $theme->item()->id)
+ ->where("state", "=", "published")
+ ->order_by("created", "ASC")
+ ->find_all();
+
+ $block->content = $view;
+ return $block;
+ }
+} \ No newline at end of file
diff --git a/modules/comment/helpers/comments_rest.php b/modules/comment/helpers/comments_rest.php
new file mode 100644
index 0000000..6fc86ad
--- /dev/null
+++ b/modules/comment/helpers/comments_rest.php
@@ -0,0 +1,62 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class comments_rest_Core {
+ /**
+ * Possible request parameters:
+ * start=#
+ * start at the Nth comment (zero based)
+ *
+ * num=#
+ * return up to N comments (max 100)
+ */
+ static function get($request) {
+ $comments = array();
+
+ $p = $request->params;
+ $num = isset($p->num) ? min((int)$p->num, 100) : 10;
+ $start = isset($p->start) ? (int)$p->start : 0;
+
+ foreach (ORM::factory("comment")->viewable()->find_all($num, $start) as $comment) {
+ $comments[] = rest::url("comment", $comment);
+ }
+ return array("url" => rest::url("comments"),
+ "members" => $comments);
+ }
+
+
+ static function post($request) {
+ $entity = $request->params->entity;
+
+ $item = rest::resolve($entity->item);
+ access::required("edit", $item);
+
+ $comment = ORM::factory("comment");
+ $comment->author_id = identity::active_user()->id;
+ $comment->item_id = $item->id;
+ $comment->text = $entity->text;
+ $comment->save();
+
+ return array("url" => rest::url("comment", $comment));
+ }
+
+ static function url() {
+ return url::abs_site("rest/comments");
+ }
+}
diff --git a/modules/comment/helpers/item_comments_rest.php b/modules/comment/helpers/item_comments_rest.php
new file mode 100644
index 0000000..f6f8930
--- /dev/null
+++ b/modules/comment/helpers/item_comments_rest.php
@@ -0,0 +1,50 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class item_comments_rest_Core {
+ static function get($request) {
+ $item = rest::resolve($request->url);
+ access::required("view", $item);
+
+ $comments = array();
+ foreach (ORM::factory("comment")
+ ->viewable()
+ ->where("item_id", "=", $item->id)
+ ->order_by("created", "DESC")
+ ->find_all() as $comment) {
+ $comments[] = rest::url("comment", $comment);
+ }
+
+ return array(
+ "url" => $request->url,
+ "members" => $comments);
+ }
+
+ static function resolve($id) {
+ $item = ORM::factory("item", $id);
+ if (!access::can("view", $item)) {
+ throw new Kohana_404_Exception();
+ }
+ return $item;
+ }
+
+ static function url($item) {
+ return url::abs_site("rest/item_comments/{$item->id}");
+ }
+}
diff --git a/modules/comment/js/comment.js b/modules/comment/js/comment.js
new file mode 100644
index 0000000..2487c5f
--- /dev/null
+++ b/modules/comment/js/comment.js
@@ -0,0 +1,45 @@
+$("document").ready(function() {
+ $("#g-add-comment").click(function(event) {
+ event.preventDefault();
+ if (!$("#g-comment-form").length) {
+ $.get($(this).attr("href"),
+ {},
+ function(data) {
+ $("#g-comment-detail").append(data);
+ ajaxify_comment_form();
+ $.scrollTo("#g-comment-form-anchor", 800);
+ });
+ }
+ });
+ $(".g-no-comments a").click(function(event) {
+ event.preventDefault();
+ if (!$("#g-comment-form").length) {
+ $.get($(this).attr("href"),
+ {},
+ function(data) {
+ $("#g-comment-detail").append(data);
+ ajaxify_comment_form();
+ });
+ $(".g-no-comments").remove();
+ }
+ });
+});
+
+function ajaxify_comment_form() {
+ $("#g-comments form").ajaxForm({
+ dataType: "json",
+ success: function(data) {
+ if (data.result == "success") {
+ $("#g-comments #g-comment-detail ul").append(data.view);
+ $("#g-comments #g-comment-detail ul li:last").effect("highlight", {color: "#cfc"}, 8000);
+ $("#g-comment-form").hide(2000).remove();
+ $("#g-no-comments").hide(2000);
+ } else {
+ if (data.form) {
+ $("#g-comments form").replaceWith(data.form);
+ ajaxify_comment_form();
+ }
+ }
+ }
+ });
+}
diff --git a/modules/comment/models/comment.php b/modules/comment/models/comment.php
new file mode 100644
index 0000000..62ab8bc
--- /dev/null
+++ b/modules/comment/models/comment.php
@@ -0,0 +1,194 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2013 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Comment_Model_Core extends ORM {
+ function item() {
+ return ORM::factory("item", $this->item_id);
+ }
+
+ function author() {
+ return identity::lookup_user($this->author_id);
+ }
+
+ function author_name() {
+ $author = $this->author();
+ if ($author->guest) {
+ return $this->guest_name;
+ } else {
+ return $author->display_name();
+ }
+ }
+
+ function author_email() {
+ $author = $this->author();
+ if ($author->guest) {
+ return $this->guest_email;
+ } else {
+ return $author->email;
+ }
+ }
+
+ function author_url() {
+ $author = $this->author();
+ if ($author->guest) {
+ return $this->guest_url;
+ } else {
+ return $author->url;
+ }
+ }
+
+ /**
+ * Add some custom per-instance rules.
+ */
+ public function validate(Validation $array=null) {
+ // validate() is recursive, only modify the rules on the outermost call.
+ if (!$array) {
+ $this->rules = array(
+ "guest_name" => array("callbacks" => array(array($this, "valid_author"))),
+ "guest_email" => array("callbacks" => array(array($this, "valid_email"))),
+ "guest_url" => array("rules" => array("url")),
+ "item_id" => array("callbacks" => array(array($this, "valid_item"))),
+ "state" => array("rules" => array("Comment_Model::valid_state")),
+ "text" => array("rules" => array("required")),
+ );
+ }
+
+ parent::validate($array);
+ }
+
+ /**
+ * @see ORM::save()
+ */
+ public function save() {
+ $this->updated = time();
+ if (!$this->loaded()) {
+ // New comment
+ $this->created = $this->updated;
+ if (empty($this->state)) {
+ $this->state = "published";
+ }
+
+ // These values are useful for spam fighting, so save them with the comment. It's painful to
+ // check each one to see if it already exists before setting it, so just use server_http_host
+ // as a semaphore for now (we use that in g2_import.php)
+ if (empty($this->server_http_host)) {
+ $input = Input::instance();
+ $this->server_http_accept = substr($input->server("HTTP_ACCEPT"), 0, 128);
+ $this->server_http_accept_charset = substr($input->server("HTTP_ACCEPT_CHARSET"), 0, 64);
+ $this->server_http_accept_encoding = substr($input->server("HTTP_ACCEPT_ENCODING"), 0, 64);
+ $this->server_http_accept_language = substr($input->server("HTTP_ACCEPT_LANGUAGE"), 0, 64);
+ $this->server_http_connection = substr($input->server("HTTP_CONNECTION"), 0, 64);
+ $this->server_http_host = substr($input->server("HTTP_HOST"), 0, 64);
+ $this->server_http_referer = substr($input->server("HTTP_REFERER"), 0, 255);
+ $this->server_http_user_agent = substr($input->server("HTTP_USER_AGENT"), 0, 128);
+ $this->server_query_string = substr($input->server("QUERY_STRING"), 0, 64);
+ $this->server_remote_addr = substr($input->server("REMOTE_ADDR"), 0, 40);
+ $this->server_remote_host = substr($input->server("REMOTE_HOST"), 0, 255);
+ $this->server_remote_port = substr($input->server("REMOTE_PORT"), 0, 16);
+ }
+
+ $visible_change = $this->state == "published";
+ parent::save();
+ module::event("comment_created", $this);
+ } else {
+ // Updated comment
+ $original = ORM::factory("comment", $this->id);
+ $visible_change = $original->state == "published" || $this->state == "published";
+ parent::save();
+ module::event("comment_updated", $original, $this);
+ }
+
+ // We only notify on the related items if we're making a visible change.
+ if ($visible_change) {
+ $item = $this->item();
+ module::event("item_related_update", $item);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a set of restrictions to any following queries to restrict access only to items
+ * viewable by the active user.
+ * @chainable
+ */
+ public function viewable() {
+ $this->join("items", "items.id", "comments.item_id");
+ return item::viewable($this);
+ }
+
+ /**
+ * Make sure we have an appropriate author id set, or a guest name.
+ */
+ public function valid_author(Validation $v, $field) {
+ if (empty($this->author_id)) {
+ $v->add_error("author_id", "required");
+ } else if ($this->author_id == identity::guest()->id && empty($this->guest_name)) {
+ $v->add_error("guest_name", "required");
+ }
+ }
+
+ /**
+ * Make sure that the email address is legal.
+ */
+ public function valid_email(Validation $v, $field) {
+ if ($this->author_id == identity::guest()->id) {
+ if (empty($v->guest_email)) {
+ $v->add_error("guest_email", "required");
+ } else if (!valid::email($v->guest_email)) {
+ $v->add_error("guest_email", "invalid");
+ }
+ }
+ }
+
+ /**
+ * Make sure we have a valid associated item id.
+ */
+ public function valid_item(Validation $v, $field) {
+ if (db::build()
+ ->from("items")
+ ->where("id", "=", $this->item_id)
+ ->count_records() != 1) {
+ $v->add_error("item_id", "invalid");
+ }
+ }
+
+ /**
+ * Make sure that the state is legal.
+ */
+ static function valid_state($value) {
+ return in_array($value, array("published", "unpublished", "spam", "deleted"));
+ }
+
+ /**
+ * Same as ORM::as_array() but convert id fields into their RESTful form.
+ */
+ public function as_restful_array() {
+ $data = array();
+ foreach ($this->as_array() as $key => $value) {
+ if (strncmp($key, "server_", 7)) {
+ $data[$key] = $value;
+ }
+ }
+ $data["item"] = rest::url("item", $this->item());
+ unset($data["item_id"]);
+
+ return $data;
+ }
+}
diff --git a/modules/comment/module.info b/modules/comment/module.info
new file mode 100644
index 0000000..b69379f
--- /dev/null
+++ b/modules/comment/module.info
@@ -0,0 +1,7 @@
+name = "Comments"
+description = "Allows users and guests to leave comments on photos and albums."
+version = 7
+author_name = "Gallery Team"
+author_url = "http://codex.galleryproject.org/Gallery:Team"
+info_url = "http://codex.galleryproject.org/Gallery3:Modules:comment"
+discuss_url = "http://galleryproject.org/forum_module_comment"
diff --git a/modules/comment/views/admin_block_recent_comments.html.php b/modules/comment/views/admin_block_recent_comments.html.php
new file mode 100644
index 0000000..4017e4f
--- /dev/null
+++ b/modules/comment/views/admin_block_recent_comments.html.php
@@ -0,0 +1,23 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<ul>
+ <? foreach ($comments as $comment): ?>
+ <li class="<?= text::alternate("g-even", "g-odd") ?>">
+ <img src="<?= $comment->author()->avatar_url(32, $theme->url("images/avatar.jpg", true)) ?>"
+ class="g-avatar"
+ alt="<?= html::clean_attribute($comment->author_name()) ?>"
+ width="32"
+ height="32" />
+ <?= gallery::date_time($comment->created) ?>
+ <? if ($comment->author()->guest): ?>
+ <?= t('%author_name said <em>%comment_text</em>',
+ array("author_name" => html::clean($comment->author_name()),
+ "comment_text" => text::limit_words(nl2br(html::purify($comment->text)), 50))); ?>
+ <? else: ?>
+ <?= t('<a href="%url">%author_name</a> said <em>%comment_text</em>',
+ array("author_name" => html::clean($comment->author_name()),
+ "url" => user_profile::url($comment->author_id),
+ "comment_text" => text::limit_words(nl2br(html::purify($comment->text)), 50))); ?>
+ <? endif ?>
+ </li>
+ <? endforeach ?>
+</ul>
diff --git a/modules/comment/views/admin_comments.html.php b/modules/comment/views/admin_comments.html.php
new file mode 100644
index 0000000..dc6985b
--- /dev/null
+++ b/modules/comment/views/admin_comments.html.php
@@ -0,0 +1,7 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="g-block">
+ <h1> <?= t("Comment settings") ?> </h1>
+ <div class="g-block-content">
+ <?= $form ?>
+ </div>
+</div>
diff --git a/modules/comment/views/admin_manage_comments.html.php b/modules/comment/views/admin_manage_comments.html.php
new file mode 100644
index 0000000..e3c8546
--- /dev/null
+++ b/modules/comment/views/admin_manage_comments.html.php
@@ -0,0 +1,46 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript">
+ var set_state_url =
+ <?= html::js_string(url::site("admin/manage_comments/set_state/__ID__/__STATE__?csrf=$csrf")) ?>;
+ var set_state = function(state, id) {
+ $("#g-comment-" + id).fadeOut("fast", function() {
+ $.get(set_state_url.replace("__STATE__", state).replace("__ID__", id),
+ {},
+ update_menu);
+ });
+ }
+
+ var update_menu = function() {
+ $.get(<?= html::js_string(url::site("admin/manage_comments/menu_labels")) ?>, {},
+ function(data) {
+ for (var i = 0; i < data.length; i++) {
+ $("#g-admin-comments ul li:eq(" + i + ") a").html(data[i]);
+ }
+ },
+ "json");
+ }
+
+ // Paginator clicks load their href in the active tab panel
+ var fix_links = function() {
+ $(".g-paginator a, a#g-delete-all-spam").click(function(event) {
+ event.stopPropagation();
+ $.scrollTo(0, 800, { easing: "swing" });
+ $(this).parents(".ui-tabs-panel").load(
+ $(this).attr("href"),
+ function() {
+ fix_links();
+ });
+ return false;
+ });
+ }
+
+ $(document).ready(function() {
+ $("#g-admin-comments").tabs({
+ show: fix_links,
+ });
+ });
+</script>
+
+<div id="g-admin-comments" class="g-block">
+ <?= $menu->render() ?>
+</div>
diff --git a/modules/comment/views/admin_manage_comments_queue.html.php b/modules/comment/views/admin_manage_comments_queue.html.php
new file mode 100644
index 0000000..d847d72
--- /dev/null
+++ b/modules/comment/views/admin_manage_comments_queue.html.php
@@ -0,0 +1,157 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div class="g-block-content">
+ <? if ($state == "spam"): ?>
+ <div>
+ <? $spam_caught = module::get_var("comment", "spam_caught") ?>
+ <? if ($spam_caught > 0): ?>
+ <p>
+ <?= t2("Gallery has caught %count spam for you since you installed spam filtering.",
+ "Gallery has caught %count spam for you since you installed spam filtering.",
+ $spam_caught) ?>
+ </p>
+ <? endif ?>
+ <p>
+ <? if ($counts->spam): ?>
+ <?= t2("There is currently one comment in your spam queue. You can delete it with a single click, but there is no undo operation so you may want to check the message first to make sure that it really is spam.",
+ "There are currently %count comments in your spam queue. You can delete them all with a single click, but there is no undo operation so you may want to check the messages first to make sure that they really are spam. All spam messages will be deleted after 7 days automatically.",
+ $counts->spam) ?>
+ </p>
+ <p>
+ <a id="g-delete-all-spam"
+ href="<?= url::site("admin/manage_comments/delete_all_spam?csrf=$csrf") ?>">
+ <?= t("Delete all spam") ?>
+ </a>
+ <? else: ?>
+ <?= t("Your spam queue is empty!") ?>
+ <? endif ?>
+ </p>
+ </div>
+ <? endif ?>
+
+ <? if ($state == "deleted"): ?>
+ <div>
+ <p>
+ <?= t("These are messages that have been recently deleted. They will be permanently erased automatically after 7 days.") ?>
+ </p>
+ </div>
+ <? endif ?>
+
+ <div class="g-paginator">
+ <?= $theme->paginator() ?>
+ </div>
+ <table id="g-admin-comments-list">
+ <tr>
+ <th>
+ <?= t("Author") ?>
+ </th>
+ <th>
+ <?= t("Comment") ?>
+ </th>
+ <th>
+ <?= t("Actions") ?>
+ </th>
+ </tr>
+ <? foreach ($comments as $comment): ?>
+ <tr id="g-comment-<?= $comment->id ?>" class="<?= text::alternate("g-odd", "g-even") ?>">
+ <td>
+ <a href="#">
+ <img src="<?= $comment->author()->avatar_url(40, $fallback_avatar_url) ?>"
+ class="g-avatar"
+ alt="<?= html::clean_attribute($comment->author_name()) ?>"
+ width="40"
+ height="40" />
+ </a>
+ <p>
+ <a href="mailto:<?= html::clean_attribute($comment->author_email()) ?>"
+ title="<?= html::clean_attribute($comment->author_email()) ?>">
+ <?= html::clean($comment->author_name()) ?>
+ </a>
+ </p>
+ </td>
+ <td>
+ <div class="g-right">
+ <? $item = $comment->item() ?>
+ <div class="g-item g-photo">
+ <a href="<?= $item->url() ?>">
+ <? if ($item->has_thumb()): ?>
+ <img src="<?= $item->thumb_url() ?>"
+ alt="<?= html::purify($item->title)->for_html_attr() ?>"
+ <?= photo::img_dimensions($item->thumb_width, $item->thumb_height, 75) ?>
+ />
+ <? else: ?>
+ <?= t("No thumbnail") ?>
+ <? endif ?>
+ </a>
+ </div>
+ </div>
+ <p><?= gallery::date($comment->created) ?></p>
+ <?= nl2br(html::purify($comment->text)) ?>
+ </td>
+ <td>
+ <ul class="g-buttonset-vertical">
+ <? if ($comment->state != "unpublished" && $comment->state != "deleted"): ?>
+ <li>
+ <a href="javascript:set_state('unpublished',<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-check"></span>
+ <?= t("Unapprove") ?>
+ </a>
+ </li>
+ <? endif ?>
+ <? if ($comment->state != "published"): ?>
+ <li>
+ <a href="javascript:set_state('published',<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-check"></span>
+ <? if ($state == "deleted"): ?>
+ <?= t("Undelete") ?>
+ <? else: ?>
+ <?= t("Approve") ?>
+ <? endif ?>
+ </a>
+ </li>
+ <? endif ?>
+ <? if ($comment->state != "spam"): ?>
+ <li>
+ <a href="javascript:set_state('spam',<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-cancel"></span>
+ <?= t("Spam") ?>
+ </a>
+ </li>
+ <? endif ?>
+ <!--
+ <li>
+ <a href="javascript:reply(<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-arrowreturnthick-1-w"></span>
+ <?= t("Reply") ?>
+ </a>
+ </li>
+ <li>
+ <a href="javascript:Edit(<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-pencil"></span>
+ <?= t("Edit") ?>
+ </a>
+ </li>
+ -->
+ <? if ($comment->state != "deleted"): ?>
+ <li>
+ <a href="javascript:set_state('deleted',<?=$comment->id?>)"
+ class="g-button ui-state-default ui-icon-left">
+ <span class="ui-icon ui-icon-trash"></span>
+ <?= t("Delete") ?>
+ </a>
+ </li>
+ <? endif ?>
+ </ul>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </table>
+
+ <div class="g-paginator">
+ <?= $theme->paginator() ?>
+ </div>
+</div>
diff --git a/modules/comment/views/comment.html.php b/modules/comment/views/comment.html.php
new file mode 100644
index 0000000..263e5f9
--- /dev/null
+++ b/modules/comment/views/comment.html.php
@@ -0,0 +1,25 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<li id="g-comment-<?= $comment->id; ?>">
+ <p class="g-author">
+ <a href="#">
+ <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>"
+ class="g-avatar"
+ alt="<?= html::clean_attribute($comment->author_name()) ?>"
+ width="40"
+ height="40" />
+ </a>
+ <? if ($comment->author()->guest): ?>
+ <?= t("on %date_time, %name said",
+ array("date_time" => gallery::date_time($comment->created),
+ "name" => html::clean($comment->author_name()))) ?>
+ <? else: ?>
+ <?= t("on %date_time, <a href=\"%url\">%name</a> said",
+ array("date_time" => gallery::date_time($comment->created),
+ "url" => user_profile::url($comment->author_id),
+ "name" => html::clean($comment->author_name()))) ?>
+ <? endif ?>
+ </p>
+ <div>
+ <?= nl2br(html::purify($comment->text)) ?>
+ </div>
+</li>
diff --git a/modules/comment/views/comment.mrss.php b/modules/comment/views/comment.mrss.php
new file mode 100644
index 0000000..809e789
--- /dev/null
+++ b/modules/comment/views/comment.mrss.php
@@ -0,0 +1,43 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? echo "<?xml version=\"1.0\" ?>" ?>
+<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ xmlns:content="http://purl.org/rss/1.0/modules/content/"
+ xmlns:fh="http://purl.org/syndication/history/1.0">
+ <channel>
+ <generator>Gallery 3</generator>
+ <title><?= html::clean($feed->title) ?></title>
+ <link><?= $feed->uri ?></link>
+ <description><?= html::clean($feed->description) ?></description>
+ <language>en-us</language>
+ <atom:link rel="self" href="<?= $feed->uri ?>" type="application/rss+xml" />
+ <fh:complete/>
+ <? if (!empty($feed->previous_page_uri)): ?>
+ <atom:link rel="previous" href="<?= $feed->previous_page_uri ?>" type="application/rss+xml" />
+ <? endif ?>
+ <? if (!empty($feed->next_page_uri)): ?>
+ <atom:link rel="next" href="<?= $feed->next_page_uri ?>" type="application/rss+xml" />
+ <? endif ?>
+ <pubDate><?= $pub_date ?></pubDate>
+ <lastBuildDate><?= $pub_date ?></lastBuildDate>
+ <? foreach ($feed->comments as $comment): ?>
+ <item>
+ <title><?= html::purify($comment->title) ?></title>
+ <link><?= html::clean($comment->item_uri) ?></link>
+ <author><?= html::clean($comment->author) ?></author>
+ <guid isPermaLink="true"><?= $comment->item_uri ?></guid>
+ <pubDate><?= $comment->pub_date ?></pubDate>
+ <content:encoded>
+ <![CDATA[
+ <p><?= nl2br(html::purify($comment->text)) ?></p>
+ <p>
+ <img alt="" src="<?= $comment->thumb_url ?>"
+ height="<?= $comment->thumb_height ?>" width="<?= $comment->thumb_width ?>" />
+ <br />
+ </p>
+ ]]>
+ </content:encoded>
+ </item>
+ <? endforeach ?>
+ </channel>
+</rss>
diff --git a/modules/comment/views/comments.html.php b/modules/comment/views/comments.html.php
new file mode 100644
index 0000000..b524f5d
--- /dev/null
+++ b/modules/comment/views/comments.html.php
@@ -0,0 +1,56 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<? if (comment::can_comment()): ?>
+<a href="<?= url::site("form/add/comments/{$item->id}") ?>#comment-form" id="g-add-comment"
+ class="g-button ui-corner-all ui-icon-left ui-state-default">
+ <span class="ui-icon ui-icon-comment"></span>
+ <?= t("Add a comment") ?>
+</a>
+<? endif ?>
+
+<div id="g-comment-detail">
+ <? if (!$comments->count()): ?>
+ <p class="g-no-comments">
+ <? if (comment::can_comment()): ?>
+ <?= t("No comments yet. Be the first to <a %attrs>comment</a>!",
+ array("attrs" => html::mark_clean("href=\"" . url::site("form/add/comments/{$item->id}") . "\" class=\"showCommentForm\""))) ?>
+ <? else: ?>
+ <?= t("No comments yet.") ?>
+ <? endif ?>
+ </p>
+ <ul>
+ <li class="g-no-comments">&nbsp;</li>
+ </ul>
+ <? endif ?>
+
+ <? if ($comments->count()): ?>
+ <ul>
+ <? foreach ($comments as $comment): ?>
+ <li id="g-comment-<?= $comment->id ?>">
+ <p class="g-author">
+ <a href="#">
+ <img src="<?= $comment->author()->avatar_url(40, $theme->url("images/avatar.jpg", true)) ?>"
+ class="g-avatar"
+ alt="<?= html::clean_attribute($comment->author_name()) ?>"
+ width="40"
+ height="40" />
+ </a>
+ <? if ($comment->author()->guest): ?>
+ <?= t('on %date %name said',
+ array("date" => gallery::date_time($comment->created),
+ "name" => html::clean($comment->author_name()))); ?>
+ <? else: ?>
+ <?= t('on %date <a href="%url">%name</a> said',
+ array("date" => gallery::date_time($comment->created),
+ "url" => user_profile::url($comment->author_id),
+ "name" => html::clean($comment->author_name()))); ?>
+ <? endif ?>
+ </p>
+ <div>
+ <?= nl2br(html::purify($comment->text)) ?>
+ </div>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? endif ?>
+ <a name="comment-form" id="g-comment-form-anchor"></a>
+</div>
diff --git a/modules/comment/views/user_profile_comments.html.php b/modules/comment/views/user_profile_comments.html.php
new file mode 100644
index 0000000..377b2d9
--- /dev/null
+++ b/modules/comment/views/user_profile_comments.html.php
@@ -0,0 +1,20 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-comment-detail">
+<ul>
+ <? foreach ($comments as $comment): ?>
+ <li id="g-comment-<?= $comment->id ?>">
+ <p class="g-author">
+ <?= t("on %date for %title ",
+ array("date" => gallery::date_time($comment->created),
+ "title" => $comment->item()->title)); ?>
+ <a href="<?= $comment->item()->url() ?>">
+ <?= $comment->item()->thumb_img(array(), 50) ?>
+ </a>
+ </p>
+ <div>
+ <?= nl2br(html::purify($comment->text)) ?>
+ </div>
+ </li>
+ <? endforeach ?>
+</ul>
+</div>