diff --git a/INSTALL b/INSTALL index f1ad87d6ea..e584746094 100644 --- a/INSTALL +++ b/INSTALL @@ -83,6 +83,9 @@ Contents natively in UTF-8 mode by setting "default-character-set=utf8" in various parts of your "my.cnf" file, such as in the "[mysql]" part and elsewhere; but this is not really required. + Note also that you may encounter problems when MySQL is run in + "strict mode"; you may want to configure your "my.cnf" in order + to avoid using strict mode (such as `STRICT_ALL_TABLES`). c) Redis server (may be on a remote machine) for user session diff --git a/modules/bibdocfile/lib/bibdocfile.py b/modules/bibdocfile/lib/bibdocfile.py index 12598b36ac..0cada52da5 100644 --- a/modules/bibdocfile/lib/bibdocfile.py +++ b/modules/bibdocfile/lib/bibdocfile.py @@ -59,6 +59,7 @@ import cgi import sys import copy +import tarfile if sys.hexversion < 0x2060000: from md5 import md5 @@ -102,6 +103,7 @@ encode_for_xml from invenio.urlutils import create_url, make_user_agent_string from invenio.textutils import nice_size +from invenio.webuser import collect_user_info from invenio.access_control_engine import acc_authorize_action from invenio.access_control_admin import acc_is_user_in_role, acc_get_role_id from invenio.access_control_firerole import compile_role_definition, acc_firerole_check_user @@ -123,7 +125,7 @@ CFG_BIBCATALOG_SYSTEM from invenio.bibcatalog import BIBCATALOG_SYSTEM from invenio.bibdocfile_config import CFG_BIBDOCFILE_ICON_SUBFORMAT_RE, \ - CFG_BIBDOCFILE_DEFAULT_ICON_SUBFORMAT + CFG_BIBDOCFILE_DEFAULT_ICON_SUBFORMAT, CFG_BIBDOCFILE_STREAM_ARCHIVE_FORMATS from invenio.pluginutils import PluginContainer import invenio.template @@ -797,17 +799,22 @@ def get_xml_8564(self): return out - def get_total_size_latest_version(self): + def get_total_size_latest_version(self, user_info=None, subformat=None): """ Returns the total size used on disk by all the files belonging to this record and corresponding to the latest version. + @param user_info: the user_info dictionary, used to check restrictions + @type: dict + @param subformat: if subformat is specified, it limits files + only to those from that specific subformat + @type subformat: string @return: the total size. @rtype: integer """ size = 0 for (bibdoc, _) in self.bibdocs.values(): - size += bibdoc.get_total_size_latest_version() + size += bibdoc.get_total_size_latest_version(user_info, subformat) return size def get_total_size(self): @@ -1564,6 +1571,36 @@ def get_text(self, extract_text_if_necessary=True): return " ".join(texts) + def stream_archive_of_latest_files(self, req, files_size=''): + """ + Streams the tar archive with all files of a certain file size (that + are not restricted or hidden) to the user. + File size should be a string that can be compared with the output of + BibDocFile.get_subformat() function. + + @param req: Apache Request Object + @type req: Apache Request Object + @param files_size: size of the files (they can be defined in + bibdocfile_config). Empty string means the original size. + @type files_size: string + """ + # Get the internal size from the user-friendly file size name + internal_format = [f[1] for f in CFG_BIBDOCFILE_STREAM_ARCHIVE_FORMATS if f[0] == files_size] + if len(internal_format) < 1: + # Incorrect file size + return + internal_format = internal_format[0] + tarname = str(self.id) + "_" + files_size + '.tar' + + # Select files that user can download (not hidden nor restricted) + user_info = collect_user_info(req) + req.content_type = "application/x-tar" + req.headers_out["Content-Disposition"] = 'attachment; filename="%s"' % tarname + tar = tarfile.open(fileobj=req, mode='w|') + for f in self.list_latest_files(): + if f.get_subformat() == internal_format and f.is_restricted(user_info)[0] == 0 and not f.hidden: + tar.add(f.get_path(), arcname=f.get_full_name(), recursive=False) + tar.close() class BibDoc(object): """ @@ -2801,12 +2838,28 @@ def _build_related_file_list(self): cur_doc = BibDoc.create_instance(docid=docid, human_readable=self.human_readable) self.related_files[doctype].append(cur_doc) - def get_total_size_latest_version(self): + def get_total_size_latest_version(self, user_info=None, subformat=None): """Return the total size used on disk of all the files belonging - to this bibdoc and corresponding to the latest version.""" + to this bibdoc and corresponding to the latest version. Restricted + and hidden files are not counted, unless there is no user_info. + @param user_info: the user_info dictionary, used to check restrictions + @type: dict + @param subformat: if subformat is specified, it limits files + only to those from that specific subformat + @type subformat: string + """ ret = 0 + all_files = False + # If we are calling this function without user_info, then we want to + # see all the files + if not user_info: + all_files = True for bibdocfile in self.list_latest_files(): - ret += bibdocfile.get_size() + # First check for restrictions + if all_files or (bibdocfile.is_restricted(user_info)[0] == 0 and not bibdocfile.hidden): + # Then check if the format is correct + if subformat is None or bibdocfile.get_subformat() == subformat: + ret += bibdocfile.get_size() return ret def get_total_size(self): diff --git a/modules/bibdocfile/lib/bibdocfile_config.py b/modules/bibdocfile/lib/bibdocfile_config.py index 0caa8ddbd2..c07eb606ff 100644 --- a/modules/bibdocfile/lib/bibdocfile_config.py +++ b/modules/bibdocfile/lib/bibdocfile_config.py @@ -69,3 +69,12 @@ # CFG_BIBDOCFILE_DEFAULT_ICON_SUBFORMAT -- this is the default subformat used # when creating new icons. CFG_BIBDOCFILE_DEFAULT_ICON_SUBFORMAT = "icon" + +# CFG_BIBDOCFILE_STREAM_ARCHIVE_FORMATS -- a list (not dictionary, because +# we want to preserve the order) that connects the different format sizes +# (like 'small', 'medium', etc.) with internal format sizes (like 'icon-180', 'icon-640', etc.) +CFG_BIBDOCFILE_STREAM_ARCHIVE_FORMATS = [ + ('small', 'icon-180'), + ('medium', 'icon-640'), + ('large', 'icon-1440'), + ('original', '')] diff --git a/modules/bibdocfile/lib/bibdocfile_webinterface.py b/modules/bibdocfile/lib/bibdocfile_webinterface.py index 1547dd3ddf..198b72fb17 100644 --- a/modules/bibdocfile/lib/bibdocfile_webinterface.py +++ b/modules/bibdocfile/lib/bibdocfile_webinterface.py @@ -83,6 +83,12 @@ def _lookup(self, component, path): def getfile(req, form): args = wash_urlargd(form, bibdocfile_templates.files_default_urlargd) ln = args['ln'] + if filename[:9] == "allfiles-": + files_size = filename[9:] + # stream a tar package to the user + brd = BibRecDocs(self.recid) + brd.stream_archive_of_latest_files(req, files_size) + return _ = gettext_set_language(ln) diff --git a/modules/bibformat/etc/format_templates/Authority_HTML_detailed.bft b/modules/bibformat/etc/format_templates/Authority_HTML_detailed.bft index 690d24bc96..da78d45180 100644 --- a/modules/bibformat/etc/format_templates/Authority_HTML_detailed.bft +++ b/modules/bibformat/etc/format_templates/Authority_HTML_detailed.bft @@ -10,8 +10,8 @@ - - - + + + diff --git a/modules/bibformat/etc/format_templates/Institute_HTML_detailed.bft b/modules/bibformat/etc/format_templates/Institute_HTML_detailed.bft index 681482ad0d..5b534e6b64 100644 --- a/modules/bibformat/etc/format_templates/Institute_HTML_detailed.bft +++ b/modules/bibformat/etc/format_templates/Institute_HTML_detailed.bft @@ -7,8 +7,8 @@ - - - + + + diff --git a/modules/bibformat/etc/format_templates/People_HTML_brief.bft b/modules/bibformat/etc/format_templates/People_HTML_brief.bft index 7672358e3a..9f497ee47e 100644 --- a/modules/bibformat/etc/format_templates/People_HTML_brief.bft +++ b/modules/bibformat/etc/format_templates/People_HTML_brief.bft @@ -1,4 +1,26 @@ Default HTML brief Brief Authority HTML format. - + + + + +
    + + + +
