diff --git a/modules/webcomment/.cvsignore b/modules/webcomment/.cvsignore
new file mode 100644
index 000000000..a3409fca7
--- /dev/null
+++ b/modules/webcomment/.cvsignore
@@ -0,0 +1,5 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
\ No newline at end of file
diff --git a/modules/webcomment/Makefile.am b/modules/webcomment/Makefile.am
new file mode 100644
index 000000000..18a27e626
--- /dev/null
+++ b/modules/webcomment/Makefile.am
@@ -0,0 +1,22 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+SUBDIRS = lib doc web
+
+CLEANFILES = *~
diff --git a/modules/webcomment/doc/.cvsignore b/modules/webcomment/doc/.cvsignore
new file mode 100644
index 000000000..b644e5e86
--- /dev/null
+++ b/modules/webcomment/doc/.cvsignore
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
+*.shtml
+*.html
diff --git a/modules/webcomment/doc/Makefile.am b/modules/webcomment/doc/Makefile.am
new file mode 100644
index 000000000..98f8cd936
--- /dev/null
+++ b/modules/webcomment/doc/Makefile.am
@@ -0,0 +1,21 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+SUBDIRS = admin hacking
+
diff --git a/modules/webcomment/doc/admin/.cvsignore b/modules/webcomment/doc/admin/.cvsignore
new file mode 100644
index 000000000..b644e5e86
--- /dev/null
+++ b/modules/webcomment/doc/admin/.cvsignore
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
+*.shtml
+*.html
diff --git a/modules/webcomment/doc/admin/Makefile.am b/modules/webcomment/doc/admin/Makefile.am
new file mode 100644
index 000000000..7bf43a95e
--- /dev/null
+++ b/modules/webcomment/doc/admin/Makefile.am
@@ -0,0 +1,30 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+docdir = $(WEBDIR)/admin/webcomment
+
+doc_DATA = guide.html
+
+FILESWML = $(wildcard $(srcdir)/*.wml)
+EXTRA_DIST = $(FILESWML:$(srcdir)/%=%)
+
+CLEANFILES = $(doc_DATA) *~ *.tmp
+
+%.html: %.html.wml $(top_srcdir)/config/config.wml $(top_builddir)/config/configbis.wml $(top_srcdir)/config/cdsnavbar.wml
+ $(WML) -o\(ALL-LANG_*\)+LANG_EN:$@ $<
diff --git a/modules/webcomment/doc/admin/guide.html.wml b/modules/webcomment/doc/admin/guide.html.wml
new file mode 100644
index 000000000..181b85a49
--- /dev/null
+++ b/modules/webcomment/doc/admin/guide.html.wml
@@ -0,0 +1,27 @@
+## -*- mode: html; coding: utf-8; -*-
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+#include "cdspage.wml" \
+ title="WebComment Admin Guide" \
+ navtrail_previous_links="/admin/> > /admin/websearch/>WebComment Admin" \
+ navbar_name="admin" \
+ navbar_select="webcomment-admin-guide"
+
+FIXME
diff --git a/modules/webcomment/doc/hacking/.cvsignore b/modules/webcomment/doc/hacking/.cvsignore
new file mode 100644
index 000000000..f0878fb91
--- /dev/null
+++ b/modules/webcomment/doc/hacking/.cvsignore
@@ -0,0 +1,8 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
+*.py
+*.shtml
+*.html
\ No newline at end of file
diff --git a/modules/webcomment/doc/hacking/Makefile.am b/modules/webcomment/doc/hacking/Makefile.am
new file mode 100644
index 000000000..5ac343f5b
--- /dev/null
+++ b/modules/webcomment/doc/hacking/Makefile.am
@@ -0,0 +1,21 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+docdir = $(WEBDIR)/hacking/webcomment
+
diff --git a/modules/webcomment/lib/.cvsignore b/modules/webcomment/lib/.cvsignore
new file mode 100644
index 000000000..9638520ce
--- /dev/null
+++ b/modules/webcomment/lib/.cvsignore
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
+*.pyc
\ No newline at end of file
diff --git a/modules/webcomment/lib/Makefile.am b/modules/webcomment/lib/Makefile.am
new file mode 100644
index 000000000..97ab2552f
--- /dev/null
+++ b/modules/webcomment/lib/Makefile.am
@@ -0,0 +1,26 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+pylibdir = $(libdir)/python/cdsware
+
+pylib_DATA = webcomment_config.py webcomment.py webcomment_tests.py webcomment_templates.py webcommentadminlib.py
+
+EXTRA_DIST = $(pylib_DATA)
+
+CLEANFILES = *~ *.tmp *.pyc
diff --git a/modules/webcomment/lib/webcomment.py b/modules/webcomment/lib/webcomment.py
new file mode 100644
index 000000000..539ba0c96
--- /dev/null
+++ b/modules/webcomment/lib/webcomment.py
@@ -0,0 +1,857 @@
+# -*- coding: utf-8 -*-
+## $Id$
+## Comments and reviews for records.
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+__lastupdated__ = """FIXME: last updated"""
+
+# non CDSware imports:
+from email.Utils import quote
+import time
+import math
+import string
+from cgi import escape
+
+# import CDSware stuff:
+from webcomment_config import *
+from dbquery import run_sql
+from config import cdslang
+from elmsubmit_html2txt import html2txt
+
+import template
+webcomment_templates = template.load('webcomment')
+
+def perform_request_display_comments_or_remarks(recID, ln=cdslang, display_order='od', display_since='all', nb_per_page=100, page=1, voted=-1, reported=-1, reviews=0):
+ """
+ Returns all the comments (reviews) of a specific internal record or external basket record.
+ @param recID: record id where (internal record IDs > 0) or (external basket record IDs < -100)
+ @param display_order: hh = highest helpful score, review only
+ lh = lowest helpful score, review only
+ hs = highest star score, review only
+ ls = lowest star score, review only
+ od = oldest date
+ nd = newest date
+ @param display_since: all= no filtering by date
+ nd = n days ago
+ nw = n weeks ago
+ nm = n months ago
+ ny = n years ago
+ where n is a single digit integer between 0 and 9
+ @param nb_per_page: number of results per page
+ @param page: results page
+ @param voted: boolean, active if user voted for a review, see perform_request_vote function
+ @param reported: boolean, active if user reported a certain comment/review, perform_request_report function
+ @param reviews: boolean, enabled if reviews, disabled for comments
+ @return html body.
+ """
+
+ errors = []
+ warnings = []
+
+ # wash arguments
+ recID= wash_url_argument(recID, 'int')
+ ln = wash_url_argument(ln, 'str')
+ display_order = wash_url_argument(display_order, 'str')
+ display_since = wash_url_argument(display_since, 'str')
+ nb_per_page = wash_url_argument(nb_per_page, 'int')
+ page = wash_url_argument(page, 'int')
+ voted = wash_url_argument(voted, 'int')
+ reported = wash_url_argument(reported, 'int')
+ reviews = wash_url_argument(reviews, 'int')
+
+ # vital argument check
+ check_recID_is_in_range(recID, errors)
+
+ # Query the database and filter results
+ res = query_retrieve_comments_or_remarks(recID, display_order, display_since, reviews)
+ nb_res = len(res)
+
+ # chekcing non vital arguemnts - will be set to default if wrong
+ #if page <= 0 or page.lower() != 'all':
+ if page < 0:
+ page = 1
+ warnings.append(('WRN_WEBCOMMENT_INVALID_PAGE_NB',))
+ if nb_per_page < 0:
+ nb_per_page = 100
+ warnings.append(('WRN_WEBCOMMENT_INVALID_NB_RESULTS_PER_PAGE',))
+ if cfg_webcomment_allow_reviews and reviews:
+ if display_order not in ['od', 'nd', 'hh', 'lh', 'hs', 'ls']:
+ display_order = 'hh'
+ warnings.append(('WRN_WEBCOMMENT_INVALID_REVIEW_DISPLAY_ORDER',))
+ else:
+ if display_order not in ['od', 'nd']:
+ display_order = 'od'
+ warnings.append(('WRN_WEBCOMMENT_INVALID_DISPLAY_ORDER',))
+
+ # filter results according to page and number of reults per page
+ if nb_per_page > 0:
+ if nb_res > 0:
+ last_page = int(math.ceil(nb_res / float(nb_per_page)))
+ else:
+ last_page = 1
+ if page > last_page:
+ page = 1
+ warnings.append(("WRN_WEBCOMMENT_INVALID_PAGE_NB",))
+ if nb_res > nb_per_page: # if more than one page of results
+ if page < last_page:
+ res = res[(page-1)*(nb_per_page) : (page*nb_per_page)]
+ else:
+ res = res[(page-1)*(nb_per_page) : ]
+ else: # one page of results
+ pass
+ else:
+ last_page = 1
+
+ # Send to template
+ # record is an internal record
+ if recID > 0:
+ avg_score = 0.0
+ if not cfg_webcomment_allow_comments and not cfg_webcomment_allow_reviews: # comments not allowed by admin
+ errors.append(('ERR_WEBCOMMENT_COMMENTS_NOT_ALLOWED',))
+ if reported > 0:
+ warnings.append(('WRN_WEBCOMMENT_FEEDBACK_RECORDED_GREEN_TEXT',))
+ elif reported == 0:
+ warnings.append(('WRN_WEBCOMMENT_FEEDBACK_NOT_RECORDED_RED_TEXT',))
+ if cfg_webcomment_allow_reviews and reviews:
+ avg_score = calculate_avg_score(res)
+ if voted>0:
+ warnings.append(('WRN_WEBCOMMENT_FEEDBACK_RECORDED_GREEN_TEXT',))
+ elif voted == 0:
+ warnings.append(('WRN_WEBCOMMENT_FEEDBACK_NOT_RECORDED_RED_TEXT',))
+ body = webcomment_templates.tmpl_get_comments(recID, ln, nb_per_page, page, last_page, display_order, display_since, cfg_webcomment_allow_reviews, res,
+ nb_res, avg_score, warnings, border=0, reviews=reviews)
+ return (body, errors, warnings)
+ # record is an external record
+ else:
+ return ("TODO", errors, warnings) #!FIXME
+
+def perform_request_vote(comID, value):
+ """
+ Vote positively or negatively for a comment/review
+ @param comID: review id
+ @param value: +1 for voting positively
+ -1 for voting negatively
+ @return integer 1 if successful, integer 0 if not
+ """
+ #FIXME should record IP address and not allow voters to vote more than once
+ comID = wash_url_argument(comID, 'int')
+ value = wash_url_argument(value, 'int')
+ if comID > 0 and value in [-1, 1]:
+ return query_record_useful_review(comID, value)
+ else:
+ return 0
+
+def perform_request_report(comID):
+ """
+ Report a comment/review for inappropriate content.
+ Will send an email to the administrator if number of reports is a multiple of config.py/cfg_comment_nb_reports_before_send_email_to_admin
+ @param comID: comment id
+ @return integer 1 if successful, integer 0 if not
+ """
+ #FIXME should record IP address and not allow reporters to report more than once
+ comID = wash_url_argument(comID, 'int')
+ if comID <= 0:
+ return 0
+ (query_res, nb_reported) = query_record_report_this(comID)
+ if query_res == 0:
+ return 0
+ if nb_reported % cfg_webcomment_nb_reports_before_send_email_to_admin == 0:
+ (comID2, id_bibrec, id_user, com_body, com_date, com_star, com_vote, com_nb_votes, com_star_note, com_reported) = query_get_comment(comID)
+ (user_nb_reported, user_votes, user_nb_votes) = query_get_user_reports_and_votes(int(id_user))
+ (nickname, user_email, last_login) = query_get_user_contact_info(id_user)
+ from_addr = 'CDS Alert Engine <%s>' % alertengineemail
+ to_addr = adminemail
+ body = '''
+The following comment has been reported a total of %(com_reported)s times.
+
+Author: nickname = %(nickname)s
+ email = %(user_email)s
+ user_id = %(uid)s
+ This user has:
+ total number of reports = %(user_nb_reported)s
+ %(votes)s
+Comment: comment_id = %(comID)s
+ record_id = %(id_bibrec)s
+ date written = %(com_date)s
+ nb reports = %(com_reported)s
+ %(review_stuff)s
+ body =
+---start body---
+%(com_body)s
+---end body---
+
+Please go to the Comments Admin Panel %(comment_admin_link)s to delete this message if necessary. A warning will be sent to the user in question.''' % \
+ { 'cfg-report_max' : cfg_webcomment_nb_reports_before_send_email_to_admin,
+ 'nickname' : nickname,
+ 'user_email' : user_email,
+ 'uid' : id_user,
+ 'user_nb_reported' : user_nb_reported,
+ 'user_votes' : user_votes,
+ 'votes' : cfg_webcomment_allow_reviews and \
+ "total number of positive votes\t= %s\n\t\t\t\ttotal number of negative votes\t= %s" % \
+ (user_votes, (user_nb_votes - user_votes)) or "\n",
+ 'comID' : comID,
+ 'id_bibrec' : id_bibrec,
+ 'com_date' : com_date,
+ 'com_reported' : com_reported,
+ 'review_stuff' : cfg_webcomment_allow_reviews and \
+ "star score\t\t= %s\n\t\t\treview title\t\t= %s" % (com_star, com_star_note) or "",
+ 'com_body' : com_body,
+ 'comment_admin_link' : "http://%s/admin/webcomment/" % weburl,
+ 'user_admin_link' : "user_admin_link" #! FIXME
+ }
+
+ #FIXME to be added to email
+ #If you wish to ban the user, you can do so via the User Admin Panel %(user_admin_link)s.
+
+ from alert_engine import send_email
+ send_email(from_addr, to_addr, body)
+ return 1
+
+def query_get_user_contact_info(uid):
+ """
+ Get the user contact information
+ @return tuple (nickname, email, last_login), if none found return ()
+ Note: for the moment, if no nickname, will return email address up to the '@'
+ """
+ query1 = "SELECT email, nickname, last_login FROM user WHERE id=%s"
+ params1 = (uid,)
+ res1 = run_sql(query1, params1)
+ if len(res1)==0:
+ return ()
+ #!FIXME - extra code because still possible to have no nickname
+ res2 = list(res1[0])
+ if not res2[1]:
+ res2[1] = res2[0].split('@')[0]
+ return (res2[1], res2[0], res2[2])
+# return (res1[0][1], res1[0][0], res1[0][2])
+
+def query_get_user_reports_and_votes(uid):
+ """
+ Retrieve total number of reports and votes of a particular user
+ @param uid: user id
+ @return tuple (total_nb_reports, total_vote_value, total_nb_votes)
+ if none found return ()
+ """
+ query1 = "SELECT vote_value, nb_votes, nb_reported FROM cmtRECORDCOMMENT WHERE id_user=%s"
+ params1 = (uid,)
+ res1 = run_sql(query1, params1)
+ if len(res1)==0:
+ return ()
+ vote_value = nb_votes = nb_reported = 0
+ for cmt_tuple in res1:
+ vote_value += int(cmt_tuple[0])
+ nb_votes += int(cmt_tuple[1])
+ nb_reported += int(cmt_tuple[2])
+ return (nb_reported, vote_value, nb_votes)
+
+def query_get_comment(comID):
+ """
+ Get all fields of a comment
+ @param comID: comment id
+ @return tuple (comID, id_bibrec, id_user, body, date_creation, star_score, vote_value, nb_votes, star_note, nb_reported)
+ if none found return ()
+ """
+ query1 = "SELECT * FROM cmtRECORDCOMMENT WHERE id=%s"
+ params1 = (comID,)
+ res1 = run_sql(query1, params1)
+ if len(res1)>0:
+ return res1[0]
+ else:
+ return ()
+
+def query_record_report_this(comID):
+ """
+ Increment the number of reports for a comment
+ @param comID: comment id
+ @return tuple (success, new_total_nb_reports_for_this_comment) where success is integer 1 if success, integer 0 if not
+ if none found, return ()
+ """
+ #retrieve nb_reported
+ query1 = "SELECT nb_reported FROM cmtRECORDCOMMENT WHERE id=%s"
+ params1 = (comID,)
+ res1 = run_sql(query1, params1)
+ if len(res1)==0:
+ return ()
+
+ #increment and update
+ nb_reported = int(res1[0][0]) + 1
+ query2 = "UPDATE cmtRECORDCOMMENT SET nb_reported=%s WHERE id=%s"
+ params2 = (nb_reported, comID)
+ res2 = run_sql(query2, params2)
+ return (int(res2), nb_reported)
+
+def query_record_useful_review(comID, value):
+ """
+ private funciton
+ Adjust the number of useful votes and number of total votes for a comment.
+ @param comID: comment id
+ @param value: +1 or -1
+ @return integer 1 if successful, integer 0 if not
+ """
+ # retrieve nb_useful votes
+ query1 = "SELECT nb_votes, vote_value FROM cmtRECORDCOMMENT WHERE id=%s"
+ params1 = (comID,)
+ res1 = run_sql(query1, params1)
+ if len(res1)==0:
+ return 0
+
+ # modify and insert new nb_useful votes
+ vote_value = int(res1[0][1]) + value
+ nb_votes = int(res1[0][0]) + 1
+ query2 = "UPDATE cmtRECORDCOMMENT SET nb_votes=%s, vote_value=%s WHERE id=%s"
+ params2 = (nb_votes, vote_value, comID)
+ res2 = run_sql(query2, params2)
+ return int(res2)
+
+def query_retrieve_comments_or_remarks (recID=-1, display_order='od', display_since='0000-00-00 00:00:00', ranking=0):
+ """
+ Private function
+ Retrieve tuple of comments or remarks from the database
+ @param recID: record id
+ @param display_order: hh = highest helpful score
+ lh = lowest helpful score
+ hs = highest star score
+ ls = lowest star score
+ od = oldest date
+ nd = newest date
+ @param display_since: datetime, e.g. 0000-00-00 00:00:00
+ @param ranking: boolean, enabled if reviews, disabled for comments
+ @return tuple of comment where comment is
+ tuple (nickname, date_creation, body, id) if ranking disabled or
+ tuple (nickname, date_creation, body, vote_value, nb_votes, star_score, star_note, id)
+ Note: for the moment, if no nickname, will return email address up to '@'
+ """
+ display_since = calculate_start_date(display_since)
+
+ order_dict = { 'hh' : "c.vote_value/(c.nb_votes+1) DESC, c.date_creation DESC ",
+ 'lh' : "c.vote_value/(c.nb_votes+1) ASC, c.date_creation ASC ",
+ 'ls' : "c.star_score ASC, c.date_creation DESC ",
+ 'hs' : "c.star_score DESC, c.date_creation DESC ",
+ 'od' : "c.date_creation ASC ",
+ 'nd' : "c.date_creation DESC "
+ }
+
+ # Ranking only done for comments and when allowed
+ if ranking:
+ try:
+ display_order = order_dict[display_order]
+ except:
+ display_order = order_dict['od']
+ else:
+ try:
+ if display_order[-1] == 'd':
+ display_order = order_dict[display_order]
+ else:
+ display_order = order_dict['od']
+ except:
+ display_order = order_dict['od']
+
+ query = "SELECT u.nickname, c.date_creation, c.body, %(ranking)s c.id " \
+ "FROM %(table)s AS c, user AS u " \
+ "WHERE %(id_bibrec)s=\'%(recID)s\' " \
+ "AND c.id_user=u.id "\
+ "%(ranking_only)s " \
+ "%(display_since)s " \
+ "ORDER BY %(display_order)s "
+
+ params = { 'ranking' : ranking and ' c.vote_value, c.nb_votes, c.star_score, c.star_note, ' or '',
+ 'ranking_only' : ranking and ' AND c.star_score>0 ' or ' AND c.star_score=0 ',
+ 'id_bibrec' : recID>0 and 'c.id_bibrec' or 'c.id_bskBASKET_bibrec_bskEXTREC',
+ 'table' : recID>0 and 'cmtRECORDCOMMENT' or 'bskREMARK',
+ 'recID' : recID,
+ 'display_since' : display_since=='0000-00-00 00:00:00' and ' ' or 'AND c.date_creation>=\'%s\' ' % display_since,
+ 'display_order' : display_order
+ }
+ # return run_sql(query % params)
+ #FIXME - Extra horrible code cause nickname can still be blank
+ res = run_sql(query % params) #!FIXME
+ res2= []
+ for comment in res:
+ if not comment[0]:
+ comment2 = list(comment)
+ user_id = query_get_comment(comment[-1])[2]
+ comment2[0] = query_get_user_contact_info(user_id)[1].split('@')[0]
+ res2.append(comment2)
+ else:
+ res2.append(comment)
+ return tuple(res2)
+
+def query_add_comment_or_remark(recID=-1, uid=-1, msg="", note="", score=0, priority=0):
+ """
+ Private function
+ Insert a comment/review or remarkinto the database
+ @param recID: record id
+ @param uid: user id
+ @param msg: comment body
+ @param note: comment title
+ @param score: review star score
+ @param priority: remark priority #!FIXME
+ @return integer >0 representing id if successful, integer 0 if not
+ """
+ current_date = calculate_start_date('0d')
+ if recID > 0:
+ # get rid of html tags in msg but keep newlines
+ msg = msg.replace ('\n', "#br#")
+ msg= html2txt(msg)
+ msg = msg.replace('#br#', ' ')
+ note= html2txt(note)
+ #unicode
+ msg = msg.encode('utf-8')
+ note = note.encode('utf-8')
+ query = "INSERT INTO cmtRECORDCOMMENT (id_bibrec, id_user, body, date_creation, star_score, nb_votes, star_note) " \
+ "VALUES (%s, %s, %s, %s, %s, %s, %s)"
+ params = (recID, uid, msg, current_date, score, 0, note)
+ else:
+ # get rid of html tags in msg but keep newlines
+ msg = msg.replace ('\n', "#br#")
+ msg= html2txt(msg)
+ msg = msg.replace('#br#', ' ')
+ msg = msg.encode('utf-8')
+ query = "INSERT INTO bskREMARK (id_bskBASKET_bibrec_bibEXTREC, id_user, body, date_creation, priority) " \
+ "VALUES (%s, %s, %s, %s, %s)"
+ params = (recID, uid, msg, current_date, priority)
+
+ return int(run_sql(query, params))
+
+def calculate_start_date(display_since):
+ """
+ Private function
+ Returns the datetime of display_since argument in MYSQL datetime format
+ calculated according to the local time.
+ @param display_since = all= no filtering
+ nd = n days ago
+ nw = n weeks ago
+ nm = n months ago
+ ny = n years ago
+ where n is a single digit number
+ @return string of wanted datetime.
+ If 'all' given as argument, will return "0000-00-00 00:00:00"
+ If bad arguement given, will return "0000-00-00 00:00:00"
+ """
+ # time type and seconds coefficients
+ time_types = {'d':0,'w':0,'m':0,'y':0}
+
+ ## verify argument
+ # argument wrong size
+ if (display_since==(None or 'all')) or (len(display_since) > 2):
+ return ("0000-00-00 00:00:00")
+ try:
+ nb = int(display_since[0])
+ except:
+ return ("0000-00-00 00:00:00")
+ if str(display_since[1]) in time_types:
+ time_type = str(display_since[1])
+ else:
+ return ("0000-00-00 00:00:00")
+
+ ## calculate date
+ # initialize the coef
+ if time_type == 'w':
+ time_types[time_type] = 7
+ else:
+ time_types[time_type] = 1
+
+ start_time = time.localtime(time.time())
+ start_time = time.mktime(( start_time[0] - nb*time_types['y'],
+ start_time[1] - nb*time_types['m'],
+ start_time[2] - nb*time_types['d'] - nb*time_types['w'],
+ start_time[3],
+ start_time[4],
+ start_time[5],
+ start_time[6],
+ start_time[7],
+ start_time[8]))
+ return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time))
+
+def get_first_comments_or_remarks(recID=-1, ln=cdslang, nb='all', voted=-1, reported=-1):
+ """
+ Gets nb number comments/reviews or remarks.
+ In the case of comments, will get both comments and reviews
+ Comments and remarks sorted by most recent date, reviews sorted by highest helpful score
+ @param recID: record id
+ @param ln: language
+ @param nb: number of comment/reviews or remarks to get
+ @param voted: 1 if user has voted for a remark
+ @param reported: 1 if user has reported a comment or review
+ @return if comment, tuple (comments, reviews) both being html of first nb comments/reviews
+ if remark, tuple (remakrs, None)
+ """
+ warnings = []
+ errors = []
+ voted = wash_url_argument(voted, 'int')
+ reported = wash_url_argument(reported, 'int')
+
+ ## check recID argument
+ if type(recID) is not int:
+ return ()
+ if recID >= 1 or recID <= -100: #comment or remark
+ if cfg_webcomment_allow_reviews:
+ res_reviews = query_retrieve_comments_or_remarks(recID=recID, display_order="hh", ranking=1)
+ nb_res_reviews = len(res_reviews)
+ ## check nb argument
+ if type(nb) is int and nb < len(res_reviews):
+ first_res_reviews = res_reviews[:nb]
+ else:
+ if nb_res_reviews > cfg_webcomment_nb_reviews_in_detailed_view:
+ first_res_reviews = res_reviews[:cfg_comment_nb_reports_before_send_email_to_admin]
+ else:
+ first_res_reviews = res_reviews
+ if cfg_webcomment_allow_comments:
+ res_comments = query_retrieve_comments_or_remarks(recID=recID, display_order="od", ranking=0)
+ nb_res_comments = len(res_comments)
+ ## check nb argument
+ if type(nb) is int and nb < len(res_comments):
+ first_res_comments = res_comments[:nb]
+ else:
+ if nb_res_comments > cfg_webcomment_nb_comments_in_detailed_view:
+ first_res_comments = res_comments[:cfg_webcomment_nb_comments_in_detailed_view]
+ else:
+ first_res_comments = res_comments
+ else: #error
+ errors.append(('ERR_WEBCOMMENT_RECID_INVALID', recID)) #!FIXME dont return error anywhere since search page
+
+ # comment
+ if recID >= 1:
+ comments = reviews = ""
+ if reported > 0:
+ warnings.append(('WRN_WEBCOMMENT_FEEDBACK_RECORDED_GREEN_TEXT',))
+ elif reported == 0:
+ warnings.append(('WRN_WEBCOMMENT_FEEDBACK_NOT_RECORDED_RED_TEXT',))
+ if cfg_webcomment_allow_comments: # normal comments
+ comments = webcomment_templates.tmpl_get_first_comments_without_ranking(recID, ln, first_res_comments, nb_res_comments, warnings)
+ if cfg_webcomment_allow_reviews: # ranked comments
+ #calculate average score
+ avg_score = calculate_avg_score(res_reviews)
+ if voted > 0:
+ warnings.append(('WRN_WEBCOMMENT_FEEDBACK_RECORDED_GREEN_TEXT',))
+ elif voted == 0:
+ warnings.append(('WRN_WEBCOMMENT_FEEDBACK_NOT_RECORDED_RED_TEXT',))
+ reviews = webcomment_templates.tmpl_get_first_comments_with_ranking(recID, ln, first_res_reviews, nb_res_reviews, avg_score, warnings)
+ return (comments, reviews)
+ # remark
+ else:
+ return(webcomment_templates.tmpl_get_first_remarks(first_res_comments, ln, nb_res_comments), None)
+
+def calculate_avg_score(res):
+ """
+ private function
+ Calculate the avg score of reviews present in res
+ @param res: tuple of tuple returned from query_retrieve_comments_or_remarks
+ @return a float of the average score rounded to the closest 0.5
+ """
+
+ c_nickname = 0
+ c_date_creation = 1
+ c_body = 2
+ c_vote_value = 3
+ c_nb_votes = 4
+ c_star_score = 5
+ c_star_note = 6
+ c_id = 7
+
+ avg_score = 0.0
+ nb_reviews = 0
+ for comment in res:
+ if comment[c_star_score] > 0:
+ avg_score += comment[c_star_score]
+ nb_reviews += 1
+ if nb_reviews == 0:
+ return 0.0
+ avg_score = avg_score / nb_reviews
+ avg_score_unit = avg_score - math.floor(avg_score)
+ if avg_score_unit < 0.25:
+ avg_score = math.floor(avg_score)
+ elif avg_score_unit > 0.75:
+ avg_score = math.floor(avg_score) + 1
+ else:
+ avg_score = math.floor(avg_score) + 0.5
+ if avg_score > 5:
+ avg_score = 5.0
+ return avg_score
+
+def perform_request_add_comment_or_remark(recID=-1, uid=-1, action='DISPLAY', ln=cdslang, msg=None, score=None, note=None, priority=None, reviews=0, comID=-1):
+ """
+ Add a comment/review or remark
+ @param recID: record id
+ @param uid: user id
+ @param action: 'DISPLAY' to display add form
+ 'SUBMIT' to submit comment once form is filled
+ 'REPLY' to reply to an existing comment
+ @param ln: language
+ @param msg: the body of the comment/review or remark
+ @param score: star score of the review
+ @param note: title of the review
+ @param priority: priority of remark
+ @param reviews: boolean, if enabled will add a review, if disabled will add a comment
+ @param comID: if replying, this is the comment id of the commetn are replying to
+ @return html add form if action is display or reply
+ html successful added form if action is submit
+ """
+
+ warnings = []
+ errors = []
+
+ actions = ['DISPLAY', 'REPLY', 'SUBMIT']
+ ## wash arguments
+ recID = wash_url_argument(recID, 'int')
+ uid = wash_url_argument(uid, 'int')
+ msg = wash_url_argument(msg, 'str')
+ score = wash_url_argument(score, 'int')
+ note = wash_url_argument(note, 'str')
+ priority = wash_url_argument(priority, 'int')
+ reviews = wash_url_argument(reviews, 'int')
+ comID = wash_url_argument(comID, 'int')
+
+ ## check arguments
+ check_recID_is_in_range(recID, errors)
+ if uid <= 0:
+ errors.append(('ERR_WEBCOMMENT_UID_INVALID', uid))
+ else:
+ nickname = query_get_user_contact_info(uid)[0]
+
+ # show the form
+ if action == 'DISPLAY':
+ if reviews and cfg_webcomment_allow_reviews:
+ return (webcomment_templates.tmpl_add_comment_form_with_ranking(recID, uid, nickname, ln, msg, score, note, warnings), errors, warnings)
+ elif not reviews and cfg_webcomment_allow_comments:
+ return (webcomment_templates.tmpl_add_comment_form(recID, uid, nickname, ln, msg, warnings), errors, warnings)
+ else:
+ errors.append(('ERR_WEBCOMMENT_COMMENTS_NOT_ALLOWED',))
+
+ elif action == 'REPLY':
+ if reviews and cfg_webcomment_allow_reviews:
+ errors.append(('ERR_WEBCOMMENT_REPLY_REVIEW',))
+ return (webcomment_templates.tmpl_add_comment_form_with_ranking(recID, uid, nickname, ln, msg, score, note, warnings), errors, warnings)
+ elif not reviews and cfg_webcomment_allow_comments:
+ if comID>0:
+ comment = query_get_comment(comID)
+ if comment:
+ user_info = query_get_user_contact_info(comment[2])
+ if user_info:
+ msg = comment[3].replace('\n', ' ')
+ msg = msg.replace(' ', '\n')
+ msg = "Quoting %s:\n%s\n" % (user_info[0], msg)
+ return (webcomment_templates.tmpl_add_comment_form(recID, uid, nickname, ln, msg, warnings), errors, warnings)
+ else:
+ errors.append(('ERR_WEBCOMMENT_COMMENTS_NOT_ALLOWED',))
+
+ # check before submitting form
+ elif action == 'SUBMIT':
+ if reviews and cfg_webcomment_allow_reviews:
+ if note.strip() in ["", "None"]:
+ warnings.append(('WRN_WEBCOMMENT_ADD_NO_TITLE',))
+ if score == 0 or score > 5:
+ warnings.append(("WRN_WEBCOMMENT_ADD_NO_SCORE",))
+ if msg.strip() in ["", "None"]:
+ warnings.append(('WRN_WEBCOMMENT_ADD_NO_BODY',))
+ # if no warnings, submit
+ if len(warnings) == 0:
+ success = query_add_comment_or_remark(recID=recID, uid=uid, msg=msg, note=note, score=score, priority=0)
+ if success > 0:
+ if cfg_webcomment_admin_notification_level > 0:
+ notify_admin_of_new_comment(comID=success)
+ return (webcomment_templates.tmpl_add_comment_successful(recID, ln, reviews), errors, warnings)
+ else:
+ errors.append(('ERR_WEBCOMMENT_DB_INSERT_ERROR',))
+ # if are warnings or if inserting comment failed, show user where warnings are
+ if reviews and cfg_webcomment_allow_reviews:
+ return (webcomment_templates.tmpl_add_comment_form_with_ranking(recID, uid, nickname, ln, msg, score, note, warnings), errors, warnings)
+ else:
+ return (webcomment_templates.tmpl_add_comment_form(recID, uid, nickname, ln, msg, warnings), errors, warnings)
+ # unknown action send to display
+ else:
+ warnings.append(('WRN_WEBCOMMENT_ADD_UNKNOWN_ACTION',))
+ if reviews and cfg_webcomment_allow_reviews:
+ return (webcomment_templates.tmpl_add_comment_form_with_ranking(recID, uid, ln, msg, score, note, warnings), errors, warnings)
+ else:
+ return (webcomment_templates.tmpl_add_comment_form(recID, uid, ln, msg, warnings), errors, warnings)
+
+def notify_admin_of_new_comment(comID):
+ """
+ Sends an email to the admin with details regarding comment with ID = comID
+ """
+ comment = query_get_comment(comID)
+ if len(comment) > 0:
+ (comID2, id_bibrec, id_user, body, date_creation, star_score, vote_value, nb_votes, star_note, nb_reported) = comment
+ else:
+ return
+ user_info = query_get_user_contact_info(id_user)
+ if len(user_info) > 0:
+ (nickname, email, last_login) = user_info
+ if not len(nickname) > 0:
+ nickname = email.split('@')[0]
+ else:
+ nickname = email = last_login = "ERROR: Could not retrieve"
+
+ from search_engine import print_record
+ record = print_record(recID=id_bibrec, format='hs')
+
+ review_stuff = '''
+ Star score = %s
+ Title = %s''' % (star_score, star_note)
+
+ out = '''
+The following %(comment_or_review)s has just been posted (%(date)s).
+
+AUTHOR:
+ Nickname = %(nickname)s
+ Email = %(email)s
+ User ID = %(uid)s
+
+RECORD CONCERNED:
+ Record ID = %(recID)s
+ Record = %(record_details)s
+
+%(comment_or_review2)s:
+ %(comment_or_review)s ID = %(comID)s %(review_stuff)s
+ Body =
+%(body)s
+
+ADMIN OPTIONS:
+To delete comment go to %(weburl)s/admin/webcomment/webcommentadmin.py/delete?comid=%(comID)s
+ ''' % \
+ { 'comment_or_review' : star_score>0 and 'review' or 'comment',
+ 'comment_or_review' : star_score>0 and 'REVIEW' or 'COMMENT',
+ 'date' : date_creation,
+ 'nickname' : nickname,
+ 'email' : email,
+ 'uid' : id_user,
+ 'recID' : id_bibrec,
+ 'record_details' : record,
+ 'comID' : comID2,
+ 'review_stuff' : star_score>0 and review_stuff or "",
+ 'body' : body.replace(' ','\n'),
+ 'weburl' : weburl
+ }
+
+ from_addr = 'CDS Alert Engine <%s>' % alertengineemail
+ to_addr = adminemail
+
+ from alert_engine import send_email
+ send_email(from_addr, to_addr, out)
+
+def check_recID_is_in_range(recID, errors):
+ """
+ Check that recID is >= 0 or <= -100
+ Append error messages to errors listi
+ @param recID: record id
+ @param errors: list of error tuples (error_id, value)
+ @return boolean (1=true, 0=false)
+ """
+ # Make errors into a list if needed
+ if type(errors) is not list:
+ errors = [errors]
+
+ if type(recID) is int:
+ if recID >= 1 or recID <= -100:
+ return
+ else:
+ errors.append(('ERR_WEBCOMMENT_RECID_INVALID', recID))
+ else:
+ errors.append(('ERR_WEBCOMMENT_RECID_INVALID', recID))
+
+def check_int_arg_is_in_range(value, name, errors, gte_value, lte_value=None):
+ """
+ Check that variable with name 'name' >= gte_value and optionally <= lte_value
+ Append error messages to errors list
+ @param value: variable value
+ @param name: variable name
+ @param errors: list of error tuples (error_id, value)
+ @param gte_value: greater than or equal to value
+ @param lte_value: less than or equal to value
+ @return boolean (1=true, 0=false)
+ """
+ # Make errors into a list if needed
+ if type(errors) is not list:
+ errors = [errors]
+
+ if type(value) is not int or type(gte_value) is not int:
+ errors.append(('ERR_WEBCOMMENT_PROGRAMNING_ERROR',))
+ return 0
+
+ if type(value) is not int:
+ errors.append(('ERR_WEBCOMMENT_ARGUMENT_NAN', value))
+ return 0
+
+ if value < gte_value:
+ errors.append(('ERR_WEBCOMMENT_ARGUMENT_INVALID', value))
+ return 0
+ if lte_value:
+ if type(lte_value) is not int:
+ errors.append(('ERR_WEBCOMMENT_PROGRAMNING_ERROR',))
+ return 0
+ if value > lte_value:
+ errors.append(('ERR_WEBCOMMENT_ARGUMENT_INVALID', value))
+ return 0
+ return 1
+
+def wash_url_argument(var, new_type):
+ """
+ Wash argument into 'new_type', that can be 'list', 'str', or 'int'.
+ If needed, the check 'type(var) is not None' should be done before calling this function
+ @param var: variable value
+ @param new_type: variable type, 'list', 'str' or 'int'
+ @return as much as possible, value var as type new_type
+ If var is a list, will change first element into new_type.
+ If int check unsuccessful, returns 0
+ """
+ out = []
+ if new_type == 'list': # return lst
+ if type(var) is list:
+ out = var
+ else:
+ out = [var]
+ elif new_type == 'str': # return str
+ if type(var) is list:
+ try:
+ out = "%s" % var[0]
+ except:
+ out = ""
+ elif type(var) is str:
+ out = var
+ else:
+ out = "%s" % var
+ elif new_type == 'int': # return int
+ if type(var) is list:
+ try:
+ out = int(var[0])
+ except:
+ out = 0
+ elif type(var) is int:
+ out = var
+ elif type(var) is str:
+ try:
+ out = int(var)
+ except:
+ out = 0
+ else:
+ out = 0
+ elif new_type == 'tuple': # return tuple
+ if type(var) is tuple:
+ out = var
+ else:
+ out = (var,)
+ elif new_type == 'dict': # return dictionary
+ if type(var) is dict:
+ out = var
+ else:
+ out = {0:var}
+ return out
+
diff --git a/modules/webcomment/lib/webcomment_config.py b/modules/webcomment/lib/webcomment_config.py
new file mode 100644
index 000000000..db62f11b6
--- /dev/null
+++ b/modules/webcomment/lib/webcomment_config.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+## $Id$
+## Comments and reviews for records.
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+__lastupdated__ = """FIXME: last updated"""
+
+from config import *
+
+cfg_webcomment_error_messages = \
+{ 'ERR_WEBCOMMENT_RECID_INVALID' : ' %s is an invalid record ID ',
+ 'ERR_WEBCOMMENT_RECID_NAN' : ' Record ID %s is not a number ',
+ 'ERR_WEBCOMMENT_UID_INVALID' : ' %s is an invalid user ID ',
+ 'ERR_WEBCOMMENT_DB_ERROR' : ' %s ',
+ 'ERR_WEBCOMMENT_COMMENTS_NOT_ALLOWED': ' Comments on library record have been disallowed by the Administrator ',
+ 'ERR_WEBCOMMENT_ARGUMENT_NAN' : ' %s is not a number ',
+ 'ERR_WEBCOMMENT_ARGUEMENT_INVALID' : ' %s invalid argument ',
+ 'ERR_WEBCOMMENT_PROGRAMMING_ERROR' : ' Programming error, please inform the Administrator ',
+ 'ERR_WEBCOMMENT_FOR_TESTING_PURPOSES': ' THIS IS FOR TESTING PURPOSES ONLY var1=%s var2=%s var3=%s var4=%s var5=%s var6=%s ',
+ 'ERR_WEBCOMMENT_REPLY_REVIEW' : ' Cannot reply to a review '
+}
+
+cfg_webcomment_warning_messages = \
+{ 'WRN_WEBCOMMENT_INVALID_PAGE_NB' : "Bad page number --> showing first page",
+ 'WRN_WEBCOMMENT_INVALID_NB_RESULTS_PER_PAGE' : "Bad number of results per page --> showing 10 results per page",
+ 'WRN_WEBCOMMENT_INVALID_REVIEW_DISPLAY_ORDER' : "Bad display order --> showing most helpful first",
+ 'WRN_WEBCOMMENT_INVALID_DISPLAY_ORDER' : "Bad display order --> showing oldest first",
+ 'WRN_WEBCOMMENT_FEEDBACK_RECORDED_GREEN_TEXT' : "Your feedback has been recorded, many thanks",
+ 'WRN_WEBCOMMENT_FEEDBACK_NOT_RECORDED_RED_TEXT' : "Your feedback could not be recorded, please try again",
+ 'WRN_WEBCOMMENT_ADD_NO_TITLE' : "You must enter a title",
+ 'WRN_WEBCOMMENT_ADD_NO_SCORE' : "You must choose a score",
+ 'WRN_WEBCOMMENT_ADD_NO_BODY' : "You must enter a text",
+ 'ERR_WEBCOMMENT_DB_INSERT_ERROR' : 'Failed to insert your comment to the database. Please try again.',
+ 'WRN_WEBCOMMENT_ADD_UNKNOWN_ACTION' : 'Unknown action --> showing you the default add comment form',
+ 'WRN_WEBCOMMENT_ADMIN_COMID_NAN' : 'comment ID must be a number, try again',
+ 'WRN_WEBCOMMENT_ADMIN_INVALID_COMID' : 'Invalid comment ID, try again',
+ 'WRN_WEBCOMMENT_ADMIN_COMID_INEXISTANT' : "Comment ID %s does not exist, try again",
+
+}
+
+
diff --git a/modules/webcomment/lib/webcomment_templates.py b/modules/webcomment/lib/webcomment_templates.py
new file mode 100644
index 000000000..903e1fad8
--- /dev/null
+++ b/modules/webcomment/lib/webcomment_templates.py
@@ -0,0 +1,915 @@
+# -*- coding: utf-8 -*-
+## $Id$
+## Comments and reviews for records.
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+__lastupdated__ = """FIXME: last updated"""
+
+import urllib
+import time
+import string
+
+from config import *
+from messages import gettext_set_language, language_list_long
+from bibrankadminlib import addadminbox
+
+class Template:
+ def tmpl_get_first_comments_without_ranking(self, recID, ln, comments, nb_comments_total, warnings):
+ """
+ @param recID: record id
+ @param ln: language
+ @param comments: tuple as returned from webcomment.py/query_retrieve_comments_or_remarks
+ @param nb_comments_total: total number of comments for this record
+ @param warnings: list of warning tuples (warning_msg, arg1, arg2, ...)
+ @return html of comments
+ """
+
+ # load the right message language
+ _ = gettext_set_language(ln)
+
+ # naming data fields of comments
+ c_nickname = 0
+ c_date_creation = 1
+ c_body = 2
+ c_id = 3
+
+ warnings = self.tmpl_warnings(warnings)
+
+ report_link = '''%s/comments.py/report?recid=%s&ln=%s&comid=%%(comid)s&reviews=0''' % (weburl, recID, ln)
+
+ # comments
+ comment_rows = ''' '''
+ for comment in comments:
+ comment_rows += '''
+
+ Average review score: based on %(nb_comments_total)s reviews
+ Readers found the following %(nb_helpful)s review%(s)s to be most helpful.
+
+
+ %(comment_rows)s
+
+ %(view_all_comments_link)s
+ %(write_button_form)s
+ ''' % \
+ { 'comment_title' : "Rate this document:",
+ 'avg_score_img' : avg_score_img,
+ 'avg_score' : avg_score,
+ 'nb_comments_total' : nb_comments_total,
+ 'recID' : recID,
+ 'view_all_comments' : "view all %s reviews" % (nb_comments_total,),
+ 'write_comment' : "write a review",
+ 'comment_rows' : comment_rows,
+ 's' : cfg_webcomment_nb_reviews_in_detailed_view>1 and 's' or "",
+ 'tab' : ' '*4,
+ 'weburl' : weburl,
+ 'nb_helpful' : cfg_webcomment_nb_reviews_in_detailed_view>1 and cfg_webcomment_nb_reviews_in_detailed_view or "",
+ 'view_all_comments_link': nb_comments_total>0 and """View all %s reviews """ \
+ % (weburl, recID, ln, nb_comments_total) or "",
+ 'write_button_form' : write_button_form
+ }
+ else:
+ out = '''
+
+
Rate this document:
+ Have the honor of being the first to review this document.
+ %s
+ ''' % (write_button_form,)
+ return out
+
+ def tmpl_get_comment_without_ranking(self, recID, ln, nickname, date_creation, body, reply_link=None, report_link=None):
+ """
+ private function
+ @param ln: language
+ @param nickname: nickname
+ @param date_creation: date comment was written
+ @param body: comment body
+ @param reply_link: if want reply and report, give the http links
+ @param repot_link: if want reply and report, give the http links
+ @return html table of comment
+ """
+ # load the right message language
+ _ = gettext_set_language(ln)
+
+ date_creation = str(date_creation)
+ date_creation_data = date_creation[:18]
+ date_creation_data = time.strptime(str(date_creation_data), "%Y-%m-%d %H:%M:%S")
+ date_creation_data = time.strftime("%d %b %Y %H:%M:%S %Z", date_creation_data)
+ date_creation = str(date_creation_data) + date_creation[22:] # 22 to get rid of the .00 after time
+
+ out = ''' '''
+
+ # load the right message language
+ #_ = gettext_set_language(ln)
+
+ out += """
+
+
+
%(nickname)s wrote on %(date_creation)s
+
%(links)s
+
+
+
%(body)s
+
+
""" % \
+ { #! FIXME put send_a_private_message view_shared_baskets
+ 'nickname' : nickname,
+ 'date_creation' : date_creation,
+ 'body' : body,
+ 'links' : (report_link!=None and reply_link!=None) and "Report this | Reply" % (report_link, reply_link) or ""
+ }
+ return out
+
+
+ def tmpl_get_comment_with_ranking(self, recID, ln, nickname, date_creation, body, nb_votes, vote_value, star_score, star_note):
+ """
+ private function
+ @param ln: language
+ @param nickname: nickname
+ @param date_creation: date comment was written
+ @param body: comment body
+ @param nb_votes: total number of votes for this review
+ @param vote_value: number of positive votes for this record
+ @param star_score: star score for this record
+ @param star_note: title of review
+ @return html table of review
+ """
+ # load the right message language
+ _ = gettext_set_language(ln)
+
+ if star_score > 0:
+ star_score_img = 'stars-' + str(star_score) + '-0.gif'
+ else:
+ star_score_img = 'stars-except.gif'
+
+ out = """"""
+ date_creation = str(date_creation)
+ date_creation_data = date_creation[:18]
+ date_creation_data = time.strptime(str(date_creation_data), "%Y-%m-%d %H:%M:%S")
+ date_creation_data = time.strftime("%d %b %Y %H:%M:%S %Z", date_creation_data)
+ date_creation = str(date_creation_data) + date_creation[22:]
+
+ # load the right message language
+ #_ = gettext_set_language(ln)
+
+ out += """
+
+
+
+ %(star_note)s
+ Reviewed by %(nickname)s on %(date_creation)s
+ %(vote_value)s out of %(nb_votes)s people found this review useful.
+
+
+
+
%(body)s
+
+
+ """ % \
+ { #! FIXME put send_a_private_message view_shared_baskets
+ 'nickname' : nickname,
+ 'weburl' : weburl,
+ 'star_score_img': star_score_img,
+ 'date_creation' : date_creation,
+ 'body' : body,
+ 'nb_votes' : nb_votes,
+ 'star_score' : star_score,
+ 'star_note' : star_note,
+ 'vote_value' : vote_value<0 and "0" or vote_value
+ }
+ return out
+
+ def tmpl_get_comments(self, recID, ln, nb_per_page, page, nb_pages, display_order, display_since, cfg_webcomment_allow_reviews,
+ comments, total_nb_comments, avg_score, warnings, border=0, reviews=0):
+ """
+ Get table of all comments
+ @param recID: record id
+ @param ln: language
+ @param nb_per_page: number of results per page
+ @param page: page number
+ @param display_order: hh = highest helpful score, review only
+ lh = lowest helpful score, review only
+ hs = highest star score, review only
+ ls = lowest star score, review only
+ od = oldest date
+ nd = newest date
+ @param display_since: all= no filtering by date
+ nd = n days ago
+ nw = n weeks ago
+ nm = n months ago
+ ny = n years ago
+ where n is a single digit integer between 0 and 9
+ @param cfg_webcomment_allow_reviews: is ranking enable, get from config.py/cfg_webcomment_allow_reviews
+ @param comments: tuple as returned from webcomment.py/query_retrieve_comments_or_remarks
+ @param total_nb_comments: total number of comments for this record
+ @param avg_score: average score of reviews for this record
+ @param warnings: list of warning tuples (warning_msg, color)
+ @param border: boolean, active if want to show border around each comment/review
+ @param reviews: booelan, enabled for reviews, disabled for comments
+ """
+ # load the right message language
+ _ = gettext_set_language(ln)
+
+ # naming data fields of comments
+ if reviews:
+ c_nickname = 0
+ c_date_creation = 1
+ c_body = 2
+ c_vote_value = 3
+ c_nb_votes = 4
+ c_star_score = 5
+ c_star_note = 6
+ c_id = 7
+ else:
+ c_nickname = 0
+ c_date_creation = 1
+ c_body = 2
+ c_id = 3
+
+ # voting links
+ useful_dict = { 'weburl' : weburl,
+ 'recID' : recID,
+ 'ln' : ln,
+ 'do' : display_order,
+ 'ds' : display_since,
+ 'nb' : nb_per_page,
+ 'p' : page,
+ 'reviews' : reviews
+ }
+ useful_yes = '''Yes''' % useful_dict
+ useful_no = '''No''' % useful_dict
+ warnings = self.tmpl_warnings(warnings)
+
+ ## record details
+ from search_engine import print_record
+ record_details = print_record(recID=recID, format='hb')
+
+ link_dic = { 'weburl' : weburl,
+ 'module' : 'comments.py',
+ 'function' : 'index',
+ 'arguments' : 'recid=%s&do=%s&ds=%s&nb=%s&reviews=%s' % (recID, display_order, display_since, nb_per_page, reviews),
+ 'arg_page' : '&p=%s' % page,
+ 'page' : page }
+
+ ## comments table
+ comments_rows = ''' '''
+ for comment in comments:
+ comments_rows += '''
+
+
+
+ ''' % \
+ { 'record_details' : record_details,
+ 'write_button_form' : write_button_form,
+ 'write_button_form_again' : total_nb_comments>3 and write_button_form or "",
+ 'comments_rows' : comments_rows,
+ 'total_nb_comments' : total_nb_comments,
+ 'comments_or_reviews' : comments_or_reviews,
+ 'comments_or_reviews_title' : comments_or_reviews[0].upper() + comments_or_reviews[1:],
+ 'weburl' : weburl,
+ 'module' : "comments.py",
+ 'recid' : recID,
+ 'ln' : ln,
+ 'border' : border,
+ 'ranking_avg' : ranking_average }
+ form = '''
+ Display
+ comments per page that are
+ and sorted by
+ ''' % \
+ (reviews==1 and '''
+
+
+
+
+ ''' or '''
+ ''')
+ form_link = "%(weburl)s/%(module)s/%(function)s" % link_dic
+ form = self.createhiddenform(action=form_link, method="Get", text=form, button='Go', recid=recID, p=1)
+ pages = '''
+
+ Viewing %(comments_or_reviews)s %(results_nb_lower)s-%(results_nb_higher)s
+ %(page_links)s
+
+ ''' % \
+ { 'page_links' : "Page: " + page_links ,
+ 'comments_or_reviews' : not reviews and 'comments' or 'reviews',
+ 'results_nb_lower' : len(comments)>0 and ((page-1) * nb_per_page)+1 or 0,
+ 'results_nb_higher' : page == nb_pages and (((page-1) * nb_per_page) + len(comments)) or (page * nb_per_page) }
+
+ if nb_pages > 1:
+ #body = warnings + body + form + pages
+ body = warnings + body + pages
+ else:
+ body = warnings + body
+
+ return body
+
+
+ def createhiddenform(self, action="", method="Get", text="", button="confirm", cnfrm='', **hidden):
+ """
+ create select with hidden values and submit button
+ @param action: name of the action to perform on submit
+ @param method: 'get' or 'post'
+ @param text: additional text, can also be used to add non hidden input
+ @param button: value/caption on the submit button
+ @param cnfrm: if given, must check checkbox to confirm
+ @param **hidden: dictionary with name=value pairs for hidden input
+ @return html form
+ """
+
+ output = '\n'
+
+ return output
+
+ def tmpl_warnings(self, warnings):
+ """
+ Prepare the warnings list
+ @param warnings: list of warning tuples (warning_msg, arg1, arg2, etc)
+ @return html string of warnings
+ """
+ from errorlib import get_msgs_for_code_list
+ span_class = 'important'
+ out = ""
+ if type(warnings) is not list:
+ warnings = [warnings]
+ if len(warnings) > 0:
+ warnings_parsed = get_msgs_for_code_list(warnings, 'warning')
+ for (warning_code, warning_text) in warnings_parsed:
+ if not warning_code.startswith('WRN'): #display only warnings that begin with WRN to user
+ continue
+ if warning_code.find('GREEN_TEXT') >= 0:
+ span_class = "exampleleader"
+ elif warning_code.find('RED_TEXT') >= 0:
+ span_class = "important"
+ out += '''
+ %(warning)s ''' % \
+ { 'span_class' : span_class,
+ 'warning' : warning_text }
+ return out
+ else:
+ return ""
+
+ def tmpl_add_comment_form(self, recID, uid, nickname, ln, msg, warnings):
+ """
+ Add form for comments
+ @param recID: record id
+ @param uid: user id
+ @param ln: language
+ @param msg: comment body contents for when refreshing due to warning
+ @param warnings: list of warning tuples (warning_msg, color)
+ @return html add comment form
+ """
+ link_dic = { 'weburl' : weburl,
+ 'module' : 'comments.py',
+ 'function' : 'add',
+ 'arguments' : 'recid=%s&ln=%s&action=%s&reviews=0' % (recID, ln, 'SUBMIT') }
+
+ from search_engine import print_record
+ record_details = print_record(recID=recID, format='hb')
+
+ warnings = self.tmpl_warnings(warnings)
+ form = '''
+
+
Article:
+
%(record)s
+
Your nickname: %(nickname)s
+
Comment:
+
+
+
''' % { 'msg' : msg!='None' and urllib.unquote(msg) or "",
+ 'nickname' : nickname,
+ 'record' : record_details }
+ form_link = "%(weburl)s/%(module)s/%(function)s?%(arguments)s" % link_dic
+ form = self.createhiddenform(action=form_link, method="Post", text=form, button='Add comment')
+ return warnings + form
+
+ def tmpl_add_comment_form_with_ranking(self, recID, uid, nickname, ln, msg, score, note, warnings):
+ """
+ Add form for reviews
+ @param recID: record id
+ @param uid: user id
+ @param ln: language
+ @param msg: comment body contents for when refreshing due to warning
+ @param score: review score
+ @param note: review title
+ @param warnings: list of warning tuples (warning_msg, color)
+ @return html add review form
+ """
+ link_dic = { 'weburl' : weburl,
+ 'module' : 'comments.py',
+ 'function' : 'add',
+ 'arguments' : 'recid=%s&ln=%s&action=%s&reviews=1' % (recID, ln, 'SUBMIT') }
+ warnings = self.tmpl_warnings(warnings)
+
+ from search_engine import print_record
+ record_details = print_record(recID=recID, format='hb')
+
+ form = '''
+
+
Article:
+
%(record)s
+
Select your score:
+
+
Your nickname: %(nickname)s
+
Give a title to your review:
+
+
Write your review:
+
+
+
''' % { 'note' : note!='None' and note or "",
+ 'msg' : msg!='None' and msg or "",
+ 'nickname' : nickname,
+ 'record' : record_details }
+ form_link = "%(weburl)s/%(module)s/%(function)s?%(arguments)s" % link_dic
+ form = self.createhiddenform(action=form_link, method="Post", text=form, button='Add Review')
+ return warnings + form
+
+ def tmpl_add_comment_successful(self, recID, ln, reviews):
+ """
+ @param recID: record id
+ @param ln: language
+ @return html page of successfully added comment/review
+ """
+ link_dic = { 'weburl' : weburl,
+ 'module' : 'comments.py',
+ 'function' : 'display',
+ 'arguments' : 'recid=%s&ln=%s&do=od&reviews=%s' % (recID, ln, reviews) }
+ link = "%(weburl)s/%(module)s/%(function)s?%(arguments)s" % link_dic
+ return '''Your %s was successfully added
Back to record''' % (reviews==1 and 'review' or 'comment', link)
+
+ def tmpl_admin_index(self, ln):
+ """
+ """
+ # load the right message language
+ _ = gettext_set_language(ln)
+
+ out = '''
+
'''
+ if cfg_webcomment_allow_comments or cfg_webcomment_allow_reviews:
+ if cfg_webcomment_allow_comments:
+ out += '''
+
+ '''
+ out = out % { 'weburl' : weburl,
+ 'ln' : ln }
+ else:
+ out += '''
+
Comments and reviews are disabled
'''
+ out += '''
'''
+ return addadminbox('Menu', [out])
+
+
+ def tmpl_admin_delete_form(self, ln, warnings):
+ """
+ @param warnings: list of warning_tuples where warning_tuple is (warning_message, text_color)
+ see tmpl_warnings, color is optional
+ """
+ # load the right message language
+ _ = gettext_set_language(ln)
+
+ warnings = self.tmpl_warnings(warnings)
+
+ out = '''
+
+ Please enter the ID of the comment/review so that you can view it before deciding to delete it or not
+ '''
+ form = '''
+
+
+
Comment ID:
+
+
+
+
+
+
+
+ '''
+ form_link = "%s/admin/webcomment/webcommentadmin.py/delete?ln=%s" % (weburl, ln)
+ form = self.createhiddenform(action=form_link, method="Get", text=form, button='View Comment')
+ return warnings + out + form
+
+ def tmpl_admin_users(self, ln, users_data):
+ """
+ @param users_data: tuple of ct, i.e. (ct, ct, ...)
+ where ct is a tuple (total_number_reported, total_comments_reported, total_reviews_reported, total_vote_value_of_reported,
+ total_nb_votes_of_reported, user_id, user_email, user_nickname)
+ sorted by order of ct having highest total_number_reported
+ """
+ u_reports = 0
+ u_comment_reports = 1
+ u_reviews_reports = 2
+ u_vote_value = 3
+ u_nb_votes = 4
+ u_uid = 5
+ u_email = 6
+ u_nickname = 7
+
+ if not users_data:
+ return self.tmpl_warnings([("There have been no reports so far.", 'green')])
+
+ user_rows = ""
+ for utuple in users_data:
+ com_link = '''View all %s reported comments ''' % \
+ (weburl, ln, utuple[u_uid], utuple[u_comment_reports])
+ rev_link = '''View all %s reported reviews''' % \
+ (weburl, ln, utuple[u_uid], utuple[u_reviews_reports])
+ user_rows += '''
+
+
%(nickname)s
+
%(email)s
+
%(uid)s
+ %(review_row)s
+
%(reports)s
+
%(com_link)s%(rev_link)s
+
+ ''' % { 'nickname' : len(utuple[u_nickname])>0 and utuple[u_nickname] or utuple[u_email].split('@')[0],
+ 'email' : utuple[u_email],
+ 'uid' : utuple[u_uid],
+ 'reports' : utuple[u_reports],
+ 'review_row': cfg_webcomment_allow_reviews>0 and "
%s
%s
%s
" % \
+ (utuple[u_vote_value], utuple[u_nb_votes]-utuple[u_vote_value], utuple[u_nb_votes]) or "",
+ 'weburl' : weburl,
+ 'ln' : ln,
+ 'com_link' : cfg_webcomment_allow_comments>0 and com_link or "",
+ 'rev_link' : cfg_webcomment_allow_reviews>0 and rev_link or ""
+ }
+
+ out = '''
+
+ Here is a list, sorted by total number of reports, of all users who have had at least one report to one of their comments.
+
+
+
+
Nickname
+
Email
+
User ID
+ %(reviews_columns)s
+
Total number of reports
+
View all user's reported comments/reviews
+
+ %(user_rows)s
+
+ ''' % { 'reviews_columns' : cfg_webcomment_allow_reviews>0 and
+ "
Number positive votes
Number negative votes
Total number votes
" or "",
+ 'user_rows' : user_rows
+ }
+ return out
+
+ def tmpl_admin_comments(self, ln, uid, comID, comment_data, reviews):
+ """
+ @param comment_data: same type of tuple as that which is returned by webcomment.py/query_retrieve_comments_or_remarks i.e.
+ tuple of comment where comment is
+ tuple (nickname, date_creation, body, id) if ranking disabled or
+ tuple (nickname, date_creation, body, vote_value, nb_votes, star_score, star_note, id)
+ """
+ comments = self.tmpl_get_comments(recID=-1, ln=ln, nb_per_page=0, page=1, nb_pages=1, display_order='od', display_since='all',
+ cfg_webcomment_allow_reviews=cfg_webcomment_allow_reviews, comments=comment_data, total_nb_comments=len(comment_data),
+ avg_score=-1, warnings=[], border=1, reviews=reviews)
+ comments = comments.split("")[1]
+ comments = comments.split("")[0]
+
+ form_link = "%s/admin/webcomment/webcommentadmin.py/del_com?ln=%s" % (weburl, ln)
+ form = self.createhiddenform(action=form_link, method="Post", text=comments, button='Delete Selected Comments')
+
+ if uid > 0:
+ header = " Here are the reported %s of user %s
" % (reviews>0 and "reviews" or "comments", uid)
+ if comID > 0:
+ header = " Here is comment/review %s
" % comID
+ if uid > 0 and comID > 0:
+ header = " Here is comment/review %s written by user %s
" % (comID, uid)
+ if uid ==0 and comID == 0:
+ header = " Here are all reported %s sorted by most reported
" % (reviews>0 and "reviews" or "comments",)
+
+ return header + form
+
+ def tmpl_admin_del_com(self, del_res):
+ """
+ @param del_res: list of the following tuple (comment_id, was_successfully_deleted),
+ was_successfully_deleted is boolean (0=false, >0=true
+ """
+ table_rows = ''' '''
+ for deltuple in del_res:
+ table_rows += '''
+
%s
%s
+ ''' % (deltuple[0], deltuple[1]>0 and "Yes" or "No")
+
+ out = '''
+
+
comment ID
successfully deleted
+ %s
+
''' % (table_rows)
+
+ return out
+
+ def createhiddenform(self, action="", method="Get", text="", button="confirm", cnfrm='', **hidden):
+ """
+ create select with hidden values and submit button
+ @param action: name of the action to perform on submit
+ @param method: 'get' or 'post'
+ @param text: additional text, can also be used to add non hidden input
+ @param button: value/caption on the submit button
+ @param cnfrm: if given, must check checkbox to confirm
+ @param **hidden: dictionary with name=value pairs for hidden input
+ @return html form
+ """
+
+ output = '\n'
+
+ return output
+
+
diff --git a/modules/webcomment/lib/webcomment_tests.py b/modules/webcomment/lib/webcomment_tests.py
new file mode 100644
index 000000000..7a4c02e69
--- /dev/null
+++ b/modules/webcomment/lib/webcomment_tests.py
@@ -0,0 +1,31 @@
+import webcomment
+import unittest
+
+class TestWashQueryParameters(unittest.TestCase):
+ """Test for washing of search query parameters."""
+
+ def test_wash_url_argument(self):
+ """search engine - washing of URL arguments"""
+ self.assertEqual(1, search_engine.wash_url_argument(['1'],'int'))
+ self.assertEqual("1", search_engine.wash_url_argument(['1'],'str'))
+ self.assertEqual(['1'], search_engine.wash_url_argument(['1'],'list'))
+ self.assertEqual(0, search_engine.wash_url_argument('ellis','int'))
+ self.assertEqual("ellis", search_engine.wash_url_argument('ellis','str'))
+ self.assertEqual(["ellis"], search_engine.wash_url_argument('ellis','list'))
+ self.assertEqual(0, search_engine.wash_url_argument(['ellis'],'int'))
+ self.assertEqual("ellis", search_engine.wash_url_argument(['ellis'],'str'))
+ self.assertEqual(["ellis"], search_engine.wash_url_argument(['ellis'],'list'))
+
+ def test_wash_pattern(self):
+ """search engine - washing of query patterns"""
+ self.assertEqual("Ellis, J", search_engine.wash_pattern('Ellis, J'))
+ self.assertEqual("ell", search_engine.wash_pattern('ell*'))
+
+def create_test_suite():
+ """Return test suite for the search engine."""
+ return unittest.TestSuite((unittest.makeSuite(TestWashQueryParameters,'test'),
+ unittest.makeSuite(TestStripAccents,'test'),
+ unittest.makeSuite(TestQueryParser,'test')))
+
+if __name__ == "__main__":
+ unittest.TextTestRunner(verbosity=2).run(create_test_suite())
diff --git a/modules/webcomment/lib/webcommentadminlib.py b/modules/webcomment/lib/webcommentadminlib.py
new file mode 100644
index 000000000..53b310411
--- /dev/null
+++ b/modules/webcomment/lib/webcommentadminlib.py
@@ -0,0 +1,232 @@
+# -*- coding: utf-8 -*-
+## $Id$
+## Comments and reviews for records.
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+__lastupdated__ = """FIXME: last updated"""
+
+
+from bibrankadminlib import check_user
+ #write_outcome,modify_translations,get_def_name,get_i8n_name,get_name,get_rnk_nametypes,get_languages,check_user,is_adminuser,
+ #adderrorbox,addadminbox,tupletotable,tupletotable_onlyselected,addcheckboxes,createhiddenform,serialize_via_numeric_array_dumps,
+ #serialize_via_numeric_array_compr,serialize_via_numeric_array_escape,serialize_via_numeric_array,deserialize_via_numeric_array,
+ #serialize_via_marshal,deserialize_via_marshal
+from config import *
+from webcomment import wash_url_argument, query_get_comment, query_get_user_contact_info
+from mod_python import apache
+from dbquery import run_sql
+
+import template
+webcomment_templates = template.load('webcomment')
+
+def getnavtrail(previous = ''):
+ """Get the navtrail"""
+
+ navtrail = """Admin Area > WebComment Admin """ % (weburl, weburl)
+ navtrail = navtrail + previous
+ return navtrail
+
+def perform_request_index(ln=cdslang):
+ """
+ """
+ return webcomment_templates.tmpl_admin_index(ln=ln)
+
+def perform_request_delete(ln=cdslang, comID=-1):
+ """
+ """
+ warnings = []
+
+ ln = wash_url_argument(ln, 'str')
+ comID = wash_url_argument(comID, 'int')
+
+ if comID is not None:
+ if comID <= 0:
+ if comID != -1:
+ warnings.append(("WRN_WEBCOMMENT_ADMIN_INVALID_COMID",))
+ return (webcomment_templates.tmpl_admin_delete_form(ln, warnings),None, warnings)
+
+ comment = query_get_comment(comID)
+ if comment:
+ c_star_score = 5
+ if comment[c_star_score] > 0:
+ reviews = 1
+ else:
+ reviews = 0
+ return (perform_request_comments(ln=ln, comID=comID, reviews=reviews), None, warnings)
+ else:
+ warnings.append(('WRN_WEBCOMMENT_ADMIN_COMID_INEXISTANT', comID))
+ return (webcomment_templates.tmpl_admin_delete_form(ln, warnings), None, warnings)
+ else:
+ return (webcomment_templates.tmpl_admin_delete_form(ln, warnings), None, warnings)
+
+def perform_request_users(ln=cdslang):
+ """
+ """
+ ln = wash_url_argument(ln, 'str')
+
+ users_data = query_get_users_reported()
+
+ return webcomment_templates.tmpl_admin_users(ln=ln, users_data=users_data)
+
+def query_get_users_reported():
+ """
+ Get the users who have been reported at least one.
+ @return tuple of ct, i.e. (ct, ct, ...)
+ where ct is a tuple (total_number_reported, total_comments_reported, total_reviews_reported,
+ total_vote_value_of_reported, total_nb_votes_of_reported, user_id, user_email, user_nickname)
+ sorted by order of ct having highest total_number_reported
+ """
+ query1 = "SELECT c.nb_reported, c.vote_value, c.nb_votes, u.id, u.email, u.nickname, c.star_score " \
+ "FROM user AS u, cmtRECORDCOMMENT AS c " \
+ "WHERE c.id_user=u.id AND c.nb_reported > 0 " \
+ "ORDER BY u.id "
+ res1 = run_sql(query1)
+ if type(res1) is None:
+ return ()
+ users = {}
+ for cmt in res1:
+ uid = int(cmt[3])
+ if users.has_key(uid):
+ users[uid] = (users[uid][0]+int(cmt[0]), int(cmt[6])>0 and users[uid][1] or users[uid][1]+1, int(cmt[6])>0 and users[uid][2]+1 or users[uid][2],
+ users[uid][3]+int(cmt[1]), users[uid][4]+int(cmt[2]), int(cmt[3]), cmt[4], cmt[5])
+ else:
+ users[uid] = (int(cmt[0]), int(cmt[6])==0 and 1 or 0, int(cmt[6])>0 and 1 or 0, int(cmt[1]), int(cmt[2]), int(cmt[3]), cmt[4], cmt[5])
+ users = users.values()
+ users.sort()
+ users.reverse()
+ users = tuple(users)
+ return users
+
+def perform_request_comments(ln=cdslang, uid="", comID="", reviews=0):
+ """
+ """
+ warning = []
+
+ ln = wash_url_argument(ln, 'str')
+ uid = wash_url_argument(uid, 'int')
+ comID = wash_url_argument(comID, 'int')
+ reviews = wash_url_argument(reviews, 'int')
+
+ comments = query_get_comments(uid, comID, reviews)
+ return webcomment_templates.tmpl_admin_comments(ln=ln, uid=uid, comID=comID, comment_data=comments, reviews=reviews)
+
+def query_get_comments(uid, comID, reviews):
+ """
+ private funciton
+ Get the reported comments of user uid or get the comment comID or get the comment comID which was written by user uid
+ @return same type of tuple as that which is returned by webcomment.py/query_retrieve_comments_or_remarks i.e.
+ tuple of comment where comment is
+ tuple (nickname, date_creation, body, id) if ranking disabled or
+ tuple (nickname, date_creation, body, vote_value, nb_votes, star_score, star_note, id)
+ """
+ query1 = "SELECT u.nickname, c.date_creation, c.body, %s c.id, c.id_bibrec, c.id_user, " \
+ "c.nb_reported, u.id, u.email, u.nickname " \
+ "FROM user AS u, cmtRECORDCOMMENT AS c " \
+ "WHERE c.id_user=u.id %s %s %s " \
+ "ORDER BY c.nb_reported DESC, c.vote_value DESC, c.date_creation "
+ params1 = ( reviews>0 and " c.vote_value, c.nb_votes, c.star_score, c.star_note, " or "",
+ reviews>0 and " AND c.star_score>0 " or " AND c.star_score=0 ",
+ uid>0 and " AND c.id_user=%s " % uid or "",
+ comID>0 and " AND c.id=%s " % comID or " AND c.nb_reported>0 " )
+ res1 = run_sql(query1 % params1)
+ res2 = []
+ for qtuple1 in res1:
+ # exceptional use of html here for giving admin extra information
+ new_info = """ user (nickname=%s, email=%s, id=%s)
+ comment/review id = %s
+ commented this record (id=%s)
+
+
+
+
reported %s times
+
+
+
+
+
+
""" \
+ % (len(qtuple1[0])>0 and qtuple1[0] or qtuple1[-2].split('@')[0],
+ qtuple1[-2], qtuple1[-5], qtuple1[-7], weburl, qtuple1[-6], qtuple1[-6], qtuple1[-4], qtuple1[-7])
+ if reviews:
+ qtuple2 = (len(qtuple1[0])>0 and qtuple1[0] or qtuple1[-2].split('@')[0],
+ str(qtuple1[1])+new_info, qtuple1[2], qtuple1[3], qtuple1[4], qtuple1[5], qtuple1[6], qtuple1[7])
+ else:
+ qtuple2 = (len(qtuple1[0])>0 and qtuple1[0] or qtuple1[-2].split('@')[0],
+ str(qtuple1[1])+new_info, qtuple1[2], qtuple1[3])
+
+ res2.append(qtuple2)
+ return tuple(res2)
+
+def perform_request_del_com(ln=cdslang, comIDs=[]):
+ """
+ private function
+ Delete the comments and say whether successful or not
+ @param ln: language
+ @param comIDs: list of comment ids
+ """
+ ln = wash_url_argument(ln, 'str')
+ comIDs = wash_url_argument(comIDs, 'list')
+ # map ( fct, list, arguments of function)
+ comIDs = map(wash_url_argument, comIDs, ('int '*len(comIDs)).split(' ')[:-1])
+
+ if not comIDs:
+ comIDs = map(coerce, comIDs, ('0 '*len(comIDs)).split(' ')[:-1])
+ return webcomment_templates.tmpl_admin_del_com(del_res=comIDs)
+
+ del_res=[]
+ for id in comIDs:
+ del_res.append((id, query_delete_comment(id)))
+ return webcomment_templates.tmpl_admin_del_com(del_res=del_res)
+
+def query_delete_comment(comID):
+ """
+ delete comment with id comID
+ @return integer 1 if successful, integer 0 if not
+ """
+ query1 = "DELETE FROM cmtRECORDCOMMENT WHERE id=%s"
+ params1 = (comID,)
+ res1 = run_sql(query1, params1)
+ return int(res1)
+
+def getnavtrail(previous = ''):
+ """
+ Get the navtrail
+ """
+
+ navtrail = """Admin Area > WebComment Admin """ % (weburl, weburl)
+ navtrail = navtrail + previous
+ return navtrail
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/webcomment/web/.cvsignore b/modules/webcomment/web/.cvsignore
new file mode 100644
index 000000000..d4766d920
--- /dev/null
+++ b/modules/webcomment/web/.cvsignore
@@ -0,0 +1,5 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
diff --git a/modules/webcomment/web/Makefile.am b/modules/webcomment/web/Makefile.am
new file mode 100644
index 000000000..27cee6f76
--- /dev/null
+++ b/modules/webcomment/web/Makefile.am
@@ -0,0 +1,28 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+SUBDIRS = admin
+
+webappdir = $(WEBDIR)
+
+webapp_DATA = comments.py
+
+EXTRA_DIST = $(webapp_DATA)
+
+CLEANFILES = *~ *.tmp comments.pyc
diff --git a/modules/webcomment/web/admin/.cvsignore b/modules/webcomment/web/admin/.cvsignore
new file mode 100644
index 000000000..92fecb09d
--- /dev/null
+++ b/modules/webcomment/web/admin/.cvsignore
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
+*.html
diff --git a/modules/webcomment/web/admin/Makefile.am b/modules/webcomment/web/admin/Makefile.am
new file mode 100644
index 000000000..302ce3402
--- /dev/null
+++ b/modules/webcomment/web/admin/Makefile.am
@@ -0,0 +1,29 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+webappdir = $(WEBDIR)/admin/webcomment
+
+webapp_DATA = index.html webcommentadmin.py
+
+EXTRA_DIST = index.html.wml webcommentadmin.py
+
+CLEANFILES = index.html *~ *.tmp
+
+%.html: %.html.wml $(top_srcdir)/config/config.wml $(top_builddir)/config/configbis.wml
+ $(WML) -o\(ALL-LANG_*\)+LANG_EN:$@ $<
diff --git a/modules/webcomment/web/admin/index.html.wml b/modules/webcomment/web/admin/index.html.wml
new file mode 100644
index 000000000..53ab2ae09
--- /dev/null
+++ b/modules/webcomment/web/admin/index.html.wml
@@ -0,0 +1,38 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+#include "cdspage.wml" \
+ title="WebComment Admin" \
+ navtrail_previous_links="/admin/>" \
+ navbar_name="admin" \
+ navbar_select="webcomment"
+
+
+ This is the gate to the admin area for WebComment. You need to
+ login to enter.
+
Everything you want to know about WebComment administration
+
diff --git a/modules/webcomment/web/admin/webcommentadmin.py b/modules/webcomment/web/admin/webcommentadmin.py
new file mode 100644
index 000000000..0c310e589
--- /dev/null
+++ b/modules/webcomment/web/admin/webcommentadmin.py
@@ -0,0 +1,168 @@
+# -*- coding: utf-8 -*-
+## $Id$
+## Comments and reviews for records.
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+__lastupdated__ = """$FIXME $"""
+
+from cdsware.webcommentadminlib import *
+from cdsware.webpage import page, create_error_box
+from cdsware.config import weburl,cdslang
+from cdsware.webuser import getUid, page_not_authorized
+
+def index(req, ln=cdslang):
+ """
+ Menu of admin options
+ @param ln: language
+ """
+ navtrail_previous_links = getnavtrail() + """ > Comment Management""" % (weburl,)
+
+ try:
+ uid = getUid(req)
+ except MySQLdb.Error, e:
+ return error_page(req)
+
+ (auth_code, auth_msg) = check_user(uid,'cfgwebcomment')
+ if not auth_code:
+ return page(title="Comment Management",
+ body=perform_request_index(ln=ln),
+ uid=uid,
+ language=ln,
+ urlargs=req.args,
+ navtrail = navtrail_previous_links,
+ lastupdated=__lastupdated__)
+ else:
+ return page_not_authorized(req=req, text=auth_msg, navtrail=navtrail_previous_links)
+
+def delete(req, ln=cdslang, comid=""):
+ """
+ Delete a comment by giving its comment id
+ @param ln: language
+ @param comid: comment id
+ """
+ navtrail_previous_links = getnavtrail() + """ > Comment Management""" % (weburl,)
+
+ try:
+ uid = getUid(req)
+ except MySQLdb.Error, e:
+ return error_page(req)
+
+ (auth_code, auth_msg) = check_user(uid,'cfgwebcomment')
+ if not auth_code:
+ (body, errors, warnings) = perform_request_delete(ln=ln, comID=comid)
+ return page(title="Delete Comment",
+ body=body,
+ uid=uid,
+ language=ln,
+ urlargs=req.args,
+ navtrail = navtrail_previous_links,
+ req = req,
+ errors = errors,
+ warnings = warnings,
+ lastupdated=__lastupdated__)
+ else:
+ return page_not_authorized(req=req, text=auth_msg, navtrail=navtrail_previous_links)
+
+
+def comments(req, ln=cdslang, uid="", comid="", reviews=0):
+ """
+ View reported comments, filter by either user or a specific comment (only one given at a time)
+ @param ln: language
+ @param uid: user id
+ @param comid: comment id
+ @param reviews: boolean enabled for reviews, disabled for comments
+ """
+ navtrail_previous_links = getnavtrail() + """ > Comment Management""" % (weburl,)
+
+ try:
+ auid = getUid(req)
+ except MySQLdb.Error, e:
+ return error_page(req)
+
+ (auth_code, auth_msg) = check_user(auid,'cfgwebcomment')
+ if not auth_code:
+ return page(title="View all Reported %s" % (reviews>0 and "Reviews" or "Comments",),
+ body=perform_request_comments(ln=ln, uid=uid, comID=comid, reviews=reviews),
+ uid=uid,
+ language=ln,
+ urlargs=req.args,
+ navtrail = navtrail_previous_links,
+ lastupdated=__lastupdated__)
+ else:
+ return page_not_authorized(req=req, text=auth_msg, navtrail=navtrail_previous_links)
+
+
+def users(req, ln=cdslang):
+ """
+ View a list of all the users that have been reported, sorted by most reported
+ @param ln: language
+ """
+ navtrail_previous_links = getnavtrail() + """ > Comment Management""" % (weburl,)
+
+ try:
+ uid = getUid(req)
+ except MySQLdb.Error, e:
+ return error_page(req)
+
+ (auth_code, auth_msg) = check_user(uid,'cfgwebcomment')
+ if not auth_code:
+ return page(title="View all Reported Users",
+ body=perform_request_users(ln=ln),
+ uid=uid,
+ language=ln,
+ urlargs=req.args,
+ navtrail = navtrail_previous_links,
+ lastupdated=__lastupdated__)
+ else:
+ return page_not_authorized(req=req, text=auth_msg, navtrail=navtrail_previous_links)
+
+def del_com(req, ln=cdslang, **hidden):
+ """
+ private funciton
+ Delete a comment
+ @param ln: language
+ @param **hidden: ids of comments to delete sent as individual variables comidX=on, where X is id
+ """
+ navtrail_previous_links = getnavtrail() + """ > Comment Management""" % (weburl,)
+
+ try:
+ uid = getUid(req)
+ except MySQLdb.Error, e:
+ return error_page(req)
+
+ (auth_code, auth_msg) = check_user(uid,'cfgwebcomment')
+ if not auth_code:
+ comIDs = []
+ args = hidden.keys()
+ for var in args:
+ try:
+ comIDs.append(int(var.split('comid')[1]))
+ except:
+ pass
+ return page(title="Delete Comments",
+ body=perform_request_del_com(ln=ln, comIDs=comIDs),
+ uid=uid,
+ language=ln,
+ urlargs=req.args,
+ navtrail = navtrail_previous_links,
+ lastupdated=__lastupdated__)
+ else:
+ return page_not_authorized(req=req, text=auth_msg, navtrail=navtrail_previous_links)
+
diff --git a/modules/webcomment/web/comments.py b/modules/webcomment/web/comments.py
new file mode 100644
index 000000000..39af458e0
--- /dev/null
+++ b/modules/webcomment/web/comments.py
@@ -0,0 +1,194 @@
+# -*- coding: utf-8 -*-
+## $Id$
+## Comments and reviews for records.
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+__lastupdated__ = """FIXME: last updated"""
+
+from cdsware import webcomment
+from cdsware.config import *
+from cdsware.webuser import getUid, page_not_authorized, isGuestUser
+from cdsware.webaccount import create_login_page_box, create_register_page_box
+from cdsware.webpage import page, create_error_box
+from cdsware.search_engine import create_navtrail_links, guess_primary_collection_of_a_record
+
+from mod_python import apache
+import urllib
+
+def index(req):
+ """
+ Redirects to display function
+ """
+ req.err_headers_out.add("Location", "%s/comments.py/display?%s" % (weburl, req.args))
+ raise apache.SERVER_RETURN, apache.HTTP_MOVED_PERMANENTLY
+
+def display(req, ln=cdslang, recid=-1, do='od', ds='all', nb=100, p=1, voted=-1, reported=-1, reviews=0):
+ """
+ Display comments (reviews if enabled) associated with record having id recid where recid>0.
+ This function can also be used to display remarks associated with basket having id recid where recid<-99.
+ @param ln: language
+ @param recid: record id, integer
+ @param do: display order hh = highest helpful score, review only
+ lh = lowest helpful score, review only
+ hs = highest star score, review only
+ ls = lowest star score, review only
+ od = oldest date
+ nd = newest date
+ @param ds: display since all= no filtering by date
+ nd = n days ago
+ nw = n weeks ago
+ nm = n months ago
+ ny = n years ago
+ where n is a single digit integer between 0 and 9
+ @param nb: number of results per page
+ @param p: results page
+ @param voted: boolean, active if user voted for a review, see vote function
+ @param reported: boolean, active if user reported a certain comment/review, see report function
+ @param reviews: boolean, enabled for reviews, disabled for comments
+ @return the full html page.
+ """
+ (body, errors_to_display, warnings) = webcomment.perform_request_display_comments_or_remarks(recID=recid, display_order=do, display_since=ds, nb_per_page=nb,
+ page=p, ln=ln, voted=voted, reported=reported, reviews=reviews)
+ uid = getUid(req)
+
+ navtrail = create_navtrail_links(cc=guess_primary_collection_of_a_record(recid)) + \
+ """ > Detailed record #%s""" % (weburl, recid, ln, recid) + \
+ """ > %s""" % (reviews==1 and "Reviews" or "Comments",)
+
+ return page(title="", body=body, navtrail=navtrail, description="", keywords="", uid=uid,
+ cdspageheaderadd="", cdspageboxlefttopadd="", cdspageboxleftbottomadd="", cdspageboxrighttopadd="",
+ cdspageboxrightbottomadd="", cdspagefooteradd="", lastupdated="", urlargs="", verbose=1, titleprologue="", titleepilogue="",
+ req=req, errors=errors_to_display, warnings=warnings)
+
+def add(req, ln=cdslang, recid=-1, action='DISPLAY', msg="", note="", score="", reviews=0, comid=-1):
+ """
+ Add a comment (review) to record with id recid where recid>0
+ Also works for adding a remark to basket with id recid where recid<-99
+ @param ln: languange
+ @param recid: record id
+ @param action: 'DISPLAY' to display add form
+ 'SUBMIT' to submit comment once form is filled
+ 'REPLY' to reply to an already existing comment
+ @param msg: the body of the comment/review or remark
+ @param score: star score of the review
+ @param note: title of the review
+ @param comid: comment id, needed for replying
+ @return the full html page.
+ """
+ actions = ['DISPLAY', 'REPLY', 'SUBMIT']
+
+ uid = getUid(req)
+
+ navtrail = create_navtrail_links(cc=guess_primary_collection_of_a_record(recid)) + \
+ """ > Detailed record #%s""" % (weburl, recid, ln, recid) + \
+ """ > %s""" % (weburl, recid, ln, reviews==1 and 'Reviews' or 'Comments')
+
+ if action not in actions:
+ action = 'DISPLAY'
+
+ # is page allowed to be viewed
+ if uid == -1 or (not cfg_webcomment_allow_comments and not cfg_comment_allow_reviews):
+ return page_not_authorized(req, "../comments.py/add")
+
+ # if guest, must log in first
+ if isGuestUser(uid):
+ msg = "Before you add your comment, you need to log in first"
+ referer = "%s/comments.py/add?recid=%s&ln=%s&reviews=%s&comid=%s&action=%s" % (weburl, recid, ln, reviews, comid, action)
+ login_box = create_login_page_box(referer)
+ return page(title="Login", body=msg+login_box, navtrail=navtrail, description="", keywords="",
+ uid=uid, cdspageheaderadd="", cdspageboxlefttopadd="", cdspageboxleftbottomadd="",
+ cdspageboxrighttopadd="", cdspageboxrightbottomadd="", cdspagefooteradd="",
+ lastupdated="", language=cdslang, urlargs="", verbose=1, titleprologue="", titleepilogue="")
+ # user logged in
+ else:
+ (body, errors, warnings) = webcomment.perform_request_add_comment_or_remark(recID=recid, uid=uid, action=action, msg=msg, note=note, score=score, reviews=reviews, comID=comid)
+ title = "Add %s" % (reviews==1 and 'Review' or 'Comment')
+ return page(title=title, body=body, navtrail=navtrail, description="", keywords="", uid=uid,
+ cdspageheaderadd="", cdspageboxlefttopadd="", cdspageboxleftbottomadd="",
+ cdspageboxrighttopadd="", cdspageboxrightbottomadd="", cdspagefooteradd="",
+ lastupdated="", language=cdslang, urlargs="", verbose=1, titleprologue="", titleepilogue="", errors=errors, warnings=warnings)
+
+def vote(req, comid=-1, com_value=0, recid=-1, ln=cdslang, do='od', ds='all', nb=100, p=1, referer=None, reviews=0):
+ """
+ Vote positively or negatively for a comment/review.
+ @param comid: comment/review id
+ @param com_value: +1 to vote positively
+ -1 to vote negatively
+ @param recid: the id of the record the comment/review is associated with
+ @param ln: language
+ @param do: display order hh = highest helpful score, review only
+ lh = lowest helpful score, review only
+ hs = highest star score, review only
+ ls = lowest star score, review only
+ od = oldest date
+ nd = newest date
+ @param ds: display since all= no filtering by date
+ nd = n days ago
+ nw = n weeks ago
+ nm = n months ago
+ ny = n years ago
+ where n is a single digit integer between 0 and 9
+ @param nb: number of results per page
+ @param p: results page
+ @param referer: http address of the calling function to redirect to (refresh)
+ @param reviews: boolean, enabled for reviews, disabled for comments
+ """
+ success = webcomment.perform_request_vote(comid, com_value)
+ if referer:
+ referer = referer + '''?recid=%s&ln=%s&do=%s&ds=%s&nb=%s&p=%s&voted=%s&reviews=%s''' % \
+ (recid, ln, do, ds, nb, p, success, reviews)
+ req.err_headers_out.add("Location", referer)
+ raise apache.SERVER_RETURN, apache.HTTP_MOVED_PERMANENTLY
+ else: #Note: sent to commetns display
+ req.err_headers_out.add("Location", "%s/comments.py/display?recid=%s&ln=%s&reviews=1&voted=1" % (weburl, recid, ln))
+ raise apache.SERVER_RETURN, apache.HTTP_MOVED_PERMANENTLY
+
+def report(req, comid=-1, recid=-1, ln=cdslang, do='od', ds='all', nb=100, p=1, referer=None, reviews=0):
+ """
+ Report a comment/review for inappropriate content
+ @param comid: comment/review id
+ @param recid: the id of the record the comment/review is associated with
+ @param ln: language
+ @param do: display order hh = highest helpful score, review only
+ lh = lowest helpful score, review only
+ hs = highest star score, review only
+ ls = lowest star score, review only
+ od = oldest date
+ nd = newest date
+ @param ds: display since all= no filtering by date
+ nd = n days ago
+ nw = n weeks ago
+ nm = n months ago
+ ny = n years ago
+ where n is a single digit integer between 0 and 9
+ @param nb: number of results per page
+ @param p: results page
+ @param referer: http address of the calling function to redirect to (refresh)
+ @param reviews: boolean, enabled for reviews, disabled for comments
+ """
+ success = webcomment.perform_request_report(comid)
+ if referer:
+ referer = referer + '''?recid=%s&ln=%s&do=%s&ds=%s&nb=%s&p=%s&reported=%s&reviews=%s''' % \
+ (recid, ln, do, ds, nb, p, success, reviews)
+ req.err_headers_out.add("Location", referer)
+ raise apache.SERVER_RETURN, apache.HTTP_MOVED_PERMANENTLY
+ else: #Note: sent to comments display
+ req.err_headers_out.add("Location", "%s/comments.py/display?recid=%s&ln=%s&reviews=1&voted=1" % (weburl, recid, ln))
+ raise apache.SERVER_RETURN, apache.HTTP_MOVED_PERMANENTLY
+