diff --git a/modules/webcomment/lib/webcomment.py b/modules/webcomment/lib/webcomment.py index 539ba0c96..7fbc26862 100644 --- a/modules/webcomment/lib/webcomment.py +++ b/modules/webcomment/lib/webcomment.py @@ -1,857 +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) + (query_res, nb_abuse_reports) = 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)) + if nb_abuse_reports % 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_total, com_title, com_reported) = query_get_comment(comID) + (user_nb_abuse_reports, user_votes, user_nb_votes_total) = 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 + total number of reports = %(user_nb_abuse_reports)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_nb_abuse_reports' : user_nb_abuse_reports, '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", + (user_votes, (user_nb_votes_total - 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 "", + "star score\t\t= %s\n\t\t\treview title\t\t= %s" % (com_star, com_title) 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) + @return tuple (total_nb_reports, total_nb_votes_yes, total_nb_votes_total) if none found return () """ - query1 = "SELECT vote_value, nb_votes, nb_reported FROM cmtRECORDCOMMENT WHERE id_user=%s" + query1 = "SELECT nb_votes_yes, nb_votes_total, nb_abuse_reports 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 + nb_votes_yes = nb_votes_total = nb_abuse_reports = 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) + nb_votes_yes += int(cmt_tuple[0]) + nb_votes_total += int(cmt_tuple[1]) + nb_abuse_reports += int(cmt_tuple[2]) + return (nb_abuse_reports, nb_votes_yes, nb_votes_total) 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) + @return tuple (comID, id_bibrec, id_user, body, date_creation, star_score, nb_votes_yes, nb_votes_total, title, nb_abuse_reports) 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" + #retrieve nb_abuse_reports + query1 = "SELECT nb_abuse_reports 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) + nb_abuse_reports = int(res1[0][0]) + 1 + query2 = "UPDATE cmtRECORDCOMMENT SET nb_abuse_reports=%s WHERE id=%s" + params2 = (nb_abuse_reports, comID) res2 = run_sql(query2, params2) - return (int(res2), nb_reported) + return (int(res2), nb_abuse_reports) 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" + query1 = "SELECT nb_votes_total, nb_votes_yes 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) + nb_votes_yes = int(res1[0][1]) + value + nb_votes_total = int(res1[0][0]) + 1 + query2 = "UPDATE cmtRECORDCOMMENT SET nb_votes_total=%s, nb_votes_yes=%s WHERE id=%s" + params2 = (nb_votes_total, nb_votes_yes, 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) + tuple (nickname, date_creation, body, nb_votes_yes, nb_votes_total, star_score, title, 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 ", + order_dict = { 'hh' : "c.nb_votes_yes/(c.nb_votes_total+1) DESC, c.date_creation DESC ", + 'lh' : "c.nb_votes_yes/(c.nb_votes_total+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 '', + params = { 'ranking' : ranking and ' c.nb_votes_yes, c.nb_votes_total, c.star_score, c.title, ' 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) " \ + query = "INSERT INTO cmtRECORDCOMMENT (id_bibrec, id_user, body, date_creation, star_score, nb_votes_total, title) " \ "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_nb_votes_yes = 3 + c_nb_votes_total = 4 c_star_score = 5 - c_star_note = 6 + c_title = 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 + (comID2, id_bibrec, id_user, body, date_creation, star_score, nb_votes_yes, nb_votes_total, title, nb_abuse_reports) = 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) + Title = %s''' % (star_score, title) 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_caps)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', + 'comment_or_review_caps': 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_templates.py b/modules/webcomment/lib/webcomment_templates.py index fb4ee7548..e3ca5fae8 100644 --- a/modules/webcomment/lib/webcomment_templates.py +++ b/modules/webcomment/lib/webcomment_templates.py @@ -1,914 +1,914 @@ # -*- 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 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 += ''' ''' comment_rows += self.tmpl_get_comment_without_ranking(recID, ln, comment[c_nickname], comment[c_date_creation], comment[c_body]) comment_rows += '''

''' # write button write_button_link = '''%s/comments.py/add''' % (weburl,) write_button_form = ''' ''' % (recID, ln) write_button_form = self.createhiddenform(action=write_button_link, method="Get", text=write_button_form, button='Write a comment') # output if nb_comments_total > 0: out = warnings + '''
%(comment_title)s
Showing the latest %(nb_comments)s comment%(s)s: %(tab)s
%(comment_rows)s
%(view_all_comments_link)s