+
diff --git a/modules/bibformat/etc/format_templates/People_HTML_detailed.bft b/modules/bibformat/etc/format_templates/People_HTML_detailed.bft index d7c6d3e197..ecf191c2d1 100644 --- a/modules/bibformat/etc/format_templates/People_HTML_detailed.bft +++ b/modules/bibformat/etc/format_templates/People_HTML_detailed.bft @@ -1,14 +1,132 @@ Authority HTML detailed Detailed Authority HTML format. -

- -
+ - - - - - +
+
+ + +
+

Personal Information

+
+
+

Workspace

+ + + + + + + +
+
+
+

Contact

+ +
+
+

Profiles

+ +
+
+ +

Publications

+ diff --git a/modules/bibformat/etc/format_templates/Subject_HTML_detailed.bft b/modules/bibformat/etc/format_templates/Subject_HTML_detailed.bft index f1b4e7eba2..1734626370 100644 --- a/modules/bibformat/etc/format_templates/Subject_HTML_detailed.bft +++ b/modules/bibformat/etc/format_templates/Subject_HTML_detailed.bft @@ -7,8 +7,8 @@ - - - + + +
diff --git a/modules/bibformat/lib/bibreformat.py b/modules/bibformat/lib/bibreformat.py index 1571146adb..9c712dcbd3 100644 --- a/modules/bibformat/lib/bibreformat.py +++ b/modules/bibformat/lib/bibreformat.py @@ -353,7 +353,11 @@ def task_run_core(): if task_has_option("last"): recids += outdated_caches(fmt, last_updated) - if task_has_option('ignore_without'): + if task_has_option('ignore_without') or \ + task_has_option('collection') or \ + task_has_option('field') or \ + task_has_option('pattern') or \ + task_has_option('recids'): without_fmt = intbitset() else: without_fmt = missing_caches(fmt) diff --git a/modules/bibformat/lib/elements/bfe_authority_contact.py b/modules/bibformat/lib/elements/bfe_authority_contact.py new file mode 100644 index 0000000000..5fea6ffb66 --- /dev/null +++ b/modules/bibformat/lib/elements/bfe_authority_contact.py @@ -0,0 +1,142 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Invenio. +# Copyright (C) 2015, 2016 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. +"""BibFormat element - Prints the author's contact information.""" + +from invenio.messages import gettext_set_language + + +def format_email(email, email_href="yes", icon="no", vcard_support="no"): + """Return formatted email address.""" + vcard_enabled = True if vcard_support.lower() == "yes" else False + + if email_href.lower() == "yes": + email = "{1}".format( + "class='email' " if vcard_enabled else "", email) + else: + if vcard_enabled: + email = "".format(email) + if icon.lower() == "yes": + icon_class = "fa fa-envelope" + email = " {1}".format( + icon_class, email) + return email + + +def format_phone_number(phone_number, icon="no", vcard_support="no"): + """Return formatted phone number.""" + if vcard_support.lower() == "yes": + phone_number = ( + "" + "" + "{0}" + "".format(phone_number)) + if icon.lower() == "yes": + icon_class = "fa fa-phone" + phone_number = " {1}".format( + icon_class, phone_number) + return phone_number + + +def format_mobile_number(mobile_number, icon="no", vcard_support="no"): + """Return formatted mobile phone number.""" + if vcard_support.lower() == "yes": + mobile_number = ( + "" + "" + "{0}" + "".format(mobile_number)) + if icon.lower() == "yes": + icon_class = "fa fa-mobile" + mobile_number = " {1}".format( + icon_class, mobile_number) + return mobile_number + + +def format_fax_number(fax_number, icon="no", vcard_support="no"): + """Return formatted fax number.""" + if vcard_support.lower() == "yes": + fax_number = ( + "" + "" + "{0}" + "".format(fax_number)) + if icon.lower() == "yes": + icon_class = "fa fa-fax" + fax_number = " {1}".format(icon_class, fax_number) + return fax_number + + +def format_element(bfo, contact_type="all", vcard_support="no", + email_href="yes", icon="no"): + """Return contact information for the record. + + :param string contact_type: return all contact information if 'all', + other values: 'email', 'phone', 'mobile', or 'fax' + :param string vcard_support: enables vCard support if 'yes' + :param string email_href: link email address using mailto if 'yes' + :param string icon: display icon for the specified contact_type if 'yes' + """ + _ = gettext_set_language(bfo.lang) + result = "" + + # Get all contact information data + email = bfo.fields("371__m") + phone_number = bfo.fields("371__k") + mobile_number = bfo.fields("371__l") + fax_number = bfo.fields("371__f") + + if contact_type.lower() == "all": + tbl_row = "{0}{1}" + if email: + result += tbl_row.format( + _("Email address"), format_email( + email[0].lower(), email_href, vcard_support=vcard_support)) + if phone_number: + result += tbl_row.format( + _("Phone number"), format_phone_number( + phone_number[0], vcard_support=vcard_support)) + if mobile_number: + result += tbl_row.format( + _("Mobile number"), format_mobile_number(mobile_number[0])) + if fax_number: + result += tbl_row.format( + _("Fax number"), format_fax_number(fax_number[0])) + elif contact_type.lower() == "email": + if email: + result = format_email(email[0].lower(), email_href, icon) + elif contact_type.lower() == "phone": + if phone_number: + result = format_phone_number(phone_number[0], icon) + elif contact_type.lower() == "mobile": + if mobile_number: + result = format_mobile_number(mobile_number[0], icon) + elif contact_type.lower() == "fax": + if fax_number: + result = format_fax_number(fax_number[0], icon) + + return result + + +def escape_values(bfo): + """Escape return value of element. + + Called by BibFormat in order to check if output of this element + should be escaped. + """ + return 0 diff --git a/modules/bibformat/lib/elements/bfe_authority_control_no.py b/modules/bibformat/lib/elements/bfe_authority_control_no.py index 9bc85b978b..a2a95c7627 100644 --- a/modules/bibformat/lib/elements/bfe_authority_control_no.py +++ b/modules/bibformat/lib/elements/bfe_authority_control_no.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of Invenio. -# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 CERN. +# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2015, 2016 CERN. # # Invenio is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -30,9 +30,11 @@ get_low_level_recIDs_from_control_no, \ get_dependent_records_for_control_no + __revision__ = "$Id$" -def format_element(bfo): + +def format_element(bfo, print_title="yes"): """ Prints the control number of an author authority record in HTML. By default prints brief version. @@ -57,6 +59,10 @@ def format_element(bfo): recIDs = get_dependent_records_for_control_no(control_no) count = len(recIDs) count_string = str(count) + " dependent records" + + control_no_html = "{1}".format( + count_string, control_no) + from urllib import quote # if we have dependent records, provide a link to them if count: @@ -86,8 +92,9 @@ def format_element(bfo): prefix = prefix_pattern % (url_str) count_string = prefix + count_string + postfix - #assemble the html and append to list - html_str = control_no + " (" + count_string + ")" + + control_no_html = "{0}{1}{2}".format( + prefix, control_no_html, postfix) # check if there are more than one authority record with the same # control number. If so, warn the user about this inconsistency. @@ -101,22 +108,25 @@ def format_element(bfo): "&c=" + CFG_BIBAUTHORITY_AUTHORITY_COLLECTION_NAME + \ "&sc=1" + \ "&ln=" + bfo.lang - html_str += \ + control_no_html += \ ' ' + \ '(Warning, there is currently ' + \ 'more than one authority record ' + \ 'with this Control Number)' + \ '' - control_nos_formatted.append(html_str) + control_nos_formatted.append(control_no_html) - title = "" + _("Control Number(s)") + "" + result = "" if control_nos_formatted: - content = "
  • " + "
  • ".join(control_nos_formatted) + "
