diff --git a/modules/webbasket/lib/webbasket.py b/modules/webbasket/lib/webbasket.py index a028fcd7e..bab1051b6 100644 --- a/modules/webbasket/lib/webbasket.py +++ b/modules/webbasket/lib/webbasket.py @@ -1,2891 +1,2874 @@ ## This file is part of Invenio. ## Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 CERN. ## ## Invenio 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. ## ## Invenio 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """Web Baskets features.""" __revision__ = "$Id$" import sys if sys.hexversion < 0x2040000: # pylint: disable=W0622 from sets import Set as set # pylint: enable=W0622 from invenio.intbitset import intbitset import cgi +import urllib from httplib import urlsplit, HTTPConnection #from socket import getdefaulttimeout, setdefaulttimeout from zlib import decompress import re from invenio.config import CFG_SITE_LANG, CFG_SITE_URL, \ CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS from invenio.messages import gettext_set_language from invenio.dateutils import convert_datetext_to_dategui, \ convert_datetext_to_datestruct,\ convert_datestruct_to_dategui from invenio.bibformat import format_record from invenio.webbasket_config import CFG_WEBBASKET_SHARE_LEVELS, \ CFG_WEBBASKET_SHARE_LEVELS_ORDERED, \ CFG_WEBBASKET_CATEGORIES, \ InvenioWebBasketWarning from invenio.urlutils import get_referer from invenio.webuser import isGuestUser, collect_user_info from invenio.search_engine import \ record_exists, \ check_user_can_view_record, \ print_records_prologue, \ print_records_epilogue #from invenio.webcomment import check_user_can_attach_file_to_comments import invenio.webbasket_dblayer as db try: import invenio.template webbasket_templates = invenio.template.load('webbasket') except ImportError: pass from invenio.websearch_external_collections_utils import get_collection_name_by_id from invenio.websearch_external_collections import select_hosted_search_engines from invenio.websearch_external_collections_config import CFG_EXTERNAL_COLLECTION_TIMEOUT from invenio.websearch_external_collections_getter import HTTPAsyncPageGetter, async_download from invenio.errorlib import register_exception from invenio.search_engine import search_unit from invenio.htmlutils import remove_html_markup ######################################## ### Display public baskets and notes ### ######################################## def perform_request_display_public(uid, selected_bskid=0, selected_recid=0, optional_params={}, of='hb', ln=CFG_SITE_LANG): """Engine for the display of a public interface. Calls the template and returns HTML. @param selected_bskid: The id of the basket to be displayed (optional) @param selected_recid: The id of the item to be displayed (optional) @param optional_params: optional parameters to be passed, used for notes @param of: display format @param ln: language""" _ = gettext_set_language(ln) warnings_item = [] warnings_basket = [] (of, of_warnings) = wash_of(of) if of_warnings: navtrail = create_webbasket_navtrail(uid, ln=ln) body = webbasket_templates.tmpl_warnings(of_warnings, ln) return (body, of_warnings, navtrail) basket = db.get_public_basket_info(selected_bskid) if not basket: if of != 'hb': return ("", None, None) try: raise InvenioWebBasketWarning(_('The selected public basket does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings_html = webbasket_templates.tmpl_warnings(exc.message, ln) #warnings.append(exc.message) #warnings = ['WRN_WEBBASKET_INVALID_OR_RESTRICTED_PUBLIC_BASKET'] (body, navtrail) = perform_request_list_public_baskets(uid) try: raise InvenioWebBasketWarning(_('Please select a valid public basket from the list of public baskets.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_SHOW_LIST_PUBLIC_BASKETS') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) body = warnings_html + body return (body, None, navtrail) else: (bskid, basket_name, id_owner, last_update, dummy, nb_items, recids, share_rights) = basket[0] if selected_recid: - valid_recids = eval(recids + ',') + valid_recids = tuple(map(int, recids.split(','))) if selected_recid in valid_recids: (content, warnings_item) = __display_public_basket_single_item(bskid, basket_name, selected_recid, nb_items, share_rights, optional_params, of, ln) else: try: raise InvenioWebBasketWarning(_('The selected item does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings_item.append(exc.message) #warnings_item.append('WRN_WEBBASKET_INVALID_OR_RESTRICTED_ITEM') try: raise InvenioWebBasketWarning(_('Returning to the public basket view.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings_item.append(exc.message) #warnings_item.append('WRN_WEBBASKET_RETURN_TO_PUBLIC_BASKET') selected_recid = 0 if not selected_recid: if uid == id_owner: subscription_status = 0 else: if db.is_user_subscribed_to_basket(uid,bskid): subscription_status = 1 else: subscription_status = -1 (content, warnings_basket) = __display_public_basket(bskid, basket_name, last_update, nb_items, share_rights, id_owner, subscription_status, of, ln) if of == 'hb': body = webbasket_templates.tmpl_display(content=content) warnings = warnings_item + warnings_basket warnings_html = webbasket_templates.tmpl_warnings(warnings, ln) body = warnings_html + body else: body = content if of == 'hb': navtrail = create_webbasket_navtrail(uid, bskid=selected_bskid, public_basket=True, ln=ln) if of == 'hb': return (body, warnings, navtrail) else: return (body, None, None) def __display_public_basket(bskid, basket_name, last_update, nb_items, share_rights, id_owner, subscription_status, of='hb', ln=CFG_SITE_LANG): """Private function. Display a basket giving its category and topic or group. @param share_rights: rights user has on basket @param group_sharing_level: None if basket is not shared, 0 if public basket, > 0 if shared to usergroups but not public. @param category: selected category (see webbasket_config.py) @param selected_topic: # of selected topic to display baskets @param selected_group_id: id of group to display baskets @param ln: language""" _ = gettext_set_language(ln) warnings = [] nb_total_notes = 0 last_note = _("N/A") records = [] notes_dates = [] last_update = convert_datetext_to_dategui(last_update, ln) items = db.get_basket_content(bskid, of) external_recids = [] for (recid, collection_id, nb_notes, last_note, ext_val, int_val, score) in items: notes_dates.append(convert_datetext_to_datestruct(last_note)) last_note = convert_datetext_to_dategui(last_note, ln) colid = collection_id and collection_id or collection_id == 0 and -1 or 0 val = "" nb_total_notes += nb_notes if recid < 0: if ext_val: val = decompress(ext_val) else: external_recids.append(recid) else: if int_val: val = decompress(int_val) else: val = format_record(recid, of, on_the_fly=True) records.append((recid, colid, nb_notes, last_note, val, score)) if external_recids: external_records = format_external_records(external_recids, of) for external_record in external_records: for record in records: if record[0] == -external_record[0]: idx = records.index(record) tuple_to_list = list(records.pop(idx)) tuple_to_list[4] = external_record[1] records.insert(idx, tuple(tuple_to_list)) break if notes_dates: last_note = convert_datestruct_to_dategui(max(notes_dates), ln) body = webbasket_templates.tmpl_public_basket(bskid, basket_name, last_update, nb_items, (check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT'],),), nb_total_notes, records, id_owner, subscription_status, of, ln) return (body, warnings) def __display_public_basket_single_item(bskid, basket_name, recid, nb_items, share_rights, optional_params={}, of='hb', ln=CFG_SITE_LANG): """Private function. Display a basket giving its category and topic or group. @param share_rights: rights user has on basket @param group_sharing_level: None if basket is not shared, 0 if public basket, > 0 if shared to usergroups but not public. @param category: selected category (see webbasket_config.py) @param selected_topic: # of selected topic to display baskets @param selected_group_id: id of group to display baskets @param ln: language""" _ = gettext_set_language(ln) warnings = [] item = db.get_basket_item(bskid, recid, of) if item: (recid, collection_id, nb_notes, last_note, ext_val, int_val, score) = item[0] previous_item_recid = item[1] next_item_recid = item[2] item_index = item[3] else: # The validity of the recid and hence the item is already checked by the # previous function and the appropriate warning is returned. # This is just an extra check just in case we missed something. # An empty body is returned. body = "" try: raise InvenioWebBasketWarning(_('The selected item does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_INVALID_OR_RESTRICTED_ITEM') return (body, warnings) last_note = convert_datetext_to_dategui(last_note, ln) colid = collection_id and collection_id or collection_id == 0 and -1 or 0 val = "" if recid < 0: if ext_val: val = decompress(ext_val) else: external_record = format_external_records([recid], of) val = external_record and external_record[0][1] or "" else: if int_val: val = decompress(int_val) else: val = format_record(recid, of, on_the_fly=True) item = (recid, colid, nb_notes, last_note, val, score) notes = db.get_notes(bskid, recid) body = webbasket_templates.tmpl_public_basket_single_item(bskid, basket_name, nb_items, (check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']), check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT'])), item, notes, previous_item_recid, next_item_recid, item_index, optional_params, of, ln) return (body, warnings) def perform_request_list_public_baskets(uid, limit=1, sort='name', asc=1, nb_views_show_p=False, ln=CFG_SITE_LANG): """Display list of public baskets. @param limit: display baskets from the incrementally numbered 'limit' and on @param sort: sort by 'name' or 'views' or 'owner' or 'date' or 'items' @param asc: ascending sort or not @param ln: language""" warnings_html = "" number_of_all_public_baskets = db.count_all_public_baskets() limit -= 1 if limit < 0: limit = 0 elif limit >= number_of_all_public_baskets: limit = number_of_all_public_baskets - 1 if not nb_views_show_p and sort == 'views': # TODO: Add a 'sort by views' restriction warning #warnings.append('...') #warnings_html += webbasket_templates.tmpl_warnings(warnings, ln) sort = "name" all_public_baskets = db.get_list_public_baskets(limit, CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS, sort, asc) body = webbasket_templates.tmpl_display_list_public_baskets(all_public_baskets, limit, number_of_all_public_baskets, sort, asc, nb_views_show_p, ln) search_box = __create_search_box(uid=uid, category=CFG_WEBBASKET_CATEGORIES['ALLPUBLIC'], ln=ln) body = webbasket_templates.tmpl_display(content=body, search_box=search_box) body = warnings_html + body navtrail = create_webbasket_navtrail(uid, public_basket=True, ln=ln) return (body, navtrail) def perform_request_write_public_note(uid, bskid=0, recid=0, cmtid=0, ln=CFG_SITE_LANG): """Display a note writing form @param uid: user id @param bskid: basket id @param recid: record id (comments are on a specific record in a specific basket) @param cmtid: if provided this comment is a reply to comment cmtid. @param category: selected category @param topic: selected topic @param group_id: selected group id @param ln: language """ _ = gettext_set_language(ln) optional_params = {} warnings_rights = [] warnings_html = "" if not can_add_notes_to_public_basket_p(bskid): try: raise InvenioWebBasketWarning(_('You do not have permission to write notes to this item.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') # warnings_rights = exc.message #warnings_rights = ['WRN_WEBBASKET_RESTRICTED_WRITE_NOTES'] warnings_html += webbasket_templates.tmpl_warnings(warnings_rights, ln) else: if cmtid and db.note_belongs_to_item_in_basket_p(cmtid, recid, bskid): optional_params["Add note"] = db.get_note(cmtid) optional_params["Reply to"] = cmtid elif cmtid: optional_params["Add note"] = () try: raise InvenioWebBasketWarning(_('The note you are quoting does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') optional_params["Warnings"] = exc.message else: optional_params["Add note"] = () (body, warnings, navtrail) = perform_request_display_public(uid=uid, selected_bskid=bskid, selected_recid=recid, optional_params=optional_params, of='hb', ln=CFG_SITE_LANG) if not warnings: body = warnings_html + body # warnings = warnings_rights return (body, navtrail) def perform_request_save_public_note(uid, bskid=0, recid=0, note_title="", note_body="", editor_type='textarea', ln=CFG_SITE_LANG, reply_to=None): """ Save a given comment if able to. @param uid: user id (int) @param bskid: basket id (int) @param recid: record id (int) @param title: title of comment (string) @param text: comment's body (string) @param ln: language (string) @param editor_type: the kind of editor/input used for the comment: 'textarea', 'ckeditor' @param reply_to: the id of the comment we are replying to """ optional_params = {} warnings_rights = [] warnings_html = "" _ = gettext_set_language(ln) if not can_add_notes_to_public_basket_p(bskid): try: raise InvenioWebBasketWarning(_('You do not have permission to write notes to this item.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') # warnings_rights = exc.message #warnings_rights = ['WRN_WEBBASKET_RESTRICTED_WRITE_NOTES'] warnings_html += webbasket_templates.tmpl_warnings(warnings_rights, ln) else: if not note_title or not note_body: # FIXME: improve check when ckeditor optional_params["Incomplete note"] = (note_title, note_body) try: raise InvenioWebBasketWarning(_('You must fill in both the subject and the body of the note.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') optional_params["Warnings"] = exc.message else: if editor_type == 'ckeditor': # Here we remove the line feeds introduced by CKEditor (they # have no meaning for the user) and replace the HTML line # breaks by linefeeds, so that we are close to an input that # would be done without the CKEditor. That's much better if a # reply to a comment is made with a browser that does not # support CKEditor. note_body = note_body.replace('\n', '').replace('\r', '').replace('<br />', '\n') if not(db.save_note(uid, bskid, recid, note_title, note_body, reply_to)): # TODO: The note could not be saved. DB problem? pass else: # TODO: inform about successful annotating. pass (body, warnings, navtrail) = perform_request_display_public(uid=uid, selected_bskid=bskid, selected_recid=recid, optional_params=optional_params, of='hb', ln=CFG_SITE_LANG) if not warnings: body = warnings_html + body # warnings = warnings_rights return (body, navtrail) ################################# ### Display baskets and notes ### ################################# def perform_request_display(uid, selected_category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group_id=0, selected_bskid=0, selected_recid=0, optional_params={}, of='hb', ln=CFG_SITE_LANG): """Display all the baskets of given category, topic or group. @param uid: user id @param selected_category: selected category (see webbasket_config.py) @param selected_topic: # of selected topic to display baskets @param selected_group_id: id of group to display baskets @param ln: language""" _ = gettext_set_language(ln) warnings = [] warnings_html = "" valid_category_choice = False selected_basket_info = [] content = "" search_box = "" (of, of_warnings) = wash_of(of) if of_warnings: navtrail = create_webbasket_navtrail(uid, ln=ln) body = webbasket_templates.tmpl_warnings(of_warnings, ln) return (body, of_warnings, navtrail) (selected_category, category_warnings) = wash_category(selected_category) if not selected_category and category_warnings: if of == 'xm': return ("", None. None) navtrail = create_webbasket_navtrail(uid, ln=ln) body = webbasket_templates.tmpl_warnings(category_warnings, ln) return (body, category_warnings, navtrail) if selected_category == CFG_WEBBASKET_CATEGORIES['ALLPUBLIC']: if of == 'xm': return ("", None. None) # TODO: Send the correct title of the page as well. return perform_request_list_public_baskets(uid) - personal_info = db.get_all_personal_basket_ids_and_names_by_topic(uid) + personal_info = db.get_all_user_personal_basket_ids_by_topic(uid) personal_baskets_info = () + if personal_info and selected_category == CFG_WEBBASKET_CATEGORIES['PRIVATE']: + # Create a dictionary that has the valid topics for keys and the basket + # ids in each topic (string, ids separated by commas) as values. + personal_info_dict = {} + for personal_info_topic_and_bskids in personal_info: + personal_info_dict[personal_info_topic_and_bskids[0]] = map(int, personal_info_topic_and_bskids[1].split(',')) valid_category_choice = True if selected_topic: - # (A) tuples parsing check - valid_topic_names = [personal_info_topic[0] for personal_info_topic in personal_info] - if selected_topic in valid_topic_names: - # (B) DB check - #if db.is_topic_valid(uid, selected_topic): + valid_selected_topic_p = False + # Validate the topic. Check if the selected topic is one of the keys + # in the dictionary. If it is valid then get some more info for that + # topic from the DB. + if selected_topic in personal_info_dict.keys(): personal_baskets_info = db.get_personal_baskets_info_for_topic(uid, selected_topic) valid_selected_topic_p = True - else: + if not valid_selected_topic_p: try: raise InvenioWebBasketWarning(_('The selected topic does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_INVALID_OR_RESTRICTED_TOPIC') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) valid_selected_topic_p = False selected_topic = "" else: valid_selected_topic_p = True + if valid_selected_topic_p and selected_bskid: - # (A) tuples parsing check if selected_topic: - valid_baskets = [eval(personal_info_topic[2] + ',') for personal_info_topic in personal_info - if personal_info_topic[0] == selected_topic] + valid_bskids = personal_info_dict[selected_topic] else: - valid_baskets = [eval(personal_info_topic[2] + ',') for personal_info_topic in personal_info] - valid_bskids = [] - for valid_basket in valid_baskets: - valid_bskids.extend([valid_bskid[0] for valid_bskid in valid_basket]) + valid_bskids = [] + for valid_bskids_per_topic in personal_info_dict.values(): + valid_bskids.extend(valid_bskids_per_topic) if selected_bskid in valid_bskids: - # (B) DB check - #if db.is_personal_basket_valid(uid, selected_bskid): if not selected_topic: - # (A) tuples parsing check - valid_baskets_dict = {} - for personal_info_topic in personal_info: - valid_baskets_dict[personal_info_topic[0]] = eval(personal_info_topic[2] + ',') - for valid_basket in valid_baskets_dict.iteritems(): - if selected_bskid in [valid_bskid[0] for valid_bskid in valid_basket[1]]: - selected_topic = valid_basket[0] + for valid_topic in personal_info_dict.iterkeys(): + if selected_bskid in personal_info_dict[valid_topic]: + selected_topic = valid_topic break - # (B) DB check - #selected_topic = db.get_basket_topic(uid, selected_bskid) - personal_baskets_info = db.get_personal_baskets_info_for_topic(uid, selected_topic) + personal_baskets_info = db.get_personal_baskets_info_for_topic(uid, selected_topic) for personal_basket_info in personal_baskets_info: if personal_basket_info[0] == selected_bskid: selected_basket_info = list(personal_basket_info) selected_basket_info.append(CFG_WEBBASKET_SHARE_LEVELS['MANAGE']) break else: try: raise InvenioWebBasketWarning(_('The selected basket does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_INVALID_OR_RESTRICTED_BASKET') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) selected_bskid = 0 else: selected_bskid = 0 - group_info = db.get_all_group_basket_ids_and_names_by_group(uid) + group_info = db.get_all_user_group_basket_ids_by_group(uid) group_baskets_info = () selected_group_name = "" + if group_info and selected_category == CFG_WEBBASKET_CATEGORIES['GROUP']: + # Create a dictionary that has the valid group as keys and the basket + # ids in each group (string, ids separated by commas) as values. + group_info_dict = {} + for group_info_group_and_bskids in group_info: + group_info_dict[group_info_group_and_bskids[0]] = (group_info_group_and_bskids[1], \ + map(int, group_info_group_and_bskids[2].split(','))) valid_category_choice = True if selected_group_id: - # (A) tuples parsing check - valid_group_ids = [group_info_group[0] for group_info_group in group_info] - if selected_group_id in valid_group_ids: - # (B) DB check - #if db.is_group_valid(uid, selected_group_id): + valid_selected_group_p = False + # Validate the group. Check if the selected group is one of the keys + # in the dictionary. If it is valid then get some more info for that + # group from the DB. + if selected_group_id in group_info_dict.keys(): + selected_group_name = group_info_dict[selected_group_id][0] group_baskets_info = db.get_group_baskets_info_for_group(selected_group_id) - # (A) tuples parsing - for group_info_group in group_info: - if group_info_group[0] == selected_group_id: - selected_group_name = group_info_group[1] - break - # (B) DB - #selected_group_name = db.get_group_name(selected_group_id) - #if selected_group_name: - # selected_group_name = selected_group_name[0][0] valid_selected_group_p = True - else: + if not valid_selected_group_p: try: raise InvenioWebBasketWarning(_('The selected topic does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_INVALID_OR_RESTRICTED_GROUP') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) selected_group_id = "" valid_selected_group_p = False else: valid_selected_group_p = True + if valid_selected_group_p and selected_bskid: - # (A) tuples parsing check if selected_group_id: - valid_baskets = [eval(group_info_group[3] + ',') for group_info_group in group_info - if group_info_group[0] == selected_group_id] + valid_bskids = group_info_dict[selected_group_id][1] else: - valid_baskets = [eval(group_info_group[3] + ',') for group_info_group in group_info] - valid_bskids = [] - for valid_basket in valid_baskets: - valid_bskids.extend([valid_bskid[0] for valid_bskid in valid_basket]) + valid_bskids = [] + for group_and_valid_bskids_per_group in group_info_dict.values(): + valid_bskids_per_group = group_and_valid_bskids_per_group[1] + valid_bskids.extend(valid_bskids_per_group) if selected_bskid in valid_bskids: - # (B) DB check - #if db.is_group_basket_valid(uid, selected_bskid): if not selected_group_id: - # (A) tuples parsing check - valid_baskets_dict = {} - for group_info_group in group_info: - valid_baskets_dict[group_info_group[0]] = eval(group_info_group[3] + ',') - for valid_basket in valid_baskets_dict.iteritems(): - if selected_bskid in [valid_bskid[0] for valid_bskid in valid_basket[1]]: - selected_group_id = valid_basket[0] + for valid_group_id in group_info_dict.iterkeys(): + if selected_bskid in group_info_dict[valid_group_id][1]: + selected_group_id = valid_group_id break - # (B) DB check - #selected_group_id = db.get_basket_group(uid, selected_bskid) - # (A) tuples parsing - for group_info_group in group_info: - if group_info_group[0] == selected_group_id: - selected_group_name = group_info_group[1] - break - # (B) DB - #selected_group_name = db.get_group_name(selected_group_id) - #if selected_group_name: - # selected_group_name = selected_group_name[0][0] - group_baskets_info = db.get_group_baskets_info_for_group(selected_group_id) + selected_group_name = group_info_dict[selected_group_id][0] + group_baskets_info = db.get_group_baskets_info_for_group(selected_group_id) for group_basket_info in group_baskets_info: if group_basket_info[0] == selected_bskid: selected_basket_info = list(group_basket_info) # INFO: uncomment the two following lines to give MANAGE # rights to the owner of the basket even when through # the group view of the basket. #if group_basket_info[7] == uid: # selected_basket_info[6] = CFG_WEBBASKET_SHARE_LEVELS['MANAGE'] selected_basket_info.pop(7) break else: try: raise InvenioWebBasketWarning(_('The selected topic does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_INVALID_OR_RESTRICTED_BASKET') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) selected_bskid = 0 else: selected_bskid = 0 public_info = db.get_all_external_basket_ids_and_names(uid) if public_info and selected_category == CFG_WEBBASKET_CATEGORIES['EXTERNAL']: valid_category_choice = True if selected_bskid: valid_bskids = [(valid_basket[0], valid_basket[3]) for valid_basket in public_info] if (selected_bskid, 0) in valid_bskids: public_basket_info = db.get_external_basket_info(selected_bskid) if public_basket_info: selected_basket_info = list(public_basket_info[0]) elif (selected_bskid, None) in valid_bskids: try: raise InvenioWebBasketWarning(_('The selected basket is no longer public.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_FORMER_PUBLIC_BASKET') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) selected_bskid = 0 else: try: raise InvenioWebBasketWarning(_('The selected basket does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_INVALID_OR_RESTRICTED_BASKET') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) selected_bskid = 0 if not valid_category_choice: if personal_info: selected_category = CFG_WEBBASKET_CATEGORIES['PRIVATE'] elif group_info: selected_category = CFG_WEBBASKET_CATEGORIES['GROUP'] elif public_info: selected_category = CFG_WEBBASKET_CATEGORIES['EXTERNAL'] else: selected_category = CFG_WEBBASKET_CATEGORIES['ALLPUBLIC'] if not of.startswith('x'): directory_box = webbasket_templates.tmpl_create_directory_box(selected_category, selected_topic, (selected_group_id, selected_group_name), selected_bskid, (personal_info, personal_baskets_info), (group_info, group_baskets_info), public_info, ln) if selected_basket_info: if selected_recid: (bskid, basket_name, last_update, dummy, nb_items, dummy, share_rights) = selected_basket_info (content, bsk_warnings) = __display_basket_single_item(bskid, basket_name, selected_recid, last_update, nb_items, share_rights, selected_category, selected_topic, selected_group_id, optional_params, of, ln) else: (bskid, basket_name, last_update, dummy, nb_items, dummy, share_rights) = selected_basket_info share_level = db.get_basket_share_level(bskid) if share_level: share_level = share_level[0][0] else: share_level = None if share_level == 0: nb_subscribers = db.count_public_basket_subscribers(bskid) else: nb_subscribers = None (content, bsk_warnings) = __display_basket(bskid, basket_name, last_update, nb_items, nb_subscribers, share_rights, share_level, selected_category, selected_topic, selected_group_id, of, ln) warnings.extend(bsk_warnings) if not of.startswith('x'): warnings_html += webbasket_templates.tmpl_warnings(bsk_warnings, ln) else: if not of.startswith('x'): search_box = __create_search_box(uid=uid, category=selected_category, topic=selected_topic, grpid=selected_group_id, p="", n=1, ln=ln) if not of.startswith('x'): body = webbasket_templates.tmpl_display(directory_box, content, search_box) body = warnings_html + body else: body = content if not of.startswith('x'): navtrail = create_webbasket_navtrail(uid, category=selected_category, topic=selected_topic, group=selected_group_id, bskid=selected_bskid, ln=ln) if not of.startswith('x'): return (body, warnings, navtrail) else: return (body, None, None) def __display_basket(bskid, basket_name, last_update, nb_items, nb_subscribers, share_rights, share_level, selected_category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group_id=0, of="hb", ln=CFG_SITE_LANG): """Private function. Display a basket giving its category and topic or group. @param share_rights: rights user has on basket @param share_level: None if basket is not shared, 0 if public basket, > 0 if shared to usergroups but not public. @param selected_category: selected category (see webbasket_config.py) @param selected_topic: # of selected topic to display baskets @param selected_group_id: id of group to display baskets @param ln: language""" _ = gettext_set_language(ln) warnings = [] nb_total_notes = 0 last_note = _("N/A") records = [] notes_dates = [] #date_modification = convert_datetext_to_dategui(date_modification, ln) last_update = convert_datetext_to_dategui(last_update, ln) items = db.get_basket_content(bskid, of) external_recids = [] for (recid, collection_id, nb_notes, last_note, ext_val, int_val, score) in items: notes_dates.append(convert_datetext_to_datestruct(last_note)) last_note = convert_datetext_to_dategui(last_note, ln) colid = collection_id and collection_id or collection_id == 0 and -1 or 0 val = "" nb_total_notes += nb_notes if recid < 0: if ext_val: val = decompress(ext_val) else: external_recids.append(recid) else: if int_val: val = decompress(int_val) else: val = format_record(recid, of, on_the_fly=True) ## external item (record): colid = positive integet ## external item (url): colid = -1 ## local item (record): colid = 0 records.append((recid, colid, nb_notes, last_note, val, score)) if external_recids: external_records = format_external_records(external_recids, of) for external_record in external_records: for record in records: if record[0] == -external_record[0]: idx = records.index(record) tuple_to_list = list(records.pop(idx)) tuple_to_list[4] = external_record[1] records.insert(idx, tuple(tuple_to_list)) break if notes_dates: last_note = convert_datestruct_to_dategui(max(notes_dates), ln) if of == 'hb' or of.startswith('x'): body = webbasket_templates.tmpl_basket(bskid, basket_name, last_update, nb_items, nb_subscribers, (check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READITM']), check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['MANAGE']), check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']), check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']), check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDITM']), check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['DELITM'])), nb_total_notes, share_level, selected_category, selected_topic, selected_group_id, records, of, ln) else: body = "" for rec in records: body += rec[4] return (body, warnings) def __display_basket_single_item(bskid, basket_name, recid, last_update, nb_items, share_rights, selected_category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group_id=0, optional_params={}, of='hb', ln=CFG_SITE_LANG): """Private function. Display a basket giving its category and topic or group. @param share_rights: rights user has on basket @param selected_category: selected category (see webbasket_config.py) @param selected_topic: # of selected topic to display baskets @param selected_group_id: id of group to display baskets @param ln: language""" _ = gettext_set_language(ln) warnings = [] last_note = _("N/A") notes_dates = [] #date_modification = convert_datetext_to_dategui(date_modification, ln) last_update = convert_datetext_to_dategui(last_update, ln) item = db.get_basket_item(bskid, recid, of) if item: (recid, collection_id, nb_notes, last_note, ext_val, int_val, score) = item[0] previous_item_recid = item[1] next_item_recid = item[2] item_index = item[3] else: share_level = db.get_basket_share_level(bskid) if share_level: share_level = share_level[0][0] else: share_level = None if share_level == 0: nb_subscribers = db.count_public_basket_subscribers(bskid) else: nb_subscribers = None (content, bsk_warnings) = __display_basket(bskid, basket_name, last_update, nb_items, nb_subscribers, share_rights, share_level, selected_category, selected_topic, selected_group_id, of, ln) try: raise InvenioWebBasketWarning(_('The selected item does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') bsk_warnings.append(exc.message) #bsk_warnings.append('WRN_WEBBASKET_INVALID_OR_RESTRICTED_ITEM') return (content, bsk_warnings) notes_dates.append(convert_datetext_to_datestruct(last_note)) last_note = convert_datetext_to_dategui(last_note, ln) colid = collection_id and collection_id or collection_id == 0 and -1 or 0 val = "" if recid < 0: if ext_val: val = decompress(ext_val) else: external_record = format_external_records([recid], of) val = external_record and external_record[0][1] or "" else: if int_val: val = decompress(int_val) else: val = format_record(recid, of, on_the_fly=True) item = (recid, colid, nb_notes, last_note, val, score) comments = db.get_notes(bskid, recid) if notes_dates: last_note = convert_datestruct_to_dategui(max(notes_dates), ln) body = webbasket_templates.tmpl_basket_single_item(bskid, basket_name, nb_items, (check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READITM']), check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']), check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']), check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['DELCMT'])), selected_category, selected_topic, selected_group_id, item, comments, previous_item_recid, next_item_recid, item_index, optional_params, of, ln) return (body, warnings) def perform_request_search(uid, selected_category="", selected_topic="", selected_group_id=0, p="", b="", n=0, #format='xm', ln=CFG_SITE_LANG): """Search the baskets... @param uid: user id @param category: selected category (see webbasket_config.py) @param selected_topic: # of selected topic to display baskets @param selected_group_id: id of group to display baskets @param ln: language""" _ = gettext_set_language(ln) body = "" #warnings = [] warnings_html = "" (b_category, b_topic_or_grpid, b_warnings) = wash_b_search(b) # we extract the category from the washed b GET variable. # if a valid category was returned we use it as the selected category. if b_category: selected_category = b_category if selected_category == CFG_WEBBASKET_CATEGORIES['PRIVATE']: selected_topic = b_topic_or_grpid elif selected_category == CFG_WEBBASKET_CATEGORIES['GROUP']: selected_group_id = b_topic_or_grpid # if no category was returned and there were warnings it means there was a # bad input, send the warning to the user and return the page. elif b_warnings: navtrail = create_webbasket_navtrail(uid, search_baskets=True, ln=ln) body = webbasket_templates.tmpl_warnings(b_warnings, ln) return (body, navtrail) # if no category was returned and there were no warnings it means no category # was defined in the b GET variable. If the user has not defined a category # either using the category GET variable it means there is no category defined # whatsoever. elif not selected_category: selected_category = "" # finally, if no category was returned but the user has defined a category # using the category GET variable we extract the category after washing the # variable. else: (selected_category, category_warnings) = wash_category(selected_category) if not selected_category and category_warnings: navtrail = create_webbasket_navtrail(uid, search_baskets=True, ln=ln) body = webbasket_templates.tmpl_warnings(category_warnings, ln) return (body, navtrail) if selected_category == CFG_WEBBASKET_CATEGORIES['PRIVATE'] and selected_topic: (selected_topic, topic_warnings) = wash_topic(uid, selected_topic) if not selected_topic and topic_warnings: navtrail = create_webbasket_navtrail(uid, search_baskets=True, ln=ln) body = webbasket_templates.tmpl_warnings(topic_warnings, ln) return (body, navtrail) if selected_category == CFG_WEBBASKET_CATEGORIES['GROUP'] and selected_group_id: (selected_group_id, group_warnings) = wash_group(uid, selected_group_id) if not selected_group_id and group_warnings: navtrail = create_webbasket_navtrail(uid, search_baskets=True, ln=ln) body = webbasket_templates.tmpl_warnings(group_warnings, ln) return (body, navtrail) # IDEA: in case we pass an "action=search" GET variable we can use the # following bit to warn the user he's searching for an empty search pattern. #if action == "search" and not p: # warnings_html += webbasket_templates.tmpl_warnings('WRN_WEBBASKET_NO_SEARCH_PATTERN', ln) # perform_search = 0 if p: # Let's set some initial values personal_search_results = None total_no_personal_search_results = 0 group_search_results = None total_no_group_search_results = 0 public_search_results = None total_no_public_search_results = 0 all_public_search_results = None total_no_all_public_search_results = 0 # Let's precalculate the local search resutls # and the pattern for the external search results local_search_results = search_unit(p) # How strict should the pattern be? Look for the exact word # (using word boundaries: \b) or is any substring enough? # not that strict: # since we remove the html markup before searching for the pattern we # can use a rather simple pattern here. # INFO: we choose a not so strict pattern, since there are issues with # word bounderies and utf-8 strings (ex. with greek that was tested) pattern = re.compile(r'%s' % (re.escape(p),), re.DOTALL + re.MULTILINE + re.IGNORECASE + re.UNICODE) #pattern = re.compile(r'%s(?!([^<]+)?>)' % (p,), re.DOTALL + re.MULTILINE + re.IGNORECASE + re.UNICODE) # strict: # since we remove the html markup before searching for the pattern we # can use a rather simple pattern here. #pattern = re.compile(r'\b%s\b' % (re.escape(p),), re.DOTALL + re.MULTILINE + re.IGNORECASE + re.UNICODE) #pattern = re.compile(r'%s\b(?!([^<]+)?>)' % (p,), re.DOTALL + re.MULTILINE + re.IGNORECASE + re.UNICODE) # TODO: All the external records are now saved automatically first in xml. # So, the search should be done on the "xm" formatted records in the database # and not the "hb" ones. (That is not the case for their comments though). # Records in xml in the database are stored escaped. It's then suggested # that the pattern is also escaped before we performed the search for more # consistent resutls. We could also use .replace("\n", "") to clean the # content (after the removal of html markup) from all the newline characters. # The search format for external records. This means in which format will # the external records be fetched from the database to be searched then. format = 'xm' ### Calculate the search results for the user's personal baskets ### if b.startswith("P") or not b: personal_search_results = {} personal_items = db.get_all_items_in_user_personal_baskets(uid, selected_topic, format) personal_local_items = personal_items[0] personal_external_items = personal_items[1] personal_external_items_xml_records = {} for local_info_per_basket in personal_local_items: bskid = local_info_per_basket[0] basket_name = local_info_per_basket[1] topic = local_info_per_basket[2] recid_list = local_info_per_basket[3] local_recids_per_basket = intbitset(map(int, recid_list.strip(',').split(','))) intsec = local_search_results.intersection(local_recids_per_basket) if intsec: personal_search_results[bskid] = [basket_name, topic, len(intsec), list(intsec)] total_no_personal_search_results += len(intsec) for external_info_per_basket in personal_external_items: bskid = external_info_per_basket[0] basket_name = external_info_per_basket[1] topic = external_info_per_basket[2] recid = external_info_per_basket[3] value = external_info_per_basket[4] xml_record = decompress(value) personal_external_items_xml_records[recid] = xml_record text = remove_html_markup(xml_record) #text = text.replace('\n', '') result = pattern.search(text) if result: if personal_search_results.has_key(bskid): personal_search_results[bskid][2] += 1 personal_search_results[bskid][3].append(recid) else: personal_search_results[bskid] = [basket_name, topic, 1, [recid]] total_no_personal_search_results += 1 if n: personal_items_by_matching_notes = db.get_all_items_in_user_personal_baskets_by_matching_notes(uid, selected_topic, p) for info_per_basket_by_matching_notes in personal_items_by_matching_notes: bskid = info_per_basket_by_matching_notes[0] basket_name = info_per_basket_by_matching_notes[1] topic = info_per_basket_by_matching_notes[2] recid_list = info_per_basket_by_matching_notes[3] recids_per_basket_by_matching_notes = set(map(int, recid_list.strip(',').split(','))) if personal_search_results.has_key(bskid): no_personal_search_results_per_basket_so_far = personal_search_results[bskid][2] personal_search_results[bskid][3] = list(set(personal_search_results[bskid][3]).union(recids_per_basket_by_matching_notes)) personal_search_results[bskid][2] = len(personal_search_results[bskid][3]) total_no_personal_search_results += ( personal_search_results[bskid][2] - no_personal_search_results_per_basket_so_far ) else: personal_search_results[bskid] = [basket_name, topic, len(recids_per_basket_by_matching_notes), list(recids_per_basket_by_matching_notes)] total_no_personal_search_results += len(recids_per_basket_by_matching_notes) # For every found record: calculate the number of notes # and the HTML representation of the record. for bskid in personal_search_results.keys(): recids = personal_search_results[bskid][3] number_of_notes_per_record = db.get_number_of_notes_per_record_in_basket(bskid, recids) records = [] for recid_and_notes in number_of_notes_per_record: recid = recid_and_notes[0] number_of_notes = recid_and_notes[1] if recid < 0: xml_record = personal_external_items_xml_records[recid] record_html = format_record(None, of='hwbsr', xml_record=xml_record) records.append((recid, number_of_notes, record_html)) else: record_html = format_record(recid, of='hwbsr', on_the_fly=True) records.append((recid, number_of_notes, record_html)) personal_search_results[bskid][3] = records ### Calculate the search results for the user's group baskets ### if b.startswith("G") or not b: group_search_results = {} group_items = db.get_all_items_in_user_group_baskets(uid, selected_group_id, format) group_local_items = group_items[0] group_external_items = group_items[1] group_external_items_xml_records = {} for local_info_per_basket in group_local_items: bskid = local_info_per_basket[0] basket_name = local_info_per_basket[1] grpid = local_info_per_basket[2] group_name = local_info_per_basket[3] share_rights = local_info_per_basket[4] recid_list = local_info_per_basket[5] local_recids_per_basket = intbitset(map(int, recid_list.strip(',').split(','))) intsec = local_search_results.intersection(local_recids_per_basket) if intsec: share_rights_view_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']) share_rights_add_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) share_rights_notes = (share_rights_view_notes, share_rights_add_notes) group_search_results[bskid] = [basket_name, grpid, group_name, share_rights_notes, len(intsec), list(intsec)] total_no_group_search_results += len(intsec) for external_info_per_basket in group_external_items: bskid = external_info_per_basket[0] basket_name = external_info_per_basket[1] grpid = external_info_per_basket[2] group_name = external_info_per_basket[3] share_rights = external_info_per_basket[4] recid = external_info_per_basket[5] value = external_info_per_basket[6] xml_record = decompress(value) group_external_items_xml_records[recid] = xml_record text = remove_html_markup(xml_record) #text = text.replace('\n', '') result = pattern.search(text) if result: if group_search_results.has_key(bskid): group_search_results[bskid][4] += 1 group_search_results[bskid][5].append(recid) else: share_rights_view_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']) share_rights_add_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) share_rights_notes = (share_rights_view_notes, share_rights_add_notes) group_search_results[bskid] = [basket_name, grpid, group_name, share_rights_notes, 1, [recid]] total_no_group_search_results += 1 if n: group_items_by_matching_notes = db.get_all_items_in_user_group_baskets_by_matching_notes(uid, selected_group_id, p) for info_per_basket_by_matching_notes in group_items_by_matching_notes: bskid = info_per_basket_by_matching_notes[0] basket_name = info_per_basket_by_matching_notes[1] grpid = info_per_basket_by_matching_notes[2] group_name = info_per_basket_by_matching_notes[3] share_rights = info_per_basket_by_matching_notes[4] recid_list = info_per_basket_by_matching_notes[5] recids_per_basket_by_matching_notes = set(map(int, recid_list.strip(',').split(','))) if group_search_results.has_key(bskid): no_group_search_results_per_basket_so_far = group_search_results[bskid][4] group_search_results[bskid][5] = list(set(group_search_results[bskid][5]).union(recids_per_basket_by_matching_notes)) group_search_results[bskid][4] = len(group_search_results[bskid][5]) total_no_group_search_results += ( group_search_results[bskid][4] - no_group_search_results_per_basket_so_far ) else: share_rights_view_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']) share_rights_add_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) share_rights_notes = (share_rights_view_notes, share_rights_add_notes) group_search_results[bskid] = [basket_name, grpid, group_name, share_rights_notes, len(recids_per_basket_by_matching_notes), list(recids_per_basket_by_matching_notes)] total_no_group_search_results += len(recids_per_basket_by_matching_notes) # For every found record: calculate the number of notes # and the HTML representation of the record. for bskid in group_search_results.keys(): recids = group_search_results[bskid][5] number_of_notes_per_record = db.get_number_of_notes_per_record_in_basket(bskid, recids) records = [] for recid_and_notes in number_of_notes_per_record: recid = recid_and_notes[0] number_of_notes = recid_and_notes[1] if recid < 0: xml_record = group_external_items_xml_records[recid] record_html = format_record(None, of='hwbsr', xml_record=xml_record) records.append((recid, number_of_notes, record_html)) else: record_html = format_record(recid, of='hwbsr', on_the_fly=True) records.append((recid, number_of_notes, record_html)) group_search_results[bskid][5] = records ### Calculate the search results for the user's public baskets ### if b.startswith("E") or not b: public_search_results = {} public_items = db.get_all_items_in_user_public_baskets(uid, format) public_local_items = public_items[0] public_external_items = public_items[1] public_external_items_xml_records = {} for local_info_per_basket in public_local_items: bskid = local_info_per_basket[0] basket_name = local_info_per_basket[1] share_rights = local_info_per_basket[2] recid_list = local_info_per_basket[3] local_recids_per_basket = intbitset(map(int, recid_list.strip(',').split(','))) intsec = local_search_results.intersection(local_recids_per_basket) if intsec: share_rights_view_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']) share_rights_add_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) share_rights_notes = (share_rights_view_notes, share_rights_add_notes) public_search_results[bskid] = [basket_name, share_rights_notes, len(intsec), list(intsec)] total_no_public_search_results += len(intsec) for external_info_per_basket in public_external_items: bskid = external_info_per_basket[0] basket_name = external_info_per_basket[1] share_rights = external_info_per_basket[2] recid = external_info_per_basket[3] value = external_info_per_basket[4] xml_record = decompress(value) public_external_items_xml_records[recid] = xml_record text = remove_html_markup(xml_record) #text = text.replace('\n', '') result = pattern.search(text) if result: if public_search_results.has_key(bskid): public_search_results[bskid][2] += 1 public_search_results[bskid][3].append(recid) else: share_rights_view_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']) share_rights_add_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) share_rights_notes = (share_rights_view_notes, share_rights_add_notes) public_search_results[bskid] = [basket_name, share_rights_notes, 1, [recid]] total_no_public_search_results += 1 if n: public_items_by_matching_notes = db.get_all_items_in_user_public_baskets_by_matching_notes(uid, p) for info_per_basket_by_matching_notes in public_items_by_matching_notes: bskid = info_per_basket_by_matching_notes[0] basket_name = info_per_basket_by_matching_notes[1] share_rights = info_per_basket_by_matching_notes[2] recid_list = info_per_basket_by_matching_notes[3] recids_per_basket_by_matching_notes = set(map(int, recid_list.strip(',').split(','))) if public_search_results.has_key(bskid): no_public_search_results_per_basket_so_far = public_search_results[bskid][2] public_search_results[bskid][3] = list(set(public_search_results[bskid][3]).union(recids_per_basket_by_matching_notes)) public_search_results[bskid][2] = len(public_search_results[bskid][3]) total_no_public_search_results += ( public_search_results[bskid][2] - no_public_search_results_per_basket_so_far ) else: share_rights_view_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']) share_rights_add_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) share_rights_notes = (share_rights_view_notes, share_rights_add_notes) public_search_results[bskid] = [basket_name, share_rights_notes, len(recids_per_basket_by_matching_notes), list(recids_per_basket_by_matching_notes)] total_no_public_search_results += len(recids_per_basket_by_matching_notes) # For every found record: calculate the number of notes # and the HTML representation of the record. for bskid in public_search_results.keys(): recids = public_search_results[bskid][3] number_of_notes_per_record = db.get_number_of_notes_per_record_in_basket(bskid, recids) records = [] for recid_and_notes in number_of_notes_per_record: recid = recid_and_notes[0] number_of_notes = recid_and_notes[1] if recid < 0: xml_record = public_external_items_xml_records[recid] record_html = format_record(None, of='hwbsr', xml_record=xml_record) records.append((recid, number_of_notes, record_html)) else: record_html = format_record(recid, of='hwbsr', on_the_fly=True) records.append((recid, number_of_notes, record_html)) public_search_results[bskid][3] = records ### Calculate the search results for all the public baskets ### if b.startswith("A"): all_public_search_results = {} all_public_items = db.get_all_items_in_all_public_baskets(format) all_public_local_items = all_public_items[0] all_public_external_items = all_public_items[1] all_public_external_items_xml_records = {} for local_info_per_basket in all_public_local_items: bskid = local_info_per_basket[0] basket_name = local_info_per_basket[1] share_rights = local_info_per_basket[2] recid_list = local_info_per_basket[3] local_recids_per_basket = intbitset(map(int, recid_list.strip(',').split(','))) intsec = local_search_results.intersection(local_recids_per_basket) if intsec: share_rights_view_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']) share_rights_add_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) share_rights_notes = (share_rights_view_notes, share_rights_add_notes) all_public_search_results[bskid] = [basket_name, share_rights_notes, len(intsec), list(intsec)] total_no_all_public_search_results += len(intsec) for external_info_per_basket in all_public_external_items: bskid = external_info_per_basket[0] basket_name = external_info_per_basket[1] share_rights = external_info_per_basket[2] recid = external_info_per_basket[3] value = external_info_per_basket[4] xml_record = decompress(value) all_public_external_items_xml_records[recid] = xml_record text = remove_html_markup(xml_record) #text = text.replace('\n', '') result = pattern.search(text) if result: if all_public_search_results.has_key(bskid): all_public_search_results[bskid][2] += 1 all_public_search_results[bskid][3].append(recid) else: share_rights_view_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']) share_rights_add_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) share_rights_notes = (share_rights_view_notes, share_rights_add_notes) all_public_search_results[bskid] = [basket_name, share_rights_notes, 1, [recid]] total_no_all_public_search_results += 1 if n: all_public_items_by_matching_notes = db.get_all_items_in_all_public_baskets_by_matching_notes(p) for info_per_basket_by_matching_notes in all_public_items_by_matching_notes: bskid = info_per_basket_by_matching_notes[0] basket_name = info_per_basket_by_matching_notes[1] share_rights = info_per_basket_by_matching_notes[2] recid_list = info_per_basket_by_matching_notes[3] recids_per_basket_by_matching_notes = set(map(int, recid_list.strip(',').split(','))) if all_public_search_results.has_key(bskid): no_all_public_search_results_per_basket_so_far = all_public_search_results[bskid][2] all_public_search_results[bskid][3] = list(set(all_public_search_results[bskid][3]).union(recids_per_basket_by_matching_notes)) all_public_search_results[bskid][2] = len(all_public_search_results[bskid][3]) total_no_all_public_search_results += ( all_public_search_results[bskid][2] - no_all_public_search_results_per_basket_so_far ) else: share_rights_view_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']) share_rights_add_notes = check_sufficient_rights(share_rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) share_rights_notes = (share_rights_view_notes, share_rights_add_notes) all_public_search_results[bskid] = [basket_name, share_rights_notes, len(recids_per_basket_by_matching_notes), list(recids_per_basket_by_matching_notes)] total_no_all_public_search_results += len(recids_per_basket_by_matching_notes) # For every found record: calculate the number of notes # and the HTML representation of the record. for bskid in all_public_search_results.keys(): recids = all_public_search_results[bskid][3] number_of_notes_per_record = db.get_number_of_notes_per_record_in_basket(bskid, recids) records = [] for recid_and_notes in number_of_notes_per_record: recid = recid_and_notes[0] number_of_notes = recid_and_notes[1] if recid < 0: xml_record = all_public_external_items_xml_records[recid] record_html = format_record(None, of='hwbsr', xml_record=xml_record) records.append((recid, number_of_notes, record_html)) else: record_html = format_record(recid, of='hwbsr', on_the_fly=True) records.append((recid, number_of_notes, record_html)) all_public_search_results[bskid][3] = records search_results_html = webbasket_templates.tmpl_search_results(personal_search_results, total_no_personal_search_results, group_search_results, total_no_group_search_results, public_search_results, total_no_public_search_results, all_public_search_results, total_no_all_public_search_results, ln) else: search_results_html = None search_box = __create_search_box(uid=uid, category=selected_category, topic=selected_topic, grpid=selected_group_id, p=p, n=n, ln=ln) body = webbasket_templates.tmpl_display(search_box=search_box, search_results=search_results_html) body = warnings_html + body navtrail = create_webbasket_navtrail(uid, search_baskets=True, ln=ln) return (body, navtrail) def perform_request_write_note(uid, category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], topic="", group_id=0, bskid=0, recid=0, cmtid=0, ln=CFG_SITE_LANG): """Display a note writing form @param uid: user id @param bskid: basket id @param recid: record id (comments are on a specific record in a specific basket) @param cmtid: if provided this comment is a reply to comment cmtid. @param category: selected category @param topic: selected topic @param group_id: selected group id @param ln: language """ _ = gettext_set_language(ln) optional_params = {} #warnings_rights = [] warnings_html = "" if not check_user_can_comment(uid, bskid): try: raise InvenioWebBasketWarning(_('You do not have permission to write notes to this item.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings_rights = ['WRN_WEBBASKET_RESTRICTED_WRITE_NOTES'] warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) else: if cmtid and db.note_belongs_to_item_in_basket_p(cmtid, recid, bskid): optional_params["Add note"] = db.get_note(cmtid) optional_params["Reply to"] = cmtid elif cmtid: optional_params["Add note"] = () try: raise InvenioWebBasketWarning(_('The note you are quoting does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') optional_params["Warnings"] = exc.message else: optional_params["Add note"] = () (body, warnings, navtrail) = perform_request_display(uid=uid, selected_category=category, selected_topic=topic, selected_group_id=group_id, selected_bskid=bskid, selected_recid=recid, optional_params=optional_params, of='hb', ln=CFG_SITE_LANG) if not warnings: body = warnings_html + body #warnings = warnings_rights return (body, navtrail) def perform_request_save_note(uid, category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], topic="", group_id=0, bskid=0, recid=0, note_title="", note_body="", editor_type='textarea', ln=CFG_SITE_LANG, reply_to=None): """ Save a given comment if able to. @param uid: user id (int) @param bskid: basket id (int) @param recid: record id (int) @param title: title of comment (string) @param text: comment's body (string) @param ln: language (string) @param editor_type: the kind of editor/input used for the comment: 'textarea', 'ckeditor' @param reply_to: the id of the comment we are replying to """ _ = gettext_set_language(ln) optional_params = {} #warnings_rights = [] warnings_html = "" if not check_user_can_comment(uid, bskid): try: raise InvenioWebBasketWarning(_('You do not have permission to write notes to this item.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings_rights = exc.message #warnings_rights = ['WRN_WEBBASKET_RESTRICTED_WRITE_NOTES'] warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) else: if not note_title or \ ((not note_body and editor_type != 'ckeditor') or \ (not remove_html_markup(note_body, '').replace('\n', '').replace('\r', '').strip() and editor_type == 'ckeditor')): optional_params["Incomplete note"] = (note_title, note_body) try: raise InvenioWebBasketWarning(_('You must fill in both the subject and the body of the note.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') optional_params["Warnings"] = exc.message else: if editor_type == 'ckeditor': # Here we remove the line feeds introduced by CKEditor (they # have no meaning for the user) and replace the HTML line # breaks by linefeeds, so that we are close to an input that # would be done without the CKEditor. That's much better if a # reply to a comment is made with a browser that does not # support CKEditor. note_body = note_body.replace('\n', '').replace('\r', '').replace('<br />', '\n') if not(db.save_note(uid, bskid, recid, note_title, note_body, reply_to)): # TODO: The note could not be saved. DB problem? pass else: # TODO: inform about successful annotating. pass (body, warnings, navtrail) = perform_request_display(uid=uid, selected_category=category, selected_topic=topic, selected_group_id=group_id, selected_bskid=bskid, selected_recid=recid, optional_params=optional_params, of='hb', ln=CFG_SITE_LANG) if not warnings: body = warnings_html + body #warnings = warnings_rights return (body, navtrail) def perform_request_delete_note(uid, category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], topic="", group_id=0, bskid=0, recid=0, cmtid=0, ln=CFG_SITE_LANG): """Delete comment cmtid on record recid for basket bskid.""" _ = gettext_set_language(ln) #warnings_notes = [] warnings_html = "" if not __check_user_can_perform_action(uid, bskid, CFG_WEBBASKET_SHARE_LEVELS['DELCMT']): try: raise InvenioWebBasketWarning(_('You do not have permission to delete this note.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings_notes.append(exc.message) #warnings_notes.append('WRN_WEBBASKET_RESTRICTED_DELETE_NOTES') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) else: if cmtid and db.note_belongs_to_item_in_basket_p(cmtid, recid, bskid): db.delete_note(bskid, recid, cmtid) else: try: raise InvenioWebBasketWarning(_('The note you are deleting does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings_notes.append(exc.message) #warnings_notes.append('WRN_WEBBASKET_DELETE_INVALID_NOTE') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) (body, warnings, navtrail) = perform_request_display(uid=uid, selected_category=category, selected_topic=topic, selected_group_id=group_id, selected_bskid=bskid, selected_recid=recid, of='hb', ln=CFG_SITE_LANG) body = warnings_html + body #warnings.extend(warnings_notes) return (body, navtrail) def perform_request_add(uid, recids=[], category='', bskid=0, colid=0, es_title='', es_desc='', es_url='', note_body='', editor_type='', b='', successful_add=False, copy=False, wait=False, referer='', ln=CFG_SITE_LANG): """Add records to baskets @param uid: user id @param recids: list of records to add @param colid: in case of external collections, the id of the collection the records belong to @param bskids: list of baskets to add records to. if not provided, will return a page where user can select baskets @param es_title: the title of the external source @param es_desc: the description of the external source @param es_url: the url of the external source @param referer: URL of the referring page @param ln: language""" _ = gettext_set_language(ln) if successful_add: body = webbasket_templates.tmpl_add(recids=recids, category=category, bskid=bskid, colid=colid, successful_add=True, copy=copy, referer=referer, ln=ln) #warnings = [] navtrail = create_webbasket_navtrail(uid, add_to_basket=True, ln=ln) return (body, navtrail) #warnings = [] warnings_html = "" if type(recids) is not list: recids = [recids] validated_recids = [] if colid == 0: # Local records for recid in recids: recid = int(recid) if recid > 0 and record_exists(recid) == 1: validated_recids.append(recid) elif recid < 0 and copy: # if we are copying a record, colid will always be 0 but we may # still get negative recids when it comes to external items. # In that case, we just skip the checking and add them directly # to the validated_recids. validated_recids.append(recid) user_info = collect_user_info(uid) recids_to_remove = [] for recid in validated_recids: (auth_code, dummy) = check_user_can_view_record(user_info, recid) if auth_code: # User is not authorized to view record. # We should not remove items from the list while we parse it. # Better store them in another list and in the end remove them. #validated_recids.remove(recid) recids_to_remove.append(recid) try: raise InvenioWebBasketWarning(_('Sorry, you do not have sufficient rights to add record #%i.') % recid) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append(('WRN_WEBBASKET_NO_RIGHTS_TO_ADD_THIS_RECORD', recid)) try: raise InvenioWebBasketWarning(_('Some of the items were not added due to lack of sufficient rights.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') warnings_html = webbasket_templates.tmpl_warnings(exc.message, ln) #warnings_html = webbasket_templates.tmpl_warnings('WRN_WEBBASKET_NO_RIGHTS_TO_ADD_RECORDS', ln) for recid in recids_to_remove: validated_recids.remove(recid) elif colid > 0: # External records, no need to validate. validated_recids.extend(recids) elif colid == -1: # External source. es_warnings = [] if not es_title: try: raise InvenioWebBasketWarning(_('Please provide a title for the external source.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') es_warnings.append(exc.message) if not es_desc: try: raise InvenioWebBasketWarning(_('Please provide a description for the external source.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') es_warnings.append(exc.message) if not es_url: try: raise InvenioWebBasketWarning(_('Please provide a url for the external source.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') es_warnings.append(exc.message) else: (is_valid, status, dummy) = url_is_valid(es_url) if not is_valid: if str(status).startswith('0'): try: raise InvenioWebBasketWarning(_('The url you have provided is not valid.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') es_warnings.append(exc.message) #es_warnings.append('WRN_WEBBASKET_NO_VALID_URL_0') elif str(status).startswith('4'): try: raise InvenioWebBasketWarning(_('The url you have provided is not valid: The request contains bad syntax or cannot be fulfilled.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') es_warnings.append(exc.message) #es_warnings.append('WRN_WEBBASKET_NO_VALID_URL_4') elif str(status).startswith('5'): try: raise InvenioWebBasketWarning(_('The url you have provided is not valid: The server failed to fulfil an apparently valid request.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') es_warnings.append(exc.message) #es_warnings.append('WRN_WEBBASKET_NO_VALID_URL_5') elif not (es_url.startswith("http://") or es_url.startswith("https://")): es_url = "http://" + es_url if es_warnings: #warnings.extend(es_warnings) warnings_html += webbasket_templates.tmpl_warnings(es_warnings, ln) if not validated_recids: # in case there are no record ids select assume we want to add an # external source. colid = -1 # This part of code is under the current circumstances never ran, # since if there no validated_recids, colid is set to -1. # IDEA: colid should by default (i.e. when not set) be -2 and when local # recids are added we should use the 0 value. #if not validated_recids and colid >= 0: # warnings.append('WRN_WEBBASKET_NO_RECORD') # body += webbasket_templates.tmpl_warnings(warnings, ln) # if referer and not(referer.find(CFG_SITE_URL) == -1): # body += webbasket_templates.tmpl_back_link(referer, ln) # return (body, warnings) if b or (category and bskid): # if b was not defined we use category and bskid to construct it. if not b: b = category + "_" + str(bskid) # we extract the category and the bskid from the washed b POST variable # or the constracted b variable from category and bskid. (category, b_bskid, b_warnings) = wash_b_add(b) # if there were warnings it means there was a bad input. # Send the warning to the user and return the page. if b_warnings: #warnings.extend(b_warnings) warnings_html += webbasket_templates.tmpl_warnings(b_warnings, ln) if not b_warnings: (bskid, b_warnings) = wash_bskid(uid, category, b_bskid) if b_warnings: #warnings.extend(b_warnings) warnings_html += webbasket_templates.tmpl_warnings(b_warnings, ln) if not b_warnings: if not(__check_user_can_perform_action(uid, bskid, CFG_WEBBASKET_SHARE_LEVELS['ADDITM'])): try: raise InvenioWebBasketWarning(_('Sorry, you do not have sufficient rights on this basket.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_NO_RIGHTS') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) if not warnings_html: if ( colid >= 0 and not validated_recids ) or ( colid == -1 and ( not es_title or not es_desc or not es_url ) ): try: raise InvenioWebBasketWarning(_('No records to add.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) if not warnings_html and not wait: if colid == -1: es_title = es_title es_desc = nl2br(es_desc) added_items = db.add_to_basket(uid, validated_recids, colid, bskid, es_title, es_desc, es_url) if added_items: if (note_body and editor_type != 'ckeditor') or \ (editor_type == 'ckeditor' and \ remove_html_markup(note_body, '').replace('\n', '').replace('\r', '').strip()): if editor_type == 'ckeditor': # Here we remove the line feeds introduced by CKEditor (they # have no meaning for the user) and replace the HTML line # breaks by linefeeds, so that we are close to an input that # would be done without the CKEditor. That's much better if a # reply to a comment is made with a browser that does not # support CKEditor. note_title = '' note_body = note_body.replace('\n', '').replace('\r', '').replace('<br />', '\n') else: note_title = '' for recid in added_items: if not(db.save_note(uid, bskid, recid, note_title, note_body, reply_to=None)): # TODO: The note could not be saved. DB problem? pass if colid > 0: format_external_records(added_items, of="xm") return perform_request_add(uid=uid, recids=recids, category=category, bskid=bskid, colid=colid, successful_add=True, copy=copy, referer=referer) else: try: raise InvenioWebBasketWarning(_('Cannot add items to the selected basket. Invalid parameters.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_INVALID_ADD_TO_PARAMETERS') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) - personal_basket_list = db.get_all_personal_basket_ids_and_names_by_topic_for_add_to_list(uid) - group_basket_list = db.get_all_group_basket_ids_and_names_by_group_for_add_to_list(uid) + personal_basket_list = db.get_all_user_personal_basket_ids_by_topic(uid) + group_basket_list = db.get_all_user_group_basket_ids_by_group_with_add_rights(uid) if not personal_basket_list and not group_basket_list: - bskid = db.create_basket(uid=uid, basket_name="Untitled basket", topic="Untitled topic") + bskid = db.create_basket(uid=uid, basket_name=_('Untitled basket'), topic=_('Untitled topic')) try: raise InvenioWebBasketWarning(_('A default topic and basket have been automatically created. Edit them to rename them as you see fit.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_DEFAULT_TOPIC_AND_BASKET') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) if colid >= 0 and validated_recids: (body, navtrail) = perform_request_add(uid=uid, recids=validated_recids, category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], bskid=bskid, colid=colid, referer=referer, ln=ln) body = warnings_html + body return (body, navtrail) else: - personal_basket_list = db.get_all_personal_basket_ids_and_names_by_topic_for_add_to_list(uid) + personal_basket_list = db.get_all_user_personal_basket_ids_by_topic(uid) body = webbasket_templates.tmpl_add(recids=recids, category=category, bskid=bskid, colid=colid, es_title=es_title, es_desc=es_desc, es_url=es_url, note_body=note_body, personal_basket_list=personal_basket_list, group_basket_list=group_basket_list, copy=copy, referer=referer, ln=ln) body = warnings_html + body navtrail = create_webbasket_navtrail(uid, add_to_basket=True, ln=ln) return (body, navtrail) def perform_request_delete(uid, bskid, confirmed=0, category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group_id=0, ln=CFG_SITE_LANG): """Delete a given basket. @param uid: user id (user has to be owner of this basket) @param bskid: basket id @param confirmed: if 0 will return a confirmation page; if 1 will delete basket. @param category: category currently displayed @param selected_topic: topic currently displayed @param selected_group_id: if category is group, id of the group currently displayed @param ln: language""" _ = gettext_set_language(ln) body = '' #warnings = [] if not(db.check_user_owns_baskets(uid, [bskid])): try: raise InvenioWebBasketWarning(_('Sorry, you do not have sufficient rights on this basket.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append(('WRN_WEBBASKET_NO_RIGHTS',)) return body if confirmed: if not db.delete_basket(bskid): # TODO: The item was not deleted. DB problem? pass else: body = webbasket_templates.tmpl_confirm_delete(bskid, db.count_subscribers(uid, bskid), category, selected_topic, selected_group_id, ln) return body def delete_record(uid, bskid, recid): """Delete a given record in a given basket. @param uid: user id (user has to have sufficient rights on basket @param bskid: basket id @param recid: record id """ if __check_user_can_perform_action(uid, bskid, CFG_WEBBASKET_SHARE_LEVELS['DELITM']): db.delete_item(bskid, recid) def move_record(uid, bskid, recid, direction): """Move a record up or down in a basket (change score). @param uid: user id (user has to have manage rights over this basket) @param bskid: basket id @param recid: record we want to move @param direction: CFG_WEBBASKET_ACTIONS['UP'] or CFG_WEBBASKET_ACTIONS['DOWN'] """ if __check_user_can_perform_action(uid, bskid, CFG_WEBBASKET_SHARE_LEVELS['MANAGE']): db.move_item(bskid, recid, direction) def perform_request_edit(uid, bskid, topic="", new_name='', new_topic = '', new_topic_name='', groups=[], external='', ln=CFG_SITE_LANG): """Interface for management of basket. If names, groups or external is provided, will save new rights into database, else will provide interface. @param uid: user id (user has to have sufficient rights on this basket @param bskid: basket id to change rights on @param topic: topic currently used (int) @param new_name: new name of basket @param new_topic: topic in which to move basket (int), new_topic_name must be left blank @param new_topic_name: new topic in which to move basket (will overwrite param new_topic) @param groups: list of strings formed in this way: group_id + '_' + rights @param external: rights for everybody (can be 'NO') @param ln: language """ body = '' #warnings = [] # TODO: external rights must be washed, it can only be one of the following: # NO, READITM, READCMT, ADDCMT _ = gettext_set_language(ln) rights = db.get_max_user_rights_on_basket(uid, bskid) if rights != CFG_WEBBASKET_SHARE_LEVELS['MANAGE']: try: raise InvenioWebBasketWarning(_('Sorry, you do not have sufficient rights on this basket.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append(('WRN_WEBBASKET_NO_RIGHTS',)) return body bsk_name = db.get_basket_name(bskid) if not(groups) and not(external) and not(new_name) and not(new_topic) and not(new_topic_name): # display interface topics = map(lambda x: x[0], db.get_personal_topics_infos(uid)) groups_rights = db.get_groups_subscribing_to_basket(bskid) external_rights = '' if groups_rights and groups_rights[0][0] == 0: external_rights = groups_rights[0][2] groups_rights = groups_rights[1:] display_delete = db.check_user_owns_baskets(uid, bskid) display_general = display_delete if isGuestUser(uid): display_sharing = 0 else: display_sharing = 1 body = webbasket_templates.tmpl_edit(bskid=bskid, bsk_name=bsk_name, display_general=display_general, topics=topics, topic=topic, display_delete=display_delete, display_sharing=display_sharing, groups_rights=groups_rights, external_rights=external_rights, ln=ln) else: out_groups = {} if len(groups): for group in groups: (group_id, group_rights) = group.split('_') out_groups[group_id] = group_rights out_groups['0'] = external if not(isGuestUser(uid)): db.update_rights(bskid, out_groups) if new_name != bsk_name: db.rename_basket(bskid, new_name) if new_topic_name: db.move_baskets_to_topic(uid, bskid, new_topic_name) elif not (new_topic == "-1" or new_topic == topic): if db.check_user_owns_baskets(uid, bskid): topics = map(lambda x: x[0], db.get_personal_topics_infos(uid)) if new_topic in topics: new_topic_name = new_topic db.move_baskets_to_topic(uid, bskid, new_topic_name) else: # TODO: inform the admin #errors.append(('ERR_WEBBASKET_DB_ERROR')) pass else: topic = "" #warnings.append(('ERR_WEBBASKET_NOT_OWNER')) return body def perform_request_edit_topic(uid, topic='', new_name='', ln=CFG_SITE_LANG): """Interface for editing of topic. @param uid: user id (user has to have sufficient rights on this basket @param topic: topic to be edited @param new_name: new name of topic @param ln: language """ body = '' #warnings = [] #rights = db.get_max_user_rights_on_basket(uid, bskid) #if rights != CFG_WEBBASKET_SHARE_LEVELS['MANAGE']: # errors.append(('ERR_WEBBASKET_NO_RIGHTS',)) # return (body, errors, warnings) if not(new_name): # display interface #display_delete = db.check_user_owns_baskets(uid, bskid) #display_general = display_delete #if isGuestUser(uid): #display_sharing = 0 #else: #display_sharing = 1 display_general = True display_delete = True body = webbasket_templates.tmpl_edit_topic(display_general=display_general, topic=topic, display_delete=display_delete, ln=ln) else: if cgi.escape(new_name, True) != cgi.escape(topic, True): db.rename_topic(uid, topic, new_name) return body def perform_request_add_group(uid, bskid, topic="", group_id=0, ln=CFG_SITE_LANG): """If group id is specified, share basket bskid to this group with READITM rights; else return a page for selection of a group. @param uid: user id (selection only of groups user is member of) @param bskid: basket id @param topic: topic currently displayed @param group_id: id of group to share basket to @param ln: language """ if group_id: db.share_basket_with_group(bskid, group_id, CFG_WEBBASKET_SHARE_LEVELS['READITM']) else: groups = db.get_groups_user_member_of(uid) body = webbasket_templates.tmpl_add_group(bskid, topic, groups, ln) return body def perform_request_create_basket(req, uid, new_basket_name='', new_topic_name='', create_in_topic="-1", topic="-1", recids=[], colid=-1, es_title='', es_desc='', es_url='', ln=CFG_SITE_LANG): """if new_basket_name and topic infos are given create a basket and return topic number, else return body with warnings of basket creation form. @param req: request object for obtaining URL of the referring page @param uid: user id (int) @param new_basket_name: name of the basket to create (str) @param new_topic_name: name of new topic to create new basket in (str) @param create_in_topic: identification number of topic to create new basket in (int) @param topic: topic to preselect on the creation form. @pram ln: language """ warnings = [] warnings_html = "" _ = gettext_set_language(ln) if new_basket_name and (new_topic_name or create_in_topic != "-1"): #topics_infos = map(lambda x: x[0], db.get_personal_topics_infos(uid)) new_topic_name = new_topic_name.strip() if new_topic_name: topic = new_topic_name else: topic = create_in_topic bskid = db.create_basket(uid, new_basket_name, topic) #topics = map(lambda x: x[0], topics_infos) return (bskid, topic) else: referer = get_referer(req) # URL of the referring page url = CFG_SITE_URL + '/yourbaskets/create_basket' import string if string.find(referer, url) == 0: if not new_basket_name: try: raise InvenioWebBasketWarning(_('Please provide a name for the new basket.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning', req=req) warnings.append(exc.message) if (not new_topic_name and create_in_topic == "-1"): try: raise InvenioWebBasketWarning(_('Please select an existing topic or create a new one.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning', req=req) warnings.append(exc.message) topics = map(lambda x: x[0], db.get_personal_topics_infos(uid)) if topic in topics: create_in_topic = topic body = webbasket_templates.tmpl_create_basket(new_basket_name, new_topic_name, create_in_topic, topics, recids, colid, es_title, es_desc, es_url, ln) if warnings: warnings_html += webbasket_templates.tmpl_warnings(warnings, ln) body = warnings_html + body return body def perform_request_subscribe(uid, bskid, ln=CFG_SITE_LANG): """Subscribes user to the given public basket. Returns warnings if there were any.""" _ = gettext_set_language(ln) #warnings = [] warnings_html = "" if db.is_basket_public(bskid): if not db.subscribe(uid, bskid): try: raise InvenioWebBasketWarning(_('You cannot subscribe to this basket, you are the either owner or you have already subscribed.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_CAN_NOT_SUBSCRIBE') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) else: try: raise InvenioWebBasketWarning(_('The selected public basket does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_INVALID_OR_RESTRICTED_PUBLIC_BASKET') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) return warnings_html def perform_request_unsubscribe(uid, bskid, ln=CFG_SITE_LANG): """Unsubscribes user from the given public basket. Returns warnings if there were any.""" _ = gettext_set_language(ln) #warnings = [] warnings_html = "" if db.is_basket_public(bskid): if not db.unsubscribe(uid, bskid): try: raise InvenioWebBasketWarning(_('You cannot unsubscribe from this basket, you are the either owner or you have already unsubscribed.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_CAN_NOT_UNSUBSCRIBE') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) else: try: raise InvenioWebBasketWarning(_('The selected public basket does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') #warnings.append(exc.message) #warnings.append('WRN_WEBBASKET_INVALID_OR_RESTRICTED_PUBLIC_BASKET') warnings_html += webbasket_templates.tmpl_warnings(exc.message, ln) return warnings_html def check_user_can_comment(uid, bskid): """ Private function. check if a user can comment """ min_right = CFG_WEBBASKET_SHARE_LEVELS['ADDCMT'] rights = db.get_max_user_rights_on_basket(uid, bskid) if rights: if CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(rights) >= CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(min_right): return 1 return 0 def __check_user_can_perform_action(uid, bskid, rights): """ Private function, check if a user has sufficient rights""" min_right = rights rights = db.get_max_user_rights_on_basket(uid, bskid) if rights: if CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(rights) >= CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(min_right): return 1 return 0 def check_sufficient_rights(rights_user_has, rights_needed): """Private function, check if the rights are sufficient.""" try: out = CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(rights_user_has) >= \ CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(rights_needed) except ValueError: out = 0 return out def can_add_notes_to_public_basket_p(bskid): """ Private function. Checks if notes can be added to the given public basket.""" min_right = CFG_WEBBASKET_SHARE_LEVELS['ADDCMT'] rights = db.get_rights_on_public_basket(bskid) if rights: if CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(rights[0][0]) >= CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(min_right): return True return False def create_guest_warning_box(ln=CFG_SITE_LANG): """return a warning message about logging into system""" return webbasket_templates.tmpl_create_guest_warning_box(ln) def create_personal_baskets_selection_box(uid, html_select_box_name='baskets', selected_bskid=None, ln=CFG_SITE_LANG): """Return HTML box for basket selection. Only for personal baskets. @param uid: user id @param html_select_box_name: name used in html form @param selected_bskid: basket currently selected @param ln: language """ baskets = db.get_all_personal_baskets_names(uid) return webbasket_templates.tmpl_personal_baskets_selection_box( baskets, html_select_box_name, selected_bskid, ln) def create_basket_navtrail(uid, category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], topic="", group=0, bskid=0, ln=CFG_SITE_LANG): """display navtrail for basket navigation. @param uid: user id (int) @param category: selected category (see CFG_WEBBASKET_CATEGORIES) @param topic: selected topic if personal baskets @param group: selected group id for displaying (int) @param bskid: basket id (int) @param ln: language""" _ = gettext_set_language(ln) out = '' if category == CFG_WEBBASKET_CATEGORIES['PRIVATE']: - out += ' > <a class="navtrail" href="%s/yourbaskets/display?%s">'\ - '%s</a>' - out %= (CFG_SITE_URL, - 'category=' + category + '&ln=' + ln, - _("Personal baskets")) + category_html = """ > <a class="navtrail" href="%s/yourbaskets/display?%s">%s</a>""" % \ + (CFG_SITE_URL, + 'category=' + category + '&ln=' + ln, + _("Personal baskets")) + out += category_html + topics = map(lambda x: x[0], db.get_personal_topics_infos(uid)) if topic in topics: - out += ' > ' - out += '<a class="navtrail" href="%s/yourbaskets/display?%s">'\ - '%s</a>' - out %= (CFG_SITE_URL, - 'category=' + category + '&topic=' + \ - topic + '&ln=' + ln, - cgi.escape(topic)) + topic_html = """ > <a class="navtrail" href="%s/yourbaskets/display?%s">%s</a>""" % \ + (CFG_SITE_URL, + 'category=' + category + '&topic=' + \ + urllib.quote(topic) + '&ln=' + ln, + cgi.escape(topic)) + out += topic_html + if bskid: basket = db.get_public_basket_infos(bskid) if basket: - out += ' > ' - out += '<a class="navtrail" href="%s/yourbaskets/display'\ - '?%s">%s</a>' - out %= (CFG_SITE_URL, - 'category=' + category + '&topic=' + \ - topic + '&ln=' + ln + '#bsk' + str(bskid), - cgi.escape(basket[1])) + basket_html = """ > <a class="navtrail" href="%s/yourbaskets/display?%s">%s</a>""" % \ + (CFG_SITE_URL, + 'category=' + category + '&topic=' + \ + urllib.quote(topic) + '&ln=' + ln + '#bsk' + str(bskid), + cgi.escape(basket[1])) + out += basket_html elif category == CFG_WEBBASKET_CATEGORIES['GROUP']: - out += ' > <a class="navtrail" href="%s/yourbaskets/display?%s">'\ - '%s</a>' - out %= (CFG_SITE_URL, 'category=' + category + '&ln=' + ln, _("Group baskets")) + category_html = """ > <a class="navtrail" href="%s/yourbaskets/display?%s">%s</a>""" % \ + (CFG_SITE_URL, + 'category=' + category + '&ln=' + ln, + _("Group baskets")) + out += category_html + groups = db.get_group_infos(uid) if group: groups = filter(lambda x: x[0] == group, groups) if len(groups): - out += ' > ' - out += '<a class="navtrail" href="%s/yourbaskets/display?%s">%s</a>' - out %= (CFG_SITE_URL, - 'category=' + category + '&group=' + \ - str(group) + '&ln=' + ln, - cgi.escape(groups[0][1])) + group_html = """ > <a class="navtrail" href="%s/yourbaskets/display?%s">%s</a>""" % \ + (CFG_SITE_URL, + 'category=' + category + '&group=' + \ + str(group) + '&ln=' + ln, + cgi.escape(groups[0][1])) + out += group_html + if bskid: basket = db.get_public_basket_infos(bskid) if basket: - out += ' > ' - out += '<a class="navtrail" href="%s/yourbaskets/display?'\ - '%s">%s</a>' - out %= (CFG_SITE_URL, - 'category=' + category + '&group=' + \ - str(group) + '&ln=' + ln + '#bsk' + str(bskid), - cgi.escape(basket[1])) + basket_html = """ > <a class="navtrail" href="%s/yourbaskets/display?%s">%s</a>""" % \ + (CFG_SITE_URL, + 'category=' + category + '&group=' + \ + str(group) + '&ln=' + ln + '#bsk' + str(bskid), + cgi.escape(basket[1])) + out += basket_html + elif category == CFG_WEBBASKET_CATEGORIES['EXTERNAL']: - out += ' > <a class="navtrail" href="%s/yourbaskets/display?%s">'\ - '%s</a>' - out %= (CFG_SITE_URL, - 'category=' + category + '&ln=' + ln, - _("Others' baskets")) + category_html = """ > <a class="navtrail" href="%s/yourbaskets/display?%s">%s</a>""" % \ + (CFG_SITE_URL, + 'category=' + category + '&ln=' + ln, + _("Others' baskets")) + out += category_html if bskid: basket = db.get_public_basket_infos(bskid) if basket: - out += ' > ' - out += '<a class="navtrail" href="%s/yourbaskets/display?%s">'\ - '%s</a>' - out %= (CFG_SITE_URL, - 'category=' + category + '&ln=' + ln + \ - '#bsk' + str(bskid), - cgi.escape(basket[1])) + basket_html = """ > <a class="navtrail" href="%s/yourbaskets/display?%s">""" % \ + (CFG_SITE_URL, + 'category=' + category + '&ln=' + ln + \ + '#bsk' + str(bskid), + cgi.escape(basket[1])) + out += basket_html + return out def create_webbasket_navtrail(uid, category="", topic="", group=0, bskid=0, public_basket=False, search_baskets=False, add_to_basket=False, ln=CFG_SITE_LANG): """Create the navtrail for navigation withing WebBasket. @param uid: user id (int) @param category: selected category (see CFG_WEBBASKET_CATEGORIES) @param topic: selected topic (str) @param group: selected group (int) @param bskid: selected basket id (int) @param ln: language""" _ = gettext_set_language(ln) out = """<a class="navtrail" href="%s/youraccount/display?ln=%s">%s</a>""" % \ (CFG_SITE_URL, ln, _("Your Account")) out += " > " out += """<a class="navtrail" href="%s/yourbaskets/display?ln=%s">%s</a>""" % \ (CFG_SITE_URL, ln, _("Your Baskets")) if public_basket: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/list_public_baskets?ln=%s">%s</a>""" % \ (CFG_SITE_URL, ln, _("List of public baskets")) if bskid: basket = db.get_basket_name(bskid) if basket: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/display_public?bskid=%i&ln=%s">%s</a>""" % \ - (CFG_SITE_URL, bskid, ln, cgi.escape(basket)) + (CFG_SITE_URL, bskid, ln, cgi.escape(basket, True)) elif search_baskets: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/search?ln=%s">%s</a>""" % \ (CFG_SITE_URL, ln, _("Search baskets")) elif add_to_basket: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/add?ln=%s">%s</a>""" % \ (CFG_SITE_URL, ln, _("Add to basket")) else: if category == CFG_WEBBASKET_CATEGORIES['PRIVATE']: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/display?category=%s&ln=%s">%s</a>""" % \ (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['PRIVATE'], ln, _("Personal baskets")) if topic: topic_names = map(lambda x: x[0], db.get_personal_topics_infos(uid)) if topic in topic_names: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/display?category=%s&topic=%s&ln=%s">%s</a>""" % \ - (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['PRIVATE'], cgi.escape(topic), ln, cgi.escape(topic)) + (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['PRIVATE'], urllib.quote(topic), ln, cgi.escape(topic, True)) if bskid: basket = db.get_basket_name(bskid) if basket: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/display?category=%s&topic=%s&bskid=%i&ln=%s">%s</a>""" % \ - (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['PRIVATE'], cgi.escape(topic), bskid, ln, cgi.escape(basket)) + (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['PRIVATE'], urllib.quote(topic), bskid, ln, cgi.escape(basket, True)) elif category == CFG_WEBBASKET_CATEGORIES['GROUP']: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/display?category=%s&ln=%s">%s</a>""" % \ (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['GROUP'], ln, _("Group baskets")) if group: group_names = map(lambda x: x[0] == group and x[1], db.get_group_infos(uid)) if group_names and group_names[0]: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/display?category=%s&group=%i&ln=%s">%s</a>""" % \ - (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['GROUP'], group, ln, cgi.escape(group_names[0])) + (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['GROUP'], group, ln, cgi.escape(group_names[0], True)) if bskid: basket = db.get_basket_name(bskid) if basket: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/display?category=%s&topic=%s&bskid=%i&ln=%s">%s</a>""" % \ - (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['GROUP'], group, bskid, ln, cgi.escape(basket)) + (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['GROUP'], group, bskid, ln, cgi.escape(basket, True)) elif category == CFG_WEBBASKET_CATEGORIES['EXTERNAL']: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/display?category=%s&ln=%s">%s</a>""" % \ (CFG_SITE_URL, category, ln, _("Public baskets")) if bskid: basket = db.get_basket_name(bskid) if basket: out += " > " out += """<a class="navtrail" href="%s/yourbaskets/display?category=%s&topic=%s&bskid=%i&ln=%s">%s</a>""" % \ - (CFG_SITE_URL, category, group, bskid, ln, cgi.escape(basket)) + (CFG_SITE_URL, category, group, bskid, ln, cgi.escape(basket, True)) return out def account_list_baskets(uid, ln=CFG_SITE_LANG): """Display baskets informations on account page""" _ = gettext_set_language(ln) (personal, group, external) = db.count_baskets(uid) link = '<a href="%s">%s</a>' base_url = CFG_SITE_URL + '/yourbaskets/display?category=%s&ln=' + ln personal_text = personal if personal: url = base_url % CFG_WEBBASKET_CATEGORIES['PRIVATE'] personal_text = link % (url, personal_text) group_text = group if group: url = base_url % CFG_WEBBASKET_CATEGORIES['GROUP'] group_text = link % (url, group_text) external_text = external if external: url = base_url % CFG_WEBBASKET_CATEGORIES['EXTERNAL'] else: url = CFG_SITE_URL + '/yourbaskets/list_public_baskets?ln=' + ln external_text = link % (url, external_text) out = _("You have %(x_nb_perso)s personal baskets and are subscribed to %(x_nb_group)s group baskets and %(x_nb_public)s other users public baskets.") %\ {'x_nb_perso': personal_text, 'x_nb_group': group_text, 'x_nb_public': external_text} return out def page_start(req, of='xm'): """Set the content type and send the headers for the page.""" if of.startswith('x'): req.content_type = "text/xml" if of == 'xr': req.content_type = "application/rss+xml" req.send_http_header() req.write("""<?xml version="1.0" encoding="UTF-8"?>\n""") print_records_prologue(req, of) else: # assuming HTML by default req.content_type = "text/html" req.send_http_header() def page_end(req, of='xm'): """Print page footer""" if of.startswith('x'): print_records_epilogue(req, of) def perform_request_export_xml(body): """Export an xml representation of the selected baskets/items.""" return webbasket_templates.tmpl_export_xml(body) ################################ ### External items functions ### ################################ def format_external_records(recids, of='hb'): """Given a list of external records' recids, this function returns a list of tuples with each recid and the actual formatted record using the selected output format. It also stores the formatted record in the database for future use.""" # TODO: add a returnp variable to control whether we actually want anything # to be returned or not. For example when we just want to store the xml # formatted records for newly added items. # TODO: take care of external urls. Invent an xml format for them. # NOTE: this function is meant to format external records from other # libraries. It's not meant to handle custom external sources like urls # submitted manually by the user. These items are directly formatted and # stored by the add_to_basket database function. formatted_records = [] if type(recids) is not list: recids = [recids] existing_xml_formatted_records = db.get_external_records(recids, "xm") for existing_xml_formatted_record in existing_xml_formatted_records: xml_record = decompress(existing_xml_formatted_record[2]) xml_record_id = existing_xml_formatted_record[1] xml_record_colid = existing_xml_formatted_record[0] recids.remove(-xml_record_id) if of == "hb": if xml_record_colid > 0: htmlbrief_record = format_record(None, of, xml_record=xml_record) formatted_records.append((xml_record_id, htmlbrief_record)) elif of != "hb": #formatted_records.append((xml_record_id, xml_record)) formatted_records.append((xml_record_id, format_record([], of, xml_record=xml_record, on_the_fly=True))) # formatted_records.append((xml_record_id, repr(xml_record))) if formatted_records and of == "hb": db.store_external_records(formatted_records, of) records_grouped_by_collection = db.get_external_records_by_collection(recids) if records_grouped_by_collection: for records in records_grouped_by_collection: colid = records[2] if colid: external_records = fetch_and_store_external_records(records, of) formatted_records.extend(external_records) return formatted_records def fetch_and_store_external_records(records, of="hb"): """Function that fetches the formatted records for one collection and stores them into the database. It also calculates and stores the original external url for each record.""" results = [] formatted_records = [] if of == 'xm': re_controlfield = re.compile(r'<controlfield\b[^>]*>.*?</controlfield>', re.DOTALL + re.MULTILINE + re.IGNORECASE) re_blankline = re.compile(r'\s*\n', re.DOTALL + re.MULTILINE + re.IGNORECASE) # the locally saved external ids local_ext_ids = records[0].split(",") # the locally saved original external ids external_ids = records[1].split(",") collection_name = get_collection_name_by_id(records[2]) collection_engine_set = select_hosted_search_engines(collection_name) collection_engine = collection_engine_set.pop() external_ids_urls = collection_engine.build_record_urls(external_ids) external_urls = [external_id_url[1] for external_id_url in external_ids_urls] #external_urls_dict = {} #for (local_id, url) in zip(local_ext_ids, external_urls): #external_urls_dict[local_id] = url #db.store_external_urls(external_urls_dict) db.store_external_urls(zip(local_ext_ids, external_urls)) url = collection_engine.build_search_url(None, req_args=external_ids) pagegetters = [HTTPAsyncPageGetter(url)] def finished(pagegetter, dummy_data, dummy_time): """Function to be called when a page has been downloaded.""" results.append(pagegetter) finished_list = async_download(pagegetters, finish_function=finished, timeout=CFG_EXTERNAL_COLLECTION_TIMEOUT) if finished_list[0]: collection_engine.parser.parse_and_get_results(results[0].data, feedonly=True) (dummy, parsed_results_dict) = collection_engine.parser.parse_and_extract_records(of=of) for (local_ext_id, external_id) in zip(local_ext_ids, external_ids): formatted_record = parsed_results_dict[external_id] if of == 'xm': formatted_record = re_controlfield.sub('', formatted_record) formatted_record = re_blankline.sub('\n', formatted_record) formatted_records.append((int(local_ext_id), formatted_record)) db.store_external_records(formatted_records, of) else: for (local_ext_id, external_id) in zip(local_ext_ids, external_ids): formatted_records.append((int(local_ext_id), "There was a timeout when fetching the record.")) return formatted_records ############################### ### Miscellaneous functions ### ############################### def url_is_valid(url): """Returns (True, status, reason) if the url is valid or (False, status, reason) if different.""" common_errors_list = [400, 404, 500] url_tuple = urlsplit(url) if not url_tuple[0]: url = "http://" + url url_tuple = urlsplit(url) if not url_tuple[0] and not url_tuple[1]: return (False, 000, "Not Valid") # HTTPConnection had the timeout parameter introduced in python 2.6 # for the older versions we have to get and set the default timeout # In order to use a custom timeout pass it as an extra argument to this function #old_timeout = getdefaulttimeout() #setdefaulttimeout(timeout) conn = HTTPConnection(url_tuple[1]) #setdefaulttimeout(old_timeout) try: conn.request("GET", url_tuple[2]) except: return (False, 000, "Not Valid") response = conn.getresponse() status = response.status reason = response.reason if str(status).startswith('1') or str(status).startswith('2') or str(status).startswith('3'): return (True, status, reason) elif str(status).startswith('4') or str(status).startswith('5'): if status in common_errors_list: return (False, status, reason) else: return (True, status, reason) def nl2br(text): """Replace newlines (\n) found in text with line breaks (<br />).""" return '<br />'.join(text.split('\n')) def wash_b_search(b): """Wash the b GET variable for the search interface.""" _ = gettext_set_language(CFG_SITE_LANG) b = b.split('_', 1) b_category = b[0].upper() valid_categories = CFG_WEBBASKET_CATEGORIES.values() valid_categories.append('') if b_category not in valid_categories: try: raise InvenioWebBasketWarning(_('The category you have selected does not exist. Please select a valid category.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') return ("", "", exc.message) #return ("", "", ['WRN_WEBBASKET_INVALID_CATEGORY']) if len(b) == 2: if b_category == CFG_WEBBASKET_CATEGORIES['PRIVATE'] or b_category == CFG_WEBBASKET_CATEGORIES['GROUP']: return (b_category, b[1], None) # TODO: send a warning when the user has sent a second argument # specifying a category other than PRIVATE or GROUP #else: #return (b_category, "", ['WRN_WEBBASKET_']) return (b_category, "", None) def wash_b_add(b): """Wash the b POST variable for the add interface.""" _ = gettext_set_language(CFG_SITE_LANG) b = b.split('_', 1) b_category = b[0].upper() valid_categories = (CFG_WEBBASKET_CATEGORIES['PRIVATE'], CFG_WEBBASKET_CATEGORIES['GROUP']) if b_category not in valid_categories or len(b) != 2 or not b[1]: try: raise InvenioWebBasketWarning(_('Cannot add items to the selected basket. Invalid parameters.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') return ("", "", exc.message) return (b_category, b[1], None) def wash_category(category): """Wash the category.""" _ = gettext_set_language(CFG_SITE_LANG) category = category.upper() valid_categories = CFG_WEBBASKET_CATEGORIES.values() valid_categories.append('') if category not in valid_categories: try: raise InvenioWebBasketWarning(_('The category you have selected does not exist. Please select a valid category.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') return ("", "", exc.message) #return ("", ['WRN_WEBBASKET_INVALID_CATEGORY']) return (category, None) def wash_topic(uid, topic): """Wash the topic.""" _ = gettext_set_language(CFG_SITE_LANG) if not db.is_topic_valid(uid, topic): try: raise InvenioWebBasketWarning(_('The selected topic does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') return ("", "", exc.message) #return ("", ['WRN_WEBBASKET_INVALID_OR_RESTRICTED_TOPIC']) return (topic, None) def wash_group(uid, group): """Wash the topic.""" _ = gettext_set_language(ln=CFG_SITE_LANG) if not group.isdigit() or not db.is_group_valid(uid, group): try: raise InvenioWebBasketWarning(_('The selected group does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') return (0, exc.message) #return (0, ['WRN_WEBBASKET_INVALID_OR_RESTRICTED_GROUP']) return (int(group), None) def wash_bskid(uid, category, bskid): """Wash the bskid based on its category. This function expectes a washed category, either for personal or for group baskets.""" _ = gettext_set_language(CFG_SITE_LANG) if not bskid.isdigit(): try: raise InvenioWebBasketWarning(_('The selected basket does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') return (0, exc.message) #return (0, ['WRN_WEBBASKET_INVALID_OR_RESTRICTED_BASKET']) bskid = int(bskid) if category == CFG_WEBBASKET_CATEGORIES['PRIVATE'] and not db.is_personal_basket_valid(uid, bskid): try: raise InvenioWebBasketWarning(_('The selected basket does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') return (0, exc.message) #return (0, ['WRN_WEBBASKET_INVALID_OR_RESTRICTED_BASKET']) if category == CFG_WEBBASKET_CATEGORIES['GROUP'] and not db.is_group_basket_valid(uid, bskid): try: raise InvenioWebBasketWarning(_('The selected basket does not exist or you do not have access to it.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') return (0, exc.message) #return (0, ['WRN_WEBBASKET_INVALID_OR_RESTRICTED_BASKET']) return (bskid, None) def wash_of(of): """Wash the output format""" _ = gettext_set_language(CFG_SITE_LANG) list_of_accepted_formats = ['hb', 'xm', 'hx', 'xd', 'xe', 'xn', 'xw', 'xr', 'xp'] if of in list_of_accepted_formats: return (of, None) try: raise InvenioWebBasketWarning(_('The selected output format is not available or is invalid.')) except InvenioWebBasketWarning, exc: register_exception(stream='warning') return ('hb', exc.message) def __create_search_box(uid, category="", topic="", grpid=0, p="", n=0, ln=CFG_SITE_LANG): """Private function. Creates the search box and returns html code.""" topic_list = db.get_all_user_topics(uid) group_list = db.get_all_user_groups(uid) number_of_public_baskets = db.count_external_baskets(uid) search_box = webbasket_templates.tmpl_create_search_box(category, topic, grpid, topic_list, group_list, number_of_public_baskets, p, n, ln=ln) return search_box diff --git a/modules/webbasket/lib/webbasket_config.py b/modules/webbasket/lib/webbasket_config.py index 341d0524f..01b5dd684 100644 --- a/modules/webbasket/lib/webbasket_config.py +++ b/modules/webbasket/lib/webbasket_config.py @@ -1,71 +1,74 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 CERN. ## ## Invenio 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. ## ## Invenio 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """WebBasket configuration parameters.""" __revision__ = "$Id$" CFG_WEBBASKET_SHARE_LEVELS = {'READITM': 'RI', 'READCMT': 'RC', 'ADDCMT': 'AC', 'ADDITM': 'AI', 'DELCMT': 'DC', 'DELITM': 'DI', 'MANAGE': 'MA'} CFG_WEBBASKET_SHARE_LEVELS_ORDERED = [CFG_WEBBASKET_SHARE_LEVELS['READITM'], CFG_WEBBASKET_SHARE_LEVELS['READCMT'], CFG_WEBBASKET_SHARE_LEVELS['ADDCMT'], CFG_WEBBASKET_SHARE_LEVELS['ADDITM'], CFG_WEBBASKET_SHARE_LEVELS['DELCMT'], CFG_WEBBASKET_SHARE_LEVELS['DELITM'], CFG_WEBBASKET_SHARE_LEVELS['MANAGE']] +# Keep in mind that the underscore ('_') is a special character. In case you +# want to define new categories, don't use the underscore ('_') anywhere in the +# value! You may use it in the key if you wish. CFG_WEBBASKET_CATEGORIES = {'PRIVATE': 'P', 'GROUP': 'G', 'EXTERNAL': 'E', 'ALLPUBLIC': 'A'} CFG_WEBBASKET_ACTIONS = {'DELETE': 'delete', 'UP': 'moveup', 'DOWN': 'movedown', 'COPY': 'copy'} # Specify how many levels of indentation discussions can be. This can # be used to ensure that discussions will not go into deep levels of # nesting if users don't understand the difference between "reply to # comment" and "add comment". When the depth is reached, any "reply to # comment" is conceptually converted to a "reply to thread" # (i.e. reply to this parent's comment). Use -1 for no limit, 0 for # unthreaded (flat) discussions. CFG_WEBBASKET_MAX_COMMENT_THREAD_DEPTH = 1 CFG_WEBBASKET_DIRECTORY_BOX_NUMBER_OF_COLUMNS = 3 CFG_WEBBASKET_MAX_NUMBER_OF_NOTES = 100 # Exceptions: warnings class InvenioWebBasketWarning(Exception): """A generic warning for WebBasket.""" def __init__(self, message): """Initialisation.""" self.message = message def __str__(self): """String representation.""" return repr(self.message) diff --git a/modules/webbasket/lib/webbasket_dblayer.py b/modules/webbasket/lib/webbasket_dblayer.py index 92aa90b82..a33784213 100644 --- a/modules/webbasket/lib/webbasket_dblayer.py +++ b/modules/webbasket/lib/webbasket_dblayer.py @@ -1,2385 +1,2371 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 CERN. ## ## Invenio 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. ## ## Invenio 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """ Database related functions for webbasket module """ __revision__ = "$Id$" from zlib import decompress from zlib import compress from time import localtime from invenio.textutils import encode_for_xml from invenio.dbquery import run_sql from invenio.webcomment import get_reply_order_cache_data from invenio.webbasket_config import CFG_WEBBASKET_SHARE_LEVELS, \ CFG_WEBBASKET_ACTIONS, \ CFG_WEBBASKET_SHARE_LEVELS_ORDERED, \ CFG_WEBBASKET_MAX_COMMENT_THREAD_DEPTH from invenio.config import CFG_SITE_URL from invenio.dateutils import convert_datestruct_to_datetext from invenio.websession_config import CFG_WEBSESSION_USERGROUP_STATUS from invenio.search_engine import get_fieldvalues ########################### Table of contents ################################ # # NB. functions preceeded by a star use usergroup table # # 1. General functions # - count_baskets # - check_user_owns_basket # - get_max_user_rights_on_basket # # 2. Personal baskets # - get_personal_baskets_info_for_topic # - get_all_personal_basket_ids_and_names_by_topic # - get_all_personal_baskets_names # - get_basket_name # - is_personal_basket_valid # - is_topic_valid # - get_basket_topic # - get_personal_topics_infos # - rename_basket # - rename_topic # - move_baskets_to_topic # - delete_basket # - create_basket # # 3. Actions on baskets # - get_basket_record # - get_basket_content # - get_basket_item # - get_basket_item_title_and_URL # - share_basket_with_group # - update_rights # - move_item # - delete_item # - add_to_basket # - get_external_records_by_collection # - store_external_records # - store_external_urls # - store_external_source # - get_external_colid_and_url # # 4. Group baskets # - get_group_basket_infos # - get_group_name # - get_all_group_basket_ids_and_names_by_group # - (*) get_all_group_baskets_names # - is_shared_to # # 5. External baskets (baskets user has subscribed to) # - get_external_baskets_infos # - get_external_basket_info # - get_all_external_basket_ids_and_names # - count_external_baskets # - get_all_external_baskets_names # # 6. Public baskets (interface to subscribe to baskets) # - get_public_basket_infos # - get_public_basket_info # - get_basket_general_infos # - get_basket_owner_id # - count_public_baskets # - get_public_baskets_list # - is_basket_public # - subscribe # - unsubscribe # - is_user_subscribed_to_basket # - count_subscribers # - (*) get_groups_subscribing_to_basket # - get_rights_on_public_basket # # 7. Annotating # - get_notes # - get_note # - save_note # - delete_note # - note_belongs_to_item_in_basket_p # # 8. Usergroup functions # - (*) get_group_infos # - count_groups_user_member_of # - (*) get_groups_user_member_of # # 9. auxilliary functions # - __wash_sql_count # - __decompress_last # - create_pseudo_record # - prettify_url ########################## General functions ################################## def count_baskets(uid): """Return (nb personal baskets, nb group baskets, nb external baskets) tuple for given user""" query1 = "SELECT COUNT(id) FROM bskBASKET WHERE id_owner=%s" res1 = run_sql(query1, (int(uid),)) personal = __wash_sql_count(res1) query2 = """SELECT count(ugbsk.id_bskbasket) FROM usergroup_bskBASKET ugbsk LEFT JOIN user_usergroup uug ON ugbsk.id_usergroup=uug.id_usergroup WHERE uug.id_user=%s AND uug.user_status!=%s GROUP BY ugbsk.id_usergroup""" params = (int(uid), CFG_WEBSESSION_USERGROUP_STATUS['PENDING']) res2 = run_sql(query2, params) if len(res2): groups = reduce(lambda x, y: x + y, map(lambda x: x[0], res2)) else: groups = 0 external = count_external_baskets(uid) return (personal, groups, external) def check_user_owns_baskets(uid, bskids): """ Return 1 if user is owner of every basket in list bskids""" if not((type(bskids) is list) or (type(bskids) is tuple)): bskids = [bskids] query = """SELECT id_owner FROM bskBASKET WHERE %s GROUP BY id_owner""" sep = ' OR ' query %= sep.join(['id=%s'] * len(bskids)) res = run_sql(query, tuple(bskids)) if len(res)==1 and int(res[0][0])==uid: return 1 else: return 0 def get_max_user_rights_on_basket(uid, bskid): """Return the max rights a user has on this basket""" query_owner = "SELECT count(id_owner) FROM bskBASKET WHERE id_owner=%s and id=%s" params_owner = (int(uid), int(bskid)) res = run_sql(query_owner, params_owner) if res and res[0][0]: # if this user is owner of this baskets he can do anything he wants. return CFG_WEBBASKET_SHARE_LEVELS['MANAGE'] # not owner => group member ? query_group_baskets = """ SELECT share_level FROM user_usergroup AS ug LEFT JOIN usergroup_bskBASKET AS ub ON ug.id_usergroup=ub.id_usergroup WHERE ug.id_user=%s AND ub.id_bskBASKET=%s AND NOT(ub.share_level='NO') AND ug.user_status!=%s """ params_group_baskets = (int(uid), int(bskid), CFG_WEBSESSION_USERGROUP_STATUS['PENDING']) res = run_sql(query_group_baskets, params_group_baskets) group_index = None if res: try: group_index = CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(res[0][0]) except: return None # public basket ? query_public_baskets = """ SELECT share_level FROM usergroup_bskBASKET WHERE id_usergroup=0 AND id_bskBASKET=%s """ public_index = None res = run_sql(query_public_baskets, (int(bskid),)) if res: try: public_index = CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(res[0][0]) except: return None if group_index or public_index: if group_index > public_index: return CFG_WEBBASKET_SHARE_LEVELS_ORDERED[group_index] else: return CFG_WEBBASKET_SHARE_LEVELS_ORDERED[public_index] return None ########################### Personal baskets ################################## def get_personal_baskets_info_for_topic(uid, topic): """Return information about every basket that belongs to the given user and topic.""" query = """ SELECT bsk.id, bsk.name, DATE_FORMAT(bsk.date_modification, '%%Y-%%m-%%d %%H:%%i:%%s'), bsk.nb_views, count(rec.id_bibrec_or_bskEXTREC), DATE_FORMAT(max(rec.date_added), '%%Y-%%m-%%d %%H:%%i:%%s') FROM user_bskBASKET AS ubsk JOIN bskBASKET AS bsk ON bsk.id=ubsk.id_bskBASKET AND bsk.id_owner=%s LEFT JOIN bskREC AS rec ON rec.id_bskBASKET=bsk.id WHERE ubsk.id_user=%s AND ubsk.topic=%s GROUP BY bsk.id ORDER BY bsk.name""" params = (uid, uid, topic) res = run_sql(query, params) return res -def get_all_personal_basket_ids_and_names_by_topic(uid): - """For a given user return all their personal baskets - (in tuples: (id, name)) grouped by topic. Note that the - basket tuples have to evaluated to be converted to actual - tuples.""" +def get_all_user_personal_basket_ids_by_topic(uid): + """For a given user return all their personal basket ids grouped by topic.""" query = """ SELECT ubsk.topic, - count(bsk.id), - GROUP_CONCAT('(', bsk.id, ', \"', bsk.name, '\")' - ORDER BY bsk.name) - FROM user_bskBASKET AS ubsk - JOIN bskBASKET AS bsk - ON ubsk.id_bskBASKET=bsk.id - AND ubsk.id_user=bsk.id_owner - WHERE bsk.id_owner=%s - GROUP BY ubsk.topic - ORDER BY ubsk.topic""" - params = (uid,) - res = run_sql(query, params) - - return res - -def get_all_personal_basket_ids_and_names_by_topic_for_add_to_list(uid): - """For a given user return all their personal baskets - (in tuples: (id, name)) grouped by topic. Note that the - basket tuples have to evaluated to be converted to actual - tuples.""" - - query = """ SELECT ubsk.topic, - GROUP_CONCAT('(', bsk.id, ', \"', bsk.name, '\")' - ORDER BY bsk.name) + GROUP_CONCAT(bsk.id) FROM user_bskBASKET AS ubsk JOIN bskBASKET AS bsk ON ubsk.id_bskBASKET=bsk.id AND ubsk.id_user=bsk.id_owner WHERE bsk.id_owner=%s GROUP BY ubsk.topic ORDER BY ubsk.topic""" params = (uid,) res = run_sql(query, params) return res def get_all_personal_baskets_names(uid): """ for a given user, returns every basket he is owner of returns list of tuples: (bskid, bsk_name, topic) """ query = """ SELECT bsk.id, bsk.name, ubsk.topic FROM user_bskBASKET ubsk JOIN bskBASKET bsk ON ubsk.id_bskBASKET=bsk.id AND ubsk.id_user=bsk.id_owner WHERE bsk.id_owner=%s ORDER BY ubsk.topic """ params = (int(uid),) return run_sql(query, params) def get_basket_name(bskid): """return the name of a given basket""" query = 'SELECT name FROM bskBASKET where id=%s' res = run_sql(query, (int(bskid), )) if res: return res[0][0] else: return '' def is_personal_basket_valid(uid, bskid): """Check if the basked (bskid) belongs to user (uid) and is valid.""" query = """ SELECT id FROM bskBASKET WHERE id=%s AND id_owner=%s""" params = (bskid, uid) res = run_sql(query, params) return res def is_topic_valid(uid, topic): """Check if the topic defined by user (uid) exists.""" query = """ SELECT distinct(topic) FROM user_bskBASKET WHERE topic=%s AND id_user=%s""" params = (topic, uid) res = run_sql(query, params) return res def get_basket_topic(uid, bskid): """Return the name of the topic this basket (bskid) belongs to.""" query = """ SELECT topic FROM user_bskBASKET WHERE id_bskBASKET=%s AND id_user=%s""" params = (bskid,uid) res = run_sql(query, params) return res def get_personal_topics_infos(uid): """ Get the list of every topic user has defined, and the number of baskets in each topic @param uid: user id (int) @return: a list of tuples (topic name, nb of baskets) """ query = """SELECT topic, count(b.id) FROM user_bskBASKET ub JOIN bskBASKET b ON ub.id_bskBASKET=b.id AND b.id_owner=ub.id_user WHERE ub.id_user=%s GROUP BY topic ORDER BY topic""" uid = int(uid) res = run_sql(query, (uid,)) return res +def get_basket_ids_and_names(bskids, limit=0): + """For the given basket ids, return their ids and names, + ordered by basket name. + If 'limit' is greater than 0, limit the number of results returned.""" + + if not((type(bskids) is list) or (type(bskids) is tuple)): + bskids = [bskids] + + query = """ SELECT bsk.id, + bsk.name + FROM bskBASKET AS bsk + WHERE %s + ORDER BY bsk.name + %s""" + sep = ' OR ' + query %= (sep.join(['id=%s'] * len(bskids)), limit and 'LIMIT %i' % limit or '') + + params = tuple(bskids) + + res = run_sql(query, params) + + return res + def rename_basket(bskid, new_name): """Rename basket to new_name""" run_sql("UPDATE bskBASKET SET name=%s WHERE id=%s", (new_name, bskid)) def rename_topic(uid, old_topic, new_topic): """Rename topic to new_topic """ res = run_sql("UPDATE user_bskBASKET SET topic=%s WHERE id_user=%s AND topic=%s", (new_topic, uid, old_topic)) return res def move_baskets_to_topic(uid, bskids, new_topic): """Move given baskets to another topic""" if not((type(bskids) is list) or (type(bskids) is tuple)): bskids = [bskids] query = "UPDATE user_bskBASKET SET topic=%s WHERE id_user=%s AND (" query += ' OR '.join(['id_bskBASKET=%s'] * len(bskids)) query += ")" params = (new_topic, uid) + tuple(bskids) res = run_sql(query, params) return res def delete_basket(bskid): """Delete given basket.""" # TODO: check if any alerts are automaticly adding items to the given basket. bskid = int(bskid) query1 = "DELETE FROM bskBASKET WHERE id=%s" res = run_sql(query1, (bskid,)) query2A = "SELECT id_bibrec_or_bskEXTREC FROM bskREC WHERE id_bskBASKET=%s" local_and_external_ids = run_sql(query2A, (bskid,)) external_ids = [local_and_external_id[0] for local_and_external_id in \ local_and_external_ids if local_and_external_id[0]<0] for external_id in external_ids: delete_item(bskid=bskid, recid=external_id, update_date_modification=False) query2B = "DELETE FROM bskREC WHERE id_bskBASKET=%s" run_sql(query2B, (bskid,)) query3 = "DELETE FROM bskRECORDCOMMENT WHERE id_bskBASKET=%s" run_sql(query3, (bskid,)) query4 = "DELETE FROM user_bskBASKET WHERE id_bskBASKET=%s" run_sql(query4, (bskid,)) query5 = "DELETE FROM usergroup_bskBASKET WHERE id_bskBASKET=%s" run_sql(query5, (bskid,)) query6 = "DELETE FROM user_query_basket WHERE id_basket=%s" run_sql(query6, (bskid,)) return int(res) def create_basket(uid, basket_name, topic): """Create new basket for given user in given topic""" now = convert_datestruct_to_datetext(localtime()) id_bsk = run_sql("""INSERT INTO bskBASKET (id_owner, name, date_modification) VALUES (%s, %s, %s)""", (uid, basket_name, now)) run_sql("""INSERT INTO user_bskBASKET (id_user, id_bskBASKET, topic) VALUES (%s, %s, %s)""", (uid, id_bsk, topic)) return id_bsk def get_all_items_in_user_personal_baskets(uid, topic="", format='hb'): """For the specified user, return all the items in their personal baskets, grouped by basket if local or as a list if external. If topic is set, return only that topic's items.""" if topic: topic_clause = """AND ubsk.topic=%s""" params_local = (uid, uid, topic) params_external = (uid, uid, topic, format) else: topic_clause = "" params_local = (uid, uid) params_external = (uid, uid, format) query_local = """ SELECT rec.id_bskBASKET, bsk.name, ubsk.topic, GROUP_CONCAT(rec.id_bibrec_or_bskEXTREC) FROM bskREC AS rec JOIN bskBASKET AS bsk ON bsk.id=rec.id_bskBASKET AND bsk.id_owner=%%s JOIN user_bskBASKET AS ubsk ON ubsk.id_bskBASKET=rec.id_bskBASKET AND ubsk.id_user=%%s %s WHERE rec.id_bibrec_or_bskEXTREC > 0 GROUP BY rec.id_bskBASKET""" % (topic_clause,) res_local = run_sql(query_local, params_local) query_external = """ SELECT rec.id_bskBASKET, bsk.name, ubsk.topic, rec.id_bibrec_or_bskEXTREC, ext.value FROM bskREC AS rec JOIN bskBASKET AS bsk ON bsk.id=rec.id_bskBASKET AND bsk.id_owner=%%s JOIN user_bskBASKET AS ubsk ON ubsk.id_bskBASKET=rec.id_bskBASKET AND ubsk.id_user=%%s %s JOIN bskEXTFMT AS ext ON ext.id_bskEXTREC=-rec.id_bibrec_or_bskEXTREC AND ext.format=%%s WHERE rec.id_bibrec_or_bskEXTREC < 0 ORDER BY rec.id_bskBASKET""" % (topic_clause,) res_external = run_sql(query_external, params_external) return (res_local, res_external) def get_all_items_in_user_personal_baskets_by_matching_notes(uid, topic="", p=""): """For the specified user, return all the items in their personal baskets matching their notes' titles and bodies, grouped by basket. If topic is set, return only that topic's items.""" p = p and '%' + p + '%' or '%' if topic: topic_clause = """AND ubsk.topic=%s""" params = (uid, uid, topic, p, p) else: topic_clause = "" params = (uid, uid, p, p) query = """ SELECT notes.id_bskBASKET, bsk.name, ubsk.topic, GROUP_CONCAT(DISTINCT(notes.id_bibrec_or_bskEXTREC)) FROM bskRECORDCOMMENT AS notes JOIN bskBASKET AS bsk ON bsk.id=notes.id_bskBASKET AND bsk.id_owner=%%s JOIN user_bskBASKET AS ubsk ON ubsk.id_bskBASKET=notes.id_bskBASKET AND ubsk.id_user=%%s %s WHERE notes.title like %%s OR notes.body like %%s GROUP BY notes.id_bskBASKET""" % (topic_clause,) res = run_sql(query, params) return res def get_all_user_topics(uid): """Return a list of the user's topics.""" query = """ SELECT ubsk.topic FROM bskBASKET AS bsk JOIN user_bskBASKET AS ubsk ON ubsk.id_bskBASKET=bsk.id AND ubsk.id_user=bsk.id_owner WHERE bsk.id_owner=%s GROUP BY ubsk.topic""" params = (uid,) res = run_sql(query, params) return res ########################## Actions on baskets ################################# def get_basket_record(bskid, recid, format='hb'): """get record recid in basket bskid """ if recid < 0: rec_table = 'bskEXTREC' format_table = 'bskEXTFMT' id_field = 'id_bskEXTREC' sign = '-' else: rec_table = 'bibrec' format_table = 'bibfmt' id_field = 'id_bibrec' sign = '' query = """ SELECT DATE_FORMAT(record.creation_date, '%%%%Y-%%%%m-%%%%d %%%%H:%%%%i:%%%%s'), DATE_FORMAT(record.modification_date, '%%%%Y-%%%%m-%%%%d %%%%H:%%%%i:%%%%s'), DATE_FORMAT(bskREC.date_added, '%%%%Y-%%%%m-%%%%d %%%%H:%%%%i:%%%%s'), user.nickname, count(cmt.id_bibrec_or_bskEXTREC), DATE_FORMAT(max(cmt.date_creation), '%%%%Y-%%%%m-%%%%d %%%%H:%%%%i:%%%%s'), fmt.value FROM bskREC LEFT JOIN user ON bskREC.id_user_who_added_item=user.id LEFT JOIN bskRECORDCOMMENT cmt ON bskREC.id_bibrec_or_bskEXTREC=cmt.id_bibrec_or_bskEXTREC LEFT JOIN %(rec_table)s record ON (%(sign)sbskREC.id_bibrec_or_bskEXTREC=record.id) LEFT JOIN %(format_table)s fmt ON (record.id=fmt.%(id_field)s) WHERE bskREC.id_bskBASKET=%%s AND bskREC.id_bibrec_or_bskEXTREC=%%s AND fmt.format=%%s GROUP BY bskREC.id_bibrec_or_bskEXTREC """ % {'rec_table': rec_table, 'sign': sign, 'format_table': format_table, 'id_field':id_field} params = (int(bskid), int(recid), format) res = run_sql(query, params) if res: return __decompress_last(res[0]) return () def get_basket_content(bskid, format='hb'): """Get all records for a given basket.""" query = """ SELECT rec.id_bibrec_or_bskEXTREC, extrec.collection_id, count(cmt.id_bibrec_or_bskEXTREC), DATE_FORMAT(max(cmt.date_creation), '%%Y-%%m-%%d %%H:%%i:%%s'), extern.value as ext_val, intern.value as int_val, rec.score FROM bskREC AS rec LEFT JOIN bskRECORDCOMMENT AS cmt ON (rec.id_bibrec_or_bskEXTREC=cmt.id_bibrec_or_bskEXTREC AND rec.id_bskBASKET=cmt.id_bskBASKET) LEFT JOIN bskEXTFMT AS extern ON (-rec.id_bibrec_or_bskEXTREC=extern.id_bskEXTREC AND extern.format=%s) LEFT JOIN bibfmt AS intern ON (rec.id_bibrec_or_bskEXTREC=intern.id_bibrec AND intern.format=%s) LEFT JOIN bskEXTREC AS extrec ON extrec.id=-rec.id_bibrec_or_bskEXTREC WHERE rec.id_bskBASKET=%s GROUP BY rec.id_bibrec_or_bskEXTREC ORDER BY rec.score""" params = (format, format, int(bskid)) res = run_sql(query, params) if res: query2 = "UPDATE bskBASKET SET nb_views=nb_views+1 WHERE id=%s" run_sql(query2, (int(bskid),)) return res return () def get_basket_item(bskid, recid, format='hb'): """Get item (recid) for a given basket.""" query = """ SELECT rec.id_bibrec_or_bskEXTREC, extrec.collection_id, count(cmt.id_bibrec_or_bskEXTREC), DATE_FORMAT(max(cmt.date_creation), '%%Y-%%m-%%d %%H:%%i:%%s'), extern.value as ext_val, intern.value as int_val, rec.score FROM bskREC rec LEFT JOIN bskRECORDCOMMENT cmt ON (rec.id_bibrec_or_bskEXTREC=cmt.id_bibrec_or_bskEXTREC AND rec.id_bskBASKET=cmt.id_bskBASKET) LEFT JOIN bskEXTFMT extern ON (-rec.id_bibrec_or_bskEXTREC=extern.id_bskEXTREC AND extern.format=%s) LEFT JOIN bibfmt intern ON (rec.id_bibrec_or_bskEXTREC=intern.id_bibrec AND intern.format=%s) LEFT JOIN bskEXTREC AS extrec ON extrec.id=-rec.id_bibrec_or_bskEXTREC WHERE rec.id_bskBASKET=%s AND rec.id_bibrec_or_bskEXTREC=%s GROUP BY rec.id_bibrec_or_bskEXTREC ORDER BY rec.score""" params = (format, format, bskid, recid) res = run_sql(query, params) if res: queryU = """UPDATE bskBASKET SET nb_views=nb_views+1 WHERE id=%s""" paramsU = (bskid,) run_sql(queryU, paramsU) score = res[0][6] query_previous = """SELECT id_bibrec_or_bskEXTREC FROM bskREC WHERE id_bskBASKET=%s AND score<%s ORDER BY score DESC LIMIT 1""" params_previous = (bskid, score) res_previous = run_sql(query_previous, params_previous) query_next = """SELECT id_bibrec_or_bskEXTREC FROM bskREC WHERE id_bskBASKET=%s AND score>%s ORDER BY score ASC LIMIT 1""" params_next = (bskid, score) res_next = run_sql(query_next, params_next) query_index = """ SELECT COUNT(id_bibrec_or_bskEXTREC) FROM bskREC WHERE id_bskBASKET=%s AND score<=%s ORDER BY score""" params_index = (bskid, score) res_index = run_sql(query_index, params_index) res_index = __wash_sql_count(res_index) return (res[0], res_previous and res_previous[0][0] or 0, res_next and res_next[0][0] or 0, res_index) else: return () def get_basket_item_title_and_URL(recid): """ Retrieves the title and URL for the specified item in the specified basket. @param bskid: The basked id @type bskid: int @param recid: The record (item) id @type recid: int @return: A tuple containing the title as a sting and the URL as a string. """ if recid > 0: # This is a local record, we can easily retrieve the title using the # search engine's get_fieldvalues function and the MARC field and tag. title_list = get_fieldvalues(recid, '245___') # Check if the main title is always the first element in the list if title_list: title = title_list[0] else: title = "" url = '%s/record/%i' % (CFG_SITE_URL, recid) elif recid < 0: # This is an external record or item, use title = "This is an external record or item." url = '%s' % (CFG_SITE_URL,) query = """ SELECT rec.collection_id, rec.original_url, fmt.value FROM bskEXTREC as rec, bskEXTFMT as fmt WHERE rec.id=%s AND fmt.id_bskEXTREC=%s AND fmt.format='hb'""" params = (-recid, -recid) result = run_sql(query, params) if result: item = __decompress_last(result[0]) collection = item[0] url = item[1] hb = item[2] if collection == 0: # This is an external item title = hb.split('\n',1)[0] elif collection > 0: # This is an external record from a hosted collection title = hb.split('</strong>',1)[0].split('<strong>')[-1] return (title, url) def share_basket_with_group(bskid, group_id, share_level=CFG_WEBBASKET_SHARE_LEVELS['READITM']): """ Share basket bskid with group group_id with given share_level @param share_level: see CFG_WEBBASKET_SHARE_LEVELS in webbasket_config """ now = convert_datestruct_to_datetext(localtime()) run_sql("""REPLACE INTO usergroup_bskBASKET (id_usergroup, id_bskBASKET, date_shared, share_level) VALUES (%s,%s,%s,%s)""", (group_id, bskid, now, str(share_level))) def update_rights(bskid, group_rights): """update rights (permissions) for groups. @param bskid: basket id @param group_rights: dictionary of {group id: new rights} """ now = convert_datestruct_to_datetext(localtime()) query1 = """REPLACE INTO usergroup_bskBASKET (id_usergroup, id_bskBASKET, date_shared, share_level) VALUES """ + \ ', '.join(["(%s, %s, %s, %s)"] * len(group_rights.items())) params = () for (group_id, share_level) in group_rights.items(): params += (int(group_id), int(bskid), now, str(share_level)) run_sql(query1, params) query2 = """DELETE FROM usergroup_bskBASKET WHERE share_level='NO'""" run_sql(query2) def move_item(bskid, recid, direction): """Change score of an item in a basket""" bskid = int(bskid) query1 = """SELECT id_bibrec_or_bskEXTREC, score FROM bskREC WHERE id_bskBASKET=%s ORDER BY score, date_added""" items = run_sql(query1, (bskid,)) (recids, scores) = zip(*items) (recids, scores) = (list(recids), list(scores)) if len(recids) and recid in recids: current_index = recids.index(recid) if direction == CFG_WEBBASKET_ACTIONS['UP']: switch_index = 0 if current_index != 0: switch_index = current_index -1 else: switch_index = len(recids) - 1 if current_index != len(recids)-1: switch_index = current_index + 1 query2 = """UPDATE bskREC SET score=%s WHERE id_bskBASKET=%s AND id_bibrec_or_bskEXTREC=%s""" res1 = run_sql(query2, (scores[switch_index], bskid, recids[current_index])) res2 = run_sql(query2, (scores[current_index], bskid, recids[switch_index])) if res1 and res2: now = convert_datestruct_to_datetext(localtime()) query3 = "UPDATE bskBASKET SET date_modification=%s WHERE id=%s" params3 = (now, int(bskid)) run_sql(query3, params3) def delete_item(bskid, recid, update_date_modification=True): """Remove item recid from basket bskid""" if recid < 0: query0A = "select count(id_bskBASKET) from bskREC where id_bibrec_or_bskEXTREC=%s" % (int(recid)) ncopies = run_sql(query0A) if ncopies and ncopies[0][0]<=1: # uncomment the following 5 lines and comment the following 2 to delete cached records # only for external sources and not for external records #query0B = "SELECT collection_id FROM bskEXTREC WHERE id=%s" % (-int(recid)) #colid = run_sql(query0B) #if colid and colid[0][0]==0: #query0C = "DELETE from bskEXTFMT WHERE id_bskEXTREC=%s" % (-int(recid)) #run_sql(query0C) # the following two lines delete cached external records. We could keep them if we find # a way to reuse them in case the external records are added again in the future. query0D = "DELETE from bskEXTFMT WHERE id_bskEXTREC=%s" % (-int(recid)) run_sql(query0D) query0E = "DELETE from bskEXTREC WHERE id=%s" % (-int(recid)) run_sql(query0E) query_notes = "DELETE FROM bskRECORDCOMMENT WHERE id_bskBASKET=%s AND id_bibrec_or_bskEXTREC=%s" run_sql(query_notes, (bskid, recid,)) query1 = "DELETE from bskREC WHERE id_bskBASKET=%s AND id_bibrec_or_bskEXTREC=%s" params1 = (int(bskid), int(recid)) res = run_sql(query1, params1) if update_date_modification and res: now = convert_datestruct_to_datetext(localtime()) query2 = "UPDATE bskBASKET SET date_modification=%s WHERE id=%s" params2 = (now, int(bskid)) run_sql(query2, params2) return res def add_to_basket(uid, recids=[], colid=0, bskid=0, es_title="", es_desc="", es_url=""): """Add items (recids) basket (bskid).""" if (recids or (colid == -1 and es_title and es_desc and es_url)) and bskid > 0: query_max_score = """ SELECT MAX(score) FROM bskREC WHERE id_bskBASKET=%s""" params_max_score = (bskid,) res_max_score = run_sql(query_max_score, params_max_score) max_score = __wash_sql_count(res_max_score) if not max_score: # max_score == None actually means that the basket doesn't exist. # Maybe we should return 0 and inform the admin? max_score = 1 if colid > 0: query_existing = """ SELECT id, external_id FROM bskEXTREC WHERE %s AND collection_id=%s""" sep_or = ' OR ' query_existing %= (sep_or.join(['external_id=%s'] * len(recids)), colid) params_existing = tuple(recids) res_existing = run_sql(query_existing, params_existing) existing_recids = [int(external_ids_couple[1]) for external_ids_couple in res_existing] existing_ids = [int(ids[0]) for ids in res_existing] new_recids = [recid for recid in recids if int(recid) not in existing_recids] # sets approach #existing_recids = [ids[1] for ids in res_existing] #new_recids = list(set(recids)-set(existing_recids)) if new_recids: query_new = """ INSERT INTO bskEXTREC (external_id, collection_id, creation_date, modification_date) VALUES """ now = convert_datestruct_to_datetext(localtime()) records = ["(%s, %s, %s, %s)"] * len(new_recids) query_new += ', '.join(records) params_new = () for new_recid in new_recids: params_new += (int(new_recid), colid, now, now) res_new = run_sql(query_new, params_new) recids = [-int(recid) for recid in existing_ids] recids.extend(range(-res_new,-(res_new+len(new_recids)),-1)) else: recids = [-int(recid) for recid in existing_ids] elif colid < 0: query_external = """INSERT INTO bskEXTREC (collection_id, original_url, creation_date, modification_date) VALUES (%s, %s, %s, %s)""" now = convert_datestruct_to_datetext(localtime()) params_external = (colid, es_url, now, now) res_external = run_sql(query_external, params_external) recids = [-res_external] store_external_source(res_external, es_title, es_desc, es_url, 'xm') store_external_source(res_external, es_title, es_desc, es_url, 'hb') query_insert = """ INSERT IGNORE INTO bskREC (id_bibrec_or_bskEXTREC, id_bskBASKET, id_user_who_added_item, date_added, score) VALUES """ if colid == 0 or (colid > 0 and not new_recids): now = convert_datestruct_to_datetext(localtime()) records = ["(%s, %s, %s, %s, %s)"] * len(recids) query_insert += ', '.join(records) params_insert = () i = 1 for recid in recids: params_insert += (recid, bskid, uid, now, max_score + i) i += 1 run_sql(query_insert, params_insert) query_update = """ UPDATE bskBASKET SET date_modification=%s WHERE id=%s""" params_update = (now, bskid) run_sql(query_update, params_update) return recids return 0 def add_to_many_baskets(uid, recids=[], colid=0, bskids=[], es_title="", es_desc="", es_url=""): """Add items recids to every basket in bskids list.""" if (len(recids) or colid == -1) and len(bskids): query1 = """SELECT id_bskBASKET, max(score) FROM bskREC WHERE %s GROUP BY id_bskBASKET""" bskids = [bskid for bskid in bskids if int(bskid) >= 0] sep_or = ' OR ' query1 %= sep_or.join(['id_bskBASKET=%s'] * len(bskids)) bsks = dict.fromkeys(bskids, 0) params = tuple(bskids) bsks.update(dict(run_sql(query1, params))) if colid > 0: query2A = """SELECT id, external_id FROM bskEXTREC WHERE %s AND collection_id=%s""" query2A %= (sep_or.join(['external_id=%s'] * len(recids)), colid) params2A = tuple(recids) res2A = run_sql(query2A, params2A) existing_recids = [int(external_ids_couple[1]) for external_ids_couple in res2A] existing_ids = [int(ids[0]) for ids in res2A] new_recids = [recid for recid in recids if int(recid) not in existing_recids] # sets approach #existing_recids = [ids[1] for ids in res2A] #new_recids = list(set(recids)-set(existing_recids)) - f = open("/tmp/bsk_db", "w") - f.write(str(recids) + "\n" + str(existing_recids) + "\n" + str(existing_ids) + "\n" + str(new_recids) + "\n") - f.close() if new_recids: query2B = """INSERT INTO bskEXTREC (external_id, collection_id, creation_date, modification_date) VALUES """ now = convert_datestruct_to_datetext(localtime()) records = ["(%s, %s, %s, %s)"] * len(new_recids) query2B += ', '.join(records) params2B = () for new_recid in new_recids: params2B += (int(new_recid), colid, now, now) res = run_sql(query2B, params2B) recids = [-int(recid) for recid in existing_ids] recids.extend(range(-res,-(res+len(new_recids)),-1)) else: recids = [-int(recid) for recid in existing_ids] elif colid < 0: query2C = """INSERT INTO bskEXTREC (collection_id, original_url, creation_date, modification_date) VALUES (%s, %s, %s, %s)""" now = convert_datestruct_to_datetext(localtime()) params = (colid, es_url, now, now) res = run_sql(query2C, params) recids = [-res] store_external_source(res, es_title, es_desc, es_url, 'xm') store_external_source(res, es_title, es_desc, es_url, 'hb') query2 = """INSERT IGNORE INTO bskREC (id_bibrec_or_bskEXTREC, id_bskBASKET, id_user_who_added_item, date_added, score) VALUES """ if colid == 0 or (colid > 0 and not new_recids): now = convert_datestruct_to_datetext(localtime()) records = ["(%s, %s, %s, %s, %s)"] * (len(recids) * len(bsks.items())) query2 += ', '.join(records) params = () for (bskid, max_score) in bsks.items(): i = 1 for recid in recids: params += (int(recid), int(bskid), int(uid), now, int(max_score) + i) i += 1 run_sql(query2, params) query3 = """UPDATE bskBASKET SET date_modification=%s WHERE """ query3 += sep_or.join(["id=%s"] * len(bskids)) params = (now,) + tuple(bskids) run_sql(query3, params) return len(bskids) return 0 def get_external_records_by_collection(recids): """Get the selected recids, both local and external, grouped by collection.""" if recids: query = """ SELECT GROUP_CONCAT(id), GROUP_CONCAT(external_id), collection_id FROM bskEXTREC WHERE %s GROUP BY collection_id""" recids = [-recid for recid in recids] sep_or = ' OR ' query %= sep_or.join(['id=%s'] * len(recids)) params = tuple(recids) res = run_sql(query,params) return res return 0 def get_external_records(recids, of="hb"): """Get formatted external records from the database.""" if recids: query = """ SELECT rec.collection_id, fmt.id_bskEXTREC, fmt.value FROM bskEXTFMT AS fmt JOIN bskEXTREC AS rec ON rec.id=fmt.id_bskEXTREC WHERE format=%%s AND ( %s )""" recids = [-recid for recid in recids] sep_or = ' OR ' query %= sep_or.join(['id_bskEXTREC=%s'] * len(recids)) params = [of] params.extend(recids) params = tuple(params) res = run_sql(query,params) return res return () def store_external_records(records, of="hb"): """Store formatted external records to the database.""" if records: query = """INSERT INTO bskEXTFMT (id_bskEXTREC, format, last_updated, value) VALUES """ now = convert_datestruct_to_datetext(localtime()) formatted_records = ["(%s, %s, %s, %s)"] * len(records) query += ', '.join(formatted_records) params = () for record in records: params += (record[0], of, now, compress(record[1])) run_sql(query,params) def store_external_urls(ids_urls): """Store original urls for external records to the database.""" #for id_url in ids_urls.iteritems(): for id_url in ids_urls: query = """UPDATE bskEXTREC SET original_url=%s WHERE id=%s""" params = (id_url[1], id_url[0]) run_sql(query,params) def store_external_source(es_id, es_title, es_desc, es_url, of="hb"): """Store formatted external sources to the database.""" if es_id and es_title and es_desc: query = """INSERT INTO bskEXTFMT (id_bskEXTREC, format, last_updated, value) VALUES (%s, %s, %s, %s)""" now = convert_datestruct_to_datetext(localtime()) value = create_pseudo_record(es_title, es_desc, es_url, of) params = (es_id, of, now, compress(value)) run_sql(query,params) def get_external_colid_and_url(recid): """Get the collection id and original url for an external record.""" if recid: query = """SELECT collection_id, original_url FROM bskEXTREC WHERE id=%s""" params = (-recid,) res = run_sql(query,params) if res: return res else: return 0 ############################ Group baskets #################################### def get_group_baskets_info_for_group(grpid): """Return information about every basket that belongs to the given group, provided the user is its manager or a member of it.""" if not grpid: return () query = """ SELECT bsk.id, bsk.name, DATE_FORMAT(bsk.date_modification, '%%Y-%%m-%%d %%H:%%i:%%s'), bsk.nb_views, COUNT(rec.id_bibrec_or_bskEXTREC), DATE_FORMAT(max(rec.date_added), '%%Y-%%m-%%d %%H:%%i:%%s'), ugbsk.share_level, bsk.id_owner FROM usergroup_bskBASKET AS ugbsk JOIN bskBASKET AS bsk ON bsk.id=ugbsk.id_bskBASKET LEFT JOIN bskREC AS rec ON rec.id_bskBASKET=bsk.id WHERE ugbsk.id_usergroup=%s AND ugbsk.share_level!='NO' GROUP BY bsk.id ORDER BY bsk.name""" params = (grpid,) res = run_sql(query, params) return res def get_group_name(gid): """Given its id return the group's name.""" query = """ SELECT name FROM usergroup WHERE id=%s""" params = (gid,) res = run_sql(query, params) return res -def get_all_group_basket_ids_and_names_by_group(uid): - """For a given user return all their group baskets - (in tuples: (id, name)) grouped by group. Note that the - basket tuples have to evaluated to be converted to actual - tuples.""" +def get_all_user_group_basket_ids_by_group(uid): + """For a given user return all their group basket ids grouped by group.""" query = """ SELECT ug.id, ug.name, - count(bsk.id), - GROUP_CONCAT('(', ugbsk.id_bskBASKET, ', \"', bsk.name, '\")' - ORDER BY bsk.name) + GROUP_CONCAT(ugbsk.id_bskBASKET) FROM usergroup AS ug JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_usergroup=ug.id JOIN bskBASKET AS bsk ON ugbsk.id_bskBASKET=bsk.id JOIN user_usergroup AS uug ON ug.id=uug.id_usergroup AND uug.id_user=%s GROUP BY ug.name ORDER BY ug.name""" params = (uid,) res = run_sql(query, params) return res -def get_all_group_basket_ids_and_names_by_group_for_add_to_list(uid): - """For a given user return all their group baskets - (in tuples: (id, name)) grouped by group. Note that the - basket tuples have to evaluated to be converted to actual - tuples.""" +def get_all_user_group_basket_ids_by_group_with_add_rights(uid): + """For a given user return all their group basket ids grouped by group. + Return only the basket ids to which it is allowed to add records.""" query = """ SELECT ug.name, - GROUP_CONCAT('(', ugbsk.id_bskBASKET, ', \"', bsk.name, '\")' - ORDER BY bsk.name) + GROUP_CONCAT(ugbsk.id_bskBASKET) FROM usergroup AS ug JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_usergroup=ug.id AND ugbsk.share_level!='NO' AND ugbsk.share_level!='RI' AND ugbsk.share_level!='RC' AND ugbsk.share_level!='AC' JOIN bskBASKET AS bsk ON ugbsk.id_bskBASKET=bsk.id JOIN user_usergroup AS uug ON ug.id=uug.id_usergroup AND uug.id_user=%s GROUP BY ug.name ORDER BY ug.name""" params = (uid,) res = run_sql(query, params) return res def get_all_group_baskets_names(uid, min_rights=CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']): """For a given user returns every group baskets in which he can <min_rights> return a list of tuples: (bskid, bsk_name, group_name).""" # TODO: This function is no longer used. Delete if necessary. uid = int(uid) try: min_rights_num = CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(min_rights) except ValueError: return () groups = get_groups_user_member_of(uid) if groups: where_clause = '(' where_clause += " OR ".join(["ugbsk.id_usergroup=%s"] * len(groups)) where_clause += ') AND (' where_clause += " OR ".join(["ugbsk.share_level=%s"] * len(CFG_WEBBASKET_SHARE_LEVELS_ORDERED[min_rights_num:])) where_clause += ")" query = """ SELECT bsk.id, bsk.name, ug.name FROM usergroup ug JOIN usergroup_bskBASKET ugbsk ON ug.id=ugbsk.id_usergroup JOIN bskBASKET bsk ON bsk.id=ugbsk.id_bskBASKET WHERE %s AND NOT(ugbsk.share_level='NO') ORDER BY ug.name""" % where_clause params = tuple([group_id for (group_id, dummy) in groups]) params += tuple(CFG_WEBBASKET_SHARE_LEVELS_ORDERED[min_rights_num:]) return run_sql(query, params) return () def is_shared_to(bskids): """For each bskid in bskids get id of one of its group. Used to make distinction between private basket (no group), 'world' basket (0) or group basket (any int > 0) """ if not((type(bskids) == list) or (type(bskids) == tuple)): bskids = [bskids] query = """SELECT b.id, min(u.id_usergroup) FROM bskBASKET b LEFT JOIN usergroup_bskBASKET u ON (b.id=u.id_bskBASKET) """ if len(bskids) != 0: query += " WHERE " query += " OR ".join(['b.id=%s'] * len(bskids)) query += " GROUP BY b.id" params = tuple(bskids) res = run_sql(query, params) if res: return res return () def get_basket_share_level(bskid): """Get the minimum share level of the basket (bskid). Returns: None for personal baskets positive integet for group baskets 0 for public baskets Will return 0 if the basket is both group and publicly shared.""" query = """ SELECT MIN(ugbsk.id_usergroup) FROM bskBASKET AS bsk LEFT JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=bsk.id WHERE bsk.id=%s GROUP BY bsk.id""" params = (bskid,) res = run_sql(query, params) return res def get_all_items_in_user_group_baskets(uid, group=0, format='hb'): """For the specified user, return all the items in their group baskets, grouped by basket if local or as a list if external. If group is set, return only that group's items.""" if group: group_clause = """AND ugbsk.id_usergroup=%s""" params_local = (group, uid) params_external = (group, uid, format) else: group_clause = "" params_local = (uid,) params_external = (uid, format) query_local = """ SELECT rec.id_bskBASKET, bsk.name, uug.id_usergroup, ug.name, ugbsk.share_level, GROUP_CONCAT(rec.id_bibrec_or_bskEXTREC) FROM bskREC AS rec JOIN bskBASKET AS bsk ON bsk.id=rec.id_bskBASKET JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=rec.id_bskBASKET %s JOIN user_usergroup AS uug ON uug.id_usergroup=ugbsk.id_usergroup AND uug.id_user=%%s JOIN usergroup AS ug ON ug.id=uug.id_usergroup WHERE rec.id_bibrec_or_bskEXTREC > 0 GROUP BY rec.id_bskBASKET""" % (group_clause,) res_local = run_sql(query_local, params_local) query_external = """ SELECT rec.id_bskBASKET, bsk.name, uug.id_usergroup, ug.name, ugbsk.share_level, rec.id_bibrec_or_bskEXTREC, ext.value FROM bskREC AS rec JOIN bskBASKET AS bsk ON bsk.id=rec.id_bskBASKET JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=rec.id_bskBASKET %s JOIN user_usergroup AS uug ON uug.id_usergroup=ugbsk.id_usergroup AND uug.id_user=%%s JOIN usergroup AS ug ON ug.id=uug.id_usergroup JOIN bskEXTFMT AS ext ON ext.id_bskEXTREC=-rec.id_bibrec_or_bskEXTREC AND ext.format=%%s WHERE rec.id_bibrec_or_bskEXTREC < 0 ORDER BY rec.id_bskBASKET""" % (group_clause,) res_external = run_sql(query_external, params_external) return (res_local, res_external) def get_all_items_in_user_group_baskets_by_matching_notes(uid, group=0, p=""): """For the specified user, return all the items in group personal baskets matching their notes' titles and bodies, grouped by basket. If topic is set, return only that topic's items.""" p = p and '%' + p + '%' or '%' if group: group_clause = """AND ugbsk.id_usergroup=%s""" params = (group, uid, p, p) else: group_clause = "" params = (uid, p, p) query = """ SELECT notes.id_bskBASKET, bsk.name, uug.id_usergroup, ug.name, ugbsk.share_level, GROUP_CONCAT(DISTINCT(notes.id_bibrec_or_bskEXTREC)) FROM bskRECORDCOMMENT AS notes JOIN bskBASKET AS bsk ON bsk.id=notes.id_bskBASKET JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=notes.id_bskBASKET AND ugbsk.share_level IS NOT NULL AND ugbsk.share_level!='NO' AND ugbsk.share_level!='RI' %s JOIN user_usergroup AS uug ON uug.id_usergroup=ugbsk.id_usergroup AND uug.id_user=%%s JOIN usergroup AS ug ON ug.id=uug.id_usergroup WHERE notes.title like %%s OR notes.body like %%s GROUP BY notes.id_bskBASKET""" % (group_clause,) res = run_sql(query, params) return res def is_group_basket_valid(uid, bskid): """Check if the basked (bskid) belongs to one of the groups the user (uid) is a member of and is valid.""" query = """ SELECT id FROM bskBASKET AS bsk JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=bsk.id JOIN user_usergroup AS uug ON uug.id_usergroup=ugbsk.id_usergroup AND uug.id_user=%s WHERE id=%s""" params = (uid, bskid) res = run_sql(query, params) return res def is_group_valid(uid, group): """Check if the group exists and the user is a member or manager.""" query = """ SELECT id_usergroup FROM user_usergroup WHERE id_usergroup=%s AND id_user=%s""" params = (group, uid) res = run_sql(query, params) return res def get_all_user_groups(uid): """Return a list of the groups the user is a member of or manages.""" query = """ SELECT ug.id, ug.name FROM user_usergroup AS uug JOIN usergroup AS ug ON ug.id=uug.id_usergroup JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_usergroup=uug.id_usergroup WHERE uug.id_user=%s GROUP BY uug.id_usergroup""" params = (uid,) res = run_sql(query, params) return res ########################## External baskets ################################### def get_external_baskets_infos(uid): """Get general informations about every external basket user uid has subscribed to.""" query = """ SELECT bsk.id, bsk.name, DATE_FORMAT(bsk.date_modification, '%%Y-%%m-%%d %%H:%%i:%%s'), bsk.nb_views, count(rec.id_bibrec_or_bskEXTREC), DATE_FORMAT(max(rec.date_added), '%%Y-%%m-%%d %%H:%%i:%%s'), ugbsk.share_level FROM bskBASKET bsk JOIN user_bskBASKET ubsk ON (bsk.id=ubsk.id_bskBASKET AND ubsk.id_user=%s) LEFT JOIN bskREC rec ON (bsk.id=rec.id_bskBASKET) LEFT JOIN usergroup_bskBASKET ugbsk ON (ugbsk.id_bskBASKET=bsk.id AND ugbsk.id_usergroup=0) WHERE bsk.id_owner!=%s GROUP BY bsk.id """ uid = int(uid) params = (uid, uid) res = run_sql(query, params) if res: return res return () def get_external_basket_info(bskid): """""" query = """ SELECT bsk.id, bsk.name, DATE_FORMAT(bsk.date_modification, '%%Y-%%m-%%d %%H:%%i:%%s'), bsk.nb_views, count(rec.id_bibrec_or_bskEXTREC), DATE_FORMAT(max(rec.date_added), '%%Y-%%m-%%d %%H:%%i:%%s'), ugbsk.share_level FROM bskBASKET AS bsk LEFT JOIN bskREC AS rec ON bsk.id=rec.id_bskBASKET JOIN usergroup_bskBASKET AS ugbsk ON bsk.id=ugbsk.id_bskBASKET AND ugbsk.id_usergroup=0 WHERE id=%s""" params = (bskid,) res = run_sql(query, params) return res def get_all_external_basket_ids_and_names(uid): """For a given user return all their external baskets (in tuples: (id, name, number_of_records)).""" query = """ SELECT bsk.id, bsk.name, count(rec.id_bibrec_or_bskEXTREC), ugbsk.id_usergroup FROM user_bskBASKET AS ubsk JOIN bskBASKET AS bsk ON ubsk.id_bskBASKET=bsk.id AND ubsk.id_user!=bsk.id_owner LEFT JOIN bskREC AS rec ON ubsk.id_bskBASKET=rec.id_bskBASKET LEFT JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_usergroup=0 AND ugbsk.id_bskBASKET=bsk.id WHERE ubsk.id_user=%s GROUP BY bsk.id ORDER BY bsk.name""" params = (uid,) res = run_sql(query, params) return res def count_external_baskets(uid): """Returns the number of external baskets the user is subscribed to.""" query = """ SELECT COUNT(ubsk.id_bskBASKET) FROM user_bskBASKET ubsk LEFT JOIN bskBASKET bsk ON (bsk.id=ubsk.id_bskBASKET AND ubsk.id_user=%s) WHERE bsk.id_owner!=%s""" params = (int(uid), int(uid)) res = run_sql(query, params) return __wash_sql_count(res) def get_all_external_baskets_names(uid, min_rights=CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']): """ for a given user returns every basket which he has subscribed to and in which he can <min_rights> return a list of tuples: (bskid, bsk_name) """ uid = int(uid) try: min_rights_num = CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(min_rights) except ValueError: return () where_clause = ' AND (' for right in CFG_WEBBASKET_SHARE_LEVELS_ORDERED[min_rights_num:-1]: where_clause += "ugbsk.share_level = '%s' OR " % right where_clause += "ugbsk.share_level = '%s')" % CFG_WEBBASKET_SHARE_LEVELS_ORDERED[-1] query = """ SELECT bsk.id, bsk.name FROM bskBASKET bsk JOIN usergroup_bskBASKET ugbsk ON bsk.id=ugbsk.id_bskBASKET JOIN user_bskBASKET ubsk ON ubsk.id_bskBASKET=bsk.id WHERE ugbsk.id_usergroup=0 AND ubsk.id_user=%s AND NOT(bsk.id_owner=%s) AND NOT(ugbsk.share_level='NO') """ + where_clause params = (uid, uid) return run_sql(query, params) def get_all_items_in_user_public_baskets(uid, format='hb'): """For the specified user, return all the items in the public baskets they are subscribed to, grouped by basket if local or as a list if external.""" query_local = """ SELECT rec.id_bskBASKET, bsk.name, ugbsk.share_level, GROUP_CONCAT(rec.id_bibrec_or_bskEXTREC) FROM bskREC AS rec JOIN bskBASKET AS bsk ON bsk.id=rec.id_bskBASKET AND bsk.id_owner!=%s JOIN user_bskBASKET AS ubsk ON ubsk.id_bskBASKET=rec.id_bskBASKET AND ubsk.id_user=%s JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=rec.id_bskBASKET AND ugbsk.id_usergroup=0 WHERE rec.id_bibrec_or_bskEXTREC > 0 GROUP BY rec.id_bskBASKET""" params_local = (uid, uid) res_local = run_sql(query_local, params_local) query_external = """ SELECT rec.id_bskBASKET, bsk.name, ugbsk.share_level, rec.id_bibrec_or_bskEXTREC, ext.value FROM bskREC AS rec JOIN bskBASKET AS bsk ON bsk.id=rec.id_bskBASKET AND bsk.id_owner!=%s JOIN user_bskBASKET AS ubsk ON ubsk.id_bskBASKET=rec.id_bskBASKET AND ubsk.id_user=%s JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=rec.id_bskBASKET AND ugbsk.id_usergroup=0 JOIN bskEXTFMT AS ext ON ext.id_bskEXTREC=-rec.id_bibrec_or_bskEXTREC AND ext.format=%s WHERE rec.id_bibrec_or_bskEXTREC < 0 ORDER BY rec.id_bskBASKET""" params_external = (uid, uid, format) res_external = run_sql(query_external, params_external) return (res_local, res_external) def get_all_items_in_user_public_baskets_by_matching_notes(uid, p=""): """For the specified user, return all the items in the public baskets they are subscribed to, matching their notes' titles and bodies, grouped by basket""" p = p and '%' + p + '%' or '%' query = """ SELECT notes.id_bskBASKET, bsk.name, ugbsk.share_level, GROUP_CONCAT(DISTINCT(notes.id_bibrec_or_bskEXTREC)) FROM bskRECORDCOMMENT AS notes JOIN bskBASKET AS bsk ON bsk.id=notes.id_bskBASKET AND bsk.id_owner!=%s JOIN user_bskBASKET AS ubsk ON ubsk.id_bskBASKET=notes.id_bskBASKET AND ubsk.id_user=%s JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=notes.id_bskBASKET AND ugbsk.id_usergroup=0 AND ugbsk.share_level IS NOT NULL AND ugbsk.share_level!='NO' AND ugbsk.share_level!='RI' WHERE notes.title like %s OR notes.body like %s GROUP BY notes.id_bskBASKET""" params = (uid, uid, p, p) res = run_sql(query, params) return res def get_all_items_in_all_public_baskets(format='hb'): """Return all the items in all the public baskets, grouped by basket if local or as a list if external.""" query_local = """ SELECT rec.id_bskBASKET, bsk.name, ugbsk.share_level, GROUP_CONCAT(rec.id_bibrec_or_bskEXTREC) FROM bskREC AS rec JOIN bskBASKET AS bsk ON bsk.id=rec.id_bskBASKET JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=rec.id_bskBASKET AND ugbsk.id_usergroup=0 WHERE rec.id_bibrec_or_bskEXTREC > 0 GROUP BY rec.id_bskBASKET""" res_local = run_sql(query_local) query_external = """ SELECT rec.id_bskBASKET, bsk.name, ugbsk.share_level, rec.id_bibrec_or_bskEXTREC, ext.value FROM bskREC AS rec JOIN bskBASKET AS bsk ON bsk.id=rec.id_bskBASKET JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=rec.id_bskBASKET AND ugbsk.id_usergroup=0 JOIN bskEXTFMT AS ext ON ext.id_bskEXTREC=-rec.id_bibrec_or_bskEXTREC AND ext.format=%s WHERE rec.id_bibrec_or_bskEXTREC < 0 ORDER BY rec.id_bskBASKET""" params_external = (format,) res_external = run_sql(query_external, params_external) return (res_local, res_external) def get_all_items_in_all_public_baskets_by_matching_notes(p=""): """Return all the items in all the public baskets matching their notes' titles and bodies, grouped by basket""" p = p and '%' + p + '%' or '%' query = """ SELECT notes.id_bskBASKET, bsk.name, ugbsk.share_level, GROUP_CONCAT(DISTINCT(notes.id_bibrec_or_bskEXTREC)) FROM bskRECORDCOMMENT AS notes JOIN bskBASKET AS bsk ON bsk.id=notes.id_bskBASKET JOIN usergroup_bskBASKET AS ugbsk ON ugbsk.id_bskBASKET=notes.id_bskBASKET AND ugbsk.id_usergroup=0 AND ugbsk.share_level IS NOT NULL AND ugbsk.share_level!='NO' AND ugbsk.share_level!='RI' WHERE notes.title like %s OR notes.body like %s GROUP BY notes.id_bskBASKET""" params = (p, p) res = run_sql(query, params) return res ############################ Public access #################################### def get_public_basket_infos(bskid): """return (id, name, date modification, nb of views, id of owner, nickname of owner, rights for public access) for a given basket""" basket = [] query1 = """SELECT bsk.id, bsk.name, DATE_FORMAT(bsk.date_modification, '%%Y-%%m-%%d %%H:%%i:%%s'), bsk.nb_views, bsk.id_owner, user.nickname FROM bskBASKET bsk LEFT JOIN user ON bsk.id_owner=user.id WHERE bsk.id=%s""" res1 = run_sql(query1, (int(bskid),)) if len(res1): basket = list(res1[0]) query2 = """SELECT share_level FROM usergroup_bskBASKET WHERE id_usergroup=0 and id_bskBASKET=%s""" res2 = run_sql(query2, (int(bskid),)) if res2: basket.append(res2[0][0]) else: basket.append(None) return basket def get_public_basket_info(bskid): """Return information about a given public basket.""" query = """ SELECT bsk.id, bsk.name, bsk.id_owner, DATE_FORMAT(bsk.date_modification, '%%Y-%%m-%%d %%H:%%i:%%s'), bsk.nb_views, COUNT(rec.id_bibrec_or_bskEXTREC), GROUP_CONCAT(rec.id_bibrec_or_bskEXTREC), ubsk.share_level FROM bskBASKET AS bsk LEFT JOIN bskREC AS rec ON rec.id_bskBASKET=bsk.id JOIN usergroup_bskBASKET AS ubsk ON ubsk.id_bskBASKET=bsk.id AND ubsk.id_usergroup=0 WHERE bsk.id=%s GROUP BY bsk.id;""" params = (bskid,) res = run_sql(query, params) return res def get_basket_general_infos(bskid): """return information about a basket, suited for public access. @return: a (id, name, date of modification, nb of views, nb of records, id of owner) tuple """ query = """SELECT bsk.id, bsk.name, DATE_FORMAT(bsk.date_modification, '%%Y-%%m-%%d %%H:%%i:%%s'), bsk.nb_views, count(rec.id_bibrec_or_bskEXTREC), bsk.id_owner FROM bskBASKET bsk LEFT JOIN bskREC rec ON bsk.id=rec.id_bskBASKET WHERE bsk.id=%s GROUP BY bsk.id""" res = run_sql(query, (int(bskid),)) if res: query2 = "UPDATE bskBASKET SET nb_views=nb_views+1 WHERE id=%s" run_sql(query2, (int(bskid),)) return res[0] return () def get_basket_owner_id(bskid): """Return the uid of the owner.""" query = """SELECT id_owner FROM bskBASKET WHERE id=%s""" res = run_sql(query, (bskid, )) if res: return res[0][0] return -1 def count_public_baskets(): """Returns the number of public baskets.""" query = """ SELECT COUNT(id_bskBASKET) FROM usergroup_bskBASKET WHERE id_usergroup=0""" res = run_sql(query) return __wash_sql_count(res) def get_public_baskets_list(inf_limit, max_number, order=1, asc=1): """Return list of public baskets @param inf_limit: limit to baskets from number x @param max_number: number of baskets to return @order: 1: order by name of basket, 2: number of views, 3: owner @return: [(basket id, basket name, nb of views, uid of owner, nickname of owner)]""" query = """SELECT bsk.id, bsk.name, bsk.nb_views, u.id, u.nickname FROM bskBASKET bsk LEFT JOIN usergroup_bskBASKET ugbsk on bsk.id=ugbsk.id_bskBASKET LEFT JOIN user u on bsk.id_owner=u.id WHERE ugbsk.id_usergroup=0 """ if order == 2: query += 'ORDER BY bsk.nb_views' elif order == 3: query += 'ORDER BY u.nickname' if asc: query += ' ASC' else: query += ' DESC' query += ', u.id' else: query += 'ORDER BY bsk.name' if asc: query += ' ASC ' else: query += ' DESC ' query += "LIMIT %s,%s" return run_sql(query, (inf_limit, max_number)) def count_all_public_baskets(): """Return the number of all the public baskets.""" query = """ SELECT count(id_bskBASKET) FROM usergroup_bskBASKET WHERE id_usergroup=0""" res = run_sql(query) return __wash_sql_count(res) def get_list_public_baskets(page, max_number, sort='name', asc=1): """Return list of public baskets @param page: limit to baskets from number x @param max_number: maximum number of baskets to return @sort: 1: order by name of basket, 2: number of views, 3: owner @return: [(basket id, basket name, nb of views, uid of owner, nickname of owner)]""" query = """ SELECT bsk.id, bsk.name, bsk.id_owner, u.nickname, DATE_FORMAT(bsk.date_modification, '%%Y-%%m-%%d %%H:%%i:%%s'), COUNT(rec.id_bibrec_or_bskEXTREC) AS items, bsk.nb_views FROM usergroup_bskBASKET AS ugbsk JOIN bskBASKET AS bsk ON bsk.id=ugbsk.id_bskBASKET LEFT JOIN bskREC AS rec ON rec.id_bskBASKET=bsk.id LEFT JOIN user AS u ON u.id=bsk.id_owner WHERE ugbsk.id_usergroup=0 GROUP BY bsk.id""" if sort == 'name': query += """ ORDER BY bsk.name""" elif sort == 'owner': query += """ ORDER BY u.nickname""" elif sort == 'views': query += """ ORDER BY bsk.nb_views""" elif sort == 'date': query += """ ORDER BY bsk.date_modification""" elif sort == 'items': query += """ ORDER BY items""" else: query += """ ORDER BY bsk.name""" if asc: query += """ ASC""" if sort == """owner""": query += """, u.id""" else: query += """ DESC""" if sort == """owner""": query += """, u.id""" query += """ LIMIT %s, %s""" page = max(0, page) res = run_sql(query, (page, max_number)) return res def is_basket_public(bskid): """Check if the given basket is public. Returns ((0,),) if False, ((1,),) if True.""" query = """ SELECT COUNT(*) FROM usergroup_bskBASKET WHERE id_usergroup=0 AND id_bskBASKET=%s""" params = (bskid,) res = run_sql(query, params) return __wash_sql_count(res) def subscribe(uid, bskid): """Subscribe the given user to the given basket.""" query1 = """SELECT COUNT(*) FROM user_bskBASKET WHERE id_user=%s AND id_bskBASKET=%s""" params1 = (uid, bskid) res1 = run_sql(query1, params1) if res1[0][0]: # The user is either the owner of the basket or is already subscribed. return False else: query2 = """INSERT INTO user_bskBASKET (id_user, id_bskBASKET) VALUES (%s, %s)""" params2 = (uid, bskid) run_sql(query2, params2) return True def unsubscribe(uid, bskid): """Unsubscribe the given user from the given basket.""" query1 = """SELECT COUNT(*) FROM bskBASKET WHERE id_owner=%s AND id=%s""" params1 = (uid, bskid) res1 = run_sql(query1, params1) if res1[0][0]: # The user is the owner of the basket. return False else: query2 = """DELETE FROM user_bskBASKET WHERE id_user=%s AND id_bskBASKET=%s""" params2 = (uid, bskid) res2 = run_sql(query2, params2) if res2: return True else: return False def is_user_subscribed_to_basket(uid, bskid): """Return ((1,),) if the user is subscribed to the given basket or ((0,),) if the user is not subscribed or is the owner of the basket.""" query = """ SELECT COUNT(ubsk.id_bskBASKET) FROM user_bskBASKET AS ubsk JOIN bskBASKET AS bsk ON bsk.id=ubsk.id_bskBASKET AND bsk.id_owner!=ubsk.id_user WHERE ubsk.id_user=%s AND ubsk.id_bskBASKET=%s""" params = (uid, bskid) res = run_sql(query, params) return __wash_sql_count(res) def count_subscribers(uid, bskid): """Returns a (number of users, number of groups, number of alerts) tuple for the given user (uid) and basket (bskid).""" uid = int(uid) bskid = int(bskid) query_groups = """ SELECT count(id_usergroup) FROM usergroup_bskBASKET WHERE id_bskBASKET=%s AND NOT(share_level='NO') GROUP BY id_bskBASKET""" params_groups = (bskid,) res_groups = run_sql(query_groups, params_groups) nb_groups = __wash_sql_count(res_groups) query_users = """ SELECT count(id_user) FROM user_bskBASKET WHERE id_bskBASKET=%s AND id_user!=%s GROUP BY id_bskBASKET""" params_users = (bskid, uid) res_users = run_sql(query_users, params_users) nb_users = __wash_sql_count(res_users) query_alerts = """ SELECT count(id_query) FROM user_query_basket WHERE id_basket=%s GROUP BY id_basket""" params_alerts = (bskid,) res_alerts = run_sql(query_alerts, params_alerts) nb_alerts = __wash_sql_count(res_alerts) return (nb_users, nb_groups, nb_alerts) def get_groups_subscribing_to_basket(bskid): """ get list of (group id, group name, rights) tuples for a given basket Please note that group 0 is used to mean everybody. """ query = """SELECT ugb.id_usergroup, ug.name, ugb.share_level FROM usergroup_bskBASKET ugb LEFT JOIN usergroup ug ON ugb.id_usergroup=ug.id WHERE ugb.id_bskBASKET=%s ORDER BY ugb.id_usergroup""" return run_sql(query, (int(bskid),)) def get_rights_on_public_basket(bskid): """""" query = """ SELECT share_level FROM usergroup_bskBASKET WHERE id_usergroup=0 AND id_bskBASKET=%s""" params = (bskid,) res = run_sql(query, params) return res def count_public_basket_subscribers(bskid): """Return the number of users subscribed to the given public basket.""" query = """ SELECT COUNT(ubsk.id_user) FROM user_bskBASKET AS ubsk JOIN bskBASKET AS bsk ON bsk.id=ubsk.id_bskBASKET AND bsk.id_owner!=ubsk.id_user WHERE ubsk.id_bskBASKET=%s""" params = (bskid,) res = run_sql(query, params) return __wash_sql_count(res) ################################ Notes ######################################## def get_notes(bskid, recid): """Return all comments for record recid in basket bskid.""" query = """ SELECT user.id, user.nickname, bskcmt.title, bskcmt.body, DATE_FORMAT(bskcmt.date_creation, '%%Y-%%m-%%d %%H:%%i:%%s'), bskcmt.priority, bskcmt.id, bskcmt.in_reply_to_id_bskRECORDCOMMENT FROM bskRECORDCOMMENT bskcmt LEFT JOIN user ON (bskcmt.id_user=user.id) WHERE bskcmt.id_bskBASKET=%s AND bskcmt.id_bibrec_or_bskEXTREC=%s ORDER BY bskcmt.reply_order_cached_data """ bskid = int(bskid) recid = int(recid) res = run_sql(query, (bskid, recid)) if res: return res else: return () def get_note(cmtid): """Return comment cmtid as a (author's nickname, author's uid, title, body, date of creation, priority) tuple""" out = () query = """ SELECT user.nickname, user.id, bskcmt.title, bskcmt.body, DATE_FORMAT(bskcmt.date_creation, '%%Y-%%m-%%d %%H:%%i:%%s'), bskcmt.priority FROM bskRECORDCOMMENT bskcmt LEFT JOIN user ON (bskcmt.id_user=user.id) WHERE bskcmt.id=%s """ cmtid = int(cmtid) res = run_sql(query, (cmtid,)) if res: return res[0] return out def save_note(uid, bskid, recid, title, body, reply_to=None): """Save then given note (title, body) on the given item in the given basket.""" if reply_to and CFG_WEBBASKET_MAX_COMMENT_THREAD_DEPTH >= 0: # Check that we have not reached max depth note_ancestors = get_note_ancestors(reply_to) if len(note_ancestors) >= CFG_WEBBASKET_MAX_COMMENT_THREAD_DEPTH: if CFG_WEBBASKET_MAX_COMMENT_THREAD_DEPTH == 0: reply_to = None else: reply_to = note_ancestors[CFG_WEBBASKET_MAX_COMMENT_THREAD_DEPTH - 1] date = convert_datestruct_to_datetext(localtime()) res = run_sql("""INSERT INTO bskRECORDCOMMENT (id_user, id_bskBASKET, id_bibrec_or_bskEXTREC, title, body, date_creation, in_reply_to_id_bskRECORDCOMMENT) VALUES (%s, %s, %s, %s, %s, %s, %s)""", (int(uid), int(bskid), int(recid), title, body, date, reply_to or 0)) if res: new_comid = int(res) parent_reply_order = run_sql("""SELECT reply_order_cached_data from bskRECORDCOMMENT where id=%s""", (reply_to,)) if not parent_reply_order or parent_reply_order[0][0] is None: parent_reply_order = '' else: parent_reply_order = parent_reply_order[0][0] run_sql("""UPDATE bskRECORDCOMMENT SET reply_order_cached_data=%s WHERE id=%s""", (parent_reply_order + get_reply_order_cache_data(new_comid), new_comid)) return int(res) return 0 def delete_note(bskid, recid, cmtid): """Delete a comment on an item of a basket""" query = """ DELETE FROM bskRECORDCOMMENT WHERE id_bskBASKET=%s AND id_bibrec_or_bskEXTREC=%s AND id=%s""" params = (int(bskid), int(recid), int(cmtid)) run_sql(query, params) def get_note_ancestors(cmtid, depth=None): """ Returns the list of ancestors of the given note, ordered from oldest to newest ("top-down": direct parent of cmtid is at last position), up to given depth @param cmtid: the ID of the note for which we want to retrieve ancestors @type cmtid: int @param depth: the maximum of levels up from the given note we want to retrieve ancestors. None for no limit, 1 for direct parent only, etc. @type depth: int @return the list of ancestors @rtype: list """ if depth == 0: return [] res = run_sql("SELECT in_reply_to_id_bskRECORDCOMMENT FROM bskRECORDCOMMENT WHERE id=%s", (cmtid,)) if res: parent_cmtid = res[0][0] if parent_cmtid == 0: return [] parent_ancestors = [] if depth: depth -= 1 parent_ancestors = get_note_ancestors(parent_cmtid, depth) parent_ancestors.append(parent_cmtid) return parent_ancestors else: return [] def note_belongs_to_item_in_basket_p(cmtid, recid, bskid): """Returns 1 (True) if the given note (cmtid) belongs to the given item (recid) and the given basket (bskid) or 0 (False).""" query = """ SELECT COUNT(*) FROM bskRECORDCOMMENT WHERE id=%s AND id_bibrec_or_bskEXTREC=%s AND id_bskBASKET=%s""" params = (cmtid, recid, bskid) res = run_sql(query, params) return __wash_sql_count(res) def get_number_of_notes_per_record_in_basket(bskid, recids): """Returns the number of comments per record for all the given records in the given basket""" # We need to convert the list of recids into a string of commma separated # numbers (recids), instead of a tuple, to cover the case where we have # single element lists of recids. Example: # [1] --> '1' instaed of [1] --> (1,) # Single element tuples would cause the query to fail due to the syntax. query = """ SELECT rec.id_bibrec_or_bskEXTREC, COUNT(cmt.id_bibrec_or_bskEXTREC) FROM bskREC as rec LEFT JOIN bskRECORDCOMMENT as cmt ON cmt.id_bibrec_or_bskEXTREC = rec.id_bibrec_or_bskEXTREC WHERE rec.id_bskBASKET=%%s AND rec.id_bibrec_or_bskEXTREC IN (%s) GROUP BY id_bibrec_or_bskEXTREC ORDER BY rec.score""" % (str(map(int, recids))[1:-1],) params = (bskid,) result = run_sql(query, params) return result ########################## Usergroup functions ################################ def get_group_infos(uid): """For each group the user with uid is a member of return the id, name and number of baskets.""" query = """SELECT g.id, g.name, count(ugb.id_bskBASKET) FROM usergroup g LEFT JOIN (user_usergroup ug, usergroup_bskBASKET ugb) ON (g.id=ug.id_usergroup AND g.id=ugb.id_usergroup) WHERE ug.id_user=%s AND NOT(ugb.share_level='NO') AND ug.user_status!=%s GROUP BY g.id ORDER BY g.name""" params = (int(uid), CFG_WEBSESSION_USERGROUP_STATUS['PENDING']) res = run_sql(query, params) return res def count_groups_user_member_of(uid): """Returns the number of groups the user has joined.""" query = """ SELECT COUNT(id_usergroup) FROM user_usergroup WHERE id_user=%s AND user_status!=%s""" params = (int(uid), CFG_WEBSESSION_USERGROUP_STATUS['PENDING']) res = run_sql(query, params) return __wash_sql_count(res) def get_groups_user_member_of(uid): """ Get uids and names of groups user is member of. @param uid: user id (int) @return: a tuple of (group_id, group_name) tuples """ query = """ SELECT g.id, g.name FROM usergroup g JOIN user_usergroup ug ON (g.id=ug.id_usergroup) WHERE ug.id_user=%s and ug.user_status!=%s ORDER BY g.name """ params = (int(uid), CFG_WEBSESSION_USERGROUP_STATUS['PENDING']) res = run_sql(query, params) if res: return res return () ########################## auxilliary functions ############################### def __wash_sql_count(res): """Wash the result of SQL COUNT function and return only an integer.""" if res: return res[0][0] return 0 def __decompress_last(item): """private function, used to shorten code""" item = list(item) item[-1] = decompress(item[-1]) return item def create_pseudo_record(es_title, es_desc, es_url, of="hb"): """Return a pseudo record representation given a title and a description.""" if of == 'hb': record = '\n'.join([es_title, es_desc, es_url]) if of == 'xm': # In case we want to use the controlfield, # the -es_id must be used. #<controlfield tag="001">%s</controlfield> record = """<record> <datafield tag="245" ind1=" " ind2=" "> <subfield code="a">%s</subfield> </datafield> <datafield tag="520" ind1=" " ind2=" "> <subfield code="a">%s</subfield> </datafield> <datafield tag="856" ind1="4" ind2=" "> <subfield code="u">%s</subfield> </datafield> </record>""" % (encode_for_xml(es_title), encode_for_xml(es_desc), encode_for_xml(es_url)) return record def prettify_url(url, char_limit=50, nb_dots=3): """If the url has more characters than char_limit return a shortened version of it keeping the beginning and ending and replacing the rest with dots.""" if len(url) > char_limit: # let's set a minimum character limit if char_limit < 5: char_limit = 5 # let's set a maximum number of dots in relation to the character limit if nb_dots > char_limit/4: nb_dots = char_limit/5 nb_char_url = char_limit - nb_dots nb_char_end = nb_char_url/4 nb_char_beg = nb_char_url - nb_char_end return url[:nb_char_beg] + '.'*nb_dots + url[-nb_char_end:] else: return url diff --git a/modules/webbasket/lib/webbasket_templates.py b/modules/webbasket/lib/webbasket_templates.py index 057723b04..0940ca54c 100644 --- a/modules/webbasket/lib/webbasket_templates.py +++ b/modules/webbasket/lib/webbasket_templates.py @@ -1,4315 +1,4332 @@ ## This file is part of Invenio. ## Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 CERN. ## ## Invenio 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. ## ## Invenio 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """ Templating for webbasket module """ __revision__ = "$Id$" import cgi +import urllib from invenio.messages import gettext_set_language from invenio.webbasket_config import \ CFG_WEBBASKET_CATEGORIES, \ CFG_WEBBASKET_SHARE_LEVELS, \ CFG_WEBBASKET_DIRECTORY_BOX_NUMBER_OF_COLUMNS from invenio.webmessage_mailutils import email_quoted_txt2html, \ email_quote_txt, \ escape_email_quoted_text from invenio.htmlutils import get_html_text_editor from invenio.config import \ CFG_SITE_URL, \ CFG_SITE_SECURE_URL, \ CFG_SITE_LANG, \ CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS, \ CFG_WEBBASKET_USE_RICH_TEXT_EDITOR, \ CFG_SITE_RECORD from invenio.webuser import get_user_info from invenio.dateutils import convert_datetext_to_dategui -from invenio.webbasket_dblayer import get_basket_item_title_and_URL +from invenio.webbasket_dblayer import get_basket_item_title_and_URL, \ + get_basket_ids_and_names from invenio.bibformat import format_record class Template: """Templating class for webbasket module""" ######################## General interface ################################ def tmpl_create_directory_box(self, category, topic, (grpid, group_name), bskid, (personal_info, personal_baskets_info), (group_info, group_baskets_info), public_info, ln): """Template for the directory-like menu. @param category: the selected category @param topic: the selected topic (optional) @param (grpid, groupname): the id and name of the selected group (optional) @param bskid: the id of the selected basket (optional) @param (personal_info, personal_baskets_info): personal baskets data @param (group_info, group_baskets_info): group baskets data @param public_info: public baskets data @param ln: language""" _ = gettext_set_language(ln) def __calculate_prettify_name_char_limit(nb_baskets, max_chars=45, nb_dots=3): """Private function. Calculates the char_limit to be fed to the prettify_name function according to the max_chars limit and the nb_dots.""" # Let's do some initial calculations: D = nb_dots B = nb_baskets M = max_chars # some assisting abbreviations Y = ( B > 3 and 2 or B - 1 ) Z = ( B > 3 and 5 or 0 ) # and the desired result X = ( ( M - Z - ( ( 2 + D ) * Y ) - D ) / ( Y + 1 ) ) return X if not personal_info and not group_info and not public_info: return """ %(no_baskets_label)s <br /><br /> %(create_basket_label)s""" % \ {'no_baskets_label': _('You have no personal or group baskets or are subscribed to any public baskets.'), 'create_basket_label': _('You may want to start by %(x_url_open)screating a new basket%(x_url_close)s.') % \ {'x_url_open': '<a href="%s/yourbaskets/create_basket?ln=%s">' % (CFG_SITE_URL, ln), 'x_url_close': '</a>'}} ## Firstly, create the tabs area. if personal_info: ## If a specific topic is selected display the name of the topic ## and the options on it. if personal_baskets_info: personalbaskets_link = """<a href="%(url)s/yourbaskets/display?category=%(category)s&ln=%(ln)s">%(label)s</a>""" % \ - {'url': CFG_SITE_URL, - 'category': CFG_WEBBASKET_CATEGORIES['PRIVATE'], - 'ln': ln, - 'label': _('Personal baskets')} + {'url': CFG_SITE_URL, + 'category': CFG_WEBBASKET_CATEGORIES['PRIVATE'], + 'ln': ln, + 'label': _('Personal baskets')} topic_link = """<a href="%(url)s/yourbaskets/display?category=%(category)s&topic=%(topic)s&ln=%(ln)s">%(label)s</a>""" % \ {'url': CFG_SITE_URL, 'category': CFG_WEBBASKET_CATEGORIES['PRIVATE'], - 'topic': topic, + 'topic': urllib.quote(topic), 'ln': ln, 'label': cgi.escape(topic, True)} go_back_link = """<a href="%(url)s/yourbaskets/display?ln=%(ln)s"><img src="%(url)s/img/%(img)s" />%(label)s</a>""" % \ {'url': CFG_SITE_URL, 'ln': ln, 'img': 'wb-go-back.png', 'label': _('Back to Your Baskets')} create_basket_link = """<a href="%(url)s/yourbaskets/create_basket?topic=%(topic)s&ln=%(ln)s"><img src="%(url)s/img/%(img)s" />%(label)s</a>""" % \ {'url': CFG_SITE_URL, - 'topic': cgi.escape(topic, True), + 'topic': urllib.quote(topic), 'ln': ln, 'img': 'wb-create-basket.png', 'label': _('Create basket')} edit_topic_link = """<a href="%(url)s/yourbaskets/edit_topic?topic=%(topic)s&ln=%(ln)s"><img src="%(url)s/img/%(img)s" />%(label)s</a>""" % \ {'url': CFG_SITE_URL, - 'topic': cgi.escape(topic, True), + 'topic': urllib.quote(topic), 'ln': ln, 'img': 'wb-edit-topic.png', 'label': _('Edit topic')} personal_tab = """ <td class="bsk_directory_box_nav_tab_content"> %(personalbaskets_link)s > %(topic_link)s </td> <td class="bsk_directory_box_nav_tab_options"> %(go_back)s %(create_basket)s %(edit_topic)s </td>""" % {'topic_link': topic_link, 'personalbaskets_link': personalbaskets_link, 'go_back': go_back_link, 'create_basket': create_basket_link, 'edit_topic': edit_topic_link} ## If no specific topic is selected display the personal baskets tab. else: personal_tab = """ <td class="%(class)s"> <a href="%(url)s/yourbaskets/display?category=%(category)s&ln=%(ln)s">%(label)s</a> </td>""" % {'class': category == CFG_WEBBASKET_CATEGORIES['PRIVATE'] \ and "bsk_directory_box_tab_content_selected" \ or "bsk_directory_box_tab_content", 'url': CFG_SITE_URL, 'category': CFG_WEBBASKET_CATEGORIES['PRIVATE'], 'ln': ln, 'label': _('Personal baskets')} else: personal_tab = """ <td class="%(class)s"> %(label)s </td>""" % {'class': 'bsk_directory_box_tab_content_inactive', 'label': _('Personal baskets')} if group_info: ## If a specific group is selected display the name of the group ## and the options on it. if group_baskets_info: groupbaskets_link = """<a href="%(url)s/yourbaskets/display?category=%(category)s&ln=%(ln)s">%(label)s</a>""" % \ {'url': CFG_SITE_URL, 'category': CFG_WEBBASKET_CATEGORIES['GROUP'], 'ln': ln, 'label': _('Group baskets')} group_link = """<a href="%(url)s/yourbaskets/display?category=%(category)s&group=%(grpid)i&ln=%(ln)s">%(label)s</a>""" % \ {'url': CFG_SITE_URL, 'category': CFG_WEBBASKET_CATEGORIES['GROUP'], 'grpid': grpid, 'ln': ln, - 'label': group_name} + 'label': cgi.escape(group_name, True)} go_back_link = """<a href="%(url)s/yourbaskets/display?ln=%(ln)s"><img src="%(url)s/img/%(img)s" />%(label)s</a>""" % \ {'url': CFG_SITE_URL, 'ln': ln, 'img': 'wb-go-back.png', 'label': _('Back to Your Baskets')} group_tab = """ <td class="bsk_directory_box_nav_tab_content"> %(groupbaskets_link)s > %(group_link)s </td> <td class="bsk_directory_box_nav_tab_options"> %(go_back)s </td>""" % {'groupbaskets_link': groupbaskets_link, 'group_link': group_link, 'go_back': go_back_link} ## If no specific group is selected display the group baskets tab. else: group_tab = """ <td class="%(class)s"> <a href="%(url)s/yourbaskets/display?category=%(category)s&ln=%(ln)s">%(label)s</a> </td>""" % {'class': category == CFG_WEBBASKET_CATEGORIES['GROUP'] \ and "bsk_directory_box_tab_content_selected" \ or "bsk_directory_box_tab_content", 'url': CFG_SITE_URL, 'category': CFG_WEBBASKET_CATEGORIES['GROUP'], 'ln': ln, 'label': _('Group baskets')} else: group_tab = """ <td class="%(class)s"> %(label)s </td>""" % {'class': 'bsk_directory_box_tab_content_inactive', 'label': _('Group baskets')} if public_info: ## Display the public baskets tab. public_tab = """ <td class="%(class)s"> <a href="%(url)s/yourbaskets/display?category=%(category)s&ln=%(ln)s">%(label)s</a> </td>""" % {'class': category == CFG_WEBBASKET_CATEGORIES['EXTERNAL'] \ and "bsk_directory_box_tab_content_selected" \ or "bsk_directory_box_tab_content", 'url': CFG_SITE_URL, 'category': CFG_WEBBASKET_CATEGORIES['EXTERNAL'], 'ln': ln, 'label': _('Public baskets')} else: public_tab = """ <td class="%(class)s"> %(label)s </td>""" % {'class': 'bsk_directory_box_tab_content_inactive', 'label': _('Public baskets')} ## If a specific topic is selected display the name of the topic ## and the options on it. if personal_baskets_info: tabs = """ <table cellspacing="0px" cellpadding="0px" class="bsk_directory_box_tabs"> <tr>%s </tr> </table>""" % (personal_tab,) ## If a specific group is selected display the name of the group ## and the options on it. elif group_baskets_info: tabs = """ <table cellspacing="0px" cellpadding="0px" class="bsk_directory_box_tabs"> <tr> %s </tr> </table>""" % (group_tab,) ## If only a sepcific category is selected (or eveb none) display ## all the available tabs (selected, normal, inactive). else: tabs = """ <table cellspacing="0px" cellpadding="0px" class="bsk_directory_box_tabs"> <tr> <td class="bsk_directory_box_tab_separator"> </td> %(personal_tab)s <td class="bsk_directory_box_tab_separator"> </td> %(group_tab)s <td class="bsk_directory_box_tab_separator"> </td> %(public_tab)s <td class="bsk_directory_box_tab_separator_end"> </td> </tr> </table>""" % {'personal_tab': personal_tab, 'group_tab': group_tab, 'public_tab': public_tab} ## Secondly, create the content. if personal_info and category==CFG_WEBBASKET_CATEGORIES['PRIVATE']: content_list = [] ## If a specific topic is selected create a list of baskets for that topic. if personal_baskets_info: for basket in personal_baskets_info: basket_id = basket[0] basket_name = basket[1] nb_items = basket[4] basket_link = """%(opening_tag)s<a href="%(url)s/yourbaskets/display?category=%(category)s&topic=%(topic)s&bskid=%(bskid)i&ln=%(ln)s" title="%(title_name)s">%(basket_name)s</a>%(closing_tag)s <span class="bsk_directory_box_content_list_number_of">(%(nb_items)i)</span>""" % \ {'opening_tag': basket_id==bskid and "<em>" or "", 'closing_tag': basket_id==bskid and "</em>" or "", 'url': CFG_SITE_URL, 'category': category, - 'topic': cgi.escape(topic, True), + 'topic': urllib.quote(topic), 'bskid': basket_id, 'ln': ln, 'title_name': cgi.escape(basket_name, True), 'basket_name': cgi.escape(prettify_name(basket_name, 27), True), 'nb_items': nb_items} content_list_item = """ %(basket_link)s""" % {'basket_link': basket_link} content_list.append(content_list_item) ## If no specific topic is selected create a list of topics with a preview of their baskets. else: - for topic_and_baskets in personal_info: - topic_name = topic_and_baskets[0] - nb_baskets = topic_and_baskets[1] + for topic_and_bskids in personal_info: + topic_name = topic_and_bskids[0] + bskids = topic_and_bskids[1].split(',') + nb_baskets = len(bskids) topic_link = """<strong><a href="%(url)s/yourbaskets/display?category=%(category)s&topic=%(topic)s&ln=%(ln)s" title="%(title_name)s">%(topic_name)s</a></strong> <span class="bsk_directory_box_content_list_number_of">(%(nb_baskets)s)</span>""" % \ {'url': CFG_SITE_URL, 'category': category, - 'topic': cgi.escape(topic_name, True), + 'topic': urllib.quote(topic_name), 'ln': ln, 'title_name': cgi.escape(topic_name, True), 'topic_name': cgi.escape(prettify_name(topic_name, 25), True), 'nb_baskets': nb_baskets} - baskets = eval(topic_and_baskets[2] + ',') basket_links = "" basket_links_list = [] - for basket in baskets[:3]: - # TODO: adapt the prettify_name char_limit variable according to nb_baskets + #TODO: Not have the number of basket names displayed hardcoded (3 in this case) + bskids_and_names = get_basket_ids_and_names(bskids, 3) + for bskid_and_name in bskids_and_names: + bskid = bskid_and_name[0] + basket_name = bskid_and_name[1] + #TODO: adapt the prettify_name char_limit variable according to nb_baskets basket_link = """<a href="%(url)s/yourbaskets/display?category=%(category)s&topic=%(topic)s&bskid=%(bskid)i&ln=%(ln)s" title="%(title_name)s">%(basket_name)s</a>""" % \ {'url': CFG_SITE_URL, 'category': category, - 'topic': cgi.escape(topic_name, True), - 'bskid': basket[0], + 'topic': urllib.quote(topic_name), + 'bskid': bskid, 'ln': ln, - 'title_name': cgi.escape(basket[1], True), - 'basket_name': cgi.escape(prettify_name(basket[1], __calculate_prettify_name_char_limit(nb_baskets, 135/CFG_WEBBASKET_DIRECTORY_BOX_NUMBER_OF_COLUMNS)), True)} + 'title_name': cgi.escape(basket_name, True), + 'basket_name': cgi.escape(prettify_name(basket_name, __calculate_prettify_name_char_limit(nb_baskets, 135/CFG_WEBBASKET_DIRECTORY_BOX_NUMBER_OF_COLUMNS)), True)} basket_links_list.append(basket_link) basket_links = ', '.join(basket_links_list) if nb_baskets > 3: basket_links += ", ..." content_list_item = """ %(topic_link)s <br /> <small>%(basket_links)s</small>""" % \ {'topic_link': topic_link, 'basket_links': basket_links} content_list.append(content_list_item) nb_cells = CFG_WEBBASKET_DIRECTORY_BOX_NUMBER_OF_COLUMNS nb_items = len(content_list) content_list.reverse() content = """ <table cellspacing="0px" cellpadding="0px" align="center" width="100%"> <tr>""" for i in range(nb_cells): content += """ <td class="bsk_directory_box_content_list_cell" width="%s%%">""" % \ (100/nb_cells,) nb_lines = (nb_items/nb_cells) + ((nb_items%nb_cells) > i and 1 or 0) for j in range(nb_lines): content += content_list.pop() if j < (nb_lines-1): content += personal_baskets_info and "<br />" or "<br /><br />" content += """ </td>""" content += """ </tr> </table>""" elif group_info and category==CFG_WEBBASKET_CATEGORIES['GROUP']: content_list = [] ## If a specific grpid is selected create a list of baskets for that group. if group_baskets_info: for basket in group_baskets_info: basket_id = basket[0] basket_name = basket[1] nb_items = basket[4] basket_link = """%(opening_tag)s<a href="%(url)s/yourbaskets/display?category=%(category)s&group=%(grpid)i&bskid=%(bskid)i&ln=%(ln)s" title="%(title_name)s">%(basket_name)s</a>%(closing_tag)s <span class="bsk_directory_box_content_list_number_of">(%(nb_items)i)</span>""" % \ {'opening_tag': basket_id==bskid and "<em>" or "", 'closing_tag': basket_id==bskid and "</em>" or "", 'url': CFG_SITE_URL, 'category': CFG_WEBBASKET_CATEGORIES['GROUP'], 'grpid': grpid, 'bskid': basket_id, 'ln': ln, 'title_name': cgi.escape(basket_name, True), 'basket_name': cgi.escape(prettify_name(basket_name, 27), True), 'nb_items': nb_items} content_list_item = """ %(basket_link)s""" % {'basket_link': basket_link} content_list.append(content_list_item) ## If no specific grpid is selected create a list of groups with a preview of their baskets. else: - for group_and_baskets in group_info: - group_id = group_and_baskets[0] - group_name = group_and_baskets[1] - nb_baskets = group_and_baskets[2] + for group_and_bskids in group_info: + group_id = group_and_bskids[0] + group_name = group_and_bskids[1] + bskids = group_and_bskids[2].split(',') + nb_baskets = len(bskids) group_link = """<strong><a href="%(url)s/yourbaskets/display?category=%(category)s&group=%(group)i&ln=%(ln)s" title="%(title_name)s">%(group_name)s</a></strong> <span class="bsk_directory_box_content_list_number_of">(%(nb_baskets)s)</span>""" % \ {'url': CFG_SITE_URL, 'category': category, 'group': group_id, 'ln': ln, 'title_name': cgi.escape(group_name, True), 'group_name': cgi.escape(prettify_name(group_name, 25), True), 'nb_baskets': nb_baskets} - baskets = eval(group_and_baskets[3] + ',') basket_links = "" basket_links_list = [] - for basket in baskets[:3]: + #TODO: Not have the number of basket names displayed hardcoded (3 in this case) + bskids_and_names = get_basket_ids_and_names(bskids, 3) + for bskid_and_name in bskids_and_names: + bskid = bskid_and_name[0] + basket_name = bskid_and_name[1] # TODO: adapt the prettify_name char_limit variable according to nb_baskets basket_link = """<a href="%(url)s/yourbaskets/display?category=%(category)s&group=%(group)i&bskid=%(bskid)i&ln=%(ln)s" title="%(title_name)s">%(basket_name)s</a>""" % \ {'url': CFG_SITE_URL, 'category': category, 'group': group_id, - 'bskid': basket[0], + 'bskid': bskid, 'ln': ln, - 'title_name': cgi.escape(basket[1], True), - 'basket_name': cgi.escape(prettify_name(basket[1], __calculate_prettify_name_char_limit(nb_baskets, 135/CFG_WEBBASKET_DIRECTORY_BOX_NUMBER_OF_COLUMNS)), True)} + 'title_name': cgi.escape(basket_name, True), + 'basket_name': cgi.escape(prettify_name(basket_name, __calculate_prettify_name_char_limit(nb_baskets, 135/CFG_WEBBASKET_DIRECTORY_BOX_NUMBER_OF_COLUMNS)), True)} basket_links_list.append(basket_link) basket_links = ', '.join(basket_links_list) if nb_baskets > 3: basket_links += ", ..." content_list_item = """ %(group_link)s <br /> <small>%(basket_links)s</small>""" % \ {'group_link': group_link, 'basket_links': basket_links} content_list.append(content_list_item) nb_cells = CFG_WEBBASKET_DIRECTORY_BOX_NUMBER_OF_COLUMNS nb_items = len(content_list) content_list.reverse() content = """ <table cellspacing="0px" cellpadding="0px" align="center" width="100%"> <tr>""" for i in range(nb_cells): content += """ <td class="bsk_directory_box_content_list_cell" width="%s%%">""" % \ (100/nb_cells,) nb_lines = (nb_items/nb_cells) + ((nb_items%nb_cells) > i and 1 or 0) for j in range(nb_lines): content += content_list.pop() if j < (nb_lines-1): #content += "<br /><br />" content += group_baskets_info and "<br />" or "<br /><br />" content += """ </td>""" content += """ </tr> </table>""" elif public_info and category==CFG_WEBBASKET_CATEGORIES['EXTERNAL']: content_list = [] for basket in public_info: basket_id = basket[0] basket_name = basket[1] nb_items = basket[2] basket_link = """<a href="%(url)s/yourbaskets/display?category=%(category)s&bskid=%(bskid)i&ln=%(ln)s" title="%(title_name)s">%(basket_name)s</a> <span class="bsk_directory_box_content_list_number_of">(%(nb_items)i)</span>""" % \ {'url': CFG_SITE_URL, 'category': category, 'bskid': basket_id, 'ln': ln, 'title_name': cgi.escape(basket_name, True), 'basket_name': cgi.escape(prettify_name(basket_name, 27), True), 'nb_items': nb_items} content_list_item = """ %(basket_link)s""" % {'basket_link': basket_link} content_list.append(content_list_item) nb_cells = CFG_WEBBASKET_DIRECTORY_BOX_NUMBER_OF_COLUMNS nb_items = len(content_list) content_list.reverse() content = """ <table cellspacing="0px" cellpadding="0px" align="center" width="100%"> <tr>""" for i in range(nb_cells): content += """ <td class="bsk_directory_box_content_list_cell" width="%s%%">""" % \ (100/nb_cells,) nb_lines = (nb_items/nb_cells) + ((nb_items%nb_cells) > i and 1 or 0) for j in range(nb_lines): content += content_list.pop() if j < (nb_lines-1): content += "<br />" content += """ </td>""" content += """ </tr> </table>""" out = """ <table cellspacing="0px" cellpadding="0px" class="bsk_directory_box"> <tr> <td width="100%%"> %(tabs)s </td> </tr> <tr> <td width="100%%"> <table cellspacing="0px" cellpadding="0px" class="bsk_directory_box_content"> <tr> <td class="%(class)s"> %(content)s </td> </tr> </table> </td> </tr> </table>""" % {'class': ((category == CFG_WEBBASKET_CATEGORIES['PRIVATE'] and topic) or \ (category == CFG_WEBBASKET_CATEGORIES['GROUP'] and grpid)) and \ "bsk_directory_box_content_list_baskets" or \ "bsk_directory_box_content_list_topics_groups", 'tabs': tabs, 'content': content} return out def tmpl_create_search_box(self, category="", topic="", grpid=0, topic_list=(), group_list=(), number_of_public_baskets=0, p="", n=0, ln=CFG_SITE_LANG): """EXPERIMENTAL UI""" _ = gettext_set_language(ln) action = """%s/yourbaskets/search""" % (CFG_SITE_URL,) select_options = create_search_box_select_options(category, topic, grpid, topic_list, group_list, number_of_public_baskets, ln) out = """ <table cellspacing="0px" cellpadding="5px" class="bsk_search_box"> <form name="search_baskets" action="%(action)s" method="get"> <thead> <tr> <td colspan="4"> <small><strong>%(search_for_label)s:</strong><small> </td> </tr> </thead> <tbody> <tr> <td> <input name="p" value="%(p)s" type="text" /> </td> <td> <small><strong>in</strong><small> </td> <td> <select name="b">%(select_options)s </select> </td> <td> <input class="formbutton" type="submit" value="Search" /> </td> </tr> <tr> <td> <input type="checkbox" name="n" value="1"%(notes_checked)s /> <small>%(notes_label)s</small> </td> </tr> </tbody> <input type="hidden" name="ln" value="%(ln)s" /> </form> </table>""" % {'action': action, 'search_for_label': _('Search baskets for'), 'notes_label': _('Search also in notes (where allowed)'), 'notes_checked': n and ' checked="checked"' or '', 'p': p, 'select_options': select_options, - 'ln': cgi.escape(ln, True)} + 'ln': ln} return out def tmpl_search_results(self, personal_search_results={}, total_no_personal_search_results=0, group_search_results={}, total_no_group_search_results=0, public_search_results={}, total_no_public_search_results=0, all_public_search_results={}, total_no_all_public_search_results=0, ln=CFG_SITE_LANG): """Template for the search results.""" _ = gettext_set_language(ln) out = """ <table cellspacing="0px" cellpadding="5px">""" total_no_search_results = total_no_personal_search_results + \ total_no_group_search_results + \ total_no_public_search_results + \ total_no_all_public_search_results if total_no_search_results: if total_no_search_results != max(total_no_personal_search_results, \ total_no_group_search_results, \ total_no_public_search_results, \ total_no_all_public_search_results): out += """ <tr> <td class="webbasket_search_results_results_overview_cell"> <strong>%(results_overview_label)s:</strong> %(items_found_label)s </td> </tr>""" % {'results_overview_label': _('Results overview'), 'items_found_label': _('%i matching items') % total_no_search_results} if total_no_personal_search_results: out += """ <tr> <td> <a href="#%(personal_baskets_name)s">%(personal_baskets_label)s</a> <span class="webbasket_search_results_number_of_items">(%(items_found)i)</span> </td> </tr>""" % {'personal_baskets_label': _('Personal baskets'), 'personal_baskets_name': "P", 'items_found': total_no_personal_search_results} if total_no_group_search_results: out += """ <tr> <td> <a href="#%(group_baskets_name)s">%(group_baskets_label)s<a/> <span class="webbasket_search_results_number_of_items">(%(items_found)s)</span> </td> </tr>""" % {'group_baskets_label': _('Group baskets'), 'group_baskets_name': "G", 'items_found': total_no_group_search_results} if total_no_public_search_results: out += """ <tr> <td> <a href="#%(public_baskets_name)s">%(public_baskets_label)s</a> <span class="webbasket_search_results_number_of_items">(%(items_found)s)</span> </td> </tr>""" % {'public_baskets_label': _('Public baskets'), 'public_baskets_name': "E", 'items_found': total_no_public_search_results} if total_no_all_public_search_results: out += """ <tr> <td> <a href="#%(all_public_baskets_name)s">%(all_public_baskets_label)s</a> <span class="webbasket_search_results_number_of_items">(%(items_found)s)</span> </td> </tr>""" % {'all_public_baskets_label': _('All public baskets'), 'all_public_baskets_name': "A", 'items_found': total_no_all_public_search_results} out += """ <tr> <td> </td> </tr>""" else: out += """ <tr> <td> %(no_items_found_label)s </td> </tr>""" % {'no_items_found_label': _('No items found.')} ### Search results from the user's personal baskets ### if total_no_personal_search_results: # Print out the header for the personal baskets out += """ <tr> <td class="webbasket_search_results_results_overview_cell"> <a name="%(personal_baskets_name)s"></a><strong>%(personal_baskets_label)s:</strong> %(items_found_label)s </td> </tr>""" % {'personal_baskets_label': _('Personal baskets'), 'personal_baskets_name': "P", 'items_found_label': _('%i matching items') % total_no_personal_search_results} # For every basket print a link to the basket and the number of items # found in that basket for bskid in personal_search_results.keys(): basket_link = """<a href="%(url)s/yourbaskets/display?category=%(category)s&topic=%(topic)s&bskid=%(bskid)i&ln=%(ln)s">%(basket_name)s</a>""" % \ {'url': CFG_SITE_URL, 'category': CFG_WEBBASKET_CATEGORIES['PRIVATE'], - 'topic': cgi.escape(personal_search_results[bskid][1], True), + 'topic': urllib.quote(personal_search_results[bskid][1]), 'bskid': bskid, 'ln': ln, 'basket_name': cgi.escape(personal_search_results[bskid][0], True)} out += """ <tr> <td> %(in_basket_label)s <span class="webbasket_search_results_number_of_items">(%(items_found)i)</span> </td> </tr>""" % {'in_basket_label': _('In %(x_linked_basket_name)s') % \ {'x_linked_basket_name': basket_link}, 'items_found': personal_search_results[bskid][2]} # Print the list of records found in that basket out += """ <tr> <td class="webbasket_search_results_basket"> <ol>""" personal_search_result_records = personal_search_results[bskid][3] for personal_search_result_record in personal_search_result_records: recid = personal_search_result_record[0] number_of_notes = personal_search_result_record[1] record_html = personal_search_result_record[2] # If this a local record print the detailed record link and # the view/add notes link if recid > 0: detailed_record_html = """<a class="moreinfo" href="%(siteurl)s/%(CFG_SITE_RECORD)s/%(recid)i">%(detailed_record_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, 'CFG_SITE_RECORD': CFG_SITE_RECORD, 'recid': recid, 'detailed_record_label': _('Detailed record')} notes_html = """<a class="moreinfo" href="%(siteurl)s/yourbaskets/%(notes_action)s?"""\ """category=P&topic=%(topic)s&bskid=%(bskid)s&recid=%(recid)i"""\ """&ln=%(ln)s%(notes_inline_anchor)s">%(notes_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, - 'topic': personal_search_results[bskid][1], + 'topic': urllib.quote(personal_search_results[bskid][1]), 'bskid' : bskid, 'recid' : recid, 'ln' : ln, 'notes_action': number_of_notes and 'display' or 'write_note', 'notes_inline_anchor': not number_of_notes and '#note' or '', 'notes_label': number_of_notes and _('Notes') + ' (' + str(number_of_notes) + ')' or _('Add a note...')} out += """ <li> %(record_html)s <br /> %(more_info)s </li>""" % \ {'record_html': record_html, 'more_info': """<span class="moreinfo">%(detailed_record_html)s - %(notes_html)s</span>""" % \ {'detailed_record_html': detailed_record_html, 'notes_html': notes_html}} # If this an external record print only the view/add notes link else: notes_html = """<a class="moreinfo" href="%(siteurl)s/yourbaskets/%(notes_action)s?"""\ """category=P&topic=%(topic)s&bskid=%(bskid)s&recid=%(recid)i"""\ """&ln=%(ln)s%(notes_inline_anchor)s">%(notes_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, - 'topic': personal_search_results[bskid][1], + 'topic': urllib.quote(personal_search_results[bskid][1]), 'bskid' : bskid, 'recid' : recid, 'ln' : ln, 'notes_action': number_of_notes and 'display' or 'write_note', 'notes_inline_anchor': not number_of_notes and '#note' or '', 'notes_label': number_of_notes and _('Notes') + ' (' + str(number_of_notes) + ')' or _('Add a note...')} out += """ <li> %(record_html)s <br /> %(more_info)s </li>""" % \ {'record_html': record_html, 'more_info': notes_html} out += """ </ol> </td> </tr>""" out += """ <tr> <td> </td> </tr>""" ### Search results from the user's group baskets ### if total_no_group_search_results: # Print out the header for the group baskets out += """ <tr> <td class="webbasket_search_results_results_overview_cell"> <a name="%(group_baskets_name)s"></a><strong>%(group_baskets_label)s:</strong> %(items_found_label)s </td> </tr>""" % {'group_baskets_label': _('Group baskets'), 'group_baskets_name': "G", 'items_found_label': _('%i matching items') % total_no_group_search_results} # For every basket print a link to the basket and the number of items # found in that basket for bskid in group_search_results.keys(): basket_link = """<a href="%(url)s/yourbaskets/display?category=%(category)s&group=%(grpid)i&bskid=%(bskid)i&ln=%(ln)s">%(basket_name)s</a>""" % \ {'url': CFG_SITE_URL, 'category': CFG_WEBBASKET_CATEGORIES['GROUP'], 'grpid': group_search_results[bskid][1], 'bskid': bskid, 'ln': ln, 'basket_name': cgi.escape(group_search_results[bskid][0], True)} out += """ <tr> <td> %(in_basket_label)s <span class="webbasket_search_results_number_of_items">(%(items_found)i)</span> </td> </tr>""" % {'in_basket_label': _('In %(x_linked_basket_name)s') % \ {'x_linked_basket_name': basket_link}, 'items_found': group_search_results[bskid][4]} # Print the list of records found in that basket out += """ <tr> <td class="webbasket_search_results_basket"> <ol>""" group_search_result_records = group_search_results[bskid][5] (share_rights_view_notes, share_rights_add_notes) = group_search_results[bskid][3] for group_search_result_record in group_search_result_records: recid = group_search_result_record[0] number_of_notes = group_search_result_record[1] record_html = group_search_result_record[2] share_rights_notes = bool(share_rights_view_notes and (number_of_notes or share_rights_add_notes)) # If this a local record print the detailed record link and # the view/add notes link if recid > 0: detailed_record_html = """<a class="moreinfo" href="%(siteurl)s/%(CFG_SITE_RECORD)s/%(recid)i">%(detailed_record_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, 'CFG_SITE_RECORD': CFG_SITE_RECORD, 'recid': recid, 'detailed_record_label': _('Detailed record')} if share_rights_notes: notes_html = """<a class="moreinfo" href="%(siteurl)s/yourbaskets/%(notes_action)s?"""\ """category=G&group=%(grpid)i&bskid=%(bskid)s&recid=%(recid)i"""\ """&ln=%(ln)s%(notes_inline_anchor)s">%(notes_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, 'grpid': group_search_results[bskid][1], 'bskid' : bskid, 'recid' : recid, 'ln' : ln, 'notes_action': number_of_notes and 'display' or 'write_note', 'notes_inline_anchor': not number_of_notes and '#note' or '', 'notes_label': number_of_notes and _('Notes') + ' (' + str(number_of_notes) + ')' or _('Add a note...')} out += """ <li> %(record_html)s <br /> %(more_info)s </li>""" % \ {'record_html': record_html, 'more_info': """<span class="moreinfo">%(detailed_record_html)s%(separator)s%(notes_html)s</span>""" % \ {'detailed_record_html': detailed_record_html, 'separator': share_rights_notes and ' - ' or '', 'notes_html': share_rights_notes and notes_html or ''}} # If this an external record print only the view/add notes link else: if share_rights_notes: notes_html = """<a class="moreinfo" href="%(siteurl)s/yourbaskets/%(notes_action)s?"""\ """category=G&group=%(grpid)i&bskid=%(bskid)s&recid=%(recid)i"""\ """&ln=%(ln)s%(notes_inline_anchor)s">%(notes_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, 'grpid': group_search_results[bskid][1], 'bskid' : bskid, 'recid' : recid, 'ln' : ln, 'notes_action': number_of_notes and 'display' or 'write_note', 'notes_inline_anchor': not number_of_notes and '#note' or '', 'notes_label': number_of_notes and _('Notes') + ' (' + str(number_of_notes) + ')' or _('Add a note...')} out += """ <li> %(record_html)s %(more_info)s </li>""" % \ {'record_html': record_html, 'more_info': share_rights_notes and '<br />' + notes_html or ''} out += """ </ol> </td> </tr>""" out += """ <tr> <td> </td> </tr>""" ### Search results from the user's public baskets ### if total_no_public_search_results: out += """ <tr> <td class="webbasket_search_results_results_overview_cell"> <a name="%(public_baskets_name)s"></a><strong>%(public_baskets_label)s:</strong> %(items_found_label)s </td> </tr>""" % {'public_baskets_label': _('Public baskets'), 'public_baskets_name': "E", 'items_found_label': _('%i matching items') % total_no_public_search_results} for bskid in public_search_results.keys(): basket_link = """<a href="%(url)s/yourbaskets/display?category=%(category)s&bskid=%(bskid)i&ln=%(ln)s">%(basket_name)s</a>""" % \ {'url': CFG_SITE_URL, 'category': CFG_WEBBASKET_CATEGORIES['EXTERNAL'], 'bskid': bskid, 'ln': ln, 'basket_name': cgi.escape(public_search_results[bskid][0], True)} out += """ <tr> <td> %(in_basket_label)s <span class="webbasket_search_results_number_of_items">(%(items_found)i)</span> </td> </tr>""" % {'in_basket_label': _('In %(x_linked_basket_name)s') % \ {'x_linked_basket_name': basket_link}, 'items_found': public_search_results[bskid][2]} # Print the list of records found in that basket out += """ <tr> <td class="webbasket_search_results_basket"> <ol>""" public_search_result_records = public_search_results[bskid][3] (share_rights_view_notes, share_rights_add_notes) = public_search_results[bskid][1] for public_search_result_record in public_search_result_records: recid = public_search_result_record[0] number_of_notes = public_search_result_record[1] record_html = public_search_result_record[2] share_rights_notes = bool(share_rights_view_notes and (number_of_notes or share_rights_add_notes)) # If this a local record print the detailed record link and # the view/add notes link if recid > 0: detailed_record_html = """<a class="moreinfo" href="%(siteurl)s/%(CFG_SITE_RECORD)s/%(recid)i">%(detailed_record_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, 'CFG_SITE_RECORD': CFG_SITE_RECORD, 'recid': recid, 'detailed_record_label': _('Detailed record')} if share_rights_notes: notes_html = """<a class="moreinfo" href="%(siteurl)s/yourbaskets/%(notes_action)s?"""\ """bskid=%(bskid)s&recid=%(recid)i"""\ """&ln=%(ln)s%(notes_inline_anchor)s">%(notes_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, 'bskid' : bskid, 'recid' : recid, 'ln' : ln, 'notes_action': number_of_notes and 'display_public' or 'write_public_note', 'notes_inline_anchor': not number_of_notes and '#note' or '', 'notes_label': number_of_notes and _('Notes') + ' (' + str(number_of_notes) + ')' or _('Add a note...')} out += """ <li> %(record_html)s <br /> %(more_info)s </li>""" % \ {'record_html': record_html, 'more_info': """<span class="moreinfo">%(detailed_record_html)s%(separator)s%(notes_html)s</span>""" % \ {'detailed_record_html': detailed_record_html, 'separator': share_rights_notes and ' - ' or '', 'notes_html': share_rights_notes and notes_html or ''}} # If this an external record print only the view/add notes link else: if share_rights_notes: notes_html = """<a class="moreinfo" href="%(siteurl)s/yourbaskets/%(notes_action)s?"""\ """bskid=%(bskid)s&recid=%(recid)i"""\ """&ln=%(ln)s%(notes_inline_anchor)s">%(notes_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, 'bskid' : bskid, 'recid' : recid, 'ln' : ln, 'notes_action': number_of_notes and 'display_public' or 'write_public_note', 'notes_inline_anchor': not number_of_notes and '#note' or '', 'notes_label': number_of_notes and _('Notes') + ' (' + str(number_of_notes) + ')' or _('Add a note...')} out += """ <li> %(record_html)s %(more_info)s </li>""" % \ {'record_html': record_html, 'more_info': share_rights_notes and '<br />' + notes_html or ''} out += """ </ol> </td> </tr>""" out += """ <tr> <td> </td> </tr>""" ### Search results from all the public baskets ### if total_no_all_public_search_results: out += """ <tr> <td class="webbasket_search_results_results_overview_cell"> <a name="%(all_public_baskets_name)s"></a><strong>%(all_public_baskets_label)s:</strong> %(items_found_label)s </td> </tr>""" % {'all_public_baskets_label': _('All public baskets'), 'all_public_baskets_name': "A", 'items_found_label': _('%i matching items') % total_no_all_public_search_results} for bskid in all_public_search_results.keys(): basket_link = """<a href="%(url)s/yourbaskets/display_public?bskid=%(bskid)i&ln=%(ln)s">%(basket_name)s</a>""" % \ {'url': CFG_SITE_URL, 'bskid': bskid, 'ln': ln, 'basket_name': cgi.escape(all_public_search_results[bskid][0], True)} out += """ <tr> <td> %(in_basket_label)s <span class="webbasket_search_results_number_of_items">(%(items_found)i)</span> </td> </tr>""" % {'in_basket_label': _('In %(x_linked_basket_name)s') % \ {'x_linked_basket_name': basket_link}, 'items_found': all_public_search_results[bskid][2]} # Print the list of records found in that basket out += """ <tr> <td class="webbasket_search_results_basket"> <ol>""" all_public_search_result_records = all_public_search_results[bskid][3] (share_rights_view_notes, share_rights_add_notes) = all_public_search_results[bskid][1] for all_public_search_result_record in all_public_search_result_records: recid = all_public_search_result_record[0] number_of_notes = all_public_search_result_record[1] record_html = all_public_search_result_record[2] share_rights_notes = bool(share_rights_view_notes and (number_of_notes or share_rights_add_notes)) # If this a local record print the detailed record link and # the view/add notes link if recid > 0: detailed_record_html = """<a class="moreinfo" href="%(siteurl)s/%(CFG_SITE_RECORD)s/%(recid)i">%(detailed_record_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, 'CFG_SITE_RECORD': CFG_SITE_RECORD, 'recid': recid, 'detailed_record_label': _('Detailed record')} if share_rights_notes: notes_html = """<a class="moreinfo" href="%(siteurl)s/yourbaskets/%(notes_action)s?"""\ """bskid=%(bskid)s&recid=%(recid)i"""\ """&ln=%(ln)s%(notes_inline_anchor)s">%(notes_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, 'bskid' : bskid, 'recid' : recid, 'ln' : ln, 'notes_action': number_of_notes and 'display_public' or 'write_public_note', 'notes_inline_anchor': not number_of_notes and '#note' or '', 'notes_label': number_of_notes and _('Notes') + ' (' + str(number_of_notes) + ')' or _('Add a note...')} out += """ <li> %(record_html)s <br /> %(more_info)s </li>""" % \ {'record_html': record_html, 'more_info': """<span class="moreinfo">%(detailed_record_html)s%(separator)s%(notes_html)s</span>""" % \ {'detailed_record_html': detailed_record_html, 'separator': share_rights_notes and ' - ' or '', 'notes_html': share_rights_notes and notes_html or ''}} # If this an external record print only the view/add notes link else: if share_rights_notes: notes_html = """<a class="moreinfo" href="%(siteurl)s/yourbaskets/%(notes_action)s?"""\ """bskid=%(bskid)s&recid=%(recid)i"""\ """&ln=%(ln)s%(notes_inline_anchor)s">%(notes_label)s</a>""" % \ {'siteurl': CFG_SITE_URL, 'bskid' : bskid, 'recid' : recid, 'ln' : ln, 'notes_action': number_of_notes and 'display_public' or 'write_public_note', 'notes_inline_anchor': not number_of_notes and '#note' or '', 'notes_label': number_of_notes and _('Notes') + ' (' + str(number_of_notes) + ')' or _('Add a note...')} out += """ <li> %(record_html)s %(more_info)s </li>""" % \ {'record_html': record_html, 'more_info': share_rights_notes and '<br />' + notes_html or ''} out += """ </ol> </td> </tr>""" out += """ <tr> <td> </td> </tr>""" out += """ </table>""" return out def tmpl_display(self, directory='', content='', search_box='', search_results=''): """Template for the generic display. @param directory: the directory-like menu (optional) @param content: content (of a basket) (optional) @param search_box: the search form (optional) @param search_results: the search results (optional)""" display_items = [] if directory: container_directory = """ <div id="bskcontainerdirectory">%s </div> """ % (directory,) display_items.append(container_directory) if content: container_content = """ <div id="bskcontainercontent">%s </div> """ % (content,) display_items.append(container_content) if search_box: container_search_box = """ <div id="webbasket_container_search_box">%s </div> """ % (search_box,) display_items.append(container_search_box) if search_results: container_search_results = """ <div id="webbasket_container_search_results">%s </div> """ % (search_results,) display_items.append(container_search_results) display_separator= """ <div height="10px"> </div> """ display = display_separator.join(display_items) out = """ <div id="bskcontainer"> %s </div>""" % (display,) return out def tmpl_display_list_public_baskets(self, all_public_baskets, limit, number_of_all_public_baskets, sort, asc, nb_views_show_p=False, ln=CFG_SITE_LANG): """Template for the list of public baskets. @param all_public_baskets: tuple (bskid, basket_name, owner_id, nickname, date_modification, nb_views, nb_items) @param limit: display baskets from the incrementally numbered 'limit' and on @param number_of_all_public_baskets: the number of all the public baskets @param sort: 'name': sort by basket name 'views': sort by number of basket views 'nickname': sort by user nickname 'date': sort by basket modification date 'items': sort by number of basket items @param asc: ascending sort or not @param nb_views_show_p: show the views column or not @param ln: language""" _ = gettext_set_language(ln) basket_name_label = _("Public basket") owner_label = _("Owner") date_modification_label = _("Last update") nb_items_label = _("Items") nb_views_label = _("Views") if sort == "name": if asc: basket_name_sort_img = """<img src="%s/img/wb-sort-asc.gif" />""" % (CFG_SITE_URL,) else: basket_name_sort_img = """<img src="%s/img/wb-sort-desc.gif" />""" % (CFG_SITE_URL,) else: basket_name_sort_img = """<img src="%s/img/wb-sort-none.gif" />""" % (CFG_SITE_URL,) if sort == "owner": if asc: owner_sort_img = """<img src="%s/img/wb-sort-asc.gif" />""" % (CFG_SITE_URL,) else: owner_sort_img = """<img src="%s/img/wb-sort-desc.gif" />""" % (CFG_SITE_URL,) else: owner_sort_img = """<img src="%s/img/wb-sort-none.gif" />""" % (CFG_SITE_URL,) if sort == "date": if asc: date_modification_sort_img = """<img src="%s/img/wb-sort-asc.gif" />""" % (CFG_SITE_URL,) else: date_modification_sort_img = """<img src="%s/img/wb-sort-desc.gif" />""" % (CFG_SITE_URL,) else: date_modification_sort_img = """<img src="%s/img/wb-sort-none.gif" />""" % (CFG_SITE_URL,) if sort == "items": if asc: nb_items_sort_img = """<img src="%s/img/wb-sort-asc.gif" />""" % (CFG_SITE_URL,) else: nb_items_sort_img = """<img src="%s/img/wb-sort-desc.gif" />""" % (CFG_SITE_URL,) else: nb_items_sort_img = """<img src="%s/img/wb-sort-none.gif" />""" % (CFG_SITE_URL,) if sort == "views": if asc: nb_views_sort_img = """<img src="%s/img/wb-sort-asc.gif" />""" % (CFG_SITE_URL,) else: nb_views_sort_img = """<img src="%s/img/wb-sort-desc.gif" />""" % (CFG_SITE_URL,) else: nb_views_sort_img = """<img src="%s/img/wb-sort-none.gif" />""" % (CFG_SITE_URL,) basket_name_sort = """<a href="%s/yourbaskets/list_public_baskets?limit=%i&sort=name&asc=%i&ln=%s">%s</a>""" % \ (CFG_SITE_URL, limit, not(asc), ln, basket_name_sort_img) owner_sort = """<a href="%s/yourbaskets/list_public_baskets?limit=%i&sort=owner&asc=%i&ln=%s">%s</a>""" % \ (CFG_SITE_URL, limit, not(asc), ln, owner_sort_img) date_modification_sort = """<a href="%s/yourbaskets/list_public_baskets?limit=%i&sort=date&asc=%i&ln=%s">%s</a>""" % \ (CFG_SITE_URL, limit, not(asc), ln, date_modification_sort_img) nb_items_sort = """<a href="%s/yourbaskets/list_public_baskets?limit=%i&sort=items&asc=%i&ln=%s">%s</a>""" % \ (CFG_SITE_URL, limit, not(asc), ln, nb_items_sort_img) nb_views_sort = """<a href="%s/yourbaskets/list_public_baskets?limit=%i&sort=views&asc=%i&ln=%s">%s</a>""" % \ (CFG_SITE_URL, limit, not(asc), ln, nb_views_sort_img) baskets_html = '' for (bskid, basket_name, owner_id, nickname, date_modification, nb_items, nb_views) in all_public_baskets: if nickname: display = nickname else: (owner_id, nickname, display) = get_user_info(owner_id) webmessage_link = self.__create_webmessage_link(nickname, display, ln) basket_link = """<a href="%s/yourbaskets/display_public?category=%s&bskid=%s&ln=%s">%s<a/>""" % \ (CFG_SITE_URL, CFG_WEBBASKET_CATEGORIES['EXTERNAL'], bskid, ln, cgi.escape(basket_name, True)) nb_views_td = """<td class="bsk_list_public_baskets_basket_right">%i</td>""" % (nb_views,) baskets_html += """ <tr> <td class="bsk_list_public_baskets_basket_left">%(basket_link)s</td> <td class="bsk_list_public_baskets_basket_left">%(webmessage_link)s</td> <td class="bsk_list_public_baskets_basket_left">%(date_modification)s</td> <td class="bsk_list_public_baskets_basket_right">%(nb_items)i</td> %(nb_views)s </tr>""" % {'basket_link': basket_link, 'webmessage_link': webmessage_link, 'date_modification': date_modification, 'nb_items': nb_items, 'nb_views': nb_views_show_p and nb_views_td or ''} if not all_public_baskets: baskets_html = """ <tr> <td colspan="%i"> %s </td> </tr>""" % (nb_views_show_p and 5 or 4, _("There is currently no publicly accessible basket")) footer = '' if limit > CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS: limit_first = 1 page_first = """<a href="%s/yourbaskets/list_public_baskets?limit=%i&sort=%s&asc=%i&ln=%s"><img src="%s" /></a>""" % \ (CFG_SITE_URL, limit_first, sort, asc, ln, '/img/sb.gif') footer += page_first if limit > 0: limit_previous = limit > CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS \ and limit - CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS + 1 \ or 1 page_previous = """<a href="%s/yourbaskets/list_public_baskets?limit=%i&sort=%s&asc=%i&ln=%s"><img src="%s" /></a>""" % \ (CFG_SITE_URL, limit_previous, sort, asc, ln, '/img/sp.gif') footer += page_previous display_from = limit + 1 display_to = limit + CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS > number_of_all_public_baskets \ and number_of_all_public_baskets \ or limit + CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS footer += _('Displaying public baskets %(x_from)i - %(x_to)i out of %(x_total_public_basket)i public baskets in total.') % \ {'x_from': display_from, 'x_to': display_to, 'x_total_public_basket': number_of_all_public_baskets} if limit < number_of_all_public_baskets - CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS: limit_next = limit + CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS + 1 page_next = """<a href="%s/yourbaskets/list_public_baskets?limit=%i&sort=%s&asc=%i&ln=%s"><img src="%s" /></a>""" % \ (CFG_SITE_URL, limit_next, sort, asc, ln, '/img/sn.gif') footer += page_next if limit < number_of_all_public_baskets - ( 2 * CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS ): limit_last = number_of_all_public_baskets - CFG_WEBBASKET_MAX_NUMBER_OF_DISPLAYED_BASKETS + 1 page_last = """<a href="%s/yourbaskets/list_public_baskets?limit=%i&sort=%s&asc=%i&ln=%s"><img src="%s" /></a>""" % \ (CFG_SITE_URL, limit_last, sort, asc, ln, '/img/se.gif') footer += page_last if nb_views_show_p: nb_views_label_td = """<td>%(nb_views_label)s %(nb_views_sort)s</td>""" % \ {'nb_views_label': nb_views_label, 'nb_views_sort': nb_views_sort} out = """ <table class="bsk_list_public_baskets" cellpadding="5px"> <thead class="bsk_list_public_baskets_header"> <tr> <td>%(basket_name_label)s %(basket_name_sort)s</td> <td>%(owner_label)s %(owner_sort)s</td> <td>%(date_modification_label)s %(date_modification_sort)s</td> <td>%(nb_items_label)s %(nb_items_sort)s</td> %(nb_views_label_td)s </tr> </thead> <tfoot class="bsk_list_public_baskets_footer"> <tr> <td colspan="%(colspan)s" style="text-align:center">%(footer)s</td> </tr> </tfoot> <tbody> %(baskets)s </tbody> </table>""" % {'basket_name_label': basket_name_label, 'basket_name_sort': basket_name_sort, 'owner_label': owner_label, 'owner_sort': owner_sort, 'date_modification_label': date_modification_label, 'date_modification_sort': date_modification_sort, 'nb_items_label': nb_items_label, 'nb_items_sort': nb_items_sort, 'nb_views_label_td': nb_views_show_p and nb_views_label_td or '', 'colspan': nb_views_show_p and 5 or 4, 'footer': footer, 'baskets': baskets_html} return out def tmpl_quote_comment_textual(self, title, uid, nickname, date, body, ln=CFG_SITE_LANG): """Return a comment in a quoted form (i.e. with '>' signs before each line) @param title: title of comment to quote @param uid: user id of user who posted comment to quote @param nickname: nickname of user who posted comment to quote @param date: date of post of comment to quote @param body: body of comment to quote @param ln: language""" _ = gettext_set_language(ln) if not(nickname): nickname = get_user_info(uid)[2] if title: msg = _("%(x_title)s, by %(x_name)s on %(x_date)s:") % \ {'x_title': title, 'x_name': nickname, 'x_date': date} else: msg = _("%(x_name)s wrote on %(x_date)s:") % {'x_name': nickname, 'x_date': date} msg += '\n\n' msg += body return email_quote_txt(msg) def tmpl_quote_comment_html(self, title, uid, nickname, date, body, ln=CFG_SITE_LANG): """Return a comment in a quoted form (i.e. indented using HTML table) for HTML output (i.e. in CKEditor). @param title: title of comment to quote @param uid: user id of user who posted comment to quote @param nickname: nickname of user who posted comment to quote @param date: date of post of comment to quote @param body: body of comment to quote @param ln: language""" _ = gettext_set_language(ln) if not(nickname): nickname = get_user_info(uid)[2] if title: msg = _("%(x_title)s, by %(x_name)s on %(x_date)s:") % \ {'x_title': title, 'x_name': nickname, 'x_date': date} else: msg = _("%(x_name)s wrote on %(x_date)s:") % {'x_name': nickname, 'x_date': date} msg += '<br/><br/>' msg += body msg = email_quote_txt(text=msg) msg = email_quoted_txt2html(text=msg) return '<br/>' + msg + '<br/>' def __tmpl_basket_box(self, img='', title=' ', subtitle=' ', body=''): """ private function, display a basket/topic selection box """ out = """ <table class="bskbasket"> <thead class="bskbasketheader"> <tr> <td class="bskactions"> <img src="%(logo)s" alt="%(label)s" /> </td> <td class="bsktitle"> <b>%(label)s</b><br /> %(count)s </td> </tr> </thead> <tbody> <tr> <td colspan="2"> <table>%(basket_list)s </table> </td> </tr> </tbody> </table>""" out %= {'logo': img, 'label': title, 'count': subtitle, 'basket_list': body} return out def tmpl_create_box(self, new_basket_name='', new_topic_name='', topics=[], selected_topic="", ln=CFG_SITE_LANG): """Display a HTML box for creation of a new basket @param new_basket_name: prefilled value (string) @param new_topic_name: prefilled value (string) @param topics: list of topics (list of strings) @param selected_topic: preselected value for topic selection @param ln: language""" _ = gettext_set_language(ln) topics_html = '' #if selected_topic: # try: # selected_topic = topics.index(selected_topic) # except: # selected_topic = None if topics: topics = zip(topics, topics) topics.insert(0, (-1, _("Select topic"))) topics_html = self.__create_select_menu('create_in_topic', topics, selected_topic) create_html = """ <tr> <td style="padding: 10 5 0 5;">%s</td> <td style="padding: 10 5 0 0;">%s</td> </tr> <tr> <td style="padding: 10 5 0 5;">%s</td> <td style="padding: 10 5 0 0;"><input type="text" name="new_topic_name" value="%s"/></td> </tr> <tr> <td style="padding: 10 5 0 5;">%s</td> <td style="padding: 10 5 0 0;"> <input type="text" name="new_basket_name" value="%s"/> </td> -</tr>""" % (topics_html != '' and _("Choose topic") or '', topics_html, - topics_html != '' and _("or create a new one") or _("Create new topic"), new_topic_name, - _("Basket name"), new_basket_name,) +</tr>""" % (topics_html != '' and _("Choose topic") or '', + topics_html, + topics_html != '' and _("or create a new one") or _("Create new topic"), + cgi.escape(new_topic_name, True), + _("Basket name"), + cgi.escape(new_basket_name, True)) return self.__tmpl_basket_box(img=CFG_SITE_URL + '/img/webbasket_create.png', title=_("Create a new basket"), body=create_html) def tmpl_create_basket(self, new_basket_name='', new_topic_name='', create_in_topic=None, topics=[], recids=[], colid=-1, es_title='', es_desc='', es_url='', ln=CFG_SITE_LANG): """Template for basket creation @param new_basket_name: prefilled value (string) @param new_topic_name: prefilled value (string) @param topics: list of topics (list of strings) @param create_in_topic: preselected value for topic selection @param ln: language""" _ = gettext_set_language(ln) out = """ <form name="create_basket" action="%(action)s" method="post"> <input type="hidden" name="ln" value="%(ln)s" /> <div style="padding:10px;"> %(create_box)s %(recids)s %(es_title)s %(es_desc)s %(es_url)s <input type="hidden" name="colid" value="%(colid)s" /> <input type="submit" value="%(label)s" class="formbutton"/> </div> </form>""" % {'action': CFG_SITE_URL + '/yourbaskets/create_basket', 'ln': ln, 'create_box': self.tmpl_create_box(new_basket_name=new_basket_name, new_topic_name=new_topic_name, topics=topics, selected_topic=create_in_topic, ln=ln), 'recids': recids and '\n'.join(['<input type="hidden" name="recid" value="%s" />' % \ recid for recid in recids]) or '', 'es_title': es_title and \ '<input type="hidden" name="es_title" value="%s" />' % \ - (es_title,) or '', + (cgi.escape(es_title, True),) or '', 'es_desc': es_desc and \ '<input type="hidden" name="es_desc" value="%s" />' % \ - (es_desc,) or '', + (cgi.escape(es_desc, True),) or '', 'es_url': es_url and \ '<input type="hidden" name="es_url" value="%s" />' % \ - (es_url,) or '', + (cgi.escape(es_url, True),) or '', 'colid': colid, 'label': _("Create new basket")} return out ############################ external sources ########################### def tmpl_external_source_add_box(self, title="", desc="", url="", ln=CFG_SITE_LANG): """Template for adding external items.""" _ = gettext_set_language(ln) # Instead of the rich editor we choose to use everytime a simple textarea # because a rich text editor may already be used in the add to baskets # page to anotate. #desc_editor = get_html_text_editor(name="es_desc", # content=desc, # textual_content=desc, # width="640px", # height="100px", # enabled=CFG_WEBBASKET_USE_RICH_TEXT_EDITOR, # toolbar_set="WebComment") desc_editor = """<textarea name="es_desc" style="width: 640px; height: 100px;">%(value)s</textarea>""" % \ - {'value': desc} + {'value': cgi.escape(desc, True)} out = """ <table class="bskbasket" width="100%%"> <thead> <tr> <td class="bskbasketheader"> <table> <tr> <td class="bskbasketheadertitle"> <strong> %(header_label)s </strong> </td> </table> </td> </tr> </thead> <tbody> <tr> <td style="padding: 10px;"> %(instructions_label)s: </td> </tr> <tr> <td style="padding: 10px;"> <p align="left"> <small>%(title_label)s:</small> <br /> <input type="text" name="es_title" size="65" value="%(es_title)s" /> </p> <p align="left"> <small>%(desc_label)s:</small> <br /> %(desc_editor)s </p> <p align="left"> <small>%(url_label)s:</small> <br /> <input type="text" name="es_url" size="65" value="%(es_url)s" /> <input type="hidden" name="colid" value="-1" /> </p> </td> </tr> </tbody> </table>""" % {'header_label': _('External item'), 'instructions_label': _('Provide a url for the external item you wish to add and fill in a title and description'), 'title_label': _('Title'), - 'es_title': title, + 'es_title': cgi.escape(title, True), 'desc_label': _('Description'), 'desc_editor': desc_editor, 'url_label': _('URL'), - 'es_url': url} + 'es_url': cgi.escape(url, True)} return out ########################## functions on baskets ######################### def tmpl_add(self, recids=[], category="", bskid=0, colid=0, es_title="", es_desc="", es_url="", note_body="", personal_basket_list=(), group_basket_list=(), successful_add=False, copy=False, referer='', ln=CFG_SITE_LANG): """Template for addding items to baskets.""" _ = gettext_set_language(ln) if successful_add: out = """ %(success_label)s. <br /><br /> %(proceed_label)s""" % {'success_label': _('%i items have been successfully added to your basket') % (colid == -1 and 1 or len(recids)), 'proceed_label': _('Proceed to the %(x_url_open)sbasket%(x_url_close)s') % \ {'x_url_open': '<a href="%s/yourbaskets/display?category=%s&bskid=%i&ln=%s">' % (CFG_SITE_URL, category, bskid, ln), 'x_url_close': "</a>"}} if referer: if copy: out += _(' or return to your %(x_url_open)sprevious basket%(x_url_close)s') % \ {'x_url_open': '<a href="%s">' % referer, 'x_url_close': '</a>'} else: out += _(' or return to your %(x_url_open)ssearch%(x_url_close)s') % \ {'x_url_open': '<a href="%s">' % referer, 'x_url_close': '</a>'} else: out += "." return out out="" #If no recids were specified the page is asking which external item to add, #so we remind to the user to use the search engine for internal items. #(having no recids specified is just like having a colid equal -1) if len(recids) == 0: #if colid == -1: out += """ <table class="bskbasket"> <thead class="bskbasketheader"> <tr> <td class="bskactions"> <img src="%(logo)s" alt="%(label)s" /> </td> <td class="bsktitle"> <b>Adding items to your basket</b><br /> </td> </tr> </thead> <tbody> <tr> <td colspan="2"> <table> To add internal items to your basket please select them through the <a href="%(search_link)s">search page</a> and use the "Add to basket" functionality. For any external resource please use the "External item" form below. </table> </td> </tr> </tbody> </table>""" out %= {'logo': "%s/img/tick.gif"% (CFG_SITE_URL,), 'label':"tick", 'search_link':"%s"%(CFG_SITE_URL,) } note_editor = get_html_text_editor(name="note_body", content=note_body, textual_content=note_body, width="600px", height="110px", enabled=CFG_WEBBASKET_USE_RICH_TEXT_EDITOR, toolbar_set="WebComment") select_options = create_add_box_select_options(category, bskid, personal_basket_list, group_basket_list, ln) hidden_recids = "" for recid in recids: hidden_recids += """ <input type="hidden" name="recid" value="%s" />""" % (recid,) action = "%s/yourbaskets/add" % (CFG_SITE_URL,) out += """ <form name="add_to_basket" action="%(action)s" method="post">""" % {'action': action} if colid == -1: out += self.tmpl_external_source_add_box(es_title, es_desc, es_url, ln) out += """ <table class="bskbasket" width="100%%"> <thead> <tr> <td class="bskbasketheader"> <table> <tr> <td class="bskbasketheadertitle"> <strong> %(header_label)s </strong> </td> </table> </td> </tr> </thead> <tbody> <tr> <td style="padding: 10px;"> %(create_new_basket)s <br /> </td> </tr> <tr> <td style="padding: 10px;"> <p align="left"> <small>%(note_label)s:</small> <br /> %(note_editor)s </p> </td> </tr> <tr> <td style="padding: 10px;"> %(hidden_recids)s <input type="hidden" name="colid" value="%(colid)s" /> <input type="hidden" name="copy" value="%(copy)i" /> <input type="hidden" name="referer" value="%(referer)s" /> <input type="submit" class="formbutton" value="%(add_label)s" /> <input type="button" class="nonsubmitbutton" value="%(cancel_label)s" onClick="window.location='/'" /> </td> </tr> </tbody> </table>""" % {'header_label': _("Adding %i items to your baskets") % (colid == -1 and 1 or len(recids)), 'create_new_basket': _("Please choose a basket: %(x_basket_selection_box)s %(x_fmt_open)s(or %(x_url_open)screate a new one%(x_url_close)s first)%(x_fmt_close)s") % \ {'x_basket_selection_box': ' <select name="b">%s</select>' % select_options, 'x_url_open': colid == -1 and ('''<a href="%s/yourbaskets/create_basket?colid=-1" onClick="this.href+= \ - '&es_title=' + encodeURIComponent(document.add_to_basket.es_title.value) + \ - '&es_url=' + encodeURIComponent(document.add_to_basket.es_url.value) + \ - '&es_desc=' + encodeURIComponent(document.add_to_basket.es_desc.value);">''' % \ + '&es_title=' + encodeURIComponent(document.add_to_basket.es_title.value) + \ + '&es_url=' + encodeURIComponent(document.add_to_basket.es_url.value) + \ + '&es_desc=' + encodeURIComponent(document.add_to_basket.es_desc.value);">''' % \ (CFG_SITE_URL,)) - or ('<a href="%s/yourbaskets/create_basket?colid=%i&recid=%s">' % \ + or ('<a href="%s/yourbaskets/create_basket?colid=%i&recid=%s">' % \ (CFG_SITE_URL, colid, - '&recid='.join(str(recid) for recid in recids))), + '&recid='.join(str(recid) for recid in recids))), 'x_url_close': '</a>', 'x_fmt_open': '<br /><small>', 'x_fmt_close': '</small>'}, 'note_label': len(recids) > 1 and _('Optionally, add a note to each one of these items') \ or _('Optionally, add a note to this item'), 'note_editor': note_editor, 'hidden_recids': hidden_recids, 'colid': colid, 'copy': copy and 1 or 0, 'referer': referer, 'add_label': _('Add items'), 'cancel_label': _('Cancel')} out += """ </form>""" return out def tmpl_confirm_delete(self, bskid, (nb_users, nb_groups, nb_alerts), category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group_id=0, ln=CFG_SITE_LANG): """ display a confirm message @param bskid: basket id @param nb*: nb of users/groups/alerts linked to this basket @param category: private, group or external baskets are selected @param selected_topic: if private baskets, topic nb @param selected_group_id: if group: group to display baskets of @param ln: language @return: html output """ _ = gettext_set_language(ln) message = _("Are you sure you want to delete this basket?") if nb_users: message += '<p>' + _("%i users are subscribed to this basket.")% nb_users + '</p>' if nb_groups: message += '<p>' + _("%i user groups are subscribed to this basket.")% nb_groups + '</p>' if nb_alerts: message += '<p>' + _("You have set %i alerts on this basket.")% nb_alerts + '</p>' out = """ <table class="confirmoperation"> <tr> <td colspan="2" class="confirmmessage"> %(message)s </td> </tr> <tr> <td> <form name="validate" action="%(url_ok)s" method="post"> <input type="hidden" name="confirmed" value="1" /> <input type="hidden" name="category" value="%(category)s" /> <input type="hidden" name="group" value="%(group)i" /> <input type="hidden" name="topic" value="%(topic)s" /> <input type="hidden" name="ln" value="%(ln)s" /> <input type="hidden" name="bskid" value="%(bskid)i" /> <input type="submit" value="%(yes_label)s" class="formbutton" /> </form> </td> <td> <form name="cancel" action="%(url_cancel)s" method="get"> <input type="hidden" name="category" value="%(category)s" /> <input type="hidden" name="group" value="%(group)i" /> <input type="hidden" name="topic" value="%(topic)s" /> <input type="hidden" name="ln" value="%(ln)s" /> <input type="submit" value="%(no_label)s" class="formbutton" /> </form> </td> </tr> -</table>"""% {'message': message, +</table>"""% {'message': cgi.escape(message, True), 'bskid': bskid, 'url_ok': 'delete', 'url_cancel': 'display', 'category': category, - 'topic': selected_topic, + 'topic': cgi.escape(selected_topic, True), 'group': selected_group_id, 'ln':ln, 'yes_label': _("Yes"), 'no_label': _("Cancel")} return out def tmpl_edit(self, bskid, bsk_name, topic, topics, groups_rights, external_rights, display_general=0, display_sharing=0, display_delete=0, ln=CFG_SITE_LANG): """Display interface for rights management over the given basket @param group_rights: list of (group id, name, rights) tuples @param external_rights: rights as defined in CFG_WEBBASKET_SHARE_LEVELS for public access. @param display_general: display fields name and topic, used with personal baskets @param display_sharing: display sharing possibilities @param display_delete: display delete basket button """ _ = gettext_set_language(ln) general_body = '' if display_general: general_body = """ <tr> <td class="bskcontentcol">%s</td> <td class="bskcontentcol"><input type="text" name="new_name" value="%s"/></td> -</tr>""" % (_("Basket name"), cgi.escape(bsk_name, 1)) +</tr>""" % (_("Basket name"), cgi.escape(bsk_name, True)) #topics_selection = zip(range(len(topics)), topics) topics_selection = zip(topics, topics) topics_selection.insert(0, (-1, _("Choose topic"))) topics_body = """ <tr> <td style="padding: 10 5 0 5;">%s</td> <td style="padding: 10 5 0 0;">%s</td> </tr> <tr> <td style="padding: 0 5 10 5;">%s</td> <td style="padding: 0 5 10 0;"><input type="text" name="new_topic_name" /> </tr>""" % (_("Choose topic"), self.__create_select_menu('new_topic', topics_selection, topic), _("or create a new one")) general_body += topics_body general_box = self.__tmpl_basket_box(img=CFG_SITE_URL + '/img/webbasket_user.png', title=_("General settings"), body = general_body) groups_body = '' if display_sharing: for (group_id, name, rights) in groups_rights: groups_body += """ <tr> <td>%s</td> <td>%s</td> </tr>""" % (name, self.__create_group_rights_selection_menu(group_id, rights, ln)) groups_body += """ <tr> <td colspan="2"> <input type="submit" name="add_group" class="nonsubmitbutton" value="%s"/> </td> </tr>""" % _("Add group") else: groups_body = '<tr><td colspan="2">%s</td></tr>' groups_body %= self.tmpl_create_guest_forbidden_box(ln) groups_box = self.__tmpl_basket_box(img=CFG_SITE_URL + '/img/webbasket_usergroup.png', title=_("Manage group rights"), body=groups_body) if display_sharing: external_body = """ <tr> <td>%s</td> </tr>""" % self.__create_rights_selection_menu('external', external_rights, ln) else: external_body = '<tr><td colspan="2">%s</td></tr>' external_body %= self.tmpl_create_guest_forbidden_box(ln) external_box = self.__tmpl_basket_box(img=CFG_SITE_URL + '/img/webbasket_world.png', title=_("Manage global sharing rights"), body=external_body) delete_button = '' if display_delete: delete_button = '<input type="submit" class="nonsubmitbutton" name="delete" value="%s" />' delete_button %= _("Delete basket") out = """ <form name="edit" action="%(action)s" method="post"> <p>%(label)s</p> <input type="hidden" name="ln" value="%(ln)s" /> <input type="hidden" name="bskid" value="%(bskid)i" /> <input type="hidden" name="topic" value ="%(topic)s" /> <table> <tr> <td colspan="3">%(general)s</td> </tr> <tr> <td colspan="3">%(groups)s</td> </tr> <tr> <td colspan="3">%(external)s</td> </tr> <tr> <td><input type="submit" class="formbutton" name="submit" value="%(submit_label)s" /></td> <td><input type="submit" class="nonsubmitbutton" name="cancel" value="%(cancel_label)s" /></td> <td>%(delete_button)s</td> </tr> </table> </form>""" % {'label': _('Editing basket %(x_basket_name)s') % \ - {'x_basket_name': cgi.escape(bsk_name)}, + {'x_basket_name': cgi.escape(bsk_name, True)}, 'action': CFG_SITE_URL + '/yourbaskets/edit', 'ln': ln, - 'topic': topic, + 'topic': cgi.escape(topic, True), 'bskid': bskid, 'general': general_box, 'groups': groups_box, 'external': external_box, 'submit_label': _("Save changes"), 'cancel_label': _("Cancel"), 'delete_button': delete_button} return out def tmpl_edit_topic(self, topic, display_general=0, display_delete=0, ln=CFG_SITE_LANG): """Display interface for topic editing. @param display_general: display topic name @param display_delete: display delete topic button """ _ = gettext_set_language(ln) general_body = '' if not topic: general_body = """<div class="important" style="padding: 10px;">%s</div>""" general_body %= ("You must provide a valid topic name.",) display_general = False if display_general: general_body = """ <tr> <td>%s</td> <td><input type="text" name="new_name" value="%s"/></td> </tr>""" % (_("Topic name"), cgi.escape(topic, True)) #<td class="bskcontentcol">%s</td> #<td class="bskcontentcol"><input type="text" name="new_name" value="%s"/></td> general_box = self.__tmpl_basket_box(img=CFG_SITE_URL + '/img/webbasket_user.png', title=_("General settings"), body = general_body) delete_button = '' display_delete = False if display_delete: delete_button = '<input type="submit" class="nonsubmitbutton" name="delete" value="%s" />' delete_button %= _("Delete basket") out = """ <form name="edit" action="%(action)s" method="post"> <p>%(label)s</p> <input type="hidden" name="ln" value="%(ln)s" /> <input type="hidden" name="topic" value ="%(topic)s" /> <table> <tr> <td colspan="3">%(general)s</td> </tr> <tr> <td><input type="submit" class="formbutton" name="submit" value="%(submit_label)s" /></td> <td><input type="submit" class="nonsubmitbutton" name="cancel" value="%(cancel_label)s" /></td> <td>%(delete_button)s</td> </tr> </table> </form>""" % {'label': _('Editing topic: %(x_topic_name)s') % {'x_topic_name': cgi.escape(topic, True)}, 'action': CFG_SITE_URL + '/yourbaskets/edit_topic', 'ln': ln, 'topic': cgi.escape(topic, True), 'general': general_box, 'submit_label': _("Save changes"), 'cancel_label': _("Cancel"), 'delete_button': delete_button} return out def __create_rights_selection_menu(self, name, current_rights, ln=CFG_SITE_LANG): """Private function. create a drop down menu for selection of rights @param name: name of menu (for HTML name attribute) @param current_rights: rights as defined in CFG_WEBBASKET_SHARE_LEVELS @param ln: language """ _ = gettext_set_language(ln) elements = [('NO', _("No rights")), (CFG_WEBBASKET_SHARE_LEVELS['READITM'], _("View records")), (CFG_WEBBASKET_SHARE_LEVELS['READCMT'], '... ' + _("and") + ' ' + _("view comments")), (CFG_WEBBASKET_SHARE_LEVELS['ADDCMT'], '... ' + _("and") + ' ' + _("add comments"))] return self.__create_select_menu(name, elements, current_rights) def __create_group_rights_selection_menu(self, group_id, current_rights, ln=CFG_SITE_LANG): """Private function. create a drop down menu for selection of rights @param current_rights: rights as defined in CFG_WEBBASKET_SHARE_LEVELS @param ln: language """ _ = gettext_set_language(ln) elements = [(str(group_id) + '_' + 'NO', _("No rights")), (str(group_id) + '_' + CFG_WEBBASKET_SHARE_LEVELS['READITM'], _("View records")), (str(group_id) + '_' + CFG_WEBBASKET_SHARE_LEVELS['READCMT'], '... ' + _("and") + ' ' + _("view notes")), (str(group_id) + '_' + CFG_WEBBASKET_SHARE_LEVELS['ADDCMT'], '... ' + _("and") + ' ' + _("add notes")), (str(group_id) + '_' + CFG_WEBBASKET_SHARE_LEVELS['ADDITM'], '... ' + _("and") + ' ' + _("add records")), (str(group_id) + '_' + CFG_WEBBASKET_SHARE_LEVELS['DELCMT'], '... ' + _("and") + ' ' + _("delete notes")), (str(group_id) + '_' + CFG_WEBBASKET_SHARE_LEVELS['DELITM'], '... ' + _("and") + ' ' + _("remove records")), (str(group_id) + '_' + CFG_WEBBASKET_SHARE_LEVELS['MANAGE'], '... ' + _("and") + ' ' + _("manage sharing rights")) ] return self.__create_select_menu('groups', elements, str(group_id) + '_' + current_rights) def tmpl_add_group(self, bskid, selected_topic, groups=[], ln=CFG_SITE_LANG): """ return form for selection of groups. @param bskid: basket id (int) @param selected_topic: topic currently displayed (int) @param groups: list of tuples (group id, group name) @param ln: language """ _ = gettext_set_language(ln) if len(groups): groups_body = """ <tr> <td>%s</td> </tr>""" % self.__create_select_menu('new_group', groups, selected_key=None) else: groups_body = """ <tr> <td>%s</td> </tr>""" % _("You are not a member of a group.") groups_box = self.__tmpl_basket_box(img=CFG_SITE_URL + '/img/webbasket_usergroup.png', title=_("Add group"), body=groups_body) out = """ <form name="add_group" action="%(action)s" method="post"> <p>%(label)s</p> <input type="hidden" name="ln" value="%(ln)s" /> <input type="hidden" name="bskid" value="%(bskid)i" /> <input type="hidden" name="topic" value ="%(topic)s" /> <table style="width:100%%;"> <tr> <td style="width:50%%;vertical-align:top;">%(groups)s</td> <td style="width:50%%;vertical-align:top;"></td> </tr> <tr> <td colspan="2"> <input type="submit" class="formbutton" name="group_cancel" value="%(cancel_label)s" /> <input type="submit" class="formbutton" name="add_group" value="%(submit_label)s" /> </td> </tr> </table> </form>""" % {'label': _('Sharing basket to a new group'), 'action': CFG_SITE_URL + '/yourbaskets/edit', 'ln': ln, - 'topic': selected_topic, + 'topic': cgi.escape(selected_topic, True), 'bskid': bskid, 'groups': groups_box, 'cancel_label': _("Cancel"), 'submit_label': _("Add group")} return out def tmpl_personal_baskets_selection_box(self, baskets=[], select_box_name='baskets', selected_bskid=None, ln=CFG_SITE_LANG): """return an HTML popupmenu @param baskets: list of (bskid, bsk_name, bsk_topic) tuples @param select_box_name: name that will be used for the control @param selected_bskid: id of the selcte basket, use None for no selection @param ln: language""" _ = gettext_set_language(ln) elements = [(0, '- ' + _("no basket") + ' -')] for (bskid, bsk_name, bsk_topic) in baskets: - elements.append((bskid, bsk_topic + ' > ' + bsk_name)) + elements.append((bskid, bsk_topic + ' > ' + bsk_name)) return self.__create_select_menu(select_box_name, elements, selected_bskid) def tmpl_create_guest_warning_box(self, ln=CFG_SITE_LANG): """return html warning box for non registered users""" _ = gettext_set_language(ln) message = _("You are logged in as a guest user, so your baskets will disappear at the end of the current session.") + ' ' message += _("If you wish you can %(x_url_open)slogin or register here%(x_url_close)s.") %\ {'x_url_open': '<a href="' + CFG_SITE_SECURE_URL + '/youraccount/login?ln=' + ln + '">', 'x_url_close': '</a>'} out = """ <table class="errorbox"> <tr> <th class="errorboxheader">%s</th> </tr> </table>""" return out % message def tmpl_create_guest_forbidden_box(self, ln=CFG_SITE_LANG): """return html warning box for non registered users""" _ = gettext_set_language(ln) message = _("This functionality is forbidden to guest users.") + ' ' message += _("If you wish you can %(x_url_open)slogin or register here%(x_url_close)s.") %\ {'x_url_open': '<a href="' + CFG_SITE_SECURE_URL + '/youraccount/login?ln=' + ln + '">', 'x_url_close': '</a>'} out = """ <table class="errorbox"> <thead> <tr> <th class="errorboxheader">%s</th> </tr> </thead> </table>""" return out % message ############################ Utilities ################################### def __create_select_menu(self, name, elements, selected_key=None): """ private function, returns a popup menu @param name: name of HTML control @param elements: list of (key, value) @param selected_key: item that should be selected (key of elements tuple) """ out = '<select name="%s">' % name for (key, label) in elements: selected = '' if key == selected_key: selected = ' selected="selected"' - out += '<option value="%s"%s>%s</option>'% (key, selected, cgi.escape(label)) + out += '<option value="%s"%s>%s</option>'% (cgi.escape(str(key), True), selected, cgi.escape(label, True)) out += '</select>' return out def tmpl_warnings(self, warnings=[], ln=CFG_SITE_LANG): """ returns HTML for warnings """ if type(warnings) is not list: warnings = [warnings] warningbox = "" if warnings: warningbox = "<div class=\"important\">\n" for warning in warnings: lines = warning.split("\n") warningbox += " <p>" for line in lines[0:-1]: warningbox += line + " <br />\n" warningbox += lines[-1] + " </p>" warningbox += "</div><br />\n" return warningbox def tmpl_back_link(self, link, ln=CFG_SITE_LANG): """ returns HTML for a link whose label should be 'Back to search results' """ _ = gettext_set_language(ln) label = _("Back to search results") out = '<a href="%s">%s</a>' % (link, label) return out def __create_webmessage_link(self, to, display_name, ln=CFG_SITE_LANG): """prints a link to the messaging system""" link = "%s/yourmessages/write?msg_to=%s&ln=%s" % (CFG_SITE_URL, to, ln) if to: return '<a href="%s" class="maillink">%s</a>' % (link, display_name) else: return display_name def tmpl_xml_basket(self, items=[]): """Template for XML output of basket @param items: XML version of each item (list)""" items_xml = '' for item in items: items_xml += ' ' + item + '\n' return """<?xml version="1.0" encoding="UTF-8"?> <collection> %s </collection> """ % items_xml ############################ Baskets ################################### ################################## ########### BASKET VIEW ########## ################################## def tmpl_basket(self, bskid, name, date_modification, nb_items, nb_subscribers, (user_can_view_content, user_can_edit_basket, user_can_view_notes, user_can_add_notes, user_can_add_item, user_can_delete_item), nb_comments, share_level, selected_category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group=0, items=[], of='hb', ln=CFG_SITE_LANG): """Template for basket display.""" if not of.startswith('x'): out = """ <table class="bskbasket" width="100%">""" else: out = "" if not of.startswith('x'): out += self.tmpl_basket_header(bskid, name, nb_items, nb_subscribers, date_modification, (user_can_view_content, user_can_edit_basket, user_can_view_notes), selected_category, nb_comments, selected_topic, share_level, ln) if not of.startswith('x'): out += self.tmpl_basket_footer(bskid, nb_items, (user_can_view_content, user_can_edit_basket), selected_category, selected_topic, share_level, ln) out += self.tmpl_basket_content(bskid, (user_can_view_content, user_can_view_notes, user_can_add_notes, user_can_add_item, user_can_delete_item), selected_category, selected_topic, selected_group, items, of, ln) if not of.startswith('x'): out += """ </table>""" if not of.startswith('x'): out += self.tmpl_create_export_as_list(selected_category, selected_topic, selected_group, bskid, None, False) return out def tmpl_basket_header(self, bskid, name, nb_items, nb_subscribers, date_modification, (user_can_view_content, user_can_edit_basket, user_can_view_notes), selected_category, nb_comments, selected_topic, share_level, ln=CFG_SITE_LANG): """Template for basket header display.""" _ = gettext_set_language(ln) optional_colspan = nb_items and user_can_view_content and ' colspan="3"' or '' records_field = '<br />' + _('%i items') % nb_items comments_field = user_can_view_notes and (nb_comments and (', ' + _('%i notes') % nb_comments) or ', ' + _('no notes yet')) or '' subscribers_field = selected_category == CFG_WEBBASKET_CATEGORIES['PRIVATE'] and \ share_level == 0 and \ ', ' + (_('%i subscribers') % nb_subscribers) or \ '' last_update_field = '<br />' + _('last update') + ': ' + date_modification if user_can_edit_basket: - add_ext_resource_url = """%s/yourbaskets/add?category=%s&bskid=%i""" % (CFG_SITE_URL,selected_category,bskid,) + add_ext_resource_url = """%s/yourbaskets/add?category=%s&bskid=%i""" % (CFG_SITE_URL,selected_category,bskid,) add_ext_resource_logo = """<img src="%s/img/wb-create-basket.png" />""" % (CFG_SITE_URL,) add_ext_resource = """<a href="%s">%s%s</a>""" % (add_ext_resource_url, add_ext_resource_logo, _("Add item")) - edit_basket_url = """%s/yourbaskets/edit?bskid=%i&topic=%s&ln=%s""" % (CFG_SITE_URL, bskid, cgi.escape(selected_topic, True), ln) + edit_basket_url = """%s/yourbaskets/edit?bskid=%i&topic=%s&ln=%s""" % (CFG_SITE_URL, bskid, urllib.quote(selected_topic), ln) edit_basket_logo = """<img src="%s/img/wb-edit-basket.png" />""" % (CFG_SITE_URL,) edit_basket = """<a href="%s">%s%s</a>""" % (edit_basket_url, edit_basket_logo, _("Edit basket")) - delete_basket_url = """%s/yourbaskets/edit?bskid=%i&topic=%s&delete=1&ln=%s""" % (CFG_SITE_URL, bskid, cgi.escape(selected_topic, True), ln) + delete_basket_url = """%s/yourbaskets/edit?bskid=%i&topic=%s&delete=1&ln=%s""" % (CFG_SITE_URL, bskid, urllib.quote(selected_topic), ln) delete_basket_logo = """<img src="%s/img/wb-delete-basket.png" />""" % (CFG_SITE_URL,) delete_basket = """<a href="%s">%s%s</a>""" % (delete_basket_url, delete_basket_logo, _("Delete basket")) else: #edit_basket = """<small>%s</small>""" % (_("You cannot edit this basket"),) #delete_basket = """<small>%s</small>""" % (_("You cannot delete this basket"),) edit_basket = "" delete_basket = "" add_ext_resource = "" if selected_category==CFG_WEBBASKET_CATEGORIES['EXTERNAL']: unsubscribe_url = """%s/yourbaskets/unsubscribe?bskid=%i&ln=%s""" % (CFG_SITE_URL, bskid, ln) unsubscribe_logo = """<img src="%s/img/wb-unsubscribe.png" />""" % (CFG_SITE_URL,) unsubscribe = """ \n<a href="%s">%s%s</a>""" % (unsubscribe_url, unsubscribe_logo, _("Unsubscribe from basket")) else: unsubscribe = "" out = """ <thead> <tr> <td class="bskbasketheader"%(optional_colspan)s> <table width="100%%"> <tr> <td class="bskbasketheadertitle"> <strong> %(name)s </strong> <small> %(records_field)s%(comments_field)s%(subscribers_field)s %(last_update_field)s </small> </td> <td class="bskbasketheaderoptions"> %(add_ext_resource)s %(edit_basket)s %(delete_basket)s %(unsubscribe)s </td> </table> </td> </tr> </thead>""" out %= {'optional_colspan': optional_colspan, 'name': cgi.escape(name, True), 'nb_items': nb_items, 'records_field': records_field, 'comments_field': comments_field, 'subscribers_field': subscribers_field, 'last_update_field': last_update_field, 'add_ext_resource': add_ext_resource, 'edit_basket': edit_basket, 'delete_basket': delete_basket, 'unsubscribe': unsubscribe, } return out def tmpl_basket_footer(self, bskid, nb_items, (user_can_view_content, user_can_edit_basket), selected_category, selected_topic, share_level=None, ln=CFG_SITE_LANG): """Template for basket footer display.""" _ = gettext_set_language(ln) optional_colspan = nb_items and user_can_view_content and ' colspan="3"' or '' if user_can_edit_basket: - add_ext_resource_url = """%s/yourbaskets/add?category=%s&bskid=%i""" % (CFG_SITE_URL,selected_category,bskid,) + add_ext_resource_url = """%s/yourbaskets/add?category=%s&bskid=%i""" % (CFG_SITE_URL,selected_category,bskid,) add_ext_resource_logo = """<img src="%s/img/wb-create-basket.png" />""" % (CFG_SITE_URL,) add_ext_resource = """<a href="%s">%s%s</a>""" % (add_ext_resource_url, add_ext_resource_logo, _("Add item")) - edit_basket_url = """%s/yourbaskets/edit?bskid=%i&topic=%s&ln=%s""" % (CFG_SITE_URL, bskid, selected_topic, ln) + edit_basket_url = """%s/yourbaskets/edit?bskid=%i&topic=%s&ln=%s""" % (CFG_SITE_URL, bskid, urllib.quote(selected_topic), ln) edit_basket_logo = """<img src="%s/img/wb-edit-basket.png" />""" % (CFG_SITE_URL,) edit_basket = """<a href="%s">%s%s</a>""" % (edit_basket_url, edit_basket_logo, _("Edit basket")) - delete_basket_url = """%s/yourbaskets/edit?bskid=%i&topic=%s&delete=1&ln=%s""" % (CFG_SITE_URL, bskid, selected_topic, ln) + delete_basket_url = """%s/yourbaskets/edit?bskid=%i&topic=%s&delete=1&ln=%s""" % (CFG_SITE_URL, bskid, urllib.quote(selected_topic), ln) delete_basket_logo = """<img src="%s/img/wb-delete-basket.png" />""" % (CFG_SITE_URL,) delete_basket = """<a href="%s">%s%s</a>""" % (delete_basket_url, delete_basket_logo, _("Delete basket")) else: edit_basket = "" delete_basket = "" add_ext_resource = "" if selected_category==CFG_WEBBASKET_CATEGORIES['EXTERNAL']: unsubscribe_url = """%s/yourbaskets/unsubscribe?bskid=%i&ln=%s""" % (CFG_SITE_URL, bskid, ln) unsubscribe_logo = """<img src="%s/img/wb-unsubscribe.png" />""" % (CFG_SITE_URL,) unsubscribe = """ \n<a href="%s">%s%s</a>""" % (unsubscribe_url, unsubscribe_logo, _("Unsubscribe from basket")) else: unsubscribe = "" if share_level == 0: display_public_url = """%s/yourbaskets/display_public?bskid=%i""" % (CFG_SITE_URL, bskid) display_public_text = _("This basket is publicly accessible at the following address:") display_public = """%s<br /><a href="%s">%s</a>""" % (display_public_text, display_public_url, display_public_url) else: display_public = "" out = """ <tfoot> <tr> <td class="bskbasketfooter"%(optional_colspan)s> <table width="100%%"> <tr> <td class="bskbasketfootertitle"> <small> %(display_public)s </small> </td> <td class="bskbasketfooteroptions"> %(add_ext_resource)s %(edit_basket)s %(delete_basket)s %(unsubscribe)s </td> </tr> </table> </td> </tr> </tfoot>""" out %= {'optional_colspan': optional_colspan, 'display_public': display_public, 'add_ext_resource': add_ext_resource, 'edit_basket': edit_basket, 'delete_basket': delete_basket, 'unsubscribe': unsubscribe} return out def tmpl_basket_content(self, bskid, (user_can_view_content, user_can_view_notes, user_can_add_notes, user_can_add_item, user_can_delete_item), selected_category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group=0, items=[], of='hb', ln=CFG_SITE_LANG): """Template for basket content display.""" if not of.startswith('x'): _ = gettext_set_language(ln) items_html = """ <tbody>""" if user_can_view_content: if not(items): items_html += """ <tr> <td style="text-align:center; height:100px"> %s </td> </tr>""" % _("This basket does not contain any records yet.") else: count = 0 for item in items: count += 1 copy = 1 go_up = go_down = delete = 0 if user_can_add_item: go_up = go_down = 1 if item == items[0]: go_up = 0 if item == items[-1]: go_down = 0 if user_can_delete_item: delete = 1 items_html += self.__tmpl_basket_item(count=count, bskid=bskid, item=item, uparrow=go_up, downarrow=go_down, copy_item=copy, delete_item=delete, view_notes=user_can_view_notes, add_notes=user_can_add_notes, selected_category=selected_category, selected_topic=selected_topic, selected_group=selected_group, ln=ln) else: items_html += """ <tr> <td style="text-align:center; height:100px"> %s </td> </tr>""" % _("You do not have sufficient rights to view this basket's content.") items_html += """ </tbody>""" return items_html else: items_xml = "" for item in items: items_xml += item[4] + "\n" return items_xml def __tmpl_basket_item(self, count, bskid, item, uparrow=0, downarrow=0, copy_item=0, delete_item=0, view_notes=0, add_notes=0, selected_category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group=0, ln=CFG_SITE_LANG): """Template for basket item display within the basket content.""" _ = gettext_set_language(ln) (recid, colid, nb_cmt, last_cmt, val, dummy) = item if uparrow: moveup_url = "%(siteurl)s/yourbaskets/modify?action=moveup&bskid=%(bskid)i&recid=%(recid)i"\ "&category=%(category)s&topic=%(topic)s&group_id=%(group)i&ln=%(ln)s" % \ {'siteurl': CFG_SITE_URL, 'bskid': bskid, 'recid': recid, 'category': selected_category, - 'topic': selected_topic, + 'topic': urllib.quote(selected_topic), 'group': selected_group, 'ln': ln} moveup_img = "%s/img/wb-move-item-up.png" % (CFG_SITE_URL,) moveup = """<a href="%s"><img src="%s" alt="%s" /></a>""" % \ (moveup_url, moveup_img, _("Move item up")) else: moveup_img = "%s/img/wb-move-item-up-disabled.png" % (CFG_SITE_URL,) moveup = """<img src="%s" alt="%s" />""" % \ (moveup_img, _("You cannot move this item up")) if downarrow: movedown_url = "%(siteurl)s/yourbaskets/modify?action=movedown&bskid=%(bskid)i&recid=%(recid)i"\ "&category=%(category)s&topic=%(topic)s&group_id=%(group)i&ln=%(ln)s" % \ {'siteurl': CFG_SITE_URL, 'bskid': bskid, 'recid': recid, 'category': selected_category, - 'topic': selected_topic, + 'topic': urllib.quote(selected_topic), 'group': selected_group, 'ln': ln} movedown_img = "%s/img/wb-move-item-down.png" % (CFG_SITE_URL,) movedown = """<a href="%s"><img src="%s" alt="%s" /></a>""" % \ (movedown_url, movedown_img, _("Move item down")) else: movedown_img = "%s/img/wb-move-item-down-disabled.png" % (CFG_SITE_URL,) movedown = """<img src="%s" alt="%s" />""" % \ (movedown_img, _("You cannot move this item down")) if copy_item: copy_url = "%(siteurl)s/yourbaskets/modify?action=copy&bskid=%(bskid)i&recid=%(recid)i"\ "&category=%(category)s&topic=%(topic)s&group_id=%(group)i&ln=%(ln)s" % \ {'siteurl': CFG_SITE_URL, 'bskid': bskid, 'recid': recid, 'category': selected_category, - 'topic': selected_topic, + 'topic': urllib.quote(selected_topic), 'group': selected_group, 'ln': ln} copy_img = "%s/img/wb-copy-item.png" % (CFG_SITE_URL,) copy = """<a href="%s"><img src="%s" alt="%s" />%s</a>""" % \ (copy_url, copy_img, _("Copy item"), _("Copy item")) else: copy = "" if delete_item: remove_url = "%(siteurl)s/yourbaskets/modify?action=delete&bskid=%(bskid)i&recid=%(recid)i"\ "&category=%(category)s&topic=%(topic)s&group=%(group)i&ln=%(ln)s" % \ {'siteurl': CFG_SITE_URL, 'bskid': bskid, 'recid': recid, 'category': selected_category, - 'topic': selected_topic, + 'topic': urllib.quote(selected_topic), 'group': selected_group, 'ln': ln} remove_img = "%s/img/wb-delete-item.png" % (CFG_SITE_URL,) remove = """<a href="%s"><img src="%s" alt="%s" />%s</a>""" % \ (remove_url, remove_img, _("Remove item"), _("Remove item")) else: remove = "" if recid < 0: external_item_img = '<img src="%s/img/wb-external-item.png" alt="%s" style="vertical-align: top;" /> ' % \ (CFG_SITE_URL, _("External item")) else: external_item_img = '' out = """ <tr> <td class="webbasket_basket_content_item_cell"> <table> <tr> <td class="bskcontentcount"> %(count)i. </td> <td class="bskcontentcol" colspan="2"> %(icon)s%(content)s </td> </tr> <tr> <td class="bskcontentoptions"> %(moveup)s%(movedown)s </td> <td> <span class="moreinfo">""" if item[0] > 0: detailed_record = """<a class="moreinfo" href="%(siteurl)s/%(CFG_SITE_RECORD)s/%(recid)s">%(detailed_record_label)s</a>""" out += detailed_record + (view_notes and " - " or "") external_url = "" else: ## Uncomment the following lines if you want the Detailed record link to be ## displayed for external records but not for external sources (such as urls) #external_colid_and_url = db.get_external_colid_and_url(item[0]) #if external_colid_and_url and external_colid_and_url[0][0] and external_colid_and_url[0][1]: # detailed_record = '<a class="moreinfo" href="%(external_url)s">%(detailed_record_label)s</a>' # out += detailed_record + (view_notes and " - " or "") # external_url = external_colid_and_url[0][1] #else: # external_url = "" ## Currently no external items (records or sources) have a Detailed record link external_url = "" # TODO: If a user has the right to view the notes but not to add new ones, # and there are no notes for some item an anchor to write notes will be # created but with no text, hence invisible. Fix this so that no anchor # is created whatsoever. if view_notes: notes = """\n<a class="moreinfo" href="%(siteurl)s/yourbaskets/%(add_and_view_notes_action)s?"""\ """category=%(category)s&topic=%(topic)s&group=%(group)i&"""\ """bskid=%(bskid)s&recid=%(recid)i&ln=%(ln)s%(add_and_view_notes_inline_anchor)s">%(add_and_view_notes_label)s</a>""" out += notes out += """ </span> </td> <td class="bskbasketheaderoptions"> %(copy)s %(remove)s </td> </tr> </table> </td> </tr>""" out = out % {'moveup': moveup, 'movedown': movedown, 'count': count, 'icon': external_item_img, 'content': colid >= 0 and val or val and self.tmpl_create_pseudo_item(val) or _("This record does not seem to exist any more"), 'add_and_view_notes_action': nb_cmt and 'display' or 'write_note', 'add_and_view_notes_inline_anchor': not nb_cmt and '#note' or '', 'add_and_view_notes_label': nb_cmt and _('Notes') + ' (' + str(nb_cmt) + ')' or add_notes and _('Add a note...') or '', 'last_cmt': last_cmt, 'siteurl': CFG_SITE_URL, 'CFG_SITE_RECORD': CFG_SITE_RECORD, 'bskid': bskid, 'recid': recid, 'external_url': external_url, 'detailed_record_label': _("Detailed record"), 'category': selected_category, - 'topic': selected_topic, + 'topic': urllib.quote(selected_topic), 'group': selected_group, 'copy': copy, 'remove': remove, 'ln': ln} return out ############################################# ########## BASKET SINGLE ITEM VIEW ########## ############################################# def tmpl_basket_single_item(self, bskid, name, nb_items, (user_can_view_content, user_can_view_notes, user_can_add_notes, user_can_delete_notes), selected_category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group=0, item=(), comments=(), previous_item_recid=0, next_item_recid=0, item_index=0, optional_params={}, of='hb', ln=CFG_SITE_LANG): """Template for basket's single item display.""" if of != 'xm': out = """ <table class="bskbasket" width="100%">""" else: out = "" if of != 'xm': out += self.tmpl_basket_single_item_header(bskid, name, nb_items, selected_category, selected_topic, selected_group, previous_item_recid, next_item_recid, item_index, ln) if of != 'xm': out += self.tmpl_basket_single_item_footer(bskid, selected_category, selected_topic, selected_group, previous_item_recid, next_item_recid, ln) out += self.tmpl_basket_single_item_content(bskid, (user_can_view_content, user_can_view_notes, user_can_add_notes, user_can_delete_notes), selected_category, selected_topic, selected_group, item, comments, item_index, optional_params, of, ln) if of != 'xm': out += """ </table>""" if of != 'xm': out += self.tmpl_create_export_as_list(selected_category, selected_topic, selected_group, bskid, item, False) return out def tmpl_basket_single_item_header(self, bskid, name, nb_items, selected_category, selected_topic, selected_group, previous_item_recid, next_item_recid, item_index, ln=CFG_SITE_LANG): """Template for basket's single item header display.""" _ = gettext_set_language(ln) records_field = '<br />' + _('Item %(x_item_index)i of %(x_item_total)i') % \ {'x_item_index': item_index, 'x_item_total': nb_items} if previous_item_recid: previous_item_url = """%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&recid=%s&ln=%s""" % \ (CFG_SITE_URL, selected_category, - selected_topic, + urllib.quote(selected_topic), selected_group, bskid, previous_item_recid, ln) previous_item_logo = """<img src="%s/img/wb-previous-item.png" />""" % (CFG_SITE_URL,) previous_item = """<a href="%s">%s%s</a>""" % (previous_item_url, previous_item_logo, _("Previous item")) else: previous_item_logo = """<img src="%s/img/wb-previous-item-disabled.png" />""" % (CFG_SITE_URL,) previous_item = """%s%s""" % (previous_item_logo, _("Previous item")) if next_item_recid: next_item_url = """%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&recid=%s&ln=%s""" % \ (CFG_SITE_URL, selected_category, - selected_topic, + urllib.quote(selected_topic), selected_group, bskid, next_item_recid, ln) next_item_logo = """<img src="%s/img/wb-next-item.png" />""" % (CFG_SITE_URL,) next_item = """<a href="%s">%s%s</a>""" % (next_item_url, next_item_logo, _("Next item")) else: next_item_logo = """<img src="%s/img/wb-next-item-disabled.png" />""" % (CFG_SITE_URL,) next_item = """%s%s""" % (next_item_logo, _("Next item")) go_back_url = """%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&ln=%s""" % \ (CFG_SITE_URL, selected_category, - selected_topic, + urllib.quote(selected_topic), selected_group, bskid, ln) go_back_logo = """<img src="%s/img/wb-go-back.png" />""" % (CFG_SITE_URL,) go_back = """<a href="%s">%s%s</a>""" % (go_back_url, go_back_logo, _("Return to basket")) out = """ <thead> <tr> <td class="bskbasketheader"> <table> <tr> <td class="bskbasketheadertitle"> <strong> %(name)s </strong> <small> %(records_field)s </small> </td> <td class="bskbasketheaderoptions"> %(go_back)s %(previous_item)s %(next_item)s </td> </table> </td> </tr> </thead>""" out %= {'name': name, 'records_field': records_field, 'go_back': go_back, 'previous_item': previous_item, 'next_item': next_item, } return out def tmpl_basket_single_item_footer(self, bskid, selected_category, selected_topic, selected_group, previous_item_recid, next_item_recid, ln=CFG_SITE_LANG): """Template for basket's single item footer display.""" _ = gettext_set_language(ln) if previous_item_recid: previous_item_url = """%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&recid=%s&ln=%s""" % \ (CFG_SITE_URL, selected_category, - selected_topic, + urllib.quote(selected_topic), selected_group, bskid, previous_item_recid, ln) previous_item_logo = """<img src="%s/img/wb-previous-item.png" />""" % (CFG_SITE_URL,) previous_item = """<a href="%s">%s%s</a>""" % (previous_item_url, previous_item_logo, _("Previous item")) else: previous_item_logo = """<img src="%s/img/wb-previous-item-disabled.png" />""" % (CFG_SITE_URL,) previous_item = """%s%s""" % (previous_item_logo, _("Previous item")) if next_item_recid: next_item_url = """%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&recid=%s&ln=%s""" % \ (CFG_SITE_URL, selected_category, - selected_topic, + urllib.quote(selected_topic), selected_group, bskid, next_item_recid, ln) next_item_logo = """<img src="%s/img/wb-next-item.png" />""" % (CFG_SITE_URL,) next_item = """<a href="%s">%s%s</a>""" % (next_item_url, next_item_logo, _("Next item")) else: next_item_logo = """<img src="%s/img/wb-next-item-disabled.png" />""" % (CFG_SITE_URL,) next_item = """%s%s""" % (next_item_logo, _("Next item")) go_back_url = """%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&ln=%s""" % \ (CFG_SITE_URL, selected_category, - selected_topic, + urllib.quote(selected_topic), selected_group, bskid, ln) go_back_logo = """<img src="%s/img/wb-go-back.png" />""" % (CFG_SITE_URL,) go_back = """<a href="%s">%s%s</a>""" % (go_back_url, go_back_logo, _("Return to basket")) out = """ <tfoot> <tr> <td class="bskbasketfooter"> <table width="100%%"> <tr> <td class="bskbasketfootertitle"> </td> <td class="bskbasketfooteroptions"> %(go_back)s %(previous_item)s %(next_item)s </td> </table> </td> </tr> </tfoot>""" out %= {'go_back': go_back, 'previous_item': previous_item, 'next_item': next_item, } return out def tmpl_basket_single_item_content(self, bskid, (user_can_view_content, user_can_view_notes, user_can_add_notes, user_can_delete_notes), selected_category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group=0, item=(), notes=(), index_item=0, optional_params={}, of='hb', ln=CFG_SITE_LANG): """Template for basket's single item content display.""" if of != 'xm': _ = gettext_set_language(ln) item_html = """ <tbody>""" if user_can_view_content: if not item: item_html += """ <tr> <td style="text-align: center; height: 100px"> %s </td> </tr>""" % _("The item you have selected does not exist.") else: (recid, colid, dummy, last_cmt, val, dummy) = item if recid < 0: external_item_img = '<img src="%s/img/wb-external-item.png" alt="%s" style="vertical-align: top;" /> ' % \ (CFG_SITE_URL, _("External item")) else: external_item_img = '' if user_can_view_notes: notes_html = self.__tmpl_display_notes(recid, bskid, (user_can_add_notes, user_can_delete_notes), selected_category, selected_topic, selected_group, notes, optional_params, ln) notes = """ <tr> <td colspan="2" class="bskcontentnotes">%(notes_html)s </td> </tr>""" % {'notes_html': notes_html} else: notes_msg = _("You do not have sufficient rights to view this item's notes.") notes = """ <tr> <td colspan="2" style="text-align: center; height: 50px"> %(notes_msg)s </td> </tr>""" % {'notes_msg': notes_msg} item_html += """ <tr> <td style="border-bottom: 1px solid #fc0;"> <table> <tr> <td class="bskcontentcount"> %(count)i. </td> <td class="bskcontentcol"> %(icon)s%(content)s </td> </tr>%(notes)s </table> </td> </tr>""" % {'count': index_item, 'icon': external_item_img, 'content': colid >=0 and val or val and self.tmpl_create_pseudo_item(val) or _("This record does not seem to exist any more"), - 'last_cmt': last_cmt, - 'siteurl': CFG_SITE_URL, - 'bskid': bskid, - 'recid': recid, - 'category': selected_category, - 'topic': selected_topic, - 'group': selected_group, - 'notes': notes, - 'ln': ln} + 'notes': notes} else: item_html += """ <tr> <td style="text-align: center; height: 100px"> %s </td> </tr>""" % _("You do not have sufficient rights to view this item.") item_html += """ </tbody>""" return item_html else: item_xml = item[4] return item_xml def __tmpl_display_notes(self, recid, bskid, (user_can_add_notes, user_can_delete_notes), selected_category, selected_topic, selected_group, notes, optional_params, ln=CFG_SITE_LANG): """Template for basket's single item notes display.""" _ = gettext_set_language(ln) warnings_html = "" add_note_p = False if user_can_add_notes and (optional_params.has_key("Add note") or optional_params.has_key("Incomplete note")): add_note_p = True if optional_params.has_key("Add note") and optional_params['Add note']: replied_to_note = optional_params['Add note'] note_body_html = self.tmpl_quote_comment_html(replied_to_note[2], replied_to_note[1], replied_to_note[0], replied_to_note[4], replied_to_note[3], ln) note_body_textual = self.tmpl_quote_comment_textual(replied_to_note[2], replied_to_note[1], replied_to_note[0], replied_to_note[4], replied_to_note[3], ln) note_title = "Re: " + replied_to_note[2] elif optional_params.has_key("Incomplete note") and optional_params['Incomplete note']: incomplete_note = optional_params['Incomplete note'] note_body_html = incomplete_note[1] # TODO: Do we need to format incomplete body correctly as textual # and html as above? note_body_textual = incomplete_note[1] note_title = incomplete_note[0] if optional_params.has_key("Warnings"): warnings = optional_params["Warnings"] warnings_html = self.tmpl_warnings(warnings, ln) else: note_body_html = "" note_body_textual = "" note_title = "" if optional_params.has_key("Warnings"): warnings = optional_params["Warnings"] warnings_html = self.tmpl_warnings(warnings, ln) # TODO: calculate the url file_upload_url = "" action = """%s/yourbaskets/save_note?category=%s&topic=%s&group=%i&bskid=%i&recid=%i&ln=%s%s""" % \ - (CFG_SITE_URL, selected_category, selected_topic, selected_group, bskid, recid, ln, '#note') + (CFG_SITE_URL, selected_category, urllib.quote(selected_topic), selected_group, bskid, recid, ln, '#note') cancel = """%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&recid=%i&ln=%s""" % \ - (CFG_SITE_URL, selected_category, selected_topic, selected_group, bskid, recid, ln) + (CFG_SITE_URL, selected_category, urllib.quote(selected_topic), selected_group, bskid, recid, ln) editor = get_html_text_editor(name="note_body", content=note_body_html, textual_content=note_body_textual, width="99%", height="160px", enabled=CFG_WEBBASKET_USE_RICH_TEXT_EDITOR, file_upload_url=file_upload_url, toolbar_set="WebComment") add_note_html = """ <table cellspacing="0" cellpadding="0" class="bsknotescontentaddnote"> <tr> <td class="bsknotescontentaddform"> <form name="write_note" method="post" action="%(action)s"> <a name="note"></a><strong>%(add_a_note_label)s</strong> %(warnings_html)s <p align="left"> <small>Subject:</small> <br /> <input type="text" name="note_title" size="65" value="%(note_title)s" /> </p> <p align="left"> <small>Note:</small> <br /> %(editor)s </p> <input type="hidden" name="reply_to" value="%(reply_to)s" /> <p align="left"> <input type="submit" class="formbutton" value="%(submit_label)s" /> <input type="button" class="nonsubmitbutton" value="%(cancel_label)s" onClick="window.location='%(cancel)s'" /> </p> </form> </td> </tr> </table>""" % {'action': action, 'warnings_html': warnings_html, 'cancel': cancel, 'cancel_label': _('Cancel'), 'note_title': note_title, 'editor': editor, 'add_a_note_label': _('Add a note'), 'submit_label': _('Add note'), 'reply_to': optional_params.get("Reply to")} notes_icon = '<img src="%s/img/wb-notes.png" style="vertical-align: top;" /> ' % (CFG_SITE_URL,) if user_can_add_notes and not add_note_p: add_note_url = """%s/yourbaskets/write_note?category=%s&topic=%s&group=%i&bskid=%i&recid=%i&ln=%s%s""" % \ - (CFG_SITE_URL, selected_category, selected_topic, selected_group, bskid, recid, ln, '#note') + (CFG_SITE_URL, selected_category, urllib.quote(selected_topic), selected_group, bskid, recid, ln, '#note') add_note_logo = """<img src="%s/img/wb-add-note.png" />""" % (CFG_SITE_URL,) add_note = """<a href="%s">%s%s</a>""" % (add_note_url, add_note_logo, _("Add a note")) else: add_note = "" notes_html = """ <table> <tr> <td class="bsknotesheadertitle"> <br /> <strong>%(notes_icon)s%(notes_label)s</strong> <br /> <small>%(nb_notes)i notes in total</small> </td> <td class="bsknotesheaderoptions"> %(add_note)s </td> </tr>""" % {'notes_label': _('Notes'), 'notes_icon': notes_icon, 'add_note': (notes and user_can_add_notes and not add_note_p) and add_note or " ", 'nb_notes': len(notes)} if notes or add_note or add_note_p: notes_html += """ <tr> <td colspan="2" class="bsknotescontent">""" thread_history = [0] for (cmt_uid, cmt_nickname, cmt_title, cmt_body, cmt_date, dummy, cmtid, reply_to) in notes: if reply_to not in thread_history: # Going one level down in the thread thread_history.append(reply_to) depth = thread_history.index(reply_to) else: depth = thread_history.index(reply_to) thread_history = thread_history[:depth + 1] notes_html += '<div style="margin-left:%spx">' % (depth*20) if user_can_add_notes: reply_to_note = """<a href="%s/yourbaskets/write_note?category=%s&topic=%s&group=%i&bskid=%i&recid=%i&cmtid=%i&ln=%s%s">%s</a>""" % \ - (CFG_SITE_URL, selected_category, cgi.escape(selected_topic, True), selected_group, bskid, recid, cmtid, ln, '#note', _('Reply')) + (CFG_SITE_URL, selected_category, urllib.quote(selected_topic), selected_group, bskid, recid, cmtid, ln, '#note', _('Reply')) else: reply_to_note = "" if user_can_delete_notes: delete_note = """ | <a href="%s/yourbaskets/delete_note?category=%s&topic=%s&group=%i&bskid=%i&recid=%i&cmtid=%i&ln=%s">%s</a>""" % \ - (CFG_SITE_URL, selected_category, cgi.escape(selected_topic, True), selected_group, bskid, recid, cmtid, ln, _('Delete')) + (CFG_SITE_URL, selected_category, urllib.quote(selected_topic), selected_group, bskid, recid, cmtid, ln, _('Delete')) else: delete_note = "" notes_html += """ <table cellspacing="0" cellpadding="0" class="bsknotescontentnote"> <tr> <td class="bsknotescontenttitle"> %(inline_anchor)s<img src="%(CFG_SITE_URL)s/img/user-icon-1-24x24.gif" />%(authorship)s </td> </tr> <tr> <td class="bsknotescontentbody"> <blockquote> %(body)s </blockquote> </td> </tr> <tr> <td class="bsknotescontentoptions"> %(reply_to_note)s%(delete_note)s </td> </tr> </table> <br />""" % {'inline_anchor': (not add_note_p and notes[-1][-1]==cmtid) and '<a name="note"></a>' or '', 'CFG_SITE_URL': CFG_SITE_URL, 'authorship': _("%(x_title)s, by %(x_name)s on %(x_date)s") % \ {'x_title': '<strong>' + (cmt_title and cgi.escape(cmt_title, True) \ or _('Note')) + '</strong>', 'x_name': '<a href="%(CFG_SITE_URL)s/yourmessages/write?msg_to=%(user)s">%(user_display)s</a>' % \ {'CFG_SITE_URL': CFG_SITE_URL, 'user': cmt_nickname or cmt_uid, 'user_display': cmt_nickname or get_user_info(cmt_uid)[2]}, 'x_date': '<em>' + convert_datetext_to_dategui(cmt_date) + '</em>'}, 'body': email_quoted_txt2html(escape_email_quoted_text(cmt_body)), 'reply_to_note': reply_to_note, 'delete_note': delete_note} notes_html += '</div>' if add_note_p: notes_html += add_note_html notes_html += """ </td> </tr>""" notes_html += """ <tr> <td class="bsknotesfootertitle"> </td> <td class="bsknotesfooteroptions"> %(add_note)s </td> </tr> </table>""" % {'add_note': (user_can_add_notes and not add_note_p) and add_note or ' '} return notes_html ######################################## ########## PUBLIC BASKET VIEW ########## ######################################## def tmpl_public_basket(self, bskid, basket_name, date_modification, nb_items, (user_can_view_comments,), nb_comments, items=[], id_owner=0, subscription_status=0, of='hb', ln=CFG_SITE_LANG): """Template for public basket display.""" if of == 'hb': out = """ <table class="bskbasket" width="100%">""" else: out = "" if of == 'hb': out += self.tmpl_public_basket_header(bskid, basket_name, nb_items, date_modification, (user_can_view_comments,), nb_comments, subscription_status, ln) if of == 'hb': out += self.tmpl_public_basket_footer(bskid, nb_items, id_owner, subscription_status, ln) out += self.tmpl_public_basket_content(bskid, (user_can_view_comments,), items, of, ln) if of == 'hb': out += """ </table>""" if of == 'hb': out += self.tmpl_create_export_as_list(bskid=bskid, item=None, public=True) return out def tmpl_public_basket_header(self, bskid, name, nb_items, date_modification, (user_can_view_comments,), nb_comments, subscription_status, ln=CFG_SITE_LANG): """Template for public basket header display.""" _ = gettext_set_language(ln) optional_colspan = nb_items and ' colspan="3"' or '' records_field = '<br />' + _('%i items') % nb_items comments_field = user_can_view_comments and \ (nb_comments and ', ' + (_('%i notes') % nb_comments) or ', ' + _('no notes yet')) \ or '' last_update_field = '<br />' + _('last update') + ': ' + date_modification if subscription_status: subscribe_url = """%s/yourbaskets/subscribe?bskid=%i&ln=%s""" % (CFG_SITE_URL, bskid, ln) subscribe_logo = """<img src="%s/img/wb-subscribe.png" />""" % (CFG_SITE_URL,) subscribe = """<a href="%s">%s%s</a>""" % (subscribe_url, subscribe_logo, _("Subscribe to basket")) unsubscribe_url = """%s/yourbaskets/unsubscribe?bskid=%i&ln=%s""" % (CFG_SITE_URL, bskid, ln) unsubscribe_logo = """<img src="%s/img/wb-unsubscribe.png" />""" % (CFG_SITE_URL,) unsubscribe = """<a href="%s">%s%s</a>""" % (unsubscribe_url, unsubscribe_logo, _("Unsubscribe from basket")) out = """ <thead> <tr> <td class="bskbasketheader"%(optional_colspan)s> <table width="100%%"> <tr> <td class="bskbasketheadertitle"> <strong> %(name)s </strong> <small> %(records_field)s%(comments_field)s %(last_update_field)s </small> </td> <td class="bskbasketheaderoptions"> %(subscribe_unsubscribe_basket)s </td> </table> </td> </tr> </thead>""" out %= {'optional_colspan': optional_colspan, 'name': name, 'nb_items': nb_items, 'records_field': records_field, 'comments_field': comments_field, 'last_update_field': last_update_field, 'subscribe_unsubscribe_basket': subscription_status > 0 and unsubscribe or subscription_status < 0 and subscribe or not subscription_status and ' '} return out def tmpl_public_basket_footer(self, bskid, nb_items, id_owner, subscription_status, ln=CFG_SITE_LANG): """Template for public basket footer display.""" _ = gettext_set_language(ln) optional_colspan = nb_items and ' colspan="3"' or '' if subscription_status: subscribe_url = """%s/yourbaskets/subscribe?bskid=%i&ln=%s""" % (CFG_SITE_URL, bskid, ln) subscribe_logo = """<img src="%s/img/wb-subscribe.png" />""" % (CFG_SITE_URL,) subscribe = """<a href="%s">%s%s</a>""" % (subscribe_url, subscribe_logo, _("Subscribe to basket")) unsubscribe_url = """%s/yourbaskets/unsubscribe?bskid=%i&ln=%s""" % (CFG_SITE_URL, bskid, ln) unsubscribe_logo = """<img src="%s/img/wb-unsubscribe.png" />""" % (CFG_SITE_URL,) unsubscribe = """<a href="%s">%s%s</a>""" % (unsubscribe_url, unsubscribe_logo, _("Unsubscribe from basket")) (uid, nickname, display_name) = get_user_info(id_owner) display_owner_url = """%s/yourmessages/write?msg_to=%s""" % (CFG_SITE_URL, nickname or str(uid)) display_owner_text = _("This public basket belongs to the user ") display_owner = """%s<a href="%s">%s</a>.""" % (display_owner_text, display_owner_url, nickname or display_name) out = """ <tfoot> <tr> <td class="bskbasketfooter"%(optional_colspan)s> <table width="100%%"> <tr> <td class="bskbasketfootertitle"> <small> %(display_owner)s </small> </td> <td class="bskbasketfooteroptions"> %(subscribe_unsubscribe_basket)s </td> </tr> </table> </td> </tr> </tfoot>""" out %= {'optional_colspan': optional_colspan, 'display_owner': subscription_status and display_owner or _('This public basket belongs to you.'), 'subscribe_unsubscribe_basket': subscription_status > 0 and unsubscribe or subscription_status < 0 and subscribe or not subscription_status and ' '} return out def tmpl_public_basket_content(self, bskid, (user_can_view_comments,), items=[], of='hb', ln=CFG_SITE_LANG): """Template for public basket footer display.""" if of == 'hb': _ = gettext_set_language(ln) items_html = """ <tbody>""" if not(items): items_html += """ <tr> <td style="text-align:center; height:100px"> %s </td> </tr>""" % _("Basket is empty") else: count = 0 for item in items: count += 1 items_html += self.__tmpl_public_basket_item(count=count, bskid=bskid, item=item, view_notes=user_can_view_comments, ln=ln) items_html += """ </tbody>""" return items_html elif of.startswith('x'): items_xml = "" for item in items: items_xml += item[4] + "\n" return items_xml else: return "" def __tmpl_public_basket_item(self, count, bskid, item, view_notes=0, ln=CFG_SITE_LANG): """Template for basket item display within the basket content.""" _ = gettext_set_language(ln) (recid, colid, nb_cmt, last_cmt, val, dummy) = item copy_url = "%(siteurl)s/yourbaskets/modify?action=copy&bskid=%(bskid)i&recid=%(recid)i&ln=%(ln)s" % \ {'siteurl': CFG_SITE_URL, 'bskid': bskid, 'recid': recid, 'ln': ln} copy_img = "%s/img/wb-copy-item.png" % (CFG_SITE_URL,) copy = """<a href="%s"><img src="%s" alt="%s" />%s</a>""" % \ (copy_url, copy_img, _("Copy item"), _("Copy item")) if recid < 0: external_item_img = '<img src="%s/img/wb-external-item.png" alt="%s" style="vertical-align: top;" /> ' % \ (CFG_SITE_URL, _("External item")) else: external_item_img = '' out = """ <tr> <td style="border-bottom: 1px solid #fc0;"> <table> <tr> <td class="bskcontentcount"> %(count)i. </td> <td class="bskcontentcol" colspan="2"> %(icon)s%(content)s </td> </tr> <tr> <td class="bskcontentoptions"> </td> <td> <span class="moreinfo">""" if item[0] > 0: detailed_record = """<a class="moreinfo" href="%(siteurl)s/%(CFG_SITE_RECORD)s/%(recid)s">%(detailed_record_label)s</a>""" out += detailed_record + (view_notes and " - " or "") external_url = "" else: ## Uncomment the following lines if you want the Detailed record link to be ## displayed for external records but not for external sources (such as urls) #external_colid_and_url = db.get_external_colid_and_url(item[0]) #if external_colid_and_url and external_colid_and_url[0][0] and external_colid_and_url[0][1]: # detailed_record = '<a class="moreinfo" href="%(external_url)s">%(detailed_record_label)s</a>' # out += detailed_record + (view_notes and " - " or "") # external_url = external_colid_and_url[0][1] #else: # external_url = "" ## Currently no external items (records or sources) have a Detailed record link external_url = "" if view_notes: notes = """\n<a class="moreinfo" href="%(siteurl)s/yourbaskets/%(add_and_view_notes_action)s?"""\ """bskid=%(bskid)s&recid=%(recid)i&ln=%(ln)s%(add_and_view_notes_inline_anchor)s">%(add_and_view_notes_label)s</a>""" out += notes out += """ </span> </td> <td class="bskbasketheaderoptions"> %(copy)s </td> </tr> </table> </td> </tr>""" out = out % {'count': count, 'icon': external_item_img, 'content': colid >= 0 and val or val and self.tmpl_create_pseudo_item(val) or _("This record does not seem to exist any more"), 'add_and_view_notes_action': nb_cmt and 'display_public' or 'write_public_note', 'add_and_view_notes_inline_anchor': not nb_cmt and '#note' or '', 'add_and_view_notes_label': nb_cmt and _('Notes') + ' (' + str(nb_cmt) + ')' or _('Add a note...'), 'last_cmt': last_cmt, 'siteurl': CFG_SITE_URL, 'CFG_SITE_RECORD': CFG_SITE_RECORD, 'bskid': bskid, 'recid': recid, 'external_url': external_url, 'detailed_record_label': _("Detailed record"), 'copy': copy, 'ln': ln} return out #################################################### ########## PUBLIC BASKET SINGLE ITEM VIEW ########## #################################################### def tmpl_public_basket_single_item(self, bskid, name, nb_items, (user_can_view_notes, user_can_add_notes), item=(), notes=(), previous_item_recid=0, next_item_recid=0, item_index=0, optional_params={}, of='hb', ln=CFG_SITE_LANG): """Template for public basket's single item display.""" _ = gettext_set_language(ln) if of == 'hb': out = """ <table class="bskbasket" width="100%">""" else: out = "" if of == 'hb': out += self.tmpl_public_basket_single_item_header(bskid, name, nb_items, previous_item_recid, next_item_recid, item_index, ln=CFG_SITE_LANG) if of == 'hb': out += self.tmpl_public_basket_single_item_footer(bskid, previous_item_recid, next_item_recid, ln=CFG_SITE_LANG) out += self.tmpl_public_basket_single_item_content(bskid, (user_can_view_notes, user_can_add_notes), item, notes, item_index, optional_params, of, ln=CFG_SITE_LANG) if of == 'hb': out += """ </table>""" if of == 'hb': out += self.tmpl_create_export_as_list(bskid=bskid, item=item, public=True) return out def tmpl_public_basket_single_item_header(self, bskid, name, nb_items, previous_item_recid, next_item_recid, item_index, ln=CFG_SITE_LANG): """Template for public basket's single item header display.""" _ = gettext_set_language(ln) records_field = '<br />' + _('Item %(x_item_index)i of %(x_item_total)i') % \ {'x_item_index': item_index, 'x_item_total': nb_items} if previous_item_recid: previous_item_url = """%s/yourbaskets/display_public?bskid=%i&recid=%s&ln=%s""" % \ (CFG_SITE_URL, bskid, previous_item_recid, ln) previous_item_logo = """<img src="%s/img/wb-previous-item.png" />""" % (CFG_SITE_URL,) previous_item = """<a href="%s">%s%s</a>""" % (previous_item_url, previous_item_logo, _("Previous item")) else: previous_item_logo = """<img src="%s/img/wb-previous-item-disabled.png" />""" % (CFG_SITE_URL,) previous_item = """%s%s""" % (previous_item_logo, _("Previous item")) if next_item_recid: next_item_url = """%s/yourbaskets/display_public?bskid=%i&recid=%s&ln=%s""" % \ (CFG_SITE_URL, bskid, next_item_recid, ln) next_item_logo = """<img src="%s/img/wb-next-item.png" />""" % (CFG_SITE_URL,) next_item = """<a href="%s">%s%s</a>""" % (next_item_url, next_item_logo, _("Next item")) else: next_item_logo = """<img src="%s/img/wb-next-item-disabled.png" />""" % (CFG_SITE_URL,) next_item = """%s%s""" % (next_item_logo, _("Next item")) go_back_url = """%s/yourbaskets/display_public?bskid=%i&ln=%s""" % \ (CFG_SITE_URL, bskid, ln) go_back_logo = """<img src="%s/img/wb-go-back.png" />""" % (CFG_SITE_URL,) go_back = """<a href="%s">%s%s</a>""" % (go_back_url, go_back_logo, _("Return to basket")) out = """ <thead> <tr> <td class="bskbasketheader"> <table> <tr> <td class="bskbasketheadertitle"> <strong> %(name)s </strong> <small> %(records_field)s </small> </td> <td class="bskbasketheaderoptions"> %(go_back)s %(previous_item)s %(next_item)s </td> </table> </td> </tr> </thead>""" out %= {'name': name, 'records_field': records_field, 'go_back': go_back, 'previous_item': previous_item, 'next_item': next_item, } return out def tmpl_public_basket_single_item_footer(self, bskid, previous_item_recid, next_item_recid, ln=CFG_SITE_LANG): """Template for public basket's single item footer display.""" _ = gettext_set_language(ln) if previous_item_recid: previous_item_url = """%s/yourbaskets/display_public?bskid=%i&recid=%s&ln=%s""" % \ (CFG_SITE_URL, bskid, previous_item_recid, ln) previous_item_logo = """<img src="%s/img/wb-previous-item.png" />""" % (CFG_SITE_URL,) previous_item = """<a href="%s">%s%s</a>""" % (previous_item_url, previous_item_logo, _("Previous item")) else: previous_item_logo = """<img src="%s/img/wb-previous-item-disabled.png" />""" % (CFG_SITE_URL,) previous_item = """%s%s""" % (previous_item_logo, _("Previous item")) if next_item_recid: next_item_url = """%s/yourbaskets/display_public?bskid=%i&recid=%s&ln=%s""" % \ (CFG_SITE_URL, bskid, next_item_recid, ln) next_item_logo = """<img src="%s/img/wb-next-item.png" />""" % (CFG_SITE_URL,) next_item = """<a href="%s">%s%s</a>""" % (next_item_url, next_item_logo, _("Next item")) else: next_item_logo = """<img src="%s/img/wb-next-item-disabled.png" />""" % (CFG_SITE_URL,) next_item = """%s%s""" % (next_item_logo, _("Next item")) go_back_url = """%s/yourbaskets/display_public?bskid=%i&ln=%s""" % \ (CFG_SITE_URL, bskid, ln) go_back_logo = """<img src="%s/img/wb-go-back.png" />""" % (CFG_SITE_URL,) go_back = """<a href="%s">%s%s</a>""" % (go_back_url, go_back_logo, _("Return to basket")) out = """ <tfoot> <tr> <td class="bskbasketfooter"> <table width="100%%"> <tr> <td class="bskbasketfootertitle"> </td> <td class="bskbasketfooteroptions"> %(go_back)s %(previous_item)s %(next_item)s </td> </table> </td> </tr> </tfoot>""" out %= {'go_back': go_back, 'previous_item': previous_item, 'next_item': next_item, } return out def tmpl_public_basket_single_item_content(self, bskid, (user_can_view_notes, user_can_add_notes), item=(), notes=(), index_item=0, optional_params={}, of='hb', ln=CFG_SITE_LANG): """Template for public basket's single item content display.""" if of == 'hb': _ = gettext_set_language(ln) item_html = """ <tbody>""" if not item: item_html += """ <tr> <td style="text-align: center; height: 100px"> %s </td> </tr>""" % _("The item you have selected does not exist.") else: (recid, colid, dummy, dummy, val, dummy) = item if recid < 0: external_item_img = '<img src="%s/img/wb-external-item.png" alt="%s" style="vertical-align: top;" /> ' % \ (CFG_SITE_URL, _("External item")) else: external_item_img = '' if user_can_view_notes: notes_html = self.__tmpl_display_public_notes(recid, bskid, (user_can_add_notes,), notes, optional_params, ln) notes = """ <tr> <td colspan="2" class="bskcontentnotes">%(notes_html)s </td> </tr>""" % {'notes_html': notes_html} else: notes_msg = _("You do not have sufficient rights to view this item's notes.") notes = """ <tr> <td colspan="2" style="text-align: center; height: 50px"> %(notes_msg)s </td> </tr>""" % {'notes_msg': notes_msg} item_html += """ <tr> <td style="border-bottom: 1px solid #fc0;"> <table> <tr> <td class="bskcontentcount"> %(count)i. </td> <td class="bskcontentcol"> %(icon)s%(content)s </td> </tr>%(notes)s </table> </td> </tr>""" % {'count': index_item, 'icon': external_item_img, 'content': colid >= 0 and val or val and self.tmpl_create_pseudo_item(val) or _("This record does not seem to exist any more"), 'notes': notes, 'ln': ln} item_html += """ </tbody>""" return item_html elif of == 'xm': item_xml = item[4] return item_xml def __tmpl_display_public_notes(self, recid, bskid, (user_can_add_notes,), notes, optional_params, ln=CFG_SITE_LANG): """Template for public basket's single item notes display.""" _ = gettext_set_language(ln) warnings_html = "" add_note_p = False if user_can_add_notes and (optional_params.has_key("Add note") or optional_params.has_key("Incomplete note")): add_note_p = True if optional_params.has_key("Add note") and optional_params['Add note']: replied_to_note = optional_params['Add note'] note_body_html = self.tmpl_quote_comment_html(replied_to_note[2], replied_to_note[1], replied_to_note[0], replied_to_note[4], replied_to_note[3], ln) note_body_textual = self.tmpl_quote_comment_textual(replied_to_note[2], replied_to_note[1], replied_to_note[0], replied_to_note[4], replied_to_note[3], ln) note_title = "Re: " + replied_to_note[2] elif optional_params.has_key("Incomplete note") and optional_params['Incomplete note']: incomplete_note = optional_params['Incomplete note'] note_body_html = incomplete_note[1] # TODO: Do we need to format incomplete body correctly as textual # and html as above? note_body_textual = incomplete_note[1] note_title = incomplete_note[0] if optional_params.has_key("Warnings"): warnings = optional_params["Warnings"] warnings_html = self.tmpl_warnings(warnings, ln) else: note_body_html = "" note_body_textual = "" note_title = "" if optional_params.has_key("Warnings"): warnings = optional_params["Warnings"] warnings_html = self.tmpl_warnings(warnings, ln) # TODO: calculate the url file_upload_url = "" action = """%s/yourbaskets/save_public_note?bskid=%i&recid=%i&ln=%s%s""" % \ (CFG_SITE_URL, bskid, recid, ln, '#note') cancel = """%s/yourbaskets/display_public?bskid=%i&recid=%i&ln=%s""" % \ (CFG_SITE_URL, bskid, recid, ln) editor = get_html_text_editor(name="note_body", content=note_body_html, textual_content=note_body_textual, width="100%", height="200px", enabled=CFG_WEBBASKET_USE_RICH_TEXT_EDITOR, file_upload_url=file_upload_url, toolbar_set="WebComment") add_note_html = """ <table cellspacing="0" cellpadding="0" class="bsknotescontentaddnote"> <tr> <td class="bsknotescontentaddform"> <form name="write_note" method="post" action="%(action)s"> <a name="note"></a><strong>%(add_a_note_label)s</strong> %(warnings_html)s <p align="left"> <small>Subject:</small> <br /> <input type="text" name="note_title" size="65" value="%(note_title)s" /> </p> <p align="left"> <small>Note:</small> <br /> %(editor)s </p> <input type="hidden" name="reply_to" value="%(reply_to)s" /> <p align="right"> <input type="submit" class="formbutton" value="%(submit_label)s" /> <input type="button" class="nonsubmitbutton" value="%(cancel_label)s" onClick="window.location='%(cancel)s'" /> </p> </form> </td> </tr> </table>""" % {'action': action, 'warnings_html': warnings_html, 'cancel': cancel, 'cancel_label': _('Cancel'), 'note_title': note_title, 'editor': editor, 'add_a_note_label': _('Add a note'), 'submit_label': _('Add note'), 'reply_to': optional_params.get("Reply to")} notes_icon = '<img src="%s/img/wb-notes.png" style="vertical-align: top;" /> ' % (CFG_SITE_URL,) if user_can_add_notes and not add_note_p: add_note_url = """%s/yourbaskets/write_public_note?bskid=%i&recid=%i&ln=%s%s""" % \ (CFG_SITE_URL, bskid, recid, ln, '#note') add_note_logo = """<img src="%s/img/wb-add-note.png" />""" % (CFG_SITE_URL,) add_note = """<a href="%s">%s%s</a>""" % (add_note_url, add_note_logo, _("Add a note")) else: add_note = "" notes_html = """ <table> <tr> <td class="bsknotesheadertitle"> <br /> <strong>%(notes_icon)s%(notes_label)s</strong> <br /> <small>%(nb_notes)i notes in total</small> </td> <td class="bsknotesheaderoptions"> %(add_note)s </td> </tr>""" % {'notes_label': _('Notes'), 'notes_icon': notes_icon, 'add_note': (notes and user_can_add_notes and not add_note_p) and add_note or " ", 'nb_notes': len(notes)} if notes or add_note or add_note_p: notes_html += """ <tr> <td colspan="2" class="bsknotescontent">""" thread_history = [0] for (cmt_uid, cmt_nickname, cmt_title, cmt_body, cmt_date, dummy, cmtid, reply_to) in notes: if reply_to not in thread_history: # Going one level down in the thread thread_history.append(reply_to) depth = thread_history.index(reply_to) else: depth = thread_history.index(reply_to) thread_history = thread_history[:depth + 1] notes_html += '<div style="margin-left:%spx">' % (depth*20) if user_can_add_notes: reply_to_note = """<a href="%s/yourbaskets/write_public_note?bskid=%i&recid=%i&cmtid=%i&ln=%s%s">%s</a>""" % \ (CFG_SITE_URL, bskid, recid, cmtid, ln, '#note', _('Reply')) else: reply_to_note = "" notes_html += """ <table cellspacing="0" cellpadding="0" class="bsknotescontentnote"> <tr> <td class="bsknotescontenttitle"> %(inline_anchor)s<img src="%(CFG_SITE_URL)s/img/user-icon-1-24x24.gif" />%(authorship)s </td> </tr> <tr> <td class="bsknotescontentbody"> <blockquote> %(body)s </blockquote> </td> </tr> <tr> <td class="bsknotescontentoptions"> %(reply_to_note)s </td> </tr> </table> <br />""" % {'inline_anchor': (not add_note_p and notes[-1][-1]==cmtid) and '<a name="note"></a>' or '', 'CFG_SITE_URL': CFG_SITE_URL, 'authorship': _("%(x_title)s, by %(x_name)s on %(x_date)s") % \ {'x_title': '<strong>' + (cmt_title and cgi.escape(cmt_title, True) \ or _('Note')) + '</strong>', 'x_name': '<a href="%(CFG_SITE_URL)s/yourmessages/write?msg_to=%(user)s">%(user_display)s</a>' % \ {'CFG_SITE_URL': CFG_SITE_URL, 'user': cmt_nickname or cmt_uid, 'user_display': cmt_nickname or get_user_info(cmt_uid)[2]}, 'x_date': '<em>' + convert_datetext_to_dategui(cmt_date) + '</em>'}, 'body': email_quoted_txt2html(escape_email_quoted_text(cmt_body)), 'reply_to_note': reply_to_note} notes_html += '</div>' if add_note_p: notes_html += add_note_html notes_html += """ </td> </tr>""" notes_html += """ <tr> <td class="bsknotesfootertitle"> </td> <td class="bsknotesfooteroptions"> %(add_note)s </td> </tr> </table>""" % {'add_note': (user_can_add_notes and not add_note_p) and add_note or ' '} return notes_html def tmpl_create_pseudo_item(self, item, of='hb'): """""" if not item: # normally this function should never be run if "item" # is empty or does not exist anyway. return "" if of == 'hb': (es_title, es_desc, es_url) = tuple(item.split('\n')) es_title = cgi.escape(es_title, True) es_desc = cgi.escape(es_desc.replace('<br />', '\n'), True).replace('\n', '<br />') + es_url_label = cgi.escape(prettify_url(es_url)) + es_url = cgi.escape(es_url, True) out = """<strong>%s</strong> <br /> <small>%s <br /> <strong>URL:</strong> <a class="note" target="_blank" href="%s">%s</a> </small> -""" % (es_title, es_desc, es_url, cgi.escape(prettify_url(es_url))) +""" % (es_title, es_desc, es_url, es_url_label) if of == 'xm': # TODO: xml output... out = "" return out def tmpl_export_xml(self, body): """Template for the xml represantation for the selected basket/items.""" out = """ <collection xmlns="http://www.loc.gov/MARC21/slim"> %s </collection>""" % (body,) return out def tmpl_create_export_as_list(self, selected_category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], selected_topic="", selected_group=0, bskid=0, item=(), public=False): """Tamplate that creates a bullet list of export as formats for a basket or an item.""" list_of_export_as_formats = [('BibTeX','hx'), ('DC','xd'), ('EndNote','xe'), ('MARCXML', 'xm'), ('NLM','xn'), ('RefWorks','xw'), ('RSS','xr')] - recid = item and "&recid=" + str(item[0]) or "" + recid = item and "&recid=" + str(item[0]) or "" if not public: - href = "%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i%s" % \ + href = "%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i%s" % \ (CFG_SITE_URL, selected_category, - selected_topic, + urllib.quote(selected_topic), selected_group, bskid, recid) else: href = "%s/yourbaskets/display_public?bskid=%i%s" % \ (CFG_SITE_URL, bskid, recid) export_as_html = "" for format in list_of_export_as_formats: - export_as_html += """<a style="text-decoration:underline;font-weight:normal" href="%s&of=%s">%s</a>, """ % \ + export_as_html += """<a style="text-decoration:underline;font-weight:normal" href="%s&of=%s">%s</a>, """ % \ (href, format[1], format[0]) if export_as_html: export_as_html = export_as_html[:-2] out = """ <div style="float:right; text-align:right;"> <ul class="bsk_export_as_list"> <li>Export as %s </li> </ul> </div>""" % (export_as_html,) return out ############################################# ########## SUPPLEMENTARY FUNCTIONS ########## ############################################# def prettify_name(name, char_limit=10, nb_dots=3): """If name has more characters than char_limit return a shortened version of it keeping the beginning (up to char_limit) and replacing the rest with dots.""" name = unicode(name, 'utf-8') if len(name) > char_limit: while name[char_limit-1] == ' ': char_limit -= 1 prettified_name = name[:char_limit] + '.'*nb_dots return prettified_name.encode('utf-8') else: return name.encode('utf-8') def prettify_url(url, char_limit=50, nb_dots=3): """If the url has more characters than char_limit return a shortened version of it keeping the beginning and ending and replacing the rest with dots.""" if len(url) > char_limit: # let's set a minimum character limit if char_limit < 5: char_limit = 5 # let's set a maximum number of dots in relation to the character limit if nb_dots > char_limit/4: nb_dots = char_limit/5 nb_char_url = char_limit - nb_dots nb_char_end = nb_char_url/4 nb_char_beg = nb_char_url - nb_char_end return url[:nb_char_beg] + '.'*nb_dots + url[-nb_char_end:] else: return url def create_search_box_select_options(category, topic, grpid, topic_list, group_list, number_of_public_baskets, ln): """Returns an html list of options for the select form field of the search box.""" _ = gettext_set_language(ln) out = "" if category: if topic: b = CFG_WEBBASKET_CATEGORIES['PRIVATE'] + '_' + cgi.escape(topic, True) elif grpid: b = CFG_WEBBASKET_CATEGORIES['GROUP'] + '_' + str(grpid) else: b = category else: b = "" if topic_list or group_list: out += """<option value=""%(selected)s>%(label)s</option>""" % \ {'selected': not b and ' selected="selected"' or '', 'label': _("All your baskets")} if topic_list: out += """<optgroup label="%(label)s">""" % \ {'label': _("Your personal baskets")} if len(topic_list) > 1: out += """<option value="%(value)s"%(selected)s>%(label)s</option>""" % \ {'value': CFG_WEBBASKET_CATEGORIES['PRIVATE'], 'selected': b == CFG_WEBBASKET_CATEGORIES['PRIVATE'] and ' selected="selected"' or '', 'label': _("All your topics")} for topic_name in topic_list: topic_label = cgi.escape(topic_name[0], True) topic_value = "P_%s" % (topic_label,) out += """<option value="%(value)s"%(selected)s>%(label)s</option>""" % \ {'value': topic_value, 'selected': b == topic_value and ' selected="selected"' or '', 'label': topic_label} out += "</optgroup>" if group_list: out += """<optgroup label="%(label)s">""" % \ {'label': _("Your group baskets")} if len(group_list) > 1: out += """<option value="%(value)s"%(selected)s>%(label)s</option>""" % \ {'value': CFG_WEBBASKET_CATEGORIES['GROUP'], 'selected': b == CFG_WEBBASKET_CATEGORIES['GROUP'] and ' selected="selected"' or '', 'label': _("All your groups")} for group_id_and_name in group_list: group_label = cgi.escape(group_id_and_name[1], True) group_value = "G_%i" % (group_id_and_name[0],) out += """<option value="%(value)s"%(selected)s>%(label)s</option>""" % \ {'value': group_value, 'selected': b == group_value and ' selected="selected"' or '', 'label': group_label} out += "</optgroup>" if number_of_public_baskets: out += """<optgroup label="%(label)s">""" % \ {'label': _("Your public baskets")} out += """<option value="%(value)s"%(selected)s>%(label)s</option>""" % \ {'value': CFG_WEBBASKET_CATEGORIES['EXTERNAL'], 'selected': b == CFG_WEBBASKET_CATEGORIES['EXTERNAL'] and ' selected="selected"' or '', 'label': _("All your public baskets")} out += "</optgroup>" out += """<option value="%(value)s"%(selected)s>%(label)s</option>""" % \ {'value': CFG_WEBBASKET_CATEGORIES['ALLPUBLIC'], 'selected': b == CFG_WEBBASKET_CATEGORIES['ALLPUBLIC'] and ' selected="selected"' or '', 'label': _("All the public baskets")} return out def create_add_box_select_options(category, bskid, personal_basket_list, group_basket_list, ln): """Returns an html list of options for the select form field of the add box.""" _ = gettext_set_language(ln) out = "" - options = [] + # Calculate the selected basket if there is one pre-selected. if category and bskid: if category == CFG_WEBBASKET_CATEGORIES['PRIVATE']: b = CFG_WEBBASKET_CATEGORIES['PRIVATE'] + '_' + str(bskid) elif category == CFG_WEBBASKET_CATEGORIES['GROUP']: b = CFG_WEBBASKET_CATEGORIES['GROUP'] + '_' + str(bskid) elif category == CFG_WEBBASKET_CATEGORIES['EXTERNAL']: b = CFG_WEBBASKET_CATEGORIES['EXTERNAL'] + '_' + str(bskid) else: b = "" else: b = "" - #option list format: [ name, value, 1st level: True/False, 2nd level: True/False] - # name: the name of the option, it will be used as its label in the list. - # value: the value of the option that will be sent as a POST variable through - # the select form field - # 1st level: bold, no margin, used for categories - # 2nd level: bold, small margin, used for topics and groups - # * when both levels are False: normal font, big margin, - # used for actual options * - - # Let's set the default "Choose a basket..." option first. - #options= [(_("Choose a basket..."), str(-1), False, False)] + # Create the default disabled label option. out += """ - <option style="%(style)s" value="%(value)i">%(label)s</option>""" % \ - {'style': "font-weight: normal;", - 'value': -1, - 'label': _("*** basket name ***")} - - # Then, we parse the personal and group basket lists and dynamically create - # the list of options + <option disabled="disabled" value="%(value)i"%(selected)s>%(label)s</option>""" % \ + {'value': -1, + 'selected': not b and ' selected="selected"' or '', + 'label': _('Please select a basket...')} + + # Check if there is only one basket to select from. If that is the case, + # set the selected basket to its value so that it will automatically be + # pre-selected. We want to make it easier for the user if they only have + # one basket. + if not (personal_basket_list and group_basket_list): + if len(personal_basket_list) == 1: + bskids = personal_basket_list[0][1].split(',') + if len(bskids) == 1: + b = CFG_WEBBASKET_CATEGORIES['PRIVATE'] + '_' + bskids[0] + elif len(group_basket_list) == 1: + bskids = group_basket_list[0][1].split(',') + if len(bskids) == 1: + b = CFG_WEBBASKET_CATEGORIES['GROUP'] + '_' + bskids[0] + + # Create the <optgroup>s and <option>s for the user personal baskets. if personal_basket_list: - options.append((_("Your personal baskets"), None, True, False)) - for personal_topic in personal_basket_list: - personal_topic_name = cgi.escape(personal_topic[0], True) - personal_baskets = eval(personal_topic[1] + ",") - options.append((personal_topic_name, None, False, True)) - for personal_basket in personal_baskets: - personal_basket_name = cgi.escape(personal_basket[1], True) - personal_basket_value = CFG_WEBBASKET_CATEGORIES['PRIVATE'] + "_" + str(personal_basket[0]) - options.append((personal_basket_name, personal_basket_value, False, False)) + out += """ + <optgroup label="%s">""" % ('* ' + _('Your personal baskets') + ' *',) + for personal_basket_list_topic_and_bskids in personal_basket_list: + topic = personal_basket_list_topic_and_bskids[0] + bskids = personal_basket_list_topic_and_bskids[1].split(',') + out += """ + <optgroup label="%s">""" % (cgi.escape(topic, True),) + bskids_and_names = get_basket_ids_and_names(bskids) + for bskid_and_name in bskids_and_names: + basket_value = CFG_WEBBASKET_CATEGORIES['PRIVATE'] + '_' + str(bskid_and_name[0]) + basket_name = bskid_and_name[1] + out += """ + <option value="%(value)s"%(selected)s>%(label)s</option>""" % \ + {'value': basket_value, + 'selected': basket_value == b and ' selected="selected"' or '', + 'label': cgi.escape(basket_name, True)} + out += """ + </optgroup>""" + out += """ + </optgroup>""" + # Create the <optgroup>s and <option>s for the user group baskets. if group_basket_list: - options.append((_("Your group baskets"), None, True, False)) - for group_group in group_basket_list: - group_group_name = cgi.escape(group_group[0], True) - group_baskets = eval(group_group[1] + ",") - options.append((group_group_name, None, False, True)) - for group_basket in group_baskets: - group_basket_name = cgi.escape(group_basket[1], True) - group_basket_value = CFG_WEBBASKET_CATEGORIES['GROUP'] + "_" + str(group_basket[0]) - options.append((group_basket_name, group_basket_value, False, False)) - - if len(options) == 3: - # In case we only have 1 option, pretend b has the value of that option - # so that it is selected by default. - b = options[2][1] - - for option in options: out += """ - <option style="%(style)s"%(value)s%(selected)s%(disabled)s>%(label)s</option>""" % \ - {'value': not ( option[2] or option[3] ) and ' value="' + option[1] + '"' or '', - 'label': option[0], - 'selected': option[1] == b and ' selected="selected"' or '', - 'disabled': ( option[2] or option[3] ) and ' disabled="disabled"' or '', - 'style': option[2] and "font-weight: bold;" or \ - option[3] and "font-weight: bold; margin-left: 5px;" or \ - "font-weight: normal; margin-left: 10px;"} + <optgroup label="%s">""" % ('* ' + _('Your group baskets') + ' *',) + for group_basket_list_topic_and_bskids in group_basket_list: + group = group_basket_list_topic_and_bskids[0] + bskids = group_basket_list_topic_and_bskids[1].split(',') + out += """ + <optgroup label="%s">""" % (cgi.escape(group, True),) + bskids_and_names = get_basket_ids_and_names(bskids) + for bskid_and_name in bskids_and_names: + basket_value = CFG_WEBBASKET_CATEGORIES['GROUP'] + '_' + str(bskid_and_name[0]) + basket_name = bskid_and_name[1] + out += """ + <option value="%(value)s"%(selected)s>%(label)s</option>""" % \ + {'value': basket_value, + 'selected': basket_value == b and ' selected="selected"' or '', + 'label': cgi.escape(basket_name, True)} + out += """ + </optgroup>""" + out += """ + </optgroup>""" return out diff --git a/modules/webbasket/lib/webbasket_webinterface.py b/modules/webbasket/lib/webbasket_webinterface.py index 151172993..17bfdd1f9 100644 --- a/modules/webbasket/lib/webbasket_webinterface.py +++ b/modules/webbasket/lib/webbasket_webinterface.py @@ -1,1614 +1,1619 @@ ## This file is part of Invenio. ## Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 CERN. ## ## Invenio 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. ## ## Invenio 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 Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """WebBasket Web Interface.""" __revision__ = "$Id$" __lastupdated__ = """$Date$""" from invenio import webinterface_handler_config as apache import os import cgi +import urllib from invenio.config import CFG_SITE_SECURE_URL, \ CFG_ACCESS_CONTROL_LEVEL_SITE, \ CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS, \ CFG_SITE_SECURE_URL, CFG_PREFIX, CFG_SITE_LANG from invenio.messages import gettext_set_language from invenio.webpage import page from invenio.webuser import getUid, page_not_authorized, isGuestUser from invenio.webbasket import \ check_user_can_comment, \ check_sufficient_rights, \ perform_request_display, \ perform_request_search, \ create_guest_warning_box, \ create_basket_navtrail, \ perform_request_write_note, \ perform_request_save_note, \ perform_request_delete_note, \ perform_request_add_group, \ perform_request_edit, \ perform_request_edit_topic, \ perform_request_list_public_baskets, \ perform_request_unsubscribe, \ perform_request_subscribe, \ perform_request_display_public, \ perform_request_write_public_note, \ perform_request_save_public_note, \ delete_record, \ move_record, \ perform_request_add, \ perform_request_create_basket, \ perform_request_delete, \ wash_topic, \ wash_group, \ perform_request_export_xml, \ page_start, \ page_end from invenio.webbasket_config import CFG_WEBBASKET_CATEGORIES, \ CFG_WEBBASKET_ACTIONS, \ CFG_WEBBASKET_SHARE_LEVELS from invenio.webbasket_dblayer import get_basket_name, \ get_max_user_rights_on_basket -from invenio.urlutils import get_referer, redirect_to_url, make_canonical_urlargd, quote +from invenio.urlutils import get_referer, redirect_to_url, make_canonical_urlargd from invenio.webinterface_handler import wash_urlargd, WebInterfaceDirectory from invenio.webstat import register_customevent from invenio.errorlib import register_exception from invenio.webuser import collect_user_info from invenio.webcomment import check_user_can_attach_file_to_comments from invenio.access_control_engine import acc_authorize_action from htmlutils import is_html_text_editor_installed from ckeditor_invenio_connector import process_CKEditor_upload, send_response from invenio.bibdocfile import stream_file class WebInterfaceBasketCommentsFiles(WebInterfaceDirectory): """Handle upload and access to files for comments in WebBasket. The upload is currently only available through the CKEditor. """ def _lookup(self, component, path): """ This handler is invoked for the dynamic URLs (for getting and putting attachments) Eg: /yourbaskets/attachments/get/31/652/5/file/myfile.pdf /yourbaskets/attachments/get/31/552/5/image/myfigure.png bskid/recid/uid/ /yourbaskets/attachments/put/31/550/ bskid/recid """ if component == 'get' and len(path) > 4: bskid = path[0] # Basket id recid = path[1] # Record id uid = path[2] # uid of the submitter file_type = path[3] # file, image, flash or media (as # defined by CKEditor) if file_type in ['file', 'image', 'flash', 'media']: file_name = '/'.join(path[4:]) # the filename def answer_get(req, form): """Accessing files attached to comments.""" form['file'] = file_name form['type'] = file_type form['uid'] = uid form['recid'] = recid form['bskid'] = bskid return self._get(req, form) return answer_get, [] elif component == 'put' and len(path) > 1: bskid = path[0] # Basket id recid = path[1] # Record id def answer_put(req, form): """Attaching file to a comment.""" form['recid'] = recid form['bskid'] = bskid return self._put(req, form) return answer_put, [] # All other cases: file not found return None, [] def _get(self, req, form): """ Returns a file attached to a comment. A file is attached to a comment of a record of a basket, by a user (who is the author of the comment), and is of a certain type (file, image, etc). Therefore these 5 values are part of the URL. Eg: CFG_SITE_SECURE_URL/yourbaskets/attachments/get/31/91/5/file/myfile.pdf bskid/recid/uid """ argd = wash_urlargd(form, {'file': (str, None), 'type': (str, None), 'uid': (int, 0), 'bskid': (int, 0), 'recid': (int, 0)}) _ = gettext_set_language(argd['ln']) # Can user view this basket & record & comment, i.e. can user # access its attachments? #uid = getUid(req) user_info = collect_user_info(req) rights = get_max_user_rights_on_basket(argd['uid'], argd['bskid']) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) if user_info['email'] == 'guest': # Ask to login target = '/youraccount/login' + \ make_canonical_urlargd({'ln' : argd['ln'], 'referer' : \ CFG_SITE_SECURE_URL + user_info['uri']}, {}) return redirect_to_url(req, target) elif not(check_sufficient_rights(rights, CFG_WEBBASKET_SHARE_LEVELS['READITM'])): return page_not_authorized(req, "../", \ text = _("You are not authorized to view this attachment")) if not argd['file'] is None: # Prepare path to file on disk. Normalize the path so that # ../ and other dangerous components are removed. path = os.path.abspath(CFG_PREFIX + '/var/data/baskets/comments/' + \ str(argd['bskid']) + '/' + str(argd['recid']) + '/' + \ str(argd['uid']) + '/' + argd['type'] + '/' + \ argd['file']) # Check that we are really accessing attachements # directory, for the declared basket and record. if path.startswith(CFG_PREFIX + '/var/data/baskets/comments/' + \ str(argd['bskid']) + '/' + str(argd['recid'])) and \ os.path.exists(path): return stream_file(req, path) # Send error 404 in all other cases return apache.HTTP_NOT_FOUND def _put(self, req, form): """ Process requests received from CKEditor to upload files, etc. URL eg: CFG_SITE_SECURE_URL/yourbaskets/attachments/put/31/91/ bskid/recid/ """ if not is_html_text_editor_installed(): return argd = wash_urlargd(form, {'bskid': (int, 0), 'recid': (int, 0)}) uid = getUid(req) # URL where the file can be fetched after upload user_files_path = '%(CFG_SITE_SECURE_URL)s/yourbaskets/attachments/get/%(bskid)s/%(recid)i/%(uid)s' % \ {'uid': uid, 'recid': argd['recid'], 'bskid': argd['bskid'], 'CFG_SITE_SECURE_URL': CFG_SITE_SECURE_URL} # Path to directory where uploaded files are saved user_files_absolute_path = '%(CFG_PREFIX)s/var/data/baskets/comments/%(bskid)s/%(recid)s/%(uid)s' % \ {'uid': uid, 'recid': argd['recid'], 'bskid': argd['bskid'], 'CFG_PREFIX': CFG_PREFIX} # Check that user can # 1. is logged in # 2. comment records of this basket (to simplify, we use # WebComment function to check this, even if it is not # entirely adequate) # 3. attach files user_info = collect_user_info(req) (auth_code, dummy) = check_user_can_attach_file_to_comments(user_info, argd['recid']) fileurl = '' callback_function = '' if user_info['email'] == 'guest': # 1. User is guest: must login prior to upload data ='Please login before uploading file.' if not user_info['precached_usebaskets']: msg = 'Sorry, you are not allowed to use WebBasket' elif not check_user_can_comment(uid, argd['bskid']): # 2. User cannot edit comment of this basket msg = 'Sorry, you are not allowed to submit files' elif auth_code: # 3. User cannot submit msg = 'Sorry, you are not allowed to submit files.' else: # Process the upload and get the response (msg, uploaded_file_path, filename, fileurl, callback_function) = \ process_CKEditor_upload(form, uid, user_files_path, user_files_absolute_path, recid=argd['recid']) send_response(req, msg, fileurl, callback_function) class WebInterfaceYourBasketsPages(WebInterfaceDirectory): """Defines the set of /yourbaskets pages.""" _exports = ['', 'display_item', 'display', 'search', 'write_note', 'save_note', 'delete_note', 'add', 'delete', 'modify', 'edit', 'edit_topic', 'create_basket', 'display_public', 'list_public_baskets', 'subscribe', 'unsubscribe', 'write_public_note', 'save_public_note', 'attachments'] attachments = WebInterfaceBasketCommentsFiles() def index(self, req, dummy): """Index page.""" redirect_to_url(req, '%s/yourbaskets/display?%s' % (CFG_SITE_SECURE_URL, req.args)) def display_item(self, req, dummy): """Legacy URL redirection.""" redirect_to_url(req, '%s/yourbaskets/display?%s' % (CFG_SITE_SECURE_URL, req.args)) def display(self, req, form): """Display basket interface.""" #import rpdb2; rpdb2.start_embedded_debugger('password', fAllowRemote=True) argd = wash_urlargd(form, {'category': (str, CFG_WEBBASKET_CATEGORIES['PRIVATE']), 'topic': (str, ""), 'group': (int, 0), 'bskid': (int, 0), 'recid': (int, 0), 'bsk_to_sort': (int, 0), 'sort_by_title': (str, ""), 'sort_by_date': (str, ""), 'of': (str, "hb"), 'ln': (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/display", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/display%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) (body, dummy, navtrail) = perform_request_display(uid=uid, selected_category=argd['category'], selected_topic=argd['topic'], selected_group_id=argd['group'], selected_bskid=argd['bskid'], selected_recid=argd['recid'], of=argd['of'], ln=argd['ln']) if isGuestUser(uid): body = create_guest_warning_box(argd['ln']) + body # register event in webstat if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["display", "", user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") rssurl = CFG_SITE_SECURE_URL + "/rss" if argd['of'] != 'hb': page_start(req, of=argd['of']) if argd['of'].startswith('x'): req.write(body) page_end(req, of=argd['of']) return elif argd['bskid']: - rssurl = "%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&of=xr" % \ + rssurl = "%s/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&of=xr" % \ (CFG_SITE_SECURE_URL, - cgi.escape(argd['category']), - cgi.escape(argd['topic']), + argd['category'], + urllib.quote(argd['topic']), argd['group'], argd['bskid']) return page(title = _("Display baskets"), body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], navtrail_append_title_p = 0, secure_page_p=1, rssurl=rssurl) def search(self, req, form): """Search baskets interface.""" - argd = wash_urlargd(form, {'category': (str, ""), 'topic': (str, ""), 'group': (int, 0), 'p': (str, ""), 'b': (str, ""), 'n': (int, 0), 'of': (str, "hb"), 'verbose': (int, 0), 'ln': (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/search", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/search%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) (body, navtrail) = perform_request_search(uid=uid, selected_category=argd['category'], selected_topic=argd['topic'], selected_group_id=argd['group'], p=argd['p'], b=argd['b'], n=argd['n'], # format=argd['of'], ln=argd['ln']) # register event in webstat if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["search", "", user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") return page(title = _("Search baskets"), body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], navtrail_append_title_p = 0, secure_page_p=1) def write_note(self, req, form): """Write a comment (just interface for writing)""" argd = wash_urlargd(form, {'category': (str, CFG_WEBBASKET_CATEGORIES['PRIVATE']), 'topic': (str, ""), 'group': (int, 0), 'bskid': (int, 0), 'recid': (int, 0), 'cmtid': (int, 0), 'of' : (str, ''), 'ln': (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/write_note", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/write_note%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) (body, navtrail) = perform_request_write_note(uid=uid, category=argd['category'], topic=argd['topic'], group_id=argd['group'], bskid=argd['bskid'], recid=argd['recid'], cmtid=argd['cmtid'], ln=argd['ln']) # register event in webstat basket_str = "%s (%d)" % (get_basket_name(argd['bskid']), argd['bskid']) if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["write_note", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") return page(title = _("Add a note"), body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], secure_page_p=1) def save_note(self, req, form): """Save comment on record in basket""" argd = wash_urlargd(form, {'category': (str, CFG_WEBBASKET_CATEGORIES['PRIVATE']), 'topic': (str, ""), 'group': (int, 0), 'bskid': (int, 0), 'recid': (int, 0), 'note_title': (str, ""), 'note_body': (str, ""), 'editor_type': (str, ""), 'of': (str, ''), 'ln': (str, CFG_SITE_LANG), 'reply_to': (int, 0)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/save_note", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/save_note%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) (body, navtrail) = perform_request_save_note(uid=uid, category=argd['category'], topic=argd['topic'], group_id=argd['group'], bskid=argd['bskid'], recid=argd['recid'], note_title=argd['note_title'], note_body=argd['note_body'], editor_type=argd['editor_type'], ln=argd['ln'], reply_to=argd['reply_to']) # TODO: do not stat event if save was not succussful # register event in webstat basket_str = "%s (%d)" % (get_basket_name(argd['bskid']), argd['bskid']) if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["save_note", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") return page(title = _("Display item and notes"), body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], navtrail_append_title_p = 0, secure_page_p=1) def delete_note(self, req, form): """Delete a comment @param bskid: id of basket (int) @param recid: id of record (int) @param cmtid: id of comment (int) @param category: category (see webbasket_config) (str) @param topic: nb of topic currently displayed (int) @param group: id of group baskets currently displayed (int) @param ln: language""" argd = wash_urlargd(form, {'category': (str, CFG_WEBBASKET_CATEGORIES['PRIVATE']), 'topic': (str, ""), 'group': (int, 0), 'bskid': (int, 0), 'recid': (int, 0), 'cmtid': (int, 0), 'of' : (str, ''), 'ln': (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/delete_note", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/delete_note%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/display%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) (body, navtrail) = perform_request_delete_note(uid=uid, category=argd['category'], topic=argd['topic'], group_id=argd['group'], bskid=argd['bskid'], recid=argd['recid'], cmtid=argd['cmtid'], ln=argd['ln']) # TODO: do not stat event if delete was not succussful # register event in webstat basket_str = "%s (%d)" % (get_basket_name(argd['bskid']), argd['bskid']) user_info = collect_user_info(req) if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["delete_note", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") return page(title = _("Display item and notes"), body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], navtrail_append_title_p = 0, secure_page_p=1) def add(self, req, form): """Add records to baskets. @param recid: list of records to add @param colid: in case of external collections, the id of the collection the records belong to @param bskids: list of baskets to add records to. if not provided, will return a page where user can select baskets @param referer: URL of the referring page @param new_basket_name: add record to new basket @param new_topic_name: new basket goes into new topic @param create_in_topic: # of topic to put basket into @param ln: language""" # TODO: apply a maximum limit of items (100) that can be added to a basket # at once. Also see the build_search_url function of websearch_..._searcher.py # for the "rg" GET variable. argd = wash_urlargd(form, {'recid': (list, []), 'category': (str, ""), 'bskid': (int, 0), 'colid': (int, 0), 'es_title': (str, ""), 'es_desc': (str, ""), 'es_url': (str, ""), 'note_body': (str, ""), 'editor_type': (str, ""), 'b': (str, ""), 'copy': (int, 0), 'wait': (int, 0), 'referer': (str, ""), "of" : (str, ''), 'ln': (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/add", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/add%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) if not argd['referer']: argd['referer'] = get_referer(req) (body, navtrail) = perform_request_add(uid=uid, recids=argd['recid'], colid=argd['colid'], bskid=argd['bskid'], es_title=argd['es_title'], es_desc=argd['es_desc'], es_url=argd['es_url'], note_body=argd['note_body'], editor_type=argd['editor_type'], category=argd['category'], b=argd['b'], copy=argd['copy'], wait=argd['wait'], referer=argd['referer'], ln=argd['ln']) if isGuestUser(uid): body = create_guest_warning_box(argd['ln']) + body # register event in webstat bskid = argd['bskid'] basket_str = "%s (%s)" % (get_basket_name(bskid), bskid) if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["add", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") return page(title = _('Add to basket'), body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], navtrail_append_title_p = 0, secure_page_p=1) def delete(self, req, form): """Delete basket interface""" - argd = wash_urlargd(form, {'bskid': (int, -1), - 'confirmed': (int, 0), - 'category': - (str, CFG_WEBBASKET_CATEGORIES['PRIVATE']), - 'topic': (str, ""), - 'group': (int, 0), - 'of' : (str, ''), - 'ln': (str, CFG_SITE_LANG)}) + argd = wash_urlargd(form, {'bskid' : (int, -1), + 'confirmed' : (int, 0), + 'category' : (str, CFG_WEBBASKET_CATEGORIES['PRIVATE']), + 'topic' : (str, ""), + 'group' : (int, 0), + 'of' : (str, ''), + 'ln' : (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/delete", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/delete%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) body=perform_request_delete(uid=uid, bskid=argd['bskid'], confirmed=argd['confirmed'], category=argd['category'], selected_topic=argd['topic'], selected_group_id=argd['group'], ln=argd['ln']) if argd['confirmed']: if argd['category'] == CFG_WEBBASKET_CATEGORIES['PRIVATE']: argd['topic'] = wash_topic(uid, argd['topic'])[0] elif argd['category'] == CFG_WEBBASKET_CATEGORIES['GROUP']: argd['group'] = wash_group(uid, argd['group'])[0] url = """%s/yourbaskets/display?category=%s&topic=%s&group=%i&ln=%s""" % \ - (CFG_SITE_SECURE_URL, argd['category'], argd['topic'], argd['group'], argd['ln']) + (CFG_SITE_SECURE_URL, + argd['category'], + urllib.quote(argd['topic']), + argd['group'], + argd['ln']) redirect_to_url(req, url) else: navtrail = '<a class="navtrail" href="%s/youraccount/display?ln=%s">'\ '%s</a>' navtrail %= (CFG_SITE_SECURE_URL, argd['ln'], _("Your Account")) navtrail_end = create_basket_navtrail(uid=uid, category=argd['category'], topic=argd['topic'], group=argd['group'], bskid=argd['bskid'], ln=argd['ln']) if isGuestUser(uid): body = create_guest_warning_box(argd['ln']) + body # register event in webstat basket_str = "%s (%d)" % (get_basket_name(argd['bskid']), argd['bskid']) if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["delete", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") return page(title = _("Delete a basket"), body = body, navtrail = navtrail + navtrail_end, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], secure_page_p=1) def modify(self, req, form): """Modify basket content interface (reorder, suppress record, etc.)""" argd = wash_urlargd(form, {'action': (str, ""), 'bskid': (int, -1), 'recid': (int, 0), 'category': (str, CFG_WEBBASKET_CATEGORIES['PRIVATE']), 'topic': (str, ""), 'group': (int, 0), 'of' : (str, ''), 'ln': (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/modify", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/modify%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) url = CFG_SITE_SECURE_URL - url += '/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&ln=%s' % \ - (argd['category'], argd['topic'], argd['group'], argd['bskid'], argd['ln']) + url += '/yourbaskets/display?category=%s&topic=%s&group=%i&bskid=%i&ln=%s' % \ + (argd['category'], urllib.quote(argd['topic']), argd['group'], argd['bskid'], argd['ln']) if argd['action'] == CFG_WEBBASKET_ACTIONS['DELETE']: delete_record(uid, argd['bskid'], argd['recid']) redirect_to_url(req, url) elif argd['action'] == CFG_WEBBASKET_ACTIONS['UP']: move_record(uid, argd['bskid'], argd['recid'], argd['action']) redirect_to_url(req, url) elif argd['action'] == CFG_WEBBASKET_ACTIONS['DOWN']: move_record(uid, argd['bskid'], argd['recid'], argd['action']) redirect_to_url(req, url) elif argd['action'] == CFG_WEBBASKET_ACTIONS['COPY']: title = _("Copy record to basket") referer = get_referer(req) (body, navtrail) = perform_request_add(uid=uid, recids=argd['recid'], copy=True, referer=referer, ln=argd['ln']) if isGuestUser(uid): body = create_guest_warning_box(argd['ln']) + body else: title = '' body = '' # warnings = [('WRN_WEBBASKET_UNDEFINED_ACTION',)] navtrail = '<a class="navtrail" href="%s/youraccount/display?ln=%s">'\ '%s</a>' navtrail %= (CFG_SITE_SECURE_URL, argd['ln'], _("Your Account")) navtrail_end = create_basket_navtrail(uid=uid, category=argd['category'], topic=argd['topic'], group=argd['group'], bskid=argd['bskid'], ln=argd['ln']) # register event in webstat basket_str = "%s (%d)" % (get_basket_name(argd['bskid']), argd['bskid']) if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["modify", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") return page(title = title, body = body, navtrail = navtrail + navtrail_end, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], secure_page_p=1) def edit(self, req, form): """Edit basket interface""" argd = wash_urlargd(form, {'bskid': (int, 0), 'groups': (list, []), 'topic': (str, ""), 'add_group': (str, ""), 'group_cancel': (str, ""), 'submit': (str, ""), 'cancel': (str, ""), 'delete': (str, ""), 'new_name': (str, ""), 'new_topic': (str, ""), 'new_topic_name': (str, ""), 'new_group': (str, ""), 'external': (str, ""), 'of' : (str, ''), 'ln': (str, CFG_SITE_LANG)}) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/edit", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/edit%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) _ = gettext_set_language(argd['ln']) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) if argd['cancel']: url = CFG_SITE_SECURE_URL + '/yourbaskets/display?category=%s&topic=%s&ln=%s' - url %= (CFG_WEBBASKET_CATEGORIES['PRIVATE'], argd['topic'], + url %= (CFG_WEBBASKET_CATEGORIES['PRIVATE'], + urllib.quote(argd['topic']), argd['ln']) redirect_to_url(req, url) elif argd['delete']: url = CFG_SITE_SECURE_URL url += '/yourbaskets/delete?bskid=%i&category=%s&topic=%s&ln=%s' % \ - (argd['bskid'], CFG_WEBBASKET_CATEGORIES['PRIVATE'], - argd['topic'], argd['ln']) + (argd['bskid'], + CFG_WEBBASKET_CATEGORIES['PRIVATE'], + urllib.quote(argd['topic']), + argd['ln']) redirect_to_url(req, url) elif argd['add_group'] and not(argd['new_group']): body = perform_request_add_group(uid=uid, bskid=argd['bskid'], topic=argd['topic'], ln=argd['ln']) # warnings = [] elif (argd['add_group'] and argd['new_group']) or argd['group_cancel']: if argd['add_group']: perform_request_add_group(uid=uid, bskid=argd['bskid'], topic=argd['topic'], group_id=argd['new_group'], ln=argd['ln']) body = perform_request_edit(uid=uid, bskid=argd['bskid'], topic=argd['topic'], ln=argd['ln']) elif argd['submit']: body = perform_request_edit(uid=uid, bskid=argd['bskid'], topic=argd['topic'], new_name=argd['new_name'], new_topic=argd['new_topic'], new_topic_name=argd['new_topic_name'], groups=argd['groups'], external=argd['external'], ln=argd['ln']) if argd['new_topic'] != "-1": argd['topic'] = argd['new_topic'] url = CFG_SITE_SECURE_URL + '/yourbaskets/display?category=%s&topic=%s&ln=%s' % \ (CFG_WEBBASKET_CATEGORIES['PRIVATE'], - argd['topic'], argd['ln']) + urllib.quote(argd['topic']), + argd['ln']) redirect_to_url(req, url) else: body = perform_request_edit(uid=uid, - bskid=argd['bskid'], - topic=argd['topic'], - ln=argd['ln']) + bskid=argd['bskid'], + topic=argd['topic'], + ln=argd['ln']) navtrail = '<a class="navtrail" href="%s/youraccount/display?ln=%s">'\ '%s</a>' navtrail %= (CFG_SITE_SECURE_URL, argd['ln'], _("Your Account")) navtrail_end = create_basket_navtrail( uid=uid, category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], topic=argd['topic'], group=0, bskid=argd['bskid'], ln=argd['ln']) if isGuestUser(uid): body = create_guest_warning_box(argd['ln']) + body # register event in webstat basket_str = "%s (%d)" % (get_basket_name(argd['bskid']), argd['bskid']) if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["edit", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") return page(title = _("Edit basket"), body = body, navtrail = navtrail + navtrail_end, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], secure_page_p=1) def edit_topic(self, req, form): """Edit topic interface""" argd = wash_urlargd(form, {'topic': (str, ""), 'submit': (str, ""), 'cancel': (str, ""), 'delete': (str, ""), 'new_name': (str, ""), 'of' : (str, ''), 'ln': (str, CFG_SITE_LANG)}) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/edit", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/edit_topic%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) _ = gettext_set_language(argd['ln']) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) if argd['cancel']: url = CFG_SITE_SECURE_URL + '/yourbaskets/display?category=%s&ln=%s' url %= (CFG_WEBBASKET_CATEGORIES['PRIVATE'], argd['ln']) - #url = CFG_SITE_SECURE_URL + '/yourbaskets/display?category=%s&topic=%s&ln=%s' - #url %= (CFG_WEBBASKET_CATEGORIES['PRIVATE'], argd['topic'], - # argd['ln']) redirect_to_url(req, url) elif argd['delete']: url = CFG_SITE_SECURE_URL url += '/yourbaskets/delete?bskid=%i&category=%s&topic=%s&ln=%s' % \ - (argd['bskid'], CFG_WEBBASKET_CATEGORIES['PRIVATE'], - argd['topic'], argd['ln']) + (argd['bskid'], + CFG_WEBBASKET_CATEGORIES['PRIVATE'], + urllib.quote(argd['topic']), + argd['ln']) redirect_to_url(req, url) elif argd['submit']: body = perform_request_edit_topic(uid=uid, topic=argd['topic'], new_name=argd['new_name'], ln=argd['ln']) - #url = CFG_SITE_SECURE_URL + '/yourbaskets/display?category=%s&topic=%s&ln=%s' % \ - # (CFG_WEBBASKET_CATEGORIES['PRIVATE'], - # argd['topic'], argd['ln']) url = CFG_SITE_SECURE_URL + '/yourbaskets/display?category=%s&ln=%s' % \ (CFG_WEBBASKET_CATEGORIES['PRIVATE'], argd['ln']) redirect_to_url(req, url) else: body = perform_request_edit_topic(uid=uid, topic=argd['topic'], ln=argd['ln']) navtrail = '<a class="navtrail" href="%s/youraccount/display?ln=%s">'\ '%s</a>' navtrail %= (CFG_SITE_SECURE_URL, argd['ln'], _("Your Account")) navtrail_end = "" #navtrail_end = create_basket_navtrail( # uid=uid, # category=CFG_WEBBASKET_CATEGORIES['PRIVATE'], # topic=argd['topic'], # group=0, # ln=argd['ln']) if isGuestUser(uid): body = create_guest_warning_box(argd['ln']) + body # register event in webstat #basket_str = "%s (%d)" % (get_basket_name(argd['bskid']), argd['bskid']) #if user_info['email']: # user_str = "%s (%d)" % (user_info['email'], user_info['uid']) #else: # user_str = "" #try: # register_customevent("baskets", ["edit", basket_str, user_str]) #except: # register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") - return page(title = _("Edit topic"), + return page(title = _("Edit topic"), body = body, navtrail = navtrail + navtrail_end, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], secure_page_p=1) def create_basket(self, req, form): """Create basket interface""" argd = wash_urlargd(form, {'new_basket_name': (str, ""), 'new_topic_name' : (str, ""), 'create_in_topic': (str, "-1"), 'topic' : (str, ""), 'recid' : (list, []), 'colid' : (int, -1), 'es_title' : (str, ''), 'es_desc' : (str, ''), 'es_url' : (str, ''), 'of' : (str, ''), 'ln' : (str, CFG_SITE_LANG)}) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/create_basket", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/create_basket%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) _ = gettext_set_language(argd['ln']) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) if argd['new_basket_name'] and \ (argd['new_topic_name'] or argd['create_in_topic'] != "-1"): (bskid, topic) = perform_request_create_basket( req, uid=uid, new_basket_name=argd['new_basket_name'], new_topic_name=argd['new_topic_name'], create_in_topic=argd['create_in_topic'], recids=argd['recid'], colid=argd['colid'], es_title=argd['es_title'], es_desc=argd['es_desc'], es_url=argd['es_url'], ln=argd['ln']) # register event in webstat basket_str = "%s ()" % argd['new_basket_name'] if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["create_basket", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") if ( argd['recid'] and argd['colid'] >= 0 ): url = CFG_SITE_SECURE_URL + '/yourbaskets/add?category=%s&bskid=%i&colid=%i&recid=%s&wait=1&ln=%s' url %= (CFG_WEBBASKET_CATEGORIES['PRIVATE'], bskid, argd['colid'], '&recid='.join(str(recid) for recid in argd['recid']), argd['ln']) elif ( argd['es_title'] and argd['es_desc'] and argd['es_url'] and argd['colid'] == -1 ): url = CFG_SITE_SECURE_URL + '/yourbaskets/add?category=%s&bskid=%i&colid=%i&es_title=%s&es_desc=%s&es_url=%s&wait=1&ln=%s' url %= (CFG_WEBBASKET_CATEGORIES['PRIVATE'], bskid, argd['colid'], - quote(argd['es_title']), - quote(argd['es_desc']), - quote(argd['es_url']), + urllib.quote(argd['es_title']), + urllib.quote(argd['es_desc']), + urllib.quote(argd['es_url']), argd['ln']) else: url = CFG_SITE_SECURE_URL + '/yourbaskets/display?category=%s&topic=%s&ln=%s' - url %= (CFG_WEBBASKET_CATEGORIES['PRIVATE'], topic, argd['ln']) + url %= (CFG_WEBBASKET_CATEGORIES['PRIVATE'], + urllib.quote(topic), + argd['ln']) redirect_to_url(req, url) else: body = perform_request_create_basket(req, uid=uid, new_basket_name=argd['new_basket_name'], new_topic_name=argd['new_topic_name'], create_in_topic=argd['create_in_topic'], topic=argd['topic'], recids=argd['recid'], colid=argd['colid'], es_title=argd['es_title'], es_desc=argd['es_desc'], es_url=argd['es_url'], ln=argd['ln']) navtrail = '<a class="navtrail" href="%s/youraccount/'\ 'display?ln=%s">%s</a>' navtrail %= (CFG_SITE_SECURE_URL, argd['ln'], _("Your Account")) if isGuestUser(uid): body = create_guest_warning_box(argd['ln']) + body return page(title = _("Create basket"), body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], secure_page_p=1) def display_public(self, req, form): """Display a public basket""" argd = wash_urlargd(form, {'bskid': (int, 0), 'recid': (int, 0), 'of': (str, "hb"), 'ln': (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/display", navmenuid = 'yourbaskets') user_info = collect_user_info(req) if not argd['bskid']: (body, navtrail) = perform_request_list_public_baskets(uid) title = _('List of public baskets') # register event in webstat if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["list_public_baskets", "", user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") else: (body, dummy, navtrail) = perform_request_display_public(uid=uid, selected_bskid=argd['bskid'], selected_recid=argd['recid'], of=argd['of'], ln=argd['ln']) title = _('Public basket') # register event in webstat basket_str = "%s (%d)" % (get_basket_name(argd['bskid']), argd['bskid']) if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["display_public", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") rssurl = CFG_SITE_SECURE_URL + "/rss" if argd['of'] != 'hb': page_start(req, of=argd['of']) if argd['of'].startswith('x'): req.write(body) page_end(req, of=argd['of']) return elif argd['bskid']: - rssurl = "%s/yourbaskets/display_public?&bskid=%i&of=xr" % \ + rssurl = "%s/yourbaskets/display_public?&bskid=%i&of=xr" % \ (CFG_SITE_SECURE_URL, argd['bskid']) return page(title = title, body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], navtrail_append_title_p = 0, secure_page_p=1, rssurl=rssurl) def list_public_baskets(self, req, form): """List of public baskets interface.""" argd = wash_urlargd(form, {'limit': (int, 1), 'sort': (str, 'name'), 'asc': (int, 1), 'of': (str, ''), 'ln': (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE == 2: return page_not_authorized(req, "../yourbaskets/list_public_baskets", navmenuid = 'yourbaskets') user_info = collect_user_info(req) nb_views_show = acc_authorize_action(user_info, 'runwebstatadmin') nb_views_show_p = not(nb_views_show[0]) (body, navtrail) = perform_request_list_public_baskets(uid, argd['limit'], argd['sort'], argd['asc'], nb_views_show_p, argd['ln']) return page(title = _("List of public baskets"), body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], navtrail_append_title_p = 0, secure_page_p=1) def subscribe(self, req, form): """Subscribe to a basket pseudo-interface.""" argd = wash_urlargd(form, {'bskid': (int, 0), 'of': (str, 'hb'), 'ln': (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE == 2: return page_not_authorized(req, "../yourbaskets/subscribe", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/subscribe%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) if not argd['bskid']: (body, navtrail) = perform_request_list_public_baskets(uid) title = _('List of public baskets') else: # TODO: Take care of XML output as shown below #req.content_type = "text/xml" #req.send_http_header() #return perform_request_display_public(bskid=argd['bskid'], of=argd['of'], ln=argd['ln']) subscribe_warnings_html = perform_request_subscribe(uid, argd['bskid'], argd['ln']) (body, dummy, navtrail) = perform_request_display_public(uid=uid, selected_bskid=argd['bskid'], selected_recid=0, of=argd['of'], ln=argd['ln']) #warnings.extend(subscribe_warnings) body = subscribe_warnings_html + body title = _('Public basket') return page(title = title, body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], navtrail_append_title_p = 0, secure_page_p=1) def unsubscribe(self, req, form): """Unsubscribe from basket pseudo-interface.""" argd = wash_urlargd(form, {'bskid': (int, 0), 'of': (str, 'hb'), 'ln': (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE == 2: return page_not_authorized(req, "../yourbaskets/unsubscribe", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/unsubscribe%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) if not argd['bskid']: (body, navtrail) = perform_request_list_public_baskets(uid) title = _('List of public baskets') else: # TODO: Take care of XML output as shown below #req.content_type = "text/xml" #req.send_http_header() #return perform_request_display_public(bskid=argd['bskid'], of=argd['of'], ln=argd['ln']) unsubscribe_warnings_html = perform_request_unsubscribe(uid, argd['bskid'], argd['ln']) (body, dummy, navtrail) = perform_request_display_public(uid=uid, selected_bskid=argd['bskid'], selected_recid=0, of=argd['of'], ln=argd['ln']) # warnings.extend(unsubscribe_warnings) body = unsubscribe_warnings_html + body title = _('Public basket') return page(title = title, body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], navtrail_append_title_p = 0, secure_page_p=1) def write_public_note(self, req, form): """Write a comment (just interface for writing)""" argd = wash_urlargd(form, {'bskid': (int, 0), 'recid': (int, 0), 'cmtid': (int, 0), 'of' : (str, ''), 'ln' : (str, CFG_SITE_LANG)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/write_public_note", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/write_public_note%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) (body, navtrail) = perform_request_write_public_note(uid=uid, bskid=argd['bskid'], recid=argd['recid'], cmtid=argd['cmtid'], ln=argd['ln']) # register event in webstat basket_str = "%s (%d)" % (get_basket_name(argd['bskid']), argd['bskid']) if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["write_public_note", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") return page(title = _("Add a note"), body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], secure_page_p=1) def save_public_note(self, req, form): """Save comment on record in basket""" argd = wash_urlargd(form, {'bskid': (int, 0), 'recid': (int, 0), 'note_title': (str, ""), 'note_body': (str, ""), 'editor_type': (str, ""), 'of': (str, ''), 'ln': (str, CFG_SITE_LANG), 'reply_to': (str, 0)}) _ = gettext_set_language(argd['ln']) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yourbaskets/save_public_note", navmenuid = 'yourbaskets') if isGuestUser(uid): if not CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: return redirect_to_url(req, "%s/youraccount/login%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'referer' : "%s/yourbaskets/save_public_note%s" % ( CFG_SITE_SECURE_URL, make_canonical_urlargd(argd, {})), "ln" : argd['ln']}, {}))) user_info = collect_user_info(req) if not user_info['precached_usebaskets']: return page_not_authorized(req, "../", \ text = _("You are not authorized to use baskets.")) (body, navtrail) = perform_request_save_public_note(uid=uid, bskid=argd['bskid'], recid=argd['recid'], note_title=argd['note_title'], note_body=argd['note_body'], editor_type=argd['editor_type'], ln=argd['ln'], reply_to=argd['reply_to']) # TODO: do not stat event if save was not succussful # register event in webstat basket_str = "%s (%d)" % (get_basket_name(argd['bskid']), argd['bskid']) if user_info['email']: user_str = "%s (%d)" % (user_info['email'], user_info['uid']) else: user_str = "" try: register_customevent("baskets", ["save_public_note", basket_str, user_str]) except: register_exception(suffix="Do the webstat tables exists? Try with 'webstatadmin --load-config'") return page(title = _("Display item and notes"), body = body, navtrail = navtrail, uid = uid, lastupdated = __lastupdated__, language = argd['ln'], req = req, navmenuid = 'yourbaskets', of = argd['of'], navtrail_append_title_p = 0, secure_page_p=1)