%(write_button_form)s
''' % \ { 'comment_title' : "Discuss this document:", 'nb_comments_total' : nb_comments_total, 'recID' : recID, 'comment_rows' : comment_rows, 'tab' : ' '*4, 'weburl' : weburl, 's' : cfg_webcomment_nb_comments_in_detailed_view>1 and 's' or "", 'view_all_comments_link' : nb_comments_total>0 and '''View all %s comments''' \ % (weburl, recID, nb_comments_total) or "", 'write_button_form' : write_button_form, 'nb_comments' : cfg_webcomment_nb_comments_in_detailed_view>1 and cfg_webcomment_nb_comments_in_detailed_view or "" } else: out = '''
Discuss this document:
Open a a discussion about any aspect of this document.
%s
''' % (write_button_form,) return out def tmpl_get_first_comments_with_ranking(self, recID, ln, comments=None, nb_comments_total=None, avg_score=None, 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 avg_score: average score of all reviews @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_vote_value = 3 - c_nb_votes = 4 + c_nb_votes_yes = 3 + c_nb_votes_total = 4 c_star_score = 5 - c_star_note = 6 + c_title = 6 c_id = 7 warnings = self.tmpl_warnings(warnings) #stars if avg_score > 0: avg_score_img = 'stars-' + str(avg_score).split('.')[0] + '-' + str(avg_score).split('.')[1] + '.gif' else: avg_score_img = "stars-except.gif" # voting links useful_dict = { 'weburl' : weburl, 'recID' : recID, 'ln' : ln, 'yes_img' : 'smchk_gr.gif', #'yes.gif', 'no_img' : 'iconcross.gif' #'no.gif' } useful_yes = '''Yes''' % useful_dict useful_no = ''' No''' % useful_dict report_link = '''%(weburl)s/comments.py/report?recid=%(recID)s&ln=%(ln)s&comid=%%(comid)s&reviews=1''' % useful_dict #comment row comment_rows = ''' ''' for comment in comments: comment_rows += ''' ''' comment_rows += self.tmpl_get_comment_with_ranking(recID, ln, comment[c_nickname], comment[c_date_creation], comment[c_body], - comment[c_nb_votes], comment[c_vote_value], comment[c_star_score], comment[c_star_note]) + comment[c_nb_votes_total], comment[c_nb_votes_yes], comment[c_star_score], comment[c_title]) comment_rows += ''' Was this review helpful? %s / %s
''' % (useful_yes % {'comid':comment[c_id]}, useful_no % {'comid':comment[c_id]}) comment_rows += '''
''' # write button write_button_link = '''%s/comments.py/add''' % (weburl,) write_button_form = ''' ''' % (recID, ln ) write_button_form = self.createhiddenform(action=write_button_link, method="Get", text=write_button_form, button='Write a review') if nb_comments_total > 0: out = warnings + '''
%(comment_title)s
Average review score: %(avg_score)s 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): + def tmpl_get_comment_with_ranking(self, recID, ln, nickname, date_creation, body, nb_votes_total, nb_votes_yes, star_score, title): """ 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 nb_votes_total: total number of votes for this review + @param nb_votes_yes: number of positive votes for this record @param star_score: star score for this record - @param star_note: title of review + @param title: 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_score)s %(star_note)s
+ %(star_score)s %(title)s
Reviewed by %(nickname)s on %(date_creation)s
- %(vote_value)s out of %(nb_votes)s people found this review useful.
+ %(nb_votes_yes)s out of %(nb_votes_total)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, + 'nb_votes_total' : nb_votes_total, 'star_score' : star_score, - 'star_note' : star_note, - 'vote_value' : vote_value<0 and "0" or vote_value + 'title' : title, + 'nb_votes_yes' : nb_votes_yes<0 and "0" or nb_votes_yes } 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_nb_votes_yes = 3 + c_nb_votes_total = 4 c_star_score = 5 - c_star_note = 6 + c_title = 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 += ''' ''' if not reviews: report_link = '''%(weburl)s/comments.py/report?recid=%(recID)s&ln=%(ln)s&comid=%%(comid)s&do=%(do)s&ds=%(ds)s&nb=%(nb)s&p=%(p)s&reviews=%(reviews)s&referer=%(weburl)s/comments.py/display''' % useful_dict % {'comid':comment[c_id]} reply_link = '''%(weburl)s/comments.py/add?recid=%(recID)s&ln=%(ln)s&action=REPLY&comid=%%(comid)s''' % useful_dict % {'comid':comment[c_id]} comments_rows += self.tmpl_get_comment_without_ranking(recID, ln, comment[c_nickname], comment[c_date_creation], comment[c_body], reply_link, report_link) else: report_link = '''%(weburl)s/comments.py/report?recid=%(recID)s&ln=%(ln)s&comid=%%(comid)s&do=%(do)s&ds=%(ds)s&nb=%(nb)s&p=%(p)s&reviews=%(reviews)s&referer=%(weburl)s/comments.py/display''' % useful_dict % {'comid':comment[c_id]} comments_rows += self.tmpl_get_comment_with_ranking(recID, ln, comment[c_nickname], comment[c_date_creation], comment[c_body], - comment[c_nb_votes], comment[c_vote_value], comment[c_star_score], comment[c_star_note]) + comment[c_nb_votes_total], comment[c_nb_votes_yes], comment[c_star_score], comment[c_title]) comments_rows += '''
Was this review helpful? %(tab)s %(yes)s / %(no)s %(tab)s%(tab)s(Report abuse)
''' \ % { 'yes' : useful_yes % {'comid':comment[c_id]}, 'no' : useful_no % {'comid':comment[c_id]}, 'report' : report_link % {'comid':comment[c_id]}, 'tab' : ' '*2 } comments_rows += '''
''' ## page links page_links = ''' ''' # Previous if page != 1: link_dic['arg_page'] = 'p=%s' % (page - 1) page_links += ''' << ''' % link_dic else: page_links += ''' %s ''' % (' '*(len('< Previous')+7)) # Page Numbers for i in range(1, nb_pages+1): link_dic['arg_page'] = 'p=%s' % i link_dic['page'] = '%s' % i if i != page: page_links += ''' %(page)s ''' % link_dic else: page_links += ''' %s ''' % i # Next if page != nb_pages: link_dic['arg_page'] = 'p=%s' % (page + 1) page_links += ''' >> ''' % link_dic else: page_links += '''%s''' % (' '*(len('< Next')+7)) ## stuff for ranking if enabled if reviews: comments_or_reviews = 'review' if avg_score > 0: avg_score_img = 'stars-' + str(avg_score).split('.')[0] + '-' + str(avg_score).split('.')[1] + '.gif' else: avg_score_img = "stars-except.gif" ranking_average = '''
Average review socre: %(avg_score)s based on %(nb_comments_total)s reviews
''' \ % { 'weburl' : weburl, 'avg_score' : avg_score, 'avg_score_img' : avg_score_img, 'nb_comments_total' : total_nb_comments } else: ranking_average = "" comments_or_reviews = 'comment' write_button_link = '''%s/comments.py/add''' % (weburl, ) write_button_form = ''' ''' % (recID, ln, reviews) write_button_form = self.createhiddenform(action=write_button_link, method="Get", text=write_button_form, button='Write a %s' % comments_or_reviews) ## html body = '''

Record %(recid)s

Back to search results

%(record_details)s

%(comments_or_reviews_title)ss

There is a total of %(total_nb_comments)s %(comments_or_reviews)ss. %(ranking_avg)s
%(write_button_form)s
%(comments_rows)s
%(write_button_form_again)s Back to search results

''' % \ { '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' % (action, string.lower(method).strip() in ['get','post'] and method or 'Get') output += '\n
' output += text if cnfrm: output += ' ' for key in hidden.keys(): if type(hidden[key]) is list: for value in hidden[key]: output += ' \n' % (key, value) else: output += ' \n' % (key, hidden[key]) output += '' output += ' \n' % (button, ) output += '
' 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 += ''' ''' if cfg_webcomment_allow_reviews: out += ''' ''' out += ''' ''' out = out % { 'weburl' : weburl, 'ln' : ln } else: out += ''' ''' out += '''
0.  View all reported comments
0. View all reported reviews
1. Delete a specific comment/review (by ID)
2. View all users who have been reported

Comments and reviews are disabled
''' from bibrankadminlib import addadminbox 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) + where ct is a tuple (total_number_reported, total_comments_reported, total_reviews_reported, total_nb_votes_yes_of_reported, + total_nb_votes_total_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_nb_votes_yes = 3 + u_nb_votes_total = 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 "", + (utuple[u_nb_votes_yes], utuple[u_nb_votes_total]-utuple[u_nb_votes_yes], utuple[u_nb_votes_total]) 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.

%(reviews_columns)s %(user_rows)s
Nickname Email User IDTotal number of reports View all user's reported comments/reviews
''' % { 'reviews_columns' : cfg_webcomment_allow_reviews>0 and "Number positive votesNumber negative votesTotal 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) + tuple (nickname, date_creation, body, nb_votes_yes, nb_votes_total, star_score, title, 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 = ''' %s
comment IDsuccessfully deleted
''' % (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' % (action, string.lower(method).strip() in ['get','post'] and method or 'Get') output += '
\n
' output += text if cnfrm: output += ' ' for key in hidden.keys(): if type(hidden[key]) is list: for value in hidden[key]: output += ' \n' % (key, value) else: output += ' \n' % (key, hidden[key]) output += '' output += ' \n' % (button, ) output += '
' output += '\n' return output diff --git a/modules/webcomment/lib/webcommentadminlib.py b/modules/webcomment/lib/webcommentadminlib.py index 53b310411..0190ca19c 100644 --- a/modules/webcomment/lib/webcommentadminlib.py +++ b/modules/webcomment/lib/webcommentadminlib.py @@ -1,232 +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) + total_nb_votes_yes_of_reported, total_nb_votes_total_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 " \ + query1 = "SELECT c.nb_abuse_reports, c.nb_votes_yes, c.nb_votes_total, 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 " \ + "WHERE c.id_user=u.id AND c.nb_abuse_reports > 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) + tuple (nickname, date_creation, body, nb_votes_yes, nb_votes_total, star_score, title, 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 " \ + "c.nb_abuse_reports, 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 "", + "ORDER BY c.nb_abuse_reports DESC, c.nb_votes_yes DESC, c.date_creation " + params1 = ( reviews>0 and " c.nb_votes_yes, c.nb_votes_total, c.star_score, c.title, " 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 " ) + comID>0 and " AND c.id=%s " % comID or " AND c.nb_abuse_reports>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