" - else: - content = "Missing !" + result = "
  • " + "
  • ".join(control_nos_formatted) + "
" + + if print_title.lower() == "yes": + title = "" + _("Control Number(s)") + "" + result = title + ": " + result + + return result - return "

" + title + ": " + content + "

" def escape_values(bfo): """ diff --git a/modules/bibformat/lib/elements/bfe_authority_description.py b/modules/bibformat/lib/elements/bfe_authority_description.py new file mode 100644 index 0000000000..0847f230a9 --- /dev/null +++ b/modules/bibformat/lib/elements/bfe_authority_description.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Invenio. +# Copyright (C) 2015, 2016 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. +"""BibFormat element - Prints the author's description information. + +Description contains "Home Institute (short) - Department/Group". +Example: CERN - IT/OIS +""" + + +def format_element(bfo, icon="yes"): + """Return description for the record. + + :param string icon: display icon for the element if 'yes' + """ + result = "" + description = bfo.fields("371__h") + + if description: + result = description[0] + if icon.lower() == "yes": + icon_class = "fa fa-home" + result = " {1}".format(icon_class, result) + + return result + + +def escape_values(bfo): + """Escape return value of element. + + Called by BibFormat in order to check if output of this element + should be escaped. + """ + return 0 diff --git a/modules/bibformat/lib/elements/bfe_authority_links.py b/modules/bibformat/lib/elements/bfe_authority_links.py index 1e5893a8af..b01fe36fdd 100644 --- a/modules/bibformat/lib/elements/bfe_authority_links.py +++ b/modules/bibformat/lib/elements/bfe_authority_links.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of Invenio. -# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 CERN. +# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2015, 2016 CERN. # # Invenio is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -19,8 +19,6 @@ """BibFormat element - Prints the control number of an Authority Record. """ -from invenio.config import CFG_SITE_URL, CFG_SITE_NAME - from invenio.bibauthority_config import \ CFG_BIBAUTHORITY_AUTHORITY_COLLECTION_NAME, \ CFG_BIBAUTHORITY_RECORD_CONTROL_NUMBER_FIELD, \ @@ -28,12 +26,81 @@ from invenio.bibauthority_engine import \ get_low_level_recIDs_from_control_no, \ get_dependent_records_for_control_no +from invenio.config import CFG_CACHEDIR +from invenio.viafutils import get_wikipedia_link, get_wiki_link_from_record -from invenio.viafutils import get_wikipedia_link,get_wiki_link_from_record +import json +import urllib2 +import os.path __revision__ = "$Id$" -def format_element(bfo): + +def get_inspire_name_by_inspire_id( + inspire_id, + json_file=os.path.join(CFG_CACHEDIR, "inspirehep-names-mapping.json")): + """Get INSPIRE-HEP-name given the INSPIRE-ID. + + :param string inspire_id: INSPIRE-ID + :param file json_file: INSPIRE-HEP mapping + """ + inspire_name = None + try: + with open(json_file) as f: + try: + inspire_mapping = json.load(f) + inspire_name = inspire_mapping.get(inspire_id) + except ValueError: + pass + except EnvironmentError: + pass + return inspire_name + + +def get_inspire_profile(inspire_id, val, use_inspirehepname=False): + """Get HTML element for INSPIRE-HEP Profile. + + :param bool use_inspirehepname: use INSPIRE-HEP search query if + False, otherwise call get_inspire_name_by_inspire_id + """ + result = None + + if use_inspirehepname: + inspirehep_name = get_inspire_name_by_inspire_id(inspire_id) + if inspirehep_name: + url = "https://inspirehep.net/author/profile/{0}".format( + inspirehep_name) + else: + url = ("http://inspirehep.net/search?cc=HepNames&p=035__a%3A{0}&of=hd" + .format(inspire_id)) + + result = "{1}".format(url, val) + return result + + +def get_cern_phonebook(cern_id, val): + """Get HTML element for CERN Phonebook.""" + phonebook_url = ( + "https://phonebook.cern.ch/phonebook/#personDetails/?id={0}" + .format(cern_id)) + return "{1}".format(phonebook_url, val) + + +def get_cern_profile(cern_id, val): + """Get HTML element for CERN Profile.""" + html_element = None + cern_profile_url = "http://profiles.web.cern.ch/{0}".format(cern_id) + req = urllib2.Request(cern_profile_url) + + try: + urllib2.urlopen(req) + html_element = "{1}".format(cern_profile_url, val) + except urllib2.HTTPError: + pass + return html_element + + +def format_element(bfo, print_title="yes"): """ Prints the control number of an author authority record in HTML. By default prints brief version. @@ -47,7 +114,6 @@ def format_element(bfo): control_nos = [d['a'] for d in bfo.fields('035__') if d['a'] is not None] control_nos = filter(None, control_nos) # fastest way to remove empty ""s - style = "style='width:auto;height:20px;margin-right:10px'" links_formatted = [] for control_no in control_nos: from urllib import quote @@ -60,35 +126,51 @@ def format_element(bfo): link_to_wikipedia = get_wikipedia_link(viaf_id) ## Wikipedia link with wiki icon if link_to_wikipedia: - image_element = image_pattern % { "text": "Wikipedia link", "image": "wikipedia.png", "external_article": link_to_wikipedia} + image_element = image_pattern % { "text": "Wikipedia", "image": "wikipedia.png", "external_article": link_to_wikipedia} links_formatted.append(image_element) ## VIAF link image_element = image_pattern \ - % { "text" : "VIAF cluster link","image": "viaf.png", "external_article": str("http://viaf.org/viaf/"+viaf_id) } + % { "text" : "VIAF cluster","image": "viaf.png", "external_article": str("http://viaf.org/viaf/"+viaf_id) } links_formatted.append(image_element) ## Library of congress link + if (control_no.find("|(DLC)") != -1): dlc_id = control_no.split("|(DLC)")[1].replace(" ","") link_to_lccn = "http://lccn.loc.gov/"+ dlc_id - image_element = image_pattern % { "text": "Library of Congress link", "image": "library_of_congress.png", "external_article" : link_to_lccn } + image_element = image_pattern % { "text": "Library of Congress", "image": "library_of_congress.png", "external_article" : link_to_lccn } links_formatted.append(image_element) + if (control_no.find("|(INSPIRE)") != -1): + inspire_profile = get_inspire_profile( + control_no.split("|(INSPIRE)")[1], + _("INSPIRE-HEP Profile")) + (links_formatted.append(inspire_profile) + if inspire_profile is not None else None) + if (control_no.find("|(SzGeCERN)") != -1): + cern_id = control_no.split("|(SzGeCERN)")[1] + links_formatted.append( + get_cern_phonebook(cern_id, _("CERN Phonebook"))) + html_element = get_cern_profile(cern_id, _("CERN Profile")) + if html_element: + links_formatted.append(html_element) + result = "" if links_formatted: + result = "
  • " + "
  • ".join(links_formatted) + "
" + + if print_title.lower() == "yes": title = "" + _("Useful links") + "" - if links_formatted: - content = "
  • " + "
  • ".join(links_formatted) + "
" - else: - content = "Missing !" + result = title + ": " + result + + return result + - return "

" + title + ": " + content + "

" - else: - return None def escape_values(bfo): - """ + """Escape return value of element. + Called by BibFormat in order to check if output of this element should be escaped. """ diff --git a/modules/bibformat/lib/elements/bfe_authority_publications.py b/modules/bibformat/lib/elements/bfe_authority_publications.py index 79a0d2233e..b92ab4ea3d 100644 --- a/modules/bibformat/lib/elements/bfe_authority_publications.py +++ b/modules/bibformat/lib/elements/bfe_authority_publications.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of Invenio. -# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 CERN. +# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2015, 2016 CERN. # # Invenio is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -19,95 +19,104 @@ """BibFormat element - Prints the control number of an Authority Record. """ +from invenio.bibauthority_config import ( + CFG_BIBAUTHORITY_AUTHORITY_COLLECTION_NAME, + CFG_BIBAUTHORITY_RECORD_CONTROL_NUMBER_FIELD, + CFG_BIBAUTHORITY_RECORD_AUTHOR_CONTROL_NUMBER_FIELDS as control_number_fields) +from invenio.bibauthority_engine import ( + get_low_level_recIDs_from_control_no, + get_dependent_records_for_control_no) from invenio.config import CFG_SITE_URL, CFG_SITE_NAME +from invenio.search_engine import get_fieldvalues, perform_request_search -from invenio.bibauthority_config import \ - CFG_BIBAUTHORITY_AUTHORITY_COLLECTION_NAME, \ - CFG_BIBAUTHORITY_RECORD_CONTROL_NUMBER_FIELD, \ - CFG_BIBAUTHORITY_RECORD_AUTHOR_CONTROL_NUMBER_FIELDS as control_number_fields, \ - CFG_BIBAUTHORITY_AUTHORITY_COLLECTION_IDENTIFIER as authority_identifier -from invenio.bibauthority_engine import \ - get_low_level_recIDs_from_control_no, \ - get_dependent_records_for_control_no - -from invenio.search_engine import get_fieldvalues CFG_BIBAUTHORITY_PUBLICATION_VIEW_LIMIT = 10 __revision__ = "$Id$" -def format_element(bfo): + +def get_record_ids_for_authority_ids(authority_ids, author_full_name): + """Return list of record ids for a given authority ids (control numbers). + + If no record ids have been found for the given ids, do a search based + on the author's full name, stored in the field `100__a`. + + :param list authority_id: authority ids (also known as control numbers) + :param str author_full_name: if no record ids have been found for the given + authority_id, search by author_full_name + + :return: list of record ids, or empty list, if no record ids have been found + """ + record_ids = [] + for authority_id in authority_ids: + record_ids.extend(get_dependent_records_for_control_no(authority_id)) + record_ids.extend(get_dependent_records_for_control_no( + authority_id.replace("AUTHOR|(SzGeCERN)", "CERN-"))) + record_ids.extend(get_dependent_records_for_control_no( + authority_id.replace("AUTHOR|(SzGeCERN)", "CCID-"))) + if not record_ids: + record_ids.extend(get_dependent_records_for_control_no( + authority_id.replace("AUTHOR|(INSPIRE)", ""))) + + if not record_ids: + # No record ids for the given authority ids have been found + # Search for record ids using the author's full name + record_ids.extend(perform_request_search( + p="author:\"{0}\"".format(author_full_name))) + + # Remove possible duplicates + return list(set(record_ids)) + + +def format_element(bfo, print_title="yes"): """ Prints the control number of an author authority record in HTML. By default prints brief version. - @param brief: whether the 'brief' rather than the 'detailed' format @type brief: 'yes' or 'no' """ - from invenio.messages import gettext_set_language _ = gettext_set_language(bfo.lang) # load the right message language - control_nos = [d['a'] for d in bfo.fields('035__') if d.get('a')] - authority_type = [d['a'] for d in bfo.fields('980__') if d.get('a') and d.get('a')!=authority_identifier] - if authority_type and type(authority_type) is list: - authority_type = authority_type[0] - + control_nos.append("AUTHOR|(CDS){0}".format(bfo.control_field("001"))) - previous_recIDs = [] - parameters = [] - count = 0 publications_formatted = [] - recids_added = set() - ## for every control number that this author has, find all the connected records for each one - for control_no in control_nos: - for control_number_field in control_number_fields.get(authority_type,[]): - parameters.append(control_number_field + ":" + control_no.replace(" ","")) - recIDs = [x for x in get_dependent_records_for_control_no(control_no) if x not in previous_recIDs] - length = len(recIDs) or None - from urllib import quote - # if we have dependent records, provide a link to them - if length: - prefix_pattern = "" - postfix = "" - url_str = '' - # print as many of the author's publications as the CFG_BIBAUTHORITY_PUBLICATION_VIEW_LIMIT allows - for i in range(length if length" - content = "" + record_ids = get_record_ids_for_authority_ids(control_nos, + bfo.field("100__a")) + # if we have dependent records, provide a link to them + if record_ids: + prefix_pattern = "" + postfix = "" + url_str = '' + # Print as many of the author's publications as the + # CFG_BIBAUTHORITY_PUBLICATION_VIEW_LIMIT allows + for i in range( + len(record_ids) if + len(record_ids) < CFG_BIBAUTHORITY_PUBLICATION_VIEW_LIMIT else + CFG_BIBAUTHORITY_PUBLICATION_VIEW_LIMIT): + title = get_fieldvalues(record_ids[i], "245__a") + if not title: + break + url_str = "/record/"+ str(record_ids[i]) + prefix = prefix_pattern % url_str + publications_formatted.append(prefix + title[0] + postfix) + + result = "" if publications_formatted: - content = "
  • " + "
  • ".join(publications_formatted) + "
" - #else: - # content = "Missing !" - - p_val = quote(" or ".join(parameters)) - # include "&c=" parameter for bibliographic records - # and one "&c=" parameter for authority records - url_str = \ - "/search" + \ - "?p=" + p_val + \ - "&c=" + quote(CFG_SITE_NAME) + \ - "&c=" + CFG_BIBAUTHORITY_AUTHORITY_COLLECTION_NAME + \ - "&sc=1" + \ - "&ln=" + bfo.lang - prefix = prefix_pattern % url_str - if content: - content += prefix + "See all " + str(count) + " publications..." + postfix - return "

" + title + ": " + content + "

" - else: - return "" + result = ("
  1. " + + "
  2. ".join(publications_formatted) + + "
") + url_str = ( + "/search" + + "?p=" + "author:\"{0}\"".format(bfo.field("100__a")) + + "&ln=" + bfo.lang) + if result: + prefix = prefix_pattern % url_str + result += prefix + "See more publications" + postfix + if print_title.lower() == "yes": + title = "" + _("Publication(s)") + "" + result = title + ": " + result + + return result def escape_values(bfo): diff --git a/modules/webaccess/doc/hacking/webaccess-api.webdoc b/modules/webaccess/doc/hacking/webaccess-api.webdoc index f657c7ad42..dbec7eed81 100644 --- a/modules/webaccess/doc/hacking/webaccess-api.webdoc +++ b/modules/webaccess/doc/hacking/webaccess-api.webdoc @@ -23,7 +23,7 @@
 Invenio Access Control Engine can be called from within your Python programs
 via both a regular Python API and CLI.
-In addition the you get an explanation of the program flow.
+In addition to the above features, you also get an explanation of the program flow.
 
 Contents:
  1. Regular API
diff --git a/modules/websearch/lib/search_engine.py b/modules/websearch/lib/search_engine.py
index ab15175be8..eb78a0cc09 100644
--- a/modules/websearch/lib/search_engine.py
+++ b/modules/websearch/lib/search_engine.py
@@ -97,7 +97,8 @@
      InvenioWebSearchReferstoLimitError, \
      InvenioWebSearchCitedbyLimitError, \
      CFG_WEBSEARCH_IDXPAIRS_FIELDS,\
-     CFG_WEBSEARCH_IDXPAIRS_EXACT_SEARCH
+     CFG_WEBSEARCH_IDXPAIRS_EXACT_SEARCH, \
+     CFG_WEBSEARCH_BLACKLISTED_FORMATS
 from invenio.search_engine_utils import (get_fieldvalues,
                                          get_fieldvalues_alephseq_like,
                                          record_exists)
@@ -1711,7 +1712,7 @@ def get_synonym_terms(term, kbr_name, match_type, use_memoise=False):
     return dterms.keys()
 
 
-def wash_output_format(ouput_format):
+def wash_output_format(ouput_format, verbose=False, req=None):
     """Wash output format FORMAT.  Currently only prevents input like
     'of=9' for backwards-compatible format that prints certain fields
     only.  (for this task, 'of=tm' is preferred)"""
@@ -1719,6 +1720,12 @@ def wash_output_format(ouput_format):
         # asked to print MARC tags, but not enough digits,
         # so let's switch back to HTML brief default
         return 'hb'
+    elif format in CFG_WEBSEARCH_BLACKLISTED_FORMATS:
+        if verbose:
+            write_warning("Selected format is not available through perform_request_search", req=req)
+            # Returning an empty list seems dangerous because you wouldn't know
+            # right away that the list is not supposed to be empty.
+        return 'hb'
     else:
         return ouput_format
 
@@ -5714,7 +5721,7 @@ def prs_wash_arguments(req=None, cc=CFG_SITE_NAME, c=None, p="", f="", rg=CFG_WE
     """
 
     # wash output format:
-    of = wash_output_format(of)
+    of = wash_output_format(of, verbose=verbose, req=req)
 
     # wash all arguments requiring special care
     p = wash_pattern(p)
diff --git a/modules/websearch/lib/search_engine_config.py b/modules/websearch/lib/search_engine_config.py
index 17d8daf1da..2bc848a427 100644
--- a/modules/websearch/lib/search_engine_config.py
+++ b/modules/websearch/lib/search_engine_config.py
@@ -50,6 +50,11 @@
 # interfaces (0=simple, 1=advanced, 2=add-to-search):
 CFG_WEBSEARCH_ENABLED_SEARCH_INTERFACES = [0,1,2]
 
+# CFG_WEBSEARCH_BLACKLISTED_FORMATS -- list of formats that will be refused
+# by perform_request_search:
+# * recstruct is an internal format thus should not be exposed
+CFG_WEBSEARCH_BLACKLISTED_FORMATS = ["recstruct", "wapaff", "wapdat"]
+
 
 class InvenioWebSearchUnknownCollectionError(Exception):
     """Exception for bad collection."""
diff --git a/modules/websearch/lib/websearch_external_collections_getter_unit_tests.py b/modules/websearch/lib/websearch_external_collections_getter_unit_tests.py
index 8d55a05730..5ac036d9b7 100644
--- a/modules/websearch/lib/websearch_external_collections_getter_unit_tests.py
+++ b/modules/websearch/lib/websearch_external_collections_getter_unit_tests.py
@@ -51,7 +51,7 @@ def test_async_download(self):
         ##   - test 1 bad IP: 1.2.3.4
         ## Return the list of errors.
         checks = [
-            {'url': 'http://invenio-software.org', 'content': 'About Invenio'},
+            {'url': 'http://invenio-software.org', 'content': 'Invenio'},
             {'url': 'http://rjfreijoiregjreoijgoirg.fr'},
             {'url': 'http://1.2.3.4/'}]
 
diff --git a/modules/websubmit/lib/functions/Stamp_Uploaded_Files.py b/modules/websubmit/lib/functions/Stamp_Uploaded_Files.py
index e8b5b42147..40c9cee7e6 100644
--- a/modules/websubmit/lib/functions/Stamp_Uploaded_Files.py
+++ b/modules/websubmit/lib/functions/Stamp_Uploaded_Files.py
@@ -302,8 +302,8 @@ def visit_for_stamping(visit_for_stamping_arguments, dirname, filenames):
         'file_stamper_options' members.
        @param dirname: (string) - the path to the directory in which the
         files are to be stamped.
-       @param filenames: (list) - the names of each file in dirname. An
-        attempt will be made to stamp each of these files.
+       @param filenames: (list) - the names of each file and subdirectory in
+        dirname. An attempt will be made to stamp each of the files.
        @Exceptions Raised:
          + InvenioWebSubmitFunctionWarning;
          + InvenioWebSubmitFunctionError;
@@ -345,6 +345,10 @@ def visit_for_stamping(visit_for_stamping_arguments, dirname, filenames):
         path_to_subject_file = "%s/%s" % (dirname, file_to_stamp)
         file_stamper_options['input-file'] = path_to_subject_file
 
+        if not os.path.isfile(path_to_subject_file):
+            # If it's not a file, we can't stamp it. Continue with next file
+            continue
+
         ## Just before attempting to stamp the file, log the dictionary of
         ## options (file_stamper_options) that will be passed to websubmit-
         ## file-stamper: